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