]>
Commit | Line | Data |
---|---|---|
ef416fc2 | 1 | /* |
f2d18633 | 2 | * "$Id$" |
ef416fc2 | 3 | * |
71e16022 | 4 | * Directory routines for CUPS. |
ef416fc2 | 5 | * |
6 | * This set of APIs abstracts enumeration of directory entries. | |
7 | * | |
f3c17241 | 8 | * Copyright 2007-2012 by Apple Inc. |
ef416fc2 | 9 | * Copyright 1997-2005 by Easy Software Products, all rights reserved. |
10 | * | |
11 | * These coded instructions, statements, and computer programs are the | |
bc44d920 | 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/". | |
ef416fc2 | 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 | ||
71e16022 MS |
34 | #include "string-private.h" |
35 | #include "debug-private.h" | |
ef416fc2 | 36 | #include "dir.h" |
ef416fc2 | 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 | ||
536bc2c6 | 74 | val = ft.dwLowDateTime + ((ULONGLONG)ft.dwHighDateTime << 32); |
ef416fc2 | 75 | return ((time_t)(val / 10000000 - 11644732800)); |
76 | } | |
77 | ||
78 | ||
79 | /* | |
80 | * 'cupsDirClose()' - Close a directory. | |
5a738aea | 81 | * |
f3c17241 | 82 | * @since CUPS 1.2/OS X 10.5@ |
ef416fc2 | 83 | */ |
84 | ||
85 | void | |
5a738aea | 86 | cupsDirClose(cups_dir_t *dp) /* I - Directory pointer */ |
ef416fc2 | 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. | |
5a738aea | 112 | * |
f3c17241 | 113 | * @since CUPS 1.2/OS X 10.5@ |
ef416fc2 | 114 | */ |
115 | ||
5a738aea | 116 | cups_dir_t * /* O - Directory pointer or @code NULL@ if the directory could not be opened. */ |
ef416fc2 | 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. | |
5a738aea | 155 | * |
f3c17241 | 156 | * @since CUPS 1.2/OS X 10.5@ |
ef416fc2 | 157 | */ |
158 | ||
5a738aea MS |
159 | cups_dentry_t * /* O - Directory entry or @code NULL@ if there are no more */ |
160 | cupsDirRead(cups_dir_t *dp) /* I - Directory pointer */ | |
ef416fc2 | 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); | |
7cf5915e | 203 | dp->entry.fileinfo.st_size = entry.nFileSizeLow + ((unsigned long long)entry.nFileSizeHigh << 32); |
ef416fc2 | 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. | |
5a738aea | 215 | * |
f3c17241 | 216 | * @since CUPS 1.2/OS X 10.5@ |
ef416fc2 | 217 | */ |
218 | ||
219 | void | |
5a738aea | 220 | cupsDirRewind(cups_dir_t *dp) /* I - Directory pointer */ |
ef416fc2 | 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. | |
5a738aea | 265 | * |
f3c17241 | 266 | * @since CUPS 1.2/OS X 10.5@ |
ef416fc2 | 267 | */ |
268 | ||
269 | void | |
5a738aea | 270 | cupsDirClose(cups_dir_t *dp) /* I - Directory pointer */ |
ef416fc2 | 271 | { |
e07d4801 | 272 | DEBUG_printf(("cupsDirClose(dp=%p)", dp)); |
ef416fc2 | 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. | |
5a738aea | 292 | * |
f3c17241 | 293 | * @since CUPS 1.2/OS X 10.5@ |
ef416fc2 | 294 | */ |
295 | ||
5a738aea | 296 | cups_dir_t * /* O - Directory pointer or @code NULL@ if the directory could not be opened. */ |
ef416fc2 | 297 | cupsDirOpen(const char *directory) /* I - Directory name */ |
298 | { | |
299 | cups_dir_t *dp; /* Directory */ | |
300 | ||
301 | ||
e07d4801 | 302 | DEBUG_printf(("cupsDirOpen(directory=\"%s\")", directory)); |
ef416fc2 | 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. | |
5a738aea | 346 | * |
f3c17241 | 347 | * @since CUPS 1.2/OS X 10.5@ |
ef416fc2 | 348 | */ |
349 | ||
5a738aea MS |
350 | cups_dentry_t * /* O - Directory entry or @code NULL@ when there are no more */ |
351 | cupsDirRead(cups_dir_t *dp) /* I - Directory pointer */ | |
ef416fc2 | 352 | { |
ef416fc2 | 353 | struct dirent *entry; /* Pointer to entry */ |
354 | char filename[1024]; /* Full filename */ | |
2abf387c | 355 | # ifdef HAVE_PTHREAD_H |
356 | char buffer[sizeof(struct dirent) + 1024]; | |
357 | /* Directory entry buffer */ | |
358 | # endif /* HAVE_PTHREAD_H */ | |
ef416fc2 | 359 | |
360 | ||
e07d4801 | 361 | DEBUG_printf(("2cupsDirRead(dp=%p)", dp)); |
ef416fc2 | 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 | ||
07725fee | 374 | for (;;) |
ef416fc2 | 375 | { |
2abf387c | 376 | # ifdef HAVE_PTHREAD_H |
377 | /* | |
378 | * Read the next entry using the reentrant version of readdir... | |
379 | */ | |
380 | ||
ef416fc2 | 381 | if (readdir_r(dp->dir, (struct dirent *)buffer, &entry)) |
382 | { | |
e07d4801 | 383 | DEBUG_printf(("3cupsDirRead: readdir_r() failed - %s\n", strerror(errno))); |
ef416fc2 | 384 | return (NULL); |
385 | } | |
386 | ||
387 | if (!entry) | |
388 | { | |
e07d4801 | 389 | DEBUG_puts("3cupsDirRead: readdir_r() returned a NULL pointer!"); |
ef416fc2 | 390 | return (NULL); |
391 | } | |
392 | ||
e07d4801 MS |
393 | DEBUG_printf(("4cupsDirRead: readdir_r() returned \"%s\"...", |
394 | entry->d_name)); | |
ef416fc2 | 395 | |
2abf387c | 396 | # else |
397 | /* | |
398 | * Read the next entry using the original version of readdir... | |
399 | */ | |
400 | ||
401 | if ((entry = readdir(dp->dir)) == NULL) | |
402 | { | |
e07d4801 | 403 | DEBUG_puts("3cupsDirRead: readdir() returned a NULL pointer!"); |
2abf387c | 404 | return (NULL); |
405 | } | |
406 | ||
e07d4801 | 407 | DEBUG_printf(("4cupsDirRead: readdir() returned \"%s\"...", entry->d_name)); |
2abf387c | 408 | |
409 | # endif /* HAVE_PTHREAD_H */ | |
410 | ||
411 | /* | |
412 | * Skip "." and ".."... | |
413 | */ | |
414 | ||
07725fee | 415 | if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) |
416 | continue; | |
ef416fc2 | 417 | |
07725fee | 418 | /* |
419 | * Copy the name over and get the file information... | |
420 | */ | |
ef416fc2 | 421 | |
07725fee | 422 | strlcpy(dp->entry.filename, entry->d_name, sizeof(dp->entry.filename)); |
ef416fc2 | 423 | |
07725fee | 424 | snprintf(filename, sizeof(filename), "%s/%s", dp->directory, entry->d_name); |
ef416fc2 | 425 | |
07725fee | 426 | if (stat(filename, &(dp->entry.fileinfo))) |
427 | { | |
e07d4801 | 428 | DEBUG_printf(("3cupsDirRead: stat() failed for \"%s\" - %s...", filename, |
07725fee | 429 | strerror(errno))); |
430 | continue; | |
431 | } | |
432 | ||
433 | /* | |
434 | * Return the entry... | |
435 | */ | |
436 | ||
437 | return (&(dp->entry)); | |
438 | } | |
ef416fc2 | 439 | } |
440 | ||
441 | ||
442 | /* | |
443 | * 'cupsDirRewind()' - Rewind to the start of the directory. | |
5a738aea | 444 | * |
f3c17241 | 445 | * @since CUPS 1.2/OS X 10.5@ |
ef416fc2 | 446 | */ |
447 | ||
448 | void | |
5a738aea | 449 | cupsDirRewind(cups_dir_t *dp) /* I - Directory pointer */ |
ef416fc2 | 450 | { |
e07d4801 | 451 | DEBUG_printf(("cupsDirRewind(dp=%p)", dp)); |
ef416fc2 | 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 | /* | |
f2d18633 | 471 | * End of "$Id$". |
ef416fc2 | 472 | */ |