📄 pc_enum.c
字号:
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright EBS Inc. 1996
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*/
/* pc_enumerate - List select all directory entries that match rules and
* allow a callback routine to process each on.
*
* Description - This routine traverses a subdirectory tree. It tests each
* directory entry to see if it matches user supplied selection criteria.
* if it does match the criteria a user supplied callback function is
* called with the full path name of the directory entry and a pointer
* to a DSTAT structure that contains detailed information about the
* directory entry. (see the manual page for a detailed description of the
* DSTAT structure.
*
* Selection criteria - Two arguments are used to determine the selection
* criteria. On is a flags word that specifies attributes the other is
* a pattern that specifies a wild card pattern.
* The flags argument contains a bitwise or of one or more of the following:
* MATCH_DIR - Select directory entries
* MATCH_VOL - Select volume labels
* MATCH_FILES - Select files
* MATCH_DOT - Select the '.' entry MATH_DIR must be true also
* MATCH_DOTDOT - Select the '..' entry MATCH_DIR must be true also
*
* The selection pattern is a standard wildcard pattern such as '*.*' or
* *.txt.
* Note: Patterns don't work the same for VFAT and DOS 8.3. If VFAT is
* enable the pattern *.* will return any file name that has a '.' in it
* in 8.3 systems it returns all files.
*
* Note: pc_enumerate() requires a fair amount of buffer space to function.
* Instead of allocating the space internally we require that the application
* pass two buffers of size EMAXPATH in to the function. See below.
*
* Se
* Summary:
*
* int pc_enumerate(
* byte * from_pattern_buffer - pointer to a scratch buffer of size EMAXPATH
* byte * spath_buffer - pointer to a scratch buffer of size EMAXPATH
* byte * dpath_buffer - pointer to a scratch buffer of size EMAXPATH
* byte * root_search - Root of the search IE C:\ or C:\USR etc.
* word match_flags - Selection flags (see above)
* byte match_pattern - Match pattern (see above)
* int maxdepth - Maximum depth of the traversal.
* Note: to scan only one level set this to
* 1. For all levels set it to 99
* PENUMCALLBACK pcallback - User callback function. (see below)
*
* Return value
* pc_enumerate() returns 0 unless the callback function returns a non-
* zero value at any point. If the callback returns a non-zero value the
* scan terminates imediately and returns the returned value to the
* application.
*
* About the callback.
*
* The callback function is a function that returns an integer and is passed
* the fully qualified path to the current directory entry and a DSTAT
* structure. The callback fuction must return 0 if it wishes the scan to
* continue or any other integer value to stop the scan and return the
* callback's return value to the application layer.
*
* Examples
*
* The next two function implement a multilevel directory scan.
* int rdir_callback(char *path, DSTAT *d) {printf("%s\n", path);return(0);}
*
* rdir(char *path, char *pattern)
* {
* pc_enumerate(from_path,from_pattern,spath,dpath,path,
* (MATCH_DIR|MATCH_VOL|MATCH_FILES), pattern, 99, rdir_callback);
* }
*
* Poor mans deltree package
* int delfile_callback(char *path, DSTAT *d) {
* pc_unlink(path); return(0);
* }
* int deldir_callback(char *path, DSTAT *d) {
* pc_rmdir(path); return(0);
* }
*
*
* deltree(char *path)
* {
* int i;
* ==> First delete all of the files
* pc_enumerate(from_path,from_pattern,spath,dpath,path,
* (MATCH_FILES), "*",99, delfile_callback);
* i = 0;
* ==> Now delete all of the dirs.. deleting path won't work until the
* ==> tree is empty
* while(!pc_rmdir(path) && i++ < 50)
* pc_enumerate(from_path,from_pattern,spath,dpath,path,
* (MATCH_DIR), "*", 99, deldir_callback);
* }
*
*/
#include <pcdisk.h>
#define MATCH_DIR 0x01
#define MATCH_VOL 0x02
#define MATCH_FILES 0x04
#define MATCH_DOT 0x08
#define MATCH_DOTDOT 0x10
typedef int (*PENUMCALLBACK)(byte *path, DSTAT *pstat);
int pc_enumerate(
byte * from_path_buffer,
byte * from_pattern_buffer,
byte * spath_buffer,
byte * dpath_buffer,
byte * root_search,
word match_flags,
byte * match_pattern,
int maxdepth,
PENUMCALLBACK pcallback);
#if (VFAT)
#define ALL_FILES "*"
#else
#define ALL_FILES "*.*"
#endif
int get_parent_path(byte *parent, byte *path);
int dirscan_isdot(DSTAT *statobj);
int dirscan_isdotdot(DSTAT *statobj);
int pc_enumerate(
byte * from_path_buffer,
byte * from_pattern_buffer,
byte * spath_buffer,
byte * dpath_buffer,
byte * root_search,
word match_flags,
byte * match_pattern,
int maxdepth,
PENUMCALLBACK pcallback)
{
int dir_index[30];
dword dir_block[30];
int depth;
DSTAT statobj;
int process_it;
int dodone;
int call_back;
int ret_val;
#if (!VFAT)
int i;
/* IN 8.3 systems we parse the match pattern into file and ext parts */
char filepat[9];
char extpat[9];
pc_fileparse(filepat, extpat, (char *)match_pattern);
for(i = 0; i < 8; i++) if (filepat[i]==' ') filepat[i]=0;
for(i = 0; i < 3; i++) if (extpat[i]==' ') extpat[i]=0;
#endif
ret_val = 0;
pc_str2upper((char *)from_path_buffer, (char *) root_search);
depth = 0;
pc_mpath(from_pattern_buffer, from_path_buffer, (byte *)ALL_FILES);
dir_index[0] = 0;
dir_block[0] = 0;
do
{
step_into_dir:
dodone = 0;
if (pc_gfirst(&statobj, (char *)from_pattern_buffer))
{
dodone = 1;
process_it = 0;
do
{
if (!dir_block[depth] || ((dir_block[depth] ==
((DROBJ *) (statobj.pobj))->blkinfo.my_block ) &&
(dir_index[depth] ==
((DROBJ *) (statobj.pobj))->blkinfo.my_index )))
{
process_it = 1;
}
if (process_it)
{
call_back = 1;
/* Don't report directories if not requested */
if ((statobj.fattribute & ADIRENT) &&
!(match_flags & MATCH_DIR) )
call_back = 0;
/* Don't report volumes if not requested */
if (call_back && (statobj.fattribute & AVOLUME) &&
!(match_flags & MATCH_VOL) )
call_back = 0;
/* Don't report plain files if not requested */
if (call_back && !(statobj.fattribute & (AVOLUME|ADIRENT)) &&
!(match_flags & MATCH_FILES) )
call_back = 0;
/* Don't report DOT if not requested */
if (call_back && dirscan_isdot(&statobj) && !(match_flags & MATCH_DOT))
call_back = 0;
/* Don't report DOTDOT if not requested */
if (call_back && dirscan_isdotdot(&statobj) && !(match_flags & MATCH_DOTDOT))
call_back = 0;
if (call_back)
{
/* Take it if the pattern match work */
#if (VFAT)
/* Under VFAT do a pattern match on the long file name */
if (statobj.lfname[0])
call_back = pc_patcmp(match_pattern, statobj.lfname, TRUE);
else
call_back = pc_patcmp(match_pattern, (byte *)(statobj.filename), TRUE);
#else
/* Non VFAT uses 8.3 matching conventions */
pc_fileparse(filepat, extpat, (char *)match_pattern);
call_back =
pc_patcmp((byte *)&statobj.fname[0], (byte *)&filepat[0] , 8, TRUE);
call_back = call_back &&
pc_patcmp((byte *)&statobj.fext[0], (byte *)&extpat[0] , 3,TRUE);
#endif
}
/* Construct the full path */
pc_mpath(dpath_buffer, from_path_buffer, (byte *)statobj.filename);
if (call_back && pcallback)
{
/* If the callback returns non zero he says quit */
ret_val = pcallback(dpath_buffer, &statobj);
if (ret_val)
{
pc_gdone(&statobj);
goto ex_it;
}
}
}
/* If it is a subdirectory and we are still in our depth range
then process the subdirectory */
if (process_it && (depth < maxdepth) &&
!dirscan_isdot(&statobj) &&
!dirscan_isdotdot(&statobj))
{
/* Construct the full path */
pc_mpath(spath_buffer, from_path_buffer, (byte *)statobj.filename);
if (statobj.fattribute & (AVOLUME | ADIRENT))
{
if (pc_gnext(&statobj))
{
/* If path is a dir, mark our place and step in */
dir_block[depth] = ((DROBJ *) (statobj.pobj))->blkinfo.my_block;
dir_index[depth] = ((DROBJ *) (statobj.pobj))->blkinfo.my_index;
dodone = 0;
pc_gdone(&statobj);
}
else
{
dodone = 0;
pc_gdone(&statobj);
dir_index[depth] = -1;
}
depth += 1;
dir_block[depth] = 0;
dir_index[depth] = 0;
tc_strcpy((char *)from_path_buffer, (char *)spath_buffer);
pc_mpath(from_pattern_buffer, from_path_buffer, (byte *)ALL_FILES);
goto step_into_dir;
}
}
} while (pc_gnext(&statobj)); /* Get the next file in dir */
if (dodone)
pc_gdone(&statobj);
}
if (!get_parent_path(from_path_buffer, from_path_buffer))
break;
pc_mpath(from_pattern_buffer, from_path_buffer, (byte *)ALL_FILES);
depth--;
while (depth >= 0 && dir_index[depth] == -1)
{
if (!get_parent_path(from_path_buffer, from_path_buffer))
break;
pc_mpath(from_pattern_buffer, from_path_buffer, (byte *)ALL_FILES);
depth--;
}
} while (depth >= 0);
ex_it:
return (ret_val);
}
int get_parent_path(byte *parent, byte *path) /*__fn__*/
{
byte *last_backslash;
int size;
last_backslash = 0;
size = 0;
while (*path != '\0')
{
size++;
if (*path == '\\')
{
last_backslash = parent;
}
*(parent++) = *(path++);
}
/* This is to prevent catastrophie if caller ignores failure */
*parent = '\0';
if (size < 3)
return (0);
if (last_backslash)
*last_backslash = '\0';
return (1);
}
/************************************************************************
* *
* File system abstraction layer *
* *
************************************************************************/
int dirscan_isdot(DSTAT *statobj)
{
return(tc_strcmp(".", statobj->filename)==0);
}
int dirscan_isdotdot(DSTAT *statobj)
{
return(tc_strcmp("..", statobj->filename)==0);
}
#ifdef NOTDEF
/* The section from here to the bottom of the file contains code that
shows via example how to use the enumerate function.
*/
#include <conio.h>
#include <ctype.h>
#include <direct.h>
#include <dos.h>
#include <fcntl.h>
#include <io.h>
#include <sys\types.h>
#include <stdlib.h>
#include <stdio.h>
void usage(char *progname)
{
printf("Usage: %s [options] <source_path> <dest_path_1> [<dest_path_2> ...]\n",progname);
}
rdir(char *path, char *pattern);
deltree(char *path, char *pattern);
#define FILTER ALL_FILES /* Default filter */
int main(int argc,char **argv)
{
byte src_path[EMAXPATH];
byte filter[20];
char op;
ks_kernel_init();
argc--;
argv++;
if (argc < 2)
{
goto usage;
}
op = *argv[0];
tc_strcpy((char *)filter,FILTER);
argc--; argv++;
/* Process user options */
tc_strcpy(src_path,*argv);
argc--; argv++;
if (argc)
{
tc_strcpy(filter,*argv);
}
else
{
tc_strcpy((char *)filter,FILTER);
}
if (op=='R')
{
rdir(src_path, filter);
}
else if (op == 'D')
{
deltree(src_path, filter);
}
else
{
usage:
printf("(R)dir or (D)eltree PATH [pattern]\n");
}
// treeprintnew (src_path, filter, be_verbose);
}
/* Examples */
byte from_path[EMAXPATH];
byte from_pattern[EMAXPATH];
byte spath[EMAXPATH];
byte dpath[EMAXPATH];
/* Recursive DIR function */
int rdir_callback(char *path, DSTAT *d)
{
printf("%s\n", path);
return(0);
}
rdir(char *path, char *pattern)
{
pc_enumerate(from_path,from_pattern,spath,dpath,path,
(MATCH_DIR|MATCH_VOL|MATCH_FILES), pattern, 99, rdir_callback);
}
/* Poor mans deltree package */
int delfile_callback(char *path, DSTAT *d)
{
printf("Deleting file %s\n", path);
pc_unlink(path);
return(0);
}
int deldir_callback(char *path, DSTAT *d)
{
printf("Deleting directory %s\n", path);
pc_rmdir(path);
return(0);
}
deltree(char *path)
{
int i;
/* First delete all of the files */
pc_enumerate(from_path,from_pattern,spath,dpath,path,
(MATCH_FILES), "*",99, delfile_callback);
i = 0;
/* Now delete all of the dirs.. deleting the root of the path won't
work until the tree is empty */
while(!pc_rmdir(path) && i++ < 50)
{
pc_enumerate(from_path,from_pattern,spath,dpath,path,
(MATCH_DIR), "*", 99, deldir_callback);
}
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -