121357Sdist /* 2*61111Sbostic * Copyright (c) 1983, 1993 3*61111Sbostic * The Regents of the University of California. All rights reserved. 434790Sbostic * 542626Sbostic * %sccs.include.redist.c% 621357Sdist */ 721357Sdist 826582Sdonn #if defined(LIBC_SCCS) && !defined(lint) 9*61111Sbostic static char sccsid[] = "@(#)scandir.c 8.1 (Berkeley) 06/04/93"; 1034790Sbostic #endif /* LIBC_SCCS and not lint */ 1113582Ssam 129609Sralph /* 139609Sralph * Scan the directory dirname calling select to make a list of selected 149609Sralph * directory entries then sort using qsort and compare routine dcomp. 159609Sralph * Returns the number of entries and a pointer to a list of pointers to 1636545Smckusick * struct dirent (through namelist). Returns -1 if there were any errors. 179609Sralph */ 189609Sralph 199609Sralph #include <sys/types.h> 209609Sralph #include <sys/stat.h> 2136545Smckusick #include <dirent.h> 2246597Sdonn #include <stdlib.h> 2346597Sdonn #include <string.h> 249609Sralph 2536558Smckusick /* 2636558Smckusick * The DIRSIZ macro gives the minimum record length which will hold 2736558Smckusick * the directory entry. This requires the amount of space in struct dirent 2836558Smckusick * without the d_name field, plus enough space for the name with a terminating 2936558Smckusick * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary. 3036558Smckusick */ 3136558Smckusick #undef DIRSIZ 3236558Smckusick #define DIRSIZ(dp) \ 3336558Smckusick ((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3)) 3436558Smckusick 3546597Sdonn int 369609Sralph scandir(dirname, namelist, select, dcomp) 3746597Sdonn const char *dirname; 3843534Sbostic struct dirent ***namelist; 3946597Sdonn int (*select) __P((struct dirent *)); 4046597Sdonn int (*dcomp) __P((const void *, const void *)); 419609Sralph { 4236545Smckusick register struct dirent *d, *p, **names; 4346597Sdonn register size_t nitems; 449609Sralph struct stat stb; 459609Sralph long arraysz; 469609Sralph DIR *dirp; 479609Sralph 489609Sralph if ((dirp = opendir(dirname)) == NULL) 499609Sralph return(-1); 509609Sralph if (fstat(dirp->dd_fd, &stb) < 0) 519609Sralph return(-1); 529609Sralph 539609Sralph /* 549609Sralph * estimate the array size by taking the size of the directory file 559609Sralph * and dividing it by a multiple of the minimum size entry. 569609Sralph */ 579609Sralph arraysz = (stb.st_size / 24); 5836545Smckusick names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *)); 599609Sralph if (names == NULL) 609609Sralph return(-1); 619609Sralph 629609Sralph nitems = 0; 639609Sralph while ((d = readdir(dirp)) != NULL) { 649609Sralph if (select != NULL && !(*select)(d)) 659609Sralph continue; /* just selected names */ 669609Sralph /* 679609Sralph * Make a minimum size copy of the data 689609Sralph */ 6936545Smckusick p = (struct dirent *)malloc(DIRSIZ(d)); 709609Sralph if (p == NULL) 719609Sralph return(-1); 729609Sralph p->d_ino = d->d_ino; 739609Sralph p->d_reclen = d->d_reclen; 749609Sralph p->d_namlen = d->d_namlen; 7536681Sbostic bcopy(d->d_name, p->d_name, p->d_namlen + 1); 769609Sralph /* 779609Sralph * Check to make sure the array has space left and 789609Sralph * realloc the maximum size. 799609Sralph */ 809609Sralph if (++nitems >= arraysz) { 8115661Sralph if (fstat(dirp->dd_fd, &stb) < 0) 8215661Sralph return(-1); /* just might have grown */ 8315661Sralph arraysz = stb.st_size / 12; 8436545Smckusick names = (struct dirent **)realloc((char *)names, 8536545Smckusick arraysz * sizeof(struct dirent *)); 869609Sralph if (names == NULL) 879609Sralph return(-1); 889609Sralph } 899609Sralph names[nitems-1] = p; 909609Sralph } 919609Sralph closedir(dirp); 929609Sralph if (nitems && dcomp != NULL) 9336545Smckusick qsort(names, nitems, sizeof(struct dirent *), dcomp); 949609Sralph *namelist = names; 959609Sralph return(nitems); 969609Sralph } 979609Sralph 989609Sralph /* 999609Sralph * Alphabetic order comparison routine for those who want it. 1009609Sralph */ 10146597Sdonn int 1029609Sralph alphasort(d1, d2) 10346597Sdonn const void *d1; 10446597Sdonn const void *d2; 1059609Sralph { 10643609Sbostic return(strcmp((*(struct dirent **)d1)->d_name, 10743609Sbostic (*(struct dirent **)d2)->d_name)); 1089609Sralph } 109