tmpnam is used to return a unique temporary file string, which is normally used to create temporary file. tmpfile system call is used to create one temporary file, which will be removed when the process is terminated or the file stream is closed.
Definition:
ubuntu@ip-172-31-23-227:~$ less /usr/include/stdio.h
......
/* Generate a temporary filename. */
extern char *tmpnam (char *__s) __THROW __wur;
......
/* Create a temporary file and open it read/write.
This function is a possible cancellation point and therefore not
marked with __THROW. */
#ifndef __USE_FILE_OFFSET64
extern FILE *tmpfile (void) __wur;
......
fileio.c:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int main(int argc, char* argv[])
{
char *pn = tmpnam(NULL);
printf("pn pointer: %p file name: %s\n", pn, pn);
// Create another temporary name while giving the NULL as parameter
// It will create another temporary name at the same address(static address)
// which means it overwrites the previous name
printf("create another temporary name:\n");
pn = tmpnam(NULL);
printf("pn pointer: %p file name: %s\n", pn, pn);
// Provide one buffer address to tmpnam, and tmpnam will populate the name
// to this buffer place.
// The buffer length is at least "L_tmpnam", which is defined at stdio.h
// tmpnam function is called at most TMP_MAX times, which is defined at stdio.h
char tn[L_tmpnam];
tmpnam(tn);
printf("tn pointer: %p file name: %s\n", tn, tn);
// Create one temporary file, write "Hello world!" into it
// Rewind to the beginning of the file, read the line out and output to
// standard output.
FILE *fp;
if((fp = tmpfile()) == NULL) {
printf("tmpfile error!\n");
exit(1);
}
fputs("Hello world!", fp);
char line[13];
rewind(fp);
if(fgets(line, sizeof(line), fp) == NULL) {
printf("fgets error!\n");
exit(2);
}
printf("%s\n", line);
exit(0);
}
shell:
ubuntu@ip-172-31-23-227:~$ ./io.out
pn pointer: 0x7f70bf6ee930 file name: /tmp/filecqrV8F
create another temporary name:
pn pointer: 0x7f70bf6ee930 file name: /tmp/fileCMeZ3T
tn pointer: 0x7fff91cc5e60 file name: /tmp/fileDxO3Y7
Hello world!
2. tempnam
tempnam is a variation of tmpnam system call. It provides another way to generate one unique temporary name.
Definition:
ubuntu@ip-172-31-23-227:~$ less /usr/include/stdio.h
......
/* Default path prefix for `tempnam' and `tmpnam'. */
# define P_tmpdir "/tmp"
......
/* Generate a unique temporary filename using up to five characters of PFX
if it is not NULL. The directory to put this file in is searched for
as follows: First the environment variable "TMPDIR" is checked.
If it contains the name of a writable directory, that directory is used.
If not and if DIR is not NULL, that value is checked. If that fails,
P_tmpdir is tried and finally "/tmp". The storage for the filename
is allocated by `malloc'. */
extern char *tempnam (const char *__dir, const char *__pfx)
__THROW __attribute_malloc__ __wur;
.....
fileio.c:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int main(int argc, char* argv[])
{
char *pn;
// tempnam is using malloc to return the unique temporary name string, so we have to
// free that part of memory to avoid memory leak
// The order of file path determination:
// 1. If TMPDIR envrionment variable is set, then use that value as directory name
// 2. if first argument is not NULL, use that value as directory name
// 3. If P_tmpdir is set, then use that value as directory name
// 4. Lastly if all above conditions are not met, use /tmp
// If second argument is not NULL, provide at most 5 bytes as the prefix of name
pn = tempnam(argv[1][0] != ' ' ? argv[1]:NULL, argv[2][0] != ' '?argv[2]: NULL);
printf("%s\n", pn);
free(pn);
exit(0);
}
shell:
1) Although we provide 8 'X' as prefix, but, only first 5 bytes are used
2) We provide one non-exist place for path name, it will detect that this place doesn't exist, then fall to step 3, use P_tmpdir as path name, which is "/tmp" in current system.
3) We provide NULL to the path name argument, and then system will fall to step 3 to use P_tmpdir as pathname
4) Setup TMPDIR, it will then use TMPDIR value "/dev" as the pathname.
5) Setup TMPDIR to a non-exist place, and also self-provided argument is NULL, so it will fall to step 3 to use P_tmpdir as the path name.
ubuntu@ip-172-31-23-227:~$ ./io.out /bin XXXXXXXX
/bin/XXXXX2QQ1qE
ubuntu@ip-172-31-23-227:~$ ./io.out /bin/noexist XXXXX
/tmp/XXXXXeRnepO
ubuntu@ip-172-31-23-227:~$ ./io.out " " XXXXX
/tmp/XXXXXMfsRxs
ubuntu@ip-172-31-23-227:~$ TMPDIR=/dev ./io.out /bin XXXXX
/dev/XXXXXWO5xwQ
ubuntu@ip-172-31-23-227:~$ TMPDIR=/noexist ./io.out " " XXXXX
/tmp/XXXXXogD6BK
3. mkstemp
mkstemp is another way to create temporary file with given template path name string.
definition:
ubuntu@ip-172-31-23-227:~$ less /usr/include/stdlib.h
......
/* Generate a unique temporary file name from TEMPLATE.
The last six characters of TEMPLATE must be "XXXXXX";
they are replaced with a string that makes the filename unique.
Returns a file descriptor open on the file for reading and writing,
or -1 if it cannot create a uniquely-named file.
This function is a possible cancellation point and therefore not
marked with __THROW. */
# ifndef __USE_FILE_OFFSET64
extern int mkstemp (char *__template) __nonnull ((1)) __wur;
......
fileio.c:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
int main(int argc, char* argv[])
{
char pn[10];
int fd;
// provided template string's last 6 characters have to be "XXXXXX"
// mkstemp will change last 6 characters to make the string unique
strcpy(pn, "TMPXXXXXX");
if((fd = mkstemp(pn)) == -1) {
printf("mkstemp error!\n");
exit(1);
}
printf("pn will be changed to: %s\n", pn);
close(fd);
// The temporary file created by mkstemp will not be removed
// We have to unlink it by ourselves
unlink(pn);
exit(0);
}
shell:
ubuntu@ip-172-31-23-227:~$ ./io.out
pn will be changed to: TMPZnhreZ
Note:
If we use tmpnam or tempnam to create temporary file string, and then use that string to create temporary file manually, there is a small time window between, during which other process may create the temp file with same name. In practice, we normally use tmpfile and mkstemp to create temp file directly.
No comments:
Post a Comment