⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 getsdir.c

📁 minicom2.0源代码
💻 C
字号:
/* * getsdir.c * *	Get and return a sorted directory listing * *	Copyright (c) 1998 by James S. Seymour (jseymour@jimsun.LinxNet.com) * *	This code is free software; you can redistribute it and/or *	modify it under the terms of the GNU General Public License *	as published by the Free Software Foundation; either version *	2 of the License, or (at your option) any later version. * *	Note: this code uses "wildmat.c", which has different copyright *	and licensing conditions.  See the source, Luke. */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include "rcsid.h"RCSID("$Id: getsdir.c,v 1.4 2000/03/16 17:59:38 walker Exp $")#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <errno.h>#include "port.h"	/* from minicom: for needed for _PROTO macro only */#include "getsdir.h"#include "intl.h"_PROTO(extern int wildmat, (char *, char *));	/* pattern matcher *//* locally defined constants */ #define MAX_CNT 100		/* number of entries to hold in holding buf */typedef struct dat_buf {		/* structure of input buffers */    struct dat_buf *nxt;		/* pointer to next buffer */    unsigned cnt;			/* data count in present buffer */    GETSDIR_ENTRY data[MAX_CNT];	/* data in present buffer */} DAT_BUF;static DAT_BUF *datb_frst;		/* pointer to first data buffer */static DAT_BUF *datb_cur;		/* pointer to current data buffer */static int g_sortflags;			/* sort flags *//* sort compare routines */_PROTO(static int namecmpr, (GETSDIR_ENTRY *d1, GETSDIR_ENTRY *d2));_PROTO(static int timecmpr, (GETSDIR_ENTRY *d1, GETSDIR_ENTRY *d2));_PROTO(static void free_up, (void));		/* free-up used memory *//* * name:	getsdir * * purpose:	To return a directory listing - possibly sorted * * synopsis:	#include <dirent.h> * *		int getsdir(dirpath, pattern, sortflags, modemask, datptr, len) *		char *dirpath; *		char *pattern; *		int sortflags; *		mode_t modemask; *		GETSDIR_ENTRY **datptr; *		int *len; * * input:	 *dirpath - pointer to path to directory to get list of *			    files from *		 *pattern - pointer to optional wildmat pattern *		sortflags - specification flags of how to sort the *			    resulting list.  See descriptions below. *		 modemask - caller-supplied mode mask.  Bits in this will *			    be ANDed against directory entries to determine *			    whether to return them.  Ignored if 0. *		 **datptr - pointer to a destination pointer variable. *			    getsdir will allocate the required amount *			    of memory for the results and will return a *			    pointer to the returned data in this variable. * *			    The data will be in the form: *				typedef struct dirEntry { *				    char fname[MAXNAMLEN + 1]; *				    time_t time; *				    mode_t mode; *				} GETSDIR_ENTRY; *		     *len - pointer to int to contain length of longest *			    string in returned array. * * process:	For each 0..MAX_CNT values read from specified directory, *		allocates a temporary buffer to store the entries into. *		When end of directory is detected, merges the buffers into *		a single array of data and sorts into order based on key. * * output:	Count of number of data items pointed to by datptr or *		-1 if error.  errno may or may not be valid, based on *		type of error encountered. * * notes:	If there is any error, -1 is returned. * *		It is the caller's responsibility to free the memory *		block pointed to by datptr on return when done with the *		data, except in case of error return. * *		See also: opendir(3C), readdir(3C), closedir(3C), qsort(3C) * *		The pattern parameter is optional and may be 0-length or *		a NULL pointer. * *		The sort flags affect the output as follows: * *		    GETSDIR_PARNT - include parent dir (..) *		    GETSDIR_NSORT - sort by name *		    GETSDIR_TSORT - sort by time (NSORT wins if both) * *		    The following are only meaningful if GETSDIR_NSORT or *		    GETSDIR_TSORT are specified: * *			GETSDIR_DIRSF - dirs first *			GETSDIR_DIRSL - dirs last *			GETSDIR_RSORT - reverse sort (does not affect *					GETSDIR_DIRSF/GETSDIR_DIRSL) * *		So-called "hidden" files (those beginning with a ".") are *		not returned unless a pattern like ".*" is specified. * *		The present directory (".") is never returned. */intgetsdir(dirpath, pattern, sortflags, modemask, datptr, len)char *dirpath;char *pattern;int sortflags;mode_t modemask;GETSDIR_ENTRY **datptr;int *len;{    unsigned cnt;		/* data count */    DIR *dirp;			/* point to open dir */    struct dirent *dp;		/* structure of dir as per system */    struct stat statbuf;	/* structure of file stat as per system */    char fpath[BUFSIZ];		/* filename with dir path prepended */    int indx;			/* g-p array indexer */    int cmprstat;    DAT_BUF *datb_sav;		/* pointer to previous data buffer */    g_sortflags = sortflags;		/* for sort funcs */    *len = 0;				/* longest name */    datb_frst = (DAT_BUF *) NULL;	/* init pointers to first data buff */    datb_cur  = (DAT_BUF *) NULL;    /* open the specified directory */    if ((dirp = opendir(dirpath)) == NULL)	        return(-1);    /* discard current, and possibly parent, dir entries */    if(readdir(dirp) == NULL || 	(!(sortflags & GETSDIR_PARNT) && readdir(dirp) == NULL))    {	fprintf(stderr, _("DBUG: initial readdir() failed (errno == %d)\n"),	    errno);	perror("readdir");	fflush(stderr);    }    for(cnt = 1;; ++cnt)	/* for buffer count 1 to whatever... */    {	datb_sav = datb_cur;	/* save pointer to previous buffer */	/* get a new buffer */        if((datb_cur = (DAT_BUF*)calloc(1,sizeof(DAT_BUF))) == (DAT_BUF*)NULL)	{	    closedir(dirp);            return(-1);	}	/* init new buffer link pointer */	datb_cur->nxt = (DAT_BUF *) NULL;	if(datb_frst == (DAT_BUF *) NULL)	/* if first buff... */            datb_frst = datb_cur;		/* ...init first buff pointer */	else					/* else... */	    datb_sav->nxt = datb_cur;		/* ...link to new */	/* while the current buffer is not full, get directory entries */        for(datb_cur->cnt = 0; datb_cur->cnt < MAX_CNT; )            if((dp = readdir(dirp)) != NULL)	/* get next directory entry */	    {		if((sortflags & GETSDIR_PARNT) &&		   strcmp(dp->d_name, "..") == 0)		{		    cmprstat = 1;		}		else if(pattern && strlen(pattern))		    cmprstat = wildmat(dp->d_name, pattern);		else		    cmprstat = 1;		if(cmprstat)	/* matching name? */		{		    int l;		    /* copy the filename */		    strncpy(datb_cur->data[datb_cur->cnt].fname,			    dp->d_name,			    MAXNAMLEN);	            /* get information about the directory entry */	            snprintf(fpath, sizeof(fpath), "%s/%s", dirpath, dp->d_name);                    if(stat(fpath, &statbuf))	/* if error getting stat... */		    {#if 0			free_up();		/* free-up used memory */		        closedir(dirp);		/* close file pointer */		        return(-1);		/* nobody home */#endif			continue;		    }		    if(modemask && !(S_IFMT & modemask & statbuf.st_mode))			continue;		    if((l = strlen(dp->d_name)) > *len)			*len = l;		    datb_cur->data[datb_cur->cnt].time = statbuf.st_mtime;		    datb_cur->data[datb_cur->cnt].mode = statbuf.st_mode;		    ++datb_cur->cnt;	/* bump array index / data count */		}	    }	    else	        break;			/* at end of directory */	if(datb_cur->cnt < MAX_CNT)	/* if less than full buffer... */	    break;			/* ...all done */    }        closedir(dirp);		/* close file pointer */    /* get memory for single array */    if((*datptr = (GETSDIR_ENTRY *) calloc(cnt, sizeof(datb_cur->data)))	== NULL)    {	/* couldn't get space, clear everything up */	free_up();		/* free-up used memory */        return(-1);		/* error */    }    /* copy/concatenate the data */    cnt = indx = 0;			/* init final count and dest index */    do    {	datb_cur = datb_frst;	/* copy data in one swell foop */	memcpy(*datptr+indx*MAX_CNT, datb_cur->data, sizeof(datb_cur->data));	cnt += datb_cur->cnt;	/* adjust data count */	++indx;			/* bump destination index */	datb_frst = datb_cur->nxt;	free(datb_cur);		/* free no longer needed buffer */    } while (datb_frst);  /* while more to go */    free_up();	/* free-up used memory */    /* post-process array by option */    if(cnt && sortflags) {	if(sortflags & GETSDIR_NSORT)	    qsort(*datptr, cnt, sizeof(GETSDIR_ENTRY),		  (int (*)(const void *, const void *))namecmpr);	else if(sortflags & GETSDIR_TSORT)	    qsort(*datptr, cnt, sizeof(GETSDIR_ENTRY),		  (int (*)(const void *, const void *))timecmpr);    }    return(cnt);} /* getsdir *//* * name:	free_up * * purpose:	free up memory allocated for temporary buffers * * synopsis:	static void freeup() * * input:	none * * process:	as under purpose * * output:	none * * notes:	none */static voidfree_up(){    if((datb_cur = datb_frst) != (DAT_BUF *) NULL)	/* start with first */	do				/* and free 'em all */	{	    datb_frst = datb_cur->nxt;	    free(datb_cur);	} while ((datb_cur = datb_frst));} /* free_up *//* * name:	namecmpr * * purpose:	return stat to qsort on comparison between name fields in *		directory entry. * * synopsis:	static in namecmpr(d1, d2) *		GETSDIR_ENTRY *d1; *		GETSDIR_ENTRY *d2; * * input:	See explanation of qsort * * process:	See explanation of qsort * * output:	See explanation of qsort * * notes:	See explanation of qsort */static intnamecmpr(d1, d2)GETSDIR_ENTRY *d1, *d2;{    if(g_sortflags & (GETSDIR_DIRSF | GETSDIR_DIRSL)) {	if(S_ISDIR((d1->mode)) && ! S_ISDIR((d2->mode)))	    return((g_sortflags & GETSDIR_DIRSF)? -1 : 1);	else if(S_ISDIR((d2->mode)) && ! S_ISDIR((d1->mode)))	    return((g_sortflags & GETSDIR_DIRSF)? 1 : -1);    }    return((g_sortflags & GETSDIR_RSORT)?	strcmp(d2->fname, d1->fname) : strcmp(d1->fname, d2->fname));} /* namecmpr *//* * name:	timecmpr * * purpose:	return stat to qsort on comparison between time fields in *		directory entry. * * synopsis:	static in timecmpr(d1, d2) *		GETSDIR_ENTRY *d1; *		GETSDIR_ENTRY *d2; * * input:	See explanation of qsort * * process:	See explanation of qsort * * output:	See explanation of qsort * * notes:	See explanation of qsort */static inttimecmpr(d1, d2)GETSDIR_ENTRY *d1, *d2;{    if(g_sortflags & (GETSDIR_DIRSF | GETSDIR_DIRSL)) {	if(S_ISDIR((d1->mode)) && ! S_ISDIR((d2->mode)))	    return((g_sortflags & GETSDIR_DIRSF)? -1 : 1);	else if(S_ISDIR((d2->mode)) && ! S_ISDIR((d1->mode)))	    return((g_sortflags & GETSDIR_DIRSF)? 1 : -1);    }    return((g_sortflags & GETSDIR_RSORT)?	(d2->time - d1->time) : (d1->time - d2->time));} /* timecmpr */#ifdef GETSDIR_STANDALONE_TEST/* * debug for getsdir() * * usage: getsdir <dirpath> * */extern char *ctime();voidmain(argc, argv)int argc;char *argv[];{    GETSDIR_ENTRY *dirdat;    int cnt, index;    int sortflags = 0;    mode_t modemask = (mode_t) 0;    int len;    if(argc != 4)    {      fprintf(stderr,"usage: %s <dirpath> <pattern> <sortflags>\n", argv[0]);      exit(1);    }    switch(argv[3][0]) {	case 'n': sortflags = GETSDIR_NSORT;		  break;	case 't': sortflags = GETSDIR_TSORT;		  break;    }/*    sortflags |= GETSDIR_DIRSL | GETSDIR_RSORT; */    sortflags |= GETSDIR_DIRSF;/*    sortflags |= GETSDIR_PARNT; *//*    modemask = S_IFDIR | S_IFREG; */    printf("modemask==%x\n", modemask);    if((cnt = getsdir(argv[1], argv[2], sortflags, modemask, &dirdat, &len)) == -1)    {	fprintf(stderr, "%s: error getting directory\n", argv[0]);	exit(1);    }    printf(_("%d files:\n"), cnt);    for(index = 1; index <= cnt; ++index, ++dirdat)        printf("%2d: %-20s%s",	    index, dirdat->fname, ctime(&dirdat->time));    free(dirdat);    exit(0);}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -