home *** CD-ROM | disk | FTP | other *** search
- /* opendir/readdir/closedir routines */
-
- /* under MiNT (v0.9 or better) these use the appropriate system calls.
- * under TOS or older versions of MiNT, they use Fsfirst/Fsnext
- *
- * Written by Eric R. Smith and placed in the public domain
- */
-
- #include <stdlib.h>
- #include <string.h>
- #include <types.h>
- #include <limits.h>
- #include <dirent.h>
- #include <errno.h>
- #include <osbind.h>
- #include <mintbind.h>
- #include "lib.h"
-
- extern int __mint;
- extern ino_t __inode; /* in stat.c */
-
- DIR *
- opendir(uname)
- const char *uname;
- {
- DIR *d;
- long r, olddta;
- char name[PATH_MAX];
- char dirpath[PATH_MAX];
-
- _unx2dos(uname, name);
-
- if (__mint > 8) {
- r = Dopendir(name, 0);
- if ( (r & 0xff000000) == 0xff000000 ) {
- errno = -r;
- return 0;
- }
- return (DIR *)r;
- }
-
- /* TOS emulation routines */
-
- d = malloc(sizeof(DIR));
- if (!d) {
- errno = ENOMEM;
- return d;
- }
-
- strcat(name, "\\*.*");
- olddta = Fgetdta();
- Fsetdta(d->dta);
- r = Fsfirst(name, 0xff);
- Fsetdta(olddta);
-
- if (r == 0) {
- d->status = _STARTSEARCH;
- } else if (r == -ENOENT) {
- d->status = _NMFILE;
- } else {
- free(d);
- errno = -r;
- return 0;
- }
- d->buf.d_off = 0;
- /* for rewinddir: if necessary, build a relative path */
- if (name[1] == ':') { /* absolute path, no problem */
- dirpath[0] = 0;
- } else {
- dirpath[0] = Dgetdrv() + 'A';
- dirpath[1] = ':';
- dirpath[2] = 0;
- if (*name != '\\')
- (void)Dgetpath(dirpath+2, 0);
- }
- d->dirname = malloc(strlen(dirpath)+strlen(name)+1);
- if (d->dirname) {
- strcpy(d->dirname, dirpath);
- strcat(d->dirname, name);
- }
- return d;
- }
-
- struct dirent *
- readdir(d)
- DIR *d;
- {
- struct dbuf {
- long ino;
- char name[NAME_MAX + 1];
- } dbuf;
- long r, olddta;
- struct dirent *dd = &d->buf;
-
- if (__mint > 8) {
- r = Dreaddir(NAME_MAX+1+sizeof(long), d, &dbuf);
- if (r == -ENMFIL)
- return 0;
- else if (r) {
- errno = -r;
- return 0;
- }
- dd->d_ino = dbuf.ino;
- dd->d_off++;
- dd->d_reclen = strlen(dbuf.name);
- strcpy(dd->d_name, dbuf.name);
- return dd;
- }
- /* ordinary TOS search, using Fsnext. Note that the first time through,
- * Fsfirst has already provided valid data for us; for subsequent
- * searches, we need Fsnext.
- */
- if (d->status == _NMFILE)
- return 0;
- if (d->status == _STARTSEARCH) {
- d->status = _INSEARCH;
- } else {
- olddta = Fgetdta();
- Fsetdta(&d->dta);
- r = Fsnext();
- Fsetdta(olddta);
- if (r == -ENMFIL) {
- d->status = _NMFILE;
- return 0;
- } else if (r) {
- errno = -r;
- return 0;
- }
- }
- dd->d_ino = __inode++;
- dd->d_off++;
- _dos2unx(d->dta+30, dd->d_name);
- dd->d_reclen = strlen(dd->d_name);
- return dd;
- }
-
- void
- rewinddir(dirp)
- DIR *dirp;
- {
- long r, olddta;
-
- if (__mint >= 9) {
- (void)Drewinddir(dirp);
- return;
- }
-
- /* I wish POSIX had allowed an error to occur here! */
- if (!dirp->dirname) {
- return;
- }
-
- olddta = Fgetdta();
- Fsetdta(dirp->dta);
- r = Fsfirst(dirp->dirname, 0xff);
- Fsetdta(olddta);
- if (r == 0) {
- dirp->status = _STARTSEARCH;
- } else {
- dirp->status = _NMFILE;
- }
- dirp->buf.d_off = 0;
- }
-
- int
- closedir(dirp)
- DIR *dirp;
- {
- if (__mint > 8) {
- return Dclosedir(dirp);
- }
- free(dirp);
- return 0;
- }
-
- /* the next two aren't POSIX, but lots of people have them */
-
- off_t
- telldir(dirp)
- DIR *dirp;
- {
- return dirp->buf.d_off;
- }
-
- void
- seekdir(dirp, loc)
- DIR *dirp;
- off_t loc;
- {
- rewinddir(dirp);
- while (dirp->buf.d_off != loc) {
- if (!readdir(dirp))
- break;
- }
- }
-