Mercurial > gnulib
annotate lib/tmpfile.c @ 40235:5a52ef2d4772
all: Update URLs to msdn.microsoft.com.
* lib/stat-w32.c et al.: Update URLs after most of msdn.microsoft.com
was moved to docs.microsoft.com.
author | Bruno Haible <bruno@clisp.org> |
---|---|
date | Thu, 14 Mar 2019 09:49:24 +0100 |
parents | 392b2a7ad303 |
children |
rev | line source |
---|---|
8162 | 1 /* Create a temporary file. |
40057
b06060465f09
maint: Run 'make update-copyright'
Paul Eggert <eggert@cs.ucla.edu>
parents:
19484
diff
changeset
|
2 Copyright (C) 2007, 2009-2019 Free Software Foundation, Inc. |
8162 | 3 |
9309
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
8162
diff
changeset
|
4 This program is free software: you can redistribute it and/or modify |
8162 | 5 it under the terms of the GNU General Public License as published by |
9309
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
8162
diff
changeset
|
6 the Free Software Foundation; either version 3 of the License, or |
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
8162
diff
changeset
|
7 (at your option) any later version. |
8162 | 8 |
9 This program is distributed in the hope that it will be useful, | |
10 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 GNU General Public License for more details. | |
13 | |
14 You should have received a copy of the GNU General Public License | |
19190 | 15 along with this program. If not, see <https://www.gnu.org/licenses/>. */ |
8162 | 16 |
17 /* Written by Ben Pfaff. */ | |
18 | |
19 #include <config.h> | |
20 | |
21 /* Specification. */ | |
22 #include <stdio.h> | |
23 | |
40162
392b2a7ad303
tmpfile: Add support for Android, part 2.
Bruno Haible <bruno@clisp.org>
parents:
40160
diff
changeset
|
24 #include <errno.h> |
40160
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
25 #include <stdbool.h> |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
26 |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
27 #if defined _WIN32 && ! defined __CYGWIN__ |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
28 /* A native Windows platforms. */ |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
29 |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
30 # include <fcntl.h> |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
31 # include <string.h> |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
32 # include <sys/stat.h> |
8162 | 33 |
40160
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
34 # include <io.h> |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
35 |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
36 # define WIN32_LEAN_AND_MEAN /* avoid including junk */ |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
37 # include <windows.h> |
8162 | 38 |
40160
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
39 #else |
8162 | 40 |
40160
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
41 # include <unistd.h> |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
42 |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
43 #endif |
8162 | 44 |
45 #include "pathmax.h" | |
46 #include "tempname.h" | |
47 #include "tmpdir.h" | |
48 | |
15496
451ec8bd8a1c
pathmax: Leave PATH_MAX undefined on the Hurd, and a constant otherwise.
Bruno Haible <bruno@clisp.org>
parents:
14079
diff
changeset
|
49 /* PATH_MAX is guaranteed to be defined, because this replacement is only |
40160
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
50 used on native Windows and Android. */ |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
51 |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
52 #if defined _WIN32 && ! defined __CYGWIN__ |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
53 /* A native Windows platforms. */ |
15496
451ec8bd8a1c
pathmax: Leave PATH_MAX undefined on the Hurd, and a constant otherwise.
Bruno Haible <bruno@clisp.org>
parents:
14079
diff
changeset
|
54 |
8162 | 55 /* On Windows, opening a file with _O_TEMPORARY has the effect of passing |
56 the FILE_FLAG_DELETE_ON_CLOSE flag to CreateFile(), which has the effect | |
57 of deleting the file when it is closed - even when the program crashes. | |
58 But (according to the Cygwin sources) it works only on Windows NT or newer. | |
59 So we cache the info whether we are running on Windows NT or newer. */ | |
60 | |
61 static bool | |
62 supports_delete_on_close () | |
63 { | |
64 static int known; /* 1 = yes, -1 = no, 0 = unknown */ | |
65 if (!known) | |
66 { | |
67 OSVERSIONINFO v; | |
68 | |
16922
937fc0f34278
tmpfile, clean-temp: Fix invocation of GetVersionEx.
John Darrington <john@darrington.wattle.id.au>
parents:
16201
diff
changeset
|
69 /* According to |
40235
5a52ef2d4772
all: Update URLs to msdn.microsoft.com.
Bruno Haible <bruno@clisp.org>
parents:
40162
diff
changeset
|
70 <https://docs.microsoft.com/en-us/windows/desktop/api/sysinfoapi/nf-sysinfoapi-getversionexa> |
18287
f853b35738d6
Prefer American spelling for "initialize"
Paul Eggert <eggert@cs.ucla.edu>
parents:
18189
diff
changeset
|
71 this structure must be initialized as follows: */ |
16922
937fc0f34278
tmpfile, clean-temp: Fix invocation of GetVersionEx.
John Darrington <john@darrington.wattle.id.au>
parents:
16201
diff
changeset
|
72 v.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); |
937fc0f34278
tmpfile, clean-temp: Fix invocation of GetVersionEx.
John Darrington <john@darrington.wattle.id.au>
parents:
16201
diff
changeset
|
73 |
8162 | 74 if (GetVersionEx (&v)) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12233
diff
changeset
|
75 known = (v.dwPlatformId == VER_PLATFORM_WIN32_NT ? 1 : -1); |
8162 | 76 else |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12233
diff
changeset
|
77 known = -1; |
8162 | 78 } |
79 return (known > 0); | |
80 } | |
81 | |
82 FILE * | |
83 tmpfile (void) | |
84 { | |
85 char dir[PATH_MAX]; | |
86 DWORD retval; | |
87 | |
88 /* Find Windows temporary file directory. | |
89 We provide this as the directory argument to path_search because Windows | |
90 defines P_tmpdir to "\\" and will therefore try to put all temporary files | |
91 in the root directory (unless $TMPDIR is set). */ | |
92 retval = GetTempPath (PATH_MAX, dir); | |
93 if (retval > 0 && retval < PATH_MAX) | |
94 { | |
95 char xtemplate[PATH_MAX]; | |
96 | |
97 if (path_search (xtemplate, PATH_MAX, dir, NULL, true) >= 0) | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12233
diff
changeset
|
98 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12233
diff
changeset
|
99 size_t len = strlen (xtemplate); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12233
diff
changeset
|
100 int o_temporary = (supports_delete_on_close () ? _O_TEMPORARY : 0); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12233
diff
changeset
|
101 int fd; |
8162 | 102 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12233
diff
changeset
|
103 do |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12233
diff
changeset
|
104 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12233
diff
changeset
|
105 memcpy (&xtemplate[len - 6], "XXXXXX", 6); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12233
diff
changeset
|
106 if (gen_tempname (xtemplate, 0, 0, GT_NOCREATE) < 0) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12233
diff
changeset
|
107 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12233
diff
changeset
|
108 fd = -1; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12233
diff
changeset
|
109 break; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12233
diff
changeset
|
110 } |
8162 | 111 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12233
diff
changeset
|
112 fd = _open (xtemplate, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12233
diff
changeset
|
113 _O_CREAT | _O_EXCL | o_temporary |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12233
diff
changeset
|
114 | _O_RDWR | _O_BINARY, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12233
diff
changeset
|
115 _S_IREAD | _S_IWRITE); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12233
diff
changeset
|
116 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12233
diff
changeset
|
117 while (fd < 0 && errno == EEXIST); |
8162 | 118 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12233
diff
changeset
|
119 if (fd >= 0) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12233
diff
changeset
|
120 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12233
diff
changeset
|
121 FILE *fp = _fdopen (fd, "w+b"); |
8162 | 122 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12233
diff
changeset
|
123 if (fp != NULL) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12233
diff
changeset
|
124 return fp; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12233
diff
changeset
|
125 else |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12233
diff
changeset
|
126 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12233
diff
changeset
|
127 int saved_errno = errno; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12233
diff
changeset
|
128 _close (fd); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12233
diff
changeset
|
129 errno = saved_errno; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12233
diff
changeset
|
130 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12233
diff
changeset
|
131 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12233
diff
changeset
|
132 } |
8162 | 133 } |
134 else | |
135 { | |
136 if (retval > 0) | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12233
diff
changeset
|
137 errno = ENAMETOOLONG; |
8162 | 138 else |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12233
diff
changeset
|
139 /* Ideally this should translate GetLastError () to an errno value. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
12233
diff
changeset
|
140 errno = ENOENT; |
8162 | 141 } |
142 | |
143 return NULL; | |
144 } | |
40160
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
145 |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
146 #else |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
147 |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
148 FILE * |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
149 tmpfile (void) |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
150 { |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
151 char buf[PATH_MAX]; |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
152 int fd; |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
153 FILE *fp; |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
154 |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
155 /* Try $TMPDIR first, not /tmp nor P_tmpdir, because we need this replacement |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
156 on Android, and /tmp does not exist on Android. */ |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
157 |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
158 if (path_search (buf, sizeof buf, NULL, "tmpf", true)) |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
159 return NULL; |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
160 |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
161 fd = gen_tempname (buf, 0, 0, GT_FILE); |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
162 if (fd < 0) |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
163 return NULL; |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
164 |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
165 /* Note that this relies on the Unix semantics that |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
166 a file is not really removed until it is closed. */ |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
167 (void) unlink (buf); |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
168 |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
169 if ((fp = fdopen (fd, "w+b")) == NULL) |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
170 { |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
171 int saved_errno = errno; |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
172 close (fd); |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
173 errno = saved_errno; |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
174 } |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
175 |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
176 return fp; |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
177 } |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
178 |
5c7e0484c1e9
tmpfile: Add support for Android.
Bruno Haible <bruno@clisp.org>
parents:
40057
diff
changeset
|
179 #endif |