home *** CD-ROM | disk | FTP | other *** search
/ Shareware Supreme Volume 6 #1 / swsii.zip / swsii / 099 / SH164AS.ZIP / LIB / DIRECTOR.C next >
C/C++ Source or Header  |  1992-02-28  |  4KB  |  201 lines

  1. /*
  2.  * @(#)msd_dir.c 1.4 87/11/06    Public Domain.
  3.  *
  4.  *  A public domain implementation of BSD directory routines for
  5.  *  MS-DOS.  Written by Michael Rendell ({uunet,utai}michael@garfield),
  6.  *  August 1897
  7.  *
  8.  *  Modified by Ian Stewartson, Data Logic.
  9.  */
  10.  
  11. #include <sys/types.h>
  12. #include <sys/stat.h>
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <malloc.h>
  16. #include <string.h>
  17. #include <limits.h>
  18. #include <errno.h>
  19. #include <dirent.h>
  20. #include <dos.h>
  21.  
  22. #define    ATTRIBUTES        (_A_SUBDIR | _A_HIDDEN | _A_SYSTEM | \
  23.                  _A_NORMAL | _A_RDONLY | _A_ARCH)
  24.  
  25. typedef struct _dircontents    DIRCONT;
  26. static void            free_dircontents (DIRCONT *);
  27.  
  28. DIR    *opendir(name)
  29. char    *name;
  30. {
  31.     struct stat        statb;
  32.     DIR            *dirp;
  33.     char        *last;
  34.     DIRCONT        *dp;
  35.     char        *nbuf;
  36.     struct find_t    dtabuf;
  37.     int            len = strlen (name);
  38.     
  39.     if (!len)
  40.     {
  41.     errno = ENOTDIR;
  42.     return (DIR *)NULL;
  43.     }
  44.  
  45.     if ((nbuf = malloc (len + 5)) == (char *)NULL)
  46.     return (DIR *) NULL;
  47.  
  48.     strcpy (nbuf, name);
  49.     last = &nbuf[len - 1];
  50.  
  51. /* Ok, DOS is very picky about its directory names.  The following are
  52.  * valid.
  53.  *
  54.  *  c:/
  55.  *  c:.
  56.  *  c:name/name1
  57.  *
  58.  *  c:name/ is not valid
  59.  */
  60.  
  61.     if (((*last == '\\') || (*last == '/')) && (len > 1) &&
  62.     (!((len == 3) && (name[1] == ':'))))
  63.     *(last--) = 0;
  64.  
  65. /* Check its a directory */    
  66.  
  67.     if (stat (nbuf, &statb) < 0)
  68.     {
  69.     free (nbuf);
  70.     return (DIR *) NULL;
  71.     }
  72.  
  73.     if (!S_ISDIR (statb.st_mode))
  74.     {
  75.     free (nbuf);
  76.     errno = ENOTDIR;
  77.     return (DIR *)NULL;
  78.     }
  79.  
  80.     if ((dirp = (DIR *) malloc (sizeof (DIR))) == (DIR *) NULL)
  81.     {
  82.     free (nbuf);
  83.     return (DIR *) NULL;
  84.     }
  85.  
  86. /* Set up to find everything */
  87.  
  88.     if ((*last != '\\') && (*last != '/'))
  89.     strcat (last, "/");
  90.  
  91.     strcat (last, "*.*");
  92.  
  93.     dirp->dd_loc      = 0;
  94.     dirp->dd_cp       = (DIRCONT *) NULL;
  95.     dirp->dd_contents = (DIRCONT *) NULL;
  96.  
  97.     if (_dos_findfirst (nbuf, ATTRIBUTES, &dtabuf) != 0)
  98.     {
  99.     free (nbuf);
  100.     return dirp;
  101.     }
  102.  
  103.     do 
  104.     {
  105.     if (((dp = (DIRCONT *) malloc (sizeof (DIRCONT))) == (DIRCONT *)NULL) ||
  106.         ((dp->_d_entry = strdup (dtabuf.name)) == (char *) NULL))
  107.     {
  108.         if (dp != (char *)NULL)
  109.         free ((char *)dp);
  110.  
  111.         free (nbuf);
  112.         free_dircontents (dirp->dd_contents);
  113.         return (DIR *) NULL;
  114.     }
  115.  
  116.     if (dirp->dd_contents != (DIRCONT *) NULL)
  117.         dirp->dd_cp = dirp->dd_cp->_d_next = dp;
  118.  
  119.     else
  120.         dirp->dd_contents = dirp->dd_cp = dp;
  121.  
  122.     dp->_d_next = (DIRCONT *) NULL;
  123.  
  124.     } while (_dos_findnext (&dtabuf) == 0);
  125.  
  126.     dirp->dd_cp = dirp->dd_contents;
  127.     free (nbuf);
  128.  
  129.     return dirp;
  130. }
  131.  
  132. int    closedir (dirp)
  133. DIR    *dirp;
  134. {
  135.     free_dircontents (dirp->dd_contents);
  136.     free ((char *)dirp);
  137.     return 0;
  138. }
  139.  
  140. struct dirent    *readdir (dirp)
  141. DIR        *dirp;
  142. {
  143.     static struct dirent    dp;
  144.     
  145.     if (dirp->dd_cp == (DIRCONT *) NULL)
  146.     return (struct dirent *) NULL;
  147.  
  148.     dp.d_reclen = strlen (strcpy (dp.d_name, dirp->dd_cp->_d_entry));
  149.     dp.d_off    = dirp->dd_loc * 32;
  150.     dp.d_ino    = (ino_t)++dirp->dd_loc;
  151.     dirp->dd_cp = dirp->dd_cp->_d_next;
  152.     strlwr (dp.d_name);
  153.  
  154.     return &dp;
  155. }
  156.  
  157. void    rewinddir (dirp)
  158. DIR    *dirp;
  159. {
  160.     seekdir (dirp, (off_t)0);
  161. }
  162.  
  163. void    seekdir (dirp, off)
  164. DIR    *dirp;
  165. off_t    off;
  166. {
  167.     long    i = off;
  168.     DIRCONT    *dp;
  169.  
  170.     if (off < 0L)
  171.     return;
  172.  
  173.     for (dp = dirp->dd_contents; (--i >= 0) && (dp != (DIRCONT *)NULL);
  174.      dp = dp->_d_next)
  175.     ;
  176.  
  177.     dirp->dd_loc = off - (i + 1);
  178.     dirp->dd_cp = dp;
  179. }
  180.  
  181. off_t    telldir(dirp)
  182. DIR    *dirp;
  183. {
  184.     return dirp->dd_loc;
  185. }
  186.  
  187. static void    free_dircontents (dp)
  188. DIRCONT        *dp;
  189. {
  190.     DIRCONT    *odp;
  191.  
  192.     while ((odp = dp) != (DIRCONT *)NULL) 
  193.     {
  194.     if (dp->_d_entry != (char *)NULL)
  195.         free (dp->_d_entry);
  196.  
  197.     dp = dp->_d_next;
  198.     free ((char *)odp);
  199.     }
  200. }
  201.