]>
git.ipfire.org Git - thirdparty/cups.git/blob - scheduler/file.c
2 * "$Id: file.c 11984 2014-07-02 13:16:59Z msweet $"
4 * File functions for the CUPS scheduler.
6 * Copyright 2007-2014 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 * Include necessary headers...
23 #ifdef HAVE_REMOVEFILE
24 # include <removefile.h>
26 static int overwrite_data(int fd
, const char *buffer
, int bufsize
,
28 #endif /* HAVE_REMOVEFILE */
32 * 'cupsdCleanFiles()' - Clean out old files.
36 cupsdCleanFiles(const char *path
, /* I - Directory to clean */
37 const char *pattern
) /* I - Filename pattern or NULL */
39 cups_dir_t
*dir
; /* Directory */
40 cups_dentry_t
*dent
; /* Directory entry */
41 char filename
[1024]; /* Filename */
42 int status
; /* Status from unlink/rmdir */
45 cupsdLogMessage(CUPSD_LOG_DEBUG
,
46 "cupsdCleanFiles(path=\"%s\", pattern=\"%s\")", path
,
47 pattern
? pattern
: "(null)");
49 if ((dir
= cupsDirOpen(path
)) == NULL
)
51 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to open directory \"%s\" - %s",
52 path
, strerror(errno
));
56 cupsdLogMessage(CUPSD_LOG_INFO
, "Cleaning out old files in \"%s\".", path
);
58 while ((dent
= cupsDirRead(dir
)) != NULL
)
60 if (pattern
&& fnmatch(pattern
, dent
->filename
, 0))
63 snprintf(filename
, sizeof(filename
), "%s/%s", path
, dent
->filename
);
65 if (S_ISDIR(dent
->fileinfo
.st_mode
))
67 cupsdCleanFiles(filename
, pattern
);
69 status
= rmdir(filename
);
72 status
= cupsdUnlinkOrRemoveFile(filename
);
75 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to remove \"%s\" - %s", filename
,
84 * 'cupsdCloseCreatedConfFile()' - Close a created configuration file and move
88 int /* O - 0 on success, -1 on error */
89 cupsdCloseCreatedConfFile(
90 cups_file_t
*fp
, /* I - File to close */
91 const char *filename
) /* I - Filename */
93 char newfile
[1024], /* filename.N */
94 oldfile
[1024]; /* filename.O */
98 * Synchronize changes to disk if SyncOnClose is enabled.
103 if (cupsFileFlush(fp
))
105 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to write changes to \"%s\": %s",
106 filename
, strerror(errno
));
111 if (fsync(cupsFileNumber(fp
)))
113 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to sync changes to \"%s\": %s",
114 filename
, strerror(errno
));
121 * First close the file...
124 if (cupsFileClose(fp
))
128 * Then remove "filename.O", rename "filename" to "filename.O", and rename
129 * "filename.N" to "filename".
132 snprintf(newfile
, sizeof(newfile
), "%s.N", filename
);
133 snprintf(oldfile
, sizeof(oldfile
), "%s.O", filename
);
135 if ((cupsdUnlinkOrRemoveFile(oldfile
) && errno
!= ENOENT
) ||
136 (rename(filename
, oldfile
) && errno
!= ENOENT
) ||
137 rename(newfile
, filename
))
139 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to finalize \"%s\": %s",
140 filename
, strerror(errno
));
149 * 'cupsdClosePipe()' - Close a pipe as necessary.
153 cupsdClosePipe(int *fds
) /* I - Pipe file descriptors (2) */
156 * Close file descriptors as needed...
174 * 'cupsdCreateConfFile()' - Create a configuration file safely.
177 cups_file_t
* /* O - File pointer */
179 const char *filename
, /* I - Filename */
180 mode_t mode
) /* I - Permissions */
182 cups_file_t
*fp
; /* File pointer */
183 char newfile
[1024]; /* filename.N */
186 snprintf(newfile
, sizeof(newfile
), "%s.N", filename
);
187 if ((fp
= cupsFileOpen(newfile
, "w")) == NULL
)
189 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to create \"%s\": %s", newfile
,
194 if (!getuid() && fchown(cupsFileNumber(fp
), getuid(), Group
))
195 cupsdLogMessage(CUPSD_LOG_WARN
, "Unable to change group for \"%s\": %s",
196 newfile
, strerror(errno
));
198 if (fchmod(cupsFileNumber(fp
), mode
))
199 cupsdLogMessage(CUPSD_LOG_WARN
,
200 "Unable to change permissions for \"%s\": %s",
201 newfile
, strerror(errno
));
209 * 'cupsdOpenConfFile()' - Open a configuration file.
211 * This function looks for "filename.O" if "filename" does not exist and does
212 * a rename as needed.
215 cups_file_t
* /* O - File pointer */
216 cupsdOpenConfFile(const char *filename
) /* I - Filename */
218 cups_file_t
*fp
; /* File pointer */
221 if ((fp
= cupsFileOpen(filename
, "r")) == NULL
)
226 * Try opening the backup file...
229 char oldfile
[1024]; /* filename.O */
231 snprintf(oldfile
, sizeof(oldfile
), "%s.O", filename
);
232 fp
= cupsFileOpen(oldfile
, "r");
235 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to open \"%s\": %s", filename
,
244 * 'cupsdOpenPipe()' - Create a pipe which is closed on exec.
247 int /* O - 0 on success, -1 on error */
248 cupsdOpenPipe(int *fds
) /* O - Pipe file descriptors (2) */
263 * Set the "close on exec" flag on each end of the pipe...
266 if (fcntl(fds
[0], F_SETFD
, fcntl(fds
[0], F_GETFD
) | FD_CLOEXEC
))
277 if (fcntl(fds
[1], F_SETFD
, fcntl(fds
[1], F_GETFD
) | FD_CLOEXEC
))
289 * Return 0 indicating success...
297 * 'cupsdRemoveFile()' - Remove a file securely.
300 int /* O - 0 on success, -1 on error */
301 cupsdRemoveFile(const char *filename
) /* I - File to remove */
303 #ifdef HAVE_REMOVEFILE
305 * See if the file exists...
308 if (access(filename
, 0))
311 cupsdLogMessage(CUPSD_LOG_DEBUG
, "Securely removing \"%s\".", filename
);
317 return (removefile(filename
, NULL
, REMOVEFILE_SECURE_1_PASS
));
320 int fd
; /* File descriptor */
321 struct stat info
; /* File information */
322 char buffer
[512]; /* Data buffer */
323 int i
; /* Looping var */
327 * See if the file exists...
330 if (access(filename
, 0))
333 cupsdLogMessage(CUPSD_LOG_DEBUG
, "Securely removing \"%s\".", filename
);
336 * First open the file for writing in exclusive mode.
339 if ((fd
= open(filename
, O_WRONLY
| O_EXCL
)) < 0)
343 * Delete the file now - it will still be around as long as the file is
347 if (unlink(filename
))
354 * Then get the file size...
357 if (fstat(fd
, &info
))
364 * Overwrite the file with random data.
367 CUPS_SRAND(time(NULL
));
369 for (i
= 0; i
< sizeof(buffer
); i
++)
370 buffer
[i
] = CUPS_RAND();
371 if (overwrite_data(fd
, buffer
, sizeof(buffer
), (int)info
.st_size
))
378 * Close the file, which will lead to the actual deletion, and return...
382 #endif /* HAVE_REMOVEFILE */
387 * 'cupsdUnlinkOrRemoveFile()' - Unlink or securely remove a file depending
388 * on the configuration.
391 int /* O - 0 on success, -1 on error */
392 cupsdUnlinkOrRemoveFile(
393 const char *filename
) /* I - Filename */
396 return (cupsdRemoveFile(filename
));
398 return (unlink(filename
));
402 #ifndef HAVE_REMOVEFILE
404 * 'overwrite_data()' - Overwrite the data in a file.
407 static int /* O - 0 on success, -1 on error */
408 overwrite_data(int fd
, /* I - File descriptor */
409 const char *buffer
, /* I - Buffer to write */
410 int bufsize
, /* I - Size of buffer */
411 int filesize
) /* I - Size of file */
413 int bytes
; /* Bytes to write/written */
417 * Start at the beginning of the file...
420 if (lseek(fd
, 0, SEEK_SET
) < 0)
424 * Fill the file with the provided data...
429 if (filesize
> bufsize
)
434 if ((bytes
= write(fd
, buffer
, (size_t)bytes
)) < 0)
441 * Force the changes to disk...
446 #endif /* HAVE_REMOVEFILE */
450 * End of "$Id: file.c 11984 2014-07-02 13:16:59Z msweet $".