Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practices for determining binary regular file size in POSIX compliant C program

Tags:

c

posix

I need to determine the file size in bytes of binary regular files under POSIX. I'm aware of how to use this with lseek() and fstat():

#include <sys/stat.h> // for open() and fstat()
#include <fcntl.h>    // for O_RDONLY
#include <unistd.h>   // for lseek()

int fd = open("something.bin", O_RDONLY);
if (fd == -1)
{
    perror("Unable to open file to read");
    return EXIT_FAILURE;
}

// Using lseek()
const off_t size = lseek(fd, 0, SEEK_END);
if (size == (off_t) -1)
{
    perror("Unable to determine input file size");
    return EXIT_FAILURE;
}
// Don't forget to rewind
if (lseek(fd, 0, SEEK_SET) != 0)
{
    perror("Unable to seek to beginning of input file");
    return EXIT_FAILURE;
}
...

// Using fstat()
struct stat file_stat;
int rc = fstat(fd, &file_stat);
if (rc != 0 || S_ISREG(file_stat.st_mod) == 0)
{
    perror("fstat failed or file is not a regular file");
    return EXIT_FAILURE;
}
const off_t size = file_stat.st_size;

Why would I prefer one solution over the other?

Does one approach do more (and perhaps unnecessary) than the other?

Are there other POSIX compliant or standard C solutions that should be preferred?

like image 825
Luke Peterson Avatar asked Sep 11 '25 13:09

Luke Peterson


1 Answers

Normally stat(), fstat() will read the metadata of the file to retrieve the file properties for the user. Mechanism to store metadata of files may vary from file system to file system but in general designed to give optimum speed/time complexity.

'file size' is one of the file properties stored in metadata and is updated at various file operations (e.g. write/append etc). Further fstat() doesn't require you to 'open()' the file.

On the other hand, Every 'open()' and 'lseek()' operations together could involve disk activity if the file is not present in the page cache of the operating system and could be exponentially more expensive.

Therefore I would recommend fstat().

like image 83
Nitin Avatar answered Sep 13 '25 04:09

Nitin