Mail Archives: djgpp-workers/2001/10/09/09:06:32
> I've uploaded a patch again the CVS code of yesterday that adds the three
> Watcom/MinGW/MSVC compatible _findfirst(), _findnext() and _findclose()
> functions to the libc, as Eli Zaretskii suggested a few days ago on the
> comp.os.msdos.djgpp newsgroup, at the address:
> http://www.multimania.com/ebotcazou/dev/djgpp_findfirst.zip
May I suggest you post the diffs yourself next time. It makes it much
easier to discuss them.
findfirst.diff:
diff -Nu /cvsroot/djgpp/src/libc/dos/io/_findclo.c /djgpp-cvs/src/libc/dos/io/_findclo.c
--- /cvsroot/djgpp/src/libc/dos/io/_findclo.c Thu Jan 1 00:00:00 1970
+++ /djgpp-cvs/src/libc/dos/io/_findclo.c Tue Oct 9 11:36:30 2001
@@ -0,0 +1,31 @@
+#include <libc/dosio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <dpmi.h>
+#include <io.h>
+
+int
+_findclose(long handle)
+{
+ __dpmi_regs r;
+
+ if (_USE_LFN) {
+
+ r.x.ax = 0x71a1;
+ r.x.bx = handle;
+ __dpmi_int(0x21, &r);
+
+ if (!(r.x.flags & 1))
+ return 0;
+ }
+ else {
+
+ free((struct ffblk*)handle);
+ return 0;
+ }
+
+ errno = __doserr_to_errno(r.x.ax);
+ return -1;
+}
+
diff -Nu /cvsroot/djgpp/src/libc/dos/io/_findclo.txh /djgpp-cvs/src/libc/dos/io/_findclo.txh
--- /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 <io.h>
+
+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
+
diff -Nu /cvsroot/djgpp/src/libc/dos/io/_findfir.c /djgpp-cvs/src/libc/dos/io/_findfir.c
--- /cvsroot/djgpp/src/libc/dos/io/_findfir.c Thu Jan 1 00:00:00 1970
+++ /djgpp-cvs/src/libc/dos/io/_findfir.c Tue Oct 9 10:29:10 2001
@@ -0,0 +1,113 @@
+#include <libc/stubs.h>
+#include <libc/dosio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <fcntl.h>
+#include <go32.h>
+#include <dpmi.h>
+#include <dir.h>
+#include <io.h>
+
+extern time_t __dostime_to_time_t(unsigned short dosdate, unsigned short dostime);
+
+time_t __dostime_to_time_t(unsigned short dosdate, unsigned short dostime)
+{
+ struct tm t;
+
+ memset(&t, 0, sizeof(struct tm));
+ t.tm_sec = (dostime & 0x1F) * 2;
+ t.tm_min = (dostime >> 5) & 0x3F;
+ t.tm_hour = (dostime >> 11) & 0x1F;
+ t.tm_mday = (dosdate & 0x1F);
+ t.tm_mon = ((dosdate >> 5) & 0x0F) - 1;
+ t.tm_year = (dosdate >> 9) + 80;
+ t.tm_isdst = -1;
+
+ return mktime(&t);
+}
+
+long
+_findfirst(const char *pathname, struct _finddata_t *fileinfo)
+{
+ __dpmi_regs r;
+ int pathlen;
+
+ if (!pathname || !fileinfo) {
+ errno = EACCES;
+ return -1;
+ }
+
+ pathlen = strlen(pathname) + 1;
+ _put_path(pathname);
+
+ if (_USE_LFN) {
+
+ r.x.ax = 0x714e;
+ r.x.cx = _A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_VOLID | _A_SUBDIR | _A_ARCH;
+ r.x.dx = __tb_offset;
+ r.x.ds = __tb_segment;
+ r.x.di = __tb_offset + pathlen;
+ r.x.es = r.x.ds;
+ r.x.si = 1; /* DOS style date */
+ __dpmi_int(0x21, &r);
+
+ if (!(r.x.flags & 1)) {
+ struct ffblklfn ffblk32;
+
+ /* Recover results */
+ dosmemget(__tb+pathlen, sizeof(struct ffblklfn), &ffblk32);
+
+ fileinfo->attrib = (unsigned)ffblk32.fd_attrib;
+ fileinfo->time_create = __dostime_to_time_t(ffblk32.fd_ctime>>16, ffblk32.fd_ctime);
+ fileinfo->time_access = __dostime_to_time_t(ffblk32.fd_atime>>16, ffblk32.fd_atime);
+ fileinfo->time_write = __dostime_to_time_t(ffblk32.fd_mtime>>16, ffblk32.fd_mtime);
+ fileinfo->size = (_fsize_t)ffblk32.fd_size;
+ strcpy(fileinfo->name, ffblk32.fd_longname);
+
+ return (long)r.x.ax;
+ }
+ }
+ else {
+
+ #define _sizeof_dos_ffblk 44
+ /* There will be a _sizeof_dos_ffblk character return value from findfirst
+ * in the DTA. Put the file name before this. First set the DTA to be
+ * transfer buffer.
+ */
+ r.h.ah = 0x1a;
+ r.x.dx = __tb_offset + pathlen;
+ r.x.ds = __tb_segment;
+ __dpmi_int(0x21, &r);
+
+ r.h.ah = 0x4e;
+ r.x.dx = __tb_offset;
+ r.x.ds = __tb_segment;
+ r.x.cx = _A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_VOLID | _A_SUBDIR | _A_ARCH;
+ __dpmi_int(0x21, &r);
+
+ if (!(r.x.flags & 1)) {
+ struct ffblk *ffblk16 = malloc(_sizeof_dos_ffblk);
+ if (!ffblk16) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ /* Recover results */
+ dosmemget(__tb+pathlen, _sizeof_dos_ffblk, ffblk16);
+
+ fileinfo->attrib = (unsigned)ffblk16->ff_attrib;
+ fileinfo->time_create = -1;
+ fileinfo->time_access = -1;
+ fileinfo->time_write = __dostime_to_time_t(ffblk16->ff_fdate, ffblk16->ff_ftime);
+ fileinfo->size = (_fsize_t)ffblk16->ff_fsize;
+ strcpy(fileinfo->name, ffblk16->ff_name);
+
+ return (long)ffblk16;
+ }
+ }
+
+ errno = __doserr_to_errno(r.x.ax);
+ return -1;
+}
diff -Nu /cvsroot/djgpp/src/libc/dos/io/_findfir.txh /djgpp-cvs/src/libc/dos/io/_findfir.txh
--- /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 <io.h>
+
+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{<io.h>} 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 <io.h>
+#include <time.h>
+
+struct _finddata_t fileinfo;
+long handle;
+char attrib_str[7], time_str[32];
+int c = 0;
+
+handle = _findfirst("*.dat", &fileinfo);
+
+if (handle<0)
+@{
+ printf("no matching file.\n");
+@}
+else
+@{
+ do
+ @{
+ attrib_str[0] = (fileinfo.attrib&_A_RDONLY ? 'r' : '-');
+ attrib_str[1] = (fileinfo.attrib&_A_HIDDEN ? 'h' : '-');
+ attrib_str[2] = (fileinfo.attrib&_A_SYSTEM ? 's' : '-');
+ attrib_str[3] = (fileinfo.attrib&_A_VOLID ? 'l' : '-');
+ attrib_str[4] = (fileinfo.attrib&_A_SUBDIR ? 'd' : '-');
+ attrib_str[5] = (fileinfo.attrib&_A_ARCH ? 'a' : '-');
+ attrib_str[6] = '\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) == 0);
+
+ _findclose(handle);
+
+ printf("%d matching file%s\n", c, c>1 ? "s." : ".");
+@}
+@end example
diff -Nu /cvsroot/djgpp/src/libc/dos/io/_findnex.c /djgpp-cvs/src/libc/dos/io/_findnex.c
--- /cvsroot/djgpp/src/libc/dos/io/_findnex.c Thu Jan 1 00:00:00 1970
+++ /djgpp-cvs/src/libc/dos/io/_findnex.c Tue Oct 9 10:29:26 2001
@@ -0,0 +1,84 @@
+#include <libc/stubs.h>
+#include <libc/dosio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <go32.h>
+#include <dpmi.h>
+#include <dir.h>
+#include <io.h>
+
+extern time_t __dostime_to_time_t(unsigned short dosdate, unsigned short dostime);
+
+int
+_findnext(long handle, struct _finddata_t *fileinfo)
+{
+ __dpmi_regs r;
+
+ if (!fileinfo) {
+ errno = EACCES;
+ return -1;
+ }
+
+ if (_USE_LFN) {
+
+ r.x.ax = 0x714f;
+ r.x.bx = handle;
+ r.x.di = __tb_offset;
+ r.x.es = __tb_segment;
+ r.x.si = 1; /* DOS style date */
+ __dpmi_int(0x21, &r);
+
+ if (!(r.x.flags & 1)) {
+ struct ffblklfn ffblk32;
+
+ /* Recover results */
+ dosmemget(__tb, sizeof(struct ffblklfn), &ffblk32);
+
+ fileinfo->attrib = (unsigned)ffblk32.fd_attrib;
+ fileinfo->time_create = __dostime_to_time_t(ffblk32.fd_ctime>>16, ffblk32.fd_ctime);
+ fileinfo->time_access = __dostime_to_time_t(ffblk32.fd_atime>>16, ffblk32.fd_atime);
+ fileinfo->time_write = __dostime_to_time_t(ffblk32.fd_mtime>>16, ffblk32.fd_mtime);
+ fileinfo->size = (_fsize_t)ffblk32.fd_size;
+ strcpy(fileinfo->name, ffblk32.fd_longname);
+
+ return 0;
+ }
+ }
+ 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.h.ah = 0x1a;
+ r.x.dx = __tb_offset;
+ r.x.ds = __tb_segment;
+ __dpmi_int(0x21, &r);
+
+ dosmemput((struct ffblk *)handle, sizeof(struct ffblk), __tb);
+
+ r.h.ah = 0x4f;
+ __dpmi_int(0x21, &r);
+
+ if (!(r.x.flags & 1)) {
+ struct ffblk *ffblk16 = (struct ffblk *)handle;
+
+ /* Recover results */
+ dosmemget(__tb, _sizeof_dos_ffblk, ffblk16);
+
+ fileinfo->attrib = (unsigned)ffblk16->ff_attrib;
+ fileinfo->time_create = -1;
+ fileinfo->time_access = -1;
+ fileinfo->time_write = __dostime_to_time_t(ffblk16->ff_fdate, ffblk16->ff_ftime);
+ fileinfo->size = (_fsize_t)ffblk16->ff_fsize;
+ strcpy(fileinfo->name, ffblk16->ff_name);
+
+ return 0;
+ }
+ }
+
+ errno = __doserr_to_errno(r.x.ax);
+ return -1;
+}
diff -Nu /cvsroot/djgpp/src/libc/dos/io/_findnex.txh /djgpp-cvs/src/libc/dos/io/_findnex.txh
--- /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 <io.h>
+
+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
+
diff -Nu /cvsroot/djgpp/src/libc/dos/io/makefile /djgpp-cvs/src/libc/dos/io/makefile
--- /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 += _close.c
SRC += _creat.c
SRC += _creat_n.c
+SRC += _findclo.c
+SRC += _findfir.c
+SRC += _findnex.c
SRC += _open.c
SRC += _read.c
SRC += _write.c
--- /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 @@
#ifndef _POSIX_SOURCE
+#include <dos.h> /* for the _A_* flags */
#include <sys/types.h>
+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);
> The zip file also contains a little program (findfile.c) that exercises the
> three functions, tested under Win95 OSR2 and MS-DOS 7. Note that the program
> compiles unmodified under MinGW.
findfile.c:
#include <stdio.h>
#include <time.h>
#include <io.h>
int main(int argc, char *argv[])
{
struct _finddata_t fileinfo;
long handle;
char attrib_str[7], time_str[32];
int c = 0;
if (argc < 2)
return 1;
handle = _findfirst(argv[1], &fileinfo);
if (handle<0) {
printf("no matching file.\n");
}
else {
do {
attrib_str[0] = (fileinfo.attrib&_A_RDONLY ? 'r' : '-');
attrib_str[1] = (fileinfo.attrib&_A_HIDDEN ? 'h' : '-');
attrib_str[2] = (fileinfo.attrib&_A_SYSTEM ? 's' : '-');
attrib_str[3] = (fileinfo.attrib&_A_VOLID ? 'l' : '-');
attrib_str[4] = (fileinfo.attrib&_A_SUBDIR ? 'd' : '-');
attrib_str[5] = (fileinfo.attrib&_A_ARCH ? 'a' : '-');
attrib_str[6] = '\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) == 0);
_findclose(handle);
printf("%d matching file%s\n", c, c>1 ? "s." : ".");
}
return 0;
}
Right,
MartinS
- Raw text -