121357Sdist /* 221357Sdist * Copyright (c) 1983 Regents of the University of California. 334790Sbostic * All rights reserved. 434790Sbostic * 534790Sbostic * Redistribution and use in source and binary forms are permitted 634790Sbostic * provided that the above copyright notice and this paragraph are 734790Sbostic * duplicated in all such forms and that any documentation, 834790Sbostic * advertising materials, and other materials related to such 934790Sbostic * distribution and use acknowledge that the software was developed 1034790Sbostic * by the University of California, Berkeley. The name of the 1134790Sbostic * University may not be used to endorse or promote products derived 1234790Sbostic * from this software without specific prior written permission. 1334790Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434790Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534790Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1621357Sdist */ 1721357Sdist 1826582Sdonn #if defined(LIBC_SCCS) && !defined(lint) 19*36558Smckusick static char sccsid[] = "@(#)scandir.c 5.5 (Berkeley) 01/16/89"; 2034790Sbostic #endif /* LIBC_SCCS and not lint */ 2113582Ssam 229609Sralph /* 239609Sralph * Scan the directory dirname calling select to make a list of selected 249609Sralph * directory entries then sort using qsort and compare routine dcomp. 259609Sralph * Returns the number of entries and a pointer to a list of pointers to 2636545Smckusick * struct dirent (through namelist). Returns -1 if there were any errors. 279609Sralph */ 289609Sralph 299609Sralph #include <sys/types.h> 309609Sralph #include <sys/stat.h> 3136545Smckusick #include <dirent.h> 329609Sralph 33*36558Smckusick /* 34*36558Smckusick * The DIRSIZ macro gives the minimum record length which will hold 35*36558Smckusick * the directory entry. This requires the amount of space in struct dirent 36*36558Smckusick * without the d_name field, plus enough space for the name with a terminating 37*36558Smckusick * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary. 38*36558Smckusick */ 39*36558Smckusick #undef DIRSIZ 40*36558Smckusick #define DIRSIZ(dp) \ 41*36558Smckusick ((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3)) 42*36558Smckusick 439609Sralph scandir(dirname, namelist, select, dcomp) 449609Sralph char *dirname; 4536545Smckusick struct dirent *(*namelist[]); 469609Sralph int (*select)(), (*dcomp)(); 479609Sralph { 4836545Smckusick register struct dirent *d, *p, **names; 499609Sralph register int nitems; 509609Sralph register char *cp1, *cp2; 519609Sralph struct stat stb; 529609Sralph long arraysz; 539609Sralph DIR *dirp; 549609Sralph 559609Sralph if ((dirp = opendir(dirname)) == NULL) 569609Sralph return(-1); 579609Sralph if (fstat(dirp->dd_fd, &stb) < 0) 589609Sralph return(-1); 599609Sralph 609609Sralph /* 619609Sralph * estimate the array size by taking the size of the directory file 629609Sralph * and dividing it by a multiple of the minimum size entry. 639609Sralph */ 649609Sralph arraysz = (stb.st_size / 24); 6536545Smckusick names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *)); 669609Sralph if (names == NULL) 679609Sralph return(-1); 689609Sralph 699609Sralph nitems = 0; 709609Sralph while ((d = readdir(dirp)) != NULL) { 719609Sralph if (select != NULL && !(*select)(d)) 729609Sralph continue; /* just selected names */ 739609Sralph /* 749609Sralph * Make a minimum size copy of the data 759609Sralph */ 7636545Smckusick p = (struct dirent *)malloc(DIRSIZ(d)); 779609Sralph if (p == NULL) 789609Sralph return(-1); 799609Sralph p->d_ino = d->d_ino; 809609Sralph p->d_reclen = d->d_reclen; 819609Sralph p->d_namlen = d->d_namlen; 829609Sralph for (cp1 = p->d_name, cp2 = d->d_name; *cp1++ = *cp2++; ); 839609Sralph /* 849609Sralph * Check to make sure the array has space left and 859609Sralph * realloc the maximum size. 869609Sralph */ 879609Sralph if (++nitems >= arraysz) { 8815661Sralph if (fstat(dirp->dd_fd, &stb) < 0) 8915661Sralph return(-1); /* just might have grown */ 9015661Sralph arraysz = stb.st_size / 12; 9136545Smckusick names = (struct dirent **)realloc((char *)names, 9236545Smckusick arraysz * sizeof(struct dirent *)); 939609Sralph if (names == NULL) 949609Sralph return(-1); 959609Sralph } 969609Sralph names[nitems-1] = p; 979609Sralph } 989609Sralph closedir(dirp); 999609Sralph if (nitems && dcomp != NULL) 10036545Smckusick qsort(names, nitems, sizeof(struct dirent *), dcomp); 1019609Sralph *namelist = names; 1029609Sralph return(nitems); 1039609Sralph } 1049609Sralph 1059609Sralph /* 1069609Sralph * Alphabetic order comparison routine for those who want it. 1079609Sralph */ 1089609Sralph alphasort(d1, d2) 10936545Smckusick struct dirent **d1, **d2; 1109609Sralph { 1119609Sralph return(strcmp((*d1)->d_name, (*d2)->d_name)); 1129609Sralph } 113