Message-ID: <001c01c15bdf$cac187c0$0d2c24d5@zephyr> From: "Eric Botcazou" To: "DJGPP workers" Subject: _findfirst() patch (2) Date: Tue, 23 Oct 2001 18:20:29 +0200 MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_NextPart_000_0015_01C15BEF.653A1060" X-Priority: 3 X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook Express 5.00.2014.211 X-MimeOLE: Produced By Microsoft MimeOLE V5.00.2014.211 Reply-To: djgpp-workers AT delorie DOT com This is a multi-part message in MIME format. ------=_NextPart_000_0015_01C15BEF.653A1060 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Hello, I've attached a (completely) revised version of my _findfirst() patch, following the guidelines Eli and Charles provided me with. The general design is the one Eli agreed to: - _lfn_findfirst(), _lfn_findnext() and _lfn_findclose() are the low-level wrapper functions around the functions 714eh, 714fh, 71a1h respectively, living in the src/libc/dos/dir directory, - _dos_findfirst() and _dos_findnext() have been rewritten using materials from the former findfirst() and findnext(), - findfirst()/findnext() and _findfirst()/_findnext()/_findclose() are now high-level functions that call the two previously cited sets of functions, - I've revamped my DOS time to ANSI C time conversion function, because I found that there is already a structure (namely struct ftime) in dos.h which describes the DOS time format, - everything follows the 'one external function per file' rule and is documented. I've also attached a more complete version of the test program. -- Eric Botcazou ebotcazou AT multimania DOT com ------=_NextPart_000_0015_01C15BEF.653A1060 Content-Type: application/octet-stream; name="_findfirst2.diff" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="_findfirst2.diff" --- /cvsroot/djgpp/src/libc/dos/compat/d_findf.c Sun Aug 31 17:49:56 = 1997 +++ /djgpp-cvs/src/libc/dos/compat/d_findf.c Tue Oct 23 17:15:08 2001 @@ -15,29 +15,46 @@ #include #include #include -#include +#include #include =20 -unsigned int _dos_findfirst(const char *name, unsigned int attr, struct = _find_t *result) +unsigned int +_dos_findfirst(const char *name, unsigned int attr, struct _find_t = *result) { __dpmi_regs r; + int namelen; + + if (name =3D=3D 0 || result =3D=3D 0) { + errno =3D EACCES; + return 0x05; /* DOS error code: access denied */ + } + + namelen =3D strlen(name) + 1; =20 _put_path(name); - r.x.dx =3D (__tb & 15) + strlen(name) + 1; - r.x.ds =3D __tb / 16; - r.h.ah =3D 0x1A; + + /* There will be a _sizeof_dos_ffblk character return value from = _dos_findfirst=20 + in the DTA. Put the file name before this. First set the DTA to = be + transfer buffer. */ + + r.x.dx =3D __tb_offset + namelen; + r.x.ds =3D __tb_segment; + r.h.ah =3D 0x1a; __dpmi_int(0x21, &r); =20 - r.h.ah =3D 0x4E; - r.x.dx =3D (__tb & 15); - r.x.ds =3D __tb / 16; + r.h.ah =3D 0x4e; + r.x.dx =3D __tb_offset; + r.x.ds =3D __tb_segment; r.x.cx =3D attr; __dpmi_int(0x21, &r); - if ( r.x.flags & 1 ) - { + + if (r.x.flags&1) { /* error? */ errno =3D __doserr_to_errno(r.x.ax); return r.x.ax; } - dosmemget(__tb + strlen(name) + 1, sizeof(struct _find_t), result); + + /* Recover results */ + dosmemget(__tb + namelen, _sizeof_dos_ffblk, result); + return 0; } --- /cvsroot/djgpp/src/libc/dos/compat/d_findn.c Mon Oct 9 08:00:00 = 1995 +++ /djgpp-cvs/src/libc/dos/compat/d_findn.c Mon Oct 22 22:50:02 2001 @@ -14,24 +14,39 @@ #include #include #include +#include #include =20 -unsigned int _dos_findnext(struct _find_t *result) +unsigned int +_dos_findnext(struct _find_t *result) { __dpmi_regs r; =20 - r.x.dx =3D __tb & 15; - r.x.ds =3D __tb / 16; - r.h.ah =3D 0x1A; + if (result =3D=3D 0) { + errno =3D EACCES; + return 0x05; /* DOS error code: access denied */ + } + + /* The 43 character ff block must be put to the DTA, make the call, = then + recover the ff block. */ + + r.x.dx =3D __tb_offset; + r.x.ds =3D __tb_segment; + r.h.ah =3D 0x1a; __dpmi_int(0x21, &r); - dosmemput(result, sizeof(struct _find_t), __tb); - r.h.ah =3D 0x4F; + + dosmemput(result, _sizeof_dos_ffblk, __tb); + + r.h.ah =3D 0x4f; __dpmi_int(0x21, &r); - if ( r.x.flags & 1 ) - { + + if (r.x.flags&1) { /* error? */ errno =3D __doserr_to_errno(r.x.ax); return r.x.ax; } - dosmemget(__tb, sizeof(struct _find_t), result); + + /* Recover results */ + dosmemget(__tb, _sizeof_dos_ffblk, result); + return 0; } --- /cvsroot/djgpp/src/libc/dos/compat/d_gettim.c Mon Oct 9 08:00:00 = 1995 +++ /djgpp-cvs/src/libc/dos/compat/d_gettim.c Mon Oct 22 20:40:02 2001 @@ -12,14 +12,14 @@ #include #include =20 -void _dos_gettime(struct _dostime_t *time) +void _dos_gettime(struct _dostime_t *dtime) { __dpmi_regs r; =20 r.h.ah =3D 0x2C; __dpmi_int(0x21, &r); - time->hour =3D r.h.ch; - time->minute =3D r.h.cl; - time->second =3D r.h.dh; - time->hsecond =3D r.h.dl; + dtime->hour =3D r.h.ch; + dtime->minute =3D r.h.cl; + dtime->second =3D r.h.dh; + dtime->hsecond =3D r.h.dl; } --- /cvsroot/djgpp/src/libc/dos/compat/d_setftm.c Mon Oct 9 08:00:00 = 1995 +++ /djgpp-cvs/src/libc/dos/compat/d_setftm.c Mon Oct 22 20:45:18 2001 @@ -13,13 +13,13 @@ #include #include =20 -unsigned int _dos_setftime(int handle, unsigned int date, unsigned int = time) +unsigned int _dos_setftime(int handle, unsigned int date, unsigned int = dtime) { __dpmi_regs r; =20 r.x.ax =3D 0x5701; r.x.bx =3D handle; - r.x.cx =3D time; + r.x.cx =3D dtime; r.x.dx =3D date; __dpmi_int(0x21, &r); if ( r.x.flags & 1 ) --- /cvsroot/djgpp/src/libc/dos/compat/d_settim.c Sat Nov 25 03:20:36 = 1995 +++ /djgpp-cvs/src/libc/dos/compat/d_settim.c Mon Oct 22 20:45:44 2001 @@ -13,21 +13,21 @@ #include #include =20 -unsigned int _dos_settime(struct _dostime_t *time) +unsigned int _dos_settime(struct _dostime_t *dtime) { __dpmi_regs r; =20 - if (time =3D=3D 0) + if (dtime =3D=3D 0) { errno =3D EINVAL; return -1; } =20 r.h.ah =3D 0x2D; - r.h.ch =3D time->hour; - r.h.cl =3D time->minute; - r.h.dh =3D time->second; - r.h.dl =3D time->hsecond; + r.h.ch =3D dtime->hour; + r.h.cl =3D dtime->minute; + r.h.dh =3D dtime->second; + r.h.dl =3D dtime->hsecond; __dpmi_int(0x21, &r); if ( r.h.al ) { --- /cvsroot/djgpp/src/libc/dos/dir/findfirs.c Sat Aug 31 23:09:32 1996 +++ /djgpp-cvs/src/libc/dos/dir/findfirs.c Tue Oct 23 17:18:22 2001 @@ -1,56 +1,22 @@ /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ #include -#include #include #include #include -#include -#include #include -#include +#include =20 int findfirst(const char *pathname, struct ffblk *ffblk, int attrib) { - __dpmi_regs r; - int pathlen; - int use_lfn =3D _USE_LFN; - - if (pathname =3D=3D 0 || ffblk =3D=3D 0) - { - errno =3D EACCES; - return -1; - } - - pathlen =3D strlen(pathname) + 1; - - _put_path(pathname); - if(use_lfn) { + if (_USE_LFN) { + struct ffblklfn ffblk32; + long handle; =20 - /* si =3D 1 indicates DOS style dates, 0 means Win32 type dates. - DOS style dates are broken in some Win95 betas, build for = either. - Release works with DOS date, it's faster, so use it. */ - #define USEDOSDATE 1 - #if USEDOSDATE =3D=3D 1 - #define _Win32_to_DOS (long) - #else - extern long _Win32_to_DOS(long long WinTime); - #endif - - r.x.ax =3D 0x714e; - r.x.cx =3D attrib; - r.x.dx =3D __tb_offset; - r.x.ds =3D __tb_segment; - r.x.di =3D __tb_offset + pathlen; - r.x.es =3D r.x.ds; - r.x.si =3D USEDOSDATE; - __dpmi_int(0x21, &r); - if(!(r.x.flags & 1)) { - struct ffblklfn ffblk32; - /* Recover results */ - dosmemget(__tb+pathlen, sizeof(struct ffblklfn), &ffblk32); + handle =3D _lfn_findfirst(pathname, attrib, &ffblk32); =20 + if (handle > 0) { ffblk->ff_attrib =3D (char)ffblk32.fd_attrib; *(long *)(&ffblk->ff_ftime) =3D _Win32_to_DOS(ffblk32.fd_mtime); ffblk->ff_fsize =3D ffblk32.fd_size; @@ -58,43 +24,22 @@ strcpy(ffblk->lfn_magic, "LFN32"); =20 /* If no wildcards, close the handle */ - if(!strchr(pathname,'*') && !strchr(pathname,'?')) { - r.x.bx =3D r.x.ax; - r.x.ax =3D 0x71a1; - __dpmi_int(0x21, &r); - r.x.ax =3D 0; + if (!strchr(pathname,'*') && !strchr(pathname,'?')) { + _lfn_findclose(handle); + handle =3D 0; } =20 - ffblk->lfn_handle =3D r.x.ax; + ffblk->lfn_handle =3D handle; *(long *)(&ffblk->lfn_ctime) =3D _Win32_to_DOS(ffblk32.fd_ctime); *(long *)(&ffblk->lfn_atime) =3D _Win32_to_DOS(ffblk32.fd_atime); =20 return 0; } - } else { - - #define _sizeof_dos_ffblk 44 - /* There will be a _sizeof_dos_ffblk character return value from = findfirst=20 - in the DTA. Put the file name before this. First set the DTA = to be=20 - transfer buffer. */ - - r.x.dx =3D __tb_offset + pathlen; - r.x.ds =3D __tb_segment; - r.h.ah =3D 0x1a; - __dpmi_int(0x21, &r); - - r.h.ah =3D 0x4e; - r.x.dx =3D __tb_offset; - r.x.ds =3D __tb_segment; - r.x.cx =3D attrib; - __dpmi_int(0x21, &r); - if(!(r.x.flags & 1)) { - /* Recover results */ - dosmemget(__tb+pathlen, _sizeof_dos_ffblk, ffblk); + } + else { + if (_dos_findfirst(pathname, attrib, (struct _find_t *)ffblk) = =3D=3D 0) return 0; - } } =20 - errno =3D __doserr_to_errno(r.x.ax); return errno; } --- /cvsroot/djgpp/src/libc/dos/dir/findnext.c Sun Sep 1 00:09:32 1996 +++ /djgpp-cvs/src/libc/dos/dir/findnext.c Mon Oct 22 22:50:24 2001 @@ -1,56 +1,24 @@ /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ #include -#include #include +#include #include -#include -#include #include -#include -#include +#include =20 int findnext(struct ffblk *ffblk) { - __dpmi_regs r; - - if (ffblk =3D=3D 0) - { - errno =3D EACCES; - return -1; - } + if (_USE_LFN) { + struct ffblklfn ffblk32; =20 - if(_USE_LFN) - { - /* si =3D 1 indicates DOS style dates, 0 means Win32 type dates. - DOS style dates are broken in some Win95 betas, build for = either. - Release works with DOS date, it's faster, so use it. */ - #define USEDOSDATE 1 - #if USEDOSDATE =3D=3D 1 - #define _Win32_to_DOS (long) - #else - extern long _Win32_to_DOS(long long WinTime); - #endif - - r.x.ax =3D 0x714f; - r.x.bx =3D ffblk->lfn_handle; - if(!r.x.bx) - { + if (!ffblk->lfn_handle) { /* handle already closed? */ errno =3D ENMFILE; return 1; } - r.x.di =3D __tb_offset; - r.x.es =3D __tb_segment; - r.x.si =3D USEDOSDATE; - - __dpmi_int(0x21, &r); - if (!(r.x.flags & 1)) - { - struct ffblklfn ffblk32; - /* Recover results */ - dosmemget(__tb, sizeof(struct ffblklfn), &ffblk32); =20 + if (_lfn_findnext(ffblk->lfn_handle, &ffblk32) =3D=3D 0) { ffblk->ff_attrib =3D (char)ffblk32.fd_attrib; *(long *)&ffblk->ff_ftime =3D _Win32_to_DOS(ffblk32.fd_mtime); ffblk->ff_fsize =3D ffblk32.fd_size; @@ -60,44 +28,19 @@ =20 return 0; } - errno =3D __doserr_to_errno(r.x.ax); - if (errno =3D=3D ENMFILE) /* call FindClose */ - { - ffblk->lfn_handle =3D 0; - r.x.ax =3D 0x71a1; - __dpmi_int(0x21, &r); - if(r.x.flags & 1) - { - errno =3D __doserr_to_errno(r.x.ax); + + if (errno =3D=3D ENMFILE) { /* no more files? */ + if (_lfn_findclose(ffblk->lfn_handle) < 0) return -1; - } + + ffblk->lfn_handle =3D 0; return 1; } - return -1; } - else - { - #define _sizeof_dos_ffblk 44 - /* The 43 character ff block must be put to the DTA, make the call, = then - recover the ff block. */ - - r.x.dx =3D __tb_offset; - r.x.ds =3D __tb_segment; - r.h.ah =3D 0x1a; - __dpmi_int(0x21, &r); - - dosmemput(ffblk, sizeof(struct ffblk), __tb); - - r.h.ah =3D 0x4f; - __dpmi_int(0x21, &r); - if(r.x.flags & 1) - { - errno =3D __doserr_to_errno(r.x.ax); - return -1; - } - - /* Recover results */ - dosmemget(__tb, _sizeof_dos_ffblk, ffblk); - return 0; + else { + if (_dos_findnext((struct _find_t *)ffblk) =3D=3D 0) + return 0; } + + return -1; } --- /cvsroot/djgpp/src/libc/dos/dir/l_findc.c Thu Jan 1 00:00:00 1970 +++ /djgpp-cvs/src/libc/dos/dir/l_findc.c Tue Oct 23 17:17:04 2001 @@ -0,0 +1,22 @@ +#include +#include +#include +#include +#include + +int +_lfn_findclose(long handle) +{ + __dpmi_regs r; + + r.x.ax =3D 0x71a1; + r.x.bx =3D handle; + __dpmi_int(0x21, &r); + + if (r.x.flags&1) { /* error? */ + errno =3D __doserr_to_errno(r.x.ax); + return -1; + } + + return 0; +} --- /cvsroot/djgpp/src/libc/dos/dir/l_findc.txh Thu Jan 1 00:00:00 1970 +++ /djgpp-cvs/src/libc/dos/dir/l_findc.txh Tue Oct 23 01:13:22 2001 @@ -0,0 +1,21 @@ +@node _lfn_findclose, file system +@subheading Syntax + +@example +#include + +int _lfn_findclose(long handle); +@end example + +@subheading Description + +This closes the search started by @code{_lfn_findfirst}. + +@subheading Return Value + +Zero on success, -1 on error (and sets @var{errno}). + +@subheading Portability + +@portability !ansi, !posix + --- /cvsroot/djgpp/src/libc/dos/dir/l_findf.c Thu Jan 1 00:00:00 1970 +++ /djgpp-cvs/src/libc/dos/dir/l_findf.c Tue Oct 23 01:17:58 2001 @@ -0,0 +1,43 @@ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include +#include +#include + +long +_lfn_findfirst(const char *pathname, int attrib, struct ffblklfn = *ffblklfn) +{ + __dpmi_regs r; + int pathlen; + + if (pathname =3D=3D 0 || ffblklfn =3D=3D 0) { + errno =3D EACCES; + return -1; + } + + pathlen =3D strlen(pathname) + 1; + + _put_path(pathname); + + r.x.ax =3D 0x714e; + r.x.cx =3D attrib; + r.x.dx =3D __tb_offset; + r.x.ds =3D __tb_segment; + r.x.di =3D __tb_offset + pathlen; + r.x.es =3D r.x.ds; + r.x.si =3D USEDOSDATE; + __dpmi_int(0x21, &r); + + if (r.x.flags&1) { /* error? */ + errno =3D __doserr_to_errno(r.x.ax); + return -1; + } + + /* Recover results */ + dosmemget(__tb+pathlen, sizeof(struct ffblklfn), ffblklfn); + + return (long)r.x.ax; +} --- /cvsroot/djgpp/src/libc/dos/dir/l_findf.txh Thu Jan 1 00:00:00 1970 +++ /djgpp-cvs/src/libc/dos/dir/l_findf.txh Tue Oct 23 01:15:44 2001 @@ -0,0 +1,30 @@ +@node _lfn_findfirst, file system +@subheading Syntax + +@example +#include + +long _lfn_findfirst(const char *pathname, int attrib, struct ffblklfn = *ffblklfn); +@end example + +@subheading Description + +This function and the related @code{_lfn_findnext} = (@pxref{_lfn_findnext}) +and @code{_lfn_findclose} (@pxref{_lfn_findclose}) are used to scan +directories for the list of files therein. However they are not = intended +to be directly called. Use one of the two public functions instead +(@pxref{findfirst} and @pxref{_findfirst}). + +This function works only if long file names are supported by the = system. + +@subheading Return Value + +If a match is found, @code{_lfn_findfirst} returns an unique handle +identifying the search that can be used in subsequent calls to +@code{_lfn_findnext} and to @code{_lfn_findclose}. Otherwise, +@code{_lfn_findfirst} returns -1 (and sets @var{errno}). + +@subheading Portability + +@portability !ansi, !posix + --- /cvsroot/djgpp/src/libc/dos/dir/l_findn.c Thu Jan 1 00:00:00 1970 +++ /djgpp-cvs/src/libc/dos/dir/l_findn.c Tue Oct 23 17:17:54 2001 @@ -0,0 +1,36 @@ +/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ +/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include +#include +#include + +int +_lfn_findnext(long handle, struct ffblklfn *ffblklfn) +{ + __dpmi_regs r; + + if (ffblklfn =3D=3D 0) { + errno =3D EACCES; + return -1; + } + + r.x.ax =3D 0x714f; + r.x.bx =3D handle; + r.x.di =3D __tb_offset; + r.x.es =3D __tb_segment; + r.x.si =3D USEDOSDATE; + __dpmi_int(0x21, &r); + + if (r.x.flags&1) { /* error? */ + errno =3D __doserr_to_errno(r.x.ax); + return -1; + } + + /* Recover results */ + dosmemget(__tb, sizeof(struct ffblklfn), ffblklfn); + + return 0; +} --- /cvsroot/djgpp/src/libc/dos/dir/l_findn.txh Thu Jan 1 00:00:00 1970 +++ /djgpp-cvs/src/libc/dos/dir/l_findn.txh Tue Oct 23 01:13:12 2001 @@ -0,0 +1,23 @@ +@node _lfn_findnext, file system +@subheading Syntax + +@example +#include + +int _lfn_findnext(long handle, struct ffblklfn *ffblklfn) +@end example + +@subheading Description + +This finds the next file in the search started by = @code{_lfn_findfirst}. + +This function works only if long file names are supported by the = system. + +@subheading Return Value + +Zero if a match is found, -1 if not found (and sets @var{errno}). + +@subheading Portability + +@portability !ansi, !posix + --- /cvsroot/djgpp/src/libc/dos/dir/makefile Tue Jun 13 08:03:36 1995 +++ /djgpp-cvs/src/libc/dos/dir/makefile Mon Oct 22 19:17:18 2001 @@ -1,6 +1,9 @@ # Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details TOP=3D../.. =20 +SRC +=3D l_findc.c +SRC +=3D l_findf.c +SRC +=3D l_findn.c SRC +=3D findfirs.c SRC +=3D findnext.c SRC +=3D fnmerge.c --- /cvsroot/djgpp/src/libc/dos/dos/ftime2tm.c Thu Jan 1 00:00:00 1970 +++ /djgpp-cvs/src/libc/dos/dos/ftime2tm.c Mon Oct 22 18:57:36 2001 @@ -0,0 +1,20 @@ +#include +#include +#include + +time_t +_ftime_to_time_t(struct ftime *ftimep) +{ + struct tm t; + + memset(&t, 0, sizeof(struct tm)); + t.tm_sec =3D ftimep->ft_tsec * 2; + t.tm_min =3D ftimep->ft_min; + t.tm_hour =3D ftimep->ft_hour; + t.tm_mday =3D ftimep->ft_day; + t.tm_mon =3D ftimep->ft_month - 1; + t.tm_year =3D ftimep->ft_year + 80; + t.tm_isdst =3D -1; + + return mktime(&t); +} --- /cvsroot/djgpp/src/libc/dos/dos/ftime2tm.txh Thu Jan 1 00:00:00 = 1970 +++ /djgpp-cvs/src/libc/dos/dos/ftime2tm.txh Tue Oct 23 00:56:56 2001 @@ -0,0 +1,33 @@ +@node _ftime_to_time_t, file system +@subheading Syntax + +@example +#include + +time_t _ftime_to_time_t(struct ftime *ftimep); +@end example + +@subheading Description + +This function converts the DOS time format used for files +into the ANSI C time format. + +@xref{getftime}, for the description of @code{struct ftime}. + +@subheading Return Value + +Converted time value. + +@subheading Portability + +@portability !ansi, !posix + +@subheading Example + +@example +struct ftime t; +time_t time; +getftime(fd, &t); +time =3D _ftime_to_time_t(&t); +@end example + --- /cvsroot/djgpp/src/libc/dos/dos/makefile Mon Jun 19 20:00:56 2000 +++ /djgpp-cvs/src/libc/dos/dos/makefile Mon Oct 22 21:25:34 2001 @@ -5,6 +5,7 @@ SRC +=3D bdosptr.S SRC +=3D delay.c SRC +=3D fexistp.c +SRC +=3D ftime2tm.c SRC +=3D getcbrk.c SRC +=3D getdate.c SRC +=3D getdfree.c --- /cvsroot/djgpp/src/libc/dos/io/_findclo.c Thu Jan 1 00:00:00 1970 +++ /djgpp-cvs/src/libc/dos/io/_findclo.c Mon Oct 22 22:51:24 2001 @@ -0,0 +1,18 @@ +#include +#include +#include +#include +#include + +int +_findclose(long handle) +{ + if (_USE_LFN) { + return _lfn_findclose(handle); + } + else { + free((struct ffblk*)handle); + return 0; + } +} + --- /cvsroot/djgpp/src/libc/dos/io/_findclo.txh Thu Jan 1 00:00:00 1970 +++ /djgpp-cvs/src/libc/dos/io/_findclo.txh Tue Oct 9 11:52:16 2001 @@ -0,0 +1,21 @@ +@node _findclose, file system +@subheading Syntax + +@example +#include + +int _findclose(long handle); +@end example + +@subheading Description + +This closes the search started by @code{_findfirst}. + +@subheading Return Value + +Zero on success, -1 on error (and sets @var{errno}). + +@subheading Portability + +@portability !ansi, !posix + --- /cvsroot/djgpp/src/libc/dos/io/_findfir.c Thu Jan 1 00:00:00 1970 +++ /djgpp-cvs/src/libc/dos/io/_findfir.c Mon Oct 22 22:51:34 2001 @@ -0,0 +1,58 @@ +#include +#include +#include +#include +#include +#include +#include + +long +_findfirst(const char *pathname, struct _finddata_t *fileinfo) +{ + #define ALL_ATTRIB (_A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_VOLID | = _A_SUBDIR | _A_ARCH) + + if (_USE_LFN) { + struct ffblklfn ffblk32; + long handle, temp; + + handle =3D _lfn_findfirst(pathname, ALL_ATTRIB, &ffblk32); + + if (handle > 0) { + fileinfo->attrib =3D (unsigned)ffblk32.fd_attrib; + + temp =3D _Win32_to_DOS(ffblk32.fd_ctime); + fileinfo->time_create =3D _ftime_to_time_t((struct ftime = *)&temp); + + temp =3D _Win32_to_DOS(ffblk32.fd_atime); + fileinfo->time_access =3D _ftime_to_time_t((struct ftime = *)&temp); + + temp =3D _Win32_to_DOS(ffblk32.fd_mtime); + fileinfo->time_write =3D _ftime_to_time_t((struct ftime = *)&temp); + + fileinfo->size =3D (_fsize_t)ffblk32.fd_size; + strcpy(fileinfo->name, ffblk32.fd_longname); + + return handle; + } + } + else { + struct ffblk *ffblk16 =3D malloc(_sizeof_dos_ffblk); + if (!ffblk16) { + errno =3D ENOMEM; + return -1; + } + + if (_dos_findfirst(pathname, ALL_ATTRIB, (struct _find_t *)ffblk16) = =3D=3D 0) { + fileinfo->attrib =3D (unsigned)ffblk16->ff_attrib; + fileinfo->time_create =3D -1; + fileinfo->time_access =3D -1; + fileinfo->time_write =3D _ftime_to_time_t((struct ftime = *)&ffblk16->ff_ftime); + fileinfo->size =3D (_fsize_t)ffblk16->ff_fsize; + strcpy(fileinfo->name, ffblk16->ff_name); + + return (long)ffblk16; + } + } + + return -1; +} --- /cvsroot/djgpp/src/libc/dos/io/_findfir.txh Thu Jan 1 00:00:00 1970 +++ /djgpp-cvs/src/libc/dos/io/_findfir.txh Tue Oct 9 11:54:04 2001 @@ -0,0 +1,119 @@ +@node _findfirst, file system +@subheading Syntax + +@example +#include + +long _findfirst(const char *pathname, struct _finddata_t *fileinfo); +@end example + +@subheading Description + +This function and the related @code{_findnext} (@pxref{_findnext}) and +@code{_findclose} (@pxref{_findclose}) are used to scan directories for = the +list of files therein. The @var{pathname} is a wildcard that specifies = the +directory and files to search for (such as @code{subdir/*.c}) and +@var{fileinfo} is a structure to hold the results of the search. + +The results are returned in a @code{struct _finddata_t} defined in +@code{} as follows: + +@example +struct _finddata_t @{ + unsigned attrib; + time_t time_create; + time_t time_access; + time_t time_write; + _fsize_t size; + char name[260]; +@}; +@end example + +The @var{attrib} field is a combination of the following: + +@table @code + +@item _A_NORMAL (0x00) + +Normal file (no read/write restrictions) + +@item _A_RDONLY (0x01) + +Read only file + +@item _A_HIDDEN (0x02) + +Hidden file + +@item _A_SYSTEM (0x04) + +System file + +@item _A_VOLID (0x08) + +Volume ID file + +@item _A_SUBDIR (0x10) + +Subdirectory + +@item _A_ARCH (0x20) + +Archive file + +@end table + +This function supports long file names. + +@subheading Return Value + +If a match is found, @code{_findfirst} returns an unique handle = identifying +the search that can be used in subsequent calls to @code{_findnext} and = to +@code{_findclose}. Otherwise, @code{_findfirst} returns -1 (and sets +@var{errno}). + +@subheading Portability + +@portability !ansi, !posix + +@subheading Example + +@example +#include +#include + +struct _finddata_t fileinfo; +long handle; +char attrib_str[7], time_str[32]; +int c =3D 0; + +handle =3D _findfirst("*.dat", &fileinfo); + +if (handle<0) +@{ + printf("no matching file.\n"); +@} +else +@{ + do + @{ + attrib_str[0] =3D (fileinfo.attrib&_A_RDONLY ? 'r' : '-'); + attrib_str[1] =3D (fileinfo.attrib&_A_HIDDEN ? 'h' : '-'); + attrib_str[2] =3D (fileinfo.attrib&_A_SYSTEM ? 's' : '-'); + attrib_str[3] =3D (fileinfo.attrib&_A_VOLID ? 'l' : '-'); + attrib_str[4] =3D (fileinfo.attrib&_A_SUBDIR ? 'd' : '-'); + attrib_str[5] =3D (fileinfo.attrib&_A_ARCH ? 'a' : '-'); + attrib_str[6] =3D '\0'; + + strftime(time_str, sizeof(time_str), "%m/%d/%Y %H:%M ", = localtime(&fileinfo.time_write)); + + printf("%-14s %5ld kb %s %s\n", fileinfo.name, 1 + = fileinfo.size/1024, attrib_str, time_str); + + c++; + @} while (_findnext(handle, &fileinfo) =3D=3D 0); + + _findclose(handle); + + printf("%d matching file%s\n", c, c>1 ? "s." : "."); +@} +@end example --- /cvsroot/djgpp/src/libc/dos/io/_findnex.c Thu Jan 1 00:00:00 1970 +++ /djgpp-cvs/src/libc/dos/io/_findnex.c Mon Oct 22 22:52:20 2001 @@ -0,0 +1,48 @@ +#include +#include +#include +#include +#include + +int +_findnext(long handle, struct _finddata_t *fileinfo) +{ + if (_USE_LFN) { + struct ffblklfn ffblk32; + long temp; + + if (_lfn_findnext(handle, &ffblk32) =3D=3D 0) { + fileinfo->attrib =3D (unsigned)ffblk32.fd_attrib; + + temp =3D _Win32_to_DOS(ffblk32.fd_ctime); + fileinfo->time_create =3D _ftime_to_time_t((struct ftime = *)&temp); + + temp =3D _Win32_to_DOS(ffblk32.fd_atime); + fileinfo->time_access =3D _ftime_to_time_t((struct ftime = *)&temp); + + temp =3D _Win32_to_DOS(ffblk32.fd_mtime); + fileinfo->time_write =3D _ftime_to_time_t((struct ftime = *)&temp); + + fileinfo->size =3D (_fsize_t)ffblk32.fd_size; + strcpy(fileinfo->name, ffblk32.fd_longname); + + return 0; + } + } + else { + struct ffblk *ffblk16 =3D (struct ffblk *)handle; + + if (_dos_findnext((struct _find_t *)ffblk16) =3D=3D 0) { + fileinfo->attrib =3D (unsigned)ffblk16->ff_attrib; + fileinfo->time_create =3D -1; + fileinfo->time_access =3D -1; + fileinfo->time_write =3D _ftime_to_time_t((struct ftime = *)&ffblk16->ff_ftime); + fileinfo->size =3D (_fsize_t)ffblk16->ff_fsize; + strcpy(fileinfo->name, ffblk16->ff_name); + + return 0; + } + } + + return -1; +} --- /cvsroot/djgpp/src/libc/dos/io/_findnex.txh Thu Jan 1 00:00:00 1970 +++ /djgpp-cvs/src/libc/dos/io/_findnex.txh Tue Oct 9 11:46:16 2001 @@ -0,0 +1,24 @@ +@node _findnext, file system +@subheading Syntax + +@example +#include + +int _findnext(long handle, struct _finddata_t *fileinfo); +@end example + +@subheading Description + +This finds the next file in the search started by @code{_findfirst}. +See @ref{_findfirst}, for the description of @code{struct _finddata_t}. + +This function supports long file names. + +@subheading Return Value + +Zero if a match is found, -1 if not found (and sets @var{errno}). + +@subheading Portability + +@portability !ansi, !posix + --- /cvsroot/djgpp/src/libc/dos/io/makefile Wed Mar 7 06:34:26 2001 +++ /djgpp-cvs/src/libc/dos/io/makefile Mon Oct 8 21:44:18 2001 @@ -8,6 +8,9 @@ SRC +=3D _close.c SRC +=3D _creat.c SRC +=3D _creat_n.c +SRC +=3D _findfir.c +SRC +=3D _findnex.c +SRC +=3D _findclo.c SRC +=3D _open.c SRC +=3D _read.c SRC +=3D _write.c diff -u /cvsroot/djgpp/include/dir.h /djgpp-cvs/include/dir.h --- /cvsroot/djgpp/include/dir.h Mon Jun 29 01:37:14 1998 +++ /djgpp-cvs/include/dir.h Tue Oct 23 01:11:30 2001 @@ -19,7 +19,20 @@ =20 /* This is for g++ 2.7.2 and below */ #pragma pack(1) - =20 + +/* USEDOSDATE =3D 1 indicates DOS style dates, 0 means Win32 type = dates. + DOS style dates are broken in some Win95 betas, build for either. + Release works with DOS date, it's faster, so use it. */ +#define USEDOSDATE 1 + +#ifdef USEDOSDATE + #define _Win32_to_DOS (long) +#else + long _Win32_to_DOS(long long _WinTime); +#endif + +#define _sizeof_dos_ffblk 44 + struct ffblk { char lfn_magic[6] __attribute__((packed)); /* LFN */ short lfn_handle __attribute__((packed)); /* LFN */ @@ -70,6 +83,9 @@ #define DRIVE 0x10 =20 int __file_tree_walk(const char *_dir, int (*_fn)(const char *_path, = const struct ffblk *_ff)); +long _lfn_findfirst(const char *_pathname, int _attrib, struct ffblklfn = *_ffblklfn); +int _lfn_findnext(long _handle, struct ffblklfn *_ffblklfn); +int _lfn_findclose(long _handle); int findfirst(const char *_pathname, struct ffblk *_ffblk, int = _attrib); int findnext(struct ffblk *_ffblk); void fnmerge (char *_path, const char *_drive, const char *_dir, const = char *_name, const char *_ext); diff -u /cvsroot/djgpp/include/dos.h /djgpp-cvs/include/dos.h --- /cvsroot/djgpp/include/dos.h Mon Sep 24 23:11:04 2001 +++ /djgpp-cvs/include/dos.h Mon Oct 22 20:45:56 2001 @@ -11,6 +11,7 @@ =20 #ifndef _POSIX_SOURCE =20 +#include #include =20 extern int _8087; @@ -158,6 +159,8 @@ int enable(void); int disable(void); =20 +time_t _ftime_to_time_t(struct ftime *_ftimep); + int getftime(int _handle, struct ftime *_ftimep); int setftime(int _handle, struct ftime *_ftimep); =20 @@ -268,7 +271,7 @@ unsigned int _dos_settime(struct _dostime_t *_time); =20 unsigned int _dos_getftime(int _handle, unsigned int *_p_date, = unsigned int *_p_time); -unsigned int _dos_setftime(int _handle, unsigned int _date, unsigned = int _time); +unsigned int _dos_setftime(int _handle, unsigned int _date, unsigned = int _dtime); unsigned int _dos_getfileattr(const char *_filename, unsigned int = *_p_attr); unsigned int _dos_setfileattr(const char *_filename, unsigned int = _attr); =20 diff -u /cvsroot/djgpp/include/io.h /djgpp-cvs/include/io.h --- /cvsroot/djgpp/include/io.h Thu Feb 1 20:39:54 2001 +++ /djgpp-cvs/include/io.h Tue Oct 9 11:00:12 2001 @@ -14,8 +14,20 @@ =20 #ifndef _POSIX_SOURCE =20 +#include /* for the _A_* flags */ #include =20 +typedef unsigned long _fsize_t; + +struct _finddata_t { + unsigned attrib __attribute__((packed)); + time_t time_create __attribute__((packed)); + time_t time_access __attribute__((packed)); + time_t time_write __attribute__((packed)); + _fsize_t size __attribute__((packed)); + char name[260] __attribute__((packed)); +}; + int chsize(int handle, long size); int _close(int _fd); int _creat(const char *_path, int _attrib); @@ -24,6 +36,9 @@ int _dos_lock(int _fd, long _offset, long _length); int _dos_lk64(int _fd, long long _offset, long long _length); long filelength(int _handle); +long _findfirst(const char *_pathname, struct _finddata_t *_fileinfo); +int _findnext(long _handle, struct _finddata_t *_fileinfo); +int _findclose(long _handle); short _get_dev_info(int _arg); long long lfilelength(int _handle); int lock(int _fd, long _offset, long _length); ------=_NextPart_000_0015_01C15BEF.653A1060 Content-Type: application/octet-stream; name="findfile.c" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="findfile.c" #include #include #include #include #include #include void usage(void) { fprintf(stderr, "Usage:\n"); fprintf(stderr, " findfile [-i] pattern\n"); fprintf(stderr, "where i can take one of the following values:\n"); fprintf(stderr, " - 1 use the basic DOS _dos_findfirst() = function\n"); fprintf(stderr, " - 2 use the Borland-compatible findfirst() = function\n"); fprintf(stderr, " - 3 use the Watcom-compatible _findfirst() = function\n"); exit(EXIT_FAILURE); } #define ALL_ATTRIB (_A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_VOLID | = _A_SUBDIR | _A_ARCH) #define ALL_FATTRIB (FA_RDONLY | FA_HIDDEN | FA_SYSTEM | FA_LABEL | = FA_DIREC | FA_ARCH) int main(int argc, char *argv[]) { struct _find_t result; struct ffblk ffblk; struct _finddata_t fileinfo; int ret, handle; time_t time_write; char attrib_str[7], time_str[64]; int level =3D 3, c =3D 0; if (argc < 2) usage(); if (argv[1][0] =3D=3D '-') { if (argc < 3) usage(); level =3D argv[1][1] - '0'; if ((level<1) || (level>3)) usage(); argv[1] =3D argv[2]; } switch (level) { case 1: ret =3D _dos_findfirst(argv[1], ALL_ATTRIB, &result); if (ret) { printf("no matching file.\n"); } else { do { attrib_str[0] =3D (result.attrib&_A_RDONLY ? 'r' : '-'); attrib_str[1] =3D (result.attrib&_A_HIDDEN ? 'h' : '-'); attrib_str[2] =3D (result.attrib&_A_SYSTEM ? 's' : '-'); attrib_str[3] =3D (result.attrib&_A_VOLID ? 'l' : '-'); attrib_str[4] =3D (result.attrib&_A_SUBDIR ? 'd' : '-'); attrib_str[5] =3D (result.attrib&_A_ARCH ? 'a' : '-'); attrib_str[6] =3D '\0'; time_write =3D _ftime_to_time_t((struct ftime = *)&result.wr_time); strftime(time_str, sizeof(time_str), "%m/%d/%Y %H:%M ", = localtime(&time_write)); printf("%-14s %5ld kb %s %s\n", result.name, 1 + = result.size/1024, attrib_str, time_str); c++; } while (_dos_findnext(&result) =3D=3D 0); printf("%d matching file%s\n", c, c>1 ? "s." : "."); } break; case 2: ret =3D findfirst(argv[1], &ffblk, ALL_FATTRIB); if (ret) { printf("no matching file.\n"); } else { do { attrib_str[0] =3D (ffblk.ff_attrib&FA_RDONLY ? 'r' : = '-'); attrib_str[1] =3D (ffblk.ff_attrib&FA_HIDDEN ? 'h' : = '-'); attrib_str[2] =3D (ffblk.ff_attrib&FA_SYSTEM ? 's' : = '-'); attrib_str[3] =3D (ffblk.ff_attrib&FA_LABEL ? 'l' : = '-'); attrib_str[4] =3D (ffblk.ff_attrib&FA_DIREC ? 'd' : = '-'); attrib_str[5] =3D (ffblk.ff_attrib&FA_ARCH ? 'a' : = '-'); attrib_str[6] =3D '\0'; time_write =3D _ftime_to_time_t((struct ftime = *)&ffblk.ff_ftime); strftime(time_str, sizeof(time_str), "%m/%d/%Y %H:%M ", = localtime(&time_write)); printf("%-14s %5ld kb %s %s\n", ffblk.ff_name, 1 + = ffblk.ff_fsize/1024, attrib_str, time_str); c++; } while (findnext(&ffblk) =3D=3D 0); printf("%d matching file%s\n", c, c>1 ? "s." : "."); } break; case 3: handle =3D _findfirst(argv[1], &fileinfo); if (handle<0) { printf("no matching file.\n"); } else { do { attrib_str[0] =3D (fileinfo.attrib&_A_RDONLY ? 'r' : = '-'); attrib_str[1] =3D (fileinfo.attrib&_A_HIDDEN ? 'h' : = '-'); attrib_str[2] =3D (fileinfo.attrib&_A_SYSTEM ? 's' : = '-'); attrib_str[3] =3D (fileinfo.attrib&_A_VOLID ? 'l' : = '-'); attrib_str[4] =3D (fileinfo.attrib&_A_SUBDIR ? 'd' : = '-'); attrib_str[5] =3D (fileinfo.attrib&_A_ARCH ? 'a' : = '-'); attrib_str[6] =3D '\0'; strftime(time_str, sizeof(time_str), "%m/%d/%Y %H:%M ", = localtime(&fileinfo.time_write)); printf("%-14s %5ld kb %s %s\n", fileinfo.name, 1 + = fileinfo.size/1024, attrib_str, time_str); c++; } while (_findnext(handle, &fileinfo) =3D=3D 0); _findclose(handle); printf("%d matching file%s\n", c, c>1 ? "s." : "."); } break; } return 0; } ------=_NextPart_000_0015_01C15BEF.653A1060--