summaryrefslogtreecommitdiffstats
path: root/replace/scandir.c
diff options
context:
space:
mode:
Diffstat (limited to 'replace/scandir.c')
-rw-r--r--replace/scandir.c236
1 files changed, 236 insertions, 0 deletions
diff --git a/replace/scandir.c b/replace/scandir.c
new file mode 100644
index 0000000..528f544
--- /dev/null
+++ b/replace/scandir.c
@@ -0,0 +1,236 @@
+/* scandir: Scan a directory, collecting all (selected) items into a an array.
+ *
+ * This code borrowed from 'libit', which can be found here:
+ *
+ * http://www.iro.umontreal.ca/~pinard/libit/dist/scandir/
+ *
+ * The original author put this code in the public domain.
+ * It has been modified slightly to get rid of warnings, etc.
+ *
+ * Below is the email I received from pinard@iro.umontreal.ca (François Pinard)
+ * when I sent him an email asking him about the license, etc. of this
+ * code which I obtained from his site.
+ *
+ * I think the correct spelling of his name is Rich Salz. I think he's now
+ * rsalz@datapower.com...
+ * --
+ * Rich Salz, Chief Security Architect
+ * DataPower Technology http://www.datapower.com
+ * XS40 XML Security Gateway http://www.datapower.com/products/xs40.html
+ *
+ * Copyright(C): none (public domain)
+ * License: none (public domain)
+ * Author: Rich Salz <rsalz@datapower.com>
+ *
+ *
+ *
+ * -- Alan Robertson
+ * alanr@unix.sh
+ *
+ **************************************************************************
+ *
+ * Subject: Re: Scandir replacement function
+ * Date: 18 May 2001 12:00:48 -0400
+ * From: pinard@iro.umontreal.ca (François Pinard)
+ * To: Alan Robertson <alanr@unix.sh>
+ * References: 1
+ *
+ *
+ * [Alan Robertson]
+ *
+ * > Hi, I'd like to use your scandir replacement function found here:
+ * > http://www.iro.umontreal.ca/~pinard/libit/dist/scandir/ But, it does
+ * > not indicate authorship or licensing terms in it. Could you tell me
+ * > who wrote this code, under what license you distribute it, and whether
+ * > and under what terms I may further distribute it?
+ *
+ * Hello, Alan. These are (somewhat) explained in UNSHAR.HDR found in the
+ * same directory. The routines have been written by Rick Saltz (I'm not
+ * completely sure of the spelling) a long while ago. I think that nowadays,
+ * Rick is better known as the main author of the nice INN package.
+ *
+ **************************************************************************
+ *
+ * I spent a little time verifying this with Rick Salz.
+ * The results are below:
+ *
+ **************************************************************************
+ *
+ * Date: Tue, 20 Sep 2005 21:52:09 -0400 (EDT)
+ * From: Rich Salz <rsalz@datapower.com>
+ * To: Alan Robertson <alanr@unix.sh>
+ * Subject: Re: Verifying permissions/licenses/etc on some old code of yours -
+ * scandir.c
+ * In-Reply-To: <433071CA.8000107@unix.sh>
+ * Message-ID: <Pine.LNX.4.44L0.0509202151270.9198-100000@smtp.datapower.com>
+ * Content-Type: TEXT/PLAIN; charset=US-ASCII
+ *
+ * yes, it's most definitely in the public domain.
+ *
+ * I'm glad you find it useful. I'm surprised it hasn't been replaced by,
+ * e.g,. something in GLibC. Ii'm impressed you tracked me down.
+ *
+ * /r$
+ *
+ * --
+ * Rich Salz Chief Security Architect
+ * DataPower Technology http://www.datapower.com
+ * XS40 XML Security Gateway http://www.datapower.com/products/xs40.html
+ * ---------------------------------------------------------------------->
+ * Subject: scandir, ftw REDUX
+ * Date: 1 Jan 88 00:47:01 GMT
+ * From: rsalz@pebbles.bbn.com
+ * Newsgroups: comp.sources.misc
+ *
+ *
+ * Forget my previous message -- I just decided for completeness's sake to
+ * implement the SysV ftw(3) routine, too.
+ *
+ * To repeat, these are public-domain implementations of the SystemV ftw()
+ * routine, the BSD scandir() and alphasort() routines, and documentation for
+ * same. The FTW manpage could be more readable, but so it goes.
+ *
+ * Anyhow, feel free to post these, and incorporate them into your existing
+ * packages. I have readdir() routiens for MSDOS and the Amiga if anyone
+ * wants them, and should have them for VMS by the end of January; let me
+ * know if you want copies.
+ *
+ * Yours in filesystems,
+ * /r$
+ *
+ * Anyhow, feel free to post
+ * ----------------------------------------------------------------------<
+ *
+ */
+
+#include <lha_internal.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+
+#ifndef NULL
+# define NULL ((void *) 0)
+#endif
+
+/* Initial guess at directory allocated. */
+#define INITIAL_ALLOCATION 20
+
+int
+scandir (const char *directory_name,
+ struct dirent ***array_pointer,
+ int (*select_function) (const struct dirent *),
+
+#ifdef USE_SCANDIR_COMPARE_STRUCT_DIRENT
+ /* This is what the Linux man page says */
+ int (*compare_function) (const struct dirent**, const struct dirent**)
+#else
+ /* This is what the Linux header file says ... */
+ int (*compare_function) (const void *, const void *)
+#endif
+ );
+
+int
+scandir (const char *directory_name,
+ struct dirent ***array_pointer,
+ int (*select_function) (const struct dirent *),
+#ifdef USE_SCANDIR_COMPARE_STRUCT_DIRENT
+ /* This is what the linux man page says */
+ int (*compare_function) (const struct dirent**, const struct dirent**)
+#else
+ /* This is what the linux header file says ... */
+ int (*compare_function) (const void *, const void *)
+#endif
+ )
+{
+ DIR *directory;
+ struct dirent **array;
+ struct dirent *entry;
+ struct dirent *copy;
+ int allocated = INITIAL_ALLOCATION;
+ int counter = 0;
+
+ /* Get initial list space and open directory. */
+
+ if (directory = opendir (directory_name), directory == NULL)
+ return -1;
+
+ if (array = (struct dirent **) malloc (allocated * sizeof (struct dirent *)),
+ array == NULL)
+ return -1;
+
+ /* Read entries in the directory. */
+
+ while (entry = readdir (directory), entry)
+ if (select_function == NULL || (*select_function) (entry))
+ {
+ /* User wants them all, or he wants this one. Copy the entry. */
+
+ /*
+ * On some OSes the declaration of "entry->d_name" is a minimal-length
+ * placeholder. Example: Solaris:
+ * /usr/include/sys/dirent.h:
+ * "char d_name[1];"
+ * man page "dirent(3)":
+ * The field d_name is the beginning of the character array
+ * giving the name of the directory entry. This name is
+ * null terminated and may have at most MAXNAMLEN chars.
+ * So our malloc length may need to be increased accordingly.
+ * sizeof(entry->d_name): space (possibly minimal) in struct.
+ * strlen(entry->d_name): actual length of the entry.
+ *
+ * John Kavadias <john_kavadias@hotmail.com>
+ * David Lee <t.d.lee@durham.ac.uk>
+ */
+ int namelength = strlen(entry->d_name) + 1; /* length with NULL */
+ int extra = 0;
+
+ if (sizeof(entry->d_name) <= namelength) {
+ /* allocated space <= required space */
+ extra += namelength - sizeof(entry->d_name);
+ }
+
+ if (copy = (struct dirent *) malloc (sizeof (struct dirent) + extra),
+ copy == NULL)
+ {
+ closedir (directory);
+ free (array);
+ return -1;
+ }
+ copy->d_ino = entry->d_ino;
+ copy->d_reclen = entry->d_reclen;
+ strcpy (copy->d_name, entry->d_name);
+
+ /* Save the copy. */
+
+ if (counter + 1 == allocated)
+ {
+ allocated <<= 1;
+ array = (struct dirent **)
+ realloc ((char *) array, allocated * sizeof (struct dirent *));
+ if (array == NULL)
+ {
+ closedir (directory);
+ free (array);
+ free (copy);
+ return -1;
+ }
+ }
+ array[counter++] = copy;
+ }
+
+ /* Close things off. */
+
+ array[counter] = NULL;
+ *array_pointer = array;
+ closedir (directory);
+
+ /* Sort? */
+
+ if (counter > 1 && compare_function)
+ qsort ((char *) array, counter, sizeof (struct dirent *)
+ , (int (*)(const void *, const void *))(compare_function));
+
+ return counter;
+}