]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/dir.c
04706d467500cd636715685ca9dc06d5d0e41b61
[thirdparty/cups.git] / cups / dir.c
1 /*
2 * "$Id$"
3 *
4 * Directory routines for CUPS.
5 *
6 * This set of APIs abstracts enumeration of directory entries.
7 *
8 * Copyright 2007-2012 by Apple Inc.
9 * Copyright 1997-2005 by Easy Software Products, all rights reserved.
10 *
11 * These coded instructions, statements, and computer programs are the
12 * property of Apple Inc. and are protected by Federal copyright
13 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
14 * which should have been included with this file. If this file is
15 * file is missing or damaged, see the license at "http://www.cups.org/".
16 *
17 * Contents:
18 *
19 * _cups_dir_time() - Convert a FILETIME value to a UNIX time value.
20 * cupsDirClose() - Close a directory.
21 * cupsDirOpen() - Open a directory.
22 * cupsDirRead() - Read the next directory entry.
23 * cupsDirRewind() - Rewind to the start of the directory.
24 * cupsDirClose() - Close a directory.
25 * cupsDirOpen() - Open a directory.
26 * cupsDirRead() - Read the next directory entry.
27 * cupsDirRewind() - Rewind to the start of the directory.
28 */
29
30 /*
31 * Include necessary headers...
32 */
33
34 #include "string-private.h"
35 #include "debug-private.h"
36 #include "dir.h"
37
38
39 /*
40 * Windows implementation...
41 */
42
43 #ifdef WIN32
44 # include <windows.h>
45
46 /*
47 * Types and structures...
48 */
49
50 struct _cups_dir_s /**** Directory data structure ****/
51 {
52 char directory[1024]; /* Directory filename */
53 HANDLE dir; /* Directory handle */
54 cups_dentry_t entry; /* Directory entry */
55 };
56
57
58 /*
59 * '_cups_dir_time()' - Convert a FILETIME value to a UNIX time value.
60 */
61
62 time_t /* O - UNIX time */
63 _cups_dir_time(FILETIME ft) /* I - File time */
64 {
65 ULONGLONG val; /* File time in 0.1 usecs */
66
67
68 /*
69 * Convert file time (1/10 microseconds since Jan 1, 1601) to UNIX
70 * time (seconds since Jan 1, 1970). There are 11,644,732,800 seconds
71 * between them...
72 */
73
74 val = ft.dwLowDateTime + ((ULONGLONG)ft.dwHighDateTime << 32);
75 return ((time_t)(val / 10000000 - 11644732800));
76 }
77
78
79 /*
80 * 'cupsDirClose()' - Close a directory.
81 *
82 * @since CUPS 1.2/OS X 10.5@
83 */
84
85 void
86 cupsDirClose(cups_dir_t *dp) /* I - Directory pointer */
87 {
88 /*
89 * Range check input...
90 */
91
92 if (!dp)
93 return;
94
95 /*
96 * Close an open directory handle...
97 */
98
99 if (dp->dir != INVALID_HANDLE_VALUE)
100 FindClose(dp->dir);
101
102 /*
103 * Free memory used...
104 */
105
106 free(dp);
107 }
108
109
110 /*
111 * 'cupsDirOpen()' - Open a directory.
112 *
113 * @since CUPS 1.2/OS X 10.5@
114 */
115
116 cups_dir_t * /* O - Directory pointer or @code NULL@ if the directory could not be opened. */
117 cupsDirOpen(const char *directory) /* I - Directory name */
118 {
119 cups_dir_t *dp; /* Directory */
120
121
122 /*
123 * Range check input...
124 */
125
126 if (!directory)
127 return (NULL);
128
129 /*
130 * Allocate memory for the directory structure...
131 */
132
133 dp = (cups_dir_t *)calloc(1, sizeof(cups_dir_t));
134 if (!dp)
135 return (NULL);
136
137 /*
138 * Copy the directory name for later use...
139 */
140
141 dp->dir = INVALID_HANDLE_VALUE;
142
143 strlcpy(dp->directory, directory, sizeof(dp->directory));
144
145 /*
146 * Return the new directory structure...
147 */
148
149 return (dp);
150 }
151
152
153 /*
154 * 'cupsDirRead()' - Read the next directory entry.
155 *
156 * @since CUPS 1.2/OS X 10.5@
157 */
158
159 cups_dentry_t * /* O - Directory entry or @code NULL@ if there are no more */
160 cupsDirRead(cups_dir_t *dp) /* I - Directory pointer */
161 {
162 WIN32_FIND_DATA entry; /* Directory entry data */
163
164
165 /*
166 * Range check input...
167 */
168
169 if (!dp)
170 return (NULL);
171
172 /*
173 * See if we have already started finding files...
174 */
175
176 if (dp->dir == INVALID_HANDLE_VALUE)
177 {
178 /*
179 * No, find the first file...
180 */
181
182 dp->dir = FindFirstFile(dp->directory, &entry);
183 if (dp->dir == INVALID_HANDLE_VALUE)
184 return (NULL);
185 }
186 else if (!FindNextFile(dp->dir, &entry))
187 return (NULL);
188
189 /*
190 * Copy the name over and convert the file information...
191 */
192
193 strlcpy(dp->entry.filename, entry.cFileName, sizeof(dp->entry.filename));
194
195 if (entry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
196 dp->entry.fileinfo.st_mode = 0755 | S_IFDIR;
197 else
198 dp->entry.fileinfo.st_mode = 0644;
199
200 dp->entry.fileinfo.st_atime = _cups_dir_time(entry.ftLastAccessTime);
201 dp->entry.fileinfo.st_ctime = _cups_dir_time(entry.ftCreationTime);
202 dp->entry.fileinfo.st_mtime = _cups_dir_time(entry.ftLastWriteTime);
203 dp->entry.fileinfo.st_size = entry.nFileSizeLow + ((unsigned long long)entry.nFileSizeHigh << 32);
204
205 /*
206 * Return the entry...
207 */
208
209 return (&(dp->entry));
210 }
211
212
213 /*
214 * 'cupsDirRewind()' - Rewind to the start of the directory.
215 *
216 * @since CUPS 1.2/OS X 10.5@
217 */
218
219 void
220 cupsDirRewind(cups_dir_t *dp) /* I - Directory pointer */
221 {
222 /*
223 * Range check input...
224 */
225
226 if (!dp)
227 return;
228
229 /*
230 * Close an open directory handle...
231 */
232
233 if (dp->dir != INVALID_HANDLE_VALUE)
234 {
235 FindClose(dp->dir);
236 dp->dir = INVALID_HANDLE_VALUE;
237 }
238 }
239
240
241 #else
242
243 /*
244 * POSIX implementation...
245 */
246
247 # include <sys/types.h>
248 # include <dirent.h>
249
250
251 /*
252 * Types and structures...
253 */
254
255 struct _cups_dir_s /**** Directory data structure ****/
256 {
257 char directory[1024]; /* Directory filename */
258 DIR *dir; /* Directory file */
259 cups_dentry_t entry; /* Directory entry */
260 };
261
262
263 /*
264 * 'cupsDirClose()' - Close a directory.
265 *
266 * @since CUPS 1.2/OS X 10.5@
267 */
268
269 void
270 cupsDirClose(cups_dir_t *dp) /* I - Directory pointer */
271 {
272 DEBUG_printf(("cupsDirClose(dp=%p)", (void *)dp));
273
274 /*
275 * Range check input...
276 */
277
278 if (!dp)
279 return;
280
281 /*
282 * Close the directory and free memory...
283 */
284
285 closedir(dp->dir);
286 free(dp);
287 }
288
289
290 /*
291 * 'cupsDirOpen()' - Open a directory.
292 *
293 * @since CUPS 1.2/OS X 10.5@
294 */
295
296 cups_dir_t * /* O - Directory pointer or @code NULL@ if the directory could not be opened. */
297 cupsDirOpen(const char *directory) /* I - Directory name */
298 {
299 cups_dir_t *dp; /* Directory */
300
301
302 DEBUG_printf(("cupsDirOpen(directory=\"%s\")", directory));
303
304 /*
305 * Range check input...
306 */
307
308 if (!directory)
309 return (NULL);
310
311 /*
312 * Allocate memory for the directory structure...
313 */
314
315 dp = (cups_dir_t *)calloc(1, sizeof(cups_dir_t));
316 if (!dp)
317 return (NULL);
318
319 /*
320 * Open the directory...
321 */
322
323 dp->dir = opendir(directory);
324 if (!dp->dir)
325 {
326 free(dp);
327 return (NULL);
328 }
329
330 /*
331 * Copy the directory name for later use...
332 */
333
334 strlcpy(dp->directory, directory, sizeof(dp->directory));
335
336 /*
337 * Return the new directory structure...
338 */
339
340 return (dp);
341 }
342
343
344 /*
345 * 'cupsDirRead()' - Read the next directory entry.
346 *
347 * @since CUPS 1.2/OS X 10.5@
348 */
349
350 cups_dentry_t * /* O - Directory entry or @code NULL@ when there are no more */
351 cupsDirRead(cups_dir_t *dp) /* I - Directory pointer */
352 {
353 struct dirent *entry; /* Pointer to entry */
354 char filename[1024]; /* Full filename */
355 # ifdef HAVE_PTHREAD_H
356 char buffer[sizeof(struct dirent) + 1024];
357 /* Directory entry buffer */
358 # endif /* HAVE_PTHREAD_H */
359
360
361 DEBUG_printf(("2cupsDirRead(dp=%p)", (void *)dp));
362
363 /*
364 * Range check input...
365 */
366
367 if (!dp)
368 return (NULL);
369
370 /*
371 * Try reading an entry that is not "." or ".."...
372 */
373
374 for (;;)
375 {
376 # ifdef HAVE_PTHREAD_H
377 /*
378 * Read the next entry using the reentrant version of readdir...
379 */
380
381 if (readdir_r(dp->dir, (struct dirent *)buffer, &entry))
382 {
383 DEBUG_printf(("3cupsDirRead: readdir_r() failed - %s\n", strerror(errno)));
384 return (NULL);
385 }
386
387 if (!entry)
388 {
389 DEBUG_puts("3cupsDirRead: readdir_r() returned a NULL pointer!");
390 return (NULL);
391 }
392
393 DEBUG_printf(("4cupsDirRead: readdir_r() returned \"%s\"...",
394 entry->d_name));
395
396 # else
397 /*
398 * Read the next entry using the original version of readdir...
399 */
400
401 if ((entry = readdir(dp->dir)) == NULL)
402 {
403 DEBUG_puts("3cupsDirRead: readdir() returned a NULL pointer!");
404 return (NULL);
405 }
406
407 DEBUG_printf(("4cupsDirRead: readdir() returned \"%s\"...", entry->d_name));
408
409 # endif /* HAVE_PTHREAD_H */
410
411 /*
412 * Skip "." and ".."...
413 */
414
415 if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
416 continue;
417
418 /*
419 * Copy the name over and get the file information...
420 */
421
422 strlcpy(dp->entry.filename, entry->d_name, sizeof(dp->entry.filename));
423
424 snprintf(filename, sizeof(filename), "%s/%s", dp->directory, entry->d_name);
425
426 if (stat(filename, &(dp->entry.fileinfo)))
427 {
428 DEBUG_printf(("3cupsDirRead: stat() failed for \"%s\" - %s...", filename,
429 strerror(errno)));
430 continue;
431 }
432
433 /*
434 * Return the entry...
435 */
436
437 return (&(dp->entry));
438 }
439 }
440
441
442 /*
443 * 'cupsDirRewind()' - Rewind to the start of the directory.
444 *
445 * @since CUPS 1.2/OS X 10.5@
446 */
447
448 void
449 cupsDirRewind(cups_dir_t *dp) /* I - Directory pointer */
450 {
451 DEBUG_printf(("cupsDirRewind(dp=%p)", (void *)dp));
452
453 /*
454 * Range check input...
455 */
456
457 if (!dp)
458 return;
459
460 /*
461 * Rewind the directory...
462 */
463
464 rewinddir(dp->dir);
465 }
466
467
468 #endif /* WIN32 */
469
470 /*
471 * End of "$Id$".
472 */