xref: /aosp_15_r20/external/libcups/cups/tempfile.c (revision 5e7646d21f1134fb0638875d812ef646c12ab91e)
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