www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2001/10/09/09:06:32

From: Martin Stromberg <Martin DOT Stromberg AT epl DOT ericsson DOT se>
Message-Id: <200110091305.PAA22981@lws256.lu.erisoft.se>
Subject: Re: _findfirst() patch
To: djgpp-workers AT delorie DOT com
Date: Tue, 9 Oct 2001 15:05:05 +0200 (MET DST)
In-Reply-To: <01e801c150bc$beb39b40$118824d5@zephyr> from "Eric Botcazou" at Oct 09, 2001 02:19:45 PM
X-Mailer: ELM [version 2.5 PL3]
MIME-Version: 1.0
Reply-To: djgpp-workers AT delorie DOT com
Errors-To: nobody AT delorie DOT com
X-Mailing-List: djgpp-workers AT delorie DOT com
X-Unsubscribes-To: listserv AT delorie DOT com

> 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 -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019