source: rtems-tools/rtemstoolkit/libiberty/make-temp-file.c @ 87e0e76

4.104.115
Last change on this file since 87e0e76 was 87e0e76, checked in by Chris Johns <chrisj@…>, on 09/13/14 at 02:09:16

Refactor code into the RTEMS Toolkit.

  • Property mode set to 100644
File size: 5.5 KB
Line 
1/* Utility to pick a temporary filename prefix.
2   Copyright (C) 1996, 1997, 1998, 2001, 2009, 2010
3   Free Software Foundation, Inc.
4
5This file is part of the libiberty library.
6Libiberty is free software; you can redistribute it and/or
7modify it under the terms of the GNU Library General Public
8License as published by the Free Software Foundation; either
9version 2 of the License, or (at your option) any later version.
10
11Libiberty is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14Library General Public License for more details.
15
16You should have received a copy of the GNU Library General Public
17License along with libiberty; see the file COPYING.LIB.  If not,
18write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
19Boston, MA 02110-1301, USA.  */
20
21#ifdef HAVE_CONFIG_H
22#include "config.h"
23#endif
24
25#include <stdio.h>      /* May get P_tmpdir.  */
26#include <sys/types.h>
27#include <errno.h>
28#ifdef HAVE_UNISTD_H
29#include <unistd.h>
30#endif
31#ifdef HAVE_STDLIB_H
32#include <stdlib.h>
33#endif
34#ifdef HAVE_STRING_H
35#include <string.h>
36#endif
37#ifdef HAVE_SYS_FILE_H
38#include <sys/file.h>   /* May get R_OK, etc. on some systems.  */
39#endif
40#if defined(_WIN32) && !defined(__CYGWIN__)
41#include <windows.h>
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 "libiberty.h"
51extern int mkstemps (char *, int);
52
53/* '/' works just fine on MS-DOS based systems.  */
54#ifndef DIR_SEPARATOR
55#define DIR_SEPARATOR '/'
56#endif
57
58/* Name of temporary file.
59   mktemp requires 6 trailing X's.  */
60#define TEMP_FILE "rld--XXXXXX"
61#define TEMP_FILE_LEN (sizeof(TEMP_FILE) - 1)
62
63#if !defined(_WIN32) || defined(__CYGWIN__)
64
65/* Subroutine of choose_tmpdir.
66   If BASE is non-NULL, return it.
67   Otherwise it checks if DIR is a usable directory.
68   If success, DIR is returned.
69   Otherwise NULL is returned.  */
70
71static inline const char *try_dir (const char *, const char *);
72
73static inline const char *
74try_dir (const char *dir, const char *base)
75{
76  if (base != 0)
77    return base;
78  if (dir != 0
79      && access (dir, R_OK | W_OK | X_OK) == 0)
80    return dir;
81  return 0;
82}
83
84static const char tmp[] = { DIR_SEPARATOR, 't', 'm', 'p', 0 };
85static const char usrtmp[] =
86{ DIR_SEPARATOR, 'u', 's', 'r', DIR_SEPARATOR, 't', 'm', 'p', 0 };
87static const char vartmp[] =
88{ DIR_SEPARATOR, 'v', 'a', 'r', DIR_SEPARATOR, 't', 'm', 'p', 0 };
89
90#endif
91
92static char *memoized_tmpdir;
93
94/*
95
96@deftypefn Replacement char* choose_tmpdir ()
97
98Returns a pointer to a directory path suitable for creating temporary
99files in.
100
101@end deftypefn
102
103*/
104
105char *
106choose_tmpdir (void)
107{
108  if (!memoized_tmpdir)
109    {
110#if !defined(_WIN32) || defined(__CYGWIN__)
111      const char *base = 0;
112      char *tmpdir;
113      unsigned int len;
114
115#ifdef VMS
116      /* Try VMS standard temp logical.  */
117      base = try_dir ("/sys$scratch", base);
118#else
119      base = try_dir (getenv ("TMPDIR"), base);
120      base = try_dir (getenv ("TMP"), base);
121      base = try_dir (getenv ("TEMP"), base);
122#endif
123
124#ifdef P_tmpdir
125      /* We really want a directory name here as if concatenated with say \dir
126         we do not end up with a double \\ which defines an UNC path.  */
127      if (strcmp (P_tmpdir, "\\") == 0)
128        base = try_dir ("\\.", base);
129      else
130        base = try_dir (P_tmpdir, base);
131#endif
132
133      /* Try /var/tmp, /usr/tmp, then /tmp.  */
134      base = try_dir (vartmp, base);
135      base = try_dir (usrtmp, base);
136      base = try_dir (tmp, base);
137
138      /* If all else fails, use the current directory!  */
139      if (base == 0)
140        base = ".";
141      /* Append DIR_SEPARATOR to the directory we've chosen
142         and return it.  */
143      len = strlen (base);
144      tmpdir = XNEWVEC (char, len + 2);
145      strcpy (tmpdir, base);
146      tmpdir[len] = DIR_SEPARATOR;
147      tmpdir[len+1] = '\0';
148      memoized_tmpdir = tmpdir;
149#else /* defined(_WIN32) && !defined(__CYGWIN__) */
150      DWORD len;
151
152      /* Figure out how much space we need.  */
153      len = GetTempPath(0, NULL);
154      if (len)
155        {
156          memoized_tmpdir = XNEWVEC (char, len);
157          if (!GetTempPath(len, memoized_tmpdir))
158            {
159              XDELETEVEC (memoized_tmpdir);
160              memoized_tmpdir = NULL;
161            }
162        }
163      if (!memoized_tmpdir)
164        /* If all else fails, use the current directory.  */
165        memoized_tmpdir = xstrdup (".\\");
166#endif /* defined(_WIN32) && !defined(__CYGWIN__) */
167    }
168
169  return memoized_tmpdir;
170}
171
172/*
173
174@deftypefn Replacement char* make_temp_file (const char *@var{suffix})
175
176Return a temporary file name (as a string) or @code{NULL} if unable to
177create one.  @var{suffix} is a suffix to append to the file name.  The
178string is @code{malloc}ed, and the temporary file has been created.
179
180@end deftypefn
181
182*/
183
184char *
185make_temp_file (const char *suffix)
186{
187  const char *base = choose_tmpdir ();
188  char *temp_filename;
189  int base_len, suffix_len;
190  int fd;
191
192  if (suffix == 0)
193    suffix = "";
194
195  base_len = strlen (base);
196  suffix_len = strlen (suffix);
197
198  temp_filename = XNEWVEC (char, base_len
199                           + TEMP_FILE_LEN
200                           + suffix_len + 1);
201  strcpy (temp_filename, base);
202  strcpy (temp_filename + base_len, TEMP_FILE);
203  strcpy (temp_filename + base_len + TEMP_FILE_LEN, suffix);
204
205  fd = mkstemps (temp_filename, suffix_len);
206  /* Mkstemps failed.  It may be EPERM, ENOSPC etc.  */
207  if (fd == -1)
208    {
209      fprintf (stderr, "Cannot create temporary file in %s: %s\n",
210               base, strerror (errno));
211      abort ();
212    }
213  /* We abort on failed close out of sheer paranoia.  */
214  if (close (fd))
215    abort ();
216  return temp_filename;
217}
Note: See TracBrowser for help on using the repository browser.