Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
srohatgi01
GitHub Repository: srohatgi01/cups
Path: blob/master/scheduler/file.c
1090 views
1
/*
2
* File functions for the CUPS scheduler.
3
*
4
* Copyright © 2007-2014 by Apple Inc.
5
* Copyright © 1997-2007 by Easy Software Products, all rights reserved.
6
*
7
* Licensed under Apache License v2.0. See the file "LICENSE" for more
8
* information.
9
*/
10
11
/*
12
* Include necessary headers...
13
*/
14
15
#include "cupsd.h"
16
#include <cups/dir.h>
17
#include <fnmatch.h>
18
#ifdef HAVE_REMOVEFILE
19
# include <removefile.h>
20
#else
21
static int overwrite_data(int fd, const char *buffer, int bufsize,
22
int filesize);
23
#endif /* HAVE_REMOVEFILE */
24
25
26
/*
27
* 'cupsdCleanFiles()' - Clean out old files.
28
*/
29
30
void
31
cupsdCleanFiles(const char *path, /* I - Directory to clean */
32
const char *pattern) /* I - Filename pattern or NULL */
33
{
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 */
38
39
40
cupsdLogMessage(CUPSD_LOG_DEBUG,
41
"cupsdCleanFiles(path=\"%s\", pattern=\"%s\")", path,
42
pattern ? pattern : "(null)");
43
44
if ((dir = cupsDirOpen(path)) == NULL)
45
{
46
cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to open directory \"%s\" - %s",
47
path, strerror(errno));
48
return;
49
}
50
51
cupsdLogMessage(CUPSD_LOG_INFO, "Cleaning out old files in \"%s\".", path);
52
53
while ((dent = cupsDirRead(dir)) != NULL)
54
{
55
if (pattern && fnmatch(pattern, dent->filename, 0))
56
continue;
57
58
snprintf(filename, sizeof(filename), "%s/%s", path, dent->filename);
59
60
if (S_ISDIR(dent->fileinfo.st_mode))
61
{
62
cupsdCleanFiles(filename, pattern);
63
64
status = rmdir(filename);
65
}
66
else
67
status = cupsdUnlinkOrRemoveFile(filename);
68
69
if (status)
70
cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to remove \"%s\" - %s", filename,
71
strerror(errno));
72
}
73
74
cupsDirClose(dir);
75
}
76
77
78
/*
79
* 'cupsdCloseCreatedConfFile()' - Close a created configuration file and move
80
* into place.
81
*/
82
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 */
87
{
88
char newfile[1024], /* filename.N */
89
oldfile[1024]; /* filename.O */
90
91
92
/*
93
* Synchronize changes to disk if SyncOnClose is enabled.
94
*/
95
96
if (SyncOnClose)
97
{
98
if (cupsFileFlush(fp))
99
{
100
cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to write changes to \"%s\": %s",
101
filename, strerror(errno));
102
cupsFileClose(fp);
103
return (-1);
104
}
105
106
if (fsync(cupsFileNumber(fp)))
107
{
108
cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to sync changes to \"%s\": %s",
109
filename, strerror(errno));
110
cupsFileClose(fp);
111
return (-1);
112
}
113
}
114
115
/*
116
* First close the file...
117
*/
118
119
if (cupsFileClose(fp))
120
return (-1);
121
122
/*
123
* Then remove "filename.O", rename "filename" to "filename.O", and rename
124
* "filename.N" to "filename".
125
*/
126
127
snprintf(newfile, sizeof(newfile), "%s.N", filename);
128
snprintf(oldfile, sizeof(oldfile), "%s.O", filename);
129
130
if ((cupsdUnlinkOrRemoveFile(oldfile) && errno != ENOENT) ||
131
(rename(filename, oldfile) && errno != ENOENT) ||
132
rename(newfile, filename))
133
{
134
cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to finalize \"%s\": %s",
135
filename, strerror(errno));
136
return (-1);
137
}
138
139
return (0);
140
}
141
142
143
/*
144
* 'cupsdClosePipe()' - Close a pipe as necessary.
145
*/
146
147
void
148
cupsdClosePipe(int *fds) /* I - Pipe file descriptors (2) */
149
{
150
/*
151
* Close file descriptors as needed...
152
*/
153
154
if (fds[0] >= 0)
155
{
156
close(fds[0]);
157
fds[0] = -1;
158
}
159
160
if (fds[1] >= 0)
161
{
162
close(fds[1]);
163
fds[1] = -1;
164
}
165
}
166
167
168
/*
169
* 'cupsdCreateConfFile()' - Create a configuration file safely.
170
*/
171
172
cups_file_t * /* O - File pointer */
173
cupsdCreateConfFile(
174
const char *filename, /* I - Filename */
175
mode_t mode) /* I - Permissions */
176
{
177
cups_file_t *fp; /* File pointer */
178
char newfile[1024]; /* filename.N */
179
180
181
snprintf(newfile, sizeof(newfile), "%s.N", filename);
182
if ((fp = cupsFileOpen(newfile, "w")) == NULL)
183
{
184
cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create \"%s\": %s", newfile,
185
strerror(errno));
186
}
187
else
188
{
189
if (!getuid() && fchown(cupsFileNumber(fp), getuid(), Group))
190
cupsdLogMessage(CUPSD_LOG_WARN, "Unable to change group for \"%s\": %s",
191
newfile, strerror(errno));
192
193
if (fchmod(cupsFileNumber(fp), mode))
194
cupsdLogMessage(CUPSD_LOG_WARN,
195
"Unable to change permissions for \"%s\": %s",
196
newfile, strerror(errno));
197
}
198
199
return (fp);
200
}
201
202
203
/*
204
* 'cupsdOpenConfFile()' - Open a configuration file.
205
*
206
* This function looks for "filename.O" if "filename" does not exist and does
207
* a rename as needed.
208
*/
209
210
cups_file_t * /* O - File pointer */
211
cupsdOpenConfFile(const char *filename) /* I - Filename */
212
{
213
cups_file_t *fp; /* File pointer */
214
215
216
if ((fp = cupsFileOpen(filename, "r")) == NULL)
217
{
218
if (errno == ENOENT)
219
{
220
/*
221
* Try opening the backup file...
222
*/
223
224
char oldfile[1024]; /* filename.O */
225
226
snprintf(oldfile, sizeof(oldfile), "%s.O", filename);
227
fp = cupsFileOpen(oldfile, "r");
228
}
229
else
230
cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to open \"%s\": %s", filename,
231
strerror(errno));
232
}
233
234
return (fp);
235
}
236
237
238
/*
239
* 'cupsdOpenPipe()' - Create a pipe which is closed on exec.
240
*/
241
242
int /* O - 0 on success, -1 on error */
243
cupsdOpenPipe(int *fds) /* O - Pipe file descriptors (2) */
244
{
245
/*
246
* Create the pipe...
247
*/
248
249
if (pipe(fds))
250
{
251
fds[0] = -1;
252
fds[1] = -1;
253
254
return (-1);
255
}
256
257
/*
258
* Set the "close on exec" flag on each end of the pipe...
259
*/
260
261
if (fcntl(fds[0], F_SETFD, fcntl(fds[0], F_GETFD) | FD_CLOEXEC))
262
{
263
close(fds[0]);
264
close(fds[1]);
265
266
fds[0] = -1;
267
fds[1] = -1;
268
269
return (-1);
270
}
271
272
if (fcntl(fds[1], F_SETFD, fcntl(fds[1], F_GETFD) | FD_CLOEXEC))
273
{
274
close(fds[0]);
275
close(fds[1]);
276
277
fds[0] = -1;
278
fds[1] = -1;
279
280
return (-1);
281
}
282
283
/*
284
* Return 0 indicating success...
285
*/
286
287
return (0);
288
}
289
290
291
/*
292
* 'cupsdRemoveFile()' - Remove a file securely.
293
*/
294
295
int /* O - 0 on success, -1 on error */
296
cupsdRemoveFile(const char *filename) /* I - File to remove */
297
{
298
#ifdef HAVE_REMOVEFILE
299
/*
300
* See if the file exists...
301
*/
302
303
if (access(filename, 0))
304
return (0);
305
306
cupsdLogMessage(CUPSD_LOG_DEBUG, "Securely removing \"%s\".", filename);
307
308
/*
309
* Remove the file...
310
*/
311
312
return (removefile(filename, NULL, REMOVEFILE_SECURE_1_PASS));
313
314
#else
315
int fd; /* File descriptor */
316
struct stat info; /* File information */
317
char buffer[512]; /* Data buffer */
318
size_t i; /* Looping var */
319
320
321
/*
322
* See if the file exists...
323
*/
324
325
if (access(filename, 0))
326
return (0);
327
328
cupsdLogMessage(CUPSD_LOG_DEBUG, "Securely removing \"%s\".", filename);
329
330
/*
331
* First open the file for writing in exclusive mode.
332
*/
333
334
if ((fd = open(filename, O_WRONLY | O_EXCL)) < 0)
335
return (-1);
336
337
/*
338
* Delete the file now - it will still be around as long as the file is
339
* open...
340
*/
341
342
if (unlink(filename))
343
{
344
close(fd);
345
return (-1);
346
}
347
348
/*
349
* Then get the file size...
350
*/
351
352
if (fstat(fd, &info))
353
{
354
close(fd);
355
return (-1);
356
}
357
358
/*
359
* Overwrite the file with random data.
360
*/
361
362
CUPS_SRAND(time(NULL));
363
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))
367
{
368
close(fd);
369
return (-1);
370
}
371
372
/*
373
* Close the file, which will lead to the actual deletion, and return...
374
*/
375
376
return (close(fd));
377
#endif /* HAVE_REMOVEFILE */
378
}
379
380
381
/*
382
* 'cupsdUnlinkOrRemoveFile()' - Unlink or securely remove a file depending
383
* on the configuration.
384
*/
385
386
int /* O - 0 on success, -1 on error */
387
cupsdUnlinkOrRemoveFile(
388
const char *filename) /* I - Filename */
389
{
390
if (Classification)
391
return (cupsdRemoveFile(filename));
392
else
393
return (unlink(filename));
394
}
395
396
397
#ifndef HAVE_REMOVEFILE
398
/*
399
* 'overwrite_data()' - Overwrite the data in a file.
400
*/
401
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 */
407
{
408
int bytes; /* Bytes to write/written */
409
410
411
/*
412
* Start at the beginning of the file...
413
*/
414
415
if (lseek(fd, 0, SEEK_SET) < 0)
416
return (-1);
417
418
/*
419
* Fill the file with the provided data...
420
*/
421
422
while (filesize > 0)
423
{
424
if (filesize > bufsize)
425
bytes = bufsize;
426
else
427
bytes = filesize;
428
429
if ((bytes = write(fd, buffer, (size_t)bytes)) < 0)
430
return (-1);
431
432
filesize -= bytes;
433
}
434
435
/*
436
* Force the changes to disk...
437
*/
438
439
return (fsync(fd));
440
}
441
#endif /* HAVE_REMOVEFILE */
442
443