home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / zip / mint / mntlib16.lzh / MNTLIB16 / DIRENT.C < prev    next >
C/C++ Source or Header  |  1993-08-03  |  4KB  |  196 lines

  1. /* opendir/readdir/closedir routines */
  2.  
  3. /* under MiNT (v0.9 or better) these use the appropriate system calls.
  4.  * under TOS or older versions of MiNT, they use Fsfirst/Fsnext
  5.  *
  6.  * Written by Eric R. Smith and placed in the public domain
  7.  */
  8.  
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <types.h>
  12. #include <limits.h>
  13. #include <dirent.h>
  14. #include <errno.h>
  15. #include <osbind.h>
  16. #include <mintbind.h>
  17. #include "lib.h"
  18.  
  19. extern int __mint;
  20. extern ino_t __inode;    /* in stat.c */
  21.  
  22. DIR *
  23. opendir(uname)
  24.     const char *uname;
  25. {
  26.     DIR *d;
  27.     long r, olddta;
  28.     char name[PATH_MAX];
  29.     char dirpath[PATH_MAX];
  30.  
  31.     _unx2dos(uname, name);
  32.  
  33.     if (__mint > 8) {
  34.         r = Dopendir(name, 0);
  35.         if ( (r & 0xff000000) == 0xff000000 ) {
  36.             errno = -r;
  37.             return 0;
  38.         }
  39.         return (DIR *)r;
  40.     }
  41.  
  42. /* TOS emulation routines */
  43.  
  44.     d = malloc(sizeof(DIR));
  45.     if (!d) {
  46.         errno = ENOMEM;
  47.         return d;
  48.     }
  49.  
  50.     strcat(name, "\\*.*");
  51.     olddta = Fgetdta();
  52.     Fsetdta(d->dta);
  53.     r = Fsfirst(name, 0xff);
  54.     Fsetdta(olddta);
  55.  
  56.     if (r == 0) {
  57.         d->status = _STARTSEARCH;
  58.     } else if (r == -ENOENT) {
  59.         d->status = _NMFILE;
  60.     } else {
  61.         free(d);
  62.         errno = -r;
  63.         return 0;
  64.     }
  65.     d->buf.d_off = 0;
  66. /* for rewinddir: if necessary, build a relative path */
  67.     if (name[1] == ':') {    /* absolute path, no problem */
  68.         dirpath[0] = 0;
  69.     } else {
  70.         dirpath[0] = Dgetdrv() + 'A';
  71.         dirpath[1] = ':';
  72.         dirpath[2] = 0;
  73.         if (*name != '\\')
  74.             (void)Dgetpath(dirpath+2, 0);
  75.     }
  76.     d->dirname = malloc(strlen(dirpath)+strlen(name)+1);
  77.     if (d->dirname) {
  78.         strcpy(d->dirname, dirpath);
  79.         strcat(d->dirname, name);
  80.     }
  81.     return d;
  82. }
  83.  
  84. struct dirent *
  85. readdir(d)
  86.     DIR *d;
  87. {
  88.     struct dbuf {
  89.         long ino;
  90.         char name[NAME_MAX + 1];
  91.     } dbuf;
  92.     long r, olddta;
  93.     struct dirent *dd = &d->buf;
  94.  
  95.     if (__mint > 8) {
  96.         r = Dreaddir(NAME_MAX+1+sizeof(long), d, &dbuf);
  97.         if (r == -ENMFIL)
  98.             return 0;
  99.         else if (r) {
  100.             errno = -r;
  101.             return 0;
  102.         }
  103.         dd->d_ino = dbuf.ino;
  104.         dd->d_off++;
  105.         dd->d_reclen = strlen(dbuf.name);
  106.         strcpy(dd->d_name, dbuf.name);
  107.         return dd;
  108.     }
  109. /* ordinary TOS search, using Fsnext. Note that the first time through,
  110.  * Fsfirst has already provided valid data for us; for subsequent
  111.  * searches, we need Fsnext.
  112.  */
  113.     if (d->status == _NMFILE)
  114.         return 0;
  115.     if (d->status == _STARTSEARCH) {
  116.         d->status = _INSEARCH;
  117.     } else {
  118.         olddta = Fgetdta();
  119.         Fsetdta(&d->dta);
  120.         r = Fsnext();
  121.         Fsetdta(olddta);
  122.         if (r == -ENMFIL) {
  123.             d->status = _NMFILE;
  124.             return 0;
  125.         } else if (r) {
  126.             errno = -r;
  127.             return 0;
  128.         }
  129.     }
  130.     dd->d_ino = __inode++;
  131.     dd->d_off++;
  132.     _dos2unx(d->dta+30, dd->d_name);
  133.     dd->d_reclen = strlen(dd->d_name);
  134.     return dd;
  135. }
  136.  
  137. void
  138. rewinddir(dirp)
  139.     DIR *dirp;
  140. {
  141.     long r, olddta;
  142.  
  143.     if (__mint >= 9) {
  144.         (void)Drewinddir(dirp);
  145.         return;
  146.     }
  147.  
  148. /* I wish POSIX had allowed an error to occur here! */
  149.     if (!dirp->dirname) {
  150.         return;
  151.     }
  152.  
  153.     olddta = Fgetdta();
  154.     Fsetdta(dirp->dta);
  155.     r = Fsfirst(dirp->dirname, 0xff);
  156.     Fsetdta(olddta);
  157.     if (r == 0) {
  158.         dirp->status = _STARTSEARCH;
  159.     } else {
  160.         dirp->status = _NMFILE;
  161.     }
  162.     dirp->buf.d_off = 0;
  163. }
  164.  
  165. int
  166. closedir(dirp)
  167.     DIR *dirp;
  168. {
  169.     if (__mint > 8) {
  170.         return Dclosedir(dirp);
  171.     }
  172.     free(dirp);
  173.     return 0;
  174. }
  175.  
  176. /* the next two aren't POSIX, but lots of people have them */
  177.  
  178. off_t
  179. telldir(dirp)
  180.     DIR *dirp;
  181. {
  182.     return dirp->buf.d_off;
  183. }
  184.  
  185. void
  186. seekdir(dirp, loc)
  187.     DIR *dirp;
  188.     off_t loc;
  189. {
  190.     rewinddir(dirp);
  191.     while (dirp->buf.d_off != loc) {
  192.         if (!readdir(dirp))
  193.             break;
  194.     }
  195. }
  196.