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