• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  * 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
13  * missing or damaged, see the license at "http://www.cups.org/".
14  */
15 
16 /*
17  * Include necessary headers...
18  */
19 
20 #include "string-private.h"
21 #include "debug-private.h"
22 #include "dir.h"
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 */
_cups_dir_time(FILETIME ft)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 
60   val = ft.dwLowDateTime + ((ULONGLONG)ft.dwHighDateTime << 32);
61   return ((time_t)(val / 10000000 - 11644732800));
62 }
63 
64 
65 /*
66  * 'cupsDirClose()' - Close a directory.
67  *
68  * @since CUPS 1.2/macOS 10.5@
69  */
70 
71 void
cupsDirClose(cups_dir_t * dp)72 cupsDirClose(cups_dir_t *dp)		/* I - Directory pointer */
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.
98  *
99  * @since CUPS 1.2/macOS 10.5@
100  */
101 
102 cups_dir_t *				/* O - Directory pointer or @code NULL@ if the directory could not be opened. */
cupsDirOpen(const char * directory)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.
141  *
142  * @since CUPS 1.2/macOS 10.5@
143  */
144 
145 cups_dentry_t *				/* O - Directory entry or @code NULL@ if there are no more */
cupsDirRead(cups_dir_t * dp)146 cupsDirRead(cups_dir_t *dp)		/* I - Directory pointer */
147 {
148   WIN32_FIND_DATAA	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 = FindFirstFileA(dp->directory, &entry);
169     if (dp->dir == INVALID_HANDLE_VALUE)
170       return (NULL);
171   }
172   else if (!FindNextFileA(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);
189   dp->entry.fileinfo.st_size  = entry.nFileSizeLow + ((unsigned long long)entry.nFileSizeHigh << 32);
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.
201  *
202  * @since CUPS 1.2/macOS 10.5@
203  */
204 
205 void
cupsDirRewind(cups_dir_t * dp)206 cupsDirRewind(cups_dir_t *dp)		/* I - Directory pointer */
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.
251  *
252  * @since CUPS 1.2/macOS 10.5@
253  */
254 
255 void
cupsDirClose(cups_dir_t * dp)256 cupsDirClose(cups_dir_t *dp)		/* I - Directory pointer */
257 {
258   DEBUG_printf(("cupsDirClose(dp=%p)", (void *)dp));
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.
278  *
279  * @since CUPS 1.2/macOS 10.5@
280  */
281 
282 cups_dir_t *				/* O - Directory pointer or @code NULL@ if the directory could not be opened. */
cupsDirOpen(const char * directory)283 cupsDirOpen(const char *directory)	/* I - Directory name */
284 {
285   cups_dir_t	*dp;			/* Directory */
286 
287 
288   DEBUG_printf(("cupsDirOpen(directory=\"%s\")", directory));
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.
332  *
333  * @since CUPS 1.2/macOS 10.5@
334  */
335 
336 cups_dentry_t *				/* O - Directory entry or @code NULL@ when there are no more */
cupsDirRead(cups_dir_t * dp)337 cupsDirRead(cups_dir_t *dp)		/* I - Directory pointer */
338 {
339   struct dirent	*entry;			/* Pointer to entry */
340   char		filename[1024];		/* Full filename */
341 
342 
343   DEBUG_printf(("2cupsDirRead(dp=%p)", (void *)dp));
344 
345  /*
346   * Range check input...
347   */
348 
349   if (!dp)
350     return (NULL);
351 
352  /*
353   * Try reading an entry that is not "." or ".."...
354   */
355 
356   for (;;)
357   {
358    /*
359     * Read the next entry...
360     */
361 
362     if ((entry = readdir(dp->dir)) == NULL)
363     {
364       DEBUG_puts("3cupsDirRead: readdir() returned a NULL pointer!");
365       return (NULL);
366     }
367 
368     DEBUG_printf(("4cupsDirRead: readdir() returned \"%s\"...", entry->d_name));
369 
370    /*
371     * Skip "." and ".."...
372     */
373 
374     if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
375       continue;
376 
377    /*
378     * Copy the name over and get the file information...
379     */
380 
381     strlcpy(dp->entry.filename, entry->d_name, sizeof(dp->entry.filename));
382 
383     snprintf(filename, sizeof(filename), "%s/%s", dp->directory, entry->d_name);
384 
385     if (stat(filename, &(dp->entry.fileinfo)))
386     {
387       DEBUG_printf(("3cupsDirRead: stat() failed for \"%s\" - %s...", filename,
388                     strerror(errno)));
389       continue;
390     }
391 
392    /*
393     * Return the entry...
394     */
395 
396     return (&(dp->entry));
397   }
398 }
399 
400 
401 /*
402  * 'cupsDirRewind()' - Rewind to the start of the directory.
403  *
404  * @since CUPS 1.2/macOS 10.5@
405  */
406 
407 void
cupsDirRewind(cups_dir_t * dp)408 cupsDirRewind(cups_dir_t *dp)		/* I - Directory pointer */
409 {
410   DEBUG_printf(("cupsDirRewind(dp=%p)", (void *)dp));
411 
412  /*
413   * Range check input...
414   */
415 
416   if (!dp)
417     return;
418 
419  /*
420   * Rewind the directory...
421   */
422 
423   rewinddir(dp->dir);
424 }
425 #endif /* _WIN32 */
426