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