获取文件状态的系统调用有三个,分别是stat,fstat和lstat,其实他们的作用是一样的,都是查询某个文件的状态。如果查询成功,会把文件状态的信息填充在一个stat结构体中。他们的函数定义分别如下:

int stat(const char *path, struct stat *buf);
int fstat(int fd, struct stat *buf);
int lstat(const char *path, struct stat *buf);

可以看到,这三个系统调用用于输出的参数类型是一样的,都是struct stat,其中,state与fstat的区别在于,stat()用文件名来指定要查询的文件,而fstat()用文件描述符来指定目标文件;而stat()与lstat()的区别在于,如果指定的文件是一个符号链接,那么stat会解引用,查询该链接指向的普通文件的属性,而lstat()在遇到符号链接文件是,不去解引用,而是直接返回这个符号链接文件本身的属性。要成功获取到指定文件的状态信息,需要用户对文件存储位置的每一层目录都具有执行和读取权限。

Linux的系统调用中还有很多类似的以 f 和 l 开头的系统调用,他们的区别与作用和stat系列函数都是类似的。

 

返回参数struct stat的结构定义与各字段的含义分别为:

struct stat {
               dev_t     st_dev;     /* 文件存放的设备ID */
               ino_t     st_ino;     /* 索引节点号 */
               mode_t    st_mode;    /* 文件的属性掩码 */
               nlink_t   st_nlink;   /* 硬链接的数量 */
               uid_t     st_uid;     /* 文件拥有者的用户ID */
               gid_t     st_gid;     /* 文件拥有者的组ID */
               dev_t     st_rdev;    /* 设备ID,仅对部分特殊文件有效 */
               off_t     st_size;    /* 文件大小,单位字节,软连接文件的大小是链接名长度 */
               blksize_t st_blksize; /* 文件使用的存储块大小 */
               blkcnt_t  st_blocks;  /* 文件占用的存储块数量,以512字节为单位 */
               time_t    st_atime;   /* 最后一次访问的时间 */
               time_t    st_mtime;   /* 最后一次内容修改的时间 */
               time_t    st_ctime;   /* 最后一次状态变化的时间 */
           };

对于st_mode字段,系统定义了一些宏来检查文件的类型:

           S_ISREG(m)  检查是否是常规文件

           S_ISDIR(m)  检查是否是目录

           S_ISCHR(m)  检查是否是字符设备 (如键盘)

           S_ISBLK(m)  检查是否是块设备(如硬盘)

           S_ISFIFO(m) 是否是命名管道

           S_ISLNK(m)  是否是符号链接

           S_ISSOCK(m) 是否是套接字

与其他的很多系统调用一样,这几个系统调用都是成功是返回0,否则返回-1,并设置对应的errno,常见的可能出现的errno有:
       EACCES:目标文件所在的目录或某个上级目录没有查找权限

      EBADF:指定的文件描述符无效.

       EFAULT:无效的文件地址

       ELOOP:可能遇到了循环引用的软链接文件

       ENAMETOOLONG:文件路径名太长.

       ENOENT:目录或文件不存在

       ENOMEM:内核内存耗尽

       ENOTDIR:指定的文件路径上,某个部分不是目录

       EOVERFLOW:引用的文件太大了,或者使用的索引节点太多了,或者占用的存储块太多了。

 

 

如下是使用stat()系统调用的演示程序:       

#include <sys/types.h>
       #include <sys/stat.h>
       #include <time.h>
       #include <stdio.h>
       #include <stdlib.h>

       int
       main(int argc, char *argv[])
       {
           struct stat sb;

           if (argc != 2) {
               fprintf(stderr, "Usage: %s <pathname>\n", argv[0]);
               exit(EXIT_FAILURE);
           }

           if (stat(argv[1], &sb) == -1) {
               perror("stat");
               exit(EXIT_FAILURE);
           }

           printf("File type:                ");

switch (sb.st_mode & S_IFMT) {
           case S_IFBLK:  printf("block device\n");            break;
           case S_IFCHR:  printf("character device\n");        break;
           case S_IFDIR:  printf("directory\n");               break;
           case S_IFIFO:  printf("FIFO/pipe\n");               break;
           case S_IFLNK:  printf("symlink\n");                 break;
           case S_IFREG:  printf("regular file\n");            break;
           case S_IFSOCK: printf("socket\n");                  break;
           default:       printf("unknown?\n");                break;
           }

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

           printf("Mode:                     %lo (octal)\n",
                   (unsigned long) sb.st_mode);

           printf("Link count:               %ld\n", (long) sb.st_nlink);
           printf("Ownership:                UID=%ld   GID=%ld\n",
                   (long) sb.st_uid, (long) sb.st_gid);

           printf("Preferred I/O block size: %ld bytes\n",
                   (long) sb.st_blksize);
           printf("File size:                %lld bytes\n",
                   (long long) sb.st_size);
           printf("Blocks allocated:         %lld\n",
                   (long long) sb.st_blocks);

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

           exit(EXIT_SUCCESS);
       }

 

==================== 以下是广告 ====================

更多系统详尽的Linux系统编程内容,欢迎订阅GitChat专栏 《攻克Linux系统编程》

 

 

GitHub 加速计划 / li / linux-dash
10.39 K
1.2 K
下载
A beautiful web dashboard for Linux
最近提交(Master分支:2 个月前 )
186a802e added ecosystem file for PM2 4 年前
5def40a3 Add host customization support for the NodeJS version 4 年前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