2017-01-18 3 views
0

Я пишу программу, которая перемещается по системе каталогов, создает хеш-значения для найденных файлов, а затем, если найдены любые другие файлы с одним и тем же ключом хэша (дублирующиеся файлы), они сгруппированы вместе. Я планирую использовать связанный список, встроенный в другой связанный список. Связанный список верхнего уровня содержит хэш-ключ, а затем узлы, связанные с этим ключом, содержат значения файлов, которые являются дублирующими. В настоящее время я пытаюсь инициализировать список верхнего уровня. Я успешно передаю первое ключевое значение в связанный список, создав headList. Однако после первого прохода и продолжения с обходом значение ключа теряется, и я не уверен, почему. Я отслеживал его с помощью gdb и обнаружил, что значение удаляется где-то, когда я возвращаюсь в функцию searchDirects.Введенное значение связанного списка

Вот мой код:

#define _GNU_SOURCE // for asprintf(), if needed 
    #include <unistd.h> 
    #include <stdio.h> 
    #include <dirent.h> 
    #include <string.h> 
    #include <sys/stat.h> 
    #include <sys/types.h> 
    #include <stdlib.h> 
    #include <openssl/md5.h> 

    //stat -c "%s %n" filename 
    //The above will display filename and size of file 

    //gcc -g -Wall -o file file.c -lssl -lcrypto 
    //the above is needed to link libraries so the encryption will work 

    #define table_size 20 
    #define BUFFER_SIZE 4096 //max path buffer size 
    #define X (37) 

    void directoryCheck(char *fileName, char *dirValue); 

    //This will be the struct that contains the binned hash keys (the rows) 
    struct LinkNode { 
     char pathValue[BUFFER_SIZE]; // this will be used to hold the directory value 
     struct LinkNode *nextNode; 
    }; 

    struct List { 
     struct LinkNode *headNode; // Embedded linked list 
     unsigned char *key; // Hash key value 
     struct List *nextList; 
     //char *value; 
    }*headList; 


    void printAllThatShit(struct List **headList) 
    { 
     struct List *temp; 
     temp = *headList; 

     while(temp != NULL) 
     { 
      printf("Here is the key when sent to print function:\n"); 
      for(int i = 0; i < 16; i++) 
       printf("%02x", temp->key[i]); 
      printf("\n"); 
      temp = temp->nextList; 
     } 

    } 
    //Function to add to List 
    void addToList(unsigned char *key, char* dirValue) 
    { 

     //head is Null, so we will put first key in 
     if(headList == NULL) 
     { 
      printf("Adding to head of list!\n"); 
      headList = malloc(sizeof(struct List)); 
      headList->nextList = NULL; 
      headList->key = key; 
      /*printf("Here is the key: %s\n", headList->key); 
      for(int i = 0; i < 16; i++) 
       printf("%02x", headList->key[i]); 
      printf(" %s\n", dirValue);*/ 

     } 
     else 
     {  
      currentList = headList; 

      if(currentList != 0) 
      { 

       while(currentList->nextList != 0) 
       { 
        if(currentList->key == key) 
        { 
         printf("Found the same key!\n"); 
         return; 
        } 
        currentList = currentList->nextList; 
       } 
       currentList->nextList = malloc(sizeof(struct List)); 
       currentList = currentList->nextList; 
       currentList->key = key; 
       currentList->nextList = NULL; 

      } 
     } 

     printAllThatShit(&headList); //After this initial print  
            //with headList, the key value is junked 

    } 

    void deleteList(struct List **headList) 
    { 
     struct List *current, *next; 
     current = *headList; 

     while(current != NULL) 
     { 
      printf("Here is the current value: %s", current->key); 
      next = current->nextList; 
      free(current); 
      current = next; 
     } 

     *headList = NULL; 
    } 


    void md5Hash(char *path) 
    { 
     unsigned char key[MD5_DIGEST_LENGTH]; //16 bytes for the output 
     struct stat statbuf; 
     FILE *inFile; 
     MD5_CTX mdx; 
     int bytes, i, size;   

     stat(path, &statbuf); 
     size = statbuf.st_size; 

     inFile = fopen(path, "rb"); 

     /*if(size == -1) 
     { 
      fprintf(stderr, "Unable to open %s", File); 
      return; 
     }*/ 


     if(inFile == NULL) 
     { 
      fprintf(stderr, "Unable to open %s", path); 
      return; 
     } 

     unsigned char data[size]; 

     //Initialize the structure 
     MD5_Init(&mdx); 
     //fread read the file byte-by-byte for 1024 bytes, and reads it into 
     //the buffer(data). The function returns how many bytes that were 
     //successfully read. Then, MD5_Update hashes and updates the structure using 
     //the bytes in the data buffer, and goes in 1 byte increments. 
     while((bytes = fread(data, 1, size, inFile)) != 0) 
      MD5_Update(&mdx, data, bytes); 
     MD5_Final(key, &mdx); //Place the final 16 byte output in key 

     for(i = 0; i < MD5_DIGEST_LENGTH; i++) 
      printf("%02x", key[i]); 
     printf(" %s\n", path); 

     fclose(inFile); 

     printf("Here is that file path while in the hashing function: %s\n", path); 
     addToList(key, path); 


    } 


    void newFile(char *fileName, char *dirValue) 
    { 
     printf("Made it to add a new file!\n"); 
     char *appendPath = NULL; 

     asprintf(&appendPath,"%s/%s", dirValue, fileName); 

     printf("Here is that file you are now sending to be Hashed: %s\n", fileName); 

     md5Hash(appendPath); 




    } 




    //CHeck if the argument is a file 
    int is_regular_file(const char *path) 
    { 
     struct stat path_stat; 
     stat(path, &path_stat); 
     return S_ISREG(path_stat.st_mode); 
    } 

    void searchDirects(char *path, int depth) 
    { 
     DIR *dp; // represents directory stream 
     struct dirent *entry; // This is used for traversing directories 
     struct stat statbuf; // this is so you can use the stat() 
     int file; 

     stat(path, &statbuf); 


     dp = opendir(path); 
     if(dp) 
     { 
      while((entry = readdir(dp)) != NULL) 
      { 
       if(entry->d_type == DT_REG) 
       { 
        printf("Found a file in the directory!\n"); 
        newFile(entry->d_name, path); //send the file name and directory to be added 
       } 
       else if(strcmp(".",entry->d_name) == 0 || strcmp("..",entry->d_name) == 0) 
       { 
        printf("Found files with . or ..!\n"); 
        continue; 
       } 
       else 
       { 
        printf("Attempting to check a directory\n"); 
        directoryCheck(entry->d_name, path); 
       } 
       printf("[%s]\n", entry->d_name); 

      } 
      closedir(dp); 
     } 


    } 

    void directoryCheck(char *fileName, char *dirValue) 
    { 
     char *appendPath; 


     asprintf(&appendPath,"%s/%s", dirValue, fileName); 


     searchDirects(appendPath, 1); 


     free(appendPath); 
    } 

    int main(int argc, char * argv[]) 
    { 
     headList = NULL; 
     //headNode = NULL; 
     //struct node* newnode = (struct node*)malloc(20 * sizeof(struct node)); 

     if(argc <= 1) 
     { 
      return 0; 
     } 

     int i = 0; 
     for(i = 1; i < argc; i++) 
     { 
      if(is_regular_file(argv[i])) 
      {  
       printf("Put function to handle file\n"); 
       //getHashKey(argv[i]); 
       md5Hash(argv[i]); 
      }  
      else 
       searchDirects(argv[i], 1); 
     } 


     printAllThatShit(&headList); 
     printf("Going to delete the list now!\n"); 
     deleteList(&headList); 

     printf("Scan of current directory:\n"); 
     printf("Scan of current directory: %s\n", argv[1]); 
     printf("done.\n"); 
     //free(newnode); 
     exit(0); 


    } 

