linux c查看文件属性stat,lstat,fstat

2018-06-06 22:21:07

文件属性也叫文件元数据。我们从系统调用stat() 开始讲,可利用其返回一个包含多种文件属性的结构。

#include <sys/stat.h>

struct stat {
    dev_t st_dev;      /* 记录文件主,次设备号 */
    ino_t st_ino;      /* I-node号 */
    mode_t st_mode;    /* 文件类型和权限 */
    nlink_t st_nlink;  /* 硬链接数 */
    uid_t st_uid;      /* uid */
    gid_t st_gid;      /* gid */
    dev_t st_rdev;     /* 设备的主,次设备号 */
    off_t st_size;     /* 文件大小(字节)*/
    blksize_t st_blksize; /* Optimal block size for I/O (bytes) */
    blkcnt_t st_blocks; /* Number of (512B) blocks allocated */
    time_t st_atime;    /* 最近访问时间 */
    time_t st_mtime;    /* 最近修改时间 */
    time_t st_ctime;    /* 最近状态修改时间 */
};

int stat(const char *pathname, struct stat *statbuf);

//如果是符号链接,则会返回链接文件本身,而不是它指向的文件
int lstat(const char *pathname, struct stat *statbuf);
int fstat(int fd, struct stat *statbuf);

对于常规文件,st_size 字段表示文件的字节数,对于符号链接,则表示链接所指向路径名的长度,对于共享内存,该字段表示对象的大小(后面文章将讲解)。

st_blocks 字段表示实际分配给文件的总块数,块大小一般为512字节,其中包括了为指针块所分配的空间,一般来说st_blocks转为字节数大于等于st_size(因为一个块只能被一个文件占用),但是特殊情况,比如有文件空洞(这里不做讲解,可自行查阅相关资料),则会小于。

st_blksize 字段指的是文件i/o操作最优块大小,一般为4096。

st_mode 字段内含位掩码,起标识文件类型和指定文件权限的双重作用。布局情况如图。

校验文件类型或权限

switch (sb->st_mode & S_IFMT) {
    case S_IFREG:  printf("regular file\n");            break;
    case S_IFDIR:  printf("directory\n");               break;
    case S_IFCHR:  printf("character device\n");        break;
    case S_IFBLK:  printf("block device\n");            break;
    case S_IFLNK:  printf("symbolic (soft) link\n");    break;
    case S_IFIFO:  printf("FIFO or pipe\n");            break;
    case S_IFSOCK: printf("socket\n");                  break;
    default:       printf("unknown file type?\n");      break;
}

#define S_ISDIR(m)	(((m) & S_IFMT) == S_IFDIR)
#define S_ISFIFO(m)	(((m) & S_IFMT) == S_IFIFO)
#define S_ISCHR(m)	(((m) & S_IFMT) == S_IFCHR)
#define S_ISBLK(m)	(((m) & S_IFMT) == S_IFBLK)
#define S_ISREG(m)	(((m) & S_IFMT) == S_IFREG)

例子

#include <stdio.h>
#include <sys/sysmacros.h>    //major minor宏命令支持
#include <sys/stat.h>
#include <time.h>
#include <sys/types.h>
#include <stdlib.h>

/*
用来校验文件设置了
set-user-ID, set-group-ID, sticky bit
*/
#define FP_SPECIAL 1

typedef enum { FALSE, TRUE } Boolean;
#define STR_SIZE sizeof("rwxrwxrwx")

char *filePermStr(mode_t perm, int flags);

