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*36545Smckusick static char sccsid[] = "@(#)scandir.c 5.4 (Berkeley) 01/11/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 26*36545Smckusick * struct dirent (through namelist). Returns -1 if there were any errors. 279609Sralph */ 289609Sralph 299609Sralph #include <sys/types.h> 309609Sralph #include <sys/stat.h> 31*36545Smckusick #include <dirent.h> 329609Sralph 339609Sralph scandir(dirname, namelist, select, dcomp) 349609Sralph char *dirname; 35*36545Smckusick struct dirent *(*namelist[]); 369609Sralph int (*select)(), (*dcomp)(); 379609Sralph { 38*36545Smckusick register struct dirent *d, *p, **names; 399609Sralph register int nitems; 409609Sralph register char *cp1, *cp2; 419609Sralph struct stat stb; 429609Sralph long arraysz; 439609Sralph DIR *dirp; 449609Sralph 459609Sralph if ((dirp = opendir(dirname)) == NULL) 469609Sralph return(-1); 479609Sralph if (fstat(dirp->dd_fd, &stb) < 0) 489609Sralph return(-1); 499609Sralph 509609Sralph /* 519609Sralph * estimate the array size by taking the size of the directory file 529609Sralph * and dividing it by a multiple of the minimum size entry. 539609Sralph */ 549609Sralph arraysz = (stb.st_size / 24); 55*36545Smckusick names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *)); 569609Sralph if (names == NULL) 579609Sralph return(-1); 589609Sralph 599609Sralph nitems = 0; 609609Sralph while ((d = readdir(dirp)) != NULL) { 619609Sralph if (select != NULL && !(*select)(d)) 629609Sralph continue; /* just selected names */ 639609Sralph /* 649609Sralph * Make a minimum size copy of the data 659609Sralph */ 66*36545Smckusick p = (struct dirent *)malloc(DIRSIZ(d)); 679609Sralph if (p == NULL) 689609Sralph return(-1); 699609Sralph p->d_ino = d->d_ino; 709609Sralph p->d_reclen = d->d_reclen; 719609Sralph p->d_namlen = d->d_namlen; 729609Sralph for (cp1 = p->d_name, cp2 = d->d_name; *cp1++ = *cp2++; ); 739609Sralph /* 749609Sralph * Check to make sure the array has space left and 759609Sralph * realloc the maximum size. 769609Sralph */ 779609Sralph if (++nitems >= arraysz) { 7815661Sralph if (fstat(dirp->dd_fd, &stb) < 0) 7915661Sralph return(-1); /* just might have grown */ 8015661Sralph arraysz = stb.st_size / 12; 81*36545Smckusick names = (struct dirent **)realloc((char *)names, 82*36545Smckusick arraysz * sizeof(struct dirent *)); 839609Sralph if (names == NULL) 849609Sralph return(-1); 859609Sralph } 869609Sralph names[nitems-1] = p; 879609Sralph } 889609Sralph closedir(dirp); 899609Sralph if (nitems && dcomp != NULL) 90*36545Smckusick qsort(names, nitems, sizeof(struct dirent *), dcomp); 919609Sralph *namelist = names; 929609Sralph return(nitems); 939609Sralph } 949609Sralph 959609Sralph /* 969609Sralph * Alphabetic order comparison routine for those who want it. 979609Sralph */ 989609Sralph alphasort(d1, d2) 99*36545Smckusick struct dirent **d1, **d2; 1009609Sralph { 1019609Sralph return(strcmp((*d1)->d_name, (*d2)->d_name)); 1029609Sralph } 103