您的位置:首页 > 运维架构 > Linux

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

2013-06-23 22:48 671 查看
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。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Linux stat