blob: 99ed5cae984c2bcdfc08a9689242f628625af874 [file] [log] [blame]
Jari Aalto28ef6c32001-04-06 19:14:31 +00001/*
2 * tmpfile.c - functions to create and safely open temp files for the shell.
3 */
4
5/* Copyright (C) 2000 Free Software Foundation, Inc.
6
7 This file is part of GNU Bash, the Bourne Again SHell.
8
Jari Aalto31859422009-01-12 13:36:28 +00009 Bash is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
Jari Aalto28ef6c32001-04-06 19:14:31 +000013
Jari Aalto31859422009-01-12 13:36:28 +000014 Bash is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
Jari Aalto28ef6c32001-04-06 19:14:31 +000018
19 You should have received a copy of the GNU General Public License
Jari Aalto31859422009-01-12 13:36:28 +000020 along with Bash. If not, see <http://www.gnu.org/licenses/>.
21*/
Jari Aalto28ef6c32001-04-06 19:14:31 +000022
23#include <config.h>
24
25#include <bashtypes.h>
26#include <posixstat.h>
Jari Aalto7117c2d2002-07-17 14:10:11 +000027#include <posixtime.h>
Jari Aalto28ef6c32001-04-06 19:14:31 +000028#include <filecntl.h>
29
30#if defined (HAVE_UNISTD_H)
31# include <unistd.h>
32#endif
33
Chet Rameyac50fba2014-02-26 09:36:43 -050034#include <bashansi.h>
35
Jari Aalto28ef6c32001-04-06 19:14:31 +000036#include <stdio.h>
37#include <errno.h>
38
39#include <shell.h>
40
41#ifndef errno
Ricardo Cerqueiraa02fbff2013-07-25 22:35:34 +010042#include <errno.h>
Jari Aalto28ef6c32001-04-06 19:14:31 +000043#endif
44
Chet Ramey495aee42011-11-22 19:11:26 -050045#define BASEOPENFLAGS (O_CREAT | O_TRUNC | O_EXCL | O_BINARY)
Jari Aalto28ef6c32001-04-06 19:14:31 +000046
47#define DEFAULT_TMPDIR "." /* bogus default, should be changed */
48#define DEFAULT_NAMEROOT "shtmp"
49
Jari Aaltof73dda02001-11-13 17:56:06 +000050extern pid_t dollar_dollar_pid;
Jari Aalto28ef6c32001-04-06 19:14:31 +000051
Jari Aalto06285672006-10-10 14:15:34 +000052static char *get_sys_tmpdir __P((void));
53static char *get_tmpdir __P((int));
54
Jari Aalto28ef6c32001-04-06 19:14:31 +000055static char *sys_tmpdir = (char *)NULL;
56static int ntmpfiles;
57static int tmpnamelen = -1;
58static unsigned long filenum = 1L;
59
60static char *
61get_sys_tmpdir ()
62{
Jari Aalto28ef6c32001-04-06 19:14:31 +000063 if (sys_tmpdir)
64 return sys_tmpdir;
65
Jari Aaltof73dda02001-11-13 17:56:06 +000066#ifdef P_tmpdir
67 sys_tmpdir = P_tmpdir;
Jari Aaltob80f6442004-07-27 13:29:18 +000068 if (file_iswdir (sys_tmpdir))
Jari Aaltof73dda02001-11-13 17:56:06 +000069 return sys_tmpdir;
70#endif
71
Jari Aalto28ef6c32001-04-06 19:14:31 +000072 sys_tmpdir = "/tmp";
Jari Aaltob80f6442004-07-27 13:29:18 +000073 if (file_iswdir (sys_tmpdir))
Jari Aalto28ef6c32001-04-06 19:14:31 +000074 return sys_tmpdir;
75
76 sys_tmpdir = "/var/tmp";
Jari Aaltob80f6442004-07-27 13:29:18 +000077 if (file_iswdir (sys_tmpdir))
Jari Aalto28ef6c32001-04-06 19:14:31 +000078 return sys_tmpdir;
79
80 sys_tmpdir = "/usr/tmp";
Jari Aaltob80f6442004-07-27 13:29:18 +000081 if (file_iswdir (sys_tmpdir))
Jari Aalto28ef6c32001-04-06 19:14:31 +000082 return sys_tmpdir;
83
Jari Aalto28ef6c32001-04-06 19:14:31 +000084 sys_tmpdir = DEFAULT_TMPDIR;
Jari Aalto28ef6c32001-04-06 19:14:31 +000085
86 return sys_tmpdir;
87}
88
89static char *
90get_tmpdir (flags)
91 int flags;
92{
93 char *tdir;
94
95 tdir = (flags & MT_USETMPDIR) ? get_string_value ("TMPDIR") : (char *)NULL;
Jari Aalto31859422009-01-12 13:36:28 +000096 if (tdir && (file_iswdir (tdir) == 0 || strlen (tdir) > PATH_MAX))
97 tdir = 0;
98
Jari Aalto28ef6c32001-04-06 19:14:31 +000099 if (tdir == 0)
100 tdir = get_sys_tmpdir ();
101
102#if defined (HAVE_PATHCONF) && defined (_PC_NAME_MAX)
103 if (tmpnamelen == -1)
104 tmpnamelen = pathconf (tdir, _PC_NAME_MAX);
105#else
106 tmpnamelen = 0;
107#endif
108
109 return tdir;
110}
111
112char *
113sh_mktmpname (nameroot, flags)
114 char *nameroot;
115 int flags;
116{
Jari Aaltof73dda02001-11-13 17:56:06 +0000117 char *filename, *tdir, *lroot;
Jari Aalto28ef6c32001-04-06 19:14:31 +0000118 struct stat sb;
119 int r, tdlen;
120
Jari Aaltof73dda02001-11-13 17:56:06 +0000121 filename = (char *)xmalloc (PATH_MAX + 1);
Jari Aalto28ef6c32001-04-06 19:14:31 +0000122 tdir = get_tmpdir (flags);
123 tdlen = strlen (tdir);
124
Jari Aaltof73dda02001-11-13 17:56:06 +0000125 lroot = nameroot ? nameroot : DEFAULT_NAMEROOT;
Jari Aalto28ef6c32001-04-06 19:14:31 +0000126
Jari Aaltof73dda02001-11-13 17:56:06 +0000127#ifdef USE_MKTEMP
128 sprintf (filename, "%s/%s.XXXXXX", tdir, lroot);
129 if (mktemp (filename) == 0)
130 {
131 free (filename);
132 filename = NULL;
133 }
134#else /* !USE_MKTEMP */
Jari Aalto28ef6c32001-04-06 19:14:31 +0000135 while (1)
136 {
Jari Aaltof73dda02001-11-13 17:56:06 +0000137 filenum = (filenum << 1) ^
138 (unsigned long) time ((time_t *)0) ^
139 (unsigned long) dollar_dollar_pid ^
Chet Rameyac50fba2014-02-26 09:36:43 -0500140 (unsigned long) ((flags & MT_USERANDOM) ? random () : ntmpfiles++);
Jari Aaltof73dda02001-11-13 17:56:06 +0000141 sprintf (filename, "%s/%s-%lu", tdir, lroot, filenum);
Jari Aalto28ef6c32001-04-06 19:14:31 +0000142 if (tmpnamelen > 0 && tmpnamelen < 32)
143 filename[tdlen + 1 + tmpnamelen] = '\0';
Jari Aaltof73dda02001-11-13 17:56:06 +0000144# ifdef HAVE_LSTAT
Jari Aalto28ef6c32001-04-06 19:14:31 +0000145 r = lstat (filename, &sb);
Jari Aaltof73dda02001-11-13 17:56:06 +0000146# else
Jari Aalto28ef6c32001-04-06 19:14:31 +0000147 r = stat (filename, &sb);
Jari Aaltof73dda02001-11-13 17:56:06 +0000148# endif
Jari Aalto28ef6c32001-04-06 19:14:31 +0000149 if (r < 0 && errno == ENOENT)
150 break;
151 }
Jari Aaltof73dda02001-11-13 17:56:06 +0000152#endif /* !USE_MKTEMP */
Jari Aalto28ef6c32001-04-06 19:14:31 +0000153
154 return filename;
155}
156
157int
158sh_mktmpfd (nameroot, flags, namep)
159 char *nameroot;
160 int flags;
161 char **namep;
162{
Jari Aaltof73dda02001-11-13 17:56:06 +0000163 char *filename, *tdir, *lroot;
Jari Aalto28ef6c32001-04-06 19:14:31 +0000164 int fd, tdlen;
165
Jari Aaltof73dda02001-11-13 17:56:06 +0000166 filename = (char *)xmalloc (PATH_MAX + 1);
Jari Aalto28ef6c32001-04-06 19:14:31 +0000167 tdir = get_tmpdir (flags);
168 tdlen = strlen (tdir);
169
Jari Aaltof73dda02001-11-13 17:56:06 +0000170 lroot = nameroot ? nameroot : DEFAULT_NAMEROOT;
Jari Aalto28ef6c32001-04-06 19:14:31 +0000171
Jari Aaltof73dda02001-11-13 17:56:06 +0000172#ifdef USE_MKSTEMP
173 sprintf (filename, "%s/%s.XXXXXX", tdir, lroot);
174 fd = mkstemp (filename);
175 if (fd < 0 || namep == 0)
176 {
177 free (filename);
178 filename = NULL;
179 }
180 if (namep)
181 *namep = filename;
182 return fd;
183#else /* !USE_MKSTEMP */
Jari Aalto28ef6c32001-04-06 19:14:31 +0000184 do
185 {
Jari Aaltof73dda02001-11-13 17:56:06 +0000186 filenum = (filenum << 1) ^
187 (unsigned long) time ((time_t *)0) ^
188 (unsigned long) dollar_dollar_pid ^
Chet Rameyac50fba2014-02-26 09:36:43 -0500189 (unsigned long) ((flags & MT_USERANDOM) ? random () : ntmpfiles++);
Jari Aaltof73dda02001-11-13 17:56:06 +0000190 sprintf (filename, "%s/%s-%lu", tdir, lroot, filenum);
Jari Aalto28ef6c32001-04-06 19:14:31 +0000191 if (tmpnamelen > 0 && tmpnamelen < 32)
192 filename[tdlen + 1 + tmpnamelen] = '\0';
193 fd = open (filename, BASEOPENFLAGS | ((flags & MT_READWRITE) ? O_RDWR : O_WRONLY), 0600);
194 }
195 while (fd < 0 && errno == EEXIST);
196
197 if (namep)
198 *namep = filename;
199 else
200 free (filename);
201
202 return fd;
Jari Aaltof73dda02001-11-13 17:56:06 +0000203#endif /* !USE_MKSTEMP */
Jari Aalto28ef6c32001-04-06 19:14:31 +0000204}
205
206FILE *
207sh_mktmpfp (nameroot, flags, namep)
208 char *nameroot;
209 int flags;
210 char **namep;
211{
212 int fd;
Jari Aaltof73dda02001-11-13 17:56:06 +0000213 FILE *fp;
Jari Aalto28ef6c32001-04-06 19:14:31 +0000214
215 fd = sh_mktmpfd (nameroot, flags, namep);
Jari Aaltof73dda02001-11-13 17:56:06 +0000216 if (fd < 0)
217 return ((FILE *)NULL);
218 fp = fdopen (fd, (flags & MT_READWRITE) ? "w+" : "w");
219 if (fp == 0)
220 close (fd);
221 return fp;
Jari Aalto28ef6c32001-04-06 19:14:31 +0000222}