1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1997,2008 Oracle. All rights reserved. 5 * 6 * $Id: os_dir.c,v 12.18 2008/01/31 17:34:17 bostic Exp $ 7 */ 8 9#include "db_config.h" 10 11#define __INCLUDE_DIRECTORY 1 12#include "db_int.h" 13 14/* 15 * __os_dirlist -- 16 * Return a list of the files in a directory. 17 * 18 * PUBLIC: int __os_dirlist __P((ENV *, const char *, int, char ***, int *)); 19 */ 20int 21__os_dirlist(env, dir, returndir, namesp, cntp) 22 ENV *env; 23 const char *dir; 24 int returndir, *cntp; 25 char ***namesp; 26{ 27 DB_ENV *dbenv; 28 struct dirent *dp; 29 DIR *dirp; 30 struct stat sb; 31 int arraysz, cnt, ret; 32 char **names, buf[DB_MAXPATHLEN]; 33 34 *namesp = NULL; 35 *cntp = 0; 36 37 dbenv = env == NULL ? NULL : env->dbenv; 38 39 if (dbenv != NULL && 40 FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS | DB_VERB_FILEOPS_ALL)) 41 __db_msg(env, "fileops: directory list %s", dir); 42 43 if (DB_GLOBAL(j_dirlist) != NULL) 44 return (DB_GLOBAL(j_dirlist)(dir, namesp, cntp)); 45 46 if ((dirp = opendir(CHAR_STAR_CAST dir)) == NULL) 47 return (__os_get_errno()); 48 names = NULL; 49 for (arraysz = cnt = 0; (dp = readdir(dirp)) != NULL;) { 50 snprintf(buf, sizeof(buf), "%s/%s", dir, dp->d_name); 51 52 RETRY_CHK(stat(buf, &sb), ret); 53 if (ret != 0) { 54 ret = __os_posix_err(ret); 55 goto err; 56 } 57 58 /* 59 * We return regular files, and optionally return directories 60 * (except for dot and dot-dot). 61 * 62 * Shared memory files are of a different type on QNX, and we 63 * return those as well. 64 */ 65#ifdef HAVE_QNX 66 if (!S_ISREG(sb.st_mode) && !S_TYPEISSHM(&sb)) { 67#else 68 if (!S_ISREG(sb.st_mode)) { 69#endif 70 if (!returndir || !S_ISDIR(sb.st_mode)) 71 continue; 72 if (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || 73 (dp->d_name[1] == '.' && dp->d_name[2] == '\0'))) 74 continue; 75 } 76 77 if (cnt >= arraysz) { 78 arraysz += 100; 79 if ((ret = __os_realloc(env, 80 (u_int)arraysz * sizeof(names[0]), &names)) != 0) 81 goto err; 82 } 83 if ((ret = __os_strdup(env, dp->d_name, &names[cnt])) != 0) 84 goto err; 85 cnt++; 86 } 87 (void)closedir(dirp); 88 89 *namesp = names; 90 *cntp = cnt; 91 return (0); 92 93err: if (names != NULL) 94 __os_dirfree(env, names, cnt); 95 if (dirp != NULL) 96 (void)closedir(dirp); 97 return (ret); 98} 99 100/* 101 * __os_dirfree -- 102 * Free the list of files. 103 * 104 * PUBLIC: void __os_dirfree __P((ENV *, char **, int)); 105 */ 106void 107__os_dirfree(env, names, cnt) 108 ENV *env; 109 char **names; 110 int cnt; 111{ 112 if (DB_GLOBAL(j_dirfree) != NULL) 113 DB_GLOBAL(j_dirfree)(names, cnt); 114 else { 115 while (cnt > 0) 116 __os_free(env, names[--cnt]); 117 __os_free(env, names); 118 } 119} 120