dhodovsk / source-git / pacemaker

Forked from source-git/pacemaker 3 years ago
Clone

Blame replace/scandir.c

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