]>
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 * Licensed under Apache License v2.0. See the file "LICENSE" for more
12 * Include necessary headers...
18 #ifdef HAVE_REMOVEFILE
19 # include <removefile.h>
21 static int overwrite_data(int fd
, const char *buffer
, int bufsize
,
23 #endif /* HAVE_REMOVEFILE */
27 * 'cupsdCleanFiles()' - Clean out old files.
31 cupsdCleanFiles(const char *path
, /* I - Directory to clean */
32 const char *pattern
) /* I - Filename pattern or NULL */
34 cups_dir_t
*dir
; /* Directory */
35 cups_dentry_t
*dent
; /* Directory entry */
36 char filename
[1024]; /* Filename */
37 int status
; /* Status from unlink/rmdir */
40 cupsdLogMessage(CUPSD_LOG_DEBUG
,
41 "cupsdCleanFiles(path=\"%s\", pattern=\"%s\")", path
,
42 pattern
? pattern
: "(null)");
44 if ((dir
= cupsDirOpen(path
)) == NULL
)
46 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to open directory \"%s\" - %s",
47 path
, strerror(errno
));
51 cupsdLogMessage(CUPSD_LOG_INFO
, "Cleaning out old files in \"%s\".", path
);
53 while ((dent
= cupsDirRead(dir
)) != NULL
)
55 if (pattern
&& fnmatch(pattern
, dent
->filename
, 0))
58 snprintf(filename
, sizeof(filename
), "%s/%s", path
, dent
->filename
);
60 if (S_ISDIR(dent
->fileinfo
.st_mode
))
62 cupsdCleanFiles(filename
, pattern
);
64 status
= rmdir(filename
);
67 status
= cupsdUnlinkOrRemoveFile(filename
);
70 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to remove \"%s\" - %s", filename
,
79 * 'cupsdCloseCreatedConfFile()' - Close a created configuration file and move
83 int /* O - 0 on success, -1 on error */
84 cupsdCloseCreatedConfFile(
85 cups_file_t
*fp
, /* I - File to close */
86 const char *filename
) /* I - Filename */
88 char newfile
[1024], /* filename.N */
89 oldfile
[1024]; /* filename.O */
93 * Synchronize changes to disk if SyncOnClose is enabled.
98 if (cupsFileFlush(fp
))
100 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to write changes to \"%s\": %s",
101 filename
, strerror(errno
));
106 if (fsync(cupsFileNumber(fp
)))
108 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to sync changes to \"%s\": %s",
109 filename
, strerror(errno
));
116 * First close the file...
119 if (cupsFileClose(fp
))
123 * Then remove "filename.O", rename "filename" to "filename.O", and rename
124 * "filename.N" to "filename".
127 snprintf(newfile
, sizeof(newfile
), "%s.N", filename
);
128 snprintf(oldfile
, sizeof(oldfile
), "%s.O", filename
);
130 if ((cupsdUnlinkOrRemoveFile(oldfile
) && errno
!= ENOENT
) ||
131 (rename(filename
, oldfile
) && errno
!= ENOENT
) ||
132 rename(newfile
, filename
))
134 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to finalize \"%s\": %s",
135 filename
, strerror(errno
));
144 * 'cupsdClosePipe()' - Close a pipe as necessary.
148 cupsdClosePipe(int *fds
) /* I - Pipe file descriptors (2) */
151 * Close file descriptors as needed...
169 * 'cupsdCreateConfFile()' - Create a configuration file safely.
172 cups_file_t
* /* O - File pointer */
174 const char *filename
, /* I - Filename */
175 mode_t mode
) /* I - Permissions */
177 cups_file_t
*fp
; /* File pointer */
178 char newfile
[1024]; /* filename.N */
181 snprintf(newfile
, sizeof(newfile
), "%s.N", filename
);
182 if ((fp
= cupsFileOpen(newfile
, "w")) == NULL
)
184 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to create \"%s\": %s", newfile
,
189 if (!getuid() && fchown(cupsFileNumber(fp
), getuid(), Group
))
190 cupsdLogMessage(CUPSD_LOG_WARN
, "Unable to change group for \"%s\": %s",
191 newfile
, strerror(errno
));
193 if (fchmod(cupsFileNumber(fp
), mode
))
194 cupsdLogMessage(CUPSD_LOG_WARN
,
195 "Unable to change permissions for \"%s\": %s",
196 newfile
, strerror(errno
));
204 * 'cupsdOpenConfFile()' - Open a configuration file.
206 * This function looks for "filename.O" if "filename" does not exist and does
207 * a rename as needed.
210 cups_file_t
* /* O - File pointer */
211 cupsdOpenConfFile(const char *filename
) /* I - Filename */
213 cups_file_t
*fp
; /* File pointer */
216 if ((fp
= cupsFileOpen(filename
, "r")) == NULL
)
221 * Try opening the backup file...
224 char oldfile
[1024]; /* filename.O */
226 snprintf(oldfile
, sizeof(oldfile
), "%s.O", filename
);
227 fp
= cupsFileOpen(oldfile
, "r");
230 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to open \"%s\": %s", filename
,
239 * 'cupsdOpenPipe()' - Create a pipe which is closed on exec.
242 int /* O - 0 on success, -1 on error */
243 cupsdOpenPipe(int *fds
) /* O - Pipe file descriptors (2) */
258 * Set the "close on exec" flag on each end of the pipe...
261 if (fcntl(fds
[0], F_SETFD
, fcntl(fds
[0], F_GETFD
) | FD_CLOEXEC
))
272 if (fcntl(fds
[1], F_SETFD
, fcntl(fds
[1], F_GETFD
) | FD_CLOEXEC
))
284 * Return 0 indicating success...
292 * 'cupsdRemoveFile()' - Remove a file securely.
295 int /* O - 0 on success, -1 on error */
296 cupsdRemoveFile(const char *filename
) /* I - File to remove */
298 #ifdef HAVE_REMOVEFILE
300 * See if the file exists...
303 if (access(filename
, 0))
306 cupsdLogMessage(CUPSD_LOG_DEBUG
, "Securely removing \"%s\".", filename
);
312 return (removefile(filename
, NULL
, REMOVEFILE_SECURE_1_PASS
));
315 int fd
; /* File descriptor */
316 struct stat info
; /* File information */
317 char buffer
[512]; /* Data buffer */
318 int i
; /* Looping var */
322 * See if the file exists...
325 if (access(filename
, 0))
328 cupsdLogMessage(CUPSD_LOG_DEBUG
, "Securely removing \"%s\".", filename
);
331 * First open the file for writing in exclusive mode.
334 if ((fd
= open(filename
, O_WRONLY
| O_EXCL
)) < 0)
338 * Delete the file now - it will still be around as long as the file is
342 if (unlink(filename
))
349 * Then get the file size...
352 if (fstat(fd
, &info
))
359 * Overwrite the file with random data.
362 CUPS_SRAND(time(NULL
));
364 for (i
= 0; i
< sizeof(buffer
); i
++)
365 buffer
[i
] = CUPS_RAND();
366 if (overwrite_data(fd
, buffer
, sizeof(buffer
), (int)info
.st_size
))
373 * Close the file, which will lead to the actual deletion, and return...
377 #endif /* HAVE_REMOVEFILE */
382 * 'cupsdUnlinkOrRemoveFile()' - Unlink or securely remove a file depending
383 * on the configuration.
386 int /* O - 0 on success, -1 on error */
387 cupsdUnlinkOrRemoveFile(
388 const char *filename
) /* I - Filename */
391 return (cupsdRemoveFile(filename
));
393 return (unlink(filename
));
397 #ifndef HAVE_REMOVEFILE
399 * 'overwrite_data()' - Overwrite the data in a file.
402 static int /* O - 0 on success, -1 on error */
403 overwrite_data(int fd
, /* I - File descriptor */
404 const char *buffer
, /* I - Buffer to write */
405 int bufsize
, /* I - Size of buffer */
406 int filesize
) /* I - Size of file */
408 int bytes
; /* Bytes to write/written */
412 * Start at the beginning of the file...
415 if (lseek(fd
, 0, SEEK_SET
) < 0)
419 * Fill the file with the provided data...
424 if (filesize
> bufsize
)
429 if ((bytes
= write(fd
, buffer
, (size_t)bytes
)) < 0)
436 * Force the changes to disk...
441 #endif /* HAVE_REMOVEFILE */