Back to index

cell-binutils  2.17cvs20070401
make-temp-file.c
Go to the documentation of this file.
00001 /* Utility to pick a temporary filename prefix.
00002    Copyright (C) 1996, 1997, 1998, 2001 Free Software Foundation, Inc.
00003 
00004 This file is part of the libiberty library.
00005 Libiberty is free software; you can redistribute it and/or
00006 modify it under the terms of the GNU Library General Public
00007 License as published by the Free Software Foundation; either
00008 version 2 of the License, or (at your option) any later version.
00009 
00010 Libiberty is distributed in the hope that it will be useful,
00011 but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 Library General Public License for more details.
00014 
00015 You should have received a copy of the GNU Library General Public
00016 License along with libiberty; see the file COPYING.LIB.  If not,
00017 write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
00018 Boston, MA 02110-1301, USA.  */
00019 
00020 #ifdef HAVE_CONFIG_H
00021 #include "config.h"
00022 #endif
00023 
00024 #include <stdio.h>   /* May get P_tmpdir.  */
00025 #include <sys/types.h>
00026 #ifdef HAVE_UNISTD_H
00027 #include <unistd.h>
00028 #endif
00029 #ifdef HAVE_STDLIB_H
00030 #include <stdlib.h>
00031 #endif
00032 #ifdef HAVE_STRING_H
00033 #include <string.h>
00034 #endif
00035 #ifdef HAVE_SYS_FILE_H
00036 #include <sys/file.h>   /* May get R_OK, etc. on some systems.  */
00037 #endif
00038 
00039 #ifndef R_OK
00040 #define R_OK 4
00041 #define W_OK 2
00042 #define X_OK 1
00043 #endif
00044 
00045 #include "libiberty.h"
00046 extern int mkstemps (char *, int);
00047 
00048 /* '/' works just fine on MS-DOS based systems.  */
00049 #ifndef DIR_SEPARATOR
00050 #define DIR_SEPARATOR '/'
00051 #endif
00052 
00053 /* Name of temporary file.
00054    mktemp requires 6 trailing X's.  */
00055 #define TEMP_FILE "ccXXXXXX"
00056 #define TEMP_FILE_LEN (sizeof(TEMP_FILE) - 1)
00057 
00058 /* Subroutine of choose_tmpdir.
00059    If BASE is non-NULL, return it.
00060    Otherwise it checks if DIR is a usable directory.
00061    If success, DIR is returned.
00062    Otherwise NULL is returned.  */
00063 
00064 static inline const char *try_dir (const char *, const char *);
00065 
00066 static inline const char *
00067 try_dir (const char *dir, const char *base)
00068 {
00069   if (base != 0)
00070     return base;
00071   if (dir != 0
00072       && access (dir, R_OK | W_OK | X_OK) == 0)
00073     return dir;
00074   return 0;
00075 }
00076 
00077 static const char tmp[] = { DIR_SEPARATOR, 't', 'm', 'p', 0 };
00078 static const char usrtmp[] =
00079 { DIR_SEPARATOR, 'u', 's', 'r', DIR_SEPARATOR, 't', 'm', 'p', 0 };
00080 static const char vartmp[] =
00081 { DIR_SEPARATOR, 'v', 'a', 'r', DIR_SEPARATOR, 't', 'm', 'p', 0 };
00082 
00083 static char *memoized_tmpdir;
00084 
00085 /*
00086 
00087 @deftypefn Replacement char* choose_tmpdir ()
00088 
00089 Returns a pointer to a directory path suitable for creating temporary
00090 files in.
00091 
00092 @end deftypefn
00093 
00094 */
00095 
00096 char *
00097 choose_tmpdir (void)
00098 {
00099   const char *base = 0;
00100   char *tmpdir;
00101   unsigned int len;
00102 
00103   if (memoized_tmpdir)
00104     return memoized_tmpdir;
00105 
00106   base = try_dir (getenv ("TMPDIR"), base);
00107   base = try_dir (getenv ("TMP"), base);
00108   base = try_dir (getenv ("TEMP"), base);
00109 
00110 #ifdef P_tmpdir
00111   base = try_dir (P_tmpdir, base);
00112 #endif
00113 
00114   /* Try /var/tmp, /usr/tmp, then /tmp.  */
00115   base = try_dir (vartmp, base);
00116   base = try_dir (usrtmp, base);
00117   base = try_dir (tmp, base);
00118  
00119   /* If all else fails, use the current directory!  */
00120   if (base == 0)
00121     base = ".";
00122 
00123   /* Append DIR_SEPARATOR to the directory we've chosen
00124      and return it.  */
00125   len = strlen (base);
00126   tmpdir = XNEWVEC (char, len + 2);
00127   strcpy (tmpdir, base);
00128   tmpdir[len] = DIR_SEPARATOR;
00129   tmpdir[len+1] = '\0';
00130 
00131   memoized_tmpdir = tmpdir;
00132   return tmpdir;
00133 }
00134 
00135 /*
00136 
00137 @deftypefn Replacement char* make_temp_file (const char *@var{suffix})
00138 
00139 Return a temporary file name (as a string) or @code{NULL} if unable to
00140 create one.  @var{suffix} is a suffix to append to the file name.  The
00141 string is @code{malloc}ed, and the temporary file has been created.
00142 
00143 @end deftypefn
00144 
00145 */
00146 
00147 char *
00148 make_temp_file (const char *suffix)
00149 {
00150   const char *base = choose_tmpdir ();
00151   char *temp_filename;
00152   int base_len, suffix_len;
00153   int fd;
00154 
00155   if (suffix == 0)
00156     suffix = "";
00157 
00158   base_len = strlen (base);
00159   suffix_len = strlen (suffix);
00160 
00161   temp_filename = XNEWVEC (char, base_len
00162                         + TEMP_FILE_LEN
00163                         + suffix_len + 1);
00164   strcpy (temp_filename, base);
00165   strcpy (temp_filename + base_len, TEMP_FILE);
00166   strcpy (temp_filename + base_len + TEMP_FILE_LEN, suffix);
00167 
00168   fd = mkstemps (temp_filename, suffix_len);
00169   /* If mkstemps failed, then something bad is happening.  Maybe we should
00170      issue a message about a possible security attack in progress?  */
00171   if (fd == -1)
00172     abort ();
00173   /* Similarly if we can not close the file.  */
00174   if (close (fd))
00175     abort ();
00176   return temp_filename;
00177 }