• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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