The stat system call is very useful in knowing the information about the file. The information such as file last access time (read and write), created time, file mode, permissions, file type, file size etc are provided by the stat system call. These are all stored in the struct stat
data structure. This we need to pass when calling the stat().
The stat
looks like below:
int stat(const char *path, struct stat *s);
include the following header files when using this system call.
<sys/stat.h>
<sys/types.h>
<unistd.h>
stat returns 0 on success. So we should only access the structure returned in the stat call if it returns 0.
The stat data structure would look as the following.
struct stat {
dev_t st_dev; // id of the device
ino_t st_ino; // inode number
mode_t st_mode; // protection
nlink_t st_nlink; // number of hardlinks
uid_t st_uid; // user id of the owner
gid_t st_gid; // group id of the 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 io
blkcnt_t st_blocks; // number of 512B blocks allocated
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
#define st_mtime st_mtim.tv_sec
#define st_ctime st_ctim.tv_sec
};
stat data structure taken from the manual page of stat system call
The most common usage of stat
is to know if the given file is a regular file or directory.
char *path = "/home/dev/work/test.c"
struct stat s;
if (stat(path, s) < 0) {
fprintf(stderr, "failed to stat %s\n", s);
perror("stat:");
return -1;
}
if (s.st_mode & S_IFREG) {
fprintf(stderr, "regular file\n");
} else {
fprintf(stderr, "unknown or un-tested file type\n");
}
Example: basic stat example
Another usage is that the file size without reading the file and counting the number of bytes.
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
int main(int argc, char **argv)
{
int ret;
struct stat s;
if (argc != 2) {
printf("%s [file name]\n", argv[0]);
return -1;
}
ret = stat(argv[1], &s);
if (ret) {
printf("failed to stat: %s\n", strerror(errno));
return -1;
}
printf("file %s size %ld\n", argv[1], s.st_size);
return 0;
}
The st_atime
is changed by file accesses, for ex: read
calls.
The st_mtime
is changed by file modifications, for ex: write
calls.
The st_ctime
is changed by writing or by setting inode, for ex: permissions, mode etc.
The below example provides the file's last access time, modification times etc.
#include <stdio.h>
#include <errno.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
int main(int argc, char **argv)
{
struct stat s;
int ret;
if (argc != 2) {
printf("%s [filename] \n", argv[0]);
return -1;
}
ret = stat(argv[1], &s);
if (ret) {
printf("failed to stat %s\n", strerror(errno));
return -1;
}
printf("last accessed: %ld, last modified: %ld, last status changed: %ld\n",
s.st_atime,
s.st_mtime,
s.st_ctime);
return 0;
}
The stat
system call is often used in conjunction with the readdir
system call, to find if the path contains a file or a directory.