home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************
- *
- * $Source: /unixb/home/unixlib/source/unixlib37/src/unix/c/RCS/dirent,v $
- * $Date: 1996/10/30 21:59:01 $
- * $Revision: 1.4 $
- * $State: Rel $
- * $Author: unixlib $
- *
- * $Log: dirent,v $
- * Revision 1.4 1996/10/30 21:59:01 unixlib
- * Massive changes made by Nick Burret and Peter Burwood.
- *
- * Revision 1.3 1996/09/16 21:23:52 unixlib
- * CL_0002 Nick Burret
- * Minor changes to file handling
- * Change most error numbers, and use in assembler sources (SJC)
- * Various minor bug fixes and compatability changes.
- *
- * Revision 1.2 1996/05/06 09:01:35 unixlib
- * Updates to sources made by Nick Burrett, Peter Burwood and Simon Callan.
- * Saved for 3.7a release.
- *
- * Revision 1.1 1996/04/19 21:35:27 simon
- * Initial revision
- *
- * 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.
- ***************************************************************************/
-
- static const char rcs_id[] = "$Id: dirent,v 1.4 1996/10/30 21:59:01 unixlib Rel $";
-
- #include <string.h>
- #include <stdlib.h>
- #include <unistd.h>
-
- #include <sys/unix.h>
- #include <sys/syslib.h>
- #include <sys/os.h>
- #include <sys/types.h>
- #include <sys/swis.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 (const char *name)
- {
- int i;
- int r[10];
- _kernel_oserror *e;
- register DIR *d;
- char *rname;
-
- rname = __uname ((char *)name, 0);
-
- if (e = os_file (0x05, rname, r))
- {
- __seterr (e);
- return (0);
- }
-
- if (r[0] != 2 && r[0] != 3) /* pjb, added support for images directories */
- return (0);
-
- if (!(d = malloc (sizeof (DIR))))
- return (0);
- if (!(d->dd_buf = malloc (DIRBUFSIZ)))
- {
- free (d);
- return (0);
- }
- /* We have to store the original format of the name in the
- dirent buffer. The user program might perform some sort of
- hashing and hope that it's copy of the name is the same
- as that of the dirent version. */
- 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];
- _kernel_oserror *e;
- register int i;
- register char *s;
- char *rname;
-
- if (d->dd_off2 < 0)
- return (-1);
-
- /* Got to convert the filename on every usage since it could
- be Unix format. */
- rname = __uname (d->dd_name, 0);
- r[0] = 9;
- r[1] = (int) rname;
- 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 (OS_GBPB, 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;
- if (i >= MAXNAMLEN)
- s[i = MAXNAMLEN - 1] = 0;
- memcpy (r->d_name, s, i);
- r->d_namlen = i;
- r->d_reclen = DIRSIZ (r);
-
- /* The file serial number. This is the same as the st_ino member
- that stat will return for the file. */
- r->d_fileno = __get_file_serial_no (r->d_name);
-
- 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);
- }
-