|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* getsdir.c
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* Get and return a sorted directory listing
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* Copyright (c) 1998 by James S. Seymour (jseymour@jimsun.LinxNet.com)
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* This code is free software; you can redistribute it and/or
|
|
Packit |
15a96c |
* modify it under the terms of the GNU General Public License
|
|
Packit |
15a96c |
* as published by the Free Software Foundation; either version
|
|
Packit |
15a96c |
* 2 of the License, or (at your option) any later version.
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* You should have received a copy of the GNU General Public License along
|
|
Packit |
15a96c |
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
Packit |
15a96c |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* Note: this code uses "wildmat.c", which has different copyright
|
|
Packit |
15a96c |
* and licensing conditions. See the source, Luke.
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* 2011: getsdir() has been simplified wrt memory management by
|
|
Packit |
15a96c |
* Adam Lackorzynski
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
#ifdef HAVE_CONFIG_H
|
|
Packit |
15a96c |
#include <config.h>
|
|
Packit |
15a96c |
#endif
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
#include <stdio.h>
|
|
Packit |
15a96c |
#include <stdlib.h>
|
|
Packit |
15a96c |
#include <string.h>
|
|
Packit |
15a96c |
#include <sys/types.h>
|
|
Packit |
15a96c |
#include <sys/stat.h>
|
|
Packit |
15a96c |
#include <errno.h>
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
#include "getsdir.h"
|
|
Packit |
15a96c |
#include "intl.h"
|
|
Packit |
15a96c |
#include "minicom.h"
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/* locally defined constants */
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
#define MAX_CNT 100 /* number of entries to hold in holding buf */
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
typedef struct dat_buf { /* structure of input buffers */
|
|
Packit |
15a96c |
struct dat_buf *nxt; /* pointer to next buffer */
|
|
Packit |
15a96c |
unsigned cnt; /* data count in present buffer */
|
|
Packit |
15a96c |
GETSDIR_ENTRY data[MAX_CNT]; /* data in present buffer */
|
|
Packit |
15a96c |
} DAT_BUF;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
static int g_sortflags; /* sort flags */
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/* sort compare routines */
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* name: namecmpr
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* purpose: return stat to qsort on comparison between name fields in
|
|
Packit |
15a96c |
* directory entry.
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* synopsis: static in namecmpr(d1, d2)
|
|
Packit |
15a96c |
* GETSDIR_ENTRY *d1;
|
|
Packit |
15a96c |
* GETSDIR_ENTRY *d2;
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* input: See explanation of qsort
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* process: See explanation of qsort
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* output: See explanation of qsort
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* notes: See explanation of qsort
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
static int namecmpr(GETSDIR_ENTRY *d1, GETSDIR_ENTRY *d2)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
if (g_sortflags & (GETSDIR_DIRSF | GETSDIR_DIRSL)) {
|
|
Packit |
15a96c |
if (S_ISDIR((d1->mode)) && !S_ISDIR((d2->mode)))
|
|
Packit |
15a96c |
return (g_sortflags & GETSDIR_DIRSF) ? -1 : 1;
|
|
Packit |
15a96c |
else if (S_ISDIR((d2->mode)) && ! S_ISDIR((d1->mode)))
|
|
Packit |
15a96c |
return (g_sortflags & GETSDIR_DIRSF) ? 1 : -1;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
return (g_sortflags & GETSDIR_RSORT)
|
|
Packit |
15a96c |
? strcmp(d2->fname, d1->fname) : strcmp(d1->fname, d2->fname);
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
} /* namecmpr */
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* name: timecmpr
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* purpose: return stat to qsort on comparison between time fields in
|
|
Packit |
15a96c |
* directory entry.
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* synopsis: static in timecmpr(d1, d2)
|
|
Packit |
15a96c |
* GETSDIR_ENTRY *d1;
|
|
Packit |
15a96c |
* GETSDIR_ENTRY *d2;
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* input: See explanation of qsort
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* process: See explanation of qsort
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* output: See explanation of qsort
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* notes: See explanation of qsort
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
static int timecmpr(GETSDIR_ENTRY *d1, GETSDIR_ENTRY *d2)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
if (g_sortflags & (GETSDIR_DIRSF | GETSDIR_DIRSL)) {
|
|
Packit |
15a96c |
if (S_ISDIR((d1->mode)) && !S_ISDIR((d2->mode)))
|
|
Packit |
15a96c |
return (g_sortflags & GETSDIR_DIRSF) ? -1 : 1;
|
|
Packit |
15a96c |
else if (S_ISDIR((d2->mode)) && ! S_ISDIR((d1->mode)))
|
|
Packit |
15a96c |
return (g_sortflags & GETSDIR_DIRSF) ? 1 : -1;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
return (g_sortflags & GETSDIR_RSORT)
|
|
Packit |
15a96c |
? (d2->time - d1->time) : (d1->time - d2->time);
|
|
Packit |
15a96c |
} /* timecmpr */
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* name: getsdir
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* purpose: To return a directory listing - possibly sorted
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* synopsis: #include <dirent.h>
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* int getsdir(dirpath, pattern, sortflags, modemask, datptr, len)
|
|
Packit |
15a96c |
* const char *dirpath;
|
|
Packit |
15a96c |
* const char *pattern;
|
|
Packit |
15a96c |
* int sortflags;
|
|
Packit |
15a96c |
* mode_t modemask;
|
|
Packit |
15a96c |
* GETSDIR_ENTRY **datptr;
|
|
Packit |
15a96c |
* int *len;
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* input: *dirpath - pointer to path to directory to get list of
|
|
Packit |
15a96c |
* files from
|
|
Packit |
15a96c |
* *pattern - pointer to optional wildmat pattern
|
|
Packit |
15a96c |
* sortflags - specification flags of how to sort the
|
|
Packit |
15a96c |
* resulting list. See descriptions below.
|
|
Packit |
15a96c |
* modemask - caller-supplied mode mask. Bits in this will
|
|
Packit |
15a96c |
* be ANDed against directory entries to determine
|
|
Packit |
15a96c |
* whether to return them. Ignored if 0.
|
|
Packit |
15a96c |
* **datptr - pointer to a destination pointer variable.
|
|
Packit |
15a96c |
* getsdir will allocate the required amount
|
|
Packit |
15a96c |
* of memory for the results and will return a
|
|
Packit |
15a96c |
* pointer to the returned data in this variable.
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* The data will be in the form:
|
|
Packit |
15a96c |
* typedef struct dirEntry {
|
|
Packit |
15a96c |
* char fname[MAXNAMLEN + 1];
|
|
Packit |
15a96c |
* time_t time;
|
|
Packit |
15a96c |
* mode_t mode;
|
|
Packit |
15a96c |
* } GETSDIR_ENTRY;
|
|
Packit |
15a96c |
* *len - pointer to int to contain length of longest
|
|
Packit |
15a96c |
* string in returned array.
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* process: For each 0..MAX_CNT values read from specified directory,
|
|
Packit |
15a96c |
* allocates a temporary buffer to store the entries into.
|
|
Packit |
15a96c |
* When end of directory is detected, merges the buffers into
|
|
Packit |
15a96c |
* a single array of data and sorts into order based on key.
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* output: Count of number of data items pointed to by datptr or
|
|
Packit |
15a96c |
* -1 if error. errno may or may not be valid, based on
|
|
Packit |
15a96c |
* type of error encountered.
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* notes: If there is any error, -1 is returned.
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* It is the caller's responsibility to free the memory
|
|
Packit |
15a96c |
* block pointed to by datptr on return when done with the
|
|
Packit |
15a96c |
* data, except in case of error return.
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* See also: opendir(3C), readdir(3C), closedir(3C), qsort(3C)
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* The pattern parameter is optional and may be 0-length or
|
|
Packit |
15a96c |
* a NULL pointer.
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* The sort flags affect the output as follows:
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* GETSDIR_PARNT - include parent dir (..)
|
|
Packit |
15a96c |
* GETSDIR_NSORT - sort by name
|
|
Packit |
15a96c |
* GETSDIR_TSORT - sort by time (NSORT wins if both)
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* The following are only meaningful if GETSDIR_NSORT or
|
|
Packit |
15a96c |
* GETSDIR_TSORT are specified:
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* GETSDIR_DIRSF - dirs first
|
|
Packit |
15a96c |
* GETSDIR_DIRSL - dirs last
|
|
Packit |
15a96c |
* GETSDIR_RSORT - reverse sort (does not affect
|
|
Packit |
15a96c |
* GETSDIR_DIRSF/GETSDIR_DIRSL)
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* So-called "hidden" files (those beginning with a ".") are
|
|
Packit |
15a96c |
* not returned unless a pattern like ".*" is specified.
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* The present directory (".") is never returned.
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
int getsdir(const char *dirpath, const char *pattern, int sortflags,
|
|
Packit |
15a96c |
mode_t modemask, GETSDIR_ENTRY **datptr, int *len)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
unsigned cnt = 0; /* data count */
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
DIR *dirp; /* point to open dir */
|
|
Packit |
15a96c |
struct dirent *dp; /* structure of dir as per system */
|
|
Packit |
15a96c |
struct stat statbuf; /* structure of file stat as per system */
|
|
Packit |
15a96c |
char fpath[BUFSIZ]; /* filename with dir path prepended */
|
|
Packit |
15a96c |
int cmprstat;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
g_sortflags = sortflags; /* for sort funcs */
|
|
Packit |
15a96c |
*len = 0; /* longest name */
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/* open the specified directory */
|
|
Packit |
15a96c |
if ((dirp = opendir(dirpath)) == NULL)
|
|
Packit |
15a96c |
return -1;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
while ((dp = readdir(dirp)))
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
if (!strcmp(dp->d_name, "."))
|
|
Packit |
15a96c |
continue;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
if ((sortflags & GETSDIR_PARNT) && !strcmp(dp->d_name, ".."))
|
|
Packit |
15a96c |
cmprstat = 1;
|
|
Packit |
15a96c |
else if (pattern && *pattern)
|
|
Packit |
15a96c |
cmprstat = wildmat(dp->d_name, pattern);
|
|
Packit |
15a96c |
else
|
|
Packit |
15a96c |
cmprstat = 1;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
if (cmprstat)
|
|
Packit |
15a96c |
{ /* matching name? */
|
|
Packit |
15a96c |
*datptr = realloc(*datptr, sizeof(**datptr) * (cnt + 1));
|
|
Packit |
15a96c |
if (!*datptr)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
free(*datptr);
|
|
rpm-build |
c7b29f |
closedir(dirp);
|
|
Packit |
15a96c |
return -1;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/* copy the filename */
|
|
Packit |
15a96c |
strncpy((*datptr)[cnt].fname, dp->d_name, MAXNAMLEN);
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/* get information about the directory entry */
|
|
Packit |
15a96c |
snprintf(fpath, sizeof(fpath), "%s/%s", dirpath, dp->d_name);
|
|
Packit |
15a96c |
if (stat(fpath, &statbuf)) /* if error getting stat... */
|
|
Packit |
15a96c |
continue;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
if (modemask && !(S_IFMT & modemask & statbuf.st_mode))
|
|
Packit |
15a96c |
continue;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
int l;
|
|
Packit |
15a96c |
if ((l = strlen(dp->d_name)) > *len)
|
|
Packit |
15a96c |
*len = l;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
(*datptr)[cnt].time = statbuf.st_mtime;
|
|
Packit |
15a96c |
(*datptr)[cnt].mode = statbuf.st_mode;
|
|
Packit |
15a96c |
(*datptr)[cnt].cflags = 0;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
cnt++;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
closedir(dirp); /* close file pointer */
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/* post-process array by option */
|
|
Packit |
15a96c |
if (cnt && sortflags) {
|
|
Packit |
15a96c |
if (sortflags & GETSDIR_NSORT)
|
|
Packit |
15a96c |
qsort(*datptr, cnt, sizeof(GETSDIR_ENTRY),
|
|
Packit |
15a96c |
(int (*)(const void *, const void *))namecmpr);
|
|
Packit |
15a96c |
else if (sortflags & GETSDIR_TSORT)
|
|
Packit |
15a96c |
qsort(*datptr, cnt, sizeof(GETSDIR_ENTRY),
|
|
Packit |
15a96c |
(int (*)(const void *, const void *))timecmpr);
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
return cnt;
|
|
Packit |
15a96c |
} /* getsdir */
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
#ifdef GETSDIR_STANDALONE_TEST
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* debug for getsdir()
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* usage: getsdir <dirpath>
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
extern char *ctime(void);
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
void main(int argc, char **argv)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
GETSDIR_ENTRY *dirdat;
|
|
Packit |
15a96c |
int cnt, index;
|
|
Packit |
15a96c |
int sortflags = 0;
|
|
Packit |
15a96c |
mode_t modemask = (mode_t) 0;
|
|
Packit |
15a96c |
int len;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
if (argc != 4) {
|
|
Packit |
15a96c |
fprintf(stderr,"usage: %s <dirpath> <pattern> <sortflags>\n", argv[0]);
|
|
Packit |
15a96c |
exit(1);
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
switch (argv[3][0]) {
|
|
Packit |
15a96c |
case 'n': sortflags = GETSDIR_NSORT;
|
|
Packit |
15a96c |
break;
|
|
Packit |
15a96c |
case 't': sortflags = GETSDIR_TSORT;
|
|
Packit |
15a96c |
break;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/* sortflags |= GETSDIR_DIRSL | GETSDIR_RSORT; */
|
|
Packit |
15a96c |
sortflags |= GETSDIR_DIRSF;
|
|
Packit |
15a96c |
/* sortflags |= GETSDIR_PARNT; */
|
|
Packit |
15a96c |
/* modemask = S_IFDIR | S_IFREG; */
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
printf("modemask==%x\n", modemask);
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
if ((cnt = getsdir(argv[1], argv[2], sortflags, modemask, &dirdat, &len)) == -1) {
|
|
Packit |
15a96c |
fprintf(stderr, "%s: error getting directory\n", argv[0]);
|
|
Packit |
15a96c |
exit(1);
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
printf(_("%d files:\n"), cnt);
|
|
Packit |
15a96c |
for (index = 1; index <= cnt; ++index, ++dirdat)
|
|
Packit |
15a96c |
printf("%2d: %-20s%s", index, dirdat->fname, ctime(&dirdat->time));
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
free(dirdat);
|
|
Packit |
15a96c |
return 0;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
#endif
|