This is the 22nd day of my participation in the Gwen Challenge in November. Check out the details: The last Gwen Challenge in 2021.”

One, foreword

When programming files and directories in Linux, you often need to obtain the property information of specified files, such as the file type, size, creation date, and modification date.

It is very useful to obtain such information, for example, so that when opening a device file, you can determine in advance whether the device file is of the correct type in case of unknown errors. When you copy, read, or map a file, you can determine whether the file is fully read or written according to the file size.

There are three functions in Linux that can quickly obtain file and directory properties:

Stat, fstat, lstatCopy the code

Detailed introduction is as follows:

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int stat(const char *path, struct stat *buf); The file/directory state function is used to obtain the file/directory state function parameters:const char*path Path of a file or directory.struct stat *bufSave the obtained status informationint fstat(int fd.struct stat *buf);Function Obtain file status information. Function parameters:intFd file descriptorstruct stat *bufSave the obtained status informationint lstat(const char *path.struct stat *buf);Function Obtain file status information. Link files are not differentiated. Structure that holds state information:struct stat {
   dev_t     st_dev;     /* ID of device containing file */
   ino_t     st_ino;     /* inode number */
   mode_t    st_mode;    /* protection Specifies the file type */
   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 Specifies the file size */
   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 */
   time_t    st_mtime;   /* time of last modification */
   time_t    st_ctime;   /* time of last status change */
};

S_ISREG(m) is it a regular file? Common fileS_ISDIR(m) directory? directoryS_ISCHR(m) character device? Character device fileS_ISBLK(m) block device? Block device fileS_ISFIFO(m) FIFO(named pipe)? Pipeline fileS_ISLNK(m)  symbolic link? (Not in POSIX1.- 1996.) link fileS_ISSOCK(m) socket? (Not in POSIX1.- 1996.) socket fileCopy the code

The st_size attribute is not available when the stat function is used to obtain information about a directory. The size of the directory needs to be calculated, and it may contain many subdirectories, etc.

Ii. Case code

The following uses the state function to write an example: When the program runs, pass the path from the command line, call the opendir function to open the directory, cycle through the directory, read all the files in the directory, and judge the type of each file, space size and other information to print to the terminal display.

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>

int main(int argc,char **argv)
{
    if(argc! =2)
    {
        printf("Parameter:./a.out < directory path >\n");
        return 0;
    }
    /*1. Open the directory */
    DIR *dir=opendir(argv[1]);
    if(dir==NULL)
    {
        printf("%s directory failed to open.\n",argv[1]);
        return - 1;
    }
    /*2. Traverse the directory */
    struct dirent *dir_info;
    struct stat s_buf; // Store status information
    char *abs_path=NULL;
    while(dir_info=readdir(dir))
    {
        //1. Apply for space
        abs_path=malloc(strlen(argv[1]) +strlen(dir_info->d_name)+1);
        //2. Splice paths
        sprintf(abs_path,"%s%s",argv[1],dir_info->d_name);
        //3. Obtain the file status information
        stat(abs_path,&s_buf);
        //4. Print the file status
        if(S_ISREG(s_buf.st_mode))
        {
            printf("%s is a normal file. File size :%d Byte\n",abs_path,s_buf.st_size);
        }
        else if(S_ISDIR(s_buf.st_mode))
        {
            printf("%s is the directory.\n",abs_path);
        }
        else if(S_ISCHR(s_buf.st_mode))
        {
            printf("%s character device file.\n",abs_path);
        }
        else if(S_ISBLK(s_buf.st_mode))
        {
            printf("%s block device file.\n",abs_path);
        }
        else if(S_ISFIFO(s_buf.st_mode))
        {
            printf("%s is a pipe file.\n",abs_path);
        }
        else if(S_ISLNK(s_buf.st_mode))
        {
            printf("%s is a linked file.\n",abs_path);
        }

        //5. Free space
        free(abs_path);
    }
    3. Close the directory */
    closedir(dir);
    return 0;
}
Copy the code