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*36681Sbostic static char sccsid[] = "@(#)scandir.c 5.6 (Berkeley) 02/05/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 3336558Smckusick /* 3436558Smckusick * The DIRSIZ macro gives the minimum record length which will hold 3536558Smckusick * the directory entry. This requires the amount of space in struct dirent 3636558Smckusick * without the d_name field, plus enough space for the name with a terminating 3736558Smckusick * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary. 3836558Smckusick */ 3936558Smckusick #undef DIRSIZ 4036558Smckusick #define DIRSIZ(dp) \ 4136558Smckusick ((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3)) 4236558Smckusick 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 struct stat stb; 519609Sralph long arraysz; 529609Sralph DIR *dirp; 539609Sralph 549609Sralph if ((dirp = opendir(dirname)) == NULL) 559609Sralph return(-1); 569609Sralph if (fstat(dirp->dd_fd, &stb) < 0) 579609Sralph return(-1); 589609Sralph 599609Sralph /* 609609Sralph * estimate the array size by taking the size of the directory file 619609Sralph * and dividing it by a multiple of the minimum size entry. 629609Sralph */ 639609Sralph arraysz = (stb.st_size / 24); 6436545Smckusick names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *)); 659609Sralph if (names == NULL) 669609Sralph return(-1); 679609Sralph 689609Sralph nitems = 0; 699609Sralph while ((d = readdir(dirp)) != NULL) { 709609Sralph if (select != NULL && !(*select)(d)) 719609Sralph continue; /* just selected names */ 729609Sralph /* 739609Sralph * Make a minimum size copy of the data 749609Sralph */ 7536545Smckusick p = (struct dirent *)malloc(DIRSIZ(d)); 769609Sralph if (p == NULL) 779609Sralph return(-1); 789609Sralph p->d_ino = d->d_ino; 799609Sralph p->d_reclen = d->d_reclen; 809609Sralph p->d_namlen = d->d_namlen; 81*36681Sbostic bcopy(d->d_name, p->d_name, p->d_namlen + 1); 829609Sralph /* 839609Sralph * Check to make sure the array has space left and 849609Sralph * realloc the maximum size. 859609Sralph */ 869609Sralph if (++nitems >= arraysz) { 8715661Sralph if (fstat(dirp->dd_fd, &stb) < 0) 8815661Sralph return(-1); /* just might have grown */ 8915661Sralph arraysz = stb.st_size / 12; 9036545Smckusick names = (struct dirent **)realloc((char *)names, 9136545Smckusick arraysz * sizeof(struct dirent *)); 929609Sralph if (names == NULL) 939609Sralph return(-1); 949609Sralph } 959609Sralph names[nitems-1] = p; 969609Sralph } 979609Sralph closedir(dirp); 989609Sralph if (nitems && dcomp != NULL) 9936545Smckusick qsort(names, nitems, sizeof(struct dirent *), dcomp); 1009609Sralph *namelist = names; 1019609Sralph return(nitems); 1029609Sralph } 1039609Sralph 1049609Sralph /* 1059609Sralph * Alphabetic order comparison routine for those who want it. 1069609Sralph */ 1079609Sralph alphasort(d1, d2) 10836545Smckusick struct dirent **d1, **d2; 1099609Sralph { 1109609Sralph return(strcmp((*d1)->d_name, (*d2)->d_name)); 1119609Sralph } 112