Home > OS >  fstat st_size says file size is 0 when unlinking file
fstat st_size says file size is 0 when unlinking file

Time:10-11

Somewhere online I've seen a technique to immediately unlink a temporary file after opening it, since you will discard it anyway. As per my understanding of the man-page for unlink, the file will not be unlinked as long as it has an open file descriptor.

When I execute the following piece of code:

char *file, *command;
asprintf(&file, "/tmp/tempXXXXXX");
int fd = mkstemp(file);
unlink(file);

asprintf(&command, "some_command > %s", file); /*Writes n bytes in temp file*/
FILE *f = popen(command, "re");
pclose(f);

struct stat sbuf;
fstat(fd, &sbuf);
printf("%i\n", sbuf.st_size);

close(fd);
free(file);
free(command);
exit(0); 

It will print a size of 0. However, if I comment unlink(file), it will show the correct file size. I would expect both scenarios to show the correct size of the file, since unlink should wait till no processes have the file open anymore. What am I missing here?

CodePudding user response:

You're missing the fact that the file referred to by your fd is not the same file as that created by your call to popen().

In a POSIX-like shell, some_command > some_file will create some_file if it does not already exist, otherwise it will truncate some_file.

Your call to popen() invokes a shell, which in turn creates or truncates the output file before invoking some_command as per POSIX.

Since you have unlinked some_file before the call to popen(), the file is created anew: that is, the output file set up by your popen() shell is allocated under a different inode than the (now anonymous) file created by your previous call to mkstemp().

You can see that the files are different if you compare st_ino values from your fstat() (by fd) and a separate call to stat() (by name) after the popen().

  • Related