LinuxQuestions.org
Visit Jeremy's Blog.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 01-15-2012, 03:32 AM   #1
hydraMax
Member
 
Registered: Jul 2010
Location: Skynet
Distribution: Debian + Emacs
Posts: 467
Blog Entries: 60

Rep: Reputation: 51
oh unix temp directory, where art thou?


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

Last edited by hydraMax; 01-15-2012 at 03:37 AM.
 
Old 01-15-2012, 04:50 AM   #2
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
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).
 
Old 01-15-2012, 05:23 AM   #3
jschiwal
LQ Guru
 
Registered: Aug 2001
Location: Fargo, ND
Distribution: SuSE AMD64
Posts: 15,733

Rep: Reputation: 682Reputation: 682Reputation: 682Reputation: 682Reputation: 682Reputation: 682
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?
 
Old 01-15-2012, 11:45 AM   #4
hydraMax
Member
 
Registered: Jul 2010
Location: Skynet
Distribution: Debian + Emacs
Posts: 467

Original Poster
Blog Entries: 60

Rep: Reputation: 51
Quote:
Originally Posted by Nominal Animal View Post
TMPDIR should be considered an override. All Linux systems I've ever seen use /tmp and /var/tmp .
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)
 
Old 01-15-2012, 12:06 PM   #5
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Debian
Posts: 8,578
Blog Entries: 31

Rep: Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208
They are in http://tldp.org/LDP/Linux-Filesystem...tml/index.html
 
Old 01-15-2012, 10:24 PM   #6
jschiwal
LQ Guru
 
Registered: Aug 2001
Location: Fargo, ND
Distribution: SuSE AMD64
Posts: 15,733

Rep: Reputation: 682Reputation: 682Reputation: 682Reputation: 682Reputation: 682Reputation: 682
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.
 
Old 01-16-2012, 02:06 AM   #7
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
Quote:
Originally Posted by hydraMax View Post
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.)
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
where art thou Linux keithblahblahblah Linux - Newbie 11 01-07-2010 04:04 PM
LXer: Netflix Where Art Thou? LXer Syndicated Linux News 0 05-26-2009 05:00 PM
Oh Brother (2040), where art thou? BCarey Linux - Hardware 2 05-16-2006 10:21 AM
oh kernal, where art thou? ccflashback Linux - General 4 11-20-2004 11:02 AM
Oh Linux, Where Art Thou? aaronluke General 7 11-09-2002 06:48 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 06:09 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration