Friday, 7 June 2019

stat, fstat & lstat Usage & diff

Name

  • stat, fstat, lstat - get file status

Synopsis

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

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

Description

  • These functions return information about a file.
  • No permissions are required for file, but-in the case of stat() and lstat() - execute (search) permission is required on all of the directories in path that lead to the file.

Def:

  • 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.

Difference:

  • lstat() - if pathname is a symbolic link, then it returns information about the link itself, not the file (target) that it refers to.
  • stat()  - if pathname is a symbolic link, then it returns information about the target file that it refers to.

Symbolic file behaviour while opening:

  • Even if we touch the symbalic file, the modified time for target fill only will get modified, symbolic file modified time will be remain same.
  • If we edit the file using symbolic link, then modified time for target will be get changed but not symbolic file.

  • All of these system calls return a stat structure, which contains the following fields:
    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 */
    };

st_mode field:

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

Return Value

On success, zero is returned. On error, -1 is returned, and errno is set appropriately.

Program:



/* Difference between stat & lstat  by Velraj.K
 * Check : http://velrajcoding.blogspot.in
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>         // For memset

/* Note:
 *     Even if we touch the symbalic file, the modified time for target fill only will get modified,
 *          symbolic file modified time will be remain same.
 *     If we edit the file using symbolic link, then modified time for target will be get changed but not symbolic file.
 *     Difference:
 *       lstat() - if pathname is a symbolic link, then it returns information about the link itself,
 *                     not the file (target) that it refers to.
 *       stat()  - if pathname is a symbolic link, then it returns information about the target file that it refers to.
 */

void hline(char ch)
{
    int i;

    for (i = 0; i < 80; printf("%c", ch), i++);
    printf("\n");

    return;
}

void stat_display(struct stat *sb, char *method)
{
    if (!sb || !method) {
        printf("Error stat details is NULL \n");
        return;
    }

    hline('*');
    printf("\n\t Retrieve the file stat details using %s API\n", method);
    printf("\n\t ------------------------------------------------\n");
    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));
    hline('*');


}

int main(int argc, char *argv[])
{
    struct stat sb = {0};

    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);
    }

    stat_display(&sb, "stat");
    memset(&sb, 0, sizeof(struct stat));
    if (lstat(argv[1], &sb) == -1) {
        perror("stat");
        exit(EXIT_FAILURE);
    }
    stat_display(&sb, "lstat");



   exit(EXIT_SUCCESS);
}

 

Output:

 labuser@labuser-virtual-machine:~/velrajk/sample$ touch ../temp/new_s
labuser@labuser-virtual-machine:~/velrajk/sample$ ./a.out ../temp/new_s
********************************************************************************

         Retrieve the file stat details using stat API

         ------------------------------------------------
File type:                regular file
I-node number:            1887181
Mode:                     100664 (octal)
Link count:               1
Ownership:                UID=1000   GID=1000
Preferred I/O block size: 4096 bytes
File size:                11 bytes
Blocks allocated:         8
Last status change:       Fri Jun  7 12:05:50 2019
Last file access:         Fri Jun  7 12:05:50 2019
Last file modification:   Fri Jun  7 12:05:50 2019
********************************************************************************
********************************************************************************

         Retrieve the file stat details using lstat API

         ------------------------------------------------
File type:                symlink
I-node number:            1963069
Mode:                     120777 (octal)
Link count:               1
Ownership:                UID=1000   GID=1000
Preferred I/O block size: 4096 bytes
File size:                3 bytes
Blocks allocated:         0
Last status change:       Thu Jun  6 19:45:36 2019
Last file access:         Thu Jun  6 19:45:38 2019
Last file modification:   Thu Jun  6 19:45:36 2019
********************************************************************************
labuser@labuser-virtual-machine:~/velrajk/sample$
labuser@labuser-virtual-machine:~/velrajk/sample$
labuser@labuser-virtual-machine:~/velrajk/sample$
labuser@labuser-virtual-machine:~/velrajk/sample$ date
Fri Jun  7 12:06:05 IST 2019
labuser@labuser-virtual-machine:~/velrajk/sample$

No comments:

Post a Comment