Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 1999, 2001-2002, 2006, 2009-2025 Free Software Foundation, |
2 | | Inc. |
3 | | This file is part of the GNU C Library. |
4 | | |
5 | | This file is free software: you can redistribute it and/or modify |
6 | | it under the terms of the GNU Lesser General Public License as |
7 | | published by the Free Software Foundation, either version 3 of the |
8 | | License, or (at your option) any later version. |
9 | | |
10 | | This file 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 |
13 | | GNU Lesser General Public License for more details. |
14 | | |
15 | | You should have received a copy of the GNU Lesser General Public License |
16 | | along with this program. If not, see <https://www.gnu.org/licenses/>. */ |
17 | | |
18 | | /* Extracted from sysdeps/posix/tempname.c. */ |
19 | | |
20 | | #include <config.h> |
21 | | |
22 | | /* Specification. */ |
23 | | #include "tmpdir.h" |
24 | | |
25 | | #include <stdlib.h> |
26 | | #include <string.h> |
27 | | |
28 | | #include <errno.h> |
29 | | #ifndef __set_errno |
30 | 0 | # define __set_errno(Val) errno = (Val) |
31 | | #endif |
32 | | |
33 | | #include <stdio.h> |
34 | | #ifndef P_tmpdir |
35 | | # ifdef _P_tmpdir /* native Windows */ |
36 | | # define P_tmpdir _P_tmpdir |
37 | | # else |
38 | | # define P_tmpdir "/tmp" |
39 | | # endif |
40 | | #endif |
41 | | |
42 | | #include <sys/stat.h> |
43 | | |
44 | | #if defined _WIN32 && ! defined __CYGWIN__ |
45 | | # define WIN32_LEAN_AND_MEAN /* avoid including junk */ |
46 | | # include <windows.h> |
47 | | #endif |
48 | | |
49 | | #include "pathmax.h" |
50 | | |
51 | | #if defined _WIN32 && ! defined __CYGWIN__ |
52 | | /* Don't assume that UNICODE is not defined. */ |
53 | | # undef GetTempPath |
54 | | # define GetTempPath GetTempPathA |
55 | | #endif |
56 | | |
57 | | #if _LIBC |
58 | | # define struct_stat64 struct stat64 |
59 | | #else |
60 | 0 | # define struct_stat64 struct stat |
61 | 0 | # define __libc_secure_getenv secure_getenv |
62 | 0 | # define __xstat64(version, path, buf) stat (path, buf) |
63 | | #endif |
64 | | |
65 | | /* Pathname support. |
66 | | ISSLASH(C) tests whether C is a directory separator character. |
67 | | */ |
68 | | #if defined _WIN32 || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__ |
69 | | /* Native Windows, Cygwin, OS/2, DOS */ |
70 | | # define ISSLASH(C) ((C) == '/' || (C) == '\\') |
71 | | #else |
72 | | /* Unix */ |
73 | 0 | # define ISSLASH(C) ((C) == '/') |
74 | | #endif |
75 | | |
76 | | |
77 | | /* Return nonzero if DIR is an existent directory. */ |
78 | | static bool |
79 | | direxists (const char *dir) |
80 | 0 | { |
81 | 0 | struct_stat64 buf; |
82 | 0 | return __xstat64 (_STAT_VER, dir, &buf) == 0 && S_ISDIR (buf.st_mode); |
83 | 0 | } |
84 | | |
85 | | /* Path search algorithm, for tmpnam, tmpfile, etc. If DIR is |
86 | | non-null and exists, uses it; otherwise uses the first of $TMPDIR, |
87 | | P_tmpdir, /tmp that exists. Copies into TMPL a template suitable |
88 | | for use with mk[s]temp. Will fail (-1) if DIR is non-null and |
89 | | doesn't exist, none of the searched dirs exists, or there's not |
90 | | enough space in TMPL. */ |
91 | | int |
92 | | path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, |
93 | | bool try_tmpdir) |
94 | 0 | { |
95 | 0 | const char *d; |
96 | 0 | size_t dlen, plen; |
97 | 0 | bool add_slash; |
98 | |
|
99 | 0 | if (!pfx || !pfx[0]) |
100 | 0 | { |
101 | 0 | pfx = "file"; |
102 | 0 | plen = 4; |
103 | 0 | } |
104 | 0 | else |
105 | 0 | { |
106 | 0 | plen = strlen (pfx); |
107 | 0 | if (plen > 5) |
108 | 0 | plen = 5; |
109 | 0 | } |
110 | |
|
111 | 0 | if (try_tmpdir) |
112 | 0 | { |
113 | 0 | d = __libc_secure_getenv ("TMPDIR"); |
114 | 0 | if (d != NULL && direxists (d)) |
115 | 0 | dir = d; |
116 | 0 | else if (dir != NULL && direxists (dir)) |
117 | 0 | /* nothing */ ; |
118 | 0 | else |
119 | 0 | dir = NULL; |
120 | 0 | } |
121 | 0 | if (dir == NULL) |
122 | 0 | { |
123 | | #if defined _WIN32 && ! defined __CYGWIN__ |
124 | | char dirbuf[PATH_MAX]; |
125 | | DWORD retval; |
126 | | |
127 | | /* Find Windows temporary file directory. |
128 | | We try this before P_tmpdir because Windows defines P_tmpdir to "\\" |
129 | | and will therefore try to put all temporary files in the root |
130 | | directory (unless $TMPDIR is set). */ |
131 | | retval = GetTempPath (PATH_MAX, dirbuf); |
132 | | if (retval > 0 && retval < PATH_MAX && direxists (dirbuf)) |
133 | | dir = dirbuf; |
134 | | else |
135 | | #endif |
136 | 0 | if (direxists (P_tmpdir)) |
137 | 0 | dir = P_tmpdir; |
138 | 0 | else if (strcmp (P_tmpdir, "/tmp") != 0 && direxists ("/tmp")) |
139 | 0 | dir = "/tmp"; |
140 | 0 | else |
141 | 0 | { |
142 | 0 | __set_errno (ENOENT); |
143 | 0 | return -1; |
144 | 0 | } |
145 | 0 | } |
146 | | |
147 | 0 | dlen = strlen (dir); |
148 | | #ifdef __VMS |
149 | | add_slash = 0; |
150 | | #else |
151 | 0 | add_slash = dlen != 0 && !ISSLASH (dir[dlen - 1]); |
152 | 0 | #endif |
153 | | |
154 | | /* check we have room for "${dir}/${pfx}XXXXXX\0" */ |
155 | 0 | if (tmpl_len < dlen + add_slash + plen + 6 + 1) |
156 | 0 | { |
157 | 0 | __set_errno (EINVAL); |
158 | 0 | return -1; |
159 | 0 | } |
160 | | |
161 | 0 | memcpy (tmpl, dir, dlen); |
162 | 0 | sprintf (tmpl + dlen, &"/%.*sXXXXXX"[!add_slash], (int) plen, pfx); |
163 | 0 | return 0; |
164 | 0 | } |