guido@cwi.nl.UUCP (Guido van Rossum) (07/18/87)
Since Rich Salz in comp.sources.unix asked for MS-DOS (and other) implementations of Doug Gwyn's directory package, here's what I am using myself. It's only opendir, readdir and closedir, but I've written several programs that use it and port problemless between several Unix flavours, MS-DOS and the Apple Macintosh. -- Guido van Rossum, Centre for Mathematics and Computer Science (CWI), Amsterdam guido@cwi.nl or mcvax!guido or (from ARPAnet) guido%cwi.nl@seismo.css.gov : This is a shell archive. : Extract with 'sh this_file'. echo 'Start of pack.out, part 01 out of 01:' echo 'x - README' sed 's/^X//' > 'README' << 'EOF' XHere's something for MS-DOS that makes it easier to port Unix programs Xthat scan directories: an implementation of opendir, readdir and Xclosedir. X XIt's a rather minimal implementation, e.g., it allows only one open Xdirectory at a time, and there are no rewinddir, telldir and seekdir, Xbut I suspect these are much less used than readdir. X XThis works with Microsoft C 4.0 (and also used to work with 3.0). XOwners of other compilers are on their own. X XBeing sick and tired of copyright wars I hereby place this code in the Xpublic domain, although it would still be nice if my name remained in Xredistributed or changed copies of the source. X XGuido van Rossum XCWI, dept. AA XKruislaan 413 X1098 SJ Amsterdam X XPhone: + 20 - 5924138 X XE-mail: guido@cwi.nl EOF echo 'x - dir.c' sed 's/^X//' > 'dir.c' << 'EOF' X/* X * MS-DOS version of UNIX directory access package. X * (opendir, readdir, closedir). X * Public domain by Guido van Rossum, CWI, Amsterdam (July 1987). X */ X X#include <sys/types.h> X#include <sys/stat.h> X#include <errno.h> X#include <dos.h> Xextern int errno; X#define MAXPATH 64 X X#include "dir.h" Xstatic char *firstf(); Xstatic char *nextf(); X Xtypedef int bool; X#define TRUE 1 X#define FALSE 0 X#define EOS '\0' X#define NULL 0 X Xstatic char dirpath[MAXPATH+1]= ""; Xstatic bool busy= FALSE; X X/* X * Open a directory. X * This MS-DOS version allows only one directory to be open at a time. X * The path must exist and be a directory. X * Then it only saves the file name and returns a pointer to it. X */ X Xchar * Xopendir(path) X char *path; X{ X struct stat buffer; X X if (dirpath[0] != EOS) { X errno= EMFILE; X return NULL; /* Only one directory can be open at a time */ X } X if (stat(path, &buffer) == -1) X return NULL; /* Directory doesn't exist */ X if ((buffer.st_mode & S_IFMT) != S_IFDIR) { X errno= ENOENT; X return NULL; /* Not a directory */ X } X strcpy(dirpath, path); X path= dirpath + strlen(dirpath); X if (path > dirpath && path[-1] != ':' && path[-1] != '/' && X path[-1] != '\\') X *path++ = '\\'; X strcpy(path, "*.*"); X busy= FALSE; /* Tell readdir this is the first time */ X return dirpath; X} X X/* X * Close a directory. X * We must clear the first char of dirpath to signal opendir that X * no directory is open. X */ X Xclosedir(dirp) X char *dirp; X{ X dirp[0]= EOS; X} X X/* X * Read the next directory entry. X */ X Xstruct direct * Xreaddir(dp) X char *dp; X{ X static struct direct buffer; X char *p; X X if (!busy) X p= firstf(dp); X else X p= nextf(); X busy= (p != NULL); X if (!busy) X return NULL; X strcpy(buffer.d_name, p); X buffer.d_namlen= strlen(p); X return &buffer; X} X X X/* X * Low-level implementation -- access to DOS system calls FIRST and NEXT. X */ X Xstatic char dta[64]; /* Device Transfer Area */ X X/* File attributes */ X#define READONLY 0x01 X#define HIDDEN 0x02 X#define SYSTEM 0x04 X#define VOLUMEID 0x08 X#define DIRECTORY 0x10 X#define ARCHIVE 0x20 X X#define MATCHATTR (HIDDEN|SYSTEM|DIRECTORY) X Xstatic char * Xfirstf(pat) X char *pat; X{ X int flags; X union REGS regs; X struct SREGS segregs; X X setdta(dta); X X segread(&segregs); X regs.h.ah = 0x4e; X regs.x.cx = MATCHATTR; X#ifdef M_I86LM /* Large Model -- far pointers */ X regs.x.dx = FP_OFF(pat); X segregs.ds = FP_SEG(pat); X#else X regs.x.dx = (int) pat; X#endif X flags= intdosx(®s, ®s, &segregs); X if (regs.x.cflag) X return NULL; X fixfile(); X return dta + 30; X} X Xstatic char * Xnextf() X{ X int flags; X union REGS regs; X X setdta(dta); X X regs.h.ah = 0x4f; X flags= intdos(®s, ®s); X if (regs.x.cflag) X return NULL; X fixfile(); X return dta + 30; X} X X/* X * Convert the file name in the Device Transfer Area to lower case. X */ X Xstatic Xfixfile() X{ X char *cp; X X for (cp= dta+30; *cp != EOS; ++cp) X *cp= tolower(*cp); X} X X/* X * Tell MS-DOS where the Device Transfer Area is. X */ X Xstatic Xsetdta(dta) X char *dta; X{ X union REGS regs; X struct SREGS segregs; X X segread(&segregs); X regs.h.ah = 0x1a; X#ifdef M_I86LM /* Large Model -- far pointers */ X regs.x.dx = FP_OFF(dta); X segregs.ds = FP_SEG(dta); X#else X regs.x.dx = (int) dta; X#endif X intdosx(®s, ®s, &segregs); X} EOF echo 'x - dir.h' sed 's/^X//' > 'dir.h' << 'EOF' X/* X * Interface for MS-DOS version of UNIX directory access package. X * (opendir, readdir, closedir). X * Public domain by Guido van Rossum, CWI, Amsterdam (July 1987). X */ X Xstruct direct { X char d_namlen; X char d_name[13]; X}; X Xtypedef char DIR; X XDIR *opendir(); Xstruct direct *readdir(); EOF echo 'Part 01 out of 01 of pack.out complete.' exit 0