/* CDIRENT.C (c) 1996 Oliver Kraus */ #include #include #include #include "ccommon.h" #include "cdirent.h" #include "cio.h" #ifdef C_DOS #include #include #include "dpmicall.h" #endif #ifdef C_UNIX #include #include #include #endif #define CDIR_EXPAND_MEM 8192 unsigned char c_translation[] = { 0, /* */ 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, /* 0 */ 49, /* 1 */ 50, /* 2 */ 51, /* 3 */ 52, /* 4 */ 53, /* 5 */ 54, /* 6 */ 55, /* 7 */ 56, /* 8 */ 57, /* 9 */ 58, /* : */ 59, /* ; */ 60, /* < */ 61, /* = */ 62, /* > */ 63, /* ? */ 64, /* @ */ 'A', /* A */ 'B', /* B */ 'C', /* C */ 'D', /* D */ 'E', /* E */ 'F', /* F */ 'G', /* G */ 'H', /* H */ 'I', /* I */ 'J', /* J */ 'K', /* K */ 'L', /* L */ 'M', /* M */ 'N', /* N */ 'O', /* O */ 'P', /* P */ 'Q', /* Q */ 'R', /* R */ 'S', /* S */ 'T', /* T */ 'U', /* U */ 'V', /* V */ 'W', /* W */ 'X', /* X */ 'Y', /* Y */ 'Z', /* Z */ 91, /* [ */ 92, /* \ */ 93, /* ] */ 94, /* ^ */ 95, /* _ */ 96, /* ` */ 'A', /* a */ 'B', /* b */ 'C', /* c */ 'D', /* d */ 'E', /* e */ 'F', /* f */ 'G', /* g */ 'H', /* h */ 'I', /* i */ 'J', /* j */ 'K', /* k */ 'L', /* l */ 'M', /* m */ 'N', /* n */ 'O', /* o */ 'P', /* p */ 'Q', /* q */ 'R', /* r */ 'S', /* s */ 'T', /* t */ 'U', /* u */ 'V', /* v */ 'W', /* w */ 'X', /* x */ 'Y', /* y */ 'Z', /* z */ 123, /* { */ 124, /* | */ 125, /* } */ 126, /* ~ */ 127, /* */ 128, /* */ 'U', /* */ 'E', /* */ 'A', /* */ 'A', /* */ 'A', /* */ 'A', /* */ 'C', /* */ 'E', /* */ 'E', /* */ 'E', /* */ 'I', /* */ 'I', /* */ 'I', /* */ 'A', /* */ 'A', /* */ 'E', /* */ 145, /* */ 'A', /* */ 'O', /* */ 'O', /* */ 'O', /* */ 'U', /* */ 'U', /* */ 'Y', /* */ 'O', /* */ 'U', /* */ 'C', /* */ 156, /* */ 157, /* */ 158, /* */ 159, /* */ 'A', /* */ 'I', /* */ 'O', /* */ 'U', /* */ 'N', /* */ 'N', /* */ 166, /* */ 167, /* */ 168, /* */ 169, /* */ 170, /* */ 171, /* */ 172, /* */ 173, /* */ 174, /* */ 175, /* */ 176, /* */ 177, /* */ 178, /* */ 179, /* */ 180, /* */ 181, /* */ 182, /* */ 183, /* */ 184, /* */ 185, /* */ 186, /* */ 187, /* */ 188, /* */ 189, /* */ 190, /* */ 191, /* */ 192, /* */ 193, /* */ 194, /* */ 195, /* */ 196, /* */ 197, /* */ 198, /* */ 199, /* */ 200, /* */ 201, /* */ 202, /* */ 203, /* */ 204, /* */ 205, /* */ 206, /* */ 207, /* */ 208, /* */ 209, /* */ 210, /* */ 211, /* */ 212, /* */ 213, /* */ 214, /* */ 215, /* */ 216, /* */ 217, /* */ 218, /* */ 219, /* */ 220, /* */ 221, /* */ 222, /* */ 223, /* */ 224, /* */ 'S', /* */ 226, /* */ 227, /* */ 228, /* */ 229, /* */ 230, /* */ 231, /* */ 232, /* */ 233, /* */ 234, /* */ 235, /* */ 236, /* */ 237, /* */ 238, /* */ 239, /* */ 240, /* */ 241, /* */ 242, /* */ 243, /* */ 244, /* */ 245, /* */ 246, /* */ 247, /* */ 248, /* */ 249, /* */ 250, /* */ 251, /* */ 252, /* */ 253, /* */ 254, /* */ 255 /* */ }; #define c_toupper(c) (c_translation[(unsigned char)(c)]) char *c_strupr(char *s) { char *t = s; if ( s != NULL ) { while(*s != '\0') { *s = c_toupper(*s); s++; } } return t; } int patmat(char *raw, char *pat) { if ( *pat == '\0' ) return *raw == '\0'; /* *raw == '\0' ? 1 : 0 */ if (*pat != '*') /* if pattern is not a '*'*/ { if (*raw == '\0') /* if end of raw then */ return( 0 ) ; /* mismatch */ while ((*pat == '?') || (*pat == *raw)) /* if chars match then */ { raw++; pat++; if ( *pat == '\0' ) return *raw == '\0'; /* *raw == '\0' ? 1 : 0 */ } } /* no else !!! */ /* no match, if pat is not '*' */ if (*pat == '*') /* if pattern is a '*' */ { while(*pat == '*') /* ignore more '*' */ pat++; if (*(pat ) == '\0') /* if it is end of pat */ return( 1 ) ; /* then match */ while( *raw != '\0' ) /* else hunt for match */ { if((*pat == '?') || (*pat == *raw)) { if (patmat(++raw, pat+1) != 0) /* if found,match */ return( 1 ) ; /* rest of pat */ } else { raw++; } } } return( 0 ) ; /* no match found */ } int upatmat(char *raw, char *pat) { if ( *pat == '\0' ) return *raw == '\0'; /* *raw == '\0' ? 1 : 0 */ if (*pat != '*') /* if pattern is not a '*'*/ { if (*raw == '\0') /* if end of raw then */ return( 0 ) ; /* mismatch */ while (((unsigned char)*pat == c_toupper(*raw)) || (*pat == '?')) { raw++; pat++; if ( *pat == '\0' ) return *raw == '\0'; /* *raw == '\0' ? 1 : 0 */ } } /* no else !!! */ /* no match, if pat is not '*' */ if (*pat == '*') /* if pattern is a '*' */ { while(*pat == '*') /* ignore more '*' */ pat++; if (*(pat ) == '\0') /* if it is end of pat */ return( 1 ) ; /* then match */ while( *raw != '\0' ) /* else hunt for match */ { if (((unsigned char)*pat == c_toupper(*raw)) || (*pat == '?')) { if (upatmat(++raw, pat+1) != 0) /* if found,match */ return( 1 ) ; /* rest of pat */ } else { raw++; } } } return( 0 ) ; /* no match found */ } int _add_name(CDIR *dirp, char *name, char *short_name, unsigned long size, int is_dir) { size_t len; struct c_dirent *de; if ( name == NULL ) return 1; if ( name[0] == '\0' ) return 1; if ( (dirp->options & CDIR_MATCH_ALL) == 0 ) { if ( is_dir == 0 ) { if ( dirp->pat[0] == '\0' ) return 1; if ( dirp->patmat_fn(name, dirp->pat) == 0 ) if ( dirp->patmat_fn(short_name, dirp->pat) == 0 ) return 1; } } len = strlen(name)+1+sizeof(struct c_dirent); len = (size_t)(len + sizeof(long) - (size_t)1) & (size_t)0x0fffffffc; while ( dirp->cnt+len > dirp->max ) { char *ptr; ptr = (char *)realloc(dirp->ptr, dirp->max+CDIR_EXPAND_MEM); if ( ptr == NULL ) return 0; dirp->ptr = ptr; dirp->max += CDIR_EXPAND_MEM; } de = (struct c_dirent *)(dirp->ptr+dirp->cnt); de->d_size = size; /* de->d_ino = 0L; */ de->d_off = 0L; de->d_reclen = (unsigned short)len; de->d_is_dir = (short)is_dir; strcpy(de->d_name, name); strncpy(de->d_short_name, short_name, 14); de->d_short_name[13] = '\0'; dirp->cnt += len; return 1; } #ifdef C_DOS int _add_dos_files(CDIR *dirp) { struct _find_t fileinfo; if ( _dos_findfirst("*.*", _A_SUBDIR | _A_NORMAL | _A_HIDDEN | _A_RDONLY | _A_ARCH | _A_SYSTEM, &fileinfo) == 0 ) { do { if ( _add_name(dirp, fileinfo.name, fileinfo.name, fileinfo.size, (fileinfo.attrib & _A_SUBDIR)==0?0:1 ) == 0 ) return 0; } while(_dos_findnext(&fileinfo) == 0); } return 1; } struct _win95_find_data { unsigned long attr; unsigned long create_time1; unsigned long create_time2; unsigned long access_time1; unsigned long access_time2; unsigned long modify_time1; unsigned long modify_time2; unsigned long size1; /* high bytes */ unsigned long size2; /* low bytes */ char fill[8]; char long_name[260]; char short_name[14]; }; #ifdef C_DIRECT_16_ int _add_longfile(CDIR *dirp) { unsigned short handle; char far *search = "*"; struct _win95_find_data fd; union REGS r; struct SREGS s; r.x.ax = 0x0714e; r.h.cl = 0x0ff; /* every attrib ok */ r.h.ch = 0; /* no attrib req. */ r.x.si = 0; /* win95 time format?? */ s.ds = (unsigned)(((unsigned long)search)>>16); r.x.dx = (unsigned)(((unsigned long)search)&0x0ffffUL); s.es = (unsigned)(((unsigned long)((void far *)&fd))>>16); r.x.di = (unsigned)(((unsigned long)((void far *)&fd))&0x0ffffUL); int86x(0x021, &r, &r, &s); if ( r.x.cflag != 0 ) return 0; handle = (unsigned short)r.x.ax; for(;;) { if ( _add_name(dirp, fd.long_name, fd.short_name, fd.size2, (fd.attr&0x010)==0?0:1 ) == 0 ) break; r.x.ax = 0x0714f; r.x.bx = handle; r.x.si = 0; /* win95 time format?? */ s.es = (unsigned)(((unsigned long)((void far *)&fd))>>16); r.x.di = (unsigned)(((unsigned long)((void far *)&fd))&0x0ffffUL); int86x(0x021, &r, &r, &s); if ( r.x.cflag != 0 ) break; } r.x.ax = 0x071a1; r.x.bx = handle; int86x(0x021, &r, &r, &s); return 1; } #endif int _add_dpmi_longfile(CDIR *dirp) { unsigned short handle; short sel_search, seg_search; short sel_fd, seg_fd; rminfo_struct rmi; struct _win95_find_data fd; if ( dpmi_alloc_dos_memory(4, &sel_search, &seg_search ) == 0 ) return 0; if ( dpmi_alloc_dos_memory(sizeof(struct _win95_find_data), &sel_fd, &seg_fd ) == 0 ) { dpmi_free_dos_memory(sel_search); return 0; } dpmi_copy_to_dos(sel_search, (void *)"*", 2); rmi.eax = 0x0714eL; rmi.ecx = 0x0ffL; /* every attrib ok, no attrib req. */ rmi.esi = 0L; /* win95 time format?? */ rmi.ds = seg_search; rmi.edx = 0L; rmi.es = seg_fd; rmi.edi = 0L; if ( dpmi_simulate_rmi(0x021, &rmi) != 0 ) return 0; handle = (unsigned short)rmi.eax; for(;;) { dpmi_copy_from_dos(sel_fd, &fd, sizeof(struct _win95_find_data)); if ( _add_name(dirp, fd.long_name, fd.short_name, fd.size2, (fd.attr&0x010)==0?0:1 ) == 0 ) break; rmi.eax = 0x0714fL; rmi.ebx = (long)handle; rmi.esi = 0L; /* win95 time format?? */ rmi.es = seg_fd; rmi.edi = 0L; if ( dpmi_simulate_rmi(0x021, &rmi) != 0 ) break; } rmi.eax = 0x071a1L; rmi.ebx = (long)handle; dpmi_simulate_rmi(0x021, &rmi); dpmi_free_dos_memory(sel_fd); dpmi_free_dos_memory(sel_search); return 1; } int _add_files(CDIR *dirp) { if ( c_is_long_filename() != 0 ) return _add_dpmi_longfile(dirp); return _add_dos_files(dirp); } #endif #ifdef C_UNIX int _add_files(CDIR *dirp) { DIR *d; struct dirent *e; struct stat s; d = opendir("."); if ( d == NULL ) return 0; for(;;) { e = readdir(d); if ( e == NULL ) break; if ( stat(e->d_name, &s) != 0 ) { closedir(d); return 0; } if ( _add_name(dirp, e->d_name, "", s.st_size, (s.st_mode&S_IFDIR)!=0?1:0 ) == 0 ) break; } closedir(d); return 1; } #endif CDIR *c_opendir(const char *path, const char *pat, int options) { CDIR *d; d = (CDIR *)malloc(sizeof(struct _CDIR_struct)); if ( d != NULL ) { d->options = options; d->path = (char *)malloc(strlen(path)+2); if ( d->path != NULL ) { strcpy(d->path, path); d->pat = (char *)malloc(strlen(pat)+2); if ( d->pat != NULL ) { strcpy(d->pat, pat); d->ptr = (char *)malloc(CDIR_EXPAND_MEM); if ( d->ptr != NULL ) { d->max = (size_t)CDIR_EXPAND_MEM; d->cnt = (size_t)0; d->pos = 0; d->patmat_fn = patmat; if ( (options & CDIR_MATCH_CASE) == 0 ) { d->patmat_fn = upatmat; c_strupr(d->pat); } c_chdir(path); if ( _add_files(d) == 0 ) { /* ... */ } return d; } free(d->pat); } free(d->path); } free(d); } return NULL; } int c_closedir(CDIR *dirp) { if ( dirp != NULL ) { free(dirp->ptr); free(dirp->pat); free(dirp->path); free(dirp); } return 1; } struct c_dirent *c_readdir(CDIR *dirp) { struct c_dirent *de; if ( dirp == NULL ) return NULL; if ( dirp->pos >= dirp->cnt ) return NULL; de = (struct c_dirent *)(dirp->pos+dirp->ptr); dirp->pos += de->d_reclen; return de; } void c_rewinddir(CDIR *dirp) { if ( dirp == NULL ) return; dirp->pos = 0; } long c_telldir(CDIR *dirp) { if ( dirp == NULL ) return -1L; return (long)dirp->pos; } void c_seekdir(CDIR *dirp, long pos) { if ( dirp == NULL ) return; dirp->pos = (size_t)pos; } #ifdef CDIRENT_MAIN #include void main(void) { CDIR *d; struct c_dirent *e; d = c_opendir(".", "*", 0); for(;;) { e = c_readdir(d); if ( e == NULL ) break; if ( c_is_dir(e) != 0 ) printf(" "); else printf(" "); printf("%-14s %s\n", e->d_short_name, e->d_name); } c_closedir(d); } #endif