home *** CD-ROM | disk | FTP | other *** search
/ PC Extra Super CD 1998 January / PCPLUS131.iso / DJGPP / V2 / DJLSR201.ZIP / src / libc / dos / dir / ftreewlk.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-31  |  3.9 KB  |  166 lines

  1. /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  2. /*
  3.  * Recursively descent the directory hierarchy rooted in DIR,
  4.  * calling FUNC for each object in the hierarchy.  We cannot
  5.  * use ftw(), because it uses some non-ANSI functions which
  6.  * will pollute ANSI namespace, while we need this function
  7.  * in some ANSI functions (e.g., rename()).  Thus, this function
  8.  * is closely modeled on ftw(), but uses DOS directory search
  9.  * functions and structures instead of opendir()/readdir()/stat().
  10.  *
  11.  * Copyright (c) 1995, 1996 Eli Zaretskii <eliz@is.elta.co.il>
  12.  *
  13.  * This software may be used freely as long as this copyright notice is
  14.  * left intact.  There is no warranty on this software.
  15.  *
  16.  */
  17.  
  18. #include <libc/stubs.h>
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include <errno.h>
  22. #include <ctype.h>
  23. #include <dir.h>
  24.  
  25. #define FA_ALL  (FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_LABEL|FA_DIREC|FA_ARCH)
  26.  
  27. int
  28. __file_tree_walk(const char *dir,
  29.                int (*func)(const char *, const struct ffblk *))
  30. {
  31.   struct ffblk  ff;
  32.   unsigned char searchspec[FILENAME_MAX];
  33.   unsigned char found[FILENAME_MAX], *dir_end;
  34.   int e = errno;
  35.  
  36.   if (dir == 0 || func == 0)
  37.     {
  38.       errno = EFAULT;
  39.       return -1;
  40.     }
  41.  
  42.   if (*dir == '\0')
  43.     {
  44.       errno = ENOENT;
  45.       return -1;
  46.     }
  47.  
  48.   /* Construct the search spec for findfirst().  Treat ``d:'' as ``d:.''.  */
  49.   strcpy(searchspec, dir);
  50.   dir_end = searchspec + strlen(searchspec) - 1;
  51.   if (*dir_end == ':')
  52.     {
  53.       *++dir_end = '.';
  54.       *++dir_end = '\0';
  55.     }
  56.   else if (*dir_end == '/' || *dir_end == '\\')
  57.     *dir_end   = '\0';
  58.   else
  59.     ++dir_end;
  60.   strcpy(dir_end, "/*.*");
  61.  
  62.   /* Prepare the buffer where the full pathname of the found files
  63.      will be placed.  */
  64.   strcpy(found, dir);
  65.   dir_end = found + strlen(found) - 1;
  66.   if (*dir_end == ':')
  67.     {
  68.       *++dir_end = '.';
  69.       dir_end[1] = '\0';
  70.     }
  71.   if (*dir_end != '/' && *dir_end != '\\')
  72.     {
  73.       /* Try to preserve user's forward/backward slash style.  */
  74.       *++dir_end = strchr(found, '\\') == 0 ? '/': '\\';
  75.       *++dir_end   = '\0';
  76.     }
  77.   else
  78.     ++dir_end;
  79.  
  80.   if (findfirst(searchspec, &ff, FA_ALL))
  81.     return -1;
  82.  
  83.   do
  84.     {
  85.       int func_result;
  86.  
  87.       /* Skip `.' and `..' entries.  */
  88.       if (ff.ff_name[0] == '.' &&
  89.           (ff.ff_name[1] == '\0' || ff.ff_name[1] == '.'))
  90.         continue;
  91.  
  92.       /* Construct full pathname in FOUND[].  */
  93.       strcpy(dir_end, ff.ff_name);
  94.  
  95.       /* Invoke FUNC() on this file.  */
  96.       if ((func_result = (*func)(found, &ff)) != 0)
  97.         return func_result;
  98.  
  99.       /* If this is a directory, walk its siblings.  */
  100.       if (ff.ff_attrib & 0x10)
  101.         {
  102.           int subwalk_result;
  103.  
  104.           if ((subwalk_result = __file_tree_walk(found, func)) != 0)
  105.             return subwalk_result;
  106.         }
  107.     } while (findnext(&ff) == 0);
  108.  
  109.   if (errno == ENMFILE)     /* normal case: tree exhausted */
  110.     {
  111.       errno = e;    /* restore errno from previous syscall */
  112.       return 0;
  113.     }
  114.  
  115.   return -1;                /* error; errno set by findnext() */
  116. }
  117.  
  118. #ifdef  TEST
  119.  
  120. #include <stdlib.h>
  121.  
  122. int
  123. ff_walker(const char *path, const struct ffblk *ff)
  124. {
  125.   printf("%s:\t%lu\t", path, ff->ff_fsize);
  126.   if (ff->ff_attrib & 1)
  127.     printf("R");
  128.   if (ff->ff_attrib & 2)
  129.     printf("H");
  130.   if (ff->ff_attrib & 4)
  131.     printf("S");
  132.   if (ff->ff_attrib & 8)
  133.     printf("V");
  134.   if (ff->ff_attrib & 0x10)
  135.     printf("D");
  136.   if (ff->ff_attrib & 0x20)
  137.     printf("A");
  138.   printf("\n");
  139.  
  140.   if (strcmp(ff->ff_name, "XXXXX") == 0)
  141.     return 8;
  142.   return 0;
  143. }
  144.  
  145. int
  146. main(int argc, char *argv[])
  147. {
  148.   if (argc > 1)
  149.     {
  150.       char msg[80];
  151.  
  152.       sprintf(msg, "file_tree_walk: %d",
  153.                    file_tree_walk(argv[1], ff_walker));
  154.       if (errno)
  155.         perror(msg);
  156.       else
  157.         puts(msg);
  158.     }
  159.   else
  160.     printf("Usage: %s dir\n", argv[0]);
  161.  
  162.   return 0;
  163. }
  164.  
  165. #endif
  166.