Advertisement
Guest User

Untitled

a guest
Apr 22nd, 2017
201
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.24 KB | None | 0 0
  1. /**********************************
  2.  * finder.c
  3.  *
  4.  * CS50 AP
  5.  * Finder
  6.  *
  7.  * Searches for a target string in
  8.  * all files in a directory
  9.  *
  10.  **********************************/
  11.  
  12. #define _BSD_SOURCE
  13. #define _GNU_SOURCE
  14.  
  15. #include <cs50.h>
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <dirent.h>
  20.  
  21. // struct to hold the file name and type
  22. typedef struct
  23. {
  24.     string name;
  25.     string type;
  26. }
  27. path;
  28.  
  29. // struct to hold the directory info
  30. typedef struct
  31. {
  32.     string name;
  33.     int npaths;
  34.     path* paths;
  35. }
  36. directory;
  37.  
  38. // string to hold the word to seek
  39. string key;
  40.  
  41. // the function to search for files in a directory and populate the struct
  42. directory populate(directory dir);
  43.  
  44. // the function to recursively iterate through directories and handle files
  45. int seek(directory dir);
  46.  
  47. // main - sets arguments and calls the seek function
  48. int main(int argc, char* argv[])
  49. {
  50.     // create initial directory
  51.     directory dir;
  52.    
  53.     // Ensure propper amount of command line arguments
  54.     // Set "dir"s name based on command line arguments entered
  55.     if (argc == 2)
  56.     {
  57.         dir.name = "./";
  58.     }
  59.     else if (argc == 3)
  60.     {
  61.         if (argv[2][(strlen(argv[2])-1)] == '/')
  62.         {
  63.             dir.name = argv[2];
  64.         }
  65.         else
  66.         {
  67.             printf("Error: Directory does not end with '/' \n");
  68.             return 2;
  69.         }
  70.     }
  71.     else
  72.     {
  73.         printf("Usage: ./<program> <search term> [directory]\n");
  74.         return 1;
  75.     }
  76.    
  77.     // assign search term to key.
  78.     key = argv[1];
  79.  
  80.     // call the seek function to search files for key
  81.     return seek(dir);
  82. }
  83.  
  84. // for a given directory, searches for files and fills array in the struct
  85. directory populate(directory dir)
  86. {
  87.     // initialize all pointers and values in the given struct
  88.     dir.npaths = 0;
  89.     dir.paths = NULL;
  90.     DIR* dirp;
  91.     struct dirent* entry;
  92.    
  93.     // opendir is a system call that opens a "directory stream" containing
  94.     // information about all files in the given directory (represented here
  95.     // by dir.name)
  96.     dirp = opendir(dir.name);
  97.     if (dirp == NULL)
  98.     {
  99.         printf("Opening directory failed. Check your input filepath!\n");
  100.         return dir;
  101.     }
  102.    
  103.     // while directory stream still contains files, seek through them
  104.     while((entry = readdir(dirp)) != NULL)
  105.     {
  106.         // if entry is a directory and not '.' or '..',
  107.         // increase file count and populate the struct
  108.         if (entry->d_type == DT_DIR && strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0)
  109.         {
  110.             // allocate zeroed-out memory for the construction of the file name
  111.             string name = calloc(1, strlen(dir.name) + strlen(entry->d_name) + 2);
  112.             strcat(name, dir.name);
  113.             strcat(name, entry->d_name);
  114.             strcat(name, "/");
  115.            
  116.             // reallocate memory to expand the array
  117.             dir.paths = realloc(dir.paths, (dir.npaths + 1) * sizeof(path));
  118.            
  119.             // add a new element to the array containing names and types
  120.             path newPath = {.name = name, .type = "directory"};
  121.             dir.paths[dir.npaths] = newPath;
  122.            
  123.             // increase file count for the directory
  124.             dir.npaths++;
  125.         }
  126.        
  127.         // else if entry is a file, increase file count and populate the struct
  128.         else if (entry->d_type == DT_REG)
  129.         {
  130.             // allocate zeroed-out memory for the construction of the file name
  131.             string name = calloc(1, strlen(dir.name) + strlen(entry->d_name) + 1);
  132.             strcat(name, dir.name);
  133.             strcat(name, entry->d_name);
  134.            
  135.             // reallocate memory to expand the array
  136.             dir.paths = realloc(dir.paths, (dir.npaths + 1) * sizeof(path));
  137.            
  138.             // add a new element to the array containing names and types
  139.             path newPath = {.name = name, .type = "file"};
  140.             dir.paths[dir.npaths] = newPath;
  141.            
  142.             // increase file count for the directory
  143.             dir.npaths++;
  144.         }
  145.     }
  146.    
  147.     // close directory stream using system call closedir and return struct
  148.     closedir(dirp);
  149.     return dir;
  150.    
  151. }
  152.  
  153. // recursive function to iterate through directories and search files
  154. int seek(directory dir)
  155. {
  156.     // Segmentation fault cause is in here. Probably due to recursion.
  157.     populate(dir);
  158.    
  159.     printf("Sanity Check. Should = 0\n");
  160.     printf("%i\n", strncmp(dir.paths[dir.npaths].type, "file", 4));
  161.    
  162.     // Check file type
  163.     if (strncmp(dir.paths[dir.npaths].type, "file", 4) == 0)
  164.     {
  165.         // Open current file.
  166.         FILE* fp = fopen(dir.paths[dir.npaths].name, "r");
  167.         if (fp == NULL)
  168.         {
  169.             printf("Critical Failure. No file found.\n");
  170.             return 4;
  171.         }
  172.        
  173.         printf("Sanity Check2\n");
  174.         int i = 2;
  175.         do
  176.         {
  177.             // Checks string by string for key in opened file.
  178.             char str[50];
  179.             fgets(str, 50, fp);
  180.             if (strstr(str, key) != NULL)
  181.             {
  182.                 printf("Sanity Check3\n");
  183.                 // If key is found, open new file and write file name where key was found.
  184.                 FILE* fr = fopen("found.txt", "a");
  185.                 if (fr != NULL)
  186.                 {
  187.                     fprintf(fr, "%s", dir.paths[dir.npaths].name);
  188.                 }
  189.                 fclose(fr);
  190.                 break;
  191.             }
  192.            
  193.             // Notify user if key wasn't found.
  194.             if (strstr(str,key) == NULL)
  195.             {
  196.                 printf("Nothing found.\n");
  197.                 break;
  198.             }
  199.             fgets(str, 50, fp);
  200.             i--;
  201.         }
  202.         while (i != 0); // Just needed termination
  203.         fclose(fp);
  204.     }
  205.    
  206.     // If type equals directory call self recursively.
  207.     if (strncmp(dir.paths[dir.npaths].type, "directory", 9) == 0)
  208.     {
  209.         directory changing_name;// recursive needs to create a new struct each time.
  210.         seek(changing_name);
  211.     }
  212.     else
  213.     {
  214.         printf("Unknown type.\n");
  215.         return 3;
  216.     }
  217.    
  218.     return 0;
  219. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement