OSDN Git Service

Warning fixes:
[pf3gnuchains/gcc-fork.git] / libiberty / choose-temp.c
1 /* Utility to pick a temporary filename prefix.
2    Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
3
4 This file is part of the libiberty library.
5 Libiberty is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 Libiberty is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with libiberty; see the file COPYING.LIB.  If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.  */
19
20 /* This file exports two functions: choose_temp_base and make_temp_file.  */
21
22 /* This file lives in at least two places: libiberty and gcc.
23    Don't change one without the other.  */
24
25 #if defined (IN_GCC) || defined (HAVE_CONFIG_H)
26 #include "config.h"
27 #endif
28
29 #ifdef IN_GCC
30 #include "system.h"
31 #else
32
33 /* If we are in gcc, system.h has handled everything.  When not in
34    gcc, if we have a config.h we assume that HAVE_SYS_FILE_H tells us
35    whether to include sys/file.h.  However, libiberty does not have a
36    config.h, and instead arranges to define NO_SYS_FILE_H on the
37    command line when there is no sys/file.h.  */
38
39 #if defined (HAVE_CONFIG_H) ? defined (HAVE_SYS_FILE_H) : ! defined (NO_SYS_FILE_H)
40 #include <sys/types.h>
41 #include <sys/file.h>   /* May get R_OK, etc. on some systems.  */
42 #endif
43
44 #ifndef R_OK
45 #define R_OK 4
46 #define W_OK 2
47 #define X_OK 1
48 #endif
49
50 #include <stdio.h>      /* May get P_tmpdir.  */
51 #endif /* IN_GCC */
52
53 #ifdef IN_GCC
54 #include "gansidecl.h"
55 extern char *xmalloc ();
56 extern int mkstemps ();
57 #else
58 #include "ansidecl.h"
59 #include "libiberty.h"
60 #if defined (__MSDOS__) || defined (_WIN32)
61 #define DIR_SEPARATOR '\\'
62 #endif
63 #endif
64
65 #ifndef DIR_SEPARATOR
66 #define DIR_SEPARATOR '/'
67 #endif
68
69 /* On MSDOS, write temp files in current dir
70    because there's no place else we can expect to use.  */
71 /* ??? Although the current directory is tried as a last resort,
72    this is left in so that on MSDOS it is preferred to /tmp on the
73    off chance that someone requires this, since that was the previous
74    behaviour.  */
75 #ifdef __MSDOS__
76 #ifndef P_tmpdir
77 #define P_tmpdir "."
78 #endif
79 #endif
80
81 /* Name of temporary file.
82    mktemp requires 6 trailing X's.  */
83 #define TEMP_FILE "ccXXXXXX"
84
85 /* Subroutine of choose_temp_base.
86    If BASE is non-NULL, return it.
87    Otherwise it checks if DIR is a usable directory.
88    If success, DIR is returned.
89    Otherwise NULL is returned.  */
90
91 static char *
92 try (dir, base)
93      char *dir, *base;
94 {
95   if (base != 0)
96     return base;
97   if (dir != 0
98       && access (dir, R_OK | W_OK | X_OK) == 0)
99     return dir;
100   return 0;
101 }
102
103 /* Return a prefix for temporary file names or NULL if unable to find one.
104    The current directory is chosen if all else fails so the program is
105    exited if a temporary directory can't be found (mktemp fails).
106    The buffer for the result is obtained with xmalloc. 
107
108    This function is provided for backwards compatability only.  It use
109    is not recommended.  */
110
111 char *
112 choose_temp_base ()
113 {
114   char *base = 0;
115   char *temp_filename;
116   int len;
117   static char tmp[] = { DIR_SEPARATOR, 't', 'm', 'p', 0 };
118   static char usrtmp[] = { DIR_SEPARATOR, 'u', 's', 'r', DIR_SEPARATOR, 't', 'm', 'p', 0 };
119
120   base = try (getenv ("TMPDIR"), base);
121   base = try (getenv ("TMP"), base);
122   base = try (getenv ("TEMP"), base);
123
124 #ifdef P_tmpdir
125   base = try (P_tmpdir, base);
126 #endif
127
128   /* Try /usr/tmp, then /tmp.  */
129   base = try (usrtmp, base);
130   base = try (tmp, base);
131  
132   /* If all else fails, use the current directory!  */
133   if (base == 0)
134     base = ".";
135
136   len = strlen (base);
137   temp_filename = xmalloc (len + 1 /*DIR_SEPARATOR*/
138                            + strlen (TEMP_FILE) + 1);
139   strcpy (temp_filename, base);
140
141   if (len != 0
142       && temp_filename[len-1] != '/'
143       && temp_filename[len-1] != DIR_SEPARATOR)
144     temp_filename[len++] = DIR_SEPARATOR;
145   strcpy (temp_filename + len, TEMP_FILE);
146
147   mktemp (temp_filename);
148   if (strlen (temp_filename) == 0)
149     abort ();
150   return temp_filename;
151 }
152 /* Return a temporary file name (as a string) or NULL if unable to create
153    one.  */
154
155 char *
156 make_temp_file (suffix)
157      char *suffix;
158 {
159   char *base = 0;
160   char *temp_filename;
161   int base_len, suffix_len;
162   int fd;
163   static char tmp[] = { DIR_SEPARATOR, 't', 'm', 'p', 0 };
164   static char usrtmp[] = { DIR_SEPARATOR, 'u', 's', 'r', DIR_SEPARATOR, 't', 'm', 'p', 0 };
165
166   base = try (getenv ("TMPDIR"), base);
167   base = try (getenv ("TMP"), base);
168   base = try (getenv ("TEMP"), base);
169
170 #ifdef P_tmpdir
171   base = try (P_tmpdir, base);
172 #endif
173
174   /* Try /usr/tmp, then /tmp.  */
175   base = try (usrtmp, base);
176   base = try (tmp, base);
177  
178   /* If all else fails, use the current directory!  */
179   if (base == 0)
180     base = ".";
181
182   base_len = strlen (base);
183
184   if (suffix)
185     suffix_len = strlen (suffix);
186   else
187     suffix_len = 0;
188
189   temp_filename = xmalloc (base_len + 1 /*DIR_SEPARATOR*/
190                            + strlen (TEMP_FILE)
191                            + suffix_len + 1);
192   strcpy (temp_filename, base);
193
194   if (base_len != 0
195       && temp_filename[base_len-1] != '/'
196       && temp_filename[base_len-1] != DIR_SEPARATOR)
197     temp_filename[base_len++] = DIR_SEPARATOR;
198   strcpy (temp_filename + base_len, TEMP_FILE);
199
200   if (suffix)
201     strcat (temp_filename, suffix);
202
203   fd = mkstemps (temp_filename, suffix_len);
204   /* If mkstemps failed, then something bad is happening.  Maybe we should
205      issue a message about a possible security attack in progress?  */
206   if (fd == -1)
207     abort ();
208   /* Similarly if we can not close the file.  */
209   if (close (fd))
210     abort ();
211   return temp_filename;
212 }