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