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