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()
.