/* CRDIR.C compatible recursive directory search */ #include #include #include "ccommon.h" #include "crdir.h" #ifdef C_DOS #include #endif static char *_c_delimiter_to_host(char *s) { static char t[CRDIR_MAX_PATHNAME]; int i = 0; while( i < CRDIR_MAX_PATHNAME) { t[i] = s[i]; #ifdef C_UNIX if ( t[i] == '\\' ) t[i] = C_DELIMITER_CHAR; #endif #ifdef C_DOS if ( t[i] == '/' ) t[i] = C_DELIMITER_CHAR; #endif if ( t[i] == '\0' ) break; i++; } t[CRDIR_MAX_PATHNAME-1] = '\0'; return t; } CRDIR *c_openrdir(char *dir, char *pat, int options) { CRDIR *crd; crd = (CRDIR *)malloc(sizeof(struct _CRDIR_struct)); if ( crd != NULL ) { crd->cdir_depth = 0; crd->options = options; c_strncpy(crd->pat, pat, CRDIR_MAX_FILE); c_strncpy(crd->pn, _c_delimiter_to_host(dir), CRDIR_MAX_PATHNAME); if ( crd->pn[0] == '\0' ) strcpy(crd->pn, _c_delimiter_to_host("./")); if ( strcmp( crd->pn+strlen(crd->pn)-1, _c_delimiter_to_host("/")) != 0 ) strcat(crd->pn, _c_delimiter_to_host("/")); crd->pn_end_pos[crd->cdir_depth] = strlen(crd->pn); c_chdir(crd->pn); crd->cdir_list[crd->cdir_depth] = c_opendir(".", crd->pat, crd->options); if ( crd->cdir_list[crd->cdir_depth] != NULL ) { crd->cdir_depth++; crd->mem_dir = NULL; return crd; } free(crd); } return NULL; } static int _c_push_rdir(CRDIR *crd, char *name, int is_dir) { size_t pn_len, name_len; pn_len = strlen(crd->pn); name_len = strlen(name); if ( pn_len+name_len+2 >= CRDIR_MAX_PATHNAME ) return 0; if ( crd->cdir_depth >= CRDIR_MAX_DEPTH ) return 0; if ( crd->cdir_depth == 0 ) return 0; strcpy(crd->pn+pn_len, name); strcpy(crd->pn+pn_len+name_len, _c_delimiter_to_host("/")); crd->pn_end_pos[crd->cdir_depth] = pn_len+name_len+1; crd->cdir_list[crd->cdir_depth] = NULL; if ( is_dir != 0 ) { if ( c_chdir(name) != 0 ) { crd->pn[crd->pn_end_pos[crd->cdir_depth-1]] = '\0'; /* printf("c_chdir(%s) failed\n", name); */ return 0; } crd->cdir_list[crd->cdir_depth] = c_opendir(".", crd->pat, crd->options); if ( crd->cdir_list[crd->cdir_depth] == NULL ) { crd->pn[crd->pn_end_pos[crd->cdir_depth-1]] = '\0'; /* printf("opendir() failed\n"); */ return 0; } } crd->cdir_depth++; return 1; } static int _c_pop_rdir(CRDIR *crd) { if ( crd->cdir_depth == 0 ) return 0; crd->cdir_depth--; if ( crd->cdir_list[crd->cdir_depth] != NULL ) { c_closedir(crd->cdir_list[crd->cdir_depth]); if ( crd->cdir_depth != 0 ) { c_chdir(".."); } } crd->pn[crd->pn_end_pos[crd->cdir_depth-1]] = '\0'; return 1; } struct c_dirent *c_readrdir(CRDIR *crd) { size_t pos; struct c_dirent *de; if ( crd->cdir_depth == 0 ) return NULL; if ( (crd->options & CRDIR_GO_DIRS) != 0 ) { for(;;) { if ( crd->cdir_depth == 0 ) return NULL; pos = crd->cdir_depth-1; if ( crd->mem_dir != NULL ) { de = crd->mem_dir; crd->mem_dir = NULL; _c_push_rdir(crd, c_get_name(de), 1); continue; /* return c_readrdir(crd); */ } de = c_readdir(crd->cdir_list[pos]); if ( de != NULL ) { if ( c_is_dir(de) != 0 ) { if ( strcmp(c_get_name(de),".") == 0 ) continue; /* return c_readrdir(crd); */ if ( strcmp(c_get_name(de),"..") == 0 ) continue; /* return c_readrdir(crd); */ if ( (crd->options & CRDIR_RET_DIRS) != 0 ) { crd->mem_dir = de; return de; } _c_push_rdir(crd, c_get_name(de), 1); continue; /* return c_readrdir(crd); */ } return de; } if ( _c_pop_rdir(crd) != 0 ) { /* return c_readrdir(crd); */ continue; } else break; } } else { pos = crd->cdir_depth-1; for(;;) { de = c_readdir(crd->cdir_list[pos]); if ( de == NULL ) break; if ( c_is_dir(de) != 0 ) { if ( (crd->options & CRDIR_RET_DIRS) != 0 ) return de; } else { return de; } } } return NULL; } void c_closerdir(CRDIR *crd) { if ( crd == NULL ) return; while( _c_pop_rdir(crd) != 0 ) ; free(crd); } #ifdef CRDIR_MAIN #include void main(void) { CRDIR *d; struct c_dirent *e; d = c_openrdir(".", "*.exe", CRDIR_DEFAULT); for(;;) { e = c_readrdir(d); if ( e == NULL ) break; printf("%d %s %-14s %s\n", d->cdir_depth, d->pn, e->d_short_name, e->d_name); } c_closerdir(d); c_io_clear(); } #endif