Linux系统调用 - 获取文件状态 (stat, lstat和fstat)

获取文件状态的系统调用有三个,分别是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);
       }

————————————————
版权声明:本文为CSDN博主「|宇文拓>」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/yubo112002/article/details/84076277

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值