home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / emacs-19.28-src.tgz / tar.out / fsf / emacs / unixlib / src / dir.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  4KB  |  178 lines

  1. #include "amiga.h"
  2. #include "dir_data.h"
  3. #include <string.h>
  4.  
  5. /* opendir/readdir/etc ... emulation w/ stat support hack */
  6.  
  7. static void free_entries(iDIR *info)
  8. {
  9.   struct idirent *scan = info->files;
  10.   
  11.   while (scan)
  12.     {
  13.       struct idirent *next = scan->next;
  14.       
  15.       free(scan);
  16.       scan = next;
  17.     }
  18. }
  19.  
  20. static int gobble_dir(DIR *dir)
  21. {
  22.   iDIR *info = (iDIR *)dir->dd_buf;
  23.   long ioerr;
  24.   struct idirent **last = &info->files;
  25.   struct FileLock *dirlock;
  26.   
  27.   free_entries(info);
  28.   last_dir = 0;
  29.   info->files = 0;
  30.   dir->dd_loc = 0;
  31.   /* Find a value for st_dev of stat() calls */
  32.   dirlock = BADDR(dir->dd_fd);
  33.   info->task = dirlock->fl_Task;
  34.   while (ExNext(dir->dd_fd, &info->fib))
  35.     {
  36.       u_short namlen = strlen(info->fib.fib_FileName);
  37.       u_short reclen = namlen + 1 + offsetof(struct idirent, entry.d_name);
  38.       struct idirent *newentry = (struct idirent *)malloc(reclen);
  39.       struct dirent *entry;
  40.       
  41.       if (!newentry)
  42.     {
  43.       errno = ENOMEM;
  44.       return 0;
  45.     }
  46.       newentry->next = 0;
  47.       *last = newentry;
  48.       last = &newentry->next;
  49.       
  50.       newentry->numblocks = info->fib.fib_NumBlocks;
  51.       newentry->size = info->fib.fib_Size;
  52.       newentry->date = info->fib.fib_Date;
  53.       newentry->type = info->fib.fib_DirEntryType;
  54.       newentry->protection = info->fib.fib_Protection;
  55.       
  56.       entry = &newentry->entry;
  57.       entry->d_reclen = reclen;
  58.       entry->d_namlen = namlen;
  59.       entry->d_off = dir->dd_loc++;
  60.       strcpy(entry->d_name, info->fib.fib_FileName);
  61.       entry->d_ino = info->fib.fib_DiskKey;
  62.     }
  63.   info->pos = info->files;
  64.   dir->dd_loc = 0;
  65.   ioerr = IoErr();
  66.   if (ioerr == ERROR_NO_MORE_ENTRIES) return 1;
  67.   
  68.   errno = convert_oserr(ioerr);
  69.   return 0;
  70. }
  71.  
  72. DIR *opendir(char *dirname)
  73. {
  74.   DIR *new = (DIR *)malloc(sizeof *new);
  75.   iDIR *info = (iDIR *)malloc(sizeof *info);
  76.   char *dircopy = malloc(strlen(dirname) + 1);
  77.  
  78.   chkabort();
  79.   if (new && dircopy && info)
  80.     {
  81.       new->dd_buf = (char *)info;
  82.       new->dd_size = sizeof *info;
  83.       
  84.       info->files = info->pos = 0;
  85.       info->seeked = 0;
  86.       info->dirname = dircopy;
  87.       strcpy(dircopy, dirname);
  88.       info->cdir = _get_cd();
  89.       
  90.       if ((new->dd_fd = Lock(dirname, ACCESS_READ)) &&
  91.       Examine(new->dd_fd, &info->fib))
  92.     {
  93.       if (gobble_dir(new)) return new;
  94.     }
  95.       else errno = convert_oserr(IoErr());
  96.       closedir(new);
  97.       return 0;
  98.     }
  99.   
  100.   errno = ENOMEM;
  101.   if (new) free(new);
  102.   if (dircopy) free(dircopy);
  103.   if (info) free(info);
  104.   
  105.   return 0;
  106. }
  107.  
  108. void closedir(DIR *dir)
  109. {
  110.   iDIR *info = (iDIR *)dir->dd_buf;
  111.   
  112.   chkabort();
  113.   last_dir = 0;
  114.   free_entries(info);
  115.   free(info->dirname);
  116.   if (dir->dd_fd) UnLock(dir->dd_fd);
  117.   free(dir->dd_buf);
  118.   free(dir);
  119. }
  120.  
  121. struct dirent *readdir(DIR *dir)
  122. {
  123.   iDIR *info = (iDIR *)dir->dd_buf;
  124.   struct dirent *entry = 0;
  125.   
  126.   chkabort();
  127.   if (info->seeked)
  128.     {
  129.       long cloc = 0;
  130.       struct idirent *pos;
  131.       
  132.       pos = info->files;
  133.       
  134.       while (cloc < dir->dd_loc && pos)
  135.     {
  136.       cloc++; pos = pos->next;
  137.     }
  138.       /*if (cloc != dir->dd_loc) error ...
  139.     This doesn't seem to be defined very precisely */
  140.       info->pos = pos;
  141.       info->seeked = 0;
  142.     }
  143.   if (info->pos)
  144.     {
  145.       entry = &info->pos->entry;
  146.       
  147.       last_dir = dir;
  148.       last_entry = info->pos;
  149.       
  150.       info->pos = info->pos->next;
  151.       dir->dd_loc++;
  152.     }
  153.   return entry;
  154. }
  155.  
  156. long telldir(DIR *dir)
  157. {
  158.   chkabort();
  159.   return dir->dd_loc;
  160. }
  161.  
  162. void seekdir(DIR *dir, long loc)
  163. {
  164.   iDIR *info = (iDIR *)dir->dd_buf;
  165.   
  166.   chkabort();
  167.   info->seeked = 1;
  168.   dir->dd_loc = loc;
  169. }
  170.  
  171. #if 0
  172. void rewwinddir(DIR *dir)
  173. {
  174.   chkabort();
  175.   gobble_dir(dir);
  176. }
  177. #endif
  178.