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), directory == NULL)
 156         return -1;
 157 
 158     if (array = (struct dirent **)malloc(allocated * sizeof(struct dirent *)), array == NULL)
 159         return -1;
 160 
 161     /* Read entries in the directory.  */
 162 
 163     while (entry = readdir(directory), entry)
 164         if (select_function == NULL || (*select_function) (entry)) {
 165             /* User wants them all, or he wants this one.  Copy the entry.  */
 166 
 167             /*
 168              * On some OSes the declaration of "entry->d_name" is a minimal-length
 169              * placeholder.  Example: Solaris:
 170              *      /usr/include/sys/dirent.h:
 171              *              "char d_name[1];"
 172              *      man page "dirent(3)":
 173              *              The field d_name is the beginning of the character array
 174              *              giving the name of the directory entry. This name is
 175              *              null terminated and may have at most MAXNAMLEN chars.
 176              * So our malloc length may need to be increased accordingly.
 177              *      sizeof(entry->d_name): space (possibly minimal) in struct.
 178              *      strlen(entry->d_name): actual length of the entry. 
 179              *
 180              *                      John Kavadias <john_kavadias@hotmail.com>
 181              *                      David Lee <t.d.lee@durham.ac.uk>
 182              */
 183             int namelength = strlen(entry->d_name) + 1; /* length with NULL */
 184             int extra = 0;
 185 
 186             if (sizeof(entry->d_name) <= namelength) {
 187                 /* allocated space <= required space */
 188                 extra += namelength - sizeof(entry->d_name);
 189             }
 190 
 191             if (copy = (struct dirent *)malloc(sizeof(struct dirent) + extra), copy == NULL) {
 192                 closedir(directory);
 193                 free(array);
 194                 return -1;
 195             }
 196             copy->d_ino = entry->d_ino;
 197             copy->d_reclen = entry->d_reclen;
 198             strcpy(copy->d_name, entry->d_name);
 199 
 200             /* Save the copy.  */
 201 
 202             if (counter + 1 == allocated) {
 203                 allocated <<= 1;
 204                 array = (struct dirent **)
 205                     realloc_safe((char *)array, allocated * sizeof(struct dirent *));
 206                 if (array == NULL) {
 207                     closedir(directory);
 208                     free(array);
 209                     free(copy);
 210                     return -1;
 211                 }
 212             }
 213             array[counter++] = copy;
 214         }
 215 
 216     /* Close things off.  */
 217 
 218     array[counter] = NULL;
 219     *array_pointer = array;
 220     closedir(directory);
 221 
 222     /* Sort?  */
 223 
 224     if (counter > 1 && compare_function)
 225         qsort((char *)array, counter, sizeof(struct dirent *)
 226               , (int (*)(const void *, const void *))(compare_function));
 227 
 228     return counter;
 229 }

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