home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / mint / mntlib24 / dirent.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-03  |  3.7 KB  |  211 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;
  28.     _DTA *olddta;
  29.     char name[PATH_MAX];
  30.     char dirpath[PATH_MAX];
  31.     char *p;
  32.  
  33.     _unx2dos(uname, name);
  34.  
  35.     if (__mint > 8) {
  36.         r = Dopendir(name, 0);
  37.         if ( (r & 0xff000000L) == 0xff000000L ) {
  38.             errno = (int) -r;
  39.             return 0;
  40.         }
  41.         return (DIR *)r;
  42.     }
  43.  
  44. /* TOS emulation routines */
  45.  
  46.     d = malloc(sizeof(DIR));
  47.     if (!d) {
  48.         errno = ENOMEM;
  49.         return d;
  50.     }
  51.  
  52.     p = name;
  53.     if (p) {
  54.     /* find the end of the string */
  55.         for (p = name; *p; p++) ;
  56.  
  57.     /* make sure the string ends in '\' */
  58.         if (*(p-1) != '\\') {
  59.             *p++ = '\\';
  60.         }
  61.     }
  62.  
  63.     strcpy(p, "*.*");
  64.     olddta = Fgetdta();
  65.     Fsetdta(&(d->dta));
  66.     r = Fsfirst(name, 0x17);
  67.     Fsetdta(olddta);
  68.  
  69.     if (r == 0) {
  70.         d->status = _STARTSEARCH;
  71.     } else if (r == -ENOENT) {
  72.         d->status = _NMFILE;
  73.     } else {
  74.         free(d);
  75.         errno = (int) -r;
  76.         return 0;
  77.     }
  78.     d->buf.d_off = 0;
  79. /* for rewinddir: if necessary, build a relative path */
  80.     if (name[1] == ':') {    /* absolute path, no problem */
  81.         dirpath[0] = 0;
  82.     } else {
  83.         dirpath[0] = Dgetdrv() + 'A';
  84.         dirpath[1] = ':';
  85.         dirpath[2] = 0;
  86.         if (*name != '\\')
  87.             (void)Dgetpath(dirpath+2, 0);
  88.     }
  89.     d->dirname = malloc(strlen(dirpath)+strlen(name)+1);
  90.     if (d->dirname) {
  91.         strcpy(d->dirname, dirpath);
  92.         strcat(d->dirname, name);
  93.     }
  94.     return d;
  95. }
  96.  
  97. struct dirent *
  98. readdir(d)
  99.     DIR *d;
  100. {
  101.     struct dbuf {
  102.         long ino;
  103.         char name[NAME_MAX + 1];
  104.     } dbuf;
  105.     long r;
  106.     _DTA *olddta;
  107.     struct dirent *dd = &d->buf;
  108.  
  109.     if (__mint > 8) {
  110.         r = (int)Dreaddir((int)(NAME_MAX+1+sizeof(long)), d, (char *) &dbuf);
  111.         if (r == -ENMFIL)
  112.             return 0;
  113.         else if (r) {
  114.             errno = (int) -r;
  115.             return 0;
  116.         }
  117.         dd->d_ino = dbuf.ino;
  118.         dd->d_off++;
  119.         dd->d_reclen = strlen(dbuf.name);
  120.         strcpy(dd->d_name, dbuf.name);
  121.         return dd;
  122.     }
  123. /* ordinary TOS search, using Fsnext. Note that the first time through,
  124.  * Fsfirst has already provided valid data for us; for subsequent
  125.  * searches, we need Fsnext.
  126.  */
  127.     if (d->status == _NMFILE)
  128.         return 0;
  129.     if (d->status == _STARTSEARCH) {
  130.         d->status = _INSEARCH;
  131.     } else {
  132.         olddta = Fgetdta();
  133.         Fsetdta(&(d->dta));
  134.         r = Fsnext();
  135.         Fsetdta(olddta);
  136.         if (r == -ENMFIL) {
  137.             d->status = _NMFILE;
  138.             return 0;
  139.         } else if (r) {
  140.             errno = (int)-r;
  141.             return 0;
  142.         }
  143.     }
  144.     dd->d_ino = __inode++;
  145.     dd->d_off++;
  146.     _dos2unx(d->dta.dta_name, dd->d_name);
  147.     dd->d_reclen = strlen(dd->d_name);
  148.     return dd;
  149. }
  150.  
  151. void
  152. rewinddir(dirp)
  153.     DIR *dirp;
  154. {
  155.     long r;
  156.     _DTA *olddta;
  157.  
  158.     if (__mint >= 9) {
  159.         (void)Drewinddir(dirp);
  160.         return;
  161.     }
  162.  
  163. /* I wish POSIX had allowed an error to occur here! */
  164.     if (!dirp->dirname) {
  165.         return;
  166.     }
  167.  
  168.     olddta = Fgetdta();
  169.     Fsetdta(&(dirp->dta));
  170.     r = Fsfirst(dirp->dirname, 0x17);
  171.     Fsetdta(olddta);
  172.     if (r == 0) {
  173.         dirp->status = _STARTSEARCH;
  174.     } else {
  175.         dirp->status = _NMFILE;
  176.     }
  177.     dirp->buf.d_off = 0;
  178. }
  179.  
  180. int
  181. closedir(dirp)
  182.     DIR *dirp;
  183. {
  184.     if (__mint > 8) {
  185.         return (int)Dclosedir(dirp);
  186.     }
  187.     free(dirp);
  188.     return 0;
  189. }
  190.  
  191. /* the next two aren't POSIX, but lots of people have them */
  192.  
  193. off_t
  194. telldir(dirp)
  195.     DIR *dirp;
  196. {
  197.     return dirp->buf.d_off;
  198. }
  199.  
  200. void
  201. seekdir(dirp, loc)
  202.     DIR *dirp;
  203.     off_t loc;
  204. {
  205.     rewinddir(dirp);
  206.     while (dirp->buf.d_off != loc) {
  207.         if (!readdir(dirp))
  208.             break;
  209.     }
  210. }
  211.