root/replace/scandir.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. scandir

   1 /* scandir: Scan a directory, collecting all (selected) items into a an array.
   2  *
   3  * This code borrowed from 'libit', which can be found here:
   4  *
   5  * http://www.iro.umontreal.ca/~pinard/libit/dist/scandir/
   6  *
   7  * The original author put this code in the public domain.
   8  * It has been modified slightly to get rid of warnings, etc.
   9  *
  10  * Below is the email I received from pinard@iro.umontreal.ca (François Pinard)
  11  * when I sent him an email asking him about the license, etc. of this
  12  * code which I obtained from his site.
  13  *
  14  * I think the correct spelling of his name is Rich Salz.  I think he's now 
  15  * rsalz@datapower.com...
  16  * -- 
  17  * Rich Salz, Chief Security Architect
  18  * DataPower Technology                           http://www.datapower.com
  19  * XS40 XML Security Gateway   http://www.datapower.com/products/xs40.html
  20  *
  21  *      Copyright(C):   none (public domain)
  22  *      License:        none (public domain)
  23  *      Author:         Rich Salz <rsalz@datapower.com>
  24  *
  25  *
  26  *
  27  *      -- Alan Robertson
  28  *         alanr@unix.sh
  29  *
  30  **************************************************************************
  31  *
  32  * Subject:     Re: Scandir replacement function
  33  * Date:        18 May 2001 12:00:48 -0400
  34  * From:        pinard@iro.umontreal.ca (François Pinard)
  35  * To:          Alan Robertson <alanr@unix.sh>
  36  * References:  1
  37  *
  38  *
  39  * [Alan Robertson]
  40  *
  41  * > Hi, I'd like to use your scandir replacement function found here:
  42  * > http://www.iro.umontreal.ca/~pinard/libit/dist/scandir/ But, it does
  43  * > not indicate authorship or licensing terms in it.  Could you tell me
  44  * > who wrote this code, under what license you distribute it, and whether
  45  * > and under what terms I may further distribute it?
  46  *
  47  * Hello, Alan.  These are (somewhat) explained in UNSHAR.HDR found in the
  48  * same directory.  The routines have been written by Rick Saltz (I'm not
  49  * completely sure of the spelling) a long while ago.  I think that nowadays,
  50  * Rick is better known as the main author of the nice INN package.
  51  *
  52  **************************************************************************
  53  *
  54  * I spent a little time verifying this with Rick Salz.
  55  * The results are below:
  56  *
  57  **************************************************************************
  58  *
  59  * Date: Tue, 20 Sep 2005 21:52:09 -0400 (EDT)
  60  * From: Rich Salz <rsalz@datapower.com>
  61  * To: Alan Robertson <alanr@unix.sh>
  62  * Subject: Re: Verifying permissions/licenses/etc on some old code of yours -
  63  *  scandir.c
  64  * In-Reply-To: <433071CA.8000107@unix.sh>
  65  * Message-ID: <Pine.LNX.4.44L0.0509202151270.9198-100000@smtp.datapower.com>
  66  * Content-Type: TEXT/PLAIN; charset=US-ASCII
  67  *
  68  * yes, it's most definitely in the public domain.
  69  *
  70  * I'm glad you find it useful.  I'm surprised it hasn't been replaced by,
  71  * e.g,. something in GLibC.  Ii'm impressed you tracked me down.
  72  *
  73  *      /r$
  74  *
  75  * -- 
  76  * Rich Salz                  Chief Security Architect
  77  * DataPower Technology       http://www.datapower.com
  78  * XS40 XML Security Gateway  http://www.datapower.com/products/xs40.html
  79  * ---------------------------------------------------------------------->
  80  * Subject:     scandir, ftw REDUX
  81  * Date:        1 Jan 88 00:47:01 GMT
  82  * From:        rsalz@pebbles.bbn.com
  83  * Newsgroups:  comp.sources.misc
  84  *
  85  *
  86  * Forget my previous message -- I just decided for completeness's sake to
  87  * implement the SysV ftw(3) routine, too.  
  88  *
  89  * To repeat, these are public-domain implementations of the SystemV ftw()
  90  * routine, the BSD scandir() and alphasort() routines, and documentation for
  91  * same.  The FTW manpage could be more readable, but so it goes.
  92  *
  93  * Anyhow, feel free to post these, and incorporate them into your existing
  94  * packages.  I have readdir() routiens for MSDOS and the Amiga if anyone
  95  *  wants them, and should have them for VMS by the end of January; let me
  96  *  know if you want copies.
  97  *
  98  *                        Yours in filesystems,
  99  *                                /r$
 100  *
 101  *                                Anyhow, feel free to post
 102  * ----------------------------------------------------------------------<
 103  *
 104  */
 105 
 106 #include <crm_internal.h>
 107 #include <sys/types.h>
 108 #include <dirent.h>
 109 #include <stdlib.h>
 110 #include <stddef.h>
 111 #include <string.h>
 112 
 113 #ifndef NULL
 114 #  define NULL ((void *) 0)
 115 #endif
 116 
 117 /* Initial guess at directory allocated.  */
 118 #define INITIAL_ALLOCATION 20
 119 
 120 int
 121 
 122 
 123 scandir(const char *directory_name,
 124         struct dirent ***array_pointer, int (*select_function) (const struct dirent *),
 125 #ifdef USE_SCANDIR_COMPARE_STRUCT_DIRENT
 126         /* This is what the Linux man page says */
 127         int (*compare_function) (const struct dirent **, const struct dirent **)
 128 #else
 129         /* This is what the Linux header file says ... */
 130         int (*compare_function) (const void *, const void *)
 131 #endif
 132     );
 133 
 134 int
 135 scandir(const char *directory_name,
     /* [previous][next][first][last][top][bottom][index][help] */
 136         struct dirent ***array_pointer, int (*select_function) (const struct dirent *),
 137 #ifdef USE_SCANDIR_COMPARE_STRUCT_DIRENT
 138         /* This is what the linux man page says */
 139         int (*compare_function) (const struct dirent **, const struct dirent **)
 140 #else
 141         /* This is what the linux header file says ... */
 142         int (*compare_function) (const void *, const void *)
 143 #endif
 144     )
 145 {
 146     DIR *directory;
 147     struct dirent **array;
 148     struct dirent *entry;
 149     struct dirent *copy;
 150     int allocated = INITIAL_ALLOCATION;
 151     int counter = 0;
 152 
 153     /* Get initial list space and open directory.  */
 154 
 155     if ((directory = opendir(directory_name)) == NULL) {
 156         return -1;
 157     }
 158 
 159     if ((array = (struct dirent **)malloc(allocated * sizeof(struct dirent *)))
 160         == NULL) {
 161         closedir(directory);
 162         return -1;
 163     }
 164 
 165     /* Read entries in the directory.  */
 166 
 167     while (entry = readdir(directory), entry)
 168         if (select_function == NULL || (*select_function) (entry)) {
 169             /* User wants them all, or he wants this one.  Copy the entry.  */
 170 
 171             /*
 172              * On some OSes the declaration of "entry->d_name" is a minimal-length
 173              * placeholder.  Example: Solaris:
 174              *      /usr/include/sys/dirent.h:
 175              *              "char d_name[1];"
 176              *      man page "dirent(3)":
 177              *              The field d_name is the beginning of the character array
 178              *              giving the name of the directory entry. This name is
 179              *              null terminated and may have at most MAXNAMLEN chars.
 180              * So our malloc length may need to be increased accordingly.
 181              *      sizeof(entry->d_name): space (possibly minimal) in struct.
 182              *      strlen(entry->d_name): actual length of the entry. 
 183              *
 184              *                      John Kavadias <john_kavadias@hotmail.com>
 185              *                      David Lee <t.d.lee@durham.ac.uk>
 186              */
 187             int namelength = strlen(entry->d_name) + 1; /* length with NULL */
 188             int extra = 0;
 189 
 190             if (sizeof(entry->d_name) <= namelength) {
 191                 /* allocated space <= required space */
 192                 extra += namelength - sizeof(entry->d_name);
 193             }
 194 
 195             if ((copy = (struct dirent *)malloc(sizeof(struct dirent) + extra)) == NULL) {
 196                 closedir(directory);
 197                 free(array);
 198                 return -1;
 199             }
 200             copy->d_ino = entry->d_ino;
 201             copy->d_reclen = entry->d_reclen;
 202             strcpy(copy->d_name, entry->d_name);
 203 
 204             /* Save the copy.  */
 205 
 206             if (counter + 1 == allocated) {
 207                 allocated <<= 1;
 208                 array = pcmk__realloc((char *)array,
 209                                       allocated * sizeof(struct dirent *));
 210                 if (array == NULL) {
 211                     closedir(directory);
 212                     free(array);
 213                     free(copy);
 214                     return -1;
 215                 }
 216             }
 217             array[counter++] = copy;
 218         }
 219 
 220     /* Close things off.  */
 221 
 222     array[counter] = NULL;
 223     *array_pointer = array;
 224     closedir(directory);
 225 
 226     /* Sort?  */
 227 
 228     if (counter > 1 && compare_function)
 229         qsort((char *)array, counter, sizeof(struct dirent *)
 230               , (int (*)(const void *, const void *))(compare_function));
 231 
 232     return counter;
 233 }

/* [previous][next][first][last][top][bottom][index][help] */