/* * Directory routines for CUPS. * * This set of APIs abstracts enumeration of directory entries. * * Copyright 2007-2017 by Apple Inc. * Copyright 1997-2005 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the * property of Apple Inc. and are protected by Federal copyright * law. Distribution and use rights are outlined in the file "LICENSE.txt" * which should have been included with this file. If this file is * missing or damaged, see the license at "http://www.cups.org/". */ /* * Include necessary headers... */ #include "string-private.h" #include "debug-private.h" #include "dir.h" /* * Windows implementation... */ #ifdef WIN32 # include <windows.h> /* * Types and structures... */ struct _cups_dir_s /**** Directory data structure ****/ { char directory[1024]; /* Directory filename */ HANDLE dir; /* Directory handle */ cups_dentry_t entry; /* Directory entry */ }; /* * '_cups_dir_time()' - Convert a FILETIME value to a UNIX time value. */ time_t /* O - UNIX time */ _cups_dir_time(FILETIME ft) /* I - File time */ { ULONGLONG val; /* File time in 0.1 usecs */ /* * Convert file time (1/10 microseconds since Jan 1, 1601) to UNIX * time (seconds since Jan 1, 1970). There are 11,644,732,800 seconds * between them... */ val = ft.dwLowDateTime + ((ULONGLONG)ft.dwHighDateTime << 32); return ((time_t)(val / 10000000 - 11644732800)); } /* * 'cupsDirClose()' - Close a directory. * * @since CUPS 1.2/macOS 10.5@ */ void cupsDirClose(cups_dir_t *dp) /* I - Directory pointer */ { /* * Range check input... */ if (!dp) return; /* * Close an open directory handle... */ if (dp->dir != INVALID_HANDLE_VALUE) FindClose(dp->dir); /* * Free memory used... */ free(dp); } /* * 'cupsDirOpen()' - Open a directory. * * @since CUPS 1.2/macOS 10.5@ */ cups_dir_t * /* O - Directory pointer or @code NULL@ if the directory could not be opened. */ cupsDirOpen(const char *directory) /* I - Directory name */ { cups_dir_t *dp; /* Directory */ /* * Range check input... */ if (!directory) return (NULL); /* * Allocate memory for the directory structure... */ dp = (cups_dir_t *)calloc(1, sizeof(cups_dir_t)); if (!dp) return (NULL); /* * Copy the directory name for later use... */ dp->dir = INVALID_HANDLE_VALUE; strlcpy(dp->directory, directory, sizeof(dp->directory)); /* * Return the new directory structure... */ return (dp); } /* * 'cupsDirRead()' - Read the next directory entry. * * @since CUPS 1.2/macOS 10.5@ */ cups_dentry_t * /* O - Directory entry or @code NULL@ if there are no more */ cupsDirRead(cups_dir_t *dp) /* I - Directory pointer */ { WIN32_FIND_DATA entry; /* Directory entry data */ /* * Range check input... */ if (!dp) return (NULL); /* * See if we have already started finding files... */ if (dp->dir == INVALID_HANDLE_VALUE) { /* * No, find the first file... */ dp->dir = FindFirstFile(dp->directory, &entry); if (dp->dir == INVALID_HANDLE_VALUE) return (NULL); } else if (!FindNextFile(dp->dir, &entry)) return (NULL); /* * Copy the name over and convert the file information... */ strlcpy(dp->entry.filename, entry.cFileName, sizeof(dp->entry.filename)); if (entry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) dp->entry.fileinfo.st_mode = 0755 | S_IFDIR; else dp->entry.fileinfo.st_mode = 0644; dp->entry.fileinfo.st_atime = _cups_dir_time(entry.ftLastAccessTime); dp->entry.fileinfo.st_ctime = _cups_dir_time(entry.ftCreationTime); dp->entry.fileinfo.st_mtime = _cups_dir_time(entry.ftLastWriteTime); dp->entry.fileinfo.st_size = entry.nFileSizeLow + ((unsigned long long)entry.nFileSizeHigh << 32); /* * Return the entry... */ return (&(dp->entry)); } /* * 'cupsDirRewind()' - Rewind to the start of the directory. * * @since CUPS 1.2/macOS 10.5@ */ void cupsDirRewind(cups_dir_t *dp) /* I - Directory pointer */ { /* * Range check input... */ if (!dp) return; /* * Close an open directory handle... */ if (dp->dir != INVALID_HANDLE_VALUE) { FindClose(dp->dir); dp->dir = INVALID_HANDLE_VALUE; } } #else /* * POSIX implementation... */ # include <sys/types.h> # include <dirent.h> /* * Types and structures... */ struct _cups_dir_s /**** Directory data structure ****/ { char directory[1024]; /* Directory filename */ DIR *dir; /* Directory file */ cups_dentry_t entry; /* Directory entry */ }; /* * 'cupsDirClose()' - Close a directory. * * @since CUPS 1.2/macOS 10.5@ */ void cupsDirClose(cups_dir_t *dp) /* I - Directory pointer */ { DEBUG_printf(("cupsDirClose(dp=%p)", (void *)dp)); /* * Range check input... */ if (!dp) return; /* * Close the directory and free memory... */ closedir(dp->dir); free(dp); } /* * 'cupsDirOpen()' - Open a directory. * * @since CUPS 1.2/macOS 10.5@ */ cups_dir_t * /* O - Directory pointer or @code NULL@ if the directory could not be opened. */ cupsDirOpen(const char *directory) /* I - Directory name */ { cups_dir_t *dp; /* Directory */ DEBUG_printf(("cupsDirOpen(directory=\"%s\")", directory)); /* * Range check input... */ if (!directory) return (NULL); /* * Allocate memory for the directory structure... */ dp = (cups_dir_t *)calloc(1, sizeof(cups_dir_t)); if (!dp) return (NULL); /* * Open the directory... */ dp->dir = opendir(directory); if (!dp->dir) { free(dp); return (NULL); } /* * Copy the directory name for later use... */ strlcpy(dp->directory, directory, sizeof(dp->directory)); /* * Return the new directory structure... */ return (dp); } /* * 'cupsDirRead()' - Read the next directory entry. * * @since CUPS 1.2/macOS 10.5@ */ cups_dentry_t * /* O - Directory entry or @code NULL@ when there are no more */ cupsDirRead(cups_dir_t *dp) /* I - Directory pointer */ { struct dirent *entry; /* Pointer to entry */ char filename[1024]; /* Full filename */ DEBUG_printf(("2cupsDirRead(dp=%p)", (void *)dp)); /* * Range check input... */ if (!dp) return (NULL); /* * Try reading an entry that is not "." or ".."... */ for (;;) { /* * Read the next entry... */ if ((entry = readdir(dp->dir)) == NULL) { DEBUG_puts("3cupsDirRead: readdir() returned a NULL pointer!"); return (NULL); } DEBUG_printf(("4cupsDirRead: readdir() returned \"%s\"...", entry->d_name)); /* * Skip "." and ".."... */ if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) continue; /* * Copy the name over and get the file information... */ strlcpy(dp->entry.filename, entry->d_name, sizeof(dp->entry.filename)); snprintf(filename, sizeof(filename), "%s/%s", dp->directory, entry->d_name); if (stat(filename, &(dp->entry.fileinfo))) { DEBUG_printf(("3cupsDirRead: stat() failed for \"%s\" - %s...", filename, strerror(errno))); continue; } /* * Return the entry... */ return (&(dp->entry)); } } /* * 'cupsDirRewind()' - Rewind to the start of the directory. * * @since CUPS 1.2/macOS 10.5@ */ void cupsDirRewind(cups_dir_t *dp) /* I - Directory pointer */ { DEBUG_printf(("cupsDirRewind(dp=%p)", (void *)dp)); /* * Range check input... */ if (!dp) return; /* * Rewind the directory... */ rewinddir(dp->dir); } #endif /* WIN32 */