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