Understanding Linux fstat() With Example

Discussion in 'C' started by poornaMoksha, Dec 26, 2011.

  1. poornaMoksha

    poornaMoksha New Member

    Joined:
    Jan 29, 2011
    Messages:
    150
    Likes Received:
    33
    Trophy Points:
    0
    Occupation:
    Software developer
    Location:
    India
    We will understand a very important function 'fstat()'. We will create a working code to describe the capabilities of fstat() but before that lets theoretically Understand what it does.

    fstat() as the name suggests is used to get the status of the file. By status we mean all the useful information related to the file.

    The signature of fstat() is :

    Code:
    int fstat(int fd, struct stat *buf);
    Where fd is the file descriptor and the structure 'buf' is returned by the API. This structure object contains all the information. The function returns 0 on success and -1 on failure.

    The information that can be retrieved by the stat object is :

    Code:
    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 */ 
                   time_t    st_mtime;   /* time of last modification */ 
                   time_t    st_ctime;   /* time of last status change */ 
               };

    Information provided by fstat()



    Although fstat() provides a varied range of information. In this article we will try to understand how to use fstat() to retrieve some basic information like :
    • Whether the file is a directory or a regular file.
    • The user ID and the group ID of the owner of the file.
    • Other information like Size of the file in bytes, Access and modification times etc.
    But to begin with lets study how to use the function fstat()

    Fstat(): An example



    Before understanding the importance of fstat() lets first take a look at how to use fstat().

    Here is a code :

    Code:
    #include <stdio.h> 
    #include <sys/types.h> 
    #include <sys/stat.h> 
    #include <unistd.h> 
    #include <errno.h> 
    #include <string.h> 
    #include <fcntl.h> 
     
    int main(void) 
    { 
        int f_d = 0; 
        struct stat st; 
          
        // Open the file test.txt through open() 
        // Note that since the call to open directly gives 
        // integer file descriptor so we used open here. 
        // One can also use fopen() that returns FILE* 
        // object. Use fileno() in that case to convert 
        // FILE* object into the integer file descriptor 
        f_d = open("test.txt",O_RDONLY); 
     
        //Check if open() was successful 
        if(-1 == f_d) 
        { 
            printf("\n NULL File descriptor\n"); 
            return -1; 
        } 
     
        // set the errno to default value 
        errno = 0; 
        // Now a call to fstat is made 
        // Note that the address of struct stat object 
        // is passed as the second argument 
        if(fstat(f_d, &st)) 
        { 
            printf("\nfstat error: [%s]\n",strerror(errno)); 
            close(f_d); 
            return -1; 
        } 
     
        // Access the object 'buff' for accessing 
        // various stats information. 
     
        // Close the file 
        close(f_d); 
     
        return 0; 
    }
    In the above code we have not accessed any information as yet. We have just showed how to use fstat.

    Check whether the file is directory or a regular file



    As we know that in Linux every thing is a file, be it a directory, socket or anything else. So, lets use fstat() to check whether a file is a directory or a file.

    Here is the code :

    Code:
    #include <stdio.h> 
    #include <sys/types.h> 
    #include <sys/stat.h> 
    #include <unistd.h> 
    #include <errno.h> 
    #include <string.h> 
    #include <fcntl.h> 
     
    int main(void) 
    { 
        int f_d = 0; 
        struct stat st; 
          
        // Open the file test.txt through open() 
        // Note that since the call to open directly gives 
        // integer file descriptor so we used open here. 
        // One can also use fopen() that returns FILE* 
        // object. Use fileno() in that case to convert 
        // FILE* object into the integer file descriptor 
        f_d = open("test.txt",O_RDONLY); 
     
        //Check if open() was successful 
        if(-1 == f_d) 
        { 
            printf("\n NULL File descriptor\n"); 
            return -1; 
        } 
     
        // set the errno to default value 
        errno = 0; 
        // Now a call to fstat is made 
        // Note that the address of struct stat object 
        // is passed as the second argument 
        if(fstat(f_d, &st)) 
        { 
            printf("\nfstat error: [%s]\n",strerror(errno)); 
            close(f_d); 
            return -1; 
        } 
     
        if(S_ISREG(st.st_mode)) 
        { 
            printf("\n File is a regular file\n"); 
        } 
        else if(S_ISDIR(st.st_mode)) 
        { 
            printf("\n File is a directory\n"); 
        } 
     
        // Close the file 
        close(f_d); 
     
        return 0; 
    }
    • In the above code, we have used the macros S_ISDIR and S_ISREG to check if the file is a directory or a regular file.
    • The following POSIX macros are defined to check the file type using the st_mode field:
      • 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.)
    • You can use these macros for your suitable test.
    When you run the above program you get an output like :

    Code:
    $ ./fstat  
     
     File is a regular file
    So we see that It successfully tells that the file test.txt is a regular file.

    Also, The above check for files or directories can also be done in the following way :

    Code:
    #include <stdio.h> 
    #include <sys/types.h> 
    #include <sys/stat.h> 
    #include <unistd.h> 
    #include <errno.h> 
    #include <string.h> 
    #include <fcntl.h> 
     
    int main(void) 
    { 
        int f_d = 0; 
        struct stat st; 
          
        // Open the file test.txt through open() 
        // Note that since the call to open directly gives 
        // integer file descriptor so we used open here. 
        // One can also use fopen() that returns FILE* 
        // object. Use fileno() in that case to convert 
        // FILE* object into the integer file descriptor 
        f_d = open("test.txt",O_RDONLY); 
     
        //Check if open() was successfull 
        if(-1 == f_d) 
        { 
            printf("\n NULL File descriptor\n"); 
            return -1; 
        } 
     
        // set the errno to default value 
        errno = 0; 
        // Now a call to fstat is made 
        // Note that the address of struct stat object 
        // is passed as the second argument 
        if(fstat(f_d, &st)) 
        { 
            printf("\nfstat error: [%s]\n",strerror(errno)); 
            close(f_d); 
            return -1; 
        } 
     
        switch (st.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; 
               } 
     
     
        // Close the file 
        close(f_d); 
     
        return 0; 
    }
    The output of the above code is :

    Code:
    $ ./fstat  
    regular file
    So we see that by using these flags also we can determine the type of file.

    The following flags are defined for the st_mode field:

    S_IFMT 0170000 bit mask for the file type bit fields
    S_IFSOCK 0140000 socket
    S_IFLNK 0120000 symbolic link
    S_IFREG 0100000 regular file
    S_IFBLK 0060000 block device
    S_IFDIR 0040000 directory
    S_IFCHR 0020000 character device
    S_IFIFO 0010000 FIFO
    S_ISUID 0004000 set UID bit
    S_ISGID 0002000 set-group-ID bit (see below)
    S_ISVTX 0001000 sticky bit (see below)
    S_IRWXU 00700 mask for file owner permissions
    S_IRUSR 00400 owner has read permission
    S_IWUSR 00200 owner has write permission
    S_IXUSR 00100 owner has execute permission
    S_IRWXG 00070 mask for group permissions
    S_IRGRP 00040 group has read permission
    S_IWGRP 00020 group has write permission
    S_IXGRP 00010 group has execute permission
    S_IRWXO 00007 mask for permissions for others (not in group)
    S_IROTH 00004 others have read permission
    S_IWOTH 00002 others have write permission
    S_IXOTH 00001 others have execute permission

    The user ID and the group ID of the owner of the file



    Here is the code :

    Code:
    #include <stdio.h> 
    #include <sys/types.h> 
    #include <sys/stat.h> 
    #include <unistd.h> 
    #include <errno.h> 
    #include <string.h> 
    #include <fcntl.h> 
     
    int main(void) 
    { 
        int f_d = 0; 
        struct stat st; 
          
        // Open the file test.txt through open() 
        // Note that since the call to open directly gives 
        // integer file descriptor so we used open here. 
        // One can also use fopen() that returns FILE* 
        // object. Use fileno() in that case to convert 
        // FILE* object into the integer file descriptor 
        f_d = open("test.txt",O_RDONLY); 
     
        //Check if open() was successful 
        if(-1 == f_d) 
        { 
            printf("\n NULL File descriptor\n"); 
            return -1; 
        } 
     
        // set the errno to default value 
        errno = 0; 
        // Now a call to fstat is made 
        // Note that the address of struct stat object 
        // is passed as the second argument 
        if(fstat(f_d, &st)) 
        { 
            printf("\nfstat error: [%s]\n",strerror(errno)); 
            close(f_d); 
            return -1; 
        } 
     
     
        printf("\n The userID and the GroupID of the owner of the file are [%d] and [%d] respectively \n", (int)st.st_uid, (int)st.st_gid); 
     
        // Close the file 
        close(f_d); 
     
        return 0; 
    }
    In the above code the user ID and the group ID are accessed by the variables st_uid and st_gid of the stat structure.

    The output of the above code comes out to be :

    Code:
    ./fstat  
     
     The userID and the GroupID of the owner of the file are [1000] and [1001] respectively

    Other information like size, access/modification times etc.



    Here is the code :

    Code:
    #include <stdio.h> 
    #include <sys/types.h> 
    #include <sys/stat.h> 
    #include <unistd.h> 
    #include <errno.h> 
    #include <string.h> 
    #include <fcntl.h> 
    #include <time.h> 
     
    int main(void) 
    { 
        int f_d = 0; 
        struct stat st; 
          
        // Open the file test.txt through open() 
        // Note that since the call to open directly gives 
        // integer file descriptor so we used open here. 
        // One can also use fopen() that returns FILE* 
        // object. Use fileno() in that case to convert 
        // FILE* object into the integer file descriptor 
        f_d = open("test.txt",O_RDONLY); 
     
        //Check if open() was successful 
        if(-1 == f_d) 
        { 
            printf("\n NULL File descriptor\n"); 
            return -1; 
        } 
     
        // set the errno to default value 
        errno = 0; 
        // Now a call to fstat is made 
        // Note that the address of struct stat object 
        // is passed as the second argument 
        if(fstat(f_d, &st)) 
        { 
            printf("\nfstat error: [%s]\n",strerror(errno)); 
            close(f_d); 
            return -1; 
        } 
     
        switch (st.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("File size:                %lld bytes\n",(long long) st.st_size); 
         printf("Last status change:       %s", ctime(&st.st_ctime)); 
         printf("Last file access:         %s", ctime(&st.st_atime)); 
         printf("Last file modification:   %s", ctime(&st.st_mtime)); 
     
     
        // Close the file 
        close(f_d); 
     
        return 0; 
    }
    We see that in the above code we tried to fetch various other kind of information from the stat structure.

    The output of the above code is :

    Code:
    $ ./fstat  
    regular file 
    File size:                13 bytes 
    Last status change:       Mon Dec 26 20:56:52 2011 
    Last file access:         Mon Dec 26 20:56:56 2011 
    Last file modification:   Mon Dec 26 20:56:52 2011

    Conclusion



    To conclude, In this article, we studied the usage of fstat() API and how we can fetch various type of information related to any file using fstat() API.

    Stay tuned for more!!!
     
    lionaneesh likes this.
  2. lionaneesh

    lionaneesh Active Member

    Joined:
    Mar 21, 2010
    Messages:
    848
    Likes Received:
    224
    Trophy Points:
    43
    Occupation:
    Student
    Location:
    India

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice