home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume11 / mtools / part02 / subdir.c < prev    next >
C/C++ Source or Header  |  1987-08-27  |  4KB  |  179 lines

  1. /*
  2.  * subdir(), getdir(), get_chain(), reset_dir()
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include "msdos.h"
  7.  
  8. extern int dir_chain[25], dir_start, dir_len, dir_entries, clus_size;
  9. extern char *mcwd;
  10. static char *lastpath;
  11.  
  12. /*
  13.  * Parse the path names of a sub directory.  Both '/' and '\' are
  14.  * valid separators.  However, the use of '\' will force the operator
  15.  * to use quotes in the command line to protect '\' from the shell.
  16.  * Returns 1 on error.  Attempts to optimize by remembering the last
  17.  * path it parsed
  18.  */
  19.  
  20. subdir(name)
  21. char *name;
  22. {
  23.     char *s, *tmp, *path, *malloc(), *strchr(), *strcpy(), *strcat();
  24.     static int code;
  25.     int getdir();
  26.                     /* if full pathname */
  27.     if (*name == '/' || *name == '\\') {
  28.         tmp = malloc(strlen(name)+1);
  29.         strcpy(tmp, name);
  30.     }
  31.                     /* if relative to MCWD */
  32.     else {
  33.         if (!strlen(name)) {
  34.             tmp = malloc(strlen(mcwd)+1);
  35.             strcpy(tmp, mcwd);
  36.         }
  37.         else {
  38.             tmp = malloc(strlen(mcwd)+1+strlen(name)+1);
  39.             strcpy(tmp, mcwd);
  40.             strcat(tmp, "/");
  41.             strcat(tmp, name);
  42.         }
  43.     }
  44.                     /* if paths are same, do nothing */
  45.     if (!strcmp(tmp, lastpath))
  46.         return(0);
  47.                     /* not recursive, start at root */
  48.     reset_dir();
  49.     lastpath = malloc(strlen(tmp)+1);
  50.     strcpy(lastpath, tmp);
  51.                     /* zap the leading separator */
  52.     if (*tmp == '\\' || *tmp == '/')
  53.         tmp++;
  54.     for (s = tmp; *s; ++s) {
  55.         if (*s == '\\' || *s == '/') {
  56.             path = tmp;
  57.             *s = NULL;
  58.             if (getdir(path))
  59.                 return(1);
  60.             tmp = s+1;
  61.         }
  62.     }
  63.     code = getdir(tmp);
  64.     return(code);
  65. }
  66.  
  67. /*
  68.  * Find the directory and get the starting cluster.  A null directory
  69.  * is ok.  Returns a 1 on error.
  70.  */
  71.  
  72. int
  73. getdir(path)
  74. char *path;
  75. {
  76.     int entry, start, get_chain();
  77.     char *newname, *unixname(), *strncpy(), name[9], ext[4];
  78.     struct directory *dir, *search();
  79.  
  80.                     /* nothing required */
  81.     if (*path == NULL)
  82.         return(0);
  83.  
  84.     for (entry=0; entry<dir_entries; entry++) {
  85.         dir = search(entry);
  86.                     /* if empty */
  87.         if (dir->name[0] == NULL)
  88.             break;
  89.                     /* if erased */
  90.         if (dir->name[0] == 0xe5)
  91.             continue;
  92.                     /* skip if not a directory */
  93.         if (!(dir->attr & 0x10))
  94.             continue;
  95.         strncpy(name, dir->name, 8);
  96.         name[8] = NULL;
  97.         strncpy(ext, dir->ext, 3);
  98.         ext[3] = NULL;
  99.         newname = unixname(name, ext);
  100.         if (!strcmp(newname, path)) {
  101.             start = dir->start[1]*0x100 + dir->start[0];
  102.                     /* if '..' pointing to root */
  103.             if (!start && !strcmp(path, "..")) {
  104.                 reset_dir();
  105.                 return(0);
  106.             }
  107.                     /* fill in the directory chain */
  108.             dir_entries = get_chain(start) * 16;
  109.             return(0);
  110.         }
  111.     }
  112.                     /* if '.' or '..', must be root */
  113.     if (!strcmp(path, ".") || !strcmp(path, "..")) {
  114.         reset_dir();
  115.         return(0);
  116.     }
  117.     fprintf(stderr, "Path component '%s' is not a directory\n", path);
  118.     return(1);
  119. }
  120.  
  121. /*
  122.  * Fill in the global variable dir_chain.  Argument is the starting
  123.  * cluster number.  Info, in this variable is used by search() to 
  124.  * scan a directory.  An arbitrary limit of 25 sectors is placed, this
  125.  * equates to 400 entries.  Returns the number of sectors in the chain.
  126.  */
  127.  
  128. int
  129. get_chain(num)                /* fill the directory chain */
  130. int num;
  131. {
  132.     int next;
  133.     static int i;
  134.     void exit();
  135.  
  136.     i = 0;
  137.     while (1) {
  138.         dir_chain[i] = (num - 2)*clus_size + dir_start + dir_len;
  139.                     /* sectors, not clusters! */
  140.         if (clus_size == 2) {
  141.             dir_chain[i+1] = dir_chain[i] + 1;
  142.             i++;
  143.         }
  144.         i++;
  145.         if (i >= 25) {
  146.             fprintf(stderr, "get_chain: directory too large\n");
  147.             exit(1);
  148.         }
  149.                     /* get next cluster number */
  150.         next = getfat(num);
  151.         if (next == -1) {
  152.             fprintf(stderr, "get_chain: FAT problem\n");
  153.             exit(1);
  154.         }
  155.                     /* end of cluster chain */
  156.         if (next >= 0xff8) {
  157.             break;
  158.         }
  159.         num = next;
  160.     }
  161.     return(i);
  162. }
  163.  
  164. /* 
  165.  * Reset the global variable dir_chain to the root directory.
  166.  */
  167.  
  168. reset_dir()
  169. {
  170.     int i;
  171.  
  172.     for (i=0; i<dir_len; i++)
  173.         dir_chain[i] = dir_start + i;
  174.     dir_entries = dir_len * 16;
  175.                     /* disable subdir() optimization */
  176.     lastpath = "\0";
  177.     return;
  178. }
  179.