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