/*
CDIRENT.C
(c) 1996 Oliver Kraus
*/
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "ccommon.h"
#include "cdirent.h"
#include "cio.h"
#ifdef C_DOS
#include <dos.h>
#include <direct.h>
#include "dpmicall.h"
#endif
#ifdef C_UNIX
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#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 <stdio.h>
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("<dir> ");
else
printf(" ");
printf("%-14s %s\n", e->d_short_name, e->d_name);
}
c_closedir(d);
}
#endif