Search code examples
clinuxfilestat

Finding the size of a file from stdin gives incorrect number


I am reading a file name off the standard input and the function returns something that is completely wrong. The code below returns 4294967296 rather than what should be 7. I am running the file like this on linux:

echo "p3test.txt" | ./totalsize

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <errno.h>

//find the file size
off_t filesize(const char* fileName){
    printf("%s", fileName);

    struct stat st;
    if(stat(fileName, &st) == 0)
        printf("%zd", st.st_size);
        return st.st_size;


    fprintf(stderr, "Cannot determine size of %s: %s\n",
        fileName, strerror(errno));

    return -1;

}

int main (int argc, char *argv[])
{
    char tmpstring[1024];
    const char* fileName;
    off_t size;

    while (fgets(tmpstring, 1024, stdin)) 
  {
    fileName = tmpstring;
    size = filesize(fileName);
  }
}

Solution

  • When you use:

    while (fgets(tmpstring, 1024, stdin)) 
    

    you get the '\n' in tmpstring. Trim that character from the name before calling filesize.

    Also, the lines

    if(stat(fileName, &st) == 0)
        printf("%zd", st.st_size);
        return st.st_size;
    

    should be:

    if(stat(fileName, &st) == 0)
    {
        printf("%zd", st.st_size);
        return st.st_size;
    }
    

    Otherwise, the if statement terminates at the printf line and you end up returning st.st_size regardless of the return value of stat.

    Update

    Thanks to @chux for the suggestion. The format "%zd" might not be appropriate for the type used for stat.st_size. You should use:

        printf("%jd", (intmax_t)st.st_size);