Background:
On CentOS 7 x86_64. I am using applydeltarpm
, and was running out of disk space when creating the new RPM from the delta. I watched the /
disk space usage increase during the apply process to 100%, but could not find the working/temp file on the volume using either ls -l /tmp
or find /tmp -mmin -1 -type f
.
I changed the applydeltarpm
source code to use /var/tmp
instead of /tmp
, and rebuilt the RPM. Now apply works with the modified applydeltarpm
, because /var/tmp
has a lot more disk space. But I still cannot find the temp file created with mkstemp64
.
Question:
The temp file created by mkstemp64
appears to be "non-existent", but still exists as a file descriptor to the creator, and is using considerable disk space when applydeltarpm
creates a large RPM (1 hour to apply on a slow disk). The mkstemp64
documentation says an actual file is created. And the source code shows the template file name is /tmp/deltarpmpageXXXXXX
. But a file with that template name does not exist.
How is this temporary file able to be created on the system without being findable with the usual directory listing ls
, or find
. And how can I find these kinds of "non-existent" files in the system?
(I am curious, because I also am monitoring system security)
References:
https://github.com/rpm-software-management/deltarpm/blob/master/applydeltarpm.c
# line 198
if (pagefd < 0)
{
char tmpname[80];
sprintf(tmpname, "/tmp/deltarpmpageXXXXXX");
#ifdef DELTARPM_64BIT
pagefd = mkstemp64(tmpname);
#else
pagefd = mkstemp(tmpname);
#endif
if (pagefd < 0)
{
fprintf(stderr, "could not create page area\n");
exit(1);
}
unlink(tmpname);
}
https://www.mkssoftware.com/docs/man3/mkstemp.3.asp
The mktemp() function returns a unique file name based on the template parameter. At the time it is generated, no file in the current directory has that name. No file is actually created, so it is possible that another application could create a file with this name.
The mkstemp() function is similar to mktemp() in that it create a unique file name based on template; however, mkstemp() actually creates the file and returns its file descriptor. The name of the created file is stored in template.
The mkstemp64() function is identical to the mkstemp() function except that the file is opened with the O_LARGEFILE flag set.
It is a common practice to unlink the temporary file right after creation, if it's not needed to be accessed through a filesystem anymore. This avoids dangling temporary files if the process crashes or forgets to unlink it later.
unlink()
does not delete the file, it only removes the link to the file from the filesystem. Every link to a file in a filesystem increases the link count of the file by one (there can be several links to the same file). Also every process, that calls open()
or mmap()
to open the file, increases the file count, until it closes the descriptor - then the link count is decreased. File exists as long as there is at least one link to it. When link count reaches zero, then the file is actually deleted.
mkstemp()
also calls open()
behind the scenes to open the temporary file and return its descriptor.
In order to see the files that are opened, but do not exist in the filesystem anymore, you can use lsof and search for the lines, where there is "(deleted)" after the file name.
lsof | grep '(deleted)'
The (disk)space used by these files will be freed, when the processes they are attached to are finished or close the file descriptor by themselves.