/* * @(#)msd_dir.c 1.4 87/11/06 Public Domain. * * A public domain implementation of BSD directory routines for * MS-DOS. Written by Michael Rendell ({uunet,utai}michael@garfield), * August 1897 */ #include #include #include "msd_dir.h" #ifndef __TURBOC__ #include #else #include #endif #include #include #ifndef NULL # define NULL 0 #endif /* NULL */ #ifndef MAXPATHLEN # define MAXPATHLEN 255 #endif /* MAXPATHLEN */ /* attribute stuff */ #define A_RONLY 0x01 #define A_HIDDEN 0x02 #define A_SYSTEM 0x04 #define A_LABEL 0x08 #define A_DIR 0x10 #define A_ARCHIVE 0x20 /* dos call values */ #define DOSI_FINDF 0x4e #define DOSI_FINDN 0x4f #define DOSI_SDTA 0x1a #define Newisnull(a, t) ((a = (t *) malloc(sizeof(t))) == (t *) NULL) /* #define ATTRIBUTES (A_DIR | A_HIDDEN | A_SYSTEM) */ #define ATTRIBUTES (A_RONLY | A_SYSTEM | A_DIR) /* what find first/next calls look use */ typedef struct { char d_buf[21]; char d_attribute; unsigned short d_time; unsigned short d_date; long d_size; char d_name[13]; } Dta_buf; static char *getdirent (); static void mysetdta (); static void free_dircontents (); static Dta_buf dtabuf; static Dta_buf *dtapnt = &dtabuf; static union REGS reg, nreg; #if defined(M_I86LM) static struct SREGS sreg; #endif DIR * opendir (name) char *name; { struct stat statb; DIR *dirp; char c; char *s; struct _dircontents *dp; char nbuf[MAXPATHLEN + 1]; if (stat (name, &statb) < 0 || (statb.st_mode & S_IFMT) != S_IFDIR) return (DIR *) NULL; if (Newisnull (dirp, DIR)) return (DIR *) NULL; if (*name && (c = name[strlen (name) - 1]) != '\\' && c != '/') (void) strcat (strcpy (nbuf, name), "\\*.*"); else (void) strcat (strcpy (nbuf, name), "*.*"); dirp->dd_loc = 0; mysetdta (); dirp->dd_contents = dirp->dd_cp = (struct _dircontents *) NULL; if ((s = getdirent (nbuf)) == (char *) NULL) return dirp; do { if (Newisnull (dp, struct _dircontents) || (dp->_d_entry = malloc ((unsigned) (strlen (s) + 1))) == (char *) NULL) { if (dp) free ((char *) dp); free_dircontents (dirp->dd_contents); return (DIR *) NULL; } if (dirp->dd_contents) dirp->dd_cp = dirp->dd_cp->_d_next = dp; else dirp->dd_contents = dirp->dd_cp = dp; (void) strcpy (dp->_d_entry, s); dp->_d_next = (struct _dircontents *) NULL; } while ((s = getdirent ((char *) NULL)) != (char *) NULL); dirp->dd_cp = dirp->dd_contents; return dirp; } void closedir (dirp) DIR *dirp; { free_dircontents (dirp->dd_contents); free ((char *) dirp); } struct dirent * readdir (dirp) DIR *dirp; { static struct dirent dp; if (dirp->dd_cp == (struct _dircontents *) NULL) return (struct dirent *) NULL; dp.d_namlen = dp.d_reclen = strlen (strcpy (dp.d_name, dirp->dd_cp->_d_entry)); strlwr (dp.d_name); /* JF */ dp.d_ino = 0; dirp->dd_cp = dirp->dd_cp->_d_next; dirp->dd_loc++; return &dp; } void seekdir (dirp, off) DIR *dirp; long off; { long i = off; struct _dircontents *dp; if (off < 0) return; for (dp = dirp->dd_contents; --i >= 0 && dp; dp = dp->_d_next) ; dirp->dd_loc = off - (i + 1); dirp->dd_cp = dp; } long telldir (dirp) DIR *dirp; { return dirp->dd_loc; } static void free_dircontents (dp) struct _dircontents *dp; { struct _dircontents *odp; while (dp) { if (dp->_d_entry) free (dp->_d_entry); dp = (odp = dp)->_d_next; free ((char *) odp); } } static char * getdirent (dir) char *dir; { if (dir != (char *) NULL) { /* get first entry */ reg.h.ah = DOSI_FINDF; reg.h.cl = ATTRIBUTES; #if defined(M_I86LM) reg.x.dx = FP_OFF (dir); sreg.ds = FP_SEG (dir); #else reg.x.dx = (unsigned) dir; #endif } else { /* get next entry */ reg.h.ah = DOSI_FINDN; #if defined(M_I86LM) reg.x.dx = FP_OFF (dtapnt); sreg.ds = FP_SEG (dtapnt); #else reg.x.dx = (unsigned) dtapnt; #endif } #if defined(M_I86LM) intdosx (®, &nreg, &sreg); #else intdos (®, &nreg); #endif if (nreg.x.cflag) return (char *) NULL; return dtabuf.d_name; } static void mysetdta () { reg.h.ah = DOSI_SDTA; #if defined(M_I86LM) reg.x.dx = FP_OFF (dtapnt); sreg.ds = FP_SEG (dtapnt); intdosx (®, &nreg, &sreg); #else reg.x.dx = (int) dtapnt; intdos (®, &nreg); #endif }