1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 1997 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 /* 31 * University Copyright- Copyright (c) 1982, 1986, 1988 32 * The Regents of the University of California 33 * All Rights Reserved 34 * 35 * University Acknowledgment- Portions of this document are derived from 36 * software developed by the University of California, Berkeley, and its 37 * contributors. 38 */ 39 40 /*LINTLIBRARY*/ 41 42 /* 43 * Scan the directory dirname calling select to make a list of selected 44 * directory entries then sort using qsort and compare routine dcomp. 45 * Returns the number of entries and a pointer to a list of pointers to 46 * struct direct (through namelist). Returns -1 if there were any errors. 47 */ 48 49 #include <sys/types.h> 50 #include <sys/stat.h> 51 #include <sys/dir.h> 52 #include <errno.h> 53 #include <limits.h> 54 #include <stdlib.h> 55 #include <string.h> 56 57 /* 58 * The macro DIRSIZ(dp) gives an amount of space required to represent 59 * a directory entry. For any directory entry dp->d_reclen >= DIRSIZ(dp). 60 * Specific filesystem types may use this use this macro to construct the value 61 * for d_reclen. 62 */ 63 #undef DIRSIZ 64 #define DIRSIZ(dp) \ 65 ((sizeof (struct direct) - sizeof ((dp)->d_name) + \ 66 (strlen((dp)->d_name)+1) + 3) & ~3) 67 68 #if !defined(_LP64) 69 int 70 scandir64(char *dirname, struct direct64 *(*namelist[]), 71 int (*select)(struct direct64 *), 72 int (*dcomp)(struct direct64 **, struct direct64 **)) 73 { 74 struct direct64 *d, *p, **names; 75 int nitems; 76 char *cp1, *cp2; 77 struct stat64 stb; 78 long arraysz; 79 DIR *dirp; 80 81 if ((dirp = opendir(dirname)) == NULL) 82 return (-1); 83 if (fstat64(dirp->dd_fd, &stb) < 0) 84 return (-1); 85 86 /* 87 * estimate the array size by taking the size of the directory file 88 * and dividing it by a multiple of the minimum size entry. 89 */ 90 arraysz = (stb.st_size / 24); 91 names = (struct direct64 **)malloc(arraysz * 92 sizeof (struct direct64 *)); 93 if (names == NULL) 94 return (-1); 95 96 nitems = 0; 97 while ((d = readdir64(dirp)) != NULL) { 98 if (select != NULL && !(*select)(d)) 99 continue; /* just selected names */ 100 /* 101 * Make a minimum size copy of the data 102 */ 103 p = (struct direct64 *)malloc(DIRSIZ64(d)); 104 if (p == NULL) 105 return (-1); 106 p->d_ino = d->d_ino; 107 p->d_reclen = d->d_reclen; 108 p->d_namlen = d->d_namlen; 109 for (cp1 = p->d_name, cp2 = d->d_name; *cp1++ = *cp2++; ) 110 ; 111 /* 112 * Check to make sure the array has space left and 113 * realloc the maximum size. 114 */ 115 if (++nitems >= arraysz) { 116 if (fstat64(dirp->dd_fd, &stb) < 0) 117 return (-1); /* just might have grown */ 118 arraysz = stb.st_size / 12; 119 names = (struct direct64 **)realloc((char *)names, 120 arraysz * sizeof (struct direct64 *)); 121 if (names == NULL) 122 return (-1); 123 } 124 names[nitems-1] = p; 125 } 126 (void) closedir(dirp); 127 if (nitems && dcomp != NULL) 128 qsort(names, nitems, sizeof (struct direct64 *), 129 (int(*)(const void *, const void *)) dcomp); 130 *namelist = names; 131 return (nitems); 132 } 133 #endif 134 135 136 int 137 scandir(char *dirname, struct direct *(*namelist[]), 138 int (*select)(struct direct *), 139 int (*dcomp)(struct direct **, struct direct **)) 140 { 141 struct direct *d, *p, **names; 142 int nitems; 143 char *cp1, *cp2; 144 struct stat64 stb; 145 long arraysz; 146 DIR *dirp; 147 148 if ((dirp = opendir(dirname)) == NULL) 149 return (-1); 150 if (fstat64(dirp->dd_fd, &stb) < 0) 151 return (-1); 152 /* 153 * estimate the array size by taking the size of the directory file 154 * and dividing it by a multiple of the minimum size entry. 155 */ 156 if (stb.st_size > SSIZE_MAX) { 157 errno = EOVERFLOW; 158 return (-1); 159 } 160 arraysz = (stb.st_size / 24); 161 162 names = (struct direct **)malloc(arraysz * sizeof (struct direct *)); 163 if (names == NULL) 164 return (-1); 165 166 nitems = 0; 167 while ((d = readdir(dirp)) != NULL) { 168 if (select != NULL && !(*select)(d)) 169 continue; /* just selected names */ 170 /* 171 * Make a minimum size copy of the data 172 */ 173 p = (struct direct *)malloc(DIRSIZ(d)); 174 if (p == NULL) 175 return (-1); 176 p->d_ino = d->d_ino; 177 p->d_reclen = d->d_reclen; 178 p->d_namlen = d->d_namlen; 179 for (cp1 = p->d_name, cp2 = d->d_name; *cp1++ = *cp2++; ) 180 ; 181 /* 182 * Check to make sure the array has space left and 183 * realloc the maximum size. 184 */ 185 if (++nitems >= arraysz) { 186 if (fstat64(dirp->dd_fd, &stb) < 0) 187 return (-1); /* just might have grown */ 188 arraysz = stb.st_size / 12; 189 names = (struct direct **)realloc((char *)names, 190 arraysz * sizeof (struct direct *)); 191 if (names == NULL) 192 return (-1); 193 } 194 names[nitems-1] = p; 195 } 196 (void) closedir(dirp); 197 if (nitems && dcomp != NULL) 198 qsort(names, nitems, sizeof (struct direct *), 199 (int(*)(const void *, const void *)) dcomp); 200 *namelist = names; 201 return (nitems); 202 } 203 204 /* 205 * Alphabetic order comparison routine for those who want it. 206 */ 207 int 208 alphasort(struct direct **d1, struct direct **d2) 209 { 210 return (strcmp((*d1)->d_name, (*d2)->d_name)); 211 } 212 213 #if !defined(_LP64) 214 int 215 alphasort64(struct direct64 **d1, struct direct64 **d2) 216 { 217 return (strcmp((*d1)->d_name, (*d2)->d_name)); 218 } 219 #endif 220