2
0
mirror of https://sourceware.org/git/binutils-gdb.git synced 2024-12-21 04:42:53 +08:00
binutils-gdb/libiberty/make-temp-file.c

218 lines
5.5 KiB
C
Raw Normal View History

2001-03-22 04:12:30 +08:00
/* Utility to pick a temporary filename prefix.
2011-01-04 05:05:58 +08:00
Copyright (C) 1996, 1997, 1998, 2001, 2009, 2010
Free Software Foundation, Inc.
2001-03-22 04:12:30 +08:00
This file is part of the libiberty library.
Libiberty is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
Libiberty is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with libiberty; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
Boston, MA 02110-1301, USA. */
2001-03-22 04:12:30 +08:00
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h> /* May get P_tmpdir. */
#include <sys/types.h>
2008-08-01 03:06:35 +08:00
#include <errno.h>
2001-03-22 04:12:30 +08:00
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_SYS_FILE_H
#include <sys/file.h> /* May get R_OK, etc. on some systems. */
#endif
2009-02-23 08:16:38 +08:00
#if defined(_WIN32) && !defined(__CYGWIN__)
#include <windows.h>
#endif
2001-03-22 04:12:30 +08:00
#ifndef R_OK
#define R_OK 4
#define W_OK 2
#define X_OK 1
#endif
#include "libiberty.h"
2005-03-28 10:09:01 +08:00
extern int mkstemps (char *, int);
2001-03-22 04:12:30 +08:00
/* '/' works just fine on MS-DOS based systems. */
#ifndef DIR_SEPARATOR
#define DIR_SEPARATOR '/'
#endif
/* Name of temporary file.
mktemp requires 6 trailing X's. */
#define TEMP_FILE "ccXXXXXX"
#define TEMP_FILE_LEN (sizeof(TEMP_FILE) - 1)
2009-02-23 08:16:38 +08:00
#if !defined(_WIN32) || defined(__CYGWIN__)
2001-03-22 04:12:30 +08:00
/* Subroutine of choose_tmpdir.
If BASE is non-NULL, return it.
Otherwise it checks if DIR is a usable directory.
If success, DIR is returned.
Otherwise NULL is returned. */
2005-05-25 05:01:33 +08:00
static inline const char *try_dir (const char *, const char *);
2001-03-22 04:12:30 +08:00
2001-04-04 09:16:27 +08:00
static inline const char *
2005-05-25 05:01:33 +08:00
try_dir (const char *dir, const char *base)
2001-03-22 04:12:30 +08:00
{
if (base != 0)
return base;
if (dir != 0
&& access (dir, R_OK | W_OK | X_OK) == 0)
return dir;
return 0;
}
static const char tmp[] = { DIR_SEPARATOR, 't', 'm', 'p', 0 };
static const char usrtmp[] =
{ DIR_SEPARATOR, 'u', 's', 'r', DIR_SEPARATOR, 't', 'm', 'p', 0 };
static const char vartmp[] =
{ DIR_SEPARATOR, 'v', 'a', 'r', DIR_SEPARATOR, 't', 'm', 'p', 0 };
2009-02-23 08:16:38 +08:00
#endif
2001-03-22 04:12:30 +08:00
static char *memoized_tmpdir;
2001-10-16 10:55:31 +08:00
/*
@deftypefn Replacement char* choose_tmpdir ()
Returns a pointer to a directory path suitable for creating temporary
files in.
@end deftypefn
*/
2001-03-22 04:12:30 +08:00
char *
2005-03-28 10:09:01 +08:00
choose_tmpdir (void)
2001-03-22 04:12:30 +08:00
{
2009-02-23 08:16:38 +08:00
if (!memoized_tmpdir)
{
#if !defined(_WIN32) || defined(__CYGWIN__)
const char *base = 0;
char *tmpdir;
unsigned int len;
2009-07-30 04:01:28 +08:00
#ifdef VMS
/* Try VMS standard temp logical. */
base = try_dir ("/sys$scratch", base);
#else
2009-02-23 08:16:38 +08:00
base = try_dir (getenv ("TMPDIR"), base);
base = try_dir (getenv ("TMP"), base);
base = try_dir (getenv ("TEMP"), base);
2009-07-30 04:01:28 +08:00
#endif
2009-02-23 08:16:38 +08:00
2001-03-22 04:12:30 +08:00
#ifdef P_tmpdir
2010-07-22 00:08:01 +08:00
/* We really want a directory name here as if concatenated with say \dir
we do not end up with a double \\ which defines an UNC path. */
if (strcmp (P_tmpdir, "\\") == 0)
base = try_dir ("\\.", base);
else
base = try_dir (P_tmpdir, base);
2001-03-22 04:12:30 +08:00
#endif
2009-02-23 08:16:38 +08:00
/* Try /var/tmp, /usr/tmp, then /tmp. */
base = try_dir (vartmp, base);
base = try_dir (usrtmp, base);
base = try_dir (tmp, base);
/* If all else fails, use the current directory! */
if (base == 0)
base = ".";
/* Append DIR_SEPARATOR to the directory we've chosen
and return it. */
len = strlen (base);
tmpdir = XNEWVEC (char, len + 2);
strcpy (tmpdir, base);
tmpdir[len] = DIR_SEPARATOR;
tmpdir[len+1] = '\0';
memoized_tmpdir = tmpdir;
#else /* defined(_WIN32) && !defined(__CYGWIN__) */
DWORD len;
/* Figure out how much space we need. */
len = GetTempPath(0, NULL);
if (len)
{
memoized_tmpdir = XNEWVEC (char, len);
if (!GetTempPath(len, memoized_tmpdir))
{
XDELETEVEC (memoized_tmpdir);
memoized_tmpdir = NULL;
}
}
if (!memoized_tmpdir)
/* If all else fails, use the current directory. */
memoized_tmpdir = xstrdup (".\\");
#endif /* defined(_WIN32) && !defined(__CYGWIN__) */
}
return memoized_tmpdir;
2001-03-22 04:12:30 +08:00
}
2001-10-16 10:55:31 +08:00
/*
@deftypefn Replacement char* make_temp_file (const char *@var{suffix})
Return a temporary file name (as a string) or @code{NULL} if unable to
create one. @var{suffix} is a suffix to append to the file name. The
2001-10-18 06:35:28 +08:00
string is @code{malloc}ed, and the temporary file has been created.
2001-10-16 10:55:31 +08:00
@end deftypefn
*/
2001-03-22 04:12:30 +08:00
char *
2005-03-28 10:09:01 +08:00
make_temp_file (const char *suffix)
2001-03-22 04:12:30 +08:00
{
const char *base = choose_tmpdir ();
char *temp_filename;
int base_len, suffix_len;
int fd;
if (suffix == 0)
suffix = "";
base_len = strlen (base);
suffix_len = strlen (suffix);
2005-05-25 05:01:33 +08:00
temp_filename = XNEWVEC (char, base_len
2001-03-22 04:12:30 +08:00
+ TEMP_FILE_LEN
+ suffix_len + 1);
strcpy (temp_filename, base);
strcpy (temp_filename + base_len, TEMP_FILE);
strcpy (temp_filename + base_len + TEMP_FILE_LEN, suffix);
fd = mkstemps (temp_filename, suffix_len);
2008-08-01 03:06:35 +08:00
/* Mkstemps failed. It may be EPERM, ENOSPC etc. */
2001-03-22 04:12:30 +08:00
if (fd == -1)
2008-08-01 03:06:35 +08:00
{
fprintf (stderr, "Cannot create temporary file in %s: %s\n",
base, strerror (errno));
abort ();
}
/* We abort on failed close out of sheer paranoia. */
2001-03-22 04:12:30 +08:00
if (close (fd))
abort ();
return temp_filename;
}