메타 정보 획득하기
-
파일 시스템에는 데이터 외에도 다음과 같은 정보가 추가적으로 저장되어 있다.
- 파일의 종류
- 크기
- 권한
- 소유자
- 그룹
- 작성시간
- 변경 시간
- 액세스 시간
stat(2)
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *path, struct stat *buf);
int lstat(const char *path, struct stat *buf);
-
stat()
은path
로 지정한 엔트리 정보를 취득해서buf
에 써넣는다. 성공하면 0을 반환하고, 실패하면 -1을 반환하면서errno
를 설정한다. -
lstat()
은stat()
와 거의 같지만,path
가 심볼릭 링크인 경우 해당 링크를 따라가지 않고 심볼릭 링크 자신의 정보를 반환한다는 점이 다르다. -
또한, 파일 디스크립터에서 동일한 정보를 얻을 수 있는
fstat()
도 있다.
-
fstat()
에 관해서는man
페이지를 참고하면 자세히 나와 있다. -
리눅스
struct stat
구조체와 의미는 아래와 같다.
stat
명령어 만들기
- 시스템 콜
stat()
을 사용하여stat
명령어를 만들어 볼 것이다.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
static char *filetype(mode_t mode);
int main(int argc, char *argv[]) {
struct stat st;
if (argc != 2) {
fprintf(stderr, "wrong argument\n");
exit(1);
}
if (lstat(argv[1], &st) < 0) {
perror(argv[1]);
exit(1);
}
printf("type\t%o (%s)\n", (st.st_mode & S_IFMT), filetype(st.st_mode));
printf("mode\t%o\n", st.st_mode & ~S_IFMT);
printf("dev\t%llu\n", (unsigned long long)st.st_dev);
printf("ino\t%lu\n", (unsigned long)st.st_ino);
printf("rdev\t%lu\n", (unsigned long)st.st_rdev);
printf("nlink\t%lu\n", (unsigned long)st.st_nlink);
printf("uid\t%d\n", st.st_uid);
printf("gid\t%d\n", st.st_gid);
printf("size\t%ld\n", st.st_size);
printf("blksize\t%ld\n", (unsigned long)st.st_blksize);
printf("blocks\t%lu\n", (unsigned long)st.st_blocks);
printf("atime\t%s", ctime(&st.st_atime));
printf("mtime\t%s", ctime(&st.st_mtime));
printf("ctime\t%s", ctime(&st.st_ctime));
exit(0);
}
static char *filetype(mode_t mode) {
if (S_ISREG(mode)) return "file";
if (S_ISDIR(mode)) return "directory";
if (S_ISCHR(mode)) return "chardev";
if (S_ISBLK(mode)) return "blockdev";
if (S_ISFIFO(mode)) return "fifo";
if (S_ISLNK(mode)) return "symlink";
if (S_ISSOCK(mode)) return "socket";
return "unknown";
}
- 실행 결과는 위와 같다.
메타 정보 변경하기
- 메타 정보를 획득하는 시스템 콜은
stat(2)
한 개지만, 변경하는 시스템 콜은 여러개가 있다.
변경 대상 | 사용하는 시스템 콜 |
---|---|
권한 | chmod(2) |
오너와 그룹 | chown (2) |
최종 액세스 시간과 최종 갱신 시각 | utime(2) |
chmod(2)
#include <sys/stat.h>
int chmod(const char *path, mode_t mode);
-
chmod
는 경로로 지정한 파일의 모드를 변경한다. 성공하면 0을 반환하고 실패하면 -1을 반환하면서errno
에 에러 번호를 설정한다. -
mode
는 표에 있는 상수를OR
로 묶어서 지정하거나0775
같은 숫자를 사용한다. C언어에서 숫자에 0을 앞에 두면 8진수가 된다. -
예를 들어서, 권한 644의 경우, ‘0644’ 또는 ‘S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH`로 지정한다.
chown(2)
#include <unistd.h>
int chown(const char *path, uid_t owner, gid_t group);
int lchown(const char *path, uid_t owner, gid_t group);
-
chown()
은 파일path
의 소유 사용자를owner
로, 소유 그룹을group
로 변경한다. 그중 하나만을 변경하려는 경우에는 변경하지 않는 쪽에 -1을 지정한다. -
lchown()
의 동작은chown()
과 거의 같지만,path
가 심볼릭 링크인 경우에는 그 심볼릭 링크 자체의 정보를 변경하는 점이 다르다. 그리고chown()
은 심볼릭 링크가 가리키는 파일의 정보를 변경한다. -
둘 다 성공하면 0을 반환하며, 실패하면 -1을 반환하고
errno
를 설정한다. -
어느 시스템 콜이든지 소유 사용자를 변경하려면 슈퍼 사용자 권한이 필요하다. 그리고 소유 그룹을 변경하는 경우에는 해당 파일의 소유 사용자여야 하며, 그리고 자신이 포함된 그룹으로만 변경할 수 있다. 물론, 슈퍼 사용자라면 임의의 그룹으로 변경할 수 있다.
-
lchown()
이 있다면lchmod()
도 있을 것 같지만, 리눅스에서는 심볼릭 링크 자체에 권한이 없어lchmod()
란 존재하지 않는다. 그러나 BSD 계열의 유닉스에는 존재한다.
utime(2)
#include <sys/types.h>
#include <utime.h>
int utime(const char *path, struct utimbuf *buf);
struct utimbuf {
time_t actime; /* 최종 액세스 시간 */
time_t modetime; /* 최종 갱신 시간 */
}
-
utime()
은 경로로 지정한 파일의 최종 액세스 시간과 최종 갱신 시간을 변경한다. 만약buf
가 NULL이 아니면buf
의 내용에 따라서actime
과modtime
이 설정된다. -
buf
가 NULL 이라면 양쪽 모두 현재 시간으로 변경된다.
chmod 명령어 작성하기
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
int main(int argc, char *argv[]) {
int mode;
int i;
if (argc < 2) {
fprintf(stderr, "no mode given\n");
exit(1);
}
mode = strtol(argv[1], NULL, 0);
for (i = 2; i < argc; i++) {
if (chmod(argv[i], mode) < 0) {
perror(argv[i]);
}
}
exit(0);
}
strtol()
은atoi()
와 같이 정수가 표현된 문자열을 정수 타입의 값으로 변환하는 함수이다. 그러나atoi()
와 다르게 세번째 인자로 진수를 설정할 수 있다.