static void
displayStatInfo(const struct stat *sb){
    printf("File type:                ");

    switch (sb->st_mode & S_IFMT) {
    case S_IFREG:  printf("regular file\n");            break;
    case S_IFDIR:  printf("directory\n");               break;
    case S_IFCHR:  printf("character device\n");        break;
    case S_IFBLK:  printf("block device\n");            break;
    case S_IFLNK:  printf("symbolic (soft) link\n");    break;
    case S_IFIFO:  printf("FIFO or pipe\n");            break;
    case S_IFSOCK: printf("socket\n");                  break;
    default:       printf("unknown file type?\n");      break;
    }
    
    if(sb->st_mode & S_IFMT == S_IFBLK){
        printf("设备文件主次设备号: major=%ld   minor=%ld\n",
                (long) major(sb->st_rdev), (long) minor(sb->st_rdev));
    }else{
        printf("主次设备号: major=%ld   minor=%ld\n",
                (long) major(sb->st_dev), (long) minor(sb->st_dev));
    }
    

    printf("I-node number:            %ld\n", (long) sb->st_ino);

    printf("Mode:                     %lo (%s)\n",
            (unsigned long) sb->st_mode, filePermStr(sb->st_mode, 0));

    if (sb->st_mode & (S_ISUID | S_ISGID | S_ISVTX))
        printf("    special bits set:     %s%s%s\n",
                (sb->st_mode & S_ISUID) ? "set-UID " : "",
                (sb->st_mode & S_ISGID) ? "set-GID " : "",
                (sb->st_mode & S_ISVTX) ? "sticky " : "");

    printf("Number of (hard) links:   %ld\n", (long) sb->st_nlink);

    printf("Ownership:                UID=%ld   GID=%ld\n",
            (long) sb->st_uid, (long) sb->st_gid);

    if (S_ISCHR(sb->st_mode) || S_ISBLK(sb->st_mode))
        printf("Device number (st_rdev):  major=%ld; minor=%ld\n",
                (long) major(sb->st_rdev), (long) minor(sb->st_rdev));

    printf("File size:                %lld bytes\n", (long long) sb->st_size);
    printf("Optimal I/O block size:   %ld bytes\n", (long) sb->st_blksize);
    printf("512B blocks allocated:    %lld\n", (long long) sb->st_blocks);

    printf("Last file access:         %s", ctime(&sb->st_atime));
    printf("Last file modification:   %s", ctime(&sb->st_mtime));
    printf("Last status change:       %s", ctime(&sb->st_ctime));
}

char * filePermStr(mode_t perm, int flags){
    static char str[STR_SIZE];

    snprintf(str, STR_SIZE, "%c%c%c%c%c%c%c%c%c",
        (perm & S_IRUSR) ? 'r' : '-', (perm & S_IWUSR) ? 'w' : '-',
        (perm & S_IXUSR) ?
            (((perm & S_ISUID) && (flags & FP_SPECIAL)) ? 's' : 'x') :
            (((perm & S_ISUID) && (flags & FP_SPECIAL)) ? 'S' : '-'),
                
        (perm & S_IRGRP) ? 'r' : '-', (perm & S_IWGRP) ? 'w' : '-',
        (perm & S_IXGRP) ?
            (((perm & S_ISGID) && (flags & FP_SPECIAL)) ? 's' : 'x') :
            (((perm & S_ISGID) && (flags & FP_SPECIAL)) ? 'S' : '-'),
                
        (perm & S_IROTH) ? 'r' : '-', (perm & S_IWOTH) ? 'w' : '-',
        (perm & S_IXOTH) ?
            (((perm & S_ISVTX) && (flags & FP_SPECIAL)) ? 't' : 'x') :
            (((perm & S_ISVTX) && (flags & FP_SPECIAL)) ? 'T' : '-'));

    return str;
}

int main(int argc, char *argv[]){
    struct stat sb;
    Boolean statLink;
    int fname;         //文件名索引位置
    
    // -l 参数加上则返回 1
    statLink = (argc > 1) && strcmp(argv[1], "-l") == 0;

    fname = statLink ? 2 : 1;

    if (fname >= argc || (argc > 1 && strcmp(argv[1], "--help") == 0)){
        printf("%s [-l] file\n"
                "        -l = use lstat() instead of stat()\n", argv[0]);
        exit(1);
    }
        

    if (statLink) {
        if (lstat(argv[fname], &sb) == -1)
            exit(-1);
    } else {
        if (stat(argv[fname], &sb) == -1)
            exit(-1);
    }

    displayStatInfo(&sb);

    exit(0);
}
[root@izj6cfw9yi1iqoik31tqbgz c]# ll -i tmp_fifo 
142117 prw-r--r-- 1 root root 0 Jun  6 22:10 tmp_fifo

[root@izj6cfw9yi1iqoik31tqbgz c]# ll -i main.c 
142110 -rw-rw-r-- 1 root root 4318 Jun  6 22:18 main.c

