Linux 获取文件属性 函数 stat, fstat, lstat 以及 stat 结构体


linux编程里,有三个函数可以获取 文件的属性(包含了文件类型和文件权限等属性)。


三个函数的原型如下:

#include <sys/stat.h>

int stat(const char *restrict pathname, struct stat *restrict buf);

int fstat(int filedes, struct stat *restrict buf);

int lstat(const char *restrict pathname, struct stat *resstrict buf);


在这三个函数中,都用到了stat 结构体, 这里就介绍一下stat结构体。

struct stat

{

    mode_t   st_mode;      //文件访问权限,类型

    ino_t        st_ino;          //索引节点号

    dev_t       st_dev;         //文件所在设备的设备号

    dev_t       st_rdev;       //文件inode所代表的设备的设备号。

    nlink_t     st_nlink;      //硬链接数

    uid_t        st_uid;         //文件所有者 用户ID

    gid_t        st_gid;         //文件所在组 组ID

    off_t         st_size;        //普通文件,文件大小, Bytes

    time_t      st_atime;     //文件被最后访问(access)的时间

    time_t      st_mtime;    //文件内容最后被修改(modify)的时间

    time_t      st_ctime;     //文件状态最后被修改的时间( status change)

    blksize_t st_blksize;     //文件所在磁盘的磁盘块大小

    blkcnt_t   st_blocks;      //文件占用块数量

};

通过一下的带参宏定义我们可以通过 st_mode参数判断出文件的类型:


S_ISREG(m)      : 是否是普通文件。

S_ISDIR(m)       : 是否是目录

S_ISCHR(m)     : 是否是字符设备

S_ISBLK(m)      : 是否是块设备

S_ISFIFO(m)      : 是否是FIFO(命名管道?)

S_ISLNK(m)      : 是否是链接

S_ISSOCK(m)   : 是否是socket


另外对于文件的读写属性也有如下的宏定义:

S_IRUSR  :所有者-读

S_IWUSR  :所有者-写

S_IXUSR   :所有者-执行

S_IRGRP  : 组-读

S_IWGRP  : 组-写

S_IXGRP  :组-执行

S_IROTH  :其他-读

S_IWOTH  :其他-写

S_IXOTH  :其他-执行


讲完了,stat函数 中最重要的出参 struct stat, 接下来就讲下 函数的返回值


函数返回值:

成功执行返回为0,  如果失败则返回-1, 并且置errno。


errno类型:

EACCES: 搜索权限被拒绝。

EBADF   : fd有误

EFAULT  : 地址有误

ELOOP    : 遍历路径时遇到太多的符号连接

ENAMETOOLONG  : path 太长

ENOENT  : 路径path为空,或者路径有误。

ENOMEM : no memory

ENOTDIR : 路径非法,其中路径中有不是目录的部分。


然后, stat, fstat, 和lstat 之间的区别是什么呢?


通过函数原型,我们也可以知道一二。

对于stat,它可以仅仅通过文件地址,获取文件属性,而不一定要打开文件; 而fstat 需要将文件打开,获取fd,然后通过fd来获取文件的stat。

对于链接文件, stat获取的文件属性是被链接文件的文件属性,而lstat获取的则是链接文件本身的文件属性。


示例:(来自于http://linux.die.net/man/2/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);
}

上述示例中的, S_IF* (S_IFBLK, ....)可以通过 sb.st_mode & S_IFMT 来获取,也可以通过 上边介绍的那些宏定义S_ISREG(m)来获取。


在我现在尝试写的一个webserver 小程序里,就需要通过 stat 来判断 文件是否存在, 文件是否可以执行。


inline int IsExecutable(mode_t mode)

{

      return (mode & S_IXOTH );

}.



本文有部分内容来自于:http://linux.die.net/man/2/stat。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值