summaryrefslogtreecommitdiff
path: root/lib/C/fake/scandir.C
blob: b74d4eee52180b47aa3eb83be72a35555940cf38 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
 * scandir.C -- A scandir implementation.
 */

/*
 * $Id: scandir.C,v 3.0.1.1 1994/01/24 13:58:45 ram Exp $
 *
 *  Copyright (c) 1991-1993, Raphael Manfredi
 *  
 *  You may redistribute only under the terms of the Artistic Licence,
 *  as specified in the README file that comes with the distribution.
 *  You may reuse parts of this distribution only within the terms of
 *  that same Artistic Licence; a copy of which may be found at the root
 *  of the source tree for dist 3.0.
 *
 * $Log: scandir.C,v $
 * Revision 3.0.1.1  1994/01/24  13:58:45  ram
 * patch16: created
 *
 */

#include "config.h"

#ifdef I_STRING
#include <string.h>
#else
#include <strings.h>
#endif

#ifdef I_DIRENT
#include <dirent.h>
#else
#ifdef I_SYS_NDIR
#include <sys/ndir.h>
#else
#ifdef I_SYS_DIR
#include <sys/dir.h>
#endif
#endif
#endif

#include "confmagic.h"		/* Remove if not metaconfig -M */

#ifndef HAS_SCANDIR

extern Malloc_t malloc();
extern Malloc_t realloc();

extern DIR *opendir();
extern Direntry_t *readdir();

#define DIR_NULL	((DIR *) 0)
#define ENTRY_NULL	((Direntry_t *) 0)

static int alphasort _((Direntry_t **, Direntry_t **));

/*
 * scandir
 *
 * This routine reads the directory `dirnam' and builds an array of
 * pointers to directory entries using malloc(). The second parameter
 * is the address of a pointer to an array of structure pointers. The
 * third parameter is a pointer to a routine which is called with a
 * pointer to a directory entry and should return a non zero value
 * if the directory entry should be included in the arrary. If this
 * pointer is NULL, then all the directory entries will be included.
 * The last argument is a pointer to a routine which is passed to
 * qsort() to sort the completed array. If this pointer is NULL, the
 * array is not sorted.
 * scandir() returns the number of entries in the array and a pointer
 * to the array through the parameter namlist.
 * alphasort() is a routine which sorts the array alphabetically.
 */
V_FUNC(int scandir, (dirnam, namelist, sel, comp),
	char *dirnam			/* Direcotry name */ NXT_ARG
	Direntry_t ***namelist	/* Pointer to an array of struct ptrs */ NXT_ARG
	int (*sel)()			/* Routine to select entries */ NXT_ARG
	int (*comp)()			/* Routine passed to qsort */)
{
	DIR *dirp;				/* Returned by opendir() */
	Direntry_t *dp;			/* Read entry */
	Direntry_t *dp_save;	/* Place where entry is stored */
	Direntry_t **tmplist;	/* Where the array list is stored */
	int nent = 0;			/* Number of entries */

	dirp = opendir(dirnam);
	if (dirp == DIR_NULL)
		return -1;			/* Directory cannot be opened for reading */

	for (dp = readdir(dirp); dp != ENTRY_NULL; dp = readdir(dirp)) {
		if (sel == ((int (*)()) 0) || (*sel)(dp)) {
			/* If entry has to be included */
			nent++;		/* One more entry */

			if (nent == 1) {	/* Create array for first entry */
				tmplist = (Direntry_t **)
					malloc(sizeof(Direntry_t *));
				if (tmplist == (Direntry_t **) 0)
					return -1;		/* Cannot create array */
			} else {				/* Reallocate for a new entry */
				tmplist = (Direntry_t **)
					realloc(tmplist, nent*sizeof(Direntry_t *));
				if (tmplist == (Direntry_t **) 0)
					return -1;		/* Cannot reallocate array */
			}

			dp_save = (Direntry_t *) malloc(sizeof(Direntry_t));
			if (dp_save == ENTRY_NULL)
				return -1;		/* No space to save entry */
			bcopy((char *) dp, (char *) dp_save, sizeof(Direntry_t));
			*(tmplist+(nent-1)) = dp_save;
		}
	}

	if (comp != ((int (*)()) 0) && nent)	/* Need sorting ? */
		qsort(tmplist, nent, sizeof(Direntry_t *), comp);

	*namelist = tmplist;	/* Passes the address of the arrray */
	closedir(dirp);			/* Close directory */

	return nent;			/* Number of items */
}

P_FUNC(int alphasort, (d1, d2),
	Direntry_t **d1 NXT_ARG Direntry_t **d2)
{
	return strcmp((*d1)->d_name, (*d2)->d_name);
}

#endif