ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I was wondering about something -- curious if anyone had any insight (historical or otherwise): I'm writing a small C program that needs temporary work directories (presumably created with mkdtemp) so of course it needs to know the location of the temp directory. I had presumed that this would be stored in the TMPDIR environment variable, as I had read in some C document that this was what that variable was for; but I was surprised to find that TMPDIR isn't even set on my Linux distro!
So, after some research I discovered that there was a P_tmpdir definition in <stdio.h>:
Code:
#if defined __USE_SVID || defined __USE_XOPEN
/* Default path prefix for `tempnam' and `tmpnam'. */
# define P_tmpdir "/tmp"
#endif
It was interesting though, that if I target the C99 standard (gcc -std=c99) as is my normal preference, then this macro is not defined. But it is defined if I target the default gnu dialect (gnu90), or gnu99.
So anyway, I was curious if anyone has any thoughts on the subject of portably locating the temp directory.
EDIT: Interestingly enough, on my openBSD system, the <stdio.h> also includes a P_tmpdir definition, but states:
Code:
/* System V/ANSI C; this is the wrong way to do this, do *not* use these. */
#if __BSD_VISIBLE || __XPG_VISIBLE
#define P_tmpdir "/tmp/"
#endif
TMPDIR should be considered an override. All Linux systems I've ever seen use /tmp and /var/tmp .
If I were you, I'd set the default at compile time (/tmp for utilities, /var/tmp for daemons and services), but let the user override it using the TMPDIR environment variable.
(In some cases, for example when you have very large files, it is useful to put the temporary directory on the same filesystem as the target files. Replacing the target files with the temporary files is then just a hard link operation; no data needs to be copied.)
Here is a helper function you might find useful:
Code:
#include <stdlib.h>
#include <string.h>
#include <errno.h>
/* Compile-time constant, defaults to option -DTMPDIR=/tmp */
#ifndef TMPDIR
#define TMPDIR "/tmp"
#endif
/* Return a dynamically allocated string.
* The string will always start with the temporary directory;
* a slash is always appended to a non-empty directory string.
* If non-NULL, the suffix will be appended to that.
* The allocation is sized so that the string will always have
* at least one end-of-string byte, and room for 'extra'
* additional characters.
* If successful, the function will return a pointer to the
* string, and keep errno unchanged. Otherwise the function
* will return NULL (with errno most likely ENOMEM).
*/
char *temporary(const char *const suffix, const size_t extra)
{
const size_t suffix_len = (suffix) ? strlen(suffix) : 0;
size_t chars, prefix_len = 0;
const char *prefix;
char *string, *s;
int saved_errno;
saved_errno = errno;
prefix = getenv("TMPDIR");
if (!prefix)
prefix = TMPDIR;
if (prefix)
prefix_len = strlen(prefix);
chars = prefix_len + 1 + suffix_len + extra + 1;
string = malloc(chars);
if (!string) {
errno = ENOMEM;
return NULL;
}
memset(string + prefix_len + suffix_len, 0, 2 + extra);
s = string;
if (prefix_len > (size_t)0) {
memcpy(s, prefix, prefix_len);
s += prefix_len;
if (s[-1] != '/')
*(s++) = '/';
}
if (suffix_len > (size_t)0) {
memcpy(s, suffix, suffix_len);
s += suffix_len;
}
/* We already set the EOS using the memset() above. */
errno = saved_errno;
return string;
}
When creating a temp dir name for mkdtemp(), you could use temporary("myprog-XXXXXX",17) for example; you can reuse the same string for temporary file names under that directory ('/' + 16 chars, so for file names up to 16 bytes long).
The man page for tmpnam() says the directory part is the P_tmpdir value. My system does have TMPDIR defined and bash uses it. I don't know if it it is intended for the shell to use. Could you have miss configured /etc/profile on your system?
Perhaps check the posix man page for tmpnam().
On page 141 of Advanced Programming in the UNIX Environment, there are 4 options for the tempnam() directory; the first one to be true is used:
1) If TMPDIR is not NULL, it is used as the directory.
2) If directory is not NULL, it is used.
3) The string P_tmpdir in <stdio.h> is used.
4) A local directory, usually /tmp is used.
On page 140, it says it is common to use tmpnam(), create the file, and immediatly unlink it. This guarantees the file is deleted after the program is terminated.
But is that something you can count upon across all *nixes? Is the location of /var/tmp and /tmp part of some defined *nix standard? (e.g., POSIX)
It is standardized in FHS, inherited from BSD's. So yes, this is something you can count upon on all Unix, Linux, and *BSD systems.
You should not count on /tmp being emptied on reboot, and /var/tmp not being emptied on reboot, though. If you need state to be preserved over reboots, use /var/lib/service like FHS recommends. If you use temporary files, it is always recommended to create a temporary directory and put your temporary files under that one. That way you can just delete the entire directory (using rm -rf or equivalent). (It is okay to not delete the directory if a fatal error occurs mid-way through; the temporary files may help the user to diagnose the problems. System utilities, for example, behave exactly this way.)
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.