]>
git.ipfire.org Git - thirdparty/cups.git/blob - scheduler/file.c
2 * File functions for the CUPS scheduler.
4 * Copyright 2007-2014 by Apple Inc.
5 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
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 * "LICENSE" which should have been included with this file. If this
11 * file is missing or damaged, see the license at "http://www.cups.org/".
15 * Include necessary headers...
21 #ifdef HAVE_REMOVEFILE
22 # include <removefile.h>
24 static int overwrite_data(int fd
, const char *buffer
, int bufsize
,
26 #endif /* HAVE_REMOVEFILE */
30 * 'cupsdCleanFiles()' - Clean out old files.
34 cupsdCleanFiles(const char *path
, /* I - Directory to clean */
35 const char *pattern
) /* I - Filename pattern or NULL */
37 cups_dir_t
*dir
; /* Directory */
38 cups_dentry_t
*dent
; /* Directory entry */
39 char filename
[1024]; /* Filename */
40 int status
; /* Status from unlink/rmdir */
43 cupsdLogMessage(CUPSD_LOG_DEBUG
,
44 "cupsdCleanFiles(path=\"%s\", pattern=\"%s\")", path
,
45 pattern
? pattern
: "(null)");
47 if ((dir
= cupsDirOpen(path
)) == NULL
)
49 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to open directory \"%s\" - %s",
50 path
, strerror(errno
));
54 cupsdLogMessage(CUPSD_LOG_INFO
, "Cleaning out old files in \"%s\".", path
);
56 while ((dent
= cupsDirRead(dir
)) != NULL
)
58 if (pattern
&& fnmatch(pattern
, dent
->filename
, 0))
61 snprintf(filename
, sizeof(filename
), "%s/%s", path
, dent
->filename
);
63 if (S_ISDIR(dent
->fileinfo
.st_mode
))
65 cupsdCleanFiles(filename
, pattern
);
67 status
= rmdir(filename
);
70 status
= cupsdUnlinkOrRemoveFile(filename
);
73 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to remove \"%s\" - %s", filename
,
82 * 'cupsdCloseCreatedConfFile()' - Close a created configuration file and move
86 int /* O - 0 on success, -1 on error */
87 cupsdCloseCreatedConfFile(
88 cups_file_t
*fp
, /* I - File to close */
89 const char *filename
) /* I - Filename */
91 char newfile
[1024], /* filename.N */
92 oldfile
[1024]; /* filename.O */
96 * Synchronize changes to disk if SyncOnClose is enabled.
101 if (cupsFileFlush(fp
))
103 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to write changes to \"%s\": %s",
104 filename
, strerror(errno
));
109 if (fsync(cupsFileNumber(fp
)))
111 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to sync changes to \"%s\": %s",
112 filename
, strerror(errno
));
119 * First close the file...
122 if (cupsFileClose(fp
))
126 * Then remove "filename.O", rename "filename" to "filename.O", and rename
127 * "filename.N" to "filename".
130 snprintf(newfile
, sizeof(newfile
), "%s.N", filename
);
131 snprintf(oldfile
, sizeof(oldfile
), "%s.O", filename
);
133 if ((cupsdUnlinkOrRemoveFile(oldfile
) && errno
!= ENOENT
) ||
134 (rename(filename
, oldfile
) && errno
!= ENOENT
) ||
135 rename(newfile
, filename
))
137 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to finalize \"%s\": %s",
138 filename
, strerror(errno
));
147 * 'cupsdClosePipe()' - Close a pipe as necessary.
151 cupsdClosePipe(int *fds
) /* I - Pipe file descriptors (2) */
154 * Close file descriptors as needed...
172 * 'cupsdCreateConfFile()' - Create a configuration file safely.
175 cups_file_t
* /* O - File pointer */
177 const char *filename
, /* I - Filename */
178 mode_t mode
) /* I - Permissions */
180 cups_file_t
*fp
; /* File pointer */
181 char newfile
[1024]; /* filename.N */
184 snprintf(newfile
, sizeof(newfile
), "%s.N", filename
);
185 if ((fp
= cupsFileOpen(newfile
, "w")) == NULL
)
187 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to create \"%s\": %s", newfile
,
192 if (!getuid() && fchown(cupsFileNumber(fp
), getuid(), Group
))
193 cupsdLogMessage(CUPSD_LOG_WARN
, "Unable to change group for \"%s\": %s",
194 newfile
, strerror(errno
));
196 if (fchmod(cupsFileNumber(fp
), mode
))
197 cupsdLogMessage(CUPSD_LOG_WARN
,
198 "Unable to change permissions for \"%s\": %s",
199 newfile
, strerror(errno
));
207 * 'cupsdOpenConfFile()' - Open a configuration file.
209 * This function looks for "filename.O" if "filename" does not exist and does
210 * a rename as needed.
213 cups_file_t
* /* O - File pointer */
214 cupsdOpenConfFile(const char *filename
) /* I - Filename */
216 cups_file_t
*fp
; /* File pointer */
219 if ((fp
= cupsFileOpen(filename
, "r")) == NULL
)
224 * Try opening the backup file...
227 char oldfile
[1024]; /* filename.O */
229 snprintf(oldfile
, sizeof(oldfile
), "%s.O", filename
);
230 fp
= cupsFileOpen(oldfile
, "r");
233 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to open \"%s\": %s", filename
,
242 * 'cupsdOpenPipe()' - Create a pipe which is closed on exec.
245 int /* O - 0 on success, -1 on error */
246 cupsdOpenPipe(int *fds
) /* O - Pipe file descriptors (2) */
261 * Set the "close on exec" flag on each end of the pipe...
264 if (fcntl(fds
[0], F_SETFD
, fcntl(fds
[0], F_GETFD
) | FD_CLOEXEC
))
275 if (fcntl(fds
[1], F_SETFD
, fcntl(fds
[1], F_GETFD
) | FD_CLOEXEC
))
287 * Return 0 indicating success...
295 * 'cupsdRemoveFile()' - Remove a file securely.
298 int /* O - 0 on success, -1 on error */
299 cupsdRemoveFile(const char *filename
) /* I - File to remove */
301 #ifdef HAVE_REMOVEFILE
303 * See if the file exists...
306 if (access(filename
, 0))
309 cupsdLogMessage(CUPSD_LOG_DEBUG
, "Securely removing \"%s\".", filename
);
315 return (removefile(filename
, NULL
, REMOVEFILE_SECURE_1_PASS
));
318 int fd
; /* File descriptor */
319 struct stat info
; /* File information */
320 char buffer
[512]; /* Data buffer */
321 int i
; /* Looping var */
325 * See if the file exists...
328 if (access(filename
, 0))
331 cupsdLogMessage(CUPSD_LOG_DEBUG
, "Securely removing \"%s\".", filename
);
334 * First open the file for writing in exclusive mode.
337 if ((fd
= open(filename
, O_WRONLY
| O_EXCL
)) < 0)
341 * Delete the file now - it will still be around as long as the file is
345 if (unlink(filename
))
352 * Then get the file size...
355 if (fstat(fd
, &info
))
362 * Overwrite the file with random data.
365 CUPS_SRAND(time(NULL
));
367 for (i
= 0; i
< sizeof(buffer
); i
++)
368 buffer
[i
] = CUPS_RAND();
369 if (overwrite_data(fd
, buffer
, sizeof(buffer
), (int)info
.st_size
))
376 * Close the file, which will lead to the actual deletion, and return...
380 #endif /* HAVE_REMOVEFILE */
385 * 'cupsdUnlinkOrRemoveFile()' - Unlink or securely remove a file depending
386 * on the configuration.
389 int /* O - 0 on success, -1 on error */
390 cupsdUnlinkOrRemoveFile(
391 const char *filename
) /* I - Filename */
394 return (cupsdRemoveFile(filename
));
396 return (unlink(filename
));
400 #ifndef HAVE_REMOVEFILE
402 * 'overwrite_data()' - Overwrite the data in a file.
405 static int /* O - 0 on success, -1 on error */
406 overwrite_data(int fd
, /* I - File descriptor */
407 const char *buffer
, /* I - Buffer to write */
408 int bufsize
, /* I - Size of buffer */
409 int filesize
) /* I - Size of file */
411 int bytes
; /* Bytes to write/written */
415 * Start at the beginning of the file...
418 if (lseek(fd
, 0, SEEK_SET
) < 0)
422 * Fill the file with the provided data...
427 if (filesize
> bufsize
)
432 if ((bytes
= write(fd
, buffer
, (size_t)bytes
)) < 0)
439 * Force the changes to disk...
444 #endif /* HAVE_REMOVEFILE */