[root@izj6cfw9yi1iqoik31tqbgz c]# ll -i /dev/vda1
8186 brw-rw---- 1 root disk 253, 1 Mar  4 07:36 /dev/vda1
[root@izj6cfw9yi1iqoik31tqbgz c]# ./a.out tmp_fifo 
File type:                FIFO or pipe
主次设备号: major=253   minor=1
I-node number:            142117
Mode:                     10644 (rw-r--r--)
Number of (hard) links:   1
Ownership:                UID=0   GID=0
File size:                0 bytes
Optimal I/O block size:   4096 bytes
512B blocks allocated:    0
Last file access:         Wed Jun  6 22:10:57 2018
Last file modification:   Wed Jun  6 22:10:57 2018
Last status change:       Wed Jun  6 22:10:57 2018

[root@izj6cfw9yi1iqoik31tqbgz c]# ./a.out main.c 
File type:                regular file
主次设备号: major=253   minor=1
I-node number:            142110
Mode:                     100664 (rw-rw-r--)
Number of (hard) links:   1
Ownership:                UID=0   GID=0
File size:                4318 bytes
Optimal I/O block size:   4096 bytes
512B blocks allocated:    16
Last file access:         Wed Jun  6 22:17:27 2018
Last file modification:   Wed Jun  6 22:18:14 2018
Last status change:       Wed Jun  6 22:18:14 2018

[root@izj6cfw9yi1iqoik31tqbgz c]# ./a.out /dev/vda1
File type:                block device
设备文件主次设备号: major=253   minor=1
I-node number:            8186
Mode:                     60660 (rw-rw----)
Number of (hard) links:   1
Ownership:                UID=0   GID=6
Device number (st_rdev):  major=253; minor=1
File size:                0 bytes
Optimal I/O block size:   4096 bytes
512B blocks allocated:    0
Last file access:         Tue May 22 17:58:24 2018
Last file modification:   Sun Mar  4 07:36:08 2018
Last status change:       Sun Mar  4 07:36:08 2018


总结

本文对linux c文件属性做了简单的介绍,如果有疑问可以给我留言。


备注
1.编译器版本gcc4.8,运行环境centos7 64位
2.原文地址http://www.freecls.com/a/2712/48

©著作权归作者所有
收藏
推荐阅读
  • linux c挂载(mount)和卸载(unmount)

    读者可以打开linux命令系列-mount(挂载),unmount(卸载),两边对照着阅读。通过linux专有的虚拟文件 /proc/mounts,可查看当前已挂载的文件系统列表。其实/proc/mo...

  • err
    linux文件io缓冲

    出于速度和效率考虑,系统io调用(即内核)和标准 C语言库的io函数(即 stdin 函数)在操作磁盘文件时会对数据进行缓冲。read(),write()系统调用在操作磁...

  • err
    linux系统和进程信息(/proc)

    为了更方便的访问内核信息,许多现代的unix实现提供了/proc虚拟文件系统。其包含的文件和子目录并未存储在磁盘上,而是由内核进程访问此类信息动态的创建而成,都存储在内存...

  • err
    linux c时间

    日历时间#include &lt;sys/time.h&gt; struct timeval{ time_t tv_sec; /*自1970-01...

  • linux进程凭证(权限)

    每个进程都有一套用数字表示的用户id和组id,这些id决定了进程执行时具体的权限。实际用户id和实际组id这2个id决定了进程所属的用户和组。假设我们用root用户登录,那么我们在shell中创建的新...

  • nginx模块 ngx_http_headers_module

    ngx_http_headers_module 模块是用来增加 Expires 和 Cache-control,或者是任意的响应头。Syntax: add_header name value [alw...

  • nginx模块 ngx_http_gunzip_module、ngx_http_gzip_module、ngx_http_gzip_static_module

    ngx_http_gunzip_module 模块将文件解压缩后并在响应头加上 "Content-Encoding: gzip" 返回给客户端。为了解决客户端不支持gzip压缩。编译的时候带上 --w...

  • nginx模块 ngx_http_flv_module、ngx_http_mp4_module

    ngx_http_flv_module模块提供了对 flv 视频的伪流支持。编译的时候带上 --with-http_flv_module。它会根据指定的 start 参数来指定跳过多少字节,并在返回数...

  • nginx模块 ngx_http_fastcgi_module

    ngx_http_fastcgi_module 模块使得nginx可以与 fastcgi 服务器通信。比如目前要使得 nginx 支持 php 就得使用 fastcgi技术,在服务器上装上 nginx...

  • nginx模块 ngx_http_autoindex_module

    ngx_http_autoindex_module 模块可以将uri以 / 结尾时,列出里面的文件和目录。Syntax: autoindex on | off; Default: autoindex ...

简介
天降大任于斯人也,必先苦其心志。