2 * "$Id: file.c 9766 2011-05-11 22:17:34Z mike $"
4 * File functions for the CUPS scheduler.
6 * Copyright 2007-2011 by Apple Inc.
7 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * "LICENSE" which should have been included with this file. If this
13 * file is missing or damaged, see the license at "http://www.cups.org/".
17 * cupsdCleanFiles() - Clean out old files.
18 * cupsdCloseCreatedConfFile() - Close a created configuration file and move
20 * cupsdClosePipe() - Close a pipe as necessary.
21 * cupsdCreateConfFile() - Create a configuration file safely.
22 * cupsdOpenConfFile() - Open a configuration file.
23 * cupsdOpenPipe() - Create a pipe which is closed on exec.
24 * cupsdRemoveFile() - Remove a file using the 7-pass US DoD method.
25 * overwrite_data() - Overwrite the data in a file.
29 * Include necessary headers...
35 #ifdef HAVE_REMOVEFILE
36 # include <removefile.h>
38 static int overwrite_data(int fd, const char *buffer, int bufsize,
40 #endif /* HAVE_REMOVEFILE */
44 * 'cupsdCleanFiles()' - Clean out old files.
48 cupsdCleanFiles(const char *path, /* I - Directory to clean */
49 const char *pattern) /* I - Filename pattern or NULL */
51 cups_dir_t *dir; /* Directory */
52 cups_dentry_t *dent; /* Directory entry */
53 char filename[1024]; /* Filename */
54 int status; /* Status from unlink/rmdir */
57 cupsdLogMessage(CUPSD_LOG_DEBUG,
58 "cupsdCleanFiles(path=\"%s\", pattern=\"%s\")", path,
59 pattern ? pattern : "(null)");
61 if ((dir = cupsDirOpen(path)) == NULL)
63 cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to open directory \"%s\" - %s",
64 path, strerror(errno));
68 cupsdLogMessage(CUPSD_LOG_INFO, "Cleaning out old files in \"%s\"...", path);
70 while ((dent = cupsDirRead(dir)) != NULL)
72 if (pattern && fnmatch(pattern, dent->filename, 0))
75 snprintf(filename, sizeof(filename), "%s/%s", path, dent->filename);
77 if (S_ISDIR(dent->fileinfo.st_mode))
79 cupsdCleanFiles(filename, pattern);
81 status = rmdir(filename);
84 status = unlink(filename);
87 cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to remove \"%s\" - %s", filename,
90 cupsdLogMessage(CUPSD_LOG_DEBUG, "Removed \"%s\"...", filename);
98 * 'cupsdCloseCreatedConfFile()' - Close a created configuration file and move
102 int /* O - 0 on success, -1 on error */
103 cupsdCloseCreatedConfFile(
104 cups_file_t *fp, /* I - File to close */
105 const char *filename) /* I - Filename */
107 char newfile[1024], /* filename.N */
108 oldfile[1024]; /* filename.O */
112 * First close the file...
115 if (cupsFileClose(fp))
119 * Then remove "filename.O", rename "filename" to "filename.O", and rename
120 * "filename.N" to "filename".
123 snprintf(newfile, sizeof(newfile), "%s.N", filename);
124 snprintf(oldfile, sizeof(oldfile), "%s.O", filename);
126 if ((cupsdRemoveFile(oldfile) && errno != ENOENT) ||
127 (rename(filename, oldfile) && errno != ENOENT) ||
128 rename(newfile, filename))
130 cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to finalize \"%s\": %s",
131 filename, strerror(errno));
140 * 'cupsdClosePipe()' - Close a pipe as necessary.
144 cupsdClosePipe(int *fds) /* I - Pipe file descriptors (2) */
147 * Close file descriptors as needed...
165 * 'cupsdCreateConfFile()' - Create a configuration file safely.
168 cups_file_t * /* O - File pointer */
170 const char *filename, /* I - Filename */
171 mode_t mode) /* I - Permissions */
173 cups_file_t *fp; /* File pointer */
174 char newfile[1024]; /* filename.N */
177 snprintf(newfile, sizeof(newfile), "%s.N", filename);
178 if ((fp = cupsFileOpen(newfile, "w")) == NULL)
180 cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create \"%s\": %s", newfile,
185 if (!getuid() && fchown(cupsFileNumber(fp), getuid(), Group))
186 cupsdLogMessage(CUPSD_LOG_WARN, "Unable to change group for \"%s\": %s",
187 newfile, strerror(errno));
189 if (fchmod(cupsFileNumber(fp), mode))
190 cupsdLogMessage(CUPSD_LOG_WARN,
191 "Unable to change permissions for \"%s\": %s",
192 newfile, strerror(errno));
200 * 'cupsdOpenConfFile()' - Open a configuration file.
202 * This function looks for "filename.O" if "filename" does not exist and does
203 * a rename as needed.
206 cups_file_t * /* O - File pointer */
207 cupsdOpenConfFile(const char *filename) /* I - Filename */
209 cups_file_t *fp; /* File pointer */
212 if ((fp = cupsFileOpen(filename, "r")) == NULL)
217 * Try opening the backup file...
220 char oldfile[1024]; /* filename.O */
222 snprintf(oldfile, sizeof(oldfile), "%s.O", filename);
223 fp = cupsFileOpen(oldfile, "r");
226 cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to open \"%s\": %s", filename,
235 * 'cupsdOpenPipe()' - Create a pipe which is closed on exec.
238 int /* O - 0 on success, -1 on error */
239 cupsdOpenPipe(int *fds) /* O - Pipe file descriptors (2) */
254 * Set the "close on exec" flag on each end of the pipe...
257 if (fcntl(fds[0], F_SETFD, fcntl(fds[0], F_GETFD) | FD_CLOEXEC))
268 if (fcntl(fds[1], F_SETFD, fcntl(fds[1], F_GETFD) | FD_CLOEXEC))
280 * Return 0 indicating success...
288 * 'cupsdRemoveFile()' - Remove a file using the 7-pass US DoD method.
291 int /* O - 0 on success, -1 on error */
292 cupsdRemoveFile(const char *filename) /* I - File to remove */
294 #ifdef HAVE_REMOVEFILE
295 return (removefile(filename, NULL, REMOVEFILE_SECURE_7_PASS));
298 int fd; /* File descriptor */
299 struct stat info; /* File information */
300 char buffer[512]; /* Data buffer */
301 int i; /* Looping var */
305 * First open the file for writing in exclusive mode.
308 if ((fd = open(filename, O_WRONLY | O_EXCL)) < 0)
312 * Delete the file now - it will still be around as long as the file is
316 if (unlink(filename))
323 * Then get the file size...
326 if (fstat(fd, &info))
333 * Overwrite the file 7 times with 0xF6, 0x00, 0xFF, random, 0x00, 0xFF,
334 * and more random data.
337 memset(buffer, 0xF6, sizeof(buffer));
338 if (overwrite_data(fd, buffer, sizeof(buffer), (int)info.st_size))
344 memset(buffer, 0x00, sizeof(buffer));
345 if (overwrite_data(fd, buffer, sizeof(buffer), (int)info.st_size))
351 memset(buffer, 0xFF, sizeof(buffer));
352 if (overwrite_data(fd, buffer, sizeof(buffer), (int)info.st_size))
358 CUPS_SRAND(time(NULL));
360 for (i = 0; i < sizeof(buffer); i ++)
361 buffer[i] = CUPS_RAND();
362 if (overwrite_data(fd, buffer, sizeof(buffer), (int)info.st_size))
368 memset(buffer, 0x00, sizeof(buffer));
369 if (overwrite_data(fd, buffer, sizeof(buffer), (int)info.st_size))
375 memset(buffer, 0xFF, sizeof(buffer));
376 if (overwrite_data(fd, buffer, sizeof(buffer), (int)info.st_size))
382 for (i = 0; i < sizeof(buffer); i ++)
383 buffer[i] = CUPS_RAND();
384 if (overwrite_data(fd, buffer, sizeof(buffer), (int)info.st_size))
391 * Whew! Close the file (which will lead to the actual deletion) and
397 #endif /* HAVE_REMOVEFILE */
401 #ifndef HAVE_REMOVEFILE
403 * 'overwrite_data()' - Overwrite the data in a file.
406 static int /* O - 0 on success, -1 on error */
407 overwrite_data(int fd, /* I - File descriptor */
408 const char *buffer, /* I - Buffer to write */
409 int bufsize, /* I - Size of buffer */
410 int filesize) /* I - Size of file */
412 int bytes; /* Bytes to write/written */
416 * Start at the beginning of the file...
419 if (lseek(fd, 0, SEEK_SET) < 0)
423 * Fill the file with the provided data...
428 if (filesize > bufsize)
433 if ((bytes = write(fd, buffer, bytes)) < 0)
440 * Force the changes to disk...
445 #endif /* HAVE_REMOVEFILE */
449 * End of "$Id: file.c 9766 2011-05-11 22:17:34Z mike $".