home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume18 / undel / part04 / pattern.c < prev   
Encoding:
C/C++ Source or Header  |  1989-05-06  |  11.8 KB  |  525 lines

  1. /*
  2.  * $Source: /mit/jik/src/delete/RCS/pattern.c,v $
  3.  * $Author: jik $
  4.  *
  5.  * This program is part of a package including delete, undelete,
  6.  * lsdel, expunge and purge.  The software suite is meant as a
  7.  * replacement for rm which allows for file recovery.
  8.  * 
  9.  * Copyright (c) 1989 by the Massachusetts Institute of Technology.
  10.  * For copying and distribution information, see the file "mit-copyright.h."
  11.  */
  12.  
  13. #if (!defined(lint) && !defined(SABER))
  14.      static char rcsid_pattern_c[] = "$Header: pattern.c,v 1.8 89/03/27 12:07:48 jik Exp $";
  15. #endif
  16.  
  17. #include <stdio.h>
  18. #include <sys/types.h>
  19. #include <sys/dir.h>
  20. #include <sys/param.h>
  21. #include <strings.h>
  22. #include <sys/stat.h>
  23. #include "directories.h"
  24. #include "pattern.h"
  25. #include "util.h"
  26. #include "undelete.h"
  27. #include "mit-copyright.h"
  28.  
  29. static char *add_char();
  30.  
  31. extern char *malloc(), *realloc();
  32.  
  33. extern char *whoami, *error_buf;
  34.  
  35. /*
  36.  * parse_pattern returns an area of memory allocated by malloc when it
  37.  * is successful.  Therefore, other procedures calling parse_pattern
  38.  * should use free() to free the region of memory when they are done
  39.  * with it.
  40.  */
  41. char *parse_pattern(file_pattern)
  42. char *file_pattern;
  43. {
  44.      char *re_pattern, *cur_ptr, *re_ptr;
  45.      int guess_length;
  46.      
  47.      guess_length = strlen(file_pattern) + 5;
  48.      re_ptr = re_pattern = malloc(guess_length);
  49.      if (! re_ptr) {
  50.       perror(sprintf(error_buf, "%s: parse_pattern", whoami));
  51.       exit(1);
  52.      }
  53.      
  54.      for (cur_ptr = file_pattern, re_ptr = re_pattern; *cur_ptr != NULL;
  55.       cur_ptr++) {
  56.       if (*cur_ptr == '\\') {
  57.            if (! cur_ptr[1]) {
  58.             fprintf(stderr,
  59.                 "%s: parse_pattern: incomplete expression\n",
  60.                 whoami);
  61.             return((char *) NULL);
  62.            }
  63.            if (! add_char(&re_pattern, &re_ptr, &guess_length, '\\'))
  64.             return ((char *) NULL);
  65.            cur_ptr++;
  66.            if (! add_char(&re_pattern, &re_ptr, &guess_length, *cur_ptr))
  67.             return ((char *) NULL);
  68.            continue;
  69.       }
  70.       else if (*cur_ptr == '*') {
  71.            if (! add_char(&re_pattern, &re_ptr, &guess_length, '.'))
  72.             return ((char *) NULL);
  73.            if (! add_char(&re_pattern, &re_ptr, &guess_length, '*'))
  74.             return ((char *) NULL);
  75.            continue;
  76.       }
  77.       else if (*cur_ptr == '?') {
  78.            if (! add_char(&re_pattern, &re_ptr, &guess_length, '.'))
  79.             return ((char *) NULL);
  80.            continue;
  81.       }
  82.       else if (*cur_ptr == '.') {
  83.            if (! add_char(&re_pattern, &re_ptr, &guess_length, '\\'))
  84.             return ((char *) NULL);
  85.            if (! add_char(&re_pattern, &re_ptr, &guess_length, '.'))
  86.             return ((char *) NULL);
  87.       }
  88.       else {
  89.            if (! add_char(&re_pattern, &re_ptr, &guess_length, *cur_ptr))
  90.             return ((char *) NULL);
  91.       }
  92.      }
  93.      if (! add_char(&re_pattern, &re_ptr, &guess_length, '\0'))
  94.       return ((char *) NULL);
  95.      return (re_pattern);
  96. }
  97.  
  98.  
  99.  
  100.  
  101.  
  102.  
  103. /*
  104.  * add_char() takes two char **, a length which is the current amount
  105.  * of space implemented for the string pointed to by the first *(char **),
  106.  * and a character to add to the string.  It reallocs extra space if
  107.  * necessary, adds the character, and messes with the pointers if necessary.
  108.  */
  109. static char *add_char(start, finish, length, chr)
  110. char **start, **finish;
  111. int *length;
  112. char chr;
  113. {
  114.      if (*finish - *start == *length) {
  115.       *start = realloc(*start, *length + 5);
  116.       if (! *start) {
  117.            perror(sprintf(error_buf, "%s: add_char", whoami));
  118.            exit(1);
  119.       }
  120.       *finish = *start + *length - 1;
  121.       *length += 5;
  122.      }
  123.      **finish = chr;
  124.      (*finish)++;
  125.      return(*start);
  126. }
  127.  
  128.       
  129.  
  130.  
  131.  
  132.  
  133. /*
  134.  * add_arrays() takes pointers to two arrays of char **'s and their
  135.  * lengths, merges the two into the first by realloc'ing the first and
  136.  * then free's the second's memory usage.
  137.  */  
  138. add_arrays(array1, num1, array2, num2)
  139. char ***array1, ***array2;
  140. int *num1, *num2;
  141. {
  142.      int counter;
  143.      
  144.      *array1 = (char **) realloc(*array1, sizeof(char *) * (*num1 + *num2));
  145.      if (! *array1) {
  146.       perror(sprintf(error_buf, "%s: add_arrays", whoami));
  147.       exit(1);
  148.      }
  149.      for (counter = *num1; counter < *num1 + *num2; counter++)
  150.       *(*array1 + counter) = *(*array2 + counter - *num1);
  151.      free (*array2);
  152.      *num1 += *num2;
  153.      return(0);
  154. }
  155.  
  156.  
  157.  
  158.  
  159.  
  160.  
  161.  
  162. char **add_str(strs, num, str)
  163. char **strs;
  164. int num;
  165. char *str;
  166. {
  167.      strs = (char **) realloc(strs, sizeof(char *) * (num + 1));
  168.      if (! strs) {
  169.       perror(sprintf(error_buf, "%s: add_str", whoami));
  170.       exit(1);
  171.      }
  172.      strs[num] = malloc(strlen(str) + 1);
  173.      if (! strs[num]) {
  174.       perror(sprintf(error_buf, "%s: add_str", whoami));
  175.       exit(1);
  176.      }
  177.      strcpy(strs[num], str);
  178.      return(strs);
  179. }
  180.  
  181.  
  182.  
  183.  
  184.  
  185.  
  186.  
  187. char **find_deleted_matches(base, expression, num_found)
  188. char *base, *expression;
  189. int *num_found;
  190. {
  191.      struct direct *dp;
  192.      DIR *dirp;
  193.      char **found;
  194.      int num;
  195.      char **next;
  196.      int num_next;
  197.      char first[MAXNAMLEN], rest[MAXPATHLEN];
  198.      char new[MAXPATHLEN];
  199.  
  200. #ifdef DEBUG
  201.      printf("Looking for %s in %s\n", expression, base);
  202. #endif
  203.      found = (char **) malloc(0);
  204.      *num_found = num = 0;
  205.  
  206.      dirp = opendir(base);
  207.      if (! dirp)
  208.       return(found);
  209.  
  210.      readdir(dirp); readdir(dirp); /* get rid of . and .. */
  211.      
  212.      strcpy(first, reg_firstpart(expression, rest));
  213.      re_comp(first);
  214.  
  215.      for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
  216.       if (re_exec(dp->d_name) && *rest) {
  217.            strcpy(new, append(base, dp->d_name));
  218.            next = find_deleted_matches(new, rest, &num_next);
  219.            add_arrays(&found, &num, &next, &num_next);
  220.       }
  221.       else if (is_deleted(dp->d_name)) if (re_exec(&dp->d_name[2])) {
  222.            if (*rest) {
  223.             strcpy(new, append(base, dp->d_name));
  224.             next = find_deleted_matches(new, rest, &num_next);
  225.             add_arrays(&found, &num, &next, &num_next);
  226.            }
  227.            else {
  228.             found = add_str(found, num, append(base, dp->d_name));
  229.             num++;
  230.            }
  231.       }
  232.      }
  233.      closedir(dirp);
  234.      *num_found = num;
  235.      return(found);
  236. }
  237.  
  238.  
  239.  
  240.  
  241.  
  242. char **find_matches(base, expression, num_found)
  243. char *base, *expression;
  244. int *num_found;
  245. {
  246.      struct direct *dp;
  247.      DIR *dirp;
  248.      char **found;
  249.      int num;
  250.      char **next;
  251.      int num_next;
  252.      char first[MAXNAMLEN], rest[MAXPATHLEN];
  253.      char new[MAXPATHLEN];
  254.      
  255. #ifdef DEBUG
  256.      printf("Looking for %s in %s\n", expression, base);
  257. #endif
  258.      found = (char **) malloc(0);
  259.      *num_found = num = 0;
  260.  
  261.      dirp = opendir(base);
  262.      if (! dirp)
  263.       return(found);
  264.  
  265.      strcpy(first, reg_firstpart(expression, rest));
  266.  
  267.      for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
  268.       re_comp(first);
  269.       if (re_exec(dp->d_name)) {
  270.            if (*rest) {
  271.             strcpy(new, append(base, dp->d_name));
  272.             next = find_matches(new, rest, &num_next);
  273.             add_arrays(&found, &num, &next, &num_next);
  274.            }
  275.            else {
  276.             found = add_str(found, num, append(base, dp->d_name));
  277.             num++;
  278.            }
  279.       }
  280.       else if (is_deleted(dp->d_name)) if (re_exec(&dp->d_name[2])) {
  281.            if (*rest) {
  282.             strcpy(new, append(base, dp->d_name));
  283.             next = find_matches(new, rest, &num_next);
  284.             add_arrays(&found, &num, &next, &num_next);
  285.            }
  286.            else {
  287.             found = add_str(found, num, append(base, dp->d_name));
  288.             num++;
  289.            }
  290.       }
  291.      }
  292.      closedir(dirp);
  293.      *num_found = num;
  294.      return(found);
  295. }
  296.  
  297.  
  298.  
  299.  
  300.  
  301.  
  302.  
  303. char **find_recurses(base, num_found)
  304. char *base;
  305. int *num_found;
  306. {
  307.      DIR *dirp;
  308.      struct direct *dp;
  309.      char newname[MAXPATHLEN];
  310.      char **found, **new_found;
  311.      int found_num, new_found_num;
  312.      struct stat stat_buf;
  313.      
  314. #ifdef DEBUG
  315.      printf("Looking for subs of %s\n", base);
  316. #endif
  317.      found = (char **) malloc(0);
  318.      *num_found = found_num = 0;
  319.      
  320.      dirp = opendir(base);
  321.      if (! dirp)
  322.       return(found);
  323.  
  324.      readdir(dirp); readdir(dirp); /* get rid of . and .. */
  325.  
  326.      for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
  327.       strcpy(newname, append(base, dp->d_name));
  328.       found = add_str(found, found_num, newname);
  329.       found_num++;
  330.       if (lstat(newname, &stat_buf))
  331.            continue;
  332.       if ((stat_buf.st_mode & S_IFMT) == S_IFDIR) {
  333.            new_found = find_recurses(newname, &new_found_num);
  334.            add_arrays(&found, &found_num, &new_found, &new_found_num);
  335.       }
  336.      }
  337.      closedir(dirp);
  338.      *num_found = found_num;
  339.      return(found);
  340. }
  341.  
  342.  
  343.  
  344.  
  345.  
  346.  
  347. char **find_deleted_recurses(base, num_found)
  348. char *base;
  349. int *num_found;
  350. {
  351.      DIR *dirp;
  352.      struct direct *dp;
  353.      char newname[MAXPATHLEN];
  354.      char **found, **new_found;
  355.      int found_num, new_found_num;
  356.      struct stat stat_buf;
  357.      
  358.      found = (char **) malloc(0);
  359.      *num_found = found_num = 0;
  360.      
  361.      dirp = opendir(base);
  362.      if (! dirp)
  363.       return(found);
  364.  
  365.      readdir(dirp); readdir(dirp); /* get rid of . and .. */
  366.  
  367.      for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
  368.       strcpy(newname, append(base, dp->d_name));
  369.       
  370.       if (is_deleted(dp->d_name)) {
  371.            found = add_str(found, found_num, newname);
  372.            found_num++;
  373.       }
  374.       if (lstat(newname, &stat_buf)) {
  375.            continue;
  376.       }
  377.       if ((stat_buf.st_mode & S_IFMT) == S_IFDIR) {
  378.            new_found = find_deleted_recurses(newname, &new_found_num);
  379.            add_arrays(&found, &found_num, &new_found, &new_found_num);
  380.       }
  381.      }
  382.      closedir(dirp);
  383.      *num_found = found_num;
  384.      return(found);
  385. }
  386.  
  387.  
  388.  
  389.  
  390.  
  391.  
  392. char **find_contents(base, num_found)
  393. char *base;
  394. int *num_found;
  395. {
  396.      DIR *dirp;
  397.      struct direct *dp;
  398.      char **found;
  399.      int num;
  400.  
  401. #ifdef DEBUG
  402.      printf("Looking for contents of %s\n", base);
  403. #endif
  404.      found = (char **) malloc(0);
  405.      *num_found = num = 0;
  406.    
  407.      dirp = opendir(base);
  408.      if (! dirp)
  409.       return(found);
  410.  
  411.      readdir(dirp); readdir(dirp); /* get rid of . and .. */
  412.  
  413.      for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
  414.       found = add_str(found, num, append(base, dp->d_name));
  415.       num += 1;
  416.      }
  417.      closedir(dirp);
  418.      *num_found = num;
  419.      return(found);
  420. }
  421.  
  422.  
  423.      
  424. char **find_deleted_contents(base, num_found)
  425. char *base;
  426. int *num_found;
  427. {
  428.      DIR *dirp;
  429.      struct direct *dp;
  430.      char **found;
  431.      int num;
  432.  
  433. #ifdef DEBUG
  434.      printf("Looking for deleted contents of %s\n", base);
  435. #endif
  436.      found = (char **) malloc(0);
  437.      *num_found = num = 0;
  438.    
  439.      dirp = opendir(base);
  440.      if (! dirp)
  441.       return(found);
  442.  
  443.      readdir(dirp); readdir(dirp); /* get rid of . and .. */
  444.  
  445.      for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
  446.       if (is_deleted(dp->d_name)) {
  447.            found = add_str(found, num, append(base, dp->d_name));
  448.            num += 1;
  449.       }
  450.      }
  451.      closedir(dirp);
  452.      *num_found = num;
  453.      return(found);
  454. }
  455.  
  456.  
  457.  
  458.  
  459. char **find_deleted_contents_recurs(base, num_found)
  460. char *base;
  461. int *num_found;
  462. {
  463.      DIR *dirp;
  464.      struct direct *dp;
  465.      char **found;
  466.      int num;
  467.      struct stat stat_buf;
  468.      char newname[MAXPATHLEN];
  469.      char **new_found;
  470.      int new_found_num;
  471.      
  472. #ifdef DEBUG
  473.      printf("Looking for recursive deleted contents of %s\n", base);
  474. #endif
  475.      found = (char **) malloc(0);
  476.      *num_found = num = 0;
  477.    
  478.      dirp = opendir(base);
  479.      if (! dirp)
  480.       return(found);
  481.  
  482.      readdir(dirp); readdir(dirp); /* get rid of . and .. */
  483.  
  484.      for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
  485.       if (is_deleted(dp->d_name)) {
  486.            strcpy(newname, append(base, dp->d_name));
  487.            found = add_str(found, num, newname);
  488.            num += 1;
  489.            if (lstat(newname, &stat_buf))
  490.             continue;
  491.            if ((stat_buf.st_mode & S_IFMT) == S_IFDIR) {
  492.             new_found = find_recurses(newname, &new_found_num);
  493.             add_arrays(&found, &num, &new_found, &new_found_num);
  494.            }
  495.       }
  496.      }
  497.      closedir(dirp);
  498.      *num_found = num;
  499.      return(found);
  500. }
  501.      
  502.  
  503.  
  504. /*
  505.  * returns true if the filename has no regular expression wildcards in
  506.  * it.  That means no non-quoted dots or asterisks.  Assumes a
  507.  * null-terminated string, and a valid regular expression.
  508.  */
  509. int no_wildcards(name)
  510. char *name;
  511. {
  512.      do {
  513.       switch (*name) {
  514.       case '\\':
  515.            name++;
  516.            break;
  517.       case '.':
  518.            return(0);
  519.       case '*':
  520.            return(0);
  521.       }
  522.      } while (*++name);
  523.      return(1);
  524. }
  525.