home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Programming / C / SASC6571.LZX / extras / dirwalker / dirwalker.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-12-24  |  2.9 KB  |  133 lines

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <proto/dos.h>
  5. #include <proto/exec.h>
  6. #include <dos.h>
  7.  
  8. #include "dirwalker.h"
  9.  
  10. #define PATHMAX 512
  11.  
  12. struct DWSTATE
  13. {
  14.    char path[PATHMAX+1];
  15.    int  pathmax;
  16.    int  pathcur;
  17.    int (*dirfunc)(char *path, char *name);
  18.    int (*filefunc)(char *path, char *name);
  19. };
  20.  
  21. static int walkdir(BPTR lock, struct DWSTATE *dws);
  22.  
  23. int dirwalker(char *name, 
  24.               int (*dirfunc)(char *path, char *dir), 
  25.               int (*filefunc)(char *path, char *file))
  26. {
  27.    BPTR lock = NULL;
  28.    struct DWSTATE *dws;
  29.    int rc;
  30.    struct FileInfoBlock *fib = NULL;
  31.  
  32.    if(!(dws=AllocMem(sizeof(*dws), 0))) return(-1);
  33.  
  34.    dws->path[0]  = 0;
  35.    dws->pathcur  = 0;
  36.    dws->pathmax  = PATHMAX;
  37.    dws->dirfunc  = dirfunc;
  38.    dws->filefunc = filefunc;
  39.  
  40.    if(name) 
  41.    {
  42.       if(!(fib = AllocMem(sizeof(*fib), 0)) ||
  43.          !(lock = Lock(name, SHARED_LOCK)))
  44.       {
  45.          rc = -1;
  46.          goto cleanup;
  47.       };
  48.       Examine(lock, fib);
  49.       if(fib->fib_DirEntryType <= 0)
  50.       {
  51.          rc = -1;  /* File, not directory */
  52.          goto cleanup;
  53.       }
  54.    }
  55.    else
  56.       CurrentDir(DupLock(lock=CurrentDir(NULL)));
  57.  
  58.    rc = walkdir(lock, dws);
  59.  
  60. cleanup:
  61.    FreeMem(dws, sizeof(*dws));
  62.    if(fib) FreeMem(fib, sizeof(*fib));
  63.    if(lock) UnLock(lock);
  64.    return(rc);
  65. }
  66.  
  67. static int walkdir(BPTR lock, struct DWSTATE *dws)
  68. {
  69.    struct FileInfoBlock *fib;
  70.    BPTR dirlock, odir;
  71.    int i;
  72.    int pathcur = dws->pathcur;
  73.  
  74.    fib = AllocMem(sizeof(struct FileInfoBlock), 0);
  75.    odir = CurrentDir(lock);
  76.  
  77.    if(Examine(lock, fib))
  78.    {
  79.       i = strlen(fib->fib_FileName);
  80.       if(i+1+dws->pathcur < dws->pathmax)
  81.       {
  82.          strcpy(dws->path+dws->pathcur, fib->fib_FileName);
  83.          dws->pathcur += i;
  84.          dws->path[dws->pathcur++] = '/';
  85.          dws->path[dws->pathcur] = 0;
  86.       }
  87.       else
  88.       {
  89.          if(dws->pathcur > PATHMAX-3) dws->pathcur = PATHMAX-3;
  90.          strcpy(dws->path+dws->pathcur, "...");
  91.          dws->pathcur = PATHMAX;
  92.       }
  93.       while(ExNext(lock, fib))
  94.       {
  95.          if(fib->fib_DirEntryType > 0)
  96.          {
  97.             dirlock = Lock(fib->fib_FileName, SHARED_LOCK);
  98.             if(dws->dirfunc && 
  99.                  (*dws->dirfunc)(dws->path, fib->fib_FileName))
  100.             {
  101.                i = -1;
  102.                goto cleanup;
  103.             }
  104.             else
  105.                i = walkdir(dirlock, dws);
  106.             UnLock(dirlock);
  107.             if(i < 0) goto cleanup;
  108.          }
  109.          else if(fib->fib_DirEntryType < 0)
  110.          {
  111.             if(dws->filefunc)
  112.                if((*dws->filefunc)(dws->path, fib->fib_FileName))
  113.                {
  114.                   i = -1;
  115.                   goto cleanup;
  116.                }
  117.          }
  118.       }
  119.    }
  120.    if((i=IoErr()) != ERROR_NO_MORE_ENTRIES && i)
  121.       poserr(dws->path);
  122.    else
  123.       i = 0;
  124.  
  125. cleanup:
  126.    FreeMem(fib, sizeof(struct FileInfoBlock));
  127.    CurrentDir(odir);
  128.    dws->pathcur = pathcur;
  129.    dws->path[dws->pathcur] = 0;
  130.  
  131.    return(i);
  132. }
  133.