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