1 /* 2 * Copyright (c) 1983 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 */ 17 18 #if defined(LIBC_SCCS) && !defined(lint) 19 static char sccsid[] = "@(#)scandir.c 5.3 (Berkeley) 06/18/88"; 20 #endif /* LIBC_SCCS and not lint */ 21 22 /* 23 * Scan the directory dirname calling select to make a list of selected 24 * directory entries then sort using qsort and compare routine dcomp. 25 * Returns the number of entries and a pointer to a list of pointers to 26 * struct direct (through namelist). Returns -1 if there were any errors. 27 */ 28 29 #include <sys/types.h> 30 #include <sys/stat.h> 31 #include <sys/dir.h> 32 33 scandir(dirname, namelist, select, dcomp) 34 char *dirname; 35 struct direct *(*namelist[]); 36 int (*select)(), (*dcomp)(); 37 { 38 register struct direct *d, *p, **names; 39 register int nitems; 40 register char *cp1, *cp2; 41 struct stat stb; 42 long arraysz; 43 DIR *dirp; 44 45 if ((dirp = opendir(dirname)) == NULL) 46 return(-1); 47 if (fstat(dirp->dd_fd, &stb) < 0) 48 return(-1); 49 50 /* 51 * estimate the array size by taking the size of the directory file 52 * and dividing it by a multiple of the minimum size entry. 53 */ 54 arraysz = (stb.st_size / 24); 55 names = (struct direct **)malloc(arraysz * sizeof(struct direct *)); 56 if (names == NULL) 57 return(-1); 58 59 nitems = 0; 60 while ((d = readdir(dirp)) != NULL) { 61 if (select != NULL && !(*select)(d)) 62 continue; /* just selected names */ 63 /* 64 * Make a minimum size copy of the data 65 */ 66 p = (struct direct *)malloc(DIRSIZ(d)); 67 if (p == NULL) 68 return(-1); 69 p->d_ino = d->d_ino; 70 p->d_reclen = d->d_reclen; 71 p->d_namlen = d->d_namlen; 72 for (cp1 = p->d_name, cp2 = d->d_name; *cp1++ = *cp2++; ); 73 /* 74 * Check to make sure the array has space left and 75 * realloc the maximum size. 76 */ 77 if (++nitems >= arraysz) { 78 if (fstat(dirp->dd_fd, &stb) < 0) 79 return(-1); /* just might have grown */ 80 arraysz = stb.st_size / 12; 81 names = (struct direct **)realloc((char *)names, 82 arraysz * sizeof(struct direct *)); 83 if (names == NULL) 84 return(-1); 85 } 86 names[nitems-1] = p; 87 } 88 closedir(dirp); 89 if (nitems && dcomp != NULL) 90 qsort(names, nitems, sizeof(struct direct *), dcomp); 91 *namelist = names; 92 return(nitems); 93 } 94 95 /* 96 * Alphabetic order comparison routine for those who want it. 97 */ 98 alphasort(d1, d2) 99 struct direct **d1, **d2; 100 { 101 return(strcmp((*d1)->d_name, (*d2)->d_name)); 102 } 103