]> git.ipfire.org Git - thirdparty/cups.git/blame - cups/dir.c
Merge changes from CUPS 1.4svn-r7282.
[thirdparty/cups.git] / cups / dir.c
CommitLineData
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 *
5a738aea 8 * Copyright 2007-2008 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
52struct _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
64time_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.
5a738aea
MS
83 *
84 * @since CUPS 1.2@
ef416fc2 85 */
86
87void
5a738aea 88cupsDirClose(cups_dir_t *dp) /* I - Directory pointer */
ef416fc2 89{
90 /*
91 * Range check input...
92 */
93
94 if (!dp)
95 return;
96
97 /*
98 * Close an open directory handle...
99 */
100
101 if (dp->dir != INVALID_HANDLE_VALUE)
102 FindClose(dp->dir);
103
104 /*
105 * Free memory used...
106 */
107
108 free(dp);
109}
110
111
112/*
113 * 'cupsDirOpen()' - Open a directory.
5a738aea
MS
114 *
115 * @since CUPS 1.2@
ef416fc2 116 */
117
5a738aea 118cups_dir_t * /* O - Directory pointer or @code NULL@ if the directory could not be opened. */
ef416fc2 119cupsDirOpen(const char *directory) /* I - Directory name */
120{
121 cups_dir_t *dp; /* Directory */
122
123
124 /*
125 * Range check input...
126 */
127
128 if (!directory)
129 return (NULL);
130
131 /*
132 * Allocate memory for the directory structure...
133 */
134
135 dp = (cups_dir_t *)calloc(1, sizeof(cups_dir_t));
136 if (!dp)
137 return (NULL);
138
139 /*
140 * Copy the directory name for later use...
141 */
142
143 dp->dir = INVALID_HANDLE_VALUE;
144
145 strlcpy(dp->directory, directory, sizeof(dp->directory));
146
147 /*
148 * Return the new directory structure...
149 */
150
151 return (dp);
152}
153
154
155/*
156 * 'cupsDirRead()' - Read the next directory entry.
5a738aea
MS
157 *
158 * @since CUPS 1.2@
ef416fc2 159 */
160
5a738aea
MS
161cups_dentry_t * /* O - Directory entry or @code NULL@ if there are no more */
162cupsDirRead(cups_dir_t *dp) /* I - Directory pointer */
ef416fc2 163{
164 WIN32_FIND_DATA entry; /* Directory entry data */
165
166
167 /*
168 * Range check input...
169 */
170
171 if (!dp)
172 return (NULL);
173
174 /*
175 * See if we have already started finding files...
176 */
177
178 if (dp->dir == INVALID_HANDLE_VALUE)
179 {
180 /*
181 * No, find the first file...
182 */
183
184 dp->dir = FindFirstFile(dp->directory, &entry);
185 if (dp->dir == INVALID_HANDLE_VALUE)
186 return (NULL);
187 }
188 else if (!FindNextFile(dp->dir, &entry))
189 return (NULL);
190
191 /*
192 * Copy the name over and convert the file information...
193 */
194
195 strlcpy(dp->entry.filename, entry.cFileName, sizeof(dp->entry.filename));
196
197 if (entry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
198 dp->entry.fileinfo.st_mode = 0755 | S_IFDIR;
199 else
200 dp->entry.fileinfo.st_mode = 0644;
201
202 dp->entry.fileinfo.st_atime = _cups_dir_time(entry.ftLastAccessTime);
203 dp->entry.fileinfo.st_ctime = _cups_dir_time(entry.ftCreationTime);
204 dp->entry.fileinfo.st_mtime = _cups_dir_time(entry.ftLastWriteTime);
205 dp->entry.fileinfo.st_size = entry.nFileSizeLow + (entry.nFileSizeHigh << 32);
206
207 /*
208 * Return the entry...
209 */
210
211 return (&(dp->entry));
212}
213
214
215/*
216 * 'cupsDirRewind()' - Rewind to the start of the directory.
5a738aea
MS
217 *
218 * @since CUPS 1.2@
ef416fc2 219 */
220
221void
5a738aea 222cupsDirRewind(cups_dir_t *dp) /* I - Directory pointer */
ef416fc2 223{
224 /*
225 * Range check input...
226 */
227
228 if (!dp)
229 return;
230
231 /*
232 * Close an open directory handle...
233 */
234
235 if (dp->dir != INVALID_HANDLE_VALUE)
236 {
237 FindClose(dp->dir);
238 dp->dir = INVALID_HANDLE_VALUE;
239 }
240}
241
242
243#else
244
245/*
246 * POSIX implementation...
247 */
248
249# include <sys/types.h>
250# include <dirent.h>
251
252
253/*
254 * Types and structures...
255 */
256
257struct _cups_dir_s /**** Directory data structure ****/
258{
259 char directory[1024]; /* Directory filename */
260 DIR *dir; /* Directory file */
261 cups_dentry_t entry; /* Directory entry */
262};
263
264
265/*
266 * 'cupsDirClose()' - Close a directory.
5a738aea
MS
267 *
268 * @since CUPS 1.2@
ef416fc2 269 */
270
271void
5a738aea 272cupsDirClose(cups_dir_t *dp) /* I - Directory pointer */
ef416fc2 273{
274 DEBUG_printf(("cupsDirClose(dp=%p)\n", dp));
275
276 /*
277 * Range check input...
278 */
279
280 if (!dp)
281 return;
282
283 /*
284 * Close the directory and free memory...
285 */
286
287 closedir(dp->dir);
288 free(dp);
289}
290
291
292/*
293 * 'cupsDirOpen()' - Open a directory.
5a738aea
MS
294 *
295 * @since CUPS 1.2@
ef416fc2 296 */
297
5a738aea 298cups_dir_t * /* O - Directory pointer or @code NULL@ if the directory could not be opened. */
ef416fc2 299cupsDirOpen(const char *directory) /* I - Directory name */
300{
301 cups_dir_t *dp; /* Directory */
302
303
304 DEBUG_printf(("cupsDirOpen(directory=\"%s\")\n", directory));
305
306 /*
307 * Range check input...
308 */
309
310 if (!directory)
311 return (NULL);
312
313 /*
314 * Allocate memory for the directory structure...
315 */
316
317 dp = (cups_dir_t *)calloc(1, sizeof(cups_dir_t));
318 if (!dp)
319 return (NULL);
320
321 /*
322 * Open the directory...
323 */
324
325 dp->dir = opendir(directory);
326 if (!dp->dir)
327 {
328 free(dp);
329 return (NULL);
330 }
331
332 /*
333 * Copy the directory name for later use...
334 */
335
336 strlcpy(dp->directory, directory, sizeof(dp->directory));
337
338 /*
339 * Return the new directory structure...
340 */
341
342 return (dp);
343}
344
345
346/*
347 * 'cupsDirRead()' - Read the next directory entry.
5a738aea
MS
348 *
349 * @since CUPS 1.2@
ef416fc2 350 */
351
5a738aea
MS
352cups_dentry_t * /* O - Directory entry or @code NULL@ when there are no more */
353cupsDirRead(cups_dir_t *dp) /* I - Directory pointer */
ef416fc2 354{
ef416fc2 355 struct dirent *entry; /* Pointer to entry */
356 char filename[1024]; /* Full filename */
2abf387c 357# ifdef HAVE_PTHREAD_H
358 char buffer[sizeof(struct dirent) + 1024];
359 /* Directory entry buffer */
360# endif /* HAVE_PTHREAD_H */
ef416fc2 361
362
363 DEBUG_printf(("cupsDirRead(dp=%p)\n", dp));
364
365 /*
366 * Range check input...
367 */
368
369 if (!dp)
370 return (NULL);
371
372 /*
373 * Try reading an entry that is not "." or ".."...
374 */
375
07725fee 376 for (;;)
ef416fc2 377 {
2abf387c 378# ifdef HAVE_PTHREAD_H
379 /*
380 * Read the next entry using the reentrant version of readdir...
381 */
382
ef416fc2 383 if (readdir_r(dp->dir, (struct dirent *)buffer, &entry))
384 {
385 DEBUG_printf((" readdir_r() failed - %s\n", strerror(errno)));
386 return (NULL);
387 }
388
389 if (!entry)
390 {
391 DEBUG_puts(" readdir_r() returned a NULL pointer!");
392 return (NULL);
393 }
394
395 DEBUG_printf((" readdir_r() returned \"%s\"...\n", entry->d_name));
ef416fc2 396
2abf387c 397# else
398 /*
399 * Read the next entry using the original version of readdir...
400 */
401
402 if ((entry = readdir(dp->dir)) == NULL)
403 {
404 DEBUG_puts(" readdir() returned a NULL pointer!");
405 return (NULL);
406 }
407
408 DEBUG_printf((" readdir() returned \"%s\"...\n", entry->d_name));
409
410# endif /* HAVE_PTHREAD_H */
411
412 /*
413 * Skip "." and ".."...
414 */
415
07725fee 416 if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
417 continue;
ef416fc2 418
07725fee 419 /*
420 * Copy the name over and get the file information...
421 */
ef416fc2 422
07725fee 423 strlcpy(dp->entry.filename, entry->d_name, sizeof(dp->entry.filename));
ef416fc2 424
07725fee 425 snprintf(filename, sizeof(filename), "%s/%s", dp->directory, entry->d_name);
ef416fc2 426
07725fee 427 if (stat(filename, &(dp->entry.fileinfo)))
428 {
429 DEBUG_printf((" stat() failed for \"%s\" - %s...\n", filename,
430 strerror(errno)));
431 continue;
432 }
433
434 /*
435 * Return the entry...
436 */
437
438 return (&(dp->entry));
439 }
ef416fc2 440}
441
442
443/*
444 * 'cupsDirRewind()' - Rewind to the start of the directory.
5a738aea
MS
445 *
446 * @since CUPS 1.2@
ef416fc2 447 */
448
449void
5a738aea 450cupsDirRewind(cups_dir_t *dp) /* I - Directory pointer */
ef416fc2 451{
452 DEBUG_printf(("cupsDirRewind(dp=%p)\n", dp));
453
454 /*
455 * Range check input...
456 */
457
458 if (!dp)
459 return;
460
461 /*
462 * Rewind the directory...
463 */
464
465 rewinddir(dp->dir);
466}
467
468
469#endif /* WIN32 */
470
471/*
f7faf1f5 472 * End of "$Id$".
ef416fc2 473 */