1169695Skan/* Utility to pick a temporary filename prefix. 2169695Skan Copyright (C) 1996, 1997, 1998, 2001 Free Software Foundation, Inc. 3169695Skan 4169695SkanThis file is part of the libiberty library. 5169695SkanLibiberty is free software; you can redistribute it and/or 6169695Skanmodify it under the terms of the GNU Library General Public 7169695SkanLicense as published by the Free Software Foundation; either 8169695Skanversion 2 of the License, or (at your option) any later version. 9169695Skan 10169695SkanLibiberty is distributed in the hope that it will be useful, 11169695Skanbut WITHOUT ANY WARRANTY; without even the implied warranty of 12169695SkanMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13169695SkanLibrary General Public License for more details. 14169695Skan 15169695SkanYou should have received a copy of the GNU Library General Public 16169695SkanLicense along with libiberty; see the file COPYING.LIB. If not, 17169695Skanwrite to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, 18169695SkanBoston, MA 02110-1301, USA. */ 19169695Skan 20169695Skan#ifdef HAVE_CONFIG_H 21169695Skan#include "config.h" 22169695Skan#endif 23169695Skan 24169695Skan#include <stdio.h> /* May get P_tmpdir. */ 25169695Skan#include <sys/types.h> 26169695Skan#ifdef HAVE_UNISTD_H 27169695Skan#include <unistd.h> 28169695Skan#endif 29169695Skan#ifdef HAVE_STDLIB_H 30169695Skan#include <stdlib.h> 31169695Skan#endif 32169695Skan#ifdef HAVE_STRING_H 33169695Skan#include <string.h> 34169695Skan#endif 35169695Skan#ifdef HAVE_SYS_FILE_H 36169695Skan#include <sys/file.h> /* May get R_OK, etc. on some systems. */ 37169695Skan#endif 38169695Skan 39169695Skan#ifndef R_OK 40169695Skan#define R_OK 4 41169695Skan#define W_OK 2 42169695Skan#define X_OK 1 43169695Skan#endif 44169695Skan 45169695Skan#include "libiberty.h" 46169695Skanextern int mkstemps (char *, int); 47169695Skan 48169695Skan/* '/' works just fine on MS-DOS based systems. */ 49169695Skan#ifndef DIR_SEPARATOR 50169695Skan#define DIR_SEPARATOR '/' 51169695Skan#endif 52169695Skan 53169695Skan/* Name of temporary file. 54169695Skan mktemp requires 6 trailing X's. */ 55169695Skan#define TEMP_FILE "ccXXXXXX" 56169695Skan#define TEMP_FILE_LEN (sizeof(TEMP_FILE) - 1) 57169695Skan 58169695Skan/* Subroutine of choose_tmpdir. 59169695Skan If BASE is non-NULL, return it. 60169695Skan Otherwise it checks if DIR is a usable directory. 61169695Skan If success, DIR is returned. 62169695Skan Otherwise NULL is returned. */ 63169695Skan 64169695Skanstatic inline const char *try_dir (const char *, const char *); 65169695Skan 66169695Skanstatic inline const char * 67169695Skantry_dir (const char *dir, const char *base) 68169695Skan{ 69169695Skan if (base != 0) 70169695Skan return base; 71169695Skan if (dir != 0 72169695Skan && access (dir, R_OK | W_OK | X_OK) == 0) 73169695Skan return dir; 74169695Skan return 0; 75169695Skan} 76169695Skan 77169695Skanstatic const char tmp[] = { DIR_SEPARATOR, 't', 'm', 'p', 0 }; 78169695Skanstatic const char usrtmp[] = 79169695Skan{ DIR_SEPARATOR, 'u', 's', 'r', DIR_SEPARATOR, 't', 'm', 'p', 0 }; 80169695Skanstatic const char vartmp[] = 81169695Skan{ DIR_SEPARATOR, 'v', 'a', 'r', DIR_SEPARATOR, 't', 'm', 'p', 0 }; 82169695Skan 83169695Skanstatic char *memoized_tmpdir; 84169695Skan 85169695Skan/* 86169695Skan 87169695Skan@deftypefn Replacement char* choose_tmpdir () 88169695Skan 89169695SkanReturns a pointer to a directory path suitable for creating temporary 90169695Skanfiles in. 91169695Skan 92169695Skan@end deftypefn 93169695Skan 94169695Skan*/ 95169695Skan 96169695Skanchar * 97169695Skanchoose_tmpdir (void) 98169695Skan{ 99169695Skan const char *base = 0; 100169695Skan char *tmpdir; 101169695Skan unsigned int len; 102169695Skan 103169695Skan if (memoized_tmpdir) 104169695Skan return memoized_tmpdir; 105169695Skan 106169695Skan base = try_dir (getenv ("TMPDIR"), base); 107169695Skan base = try_dir (getenv ("TMP"), base); 108169695Skan base = try_dir (getenv ("TEMP"), base); 109169695Skan 110169695Skan#ifdef P_tmpdir 111169695Skan base = try_dir (P_tmpdir, base); 112169695Skan#endif 113169695Skan 114169712Skan /* Try /tmp, /var/tmp, then /usr/tmp. */ 115169712Skan base = try_dir (tmp, base); 116169695Skan base = try_dir (vartmp, base); 117169695Skan base = try_dir (usrtmp, base); 118169695Skan 119169695Skan /* If all else fails, use the current directory! */ 120169695Skan if (base == 0) 121169695Skan base = "."; 122169695Skan 123169695Skan /* Append DIR_SEPARATOR to the directory we've chosen 124169695Skan and return it. */ 125169695Skan len = strlen (base); 126169695Skan tmpdir = XNEWVEC (char, len + 2); 127169695Skan strcpy (tmpdir, base); 128169695Skan tmpdir[len] = DIR_SEPARATOR; 129169695Skan tmpdir[len+1] = '\0'; 130169695Skan 131169695Skan memoized_tmpdir = tmpdir; 132169695Skan return tmpdir; 133169695Skan} 134169695Skan 135169695Skan/* 136169695Skan 137169695Skan@deftypefn Replacement char* make_temp_file (const char *@var{suffix}) 138169695Skan 139169695SkanReturn a temporary file name (as a string) or @code{NULL} if unable to 140169695Skancreate one. @var{suffix} is a suffix to append to the file name. The 141169695Skanstring is @code{malloc}ed, and the temporary file has been created. 142169695Skan 143169695Skan@end deftypefn 144169695Skan 145169695Skan*/ 146169695Skan 147169695Skanchar * 148169695Skanmake_temp_file (const char *suffix) 149169695Skan{ 150169695Skan const char *base = choose_tmpdir (); 151169695Skan char *temp_filename; 152169695Skan int base_len, suffix_len; 153169695Skan int fd; 154169695Skan 155169695Skan if (suffix == 0) 156169695Skan suffix = ""; 157169695Skan 158169695Skan base_len = strlen (base); 159169695Skan suffix_len = strlen (suffix); 160169695Skan 161169695Skan temp_filename = XNEWVEC (char, base_len 162169695Skan + TEMP_FILE_LEN 163169695Skan + suffix_len + 1); 164169695Skan strcpy (temp_filename, base); 165169695Skan strcpy (temp_filename + base_len, TEMP_FILE); 166169695Skan strcpy (temp_filename + base_len + TEMP_FILE_LEN, suffix); 167169695Skan 168169695Skan fd = mkstemps (temp_filename, suffix_len); 169169695Skan /* If mkstemps failed, then something bad is happening. Maybe we should 170169695Skan issue a message about a possible security attack in progress? */ 171169695Skan if (fd == -1) 172169695Skan abort (); 173169695Skan /* Similarly if we can not close the file. */ 174169695Skan if (close (fd)) 175169695Skan abort (); 176169695Skan return temp_filename; 177169695Skan} 178