st_mode 구조
- _rwer__r__
- 파일 종류 1비트, (특수 접근 권한 3비트,) user 권한 3비트, group 권한 3비트, other 권한 3비트
- 111100100 2진수로 표현, 각 3자리를 10진수로 변환해서 744로 표현 가능함
- r: read, w: write, e: execute
- 권한 바꾸고 싶을 때
- chmod u-x, g+w, o+w testdata
-> user에서 실행 권한 빼고 group, other에 write 권한 주기 - chmod 600 testdata
-> testdata의 권한을 600(110000000) 으로 바꾸기
- chmod u-x, g+w, o+w testdata
- 파일 소유자 : 사용자 식별번호로 구별
- uid, gid, /etc/password
- 유효 사용자 식별번호 euid
- set user-id(04000) : 일시적으로 유효 사용자 식별자 부여
- 진짜 사용자 식별번호 ruid
- set group-id(02000) : 일시적으로 유효 그룹 사용자 식별자 부여
- 일반적으로 두개는 같음
- sticky bit(01000)
- 임시 저장공간 쓰기 위한 것, 일반적으로 공유 모드로 사용 가능
- 공유 디렉토리 /tmp에 대한 접근 권한 또는 텍스트-이미지를 swqp 영역에 남겨둠
/tmp : 임의의 사용자가 데이터 쓸 수 있음 - 실행권한 있을 때는 S, 없을 때는 s
ex) _rw_r__r_s - chmod g+s unix.txt
-> group의 e 자리가 s로 바뀜 (실행권한이 없을 때)
파일 종류 검색
상수 이용
사용 시 모드값과 상수값(S_IFMT)을 &연산 해서 파일 종류 부분만 알 수 있게 함
상수명 | 상수값 (16진수) | 기능 |
S_IFMT | 0xF000 | st_mode 값에서 파일 종류 정의한 부분 가져옴 |
S_IFIFO | 0x1000 | FIFO 파일 |
S_IFCHR | 0x2000 | 문자 장치 특수 파일 ex) 모니터 |
S_IFDIR | 0x4000 | 디렉토리 |
S_IFBLK | 0x6000 | 블록 장치 특수 파일 ex) 하드디스크 |
S_IFREG | 0x8000 | 일반 파일 |
S_IFLNK | 0xA000 | 심볼릭 링크 파일 |
S_IFSOCK | 0xC000 | 소켓 파일 |
int main(){
struct stat buf;
int kind;
stat("fileName",&buf);
kind = buf.st_mode&S_IFMT;
switch(kind){
case S_IFIFO:
printf("FIFO");
break;
csas S_IFDIR:
printf("directory");
break;
}
}
매크로 이용
POSIX 표준
인자로 받은 mode 값을 0xF000과 &연산하고 연산 결과를 파일 종류별로 정해진 값과 비교해 파일 종류 판단함
매크로명 | 기능 (true일 경우) |
S_ISFIFO(mode) | FIFO 파일 |
S_ISCHR(mode) | 문자 장치 특수 파일 |
S_ISDIR(mode) | 디렉토리 |
S_ISBLK(mode) | 블록 장치 특수 파일 |
S_ISREG(mode) | 일반 파일 |
S_ISLNK(mode) | 심볼릭 링크 파일 |
S_ISSOCK(mode) | 소켓 파일 |
int main(){
struct stat buf;
stat("filename",&buf);
if(S_ISFIFO(buf.st_mode)) printf("FIFO");
}
파일 접근 권한 검색
상수 이용
- 그룹 사용자 : 3비트 shift
ex) st_mode & (S_IREAD >> 3) - 기타 사용자 : 6비트 shift
상수명 | 상수값 | 기능 |
S_ISUID | 0x800 | st_mode와 &연산 0 아니면 setuid 설정 |
S_ISGID | 0x400 | st_mode와 &연산 0 아니면 setgid 설정 |
S_ISVTX | 0x200 | st_mode와 &연산 0 아니면 스티키 비트 설정 |
S_IREAD | 00400 | st_mode와 & 연산으로 소유자 읽기 권한 확인 |
S_IWRITE | 00200 | st_mode와 & 연산으로 소유자 쓰기 권한 확인 |
S_IEXEC | 00100 | st_mode와 & 연산으로 소유자 실행 권한 확인 |
POSIX 상수 이용
- 소유자
- S_IRWXU, S_IRUSR, S_IWUSR, S_IXUSR
- 소유자 읽기/쓰기/실행 권한, 소유자 읽기, 소유자 쓰기, 소유자 실행 권한
- 그룹
- S_IRWXG, S_IRGRP, S_IWGRP, S_IXGRP
- 기타 사용자
- S_IRWXO, S_IROTH, S_IWOTH, S_IXOTH
int main(){
struct stat buf;
stat("filename",&buf);
if((buf.st_mode & S_IREAD) !=0 ) printf("user has read");
}
함수 사용 - access
#include <unistd.h>
int access(const char *path, int amode);
- path에 지정된 파일이 amode로 지정한 권한 가지는지 확인 후 리턴 (실제 사용자에 대한 권한만 확인해줌)
- amode 값
- R_OK, W_OK, X_OK, F_OK
- 읽기 / 쓰기 / 실행 권한 확인, 파일 존재하는지 확인
- 접근 권한 있으면 0, 오류 있으면 -1 리턴
- 오류 메시지
- ENOENT : 파일 존재 X
- EACCES : 접근 권한 X
- 오류 메시지
extern int errno;
int main(){
int per;
if(access("filename",F_OK) == -1 && errno == ENOENT) printf("File not exist");
//파일 없어서 에러난건지 체크
per = access("filename",R_OK);
if(per == 0) printf("read permission is permitted");
else if(per == -1 && errno == EACCES) printf("read is not permitted");
}
파일 접근 권한 변경
파일명으로 변경 - chmod
#include <sys/types.h>
#include <sys/stat.h>
int chmod(const char *path, mode_t mode);
- 접근 권한 변경할 파일 경로 받아서 mode에 지정한 상수값으로 권한 변경함
- 접근 권한 더할 때는 | 연산자, 뺄 때는 ~연산 후 &연산자
- chmod(path, S_IRWXU);
- chmod(path, S_IRWXU|S_IRGRP);
- MODE |= S_IWGRP;
- MODE & ~(S_IROTH);
- mode 값 변경 후 chmod 함수 호출해야 변경 적용됨!
int main(){
struct stat buf;
stat("filename",&buf);
buf.st_mode |= S_IWGRP;
buf.st_mode &= ~(S_IROTH);
chmod("filename", buf.st_mode);
stat("filename", &buf);
printf("mode : %o", (unsigned int)buf.st_mode);
}
파일 기술자로 변경 - fchmod
#include <sys/types.h>
#include <sys/stat.h>
int fchmod(int fd, mode_t mode);
- 열려 있는 파일의 파일 기술자를 받아서 mode에 미리 정해놓은 상수값으로 변경할 권한 지정함
파일명으로 변경 - umask
#include <sys/types.h>
#include <sys/stat.h>
mode_t umask(mode_t newmask);
- 각 프로세스에는 파일 생성 마스크가 설정됨
- 파일이 생성될 때 어떤 모드가 주어지든지 자동적으로 허가 비트를 0으로 만들기 위해서 사용함
- fd = open(filename, O_CREAT, mode) == fd = open(filename, O_CREAT, (~mask)&mode)
- fd = open(filename, O_CREAT, 0644) 에 umask = 007 적용하면 기타의 100 & 000(~111) = 000
fd = open(filename, O_CREAT, 0640)
- umask한 뒤에 open하거나 unlink(fd)로 파일 지우고 새로 open해주기
#define FILENAME "unix.txt"
int main(void)
{
int fd = open(FILENAME, O_CREAT|O_RDWR, 0644);
// 110 100 100 & 111 111 111 (~0) = 0644
umask(0);
unlink(FILENAME);
fd = open(FILENAME, O_CREAT|O_RDWR, 0644);
// 110 100 100 & 100 101 110 (~011 010 001) = 0444
umask(0321);
unlink(FILENAME);
fd = open(FILENAME, O_CREAT|O_RDWR, 0644);
// 110 110 110 & 111 101 101 (~000 010 010) = 0644
umask(022);
unlink(FILENAME);
fd = open(FILENAME, O_CREAT|O_RDWR, 0666);
return 0;
}