Я знаю, что у меня есть много различных ошибок, и, скорее всего, утечка памяти в данный момент. Тем не менее, я просто пытаюсь понять, почему ключевое значение теряется в ключе headList-> после начального прохода. И, любые последующие проходы, ключ теряется для добавленных узлов. Я думал, что это может быть, потому что я создаю хэш-ключ и передаю его, но затем, когда я запускал gdb, я понял, что ключ потерян, когда я возвращаюсь к while(), ищущему каталоги (как я упоминал выше). Спасибо за любую помощь или прозрение.

ответ

2

Проблема вызвана общей ошибкой. В addToList:

headList->key = key; 

Это создает указатель на буфер key. Однако addToList называется так, в функции md5Hash:

unsigned char key[MD5_DIGEST_LENGTH]; 
addToList(key, path); 

В этом коде key является локальной переменной. Он выходит из области действия, когда функция md5Hash завершается. И поэтому связанный список key поле является недопустимым указателем. Все ставки отключены в этот момент, поскольку доступ к памяти из недопустимого указателя - это неопределенное поведение.

Одно исправление: memcpy ключевое значение в связанном списке.

Определить key как массив вместо указателя.

struct List { 
    struct LinkNode *headNode; // Embedded linked list 
    unsigned char key[MD5_DIGEST_LENGTH]; // Hash key value 
    struct List *nextList; 
    //char *value; 
}*headList; 

addToList В:

// REMOVE THIS LINE: 
// headList->key = key; 

// REPLACE WITH THIS: 
memcpy(headList->key, key, sizeof(headList->key)); 
+0

Спасибо! Вместо этого я использовал strcpy() - в основном потому, что использовал его раньше и лучше понимаю, как это работает. Тем не менее, вы указали, что моя первоначальная проблема на вершине имеет полный смысл. Я сделал ключ массив, как вы предложили, еще раз спасибо! – MuffinMan1042

+0

@ MuffinMan1042 Я настоятельно рекомендую использовать 'strcpy'. Я специально не использовал это. Потому что я думаю, что 'key', заданный функциями библиотеки MD5, является * not * строкой. Использование строковых функций может работать, но является неопределенным поведением и просто ждет выхода из строя. – kaylum

+0

Хорошо, я буду использовать memcpy, как вы предложили. Еще раз спасибо! – MuffinMan1042