linux系统编程之文件与I/O(四):文件的属性

一、读取文件元数据

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

 stat() stats the file pointed to by path and fills in buf.

  lstat()  is  identical to stat(), except that if path is a symbolic link, then the link itself is stat-ed, not the file that it refers to.   fstat() is identical to stat(), except that the file to be stat-ed is specified by the file descriptor fd.

二、stat结构体

struct stat { dev_t     st_dev;     /* ID of device containing file */ ino_t     st_ino;     /* inode number */ mode_t    st_mode;    /* protection */ nlink_t   st_nlink;   /* number of hard links */     硬链接是不可以跨越文件系统的 uid_t     st_uid;     /* user ID of owner */ gid_t     st_gid;     /* group ID of owner */ dev_t     st_rdev;    /* device ID (if special file) */ off_t     st_size;    /* total size, in bytes */ blksize_t st_blksize; /* blocksize for file system I/O */ blkcnt_t  st_blocks;  /* number of 512B blocks allocated */ time_t    st_atime;   /* time of last access */  read time_t    st_mtime;   /* time of last modification */  write time_t    st_ctime;   /* time of last status change */ chmod/chown };

示例程序:

/*************************************************************************
    > File Name: file_stat.c
    > Author: Simba
    > Mail: dameng34@163.com
    > Created Time: Sat 23 Feb 2013 02:34:02 PM CST
 ************************************************************************/
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>

#define ERR_EXIT(m) \
    do { \
        perror(m); \
        exit(EXIT_FAILURE); \
    } while(0)

#define MAJOR(a) (int)((unsigned short)a >> 8)  // 高8位,主设备号
#define MINOR(a) (int)((unsigned short)a & 0xFF)

int filetype(struct stat *buf)
{
    int flag = 0;
    printf("Filetype:");
    mode_t mode;
    mode = buf->st_mode;
    switch (mode & S_IFMT)
    {

    case S_IFSOCK:
        printf("socket\n");
        break;
    case S_IFLNK:
        printf("symbolic link\n");
        break;
    case S_IFREG:
        printf("regular file\n");
        break;
    case S_IFBLK:
        printf("block device\n");
        flag = 1;
        break;
    case S_IFDIR:
        printf("directory\n");
        break;
    case S_IFCHR:
        printf("character device\n");
        flag = 1;
        break;
    case S_IFIFO:
        printf("FIFO\n");
        break;
    default:
        printf("unknown file type\n");
        break;
    }

    return flag;
}

void fileperm(struct stat *buf, char perm[])
{
    strcpy(perm, "----------");
    perm[0] = '?';
    mode_t mode;
    mode = buf->st_mode;
    switch (mode & S_IFMT)
    {

    case S_IFSOCK:
        perm[0] = 's';
        break;
    case S_IFLNK:
        perm[0] = 'l';
        break;
    case S_IFREG:
        perm[0] = '-';
        break;
    case S_IFBLK:
        perm[0] = 'b';
        break;
    case S_IFDIR:
        perm[0] = 'd';
        break;
    case S_IFCHR:
        perm[0] = 'c';
        break;
    case S_IFIFO:
        perm[0] = 'p';
        break;
    }

    if (mode & S_IRUSR)
        perm[1] = 'r';
    if (mode & S_IWUSR)
        perm[2] = 'w';
    if (mode & S_IXUSR)
        perm[3] = 'x';
    if (mode & S_IRGRP)
        perm[4] = 'r';
    if (mode & S_IWGRP)
        perm[5] = 'w';
    if (mode & S_IXGRP)
        perm[6] = 'x';
    if (mode & S_IROTH)
        perm[7] = 'r';
    if (mode & S_IWOTH)
        perm[8] = 'w';
    if (mode & S_IXOTH)
        perm[9] = 'x';
    perm[10] = '\0';
}


int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        fprintf(stderr, "Usage %s file\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    printf("Filename:%s\n", argv[1]);
    struct stat sbuf;
    if (lstat(argv[1], &sbuf) == -1)
        ERR_EXIT("stat error");

    printf("file in Dev number:major %d, minor %d\n",
           MAJOR(sbuf.st_dev), MINOR(sbuf.st_dev));
    printf("File inode:%d\n", (int) sbuf.st_ino);

    if (filetype(&sbuf))
    {
        printf("Device number:major %d, minor %d\n",
               MAJOR(sbuf.st_rdev), MINOR(sbuf.st_rdev));
    }

    char perm[11] = {0};
    fileperm(&sbuf, perm);
    printf("File permission bits=%o %s\n", sbuf.st_mode & 0777, perm);  // 0777 是八进制数

    return 0;
}

测试如下:

simba@ubuntu:~/Documents/code/linux_programming/APUE/File_IO$ ./file_stat Makefile  Filename:Makefile file in Dev number:major 8, minor 1 File inode:660022 Filetype:regular file File permission bits=664 -rw-rw-r--

