Advertisement
techno-

md5.c

Mar 2nd, 2023
120
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.95 KB | None | 0 0
  1. #include <sys/types.h>
  2. #include <sys/stat.h>
  3. #include <fcntl.h>
  4. #include <dirent.h>
  5. #include <stdlib.h>
  6. #include <unistd.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <errno.h>
  10. #include <openssl/evp.h>
  11. #include <threads.h>
  12.  
  13. #include "options.h"
  14. #include "queue.h"
  15.  
  16.  
  17. #define MAX_PATH 1024
  18. #define BLOCK_SIZE (10*1024*1024)
  19. #define MAX_LINE_LENGTH (MAX_PATH * 2)
  20.  
  21.  
  22. struct file_md5 {
  23.     char *file;
  24.     unsigned char *hash;
  25.     unsigned int hash_size;
  26. };
  27.  
  28. struct thread_get_entries_args{
  29.     int id;
  30.     char *dir;
  31.     queue q;
  32. };
  33.  
  34. struct thread_get_entries_info {
  35.     thrd_t id;
  36.     struct thread_get_entries_args * entries_args;
  37.     cnd_t condicion;
  38. };
  39.  
  40.  
  41. void get_entries(char *dir, queue q);
  42.  
  43.  
  44. void print_hash(struct file_md5 *md5) {
  45.     for(int i = 0; i < md5->hash_size; i++) {
  46.         printf("%02hhx", md5->hash[i]);
  47.     }
  48. }
  49.  
  50.  
  51. void read_hash_file(char *file, char *dir, queue q) {
  52.     FILE *fp;
  53.     char line[MAX_LINE_LENGTH];
  54.     char *file_name, *hash;
  55.     int hash_len;
  56.  
  57.     if((fp = fopen(file, "r")) == NULL) {
  58.         printf("Could not open %s : %s\n", file, strerror(errno));
  59.         exit(0);
  60.     }
  61.  
  62.     while(fgets(line, MAX_LINE_LENGTH, fp) != NULL) {
  63.         char *field_break;
  64.         struct file_md5 *md5 = malloc(sizeof(struct file_md5));
  65.  
  66.         if((field_break = strstr(line, ": ")) == NULL) {
  67.             printf("Malformed md5 file\n");
  68.             exit(0);
  69.         }
  70.         *field_break = '\0';
  71.  
  72.         file_name = line;
  73.         hash      = field_break + 2;
  74.         hash_len  = strlen(hash);
  75.  
  76.         md5->file      = malloc(strlen(file_name) + strlen(dir) + 2);
  77.         sprintf(md5->file, "%s/%s", dir, file_name);
  78.         md5->hash      = malloc(hash_len / 2);
  79.         md5->hash_size = hash_len / 2;
  80.  
  81.  
  82.         for(int i = 0; i < hash_len; i+=2)
  83.             sscanf(hash + i, "%02hhx", &md5->hash[i / 2]);
  84.         printf("Se llama a q_insert\n");
  85.         q_insert(q, md5);
  86.     }
  87.  
  88.     fclose(fp);
  89. }
  90.  
  91.  
  92. void sum_file(struct file_md5 *md5) {
  93.     EVP_MD_CTX *mdctx;
  94.     int nbytes;
  95.     FILE *fp;
  96.     char *buf;
  97.  
  98.     if((fp = fopen(md5->file, "r")) == NULL) {
  99.         printf("Could not open %s\n", md5->file);
  100.         return;
  101.     }
  102.  
  103.     buf = malloc(BLOCK_SIZE);
  104.     const EVP_MD *md = EVP_get_digestbyname("md5");
  105.  
  106.     mdctx = EVP_MD_CTX_create();
  107.     EVP_DigestInit_ex(mdctx, md, NULL);
  108.  
  109.     while((nbytes = fread(buf, 1, BLOCK_SIZE, fp)) >0)
  110.         EVP_DigestUpdate(mdctx, buf, nbytes);
  111.  
  112.     md5->hash = malloc(EVP_MAX_MD_SIZE);
  113.     EVP_DigestFinal_ex(mdctx, md5->hash, &md5->hash_size);
  114.  
  115.     EVP_MD_CTX_destroy(mdctx);
  116.     free(buf);
  117.     fclose(fp);
  118. }
  119.  
  120.  
  121. void recurse(char *entry, void *arg) {
  122.     queue q = * (queue *) arg;
  123.     struct stat st;
  124.  
  125.     stat(entry, &st);
  126.  
  127.     if(S_ISDIR(st.st_mode))/////
  128.  
  129.         get_entries(entry, q);
  130. }
  131.  
  132.  
  133. void add_files(char *entry, void *arg) {
  134.     queue q = * (queue *) arg;
  135.     struct stat st;
  136.  
  137.     stat(entry, &st);
  138.  
  139.     if(S_ISREG(st.st_mode)) {
  140.         printf("Se llama a q_insert\n");
  141.         q_insert(q, strdup(entry));
  142.     }
  143. }
  144.  
  145.  
  146. void walk_dir(char *dir, void (*action)(char *entry, void *arg), void *arg) {
  147.     DIR *d;
  148.     struct dirent *ent;
  149.     char full_path[MAX_PATH];
  150.  
  151.     if((d = opendir(dir)) == NULL) {
  152.         printf("Could not open dir %s\n", dir);
  153.         return;
  154.     }
  155.  
  156.     while((ent = readdir(d)) != NULL) {
  157.         if(strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") ==0)
  158.             continue;
  159.  
  160.         snprintf(full_path, MAX_PATH, "%s/%s", dir, ent->d_name);
  161.  
  162.         action(full_path, arg);
  163.     }
  164.  
  165.     closedir(d);
  166. }
  167.  
  168.  
  169. void get_entries(char *dir, queue q) {
  170.     walk_dir(dir, add_files, &q);
  171.     walk_dir(dir, recurse, &q);
  172. }
  173.  
  174.  
  175. void check(struct options opt) {
  176.     queue in_q;
  177.     struct file_md5 *md5_in, md5_file;
  178.  
  179.     in_q  = q_create(opt.queue_size);
  180.  
  181.     read_hash_file(opt.file, opt.dir, in_q);
  182.  
  183.     while((md5_in = q_remove(in_q))) {
  184.         printf("Se llama a q_remove\n");
  185.         md5_file.file = md5_in->file;
  186.  
  187.         sum_file(&md5_file);
  188.  
  189.         if(memcmp(md5_file.hash, md5_in->hash, md5_file.hash_size)!=0) {
  190.             printf("File %s doesn't match.\nFound:    ", md5_file.file);
  191.             print_hash(&md5_file);
  192.             printf("\nExpected: ");
  193.             print_hash(md5_in);
  194.             printf("\n");
  195.         }
  196.  
  197.         free(md5_file.hash);
  198.  
  199.         free(md5_in->file);
  200.         free(md5_in->hash);
  201.         free(md5_in);
  202.     }
  203.  
  204.     q_destroy(in_q);
  205. }
  206.  
  207. int get_entries_cast(void*ptr){
  208.     struct thread_get_entries_args * entries_args = ptr;
  209.     get_entries(entries_args->dir, entries_args->q);
  210.     printf("Llamada a q_terminar\n");
  211.     q_terminar(entries_args->q);
  212.     return 0;
  213. }
  214.  
  215. void start_get_entries_thread(char *dir, queue in_q){
  216.     struct thread_get_entries_info* thread;
  217.     thread = malloc(sizeof(struct thread_get_entries_info));
  218.     if(thread == NULL){
  219.         printf("Not enough memory available.\n");
  220.         exit(1);
  221.     }
  222.     thread->entries_args = malloc(sizeof(struct thread_get_entries_args));
  223.     thread->entries_args->dir=dir;
  224.     thread->entries_args->q=in_q;
  225.     thread->entries_args->id=0;
  226.     if(0!= thrd_create(&thread->id, get_entries_cast, thread->entries_args)){
  227.         printf("FALLO AL CREAR\n");
  228.     }
  229.     //if(thrd_join(thread->id, NULL)){
  230.       //  printf("FALLO AL UNIR\n");
  231.     //}
  232. }
  233.  
  234.  
  235. void sum(struct options opt) {
  236.     queue in_q, out_q;
  237.     char *ent;
  238.     FILE *out;
  239.     struct file_md5 *md5;
  240.     int dirname_len;
  241.  
  242.  
  243.     in_q  = q_create(opt.queue_size);
  244.     out_q = q_create(opt.queue_size);
  245.  
  246.     start_get_entries_thread(opt.dir, in_q); //////////////////////////////////////////////////////////////////////////////////////////////////////
  247.  
  248.     while((ent = q_remove(in_q)) != NULL) {
  249.         printf("Se llama a q_remove\n");
  250.         md5 = malloc(sizeof(struct file_md5));
  251.  
  252.         md5->file = ent;
  253.         sum_file(md5);
  254.         printf("Se llama a q_insert\n");
  255.         q_insert(out_q, md5);
  256.     }
  257.     printf("Llamada a q_terminar\n");
  258.     q_terminar(out_q);
  259.  
  260.     if((out = fopen(opt.file, "w")) == NULL) {
  261.         printf("Could not open output file\n");
  262.         exit(0);
  263.     }
  264.  
  265.     dirname_len = strlen(opt.dir) + 1; // length of dir + /
  266.  
  267.     while((md5 = q_remove(out_q)) != NULL) {
  268.         printf("Se llama a q_remove\n");
  269.         fprintf(out, "%s: ", md5->file + dirname_len);
  270.  
  271.         for(int i = 0; i < md5->hash_size; i++)
  272.             fprintf(out, "%02hhx", md5->hash[i]);
  273.         fprintf(out, "\n");
  274.  
  275.         free(md5->file);
  276.         free(md5->hash);
  277.         free(md5);
  278.     }
  279.  
  280.     fclose(out);
  281.     q_destroy(in_q);
  282.     q_destroy(out_q);
  283. }
  284.  
  285.  
  286. int main(int argc, char *argv[]) {
  287.     struct options opt;
  288.  
  289.     opt.num_threads = 5;
  290.     opt.queue_size  = 1;
  291.     opt.check       = true;
  292.     opt.file        = NULL;
  293.     opt.dir         = NULL;
  294.  
  295.     read_options (argc, argv, &opt);
  296.  
  297.     if(opt.check)
  298.         check(opt);
  299.     else
  300.         sum(opt);
  301.  
  302. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement