Coverage Report

Created: 2025-11-16 06:16

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