ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • C/C++ stat(2), lstat(2), fstat(2)
    C,C++ & Linux 2020. 5. 17. 00:43
    728x90

    stat 함수 기능

    지정한 파일의 정보를 담고 있는 stat 구조체를 얻어주는 시스템 함수입니다.

     

    stat(2)

    파일을 filepath 로 지정합니다.

     

    fstat(2)

    파일을 fd 넘버로 지정합니다.

     

    lstat(2)

    파일을 filepath 로 지정하되 지정된 파일이 심볼릭 링크 파일이면 링크파일 자체에 대한 정보를 얻습니다.

    stat(2) 함수로 심볼릭 링크 파일을 지정하게되면 링크파일이 가리키는 파일에 대한 정보를 얻습니다.

     

    stat구조체

    struct stat {
        dev_t st_dev;  // 디바이스 번호
        ino_t st_ino;  // inode 번호
        mode_t st_mode;  // 모드 (접근권한)
        nlink_t st_nlink;  // 하드링크 수
        uid_t st_uid;  // 소유자의 사용자 아이디
        gid_t st_gid;  // 소유자의 그룹 아이디
        dev_t st_rdev;  // 디바이스 아이디 (특수 파일인 경우)
        off_t st_size;  // 파일 크기(바이트)
        blksize_t st_blksize;  // 블록 크기
        blkcnt_t st_blocks;  // 512바이트 블록 갯수
        time_t st_atime;  // 최종 접근 시간 (access time)
        time_t st_mtime;  // 최종 수정 시간 (modification time)
        time_t st_ctime;  // 최종 상태 변경 시간 (change time)
    };

    mode_t st_mode

    st_mode 비트마스크 구조

    파일 종류 비트 마스크

    파일 종류 8진수 테스트 매크로 파일 종류
    S_IFMT 0170000   파일 타입 비트 마스크
    S_IFREG 0100000 S_ISREG() 일반 파일
    S_IFDIR 0040000 S_ISDIR() 디렉토리 파일
    S_IFCHR 0020000 S_ISCHR() 문자 디바이스
    S_IFBLK 0060000 S_ISBLK() 블록 디바이스
    S_IFFO 0010000 S_ISFIFO() FIFO, Pipe 파일
    S_IFSOCK 0140000 S_ISSOCK() 소켓
    S_IFLNK 0120000 S_ISLNK() 심볼릭 링크
    S_IFDOOR 0150000 S_ISDOOR()  

     

    유효 사용자 및 접근 권한 매크로

    테스트 매크로 8진수 내용
    S_ISUID 0004000 set-user-id
    S_ISGID 0002000 set-group-id
    S_ISVTX 0001000 sticky bit
    S_IRWXU 0000700 소유자 권한 마스크
      S_IRUSR 0000400 소유자 읽기 권한
      S_IWUSR 0000200 소유자 쓰기 권한
      S_IXUSR 0000100 소유자 실행 권한
    S_IRWXG 0000070 그룹 권한 마스크
      S_IRGRP 0000040 그룹 읽기 권한
      S_IWGRP 0000020 그룹 쓰기 권한
      S_IXGRP 0000010 그룹 실행 권한
    S_IRWXO 0000007 기타 사용자 권한 마스크
      S_IROTH 0000004 기타 사용자 읽기 권한
      S_IWOTH 0000002 기타 사용자 쓰기 권한
      S_IXOTH 0000001 기타 사용자 실행 권한

    함수 원형

    #include <unistd.h>
    #include <sys/stat.h>
    #include <sys/types.h>
    
    int stat(const char *filepath, struct stat *statbuf);
    int fstat(int fd, struct stat *statbuf);
    int lstat(const char *filepath, struct stat *statbuf);

    매개변수

    filepath

    stat 을 얻고자 하는 파일의 경로

     

    statbuf

    stat 을 주입받을 주소

     

    fd

    stat을 얻고자 하는 파일의 파일 디스크립터

    반환값

    성공 시 0 리턴

    에러 시 -1 리턴과 errno 설정

    예제

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    
    int main(int argc, char *argv[]) {
        struct stat statbuf;
    
        if (stat(argv[1], &statbuf) < 0) {
            fprintf(stderr, "stat error\n");
            exit(1);
        }
    
        // statbuf.st_size = 파일의 크기
        printf("%s %ld bytes\n", argv[1], statbuf.st_size);
    
        exit(0);
    }
    

    결과

    예제2

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/stat.h>
    #include <sys/types.h>
    
    struct stat statbuf;
    
    void ssu_checkfile(char* fname, time_t *time);
    
    int main(int argc, char* argv[]) {
    	time_t intertime;
    	if (argc != 2) {
    		fprintf(stderr, "usage: %s <file>\n", argv[0]);
    		exit(1);
    	}
    
    	if (stat(argv[1], &statbuf) < 0) {
    		fprintf(stderr, "sttat error for %s\n", argv[1]);
    		exit(1);
    	}
    
    	intertime = statbuf.st_mtime;
    	while(1) {
    		ssu_checkfile(argv[1], &intertime);
    		sleep(10);
    	}
    
    	exit(0);
    }
    
    void ssu_checkfile(char* fname, time_t* time) {
    	if (stat(fname, &statbuf) < 0) {
    		fprintf(stderr, "Warning: ssu_checkfile() error!\n");
    		exit(1);
    	}
    
    	if (statbuf.st_mtime != *time) {
    		printf("Warning: %s was modified!.\n", fname);
    		*time = statbuf.st_mtime;
    	}
    }
    

    결과

    a.out 실행 후 파일을 수정하면 변화가 감지되는 모습

    예제

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    
    int main(int argc, char *argv[]) {
        struct stat file_info;
        char *str;
        int i;
    
        for (int i = 1; i < argc; i++) {
    
            if (lstat(argv[i], &file_info) < 0) {
                fprintf(stderr, "lstat error\n");
                continue;
            }
    
            printf("name = %s, type = ", argv[i]);
            if (S_ISREG(file_info.st_mode))
                str = "regular";
            else if (S_ISDIR(file_info.st_mode))
                str = "directory";
            else if (S_ISCHR(file_info.st_mode))
                str = "character special";
            else if (S_ISBLK(file_info.st_mode))
                str = "block special";
            else if (S_ISFIFO(file_info.st_mode))
                str = "FIFO";
            else if (S_ISLNK(file_info.st_mode))
                str = "symbolic link";
            else if (S_ISSOCK(file_info.st_mode))
                str = "socket";
            else
                str = "unknown";
    
            printf("%s\n", str);
        }
    	exit(0);
    }
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    
    int main(int argc, char *argv[]) {
        struct stat file_info;
        char *str;
        int i;
    
        for (int i = 1; i < argc; i++) {
    
            if (lstat(argv[i], &file_info) < 0) {
                fprintf(stderr, "lstat error\n");
                continue;
            }
    
            printf("name = %s, type = ", argv[i]);
            if ((S_IFMT & file_info.st_mode) == S_IFREG)
                str = "regular";
            else if ((S_IFMT & file_info.st_mode) == S_IFDIR)
                str = "directory";
            else if ((S_IFMT & file_info.st_mode) == S_IFCHR)
                str = "character special";
            else if ((S_IFMT & file_info.st_mode) == S_IFBLK)
                str = "block special";
            else if ((S_IFMT & file_info.st_mode) == S_IFIFO)
                str = "FIFO";
            else if ((S_IFMT & file_info.st_mode) == S_IFLNK)
                str = "symbolic link";
            else if ((S_IFMT & file_info.st_mode) == S_IFSOCK)
                str = "socket";
            else
                str = "unknown";
    
            printf("%s\n", str);
        }
    	exit(0);
    }
    

    결과

     

     

     

     

     

    리눅스시스템프로그래밍 저자 : 홍지만
    https://book.naver.com/bookdb/book_detail.nhn?bid=14623672

    책에 기술된 예제 프로그램입니다. 책 내부에는 훨씬 더 많은 자료가 있습니다. (개인적으로 좋았습니다.)

    'C,C++ & Linux' 카테고리의 다른 글

    C/C++ umask(2)  (1) 2020.05.17
    C/C++ access(2)  (1) 2020.05.17
    C/C++ sync(2), fsync(2), fdatasync(2)  (0) 2020.05.16
    C/C++ dup2()  (0) 2020.05.16
    C/C++ dup()  (0) 2020.05.16

    댓글

Designed by Tistory.