2 * Directory routines for CUPS.
4 * This set of APIs abstracts enumeration of directory entries.
6 * Copyright 2007-2012 by Apple Inc.
7 * Copyright 1997-2005 by Easy Software Products, all rights reserved.
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/".
17 * Include necessary headers...
20 #include "string-private.h"
21 #include "debug-private.h"
26 * Windows implementation...
33 * Types and structures...
36 struct _cups_dir_s /**** Directory data structure ****/
38 char directory[1024]; /* Directory filename */
39 HANDLE dir; /* Directory handle */
40 cups_dentry_t entry; /* Directory entry */
45 * '_cups_dir_time()' - Convert a FILETIME value to a UNIX time value.
48 time_t /* O - UNIX time */
49 _cups_dir_time(FILETIME ft) /* I - File time */
51 ULONGLONG val; /* File time in 0.1 usecs */
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
60 val = ft.dwLowDateTime + ((ULONGLONG)ft.dwHighDateTime << 32);
61 return ((time_t)(val / 10000000 - 11644732800));
66 * 'cupsDirClose()' - Close a directory.
68 * @since CUPS 1.2/macOS 10.5@
72 cupsDirClose(cups_dir_t *dp) /* I - Directory pointer */
75 * Range check input...
82 * Close an open directory handle...
85 if (dp->dir != INVALID_HANDLE_VALUE)
97 * 'cupsDirOpen()' - Open a directory.
99 * @since CUPS 1.2/macOS 10.5@
102 cups_dir_t * /* O - Directory pointer or @code NULL@ if the directory could not be opened. */
103 cupsDirOpen(const char *directory) /* I - Directory name */
105 cups_dir_t *dp; /* Directory */
109 * Range check input...
116 * Allocate memory for the directory structure...
119 dp = (cups_dir_t *)calloc(1, sizeof(cups_dir_t));
124 * Copy the directory name for later use...
127 dp->dir = INVALID_HANDLE_VALUE;
129 strlcpy(dp->directory, directory, sizeof(dp->directory));
132 * Return the new directory structure...
140 * 'cupsDirRead()' - Read the next directory entry.
142 * @since CUPS 1.2/macOS 10.5@
145 cups_dentry_t * /* O - Directory entry or @code NULL@ if there are no more */
146 cupsDirRead(cups_dir_t *dp) /* I - Directory pointer */
148 WIN32_FIND_DATA entry; /* Directory entry data */
152 * Range check input...
159 * See if we have already started finding files...
162 if (dp->dir == INVALID_HANDLE_VALUE)
165 * No, find the first file...
168 dp->dir = FindFirstFile(dp->directory, &entry);
169 if (dp->dir == INVALID_HANDLE_VALUE)
172 else if (!FindNextFile(dp->dir, &entry))
176 * Copy the name over and convert the file information...
179 strlcpy(dp->entry.filename, entry.cFileName, sizeof(dp->entry.filename));
181 if (entry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
182 dp->entry.fileinfo.st_mode = 0755 | S_IFDIR;
184 dp->entry.fileinfo.st_mode = 0644;
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);
192 * Return the entry...
195 return (&(dp->entry));
200 * 'cupsDirRewind()' - Rewind to the start of the directory.
202 * @since CUPS 1.2/macOS 10.5@
206 cupsDirRewind(cups_dir_t *dp) /* I - Directory pointer */
209 * Range check input...
216 * Close an open directory handle...
219 if (dp->dir != INVALID_HANDLE_VALUE)
222 dp->dir = INVALID_HANDLE_VALUE;
230 * POSIX implementation...
233 # include <sys/types.h>
238 * Types and structures...
241 struct _cups_dir_s /**** Directory data structure ****/
243 char directory[1024]; /* Directory filename */
244 DIR *dir; /* Directory file */
245 cups_dentry_t entry; /* Directory entry */
250 * 'cupsDirClose()' - Close a directory.
252 * @since CUPS 1.2/macOS 10.5@
256 cupsDirClose(cups_dir_t *dp) /* I - Directory pointer */
258 DEBUG_printf(("cupsDirClose(dp=%p)", (void *)dp));
261 * Range check input...
268 * Close the directory and free memory...
277 * 'cupsDirOpen()' - Open a directory.
279 * @since CUPS 1.2/macOS 10.5@
282 cups_dir_t * /* O - Directory pointer or @code NULL@ if the directory could not be opened. */
283 cupsDirOpen(const char *directory) /* I - Directory name */
285 cups_dir_t *dp; /* Directory */
288 DEBUG_printf(("cupsDirOpen(directory=\"%s\")", directory));
291 * Range check input...
298 * Allocate memory for the directory structure...
301 dp = (cups_dir_t *)calloc(1, sizeof(cups_dir_t));
306 * Open the directory...
309 dp->dir = opendir(directory);
317 * Copy the directory name for later use...
320 strlcpy(dp->directory, directory, sizeof(dp->directory));
323 * Return the new directory structure...
331 * 'cupsDirRead()' - Read the next directory entry.
333 * @since CUPS 1.2/macOS 10.5@
336 cups_dentry_t * /* O - Directory entry or @code NULL@ when there are no more */
337 cupsDirRead(cups_dir_t *dp) /* I - Directory pointer */
339 struct dirent *entry; /* Pointer to entry */
340 char filename[1024]; /* Full filename */
341 # ifdef HAVE_PTHREAD_H
342 char buffer[sizeof(struct dirent) + 1024];
343 /* Directory entry buffer */
344 # endif /* HAVE_PTHREAD_H */
347 DEBUG_printf(("2cupsDirRead(dp=%p)", (void *)dp));
350 * Range check input...
357 * Try reading an entry that is not "." or ".."...
362 # ifdef HAVE_PTHREAD_H
364 * Read the next entry using the reentrant version of readdir...
367 if (readdir_r(dp->dir, (struct dirent *)buffer, &entry))
369 DEBUG_printf(("3cupsDirRead: readdir_r() failed - %s\n", strerror(errno)));
375 DEBUG_puts("3cupsDirRead: readdir_r() returned a NULL pointer!");
379 DEBUG_printf(("4cupsDirRead: readdir_r() returned \"%s\"...",
384 * Read the next entry using the original version of readdir...
387 if ((entry = readdir(dp->dir)) == NULL)
389 DEBUG_puts("3cupsDirRead: readdir() returned a NULL pointer!");
393 DEBUG_printf(("4cupsDirRead: readdir() returned \"%s\"...", entry->d_name));
395 # endif /* HAVE_PTHREAD_H */
398 * Skip "." and ".."...
401 if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
405 * Copy the name over and get the file information...
408 strlcpy(dp->entry.filename, entry->d_name, sizeof(dp->entry.filename));
410 snprintf(filename, sizeof(filename), "%s/%s", dp->directory, entry->d_name);
412 if (stat(filename, &(dp->entry.fileinfo)))
414 DEBUG_printf(("3cupsDirRead: stat() failed for \"%s\" - %s...", filename,
420 * Return the entry...
423 return (&(dp->entry));
429 * 'cupsDirRewind()' - Rewind to the start of the directory.
431 * @since CUPS 1.2/macOS 10.5@
435 cupsDirRewind(cups_dir_t *dp) /* I - Directory pointer */
437 DEBUG_printf(("cupsDirRewind(dp=%p)", (void *)dp));
440 * Range check input...
447 * Rewind the directory...