Linux系統編程:文件的屬性

一、讀取文件元數據

#include <sys/stat.h>
int stat(const char *restrict pathname, struct stat *restrict buf);
提供文件名字,獲取文件對應屬性。
int fstat(int filedes, struct stat *buf);
通過文件描述符獲取文件對應的屬性。
int lstat(const char *restrict pathname, struct stat *restrict buf);
連接文件描述命,獲取文件屬性。

二、stat結構體

struct stat {

              dev_t     st_dev;       /* 文件系統設備號 */

              ino_t     st_ino;        /* i結點號 */

              mode_t   st_mode;    /* 文件類型,權限位 */

              nlink_t   st_nlink;       /* 硬鏈接數 */

              uid_t     st_uid;        /* 主人用戶ID */

              gid_t     st_gid;        /* 主人組ID */

              dev_t     st_rdev;      /* 特殊文件設備號  */

              off_t     st_size;         /* 文件字節大小 */

              blksize_t  st_blksize;      /* 塊大小 */

              blkcnt_t  st_blocks;      /* 文件所佔塊個數 */

              time_t    st_atime;      /* 上次訪問時間 */

              time_t    st_mtime;     /* 上次修改時間 */

              time_t    st_ctime;       /* 上次文件狀態修改時間 */

};   



#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>

#define ERR_EXIT(m) \
    do { \
        perror(m); \
        exit(EXIT_FAILURE); \
    } while(0)

#define MAJOR(a) (int)((unsigned short)a >> 8)  // 高8位,主設備號
#define MINOR(a) (int)((unsigned short)a & 0xFF)

int filetype(struct stat *buf)
{
    int flag = 0;
    printf("Filetype:");
    mode_t mode;
    mode = buf->st_mode;
    switch (mode & S_IFMT)
    {

    case S_IFSOCK:
        printf("socket\n");
        break;
    case S_IFLNK:
        printf("symbolic link\n");
        break;
    case S_IFREG:
        printf("regular file\n");
        break;
    case S_IFBLK:
        printf("block device\n");
        flag = 1;
        break;
    case S_IFDIR:
        printf("directory\n");
        break;
    case S_IFCHR:
        printf("character device\n");
        flag = 1;
        break;
    case S_IFIFO:
        printf("FIFO\n");
        break;
    default:
        printf("unknown file type\n");
        break;
    }

    return flag;
}

void fileperm(struct stat *buf, char perm[])
{
    strcpy(perm, "----------");
    perm[0] = '?';
    mode_t mode;
    mode = buf->st_mode;
    switch (mode & S_IFMT)
    {

    case S_IFSOCK:
        perm[0] = 's';
        break;
    case S_IFLNK:
        perm[0] = 'l';
        break;
    case S_IFREG:
        perm[0] = '-';
        break;
    case S_IFBLK:
        perm[0] = 'b';
        break;
    case S_IFDIR:
        perm[0] = 'd';
        break;
    case S_IFCHR:
        perm[0] = 'c';
        break;
    case S_IFIFO:
        perm[0] = 'p';
        break;
    }

    if (mode & S_IRUSR)
        perm[1] = 'r';
    if (mode & S_IWUSR)
        perm[2] = 'w';
    if (mode & S_IXUSR)
        perm[3] = 'x';
    if (mode & S_IRGRP)
        perm[4] = 'r';
    if (mode & S_IWGRP)
        perm[5] = 'w';
    if (mode & S_IXGRP)
        perm[6] = 'x';
    if (mode & S_IROTH)
        perm[7] = 'r';
    if (mode & S_IWOTH)
        perm[8] = 'w';
    if (mode & S_IXOTH)
        perm[9] = 'x';
    perm[10] = '\0';
}


int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        fprintf(stderr, "Usage %s file\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    printf("Filename:%s\n", argv[1]);
    struct stat sbuf;
    if (lstat(argv[1], &sbuf) == -1)
        ERR_EXIT("stat error");

    printf("file in Dev number:major %d, minor %d\n",
           MAJOR(sbuf.st_dev), MINOR(sbuf.st_dev));
    printf("File inode:%d\n", (int) sbuf.st_ino);

    if (filetype(&sbuf))
    {
        printf("Device number:major %d, minor %d\n",
               MAJOR(sbuf.st_rdev), MINOR(sbuf.st_rdev));
    }

    char perm[11] = {0};
    fileperm(&sbuf, perm);
    printf("File permission bits=%o %s\n", sbuf.st_mode & 0777, perm);  // 0777 是八進制數

    return 0;
}
測試如下:

simba@ubuntu:~/Documents/code/linux_programming/APUE/File_IO$ ./file_stat Makefile 
Filename:Makefile
file in Dev number:major 8, minor 1
File inode:660022
Filetype:regular file
File permission bits=664 -rw-rw-r--

因爲是普通文件,故從st_dev字段看設備號,而不是st_rdev. 主設備號表示設備驅動程序,而次設備號表示特定的子設備。比如在同一個磁盤上面不同的文件系統,設備驅動程序相同,但是次設備號不同。

st_rdev只有字符特殊文件和塊特殊文件纔有這個值,表示實際設備的設備編號。



發佈了51 篇原創文章 · 獲贊 9 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章