home *** CD-ROM | disk | FTP | other *** search
/ RISC DISC 1 / RISC_DISC_1.iso / pd_share / code / unixlib / !UnixLib / src / unix / c / dirent < prev    next >
Encoding:
Text File  |  1994-09-30  |  3.8 KB  |  255 lines

  1. static char sccs_id[] = "@(#) dirent.c 3.0 " __DATE__ " HJR";
  2.  
  3. /* dirent.c (c) Copyright 1990 H.Rogers */
  4.  
  5. /* Jan 1994: Alun Jones, auj@aber.ac.uk
  6.  
  7.  * As supplied, UnixLib can only hold one directory open.
  8.  * If you try to open two, it returns a valid directory pointer,
  9.  * but overwrites the old version. For example, this stops tar from
  10.  * recursing the directory tree. dirent.c is a fixed version of
  11.  * UnixLib's dirent.
  12.  */
  13.  
  14. #include <string.h>
  15. #include <stdlib.h>
  16.  
  17. #include "sys/unix.h"
  18. #include "sys/syslib.h"
  19. #include "sys/os.h"
  20. #include "sys/types.h"
  21.  
  22. #include "dirent.h"
  23.  
  24. #define DIRBUFSIZ    1024
  25. #define DIRBUFSHIFT    10
  26.  
  27. #define MAXDIRS        32
  28. static struct
  29.   {
  30.     struct dirent *__dirval;
  31.     DIR *which;
  32.   }
  33. dirvals[MAXDIRS];
  34.  
  35. /* opendir() */
  36.  
  37. DIR *
  38. opendir (name)
  39.      char *name;
  40. {
  41.   int i;
  42.   int r[10];
  43.   os_error *e;
  44.   register DIR *d;
  45.  
  46.   name = __uname (name, 0);
  47.  
  48.   if (e = os_file (0x05, name, r))
  49.     {
  50.       __seterr (e);
  51.       return (0);
  52.     }
  53.  
  54.   if (r[0] != 2)
  55.     return (0);
  56.  
  57.   if (!(d = malloc (sizeof (DIR))))
  58.     return (0);
  59.   if (!(d->dd_buf = malloc (DIRBUFSIZ)))
  60.     {
  61.       free (d);
  62.       return (0);
  63.     }
  64.   if (!(d->dd_name = __permstr (name)))
  65.     {
  66.       free (d->dd_buf);
  67.       free (d);
  68.       return (0);
  69.     }
  70.   d->dd_fd = 0;
  71.   d->dd_loc = 0;
  72.   d->dd_size = 0;
  73.   d->dd_bsize = DIRBUFSIZ;
  74.   d->dd_off = 0;
  75.   d->dd_off2 = 0;
  76.  
  77.   for (i = 0; i < MAXDIRS; i++)
  78.     {
  79.       if (!dirvals[i].__dirval)
  80.     {
  81.       if (!(dirvals[i].__dirval = malloc (sizeof (struct dirent))))
  82.         {
  83.           free (d->dd_name);
  84.           free (d->dd_buf);
  85.           free (d);
  86.           return (0);
  87.         }
  88.       dirvals[i].which = d;
  89.       break;
  90.     }
  91.     }
  92.  
  93.   return (d);
  94. }
  95.  
  96. /* __nextdir() */
  97.  
  98. static int
  99. __nextdir (register DIR * d)
  100. {
  101.   int r[10];
  102.   os_error *e;
  103.   register int i;
  104.   register char *s;
  105.  
  106.   if (d->dd_off2 < 0)
  107.     return (-1);
  108.  
  109.   r[0] = 9;
  110.   r[1] = (int) d->dd_name;
  111.   r[2] = (int) d->dd_buf;
  112.   r[3] = DIRBUFSIZ / MAXNAMLEN;
  113.   r[4] = d->dd_off2;
  114.   r[5] = DIRBUFSIZ;
  115.   r[6] = (int) "*";
  116.  
  117.   if (e = os_swi (0x0c, r))
  118.     {
  119.       __seterr (e);
  120.       free (d->dd_name);
  121.       free (d->dd_buf);
  122.       free (d);
  123.       return (-1);
  124.     }
  125.  
  126.   for (i = r[3], s = d->dd_buf; i; i--)
  127.     while (*++s);
  128.  
  129.   d->dd_loc = 0;
  130.   d->dd_size = s - d->dd_buf;
  131.   d->dd_off = (d->dd_off2 << DIRBUFSHIFT);
  132.   d->dd_off2 = r[4];
  133.  
  134.   if (r[4] < 0 && !r[3])
  135.     return (-1);
  136.  
  137.   return (0);
  138. }
  139.  
  140. /* readdir() */
  141.  
  142. struct dirent *
  143. readdir (d)
  144.      register DIR *d;
  145. {
  146.   register struct dirent *r = NULL;
  147.   register int i;
  148.   register char *s;
  149.  
  150.   if (!d)
  151.     return (0);
  152.  
  153.   for (i = 0; i < MAXDIRS; i++)
  154.     {
  155.       if ((dirvals[i].__dirval) && (dirvals[i].which == d))
  156.     {
  157.       r = dirvals[i].__dirval;
  158.       break;
  159.     }
  160.     }
  161.  
  162.  
  163.   if (!r)
  164.     return (0);
  165.  
  166.   while (d->dd_loc >= d->dd_size)
  167.     if (__nextdir (d))
  168.       return (0);
  169.  
  170.   s = d->dd_buf + d->dd_loc;
  171.   i = strlen (s);
  172.   r->d_off = d->dd_off;
  173.   i++;
  174.   d->dd_off += i;
  175.   d->dd_loc += i;
  176.   r->d_fileno = 0;
  177.   if (i >= MAXNAMLEN)
  178.     s[i = MAXNAMLEN - 1] = 0;
  179.   memcpy (r->d_name, s, i);
  180.   r->d_namlen = i;
  181.   r->d_reclen = DIRSIZ (r);
  182.  
  183.   return (r);
  184. }
  185.  
  186. /* telldir() */
  187.  
  188. long
  189. telldir (d)
  190.      DIR *d;
  191. {
  192.   if (!d)
  193.     return (-1);
  194.  
  195.   return (d->dd_off);
  196. }
  197.  
  198. /* seekdir() */
  199.  
  200. void
  201. seekdir (d, off)
  202.      DIR *d;
  203.      long off;
  204. {
  205.   if (!d)
  206.     return;
  207.  
  208.   if (d->dd_off2 != (off >> DIRBUFSHIFT))
  209.     {
  210.       d->dd_off2 = (((int) off) >> DIRBUFSHIFT);
  211.       d->dd_loc = 0;
  212.       d->dd_size = 0;
  213.       __nextdir (d);
  214.     }
  215.  
  216.   d->dd_off = (size_t) off;
  217.   d->dd_loc = (size_t) off & (DIRBUFSHIFT - 1);
  218. }
  219.  
  220. /* rewinddir() */
  221.  
  222. void (rewinddir) (d)
  223.      DIR *d;
  224. {
  225.   rewinddir (d);
  226. }
  227.  
  228. /* closedir() */
  229.  
  230. int
  231. closedir (d)
  232.      DIR *d;
  233. {
  234.   int i;
  235.   if (!d)
  236.     return (-1);
  237.  
  238.   for (i = 0; i < MAXDIRS; i++)
  239.     {
  240.       if (dirvals[i].__dirval && (dirvals[i].which == d))
  241.     {
  242.       free (dirvals[i].__dirval);
  243.       dirvals[i].__dirval = 0;
  244.       dirvals[i].which = 0;
  245.       break;
  246.     }
  247.     }
  248.  
  249.   free (d->dd_name);
  250.   free (d->dd_buf);
  251.   free (d);
  252.  
  253.   return (0);
  254. }
  255.