• linux获取文件属性(API)


    有三个文件属性查看的API:stat、fstat、lstat。
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    int stat(const char *pathname, struct stat *buf);
    int fstat(int fd, struct stat *buf);
    int lstat(const char *pathname, struct stat *buf);
    #include <fcntl.h> /* Definition of AT_* constants */
    #include <sys/stat.h>
    int fstatat(int dirfd, const char *pathname, struct stat *buf,int flags);
    stat不用打开文件,fstat需要打开文件,lstat主要是符号链接文件,查询链接文件本身。
    struct stat是一个内核定义结构体,在#include <sys/stat.h>声明,这个里面的内容加起来就是文件属性信息。里面的各个元素就是各种属性。
    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 filesystem I/O */
    blkcnt_t st_blocks; /* number of 512B blocks allocated */
    /* Since Linux 2.6, the kernel supports nanosecond
    precision for the following timestamp fields.
    For the details before Linux 2.6, see NOTES. */
    struct timespec st_atim; /* time of last access */
    struct timespec st_mtim; /* time of last modification */
    struct timespec st_ctim; /* time of last status change */
    #define st_atime st_atim.tv_sec /* Backward compatibility */
    #define st_mtime st_mtim.tv_sec
    #define st_ctime st_ctim.tv_sec
    };
    在ubantu16.04命令行中输入 stat XXX:
    文件:'a.out'
    大小:8968 块:18 IO 块:1024 普通文件
    设备:2ah/42d Inode:5331 硬链接:1
    权限:(0777/-rwxrwxrwx) Uid:( 0/ root) Gid:( 0/ root)
    最近访问:2018-08-12 12:29:37.000000000 +0800
    最近更改:2018-08-12 12:29:37.000000000 +0800
    最近改动:2018-08-12 12:29:37.000000000 +0800
    创建时间:-
    上诉信息就为结构体里面数据。
    下面非常简单的测试函数
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <string.h>
    #define FILENAME "1.txt"
    int main (void)
    {
    int ret = -1;
    struct stat buf;
    memset(&buf, 0, sizeof(buf));
    ret = stat(FILENAME,&buf);
    if(ret<0)
    {
    perror("ret:");
    _exit(-1);
    }
    printf("st_ino = %d ",buf.st_ino);
    printf("st_size = %d ",buf.st_size);
    printf("st_blksize = %d ",buf.st_blksize);
    printf("st_blocks = %d ",buf.st_blocks);
    return 0;
    }
    如下为应用案例:
    1、判断文件类型
    文件类型在st_mode里面,这里面是为操作的,类似于CPSR寄存器。linux中有很多宏来进行操作位的测试。如下
    S_ISREG(m) is it a regular file?
    S_ISDIR(m) directory?
    S_ISCHR(m) character device?
    S_ISBLK(m) block device?
    S_ISFIFO(m) FIFO (named pipe)?
    S_ISLNK(m) symbolic link? (Not in POSIX.1-1996.)
    S_ISSOCK(m) socket? (Not in POSIX.1-1996.)
    S_ISREG这个宏返回1,则是普通文件,若不是就返回0.结果就是若是这个文件则是返回1,不是返回0.此外,st_mode还记录了文件权限。测试方法和文件类型相似,使用位掩码,但是没有宏操作。由于很多,不再一一列举,可通过man 2 stat查看。
    简单测试代码:
    unsigned int result = buf.st_mode & (S_IRUSR >> 8);
    printf("file owner :%X ",result);
    对于文件来说,很重要的一部分就是文件的权限管理。
    st_mode本质上一个三十二位的二进制,类型差不多就是unsigned int,反正差不多。
    在操作之前需要对文件进行权限规则检查:
    1、文件有9个权限位(owner,group,others)
    2、若是a.out为例,是看什么执行了a.out,也就是当前进程,是哪个用户进程。
    在linux下面可以通过access函数来判断是否有执行权限,可以测试得到当前用户当前环境对目标文件是否有某种操作权限。
    #include <unistd.h>
    int access(const char *pathname, int mode);
    具体可通过man 2 access查看。
    chowd和fchowd和lchowd
    通过man 2 chmod查看,是用修改文件属主。
    文件掩码umask是linux中的一个全局设置,作用就是设定我们系统新创建权限。
    对于目录文件,包含子文件的文件。
    opendir与readdir
    #include <sys/types.h>
    #include <dirent.h>
    DIR *opendir(const char *name);
    DIR *fdopendir(int fd);
    #include <dirent.h>
    struct dirent *readdir(DIR *dirp);
    int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
    struct dirent {
    ino_t d_ino; /* inode number */
    off_t d_off; /* not an offset; see NOTES */
    unsigned short d_reclen; /* length of this record */
    unsigned char d_type; /* type of file; not supportedby all filesystem types */
    char d_name[256]; /* filename */
    };
    每调用readdir一次只能读出一个,要想读出目录中的所有目录项,那么必须多次读取,readdir函数内部记住那个目录已经被调用的,不会回返已经读取的目录项,要是readdir要是返回NULL就表示已经读取完了。简单的测试函数如下:
    #include <stdio.h>
    #include <dirent.h>
    #include <sys/types.h>
    #include <dirent.h>
    int main(int argc,char **argv)
    {
    DIR *pDir = NULL;
    struct dirent *pEnt = NULL;
    if(argc !=2)
    {
    printf("error");
    return 0;
    }
    pDir = opendir(argv[1]);
    if(NULL == pDir)
    {
    perror("opendir: ");
    return -1;
    }
    while(1)
    {
    pEnt = readdir(pDir);
    if(pEnt != NULL)
    {
    printf("name:%s ",pEnt->d_name);
    }
    else
    {
    break;
    }
    }
    return 0;
    }
    可重入函数:readdir函数和以前接触的函数是不同的,这个函数直接返回了一个结构体指针。因readdir内部申请了内存并且给了我们地址,多次调用readdir其实不会重复申请内存而是使用第一次调用readdir是分配的那个内存,所以设计方法是readdir不可重入的关键。
    库函数有一些函数是不可重入的,后来意识到这个中不安全,后来重新封装了C库函数,一般是不可重入函数后面加入_r变成可重入的函数。

    朱友鹏老师视频学习笔记 

  • 相关阅读:
    X-Plosives (并查集)
    HDU1272小希的迷宫 (并查集)
    React 初学
    js 插件 issue
    js常用方法
    常用网址
    js 零零散散的总结。
    git 常用命令
    es6 babel编译
    屏幕适配
  • 原文地址:https://www.cnblogs.com/lifeng40433/p/9471876.html
Copyright © 2020-2023  润新知