]>
git.ipfire.org Git - thirdparty/cups.git/blob - scheduler/file.c
2 * "$Id: file.c 11201 2013-07-26 21:27:27Z msweet $"
4 * File functions for the CUPS scheduler.
6 * Copyright 2007-2013 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 securely.
25 * cupsdUnlinkOrRemoveFile() - Unlink or securely remove a file depending
26 * on the configuration.
27 * overwrite_data() - Overwrite the data in a file.
31 * Include necessary headers...
37 #ifdef HAVE_REMOVEFILE
38 # include <removefile.h>
40 static int overwrite_data(int fd
, const char *buffer
, int bufsize
,
42 #endif /* HAVE_REMOVEFILE */
46 * 'cupsdCleanFiles()' - Clean out old files.
50 cupsdCleanFiles(const char *path
, /* I - Directory to clean */
51 const char *pattern
) /* I - Filename pattern or NULL */
53 cups_dir_t
*dir
; /* Directory */
54 cups_dentry_t
*dent
; /* Directory entry */
55 char filename
[1024]; /* Filename */
56 int status
; /* Status from unlink/rmdir */
59 cupsdLogMessage(CUPSD_LOG_DEBUG
,
60 "cupsdCleanFiles(path=\"%s\", pattern=\"%s\")", path
,
61 pattern
? pattern
: "(null)");
63 if ((dir
= cupsDirOpen(path
)) == NULL
)
65 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to open directory \"%s\" - %s",
66 path
, strerror(errno
));
70 cupsdLogMessage(CUPSD_LOG_INFO
, "Cleaning out old files in \"%s\".", path
);
72 while ((dent
= cupsDirRead(dir
)) != NULL
)
74 if (pattern
&& fnmatch(pattern
, dent
->filename
, 0))
77 snprintf(filename
, sizeof(filename
), "%s/%s", path
, dent
->filename
);
79 if (S_ISDIR(dent
->fileinfo
.st_mode
))
81 cupsdCleanFiles(filename
, pattern
);
83 status
= rmdir(filename
);
86 status
= cupsdUnlinkOrRemoveFile(filename
);
89 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to remove \"%s\" - %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 * Synchronize changes to disk if SyncOnClose is enabled.
117 if (cupsFileFlush(fp
))
119 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to write changes to \"%s\": %s",
120 filename
, strerror(errno
));
125 if (fsync(cupsFileNumber(fp
)))
127 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to sync changes to \"%s\": %s",
128 filename
, strerror(errno
));
135 * First close the file...
138 if (cupsFileClose(fp
))
142 * Then remove "filename.O", rename "filename" to "filename.O", and rename
143 * "filename.N" to "filename".
146 snprintf(newfile
, sizeof(newfile
), "%s.N", filename
);
147 snprintf(oldfile
, sizeof(oldfile
), "%s.O", filename
);
149 if ((cupsdUnlinkOrRemoveFile(oldfile
) && errno
!= ENOENT
) ||
150 (rename(filename
, oldfile
) && errno
!= ENOENT
) ||
151 rename(newfile
, filename
))
153 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to finalize \"%s\": %s",
154 filename
, strerror(errno
));
163 * 'cupsdClosePipe()' - Close a pipe as necessary.
167 cupsdClosePipe(int *fds
) /* I - Pipe file descriptors (2) */
170 * Close file descriptors as needed...
188 * 'cupsdCreateConfFile()' - Create a configuration file safely.
191 cups_file_t
* /* O - File pointer */
193 const char *filename
, /* I - Filename */
194 mode_t mode
) /* I - Permissions */
196 cups_file_t
*fp
; /* File pointer */
197 char newfile
[1024]; /* filename.N */
200 snprintf(newfile
, sizeof(newfile
), "%s.N", filename
);
201 if ((fp
= cupsFileOpen(newfile
, "w")) == NULL
)
203 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to create \"%s\": %s", newfile
,
208 if (!getuid() && fchown(cupsFileNumber(fp
), getuid(), Group
))
209 cupsdLogMessage(CUPSD_LOG_WARN
, "Unable to change group for \"%s\": %s",
210 newfile
, strerror(errno
));
212 if (fchmod(cupsFileNumber(fp
), mode
))
213 cupsdLogMessage(CUPSD_LOG_WARN
,
214 "Unable to change permissions for \"%s\": %s",
215 newfile
, strerror(errno
));
223 * 'cupsdOpenConfFile()' - Open a configuration file.
225 * This function looks for "filename.O" if "filename" does not exist and does
226 * a rename as needed.
229 cups_file_t
* /* O - File pointer */
230 cupsdOpenConfFile(const char *filename
) /* I - Filename */
232 cups_file_t
*fp
; /* File pointer */
235 if ((fp
= cupsFileOpen(filename
, "r")) == NULL
)
240 * Try opening the backup file...
243 char oldfile
[1024]; /* filename.O */
245 snprintf(oldfile
, sizeof(oldfile
), "%s.O", filename
);
246 fp
= cupsFileOpen(oldfile
, "r");
249 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to open \"%s\": %s", filename
,
258 * 'cupsdOpenPipe()' - Create a pipe which is closed on exec.
261 int /* O - 0 on success, -1 on error */
262 cupsdOpenPipe(int *fds
) /* O - Pipe file descriptors (2) */
277 * Set the "close on exec" flag on each end of the pipe...
280 if (fcntl(fds
[0], F_SETFD
, fcntl(fds
[0], F_GETFD
) | FD_CLOEXEC
))
291 if (fcntl(fds
[1], F_SETFD
, fcntl(fds
[1], F_GETFD
) | FD_CLOEXEC
))
303 * Return 0 indicating success...
311 * 'cupsdRemoveFile()' - Remove a file securely.
314 int /* O - 0 on success, -1 on error */
315 cupsdRemoveFile(const char *filename
) /* I - File to remove */
317 #ifdef HAVE_REMOVEFILE
319 * See if the file exists...
322 if (access(filename
, 0))
325 cupsdLogMessage(CUPSD_LOG_DEBUG
, "Securely removing \"%s\".", filename
);
331 return (removefile(filename
, NULL
, REMOVEFILE_SECURE_1_PASS
));
334 int fd
; /* File descriptor */
335 struct stat info
; /* File information */
336 char buffer
[512]; /* Data buffer */
337 int i
; /* Looping var */
341 * See if the file exists...
344 if (access(filename
, 0))
347 cupsdLogMessage(CUPSD_LOG_DEBUG
, "Securely removing \"%s\".", filename
);
350 * First open the file for writing in exclusive mode.
353 if ((fd
= open(filename
, O_WRONLY
| O_EXCL
)) < 0)
357 * Delete the file now - it will still be around as long as the file is
361 if (unlink(filename
))
368 * Then get the file size...
371 if (fstat(fd
, &info
))
378 * Overwrite the file with random data.
381 CUPS_SRAND(time(NULL
));
383 for (i
= 0; i
< sizeof(buffer
); i
++)
384 buffer
[i
] = CUPS_RAND();
385 if (overwrite_data(fd
, buffer
, sizeof(buffer
), (int)info
.st_size
))
392 * Close the file, which will lead to the actual deletion, and return...
396 #endif /* HAVE_REMOVEFILE */
401 * 'cupsdUnlinkOrRemoveFile()' - Unlink or securely remove a file depending
402 * on the configuration.
405 int /* O - 0 on success, -1 on error */
406 cupsdUnlinkOrRemoveFile(
407 const char *filename
) /* I - Filename */
410 return (cupsdRemoveFile(filename
));
412 return (unlink(filename
));
416 #ifndef HAVE_REMOVEFILE
418 * 'overwrite_data()' - Overwrite the data in a file.
421 static int /* O - 0 on success, -1 on error */
422 overwrite_data(int fd
, /* I - File descriptor */
423 const char *buffer
, /* I - Buffer to write */
424 int bufsize
, /* I - Size of buffer */
425 int filesize
) /* I - Size of file */
427 int bytes
; /* Bytes to write/written */
431 * Start at the beginning of the file...
434 if (lseek(fd
, 0, SEEK_SET
) < 0)
438 * Fill the file with the provided data...
443 if (filesize
> bufsize
)
448 if ((bytes
= write(fd
, buffer
, bytes
)) < 0)
455 * Force the changes to disk...
460 #endif /* HAVE_REMOVEFILE */
464 * End of "$Id: file.c 11201 2013-07-26 21:27:27Z msweet $".