home *** CD-ROM | disk | FTP | other *** search
- /* POSIX compatible directory access routines for TOS */
- /* written by Eric R. Smith and placed in the public domain */
-
- #include <assert.h>
- #include <stddef.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <types.h>
- #include <stat.h>
- #include <errno.h>
- #include <dirent.h>
- #include <osbind.h>
- #include <unistd.h>
- #include "lib.h"
- #include "symdir.h"
- #ifndef _COMPILER_H
- #include <compiler.h>
- #endif
-
- static char *shadowed __PROTO((const char *name, SYMDIR *dir));
-
- ino_t __inode; /* in stat.c */
- DIR *__opendir_chain; /* ditto */
-
- static
- char *shadowed(name, dir)
- const char *name;
- SYMDIR *dir;
- {
- SYMENTRY *ent;
-
- if (!dir)
- return (char *)0;
-
- ent = dir->s_dir;
- while (ent) {
- if (!strcmp(name, ent->linkto) && (ent->flags & SD_AUTO))
- return ent->linkname;
- ent = ent->next;
- }
- return (char *)0;
- }
-
- DIR *opendir(_dirname)
- const char *_dirname;
- {
- char dirname[FILENAME_MAX];
- char tmpnam[_LIB_NAME_MAX];
- char *t;
- DIR *dd;
- struct dirent *d, *x, **last;
- SYMENTRY *lent;
- SYMDIR *ldir;
- long r;
- short i = 0;
- struct _dta mydta, *olddta;
-
- _unx2dos(_dirname, dirname);
-
- #if 0
- /* we should maybe check to see if we're opening a directory */
- /* this code doesn't work, though -- Fattrib is dumb */
- if (dirname[0] && (dirname[1] == ':') && !dirname[2]) {
- /* nothing to do */
- } else {
- r = Fattrib(dirname, 0, FA_DIR|FA_HIDDEN|FA_SYSTEM);
- if (r < 0) {
- errno = -r;
- return NULL;
- }
- else if (!(r & FA_DIR)) {
- errno = EPATH;
- return NULL;
- }
- }
- #endif
-
- if (!(dd = malloc((size_t)sizeof(DIR)))) {
- errno = ENOMEM;
- return NULL;
- }
-
- olddta = (struct _dta *)Fgetdta();
- Fsetdta(&mydta);
-
- d = x = NULL;
- last = &d;
- dd->D_path = strdup(dirname);
-
- /* check for symbolic links in the directory */
- ldir = _read_symdir(dirname);
- if (!ldir)
- goto skip_symlinks;
- lent = ldir->s_dir;
-
- while (lent) {
- x = malloc((size_t)(__DIRENTSIZ(strlen(lent->linkname))));
- if (!x) {
- errno = ENOMEM;
- free(dd->D_path);
- free(dd);
- while(d) {
- x = d->d_next;
- free(d);
- d = x;
- }
- _free_symdir(ldir);
- Fsetdta(olddta); /* reset dta ++jrb */
- return NULL;
- }
- strcpy(x->d_name, lent->linkname);
- x->d_reclen = x->d_size = strlen(x->d_name);
- x->d_ino = ++__inode;
- x->d_off = i++;
- x->d_next = NULL;
- x->d_date = x->d_time = 0;
- x->d_attribute = 0xff; /* mark symbolic link */
- *last = x;
- last = &x->d_next;
- lent = lent->next;
- }
-
- /* OK, so much for the symbolic links. Now for the real directories */
-
- skip_symlinks:
-
- strcat(dirname, "\\*.*");
- if ((r = Fsfirst(dirname, FA_SYSTEM|FA_HIDDEN|FA_DIR)) != 0) {
- /* report an error unless dirname is a root directory */
- /* (all other valid directories have '.' and '..' in them */
- if (!*dirname || strcmp(dirname+1, "\\*.*")) {
- errno = -r;
- while (d) {
- x = d->d_next;
- free(d);
- d = x;
- }
- free(dd->D_path);
- free(dd);
- dd = NULL;
- }
- } else { /* Fsfirst worked OK */
- do {
- _dos2unx(mydta.dta_name, tmpnam);
- /* skip the symbolic directory itself if we're supposed to */
- if (_lHIDE && _lOK && !strcmp(_lDIR, tmpnam))
- continue;
- /* check for files being hidden by auto symlinks */
- if (_lAUTO && (t = shadowed(tmpnam, ldir))) {
- for (x = d; x; x = x->d_next)
- if (!strcmp(x->d_name, t))
- break;
- assert(x != 0);
- /* put the real file's info in the structure */
- goto tos_fill;
- }
- x = malloc((size_t)(__DIRENTSIZ(strlen(tmpnam))));
- if (!x) {
- errno = ENOMEM;
- while (d) {
- x = d->d_next;
- free(d);
- d = x;
- }
- free(dd->D_path);
- free(dd);
- dd = NULL;
- break;
- }
- strcpy(x->d_name, tmpnam);
- x->d_ino = ++__inode; /* make sure no two are equal */
- x->d_off = i++;
- /* I don't know what d_reclen means on Unix, but for TOS we might as well
- stuff the string length in here (so sys/dir.h can be more like BSD) */
- x->d_reclen = strlen(x->d_name);
- x->d_next = NULL;
- *last = x;
- last = &x->d_next;
- tos_fill:
- /* fill in TOS specific stuff so stat can find it later */
- x->d_time = mydta.dta_time;
- x->d_date = mydta.dta_date;
- x->d_attribute = mydta.dta_attribute;
- x->d_size = mydta.dta_size;
- } while (!Fsnext());
- }
-
- Fsetdta(olddta);
- if (dd) {
- dd->D_list = dd->D_curpos = d;
- dd->D_nxtdir = __opendir_chain;
- __opendir_chain = dd;
- }
- _free_symdir(ldir);
- return dd;
- }
-
- struct dirent *readdir(dirp)
- DIR *dirp;
- {
- struct dirent *x;
-
- if (!dirp) return NULL;
-
- x = dirp->D_curpos;
- if (x) dirp->D_curpos = x->d_next;
- return x;
- }
-
- off_t telldir(dirp)
- DIR *dirp;
- {
- struct dirent *x = dirp->D_curpos;
- if (x)
- return x->d_off;
- else
- return -1;
- }
-
- void seekdir(dirp, loc)
- DIR *dirp;
- off_t loc;
- {
- struct dirent *x;
-
- x = dirp->D_list;
- while (x && x->d_off != loc)
- x = x->d_next;
- dirp->D_curpos = x;
- }
-
- void rewinddir(dirp)
- DIR *dirp;
- {
- dirp->D_curpos = dirp->D_list;
- }
-
- int closedir(dirp)
- DIR *dirp;
- {
- struct dirent *x, *oldx;
- DIR **old, *nxt;
-
- if (!dirp) return -1;
-
- if (dirp->D_path)
- free(dirp->D_path);
-
- for (x = dirp->D_list; x; ) {
- oldx = x;
- x = x->d_next;
- free(oldx);
- }
- /* unlink from __opendir_chain */
- old = &__opendir_chain;
- nxt = *old;
- while (nxt) {
- if (nxt == dirp) {
- *old = nxt->D_nxtdir;
- nxt->D_nxtdir = 0;
- break;
- }
- old = &nxt->D_nxtdir;
- nxt = *old;
- }
- free(dirp);
- return 0;
- }
-