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