1*69921123SKonstantin Belousov /* 2*69921123SKonstantin Belousov * Copyright (c) 1983, 1993 3*69921123SKonstantin Belousov * The Regents of the University of California. All rights reserved. 4*69921123SKonstantin Belousov * 5*69921123SKonstantin Belousov * Redistribution and use in source and binary forms, with or without 6*69921123SKonstantin Belousov * modification, are permitted provided that the following conditions 7*69921123SKonstantin Belousov * are met: 8*69921123SKonstantin Belousov * 1. Redistributions of source code must retain the above copyright 9*69921123SKonstantin Belousov * notice, this list of conditions and the following disclaimer. 10*69921123SKonstantin Belousov * 2. Redistributions in binary form must reproduce the above copyright 11*69921123SKonstantin Belousov * notice, this list of conditions and the following disclaimer in the 12*69921123SKonstantin Belousov * documentation and/or other materials provided with the distribution. 13*69921123SKonstantin Belousov * 3. Neither the name of the University nor the names of its contributors 14*69921123SKonstantin Belousov * may be used to endorse or promote products derived from this software 15*69921123SKonstantin Belousov * without specific prior written permission. 16*69921123SKonstantin Belousov * 17*69921123SKonstantin Belousov * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18*69921123SKonstantin Belousov * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19*69921123SKonstantin Belousov * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20*69921123SKonstantin Belousov * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21*69921123SKonstantin Belousov * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22*69921123SKonstantin Belousov * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23*69921123SKonstantin Belousov * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24*69921123SKonstantin Belousov * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25*69921123SKonstantin Belousov * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26*69921123SKonstantin Belousov * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27*69921123SKonstantin Belousov * SUCH DAMAGE. 28*69921123SKonstantin Belousov * 29*69921123SKonstantin Belousov * from: 30*69921123SKonstantin Belousov * $FreeBSD$ 31*69921123SKonstantin Belousov */ 32*69921123SKonstantin Belousov 33*69921123SKonstantin Belousov #if defined(LIBC_SCCS) && !defined(lint) 34*69921123SKonstantin Belousov static char sccsid[] = "@(#)scandir.c 8.3 (Berkeley) 1/2/94"; 35*69921123SKonstantin Belousov #endif /* LIBC_SCCS and not lint */ 36*69921123SKonstantin Belousov #include <sys/cdefs.h> 37*69921123SKonstantin Belousov __FBSDID("$FreeBSD$"); 38*69921123SKonstantin Belousov 39*69921123SKonstantin Belousov /* 40*69921123SKonstantin Belousov * Scan the directory dirname calling select to make a list of selected 41*69921123SKonstantin Belousov * directory entries then sort using qsort and compare routine dcomp. 42*69921123SKonstantin Belousov * Returns the number of entries and a pointer to a list of pointers to 43*69921123SKonstantin Belousov * struct dirent (through namelist). Returns -1 if there were any errors. 44*69921123SKonstantin Belousov */ 45*69921123SKonstantin Belousov 46*69921123SKonstantin Belousov #include "namespace.h" 47*69921123SKonstantin Belousov #define _WANT_FREEBSD11_DIRENT 48*69921123SKonstantin Belousov #include <dirent.h> 49*69921123SKonstantin Belousov #include <stdlib.h> 50*69921123SKonstantin Belousov #include <string.h> 51*69921123SKonstantin Belousov #include "un-namespace.h" 52*69921123SKonstantin Belousov 53*69921123SKonstantin Belousov #include "gen-compat.h" 54*69921123SKonstantin Belousov 55*69921123SKonstantin Belousov #ifdef I_AM_SCANDIR_B 56*69921123SKonstantin Belousov #include "block_abi.h" 57*69921123SKonstantin Belousov #define SELECT(x) CALL_BLOCK(select, x) 58*69921123SKonstantin Belousov #ifndef __BLOCKS__ 59*69921123SKonstantin Belousov void 60*69921123SKonstantin Belousov qsort_b(void *, size_t, size_t, void*); 61*69921123SKonstantin Belousov #endif 62*69921123SKonstantin Belousov #else 63*69921123SKonstantin Belousov #define SELECT(x) select(x) 64*69921123SKonstantin Belousov #endif 65*69921123SKonstantin Belousov 66*69921123SKonstantin Belousov static int freebsd11_alphasort_thunk(void *thunk, const void *p1, 67*69921123SKonstantin Belousov const void *p2); 68*69921123SKonstantin Belousov 69*69921123SKonstantin Belousov int 70*69921123SKonstantin Belousov #ifdef I_AM_SCANDIR_B 71*69921123SKonstantin Belousov freebsd11_scandir_b(const char *dirname, struct freebsd11_dirent ***namelist, 72*69921123SKonstantin Belousov DECLARE_BLOCK(int, select, const struct freebsd11_dirent *), 73*69921123SKonstantin Belousov DECLARE_BLOCK(int, dcomp, const struct freebsd11_dirent **, 74*69921123SKonstantin Belousov const struct freebsd11_dirent **)) 75*69921123SKonstantin Belousov #else 76*69921123SKonstantin Belousov freebsd11_scandir(const char *dirname, struct freebsd11_dirent ***namelist, 77*69921123SKonstantin Belousov int (*select)(const struct freebsd11_dirent *), 78*69921123SKonstantin Belousov int (*dcomp)(const struct freebsd11_dirent **, 79*69921123SKonstantin Belousov const struct freebsd11_dirent **)) 80*69921123SKonstantin Belousov #endif 81*69921123SKonstantin Belousov { 82*69921123SKonstantin Belousov struct freebsd11_dirent *d, *p, **names = NULL; 83*69921123SKonstantin Belousov size_t arraysz, numitems; 84*69921123SKonstantin Belousov DIR *dirp; 85*69921123SKonstantin Belousov 86*69921123SKonstantin Belousov if ((dirp = opendir(dirname)) == NULL) 87*69921123SKonstantin Belousov return(-1); 88*69921123SKonstantin Belousov 89*69921123SKonstantin Belousov numitems = 0; 90*69921123SKonstantin Belousov arraysz = 32; /* initial estimate of the array size */ 91*69921123SKonstantin Belousov names = (struct freebsd11_dirent **)malloc( 92*69921123SKonstantin Belousov arraysz * sizeof(struct freebsd11_dirent *)); 93*69921123SKonstantin Belousov if (names == NULL) 94*69921123SKonstantin Belousov goto fail; 95*69921123SKonstantin Belousov 96*69921123SKonstantin Belousov while ((d = freebsd11_readdir(dirp)) != NULL) { 97*69921123SKonstantin Belousov if (select != NULL && !SELECT(d)) 98*69921123SKonstantin Belousov continue; /* just selected names */ 99*69921123SKonstantin Belousov /* 100*69921123SKonstantin Belousov * Make a minimum size copy of the data 101*69921123SKonstantin Belousov */ 102*69921123SKonstantin Belousov p = (struct freebsd11_dirent *)malloc(FREEBSD11_DIRSIZ(d)); 103*69921123SKonstantin Belousov if (p == NULL) 104*69921123SKonstantin Belousov goto fail; 105*69921123SKonstantin Belousov p->d_fileno = d->d_fileno; 106*69921123SKonstantin Belousov p->d_type = d->d_type; 107*69921123SKonstantin Belousov p->d_reclen = d->d_reclen; 108*69921123SKonstantin Belousov p->d_namlen = d->d_namlen; 109*69921123SKonstantin Belousov bcopy(d->d_name, p->d_name, p->d_namlen + 1); 110*69921123SKonstantin Belousov /* 111*69921123SKonstantin Belousov * Check to make sure the array has space left and 112*69921123SKonstantin Belousov * realloc the maximum size. 113*69921123SKonstantin Belousov */ 114*69921123SKonstantin Belousov if (numitems >= arraysz) { 115*69921123SKonstantin Belousov struct freebsd11_dirent **names2; 116*69921123SKonstantin Belousov 117*69921123SKonstantin Belousov names2 = reallocarray(names, arraysz, 118*69921123SKonstantin Belousov 2 * sizeof(struct freebsd11_dirent *)); 119*69921123SKonstantin Belousov if (names2 == NULL) { 120*69921123SKonstantin Belousov free(p); 121*69921123SKonstantin Belousov goto fail; 122*69921123SKonstantin Belousov } 123*69921123SKonstantin Belousov names = names2; 124*69921123SKonstantin Belousov arraysz *= 2; 125*69921123SKonstantin Belousov } 126*69921123SKonstantin Belousov names[numitems++] = p; 127*69921123SKonstantin Belousov } 128*69921123SKonstantin Belousov closedir(dirp); 129*69921123SKonstantin Belousov if (numitems && dcomp != NULL) 130*69921123SKonstantin Belousov #ifdef I_AM_SCANDIR_B 131*69921123SKonstantin Belousov qsort_b(names, numitems, sizeof(struct freebsd11_dirent *), 132*69921123SKonstantin Belousov (void*)dcomp); 133*69921123SKonstantin Belousov #else 134*69921123SKonstantin Belousov qsort_r(names, numitems, sizeof(struct freebsd11_dirent *), 135*69921123SKonstantin Belousov &dcomp, freebsd11_alphasort_thunk); 136*69921123SKonstantin Belousov #endif 137*69921123SKonstantin Belousov *namelist = names; 138*69921123SKonstantin Belousov return (numitems); 139*69921123SKonstantin Belousov 140*69921123SKonstantin Belousov fail: 141*69921123SKonstantin Belousov while (numitems > 0) 142*69921123SKonstantin Belousov free(names[--numitems]); 143*69921123SKonstantin Belousov free(names); 144*69921123SKonstantin Belousov closedir(dirp); 145*69921123SKonstantin Belousov return (-1); 146*69921123SKonstantin Belousov } 147*69921123SKonstantin Belousov 148*69921123SKonstantin Belousov /* 149*69921123SKonstantin Belousov * Alphabetic order comparison routine for those who want it. 150*69921123SKonstantin Belousov * POSIX 2008 requires that alphasort() uses strcoll(). 151*69921123SKonstantin Belousov */ 152*69921123SKonstantin Belousov int 153*69921123SKonstantin Belousov freebsd11_alphasort(const struct freebsd11_dirent **d1, 154*69921123SKonstantin Belousov const struct freebsd11_dirent **d2) 155*69921123SKonstantin Belousov { 156*69921123SKonstantin Belousov 157*69921123SKonstantin Belousov return (strcoll((*d1)->d_name, (*d2)->d_name)); 158*69921123SKonstantin Belousov } 159*69921123SKonstantin Belousov 160*69921123SKonstantin Belousov static int 161*69921123SKonstantin Belousov freebsd11_alphasort_thunk(void *thunk, const void *p1, const void *p2) 162*69921123SKonstantin Belousov { 163*69921123SKonstantin Belousov int (*dc)(const struct freebsd11_dirent **, const struct 164*69921123SKonstantin Belousov freebsd11_dirent **); 165*69921123SKonstantin Belousov 166*69921123SKonstantin Belousov dc = *(int (**)(const struct freebsd11_dirent **, 167*69921123SKonstantin Belousov const struct freebsd11_dirent **))thunk; 168*69921123SKonstantin Belousov return (dc((const struct freebsd11_dirent **)p1, 169*69921123SKonstantin Belousov (const struct freebsd11_dirent **)p2)); 170*69921123SKonstantin Belousov } 171*69921123SKonstantin Belousov 172*69921123SKonstantin Belousov __sym_compat(alphasort, freebsd11_alphasort, FBSD_1.0); 173*69921123SKonstantin Belousov __sym_compat(scandir, freebsd11_scandir, FBSD_1.0); 174*69921123SKonstantin Belousov __sym_compat(scandir_b, freebsd11_scandir_b, FBSD_1.4); 175