1 /*
2 * Temp file utilities for CUPS.
3 *
4 * Copyright 2007-2014 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 #ifdef WIN32
46 char tmppath[1024]; /* Windows temporary directory */
47 DWORD curtime; /* Current time */
48 #else
49 struct timeval curtime; /* Current time */
50 #endif /* WIN32 */
51
52
53 /*
54 * See if TMPDIR is defined...
55 */
56
57 #ifdef WIN32
58 if ((tmpdir = getenv("TEMP")) == NULL)
59 {
60 GetTempPath(sizeof(tmppath), tmppath);
61 tmpdir = tmppath;
62 }
63 #else
64 /*
65 * Previously we put root temporary files in the default CUPS temporary
66 * directory under /var/spool/cups. However, since the scheduler cleans
67 * out temporary files there and runs independently of the user apps, we
68 * don't want to use it unless specifically told to by cupsd.
69 */
70
71 if ((tmpdir = getenv("TMPDIR")) == NULL)
72 # if defined(__APPLE__) && !TARGET_OS_IOS
73 tmpdir = "/private/tmp"; /* /tmp is a symlink to /private/tmp */
74 # else
75 tmpdir = "/tmp";
76 # endif /* __APPLE__ && !TARGET_OS_IOS */
77 #endif /* WIN32 */
78
79 /*
80 * Make the temporary name using the specified directory...
81 */
82
83 tries = 0;
84
85 do
86 {
87 #ifdef WIN32
88 /*
89 * Get the current time of day...
90 */
91
92 curtime = GetTickCount() + tries;
93
94 /*
95 * Format a string using the hex time values...
96 */
97
98 snprintf(filename, (size_t)len - 1, "%s/%05lx%08lx", tmpdir, GetCurrentProcessId(), curtime);
99 #else
100 /*
101 * Get the current time of day...
102 */
103
104 gettimeofday(&curtime, NULL);
105
106 /*
107 * Format a string using the hex time values...
108 */
109
110 snprintf(filename, (size_t)len - 1, "%s/%05x%08x", tmpdir, (unsigned)getpid(), (unsigned)(curtime.tv_sec + curtime.tv_usec + tries));
111 #endif /* WIN32 */
112
113 /*
114 * Open the file in "exclusive" mode, making sure that we don't
115 * stomp on an existing file or someone's symlink crack...
116 */
117
118 #ifdef WIN32
119 fd = open(filename, _O_CREAT | _O_RDWR | _O_TRUNC | _O_BINARY,
120 _S_IREAD | _S_IWRITE);
121 #elif defined(O_NOFOLLOW)
122 fd = open(filename, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW, 0600);
123 #else
124 fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
125 #endif /* WIN32 */
126
127 if (fd < 0 && errno != EEXIST)
128 break;
129
130 tries ++;
131 }
132 while (fd < 0 && tries < 1000);
133
134 /*
135 * Return the file descriptor...
136 */
137
138 return (fd);
139 }
140
141
142 /*
143 * 'cupsTempFile()' - Generates a temporary filename.
144 *
145 * The temporary filename is returned in the filename buffer.
146 * This function is deprecated and will no longer generate a temporary
147 * filename - use @link cupsTempFd@ or @link cupsTempFile2@ instead.
148 *
149 * @deprecated@
150 */
151
152 char * /* O - Filename or @code NULL@ on error */
cupsTempFile(char * filename,int len)153 cupsTempFile(char *filename, /* I - Pointer to buffer */
154 int len) /* I - Size of buffer */
155 {
156 (void)len;
157
158 if (filename)
159 *filename = '\0';
160
161 return (NULL);
162 }
163
164
165 /*
166 * 'cupsTempFile2()' - Creates a temporary CUPS file.
167 *
168 * The temporary filename is returned in the filename buffer.
169 * The temporary file is opened for writing.
170 *
171 * @since CUPS 1.2/macOS 10.5@
172 */
173
174 cups_file_t * /* O - CUPS file or @code NULL@ on error */
cupsTempFile2(char * filename,int len)175 cupsTempFile2(char *filename, /* I - Pointer to buffer */
176 int len) /* I - Size of buffer */
177 {
178 cups_file_t *file; /* CUPS file */
179 int fd; /* File descriptor */
180
181
182 if ((fd = cupsTempFd(filename, len)) < 0)
183 return (NULL);
184 else if ((file = cupsFileOpenFd(fd, "w")) == NULL)
185 {
186 close(fd);
187 unlink(filename);
188 return (NULL);
189 }
190 else
191 return (file);
192 }
193