home *** CD-ROM | disk | FTP | other *** search
- static char sccs_id[] = "@(#) dirent.c 3.0 " __DATE__ " HJR";
-
- /* dirent.c (c) Copyright 1990 H.Rogers */
-
- /* Jan 1994: Alun Jones, auj@aber.ac.uk
-
- * As supplied, UnixLib can only hold one directory open.
- * If you try to open two, it returns a valid directory pointer,
- * but overwrites the old version. For example, this stops tar from
- * recursing the directory tree. dirent.c is a fixed version of
- * UnixLib's dirent.
- */
-
- #include <string.h>
- #include <stdlib.h>
-
- #include "sys/unix.h"
- #include "sys/syslib.h"
- #include "sys/os.h"
- #include "sys/types.h"
-
- #include "dirent.h"
-
- #define DIRBUFSIZ 1024
- #define DIRBUFSHIFT 10
-
- #define MAXDIRS 32
- static struct
- {
- struct dirent *__dirval;
- DIR *which;
- }
- dirvals[MAXDIRS];
-
- /* opendir() */
-
- DIR *
- opendir (name)
- char *name;
- {
- int i;
- int r[10];
- os_error *e;
- register DIR *d;
-
- name = __uname (name, 0);
-
- if (e = os_file (0x05, name, r))
- {
- __seterr (e);
- return (0);
- }
-
- if (r[0] != 2)
- return (0);
-
- if (!(d = malloc (sizeof (DIR))))
- return (0);
- if (!(d->dd_buf = malloc (DIRBUFSIZ)))
- {
- free (d);
- return (0);
- }
- if (!(d->dd_name = __permstr (name)))
- {
- free (d->dd_buf);
- free (d);
- return (0);
- }
- d->dd_fd = 0;
- d->dd_loc = 0;
- d->dd_size = 0;
- d->dd_bsize = DIRBUFSIZ;
- d->dd_off = 0;
- d->dd_off2 = 0;
-
- for (i = 0; i < MAXDIRS; i++)
- {
- if (!dirvals[i].__dirval)
- {
- if (!(dirvals[i].__dirval = malloc (sizeof (struct dirent))))
- {
- free (d->dd_name);
- free (d->dd_buf);
- free (d);
- return (0);
- }
- dirvals[i].which = d;
- break;
- }
- }
-
- return (d);
- }
-
- /* __nextdir() */
-
- static int
- __nextdir (register DIR * d)
- {
- int r[10];
- os_error *e;
- register int i;
- register char *s;
-
- if (d->dd_off2 < 0)
- return (-1);
-
- r[0] = 9;
- r[1] = (int) d->dd_name;
- r[2] = (int) d->dd_buf;
- r[3] = DIRBUFSIZ / MAXNAMLEN;
- r[4] = d->dd_off2;
- r[5] = DIRBUFSIZ;
- r[6] = (int) "*";
-
- if (e = os_swi (0x0c, r))
- {
- __seterr (e);
- free (d->dd_name);
- free (d->dd_buf);
- free (d);
- return (-1);
- }
-
- for (i = r[3], s = d->dd_buf; i; i--)
- while (*++s);
-
- d->dd_loc = 0;
- d->dd_size = s - d->dd_buf;
- d->dd_off = (d->dd_off2 << DIRBUFSHIFT);
- d->dd_off2 = r[4];
-
- if (r[4] < 0 && !r[3])
- return (-1);
-
- return (0);
- }
-
- /* readdir() */
-
- struct dirent *
- readdir (d)
- register DIR *d;
- {
- register struct dirent *r = NULL;
- register int i;
- register char *s;
-
- if (!d)
- return (0);
-
- for (i = 0; i < MAXDIRS; i++)
- {
- if ((dirvals[i].__dirval) && (dirvals[i].which == d))
- {
- r = dirvals[i].__dirval;
- break;
- }
- }
-
-
- if (!r)
- return (0);
-
- while (d->dd_loc >= d->dd_size)
- if (__nextdir (d))
- return (0);
-
- s = d->dd_buf + d->dd_loc;
- i = strlen (s);
- r->d_off = d->dd_off;
- i++;
- d->dd_off += i;
- d->dd_loc += i;
- r->d_fileno = 0;
- if (i >= MAXNAMLEN)
- s[i = MAXNAMLEN - 1] = 0;
- memcpy (r->d_name, s, i);
- r->d_namlen = i;
- r->d_reclen = DIRSIZ (r);
-
- return (r);
- }
-
- /* telldir() */
-
- long
- telldir (d)
- DIR *d;
- {
- if (!d)
- return (-1);
-
- return (d->dd_off);
- }
-
- /* seekdir() */
-
- void
- seekdir (d, off)
- DIR *d;
- long off;
- {
- if (!d)
- return;
-
- if (d->dd_off2 != (off >> DIRBUFSHIFT))
- {
- d->dd_off2 = (((int) off) >> DIRBUFSHIFT);
- d->dd_loc = 0;
- d->dd_size = 0;
- __nextdir (d);
- }
-
- d->dd_off = (size_t) off;
- d->dd_loc = (size_t) off & (DIRBUFSHIFT - 1);
- }
-
- /* rewinddir() */
-
- void (rewinddir) (d)
- DIR *d;
- {
- rewinddir (d);
- }
-
- /* closedir() */
-
- int
- closedir (d)
- DIR *d;
- {
- int i;
- if (!d)
- return (-1);
-
- for (i = 0; i < MAXDIRS; i++)
- {
- if (dirvals[i].__dirval && (dirvals[i].which == d))
- {
- free (dirvals[i].__dirval);
- dirvals[i].__dirval = 0;
- dirvals[i].which = 0;
- break;
- }
- }
-
- free (d->dd_name);
- free (d->dd_buf);
- free (d);
-
- return (0);
- }
-