因为是普通文件,故从st_dev字段看设备号,而不是st_rdev. 主设备号表示设备驱动程序,而次设备号表示特定的子设备。比如在同一个磁盘上面不同的文件系统,设备驱动程序相当,但是次设备号不同。

st_rdev只有字符特殊文件和块特殊文件才有这个值,表示实际设备的设备编号。

  • The st_dev value for every filename on a system is the device number of the file system containing that filename and its corresponding  i-node.
  • Only character special files and block special files have an st_rdev value. This value contains the device number for the actual device. #include "apue.h" #ifdef SOLARIS #include <sys/mkdev.h> #endif int main(int argc, char *argv[]) {     int i;     struct stat buf;     for (i = 1; i < argc; i++)     {         printf("%s: ", argv[i]);         if (stat(argv[i], &buf) < 0)         {             err_ret("stat error");             continue;         }         printf("dev = %d/%d", major(buf.st_dev), minor(buf.st_dev));         if (S_ISCHR(buf.st_mode) || S_ISBLK(buf.st_mode))         {             printf(" (%s) rdev = %d/%d",                    (S_ISCHR(buf.st_mode)) ? "character" : "block",                    major(buf.st_rdev), minor(buf.st_rdev));         }         printf("\n");     }     exit(0); }
     $ ./a.out / /home/sar /dev/tty[01]
      /: dev = 3/3
      /home/sar: dev = 3/4
      /dev/tty0: dev = 0/7 (character) rdev = 4/0
      /dev/tty1: dev = 0/7 (character) rdev = 4/1
      $ mount                      which directories are mounted on which devices?
      /dev/hda3 on / type ext2 (rw,noatime)
      /dev/hda4 on /home type ext2 (rw,noatime)
      $ ls -lL /dev/tty[01] /dev/hda[34]
      brw-------  1 root       3,   3 Dec 31  1969 /dev/hda3
      brw-------  1 root       3,   4 Dec 31  1969 /dev/hda4
      crw-------  1 root       4,   0 Dec 31  1969 /dev/tty0
      crw-------  1 root       4,   1 Jan 18 15:36 /dev/tty1

Note that the filenames and i-nodes for the two terminal devices (st_dev) are on device 0/7 the devfs pseudo file system, which implements the /dev but that their actual device numbers are 4/0 and 4/1.

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏杨建荣的学习笔记

性能调优之redo切换频率(47天)

生产系统的一个库(负责容错处理的),目前遇到了严重的性能问题,数据量也大的出奇,一个分区表一百多个分区,blob字段达到了800多G.查看 AWR 系统负载倒不...

3254
来自专栏应兆康的专栏

100个Numpy练习【5】

翻译:YingJoy 网址: https://www.yingjoy.cn/ 来源: https://github.com/rougier/numpy-100...

50012
来自专栏重庆的技术分享区

五(七)层互联网协议(计算机网络)深入浅出,看完必懂【图文一】

1365
来自专栏Kubernetes

利用Kubernetes和Helm进行高效的超参数调优

在进行Hyperparameter Sweep的时候,我们需要根据许多不同的超参数组合进行不同的训练,为同一模型进行多次训练需要消耗大量计算资源或者耗费大量时间...

951
来自专栏青玉伏案

算法与数据结构(六) 迪杰斯特拉算法的最短路径(Swift版)

上篇博客我们详细的介绍了两种经典的最小生成树的算法,本篇博客我们就来详细的讲一下最短路径的经典算法----迪杰斯特拉算法。首先我们先聊一下什么是最短路径,这个还...

1855
来自专栏PHP实战技术

OSI 七层模型简单梳理!

功能:OSI 七层模型通过七个层次化的结构模型使不同的系统不同的网络之间实现可靠的通讯。 7.应用层 网络服务与最终用户的一个接口。 协议有:HTTP F...

47612
来自专栏土豆专栏

计算机网络基础知识整理--网络层

小编最近在复习计算机网络基础,整理出来一些我认为比较重要的知识。希望能帮到大家哈,后续会更新~

69422
来自专栏应兆康的专栏

100个Numpy练习【5】

Numpy是Python做数据分析必须掌握的基础库之一,非常适合刚学习完Numpy基础的同学,完成以下习题可以帮助你更好的掌握这个基础库。

51810
来自专栏黑白安全

如何攻破加密算法

当应用加密算法时,有许多地方可能会出错。难点在于识别和分析程序员用来加密的方法,然后寻找其中的漏洞。漏洞的种类也很多,比如弱加密算法、弱密钥生成器、服务端漏洞和...

682
来自专栏祝威廉

如何基于SDL+TensorFlow/SK-Learn开发NLP程序

确保安装了python 2.7 ,强烈建议你使用Virtualenv方便python环境的管理。之后通过pip 安装pyspark

513

扫码关注云+社区