158f0484fSRodney W. Grimes /* 258f0484fSRodney W. Grimes * Copyright (c) 1983, 1993 358f0484fSRodney W. Grimes * The Regents of the University of California. All rights reserved. 458f0484fSRodney W. Grimes * 558f0484fSRodney W. Grimes * Redistribution and use in source and binary forms, with or without 658f0484fSRodney W. Grimes * modification, are permitted provided that the following conditions 758f0484fSRodney W. Grimes * are met: 858f0484fSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 958f0484fSRodney W. Grimes * notice, this list of conditions and the following disclaimer. 1058f0484fSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 1158f0484fSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 1258f0484fSRodney W. Grimes * documentation and/or other materials provided with the distribution. 1358f0484fSRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 1458f0484fSRodney W. Grimes * must display the following acknowledgement: 1558f0484fSRodney W. Grimes * This product includes software developed by the University of 1658f0484fSRodney W. Grimes * California, Berkeley and its contributors. 1758f0484fSRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 1858f0484fSRodney W. Grimes * may be used to endorse or promote products derived from this software 1958f0484fSRodney W. Grimes * without specific prior written permission. 2058f0484fSRodney W. Grimes * 2158f0484fSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2258f0484fSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2358f0484fSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2458f0484fSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2558f0484fSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2658f0484fSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2758f0484fSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2858f0484fSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2958f0484fSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3058f0484fSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3158f0484fSRodney W. Grimes * SUCH DAMAGE. 3258f0484fSRodney W. Grimes */ 3358f0484fSRodney W. Grimes 3458f0484fSRodney W. Grimes #if defined(LIBC_SCCS) && !defined(lint) 3558f0484fSRodney W. Grimes static char sccsid[] = "@(#)scandir.c 8.3 (Berkeley) 1/2/94"; 3658f0484fSRodney W. Grimes #endif /* LIBC_SCCS and not lint */ 3758f0484fSRodney W. Grimes 3858f0484fSRodney W. Grimes /* 3958f0484fSRodney W. Grimes * Scan the directory dirname calling select to make a list of selected 4058f0484fSRodney W. Grimes * directory entries then sort using qsort and compare routine dcomp. 4158f0484fSRodney W. Grimes * Returns the number of entries and a pointer to a list of pointers to 4258f0484fSRodney W. Grimes * struct dirent (through namelist). Returns -1 if there were any errors. 4358f0484fSRodney W. Grimes */ 4458f0484fSRodney W. Grimes 4558f0484fSRodney W. Grimes #include <sys/types.h> 4658f0484fSRodney W. Grimes #include <sys/stat.h> 4758f0484fSRodney W. Grimes #include <dirent.h> 4858f0484fSRodney W. Grimes #include <stdlib.h> 4958f0484fSRodney W. Grimes #include <string.h> 5058f0484fSRodney W. Grimes 5158f0484fSRodney W. Grimes /* 5258f0484fSRodney W. Grimes * The DIRSIZ macro is the minimum record length which will hold the directory 5358f0484fSRodney W. Grimes * entry. This requires the amount of space in struct dirent without the 5458f0484fSRodney W. Grimes * d_name field, plus enough space for the name and a terminating nul byte 5558f0484fSRodney W. Grimes * (dp->d_namlen + 1), rounded up to a 4 byte boundary. 5658f0484fSRodney W. Grimes */ 5758f0484fSRodney W. Grimes #undef DIRSIZ 5858f0484fSRodney W. Grimes #define DIRSIZ(dp) \ 5958f0484fSRodney W. Grimes ((sizeof(struct dirent) - sizeof(dp)->d_name) + \ 6058f0484fSRodney W. Grimes (((dp)->d_namlen + 1 + 3) &~ 3)) 6158f0484fSRodney W. Grimes 6258f0484fSRodney W. Grimes int 6358f0484fSRodney W. Grimes scandir(dirname, namelist, select, dcomp) 6458f0484fSRodney W. Grimes const char *dirname; 6558f0484fSRodney W. Grimes struct dirent ***namelist; 6658f0484fSRodney W. Grimes int (*select) __P((struct dirent *)); 6758f0484fSRodney W. Grimes int (*dcomp) __P((const void *, const void *)); 6858f0484fSRodney W. Grimes { 6929595ffdSJulian Elischer register struct dirent *d, *p, **names = NULL; 7029595ffdSJulian Elischer register size_t nitems = 0; 7158f0484fSRodney W. Grimes struct stat stb; 7258f0484fSRodney W. Grimes long arraysz; 7358f0484fSRodney W. Grimes DIR *dirp; 7458f0484fSRodney W. Grimes 7558f0484fSRodney W. Grimes if ((dirp = opendir(dirname)) == NULL) 7658f0484fSRodney W. Grimes return(-1); 7758f0484fSRodney W. Grimes if (fstat(dirp->dd_fd, &stb) < 0) 7829595ffdSJulian Elischer goto fail; 7958f0484fSRodney W. Grimes 8058f0484fSRodney W. Grimes /* 8158f0484fSRodney W. Grimes * estimate the array size by taking the size of the directory file 8258f0484fSRodney W. Grimes * and dividing it by a multiple of the minimum size entry. 8358f0484fSRodney W. Grimes */ 8458f0484fSRodney W. Grimes arraysz = (stb.st_size / 24); 8558f0484fSRodney W. Grimes names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *)); 8658f0484fSRodney W. Grimes if (names == NULL) 8729595ffdSJulian Elischer goto fail; 8858f0484fSRodney W. Grimes 8958f0484fSRodney W. Grimes while ((d = readdir(dirp)) != NULL) { 9058f0484fSRodney W. Grimes if (select != NULL && !(*select)(d)) 9158f0484fSRodney W. Grimes continue; /* just selected names */ 9258f0484fSRodney W. Grimes /* 9358f0484fSRodney W. Grimes * Make a minimum size copy of the data 9458f0484fSRodney W. Grimes */ 9558f0484fSRodney W. Grimes p = (struct dirent *)malloc(DIRSIZ(d)); 9658f0484fSRodney W. Grimes if (p == NULL) 9729595ffdSJulian Elischer goto fail; 98e169c667SPoul-Henning Kamp p->d_fileno = d->d_fileno; 99e169c667SPoul-Henning Kamp p->d_type = d->d_type; 10058f0484fSRodney W. Grimes p->d_reclen = d->d_reclen; 10158f0484fSRodney W. Grimes p->d_namlen = d->d_namlen; 10258f0484fSRodney W. Grimes bcopy(d->d_name, p->d_name, p->d_namlen + 1); 10358f0484fSRodney W. Grimes /* 10458f0484fSRodney W. Grimes * Check to make sure the array has space left and 10558f0484fSRodney W. Grimes * realloc the maximum size. 10658f0484fSRodney W. Grimes */ 10729595ffdSJulian Elischer if (nitems >= arraysz) { 10829595ffdSJulian Elischer const int inc = 10; /* increase by this much */ 10929595ffdSJulian Elischer struct dirent **names2; 11029595ffdSJulian Elischer 11129595ffdSJulian Elischer names2 = (struct dirent **)realloc((char *)names, 11229595ffdSJulian Elischer (arraysz + inc) * sizeof(struct dirent *)); 11329595ffdSJulian Elischer if (names2 == NULL) { 11429595ffdSJulian Elischer free(p); 11529595ffdSJulian Elischer goto fail; 11658f0484fSRodney W. Grimes } 11729595ffdSJulian Elischer names = names2; 11829595ffdSJulian Elischer arraysz += inc; 11929595ffdSJulian Elischer } 12029595ffdSJulian Elischer names[nitems++] = p; 12158f0484fSRodney W. Grimes } 12258f0484fSRodney W. Grimes closedir(dirp); 12358f0484fSRodney W. Grimes if (nitems && dcomp != NULL) 12458f0484fSRodney W. Grimes qsort(names, nitems, sizeof(struct dirent *), dcomp); 12558f0484fSRodney W. Grimes *namelist = names; 12658f0484fSRodney W. Grimes return(nitems); 12729595ffdSJulian Elischer 12829595ffdSJulian Elischer fail: 12929595ffdSJulian Elischer while (nitems > 0) 13029595ffdSJulian Elischer free(names[--nitems]); 13129595ffdSJulian Elischer free(names); 13229595ffdSJulian Elischer closedir(dirp); 13329595ffdSJulian Elischer return -1; 13458f0484fSRodney W. Grimes } 13558f0484fSRodney W. Grimes 13658f0484fSRodney W. Grimes /* 13758f0484fSRodney W. Grimes * Alphabetic order comparison routine for those who want it. 13858f0484fSRodney W. Grimes */ 13958f0484fSRodney W. Grimes int 14058f0484fSRodney W. Grimes alphasort(d1, d2) 14158f0484fSRodney W. Grimes const void *d1; 14258f0484fSRodney W. Grimes const void *d2; 14358f0484fSRodney W. Grimes { 14458f0484fSRodney W. Grimes return(strcmp((*(struct dirent **)d1)->d_name, 14558f0484fSRodney W. Grimes (*(struct dirent **)d2)->d_name)); 14658f0484fSRodney W. Grimes } 147