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