/src/cups/cups/tempfile.c
Line | Count | Source |
1 | | // |
2 | | // Temp file utilities for CUPS. |
3 | | // |
4 | | // Copyright © 2020-2025 by OpenPrinting. |
5 | | // Copyright © 2007-2018 by Apple Inc. |
6 | | // Copyright © 1997-2006 by Easy Software Products. |
7 | | // |
8 | | // Licensed under Apache License v2.0. See the file "LICENSE" for more |
9 | | // information. |
10 | | // |
11 | | |
12 | | #include "cups-private.h" |
13 | | #include <stdlib.h> |
14 | | #include <fcntl.h> |
15 | | #include <sys/stat.h> |
16 | | #if defined(_WIN32) || defined(__EMX__) |
17 | | # include <io.h> |
18 | | #else |
19 | | # include <unistd.h> |
20 | | #endif // _WIN32 || __EMX__ |
21 | | |
22 | | |
23 | | // |
24 | | // 'cupsCreateTempFd()' - Creates a temporary file descriptor. |
25 | | // |
26 | | // This function creates a temporary file and associated descriptor. The unique |
27 | | // temporary filename uses the "prefix" and "suffix" arguments and is returned |
28 | | // in the "filename" buffer. The temporary file is opened for reading and |
29 | | // writing. |
30 | | // |
31 | | // @since CUPS 2.5@ |
32 | | // |
33 | | |
34 | | int // O - New file descriptor or `-1` on error |
35 | | cupsCreateTempFd(const char *prefix, // I - Filename prefix or `NULL` for none |
36 | | const char *suffix, // I - Filename suffix or `NULL` for none |
37 | | char *filename, // I - Pointer to buffer |
38 | | size_t len) // I - Size of buffer |
39 | 0 | { |
40 | 0 | int fd; // File descriptor for temp file |
41 | 0 | int tries; // Number of tries |
42 | 0 | const char *tmpdir; // TMPDIR environment var |
43 | | #if (defined(__APPLE__) && defined(_CS_DARWIN_USER_TEMP_DIR)) || defined(_WIN32) |
44 | | char tmppath[1024]; // Temporary directory |
45 | | #endif // (__APPLE__ && _CS_DARWIN_USER_TEMP_DIR) || _WIN32 |
46 | | #ifdef _WIN32 |
47 | | DWORD curtime; // Current time |
48 | | #else |
49 | 0 | struct timeval curtime; // Current time |
50 | 0 | #endif // _WIN32 |
51 | | |
52 | | |
53 | | // Get the current temporary directory... |
54 | | #ifdef _WIN32 |
55 | | if ((tmpdir = getenv("TEMP")) == NULL) |
56 | | { |
57 | | // Use the Windows API to get the system temporary directory... |
58 | | GetTempPathA(sizeof(tmppath), tmppath); |
59 | | tmpdir = tmppath; |
60 | | } |
61 | | |
62 | | #elif defined(__APPLE__) |
63 | | // On macOS and iOS, the TMPDIR environment variable is not always the best |
64 | | // location to place temporary files due to sandboxing. Instead, the confstr |
65 | | // function should be called to get the proper per-user, per-process TMPDIR |
66 | | // value. |
67 | | if ((tmpdir = getenv("TMPDIR")) != NULL && access(tmpdir, W_OK)) |
68 | | tmpdir = NULL; |
69 | | |
70 | | if (!tmpdir) |
71 | | { |
72 | | #ifdef _CS_DARWIN_USER_TEMP_DIR |
73 | | if (confstr(_CS_DARWIN_USER_TEMP_DIR, tmppath, sizeof(tmppath))) |
74 | | tmpdir = tmppath; |
75 | | else |
76 | | #endif // _CS_DARWIN_USER_TEMP_DIR |
77 | | tmpdir = "/private/tmp"; // macOS 10.4 and earlier |
78 | | } |
79 | | |
80 | | #else |
81 | | // Previously we put root temporary files in the default CUPS temporary |
82 | | // directory under /var/spool/cups. However, since the scheduler cleans |
83 | | // out temporary files there and runs independently of the user apps, we |
84 | | // don't want to use it unless specifically told to by cupsd. |
85 | 0 | if ((tmpdir = getenv("TMPDIR")) == NULL) |
86 | 0 | tmpdir = "/tmp"; |
87 | 0 | #endif // _WIN32 |
88 | | |
89 | | // Make the temporary name using the specified directory... |
90 | 0 | tries = 0; |
91 | |
|
92 | 0 | do |
93 | 0 | { |
94 | | #ifdef _WIN32 |
95 | | // Get the current time of day... |
96 | | curtime = GetTickCount() + tries; |
97 | | |
98 | | // Format a string using the hex time values... |
99 | | snprintf(filename, (size_t)len - 1, "%s/%s%05lx%08lx%s", tmpdir, prefix ? prefix : "", GetCurrentProcessId(), curtime, suffix ? suffix : ""); |
100 | | |
101 | | #else |
102 | | // Get the current time of day... |
103 | 0 | gettimeofday(&curtime, NULL); |
104 | | |
105 | | // Format a string using the hex time values... |
106 | 0 | snprintf(filename, (size_t)len - 1, "%s/%s%05x%08x%s", tmpdir, prefix ? prefix : "", (unsigned)getpid(), (unsigned)(curtime.tv_sec + curtime.tv_usec + tries), suffix ? suffix : ""); |
107 | 0 | #endif // _WIN32 |
108 | | |
109 | | // Open the file in "exclusive" mode, making sure that we don't |
110 | | // stomp on an existing file or someone's symlink crack... |
111 | | #ifdef _WIN32 |
112 | | fd = open(filename, _O_CREAT | _O_RDWR | _O_TRUNC | _O_BINARY, _S_IREAD | _S_IWRITE); |
113 | | #elif defined(O_NOFOLLOW) |
114 | 0 | fd = open(filename, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW, 0600); |
115 | | #else |
116 | | fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600); |
117 | | #endif // _WIN32 |
118 | |
|
119 | 0 | if (fd < 0 && errno != EEXIST) |
120 | 0 | break; |
121 | | |
122 | 0 | tries ++; |
123 | 0 | } |
124 | 0 | while (fd < 0 && tries < 1000); |
125 | | |
126 | | // Clear the filename if we didn't create a file... |
127 | 0 | if (fd < 0) |
128 | 0 | *filename = '\0'; |
129 | | |
130 | | // Return the file descriptor... |
131 | 0 | return (fd); |
132 | 0 | } |
133 | | |
134 | | |
135 | | // |
136 | | // 'cupsCreateTempFile()' - Creates a temporary CUPS file. |
137 | | // |
138 | | // This function creates a temporary file and returns a CUPS file for it. The |
139 | | // unique temporary filename uses the "prefix" and "suffix" arguments and is |
140 | | // returned in the "filename" buffer. The temporary file is opened for writing. |
141 | | // |
142 | | // @since CUPS 2.5@ |
143 | | // |
144 | | |
145 | | cups_file_t * // O - CUPS file or `NULL` on error |
146 | | cupsCreateTempFile(const char *prefix, // I - Filename prefix or `NULL` for none |
147 | | const char *suffix, // I - Filename suffix or `NULL` for none |
148 | | char *filename,// I - Pointer to buffer |
149 | | size_t len) // I - Size of buffer |
150 | 0 | { |
151 | 0 | cups_file_t *file; // CUPS file |
152 | 0 | int fd; // File descriptor |
153 | | |
154 | |
|
155 | 0 | if ((fd = cupsCreateTempFd(prefix, suffix, filename, len)) < 0) |
156 | 0 | { |
157 | 0 | return (NULL); |
158 | 0 | } |
159 | 0 | else if ((file = cupsFileOpenFd(fd, "w")) == NULL) |
160 | 0 | { |
161 | 0 | close(fd); |
162 | 0 | unlink(filename); |
163 | 0 | return (NULL); |
164 | 0 | } |
165 | 0 | else |
166 | 0 | { |
167 | 0 | return (file); |
168 | 0 | } |
169 | 0 | } |
170 | | |
171 | | |
172 | | // |
173 | | // 'cupsTempFd()' - Create a temporary file descriptor. |
174 | | // |
175 | | // This function creates a temporary file descriptor and places the filename in |
176 | | // the "filename" buffer. The temporary file descriptor is opened for reading |
177 | | // and writing. |
178 | | // |
179 | | // > Note: This function is deprecated. Use the @link cupsCreateTempFd@ |
180 | | // > function instead. |
181 | | // |
182 | | // @deprecated@ |
183 | | // |
184 | | |
185 | | int /* O - New file descriptor or -1 on error */ |
186 | | cupsTempFd(char *filename, /* I - Pointer to buffer */ |
187 | | int len) /* I - Size of buffer */ |
188 | 0 | { |
189 | 0 | return (cupsCreateTempFd(NULL, NULL, filename, (size_t)len)); |
190 | 0 | } |
191 | | |
192 | | |
193 | | // |
194 | | // 'cupsTempFile()' - Generate a temporary filename (deprecated). |
195 | | // |
196 | | // This function is deprecated and no longer generates a temporary filename. |
197 | | // Use @link cupsCreateTempFd@ or @link cupsCreateTempFile2@ instead. |
198 | | // |
199 | | // @deprecated@ |
200 | | // |
201 | | |
202 | | char * // O - `NULL` (error) |
203 | | cupsTempFile(char *filename, // I - Pointer to buffer */ |
204 | | int len) // I - Size of buffer |
205 | 0 | { |
206 | 0 | (void)len; |
207 | |
|
208 | 0 | if (filename) |
209 | 0 | *filename = '\0'; |
210 | |
|
211 | 0 | return (NULL); |
212 | 0 | } |
213 | | |
214 | | |
215 | | // |
216 | | // 'cupsTempFile2()' - Creates a temporary CUPS file. |
217 | | // |
218 | | // This function creates a temporary CUPS file and places the filename in the |
219 | | // "filename" buffer. The temporary file is opened for writing. |
220 | | // |
221 | | // > Note: This function is deprecated. Use the @link cupsCreateTempFile@ |
222 | | // > function instead. |
223 | | // |
224 | | // @deprecated@ |
225 | | // |
226 | | |
227 | | cups_file_t * /* O - CUPS file or @code NULL@ on error */ |
228 | | cupsTempFile2(char *filename, /* I - Pointer to buffer */ |
229 | | int len) /* I - Size of buffer */ |
230 | 0 | { |
231 | 0 | return (cupsCreateTempFile(NULL, NULL, filename, (size_t)len)); |
232 | 0 | } |