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