diff --git a/main.tsk b/main.tsk index 594f0c3..edb62fd 100644 --- a/main.tsk +++ b/main.tsk @@ -1,8 +1,3 @@ *Compile #do -gcc -o tasks tasks.c - -*Test -#do -./tasks test.tsk - +gcc -o tasks -I src src/tasks.c \ No newline at end of file diff --git a/src/lookup_list.h b/src/lookup_list.h new file mode 100644 index 0000000..f0d60cd --- /dev/null +++ b/src/lookup_list.h @@ -0,0 +1,152 @@ +#ifndef INCLUDED_LOOKUP_LIST_H +#define INCLUDED_LOOKUP_LIST_H + +#include +#include +#include +#include +#include + +// Both key and value will be string +typedef struct LookupList{ + char *key; + char *value; + struct LookupList *next; +} LookupList; + +// return -1 on failure +int LookupList_add(LookupList **list ,char *key, char *value){ + LookupList *node = (LookupList *) malloc(sizeof(LookupList)); + if(node == NULL) return -1; + + node->key = key; + node->value = value; + node->next = *list; + *list = node; + + return 0; +} + +// Does not try to free key and value strings +void LookupList_remove(LookupList **list, char *key){ + LookupList *a = *list; + if(a == NULL) return; + if(strcmp(key, a->key) == 0){ + *list = (*list)->next; + free(a); + return; + } + + LookupList *b = a->next; + while(b != NULL){ + if(strcmp(key, b->key) == 0){ + a->next = b->next; + free(b); + return; + } + + a = b; + b = b->next; + } +} + +char *LookupList_get(LookupList *list, char *key, char *r){ + while(list != NULL){ + if(strcmp(list->key, key) == 0 ) + return list->value; + list = list->next; + } + return r; +} + +void LookupList_print(LookupList *list){ + printf("{ "); + while(list != NULL){ + printf("\"%s\" : \"%s\" ,", list->key, list->value); + list = list->next; + } + printf("}\n"); +} + +// The binary will first have a uint32_t equal to the number of (key,value) pairs. +// Then we kill have char[] that are seperated using \0 in key1, value1, key2, value2, key3, value3 .... for all pairs. +void LookupList_store(LookupList *list, char *filename){ + uint32_t n = 0; + LookupList *t = list; + while(t != NULL){ + n += 1; + t = t->next; + } + + t = list; + FILE *f = fopen(filename, "wb"); + fwrite(&n, sizeof(uint32_t), 1, f); + for(int i = 0; i < n; i++){ + size_t len_key = 0; + size_t len_value = 0; + + while(t->key[len_key++] != '\0'); + while(t->value[len_value++] != '\0'); + + fwrite(t->key, sizeof(char), len_key, f); + fwrite(t->value, sizeof(char), len_value, f); + t = t->next; + } + fclose(f); +} + +void LookupList_load(LookupList **l, char *filename){ + FILE *f = fopen(filename, "rb"); + assert(f != NULL); + + uint32_t n = 0; + fread(&n, sizeof(uint32_t), 1, f); + + for(int i = 0; i < n; i++){ + + size_t key_capacity = 10; + char *key = (char *) malloc(sizeof(char) * key_capacity); + assert(key != NULL); + int j = 0; + + + while(1){ + + if((j+1) == key_capacity){ + key_capacity *= 2; + key = (char *) realloc(key, sizeof(char) * key_capacity); + assert(key != NULL); + } + + fread((key + j), sizeof(char), 1, f); + if (key[j] == '\0') + break; + + j++; + } + + size_t value_capacity = 10; + char *value = (char *) malloc(sizeof(char) * value_capacity); + assert(value != NULL); + j = 0; + + while(1){ + if((j+1) == value_capacity){ + value_capacity *= 2; + value = (char *) realloc(value, sizeof(char) * value_capacity); + assert(value != NULL); + } + + fread((value + j), sizeof(char), 1, f); + if (value[j] == '\0') + break; + j++; + } + + LookupList_add(l, key, value); + } + + fclose(f); +} + +#endif diff --git a/src/sha1.h b/src/sha1.h new file mode 100644 index 0000000..7b700d5 --- /dev/null +++ b/src/sha1.h @@ -0,0 +1,132 @@ +#ifndef INCLUDED_SHA1_H +#define INCLUDED_SHA1_H + +#include +#include +#include + +uint32_t leftRotate32( uint32_t N, uint32_t D){ + return ((N << D) | (N >> (32-D))); +} + +typedef struct SHA1_Result{ + uint32_t h0; + uint32_t h1; + uint32_t h2; + uint32_t h3; + uint32_t h4; +} SHA1_Result; + +SHA1_Result SHA1_sha1file(char *filename){ + FILE* file = fopen(filename, "r"); + + if(file == NULL){ + perror(filename); + exit(EXIT_FAILURE); + } + + SHA1_Result r; + uint32_t number_of_chuncks = 0; + uint32_t size_in_bytes = 0; + uint64_t size_in_bits = 0; + + uint32_t h0 = UINT32_C(0x67452301); + uint32_t h1 = UINT32_C(0xefcdab89); + uint32_t h2 = UINT32_C(0x98badcfe); + uint32_t h3 = UINT32_C(0x10325476); + uint32_t h4 = UINT32_C(0xc3d2e1f0); + + size_t bytes_read; + uint8_t buffer[64]; + + int lastRound = 0; + while(lastRound != 1){ + bytes_read = fread(buffer, 1, 64, file); + number_of_chuncks++; + + if(bytes_read != 64){ + // * We need to convert to 512 bit * // + size_in_bytes += bytes_read; // the final size is done here + size_in_bits = size_in_bytes * 8; + + //padding + buffer[bytes_read] = 0x80; + bytes_read += 1; + + for(int i = bytes_read; i <= 55; i++) + buffer[i] = 0; + + //adding size to end + for(int i = 63; i >= 56; i--){ + buffer[i] = size_in_bits % 256; + size_in_bits /= 256; + } + + lastRound = 1; // This is the last round + } + + // * We usually get a 512 bit chunk except the last chunck which we need to pad (which we do in the if above) * // + size_in_bytes += 64; + + /////////////////////// ****************************************** //////////////////////////////////////////// + uint32_t w[80]; + for(int i = 0; i < 16; i++) + w[i] = buffer[4*i] * 16777216 + buffer[(4*i)+1] * 65536 + buffer[(4*i)+2] * 256 + buffer[(4*i)+3]; + + for(int i = 16; i < 80; i++) + w[i] = leftRotate32( w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i - 16] , 1 ); + + uint32_t a = h0; + uint32_t b = h1; + uint32_t c = h2; + uint32_t d = h3; + uint32_t e = h4; + + uint32_t f; + uint32_t k; + + // The 80 iterations + for(int i = 0; i < 80; i++){ + if(i >= 0 && i <= 19){ + f = (b & c) ^ ((~b) & d); + k = UINT32_C(0x5a827999); + }else if ( i >= 20 && i <= 39){ + f = b ^ c ^ d; + k = UINT32_C(0x6ed9eba1); + }else if (i >= 40 && i <= 59){ + f = (b & c) ^ (b & d) ^ (c & d); + k = UINT32_C(0x8f1bbcdc); + }else if (i >= 60 && i <= 79){ + f = b ^ c ^ d; + k = UINT32_C(0xca62c1d6); + } + + uint32_t temp = leftRotate32(a,5) + f + e + k + w[i]; + e = d; + d = c; + c = leftRotate32(b, 30); + b = a; + a = temp; + } + + // Add this chunk's hash result + h0 = h0 + a; + h1 = h1 + b; + h2 = h2 + c; + h3 = h3 + d; + h4 = h4 + e; + /////////////////////// ****************************************** //////////////////////////////////////////// + } + + fclose(file); + + r.h0 = h0; + r.h1 = h1; + r.h2 = h2; + r.h3 = h3; + r.h4 = h4; + + return r; +} + +#endif diff --git a/src/tasks.c b/src/tasks.c index c5ee4a8..dbba48c 100644 --- a/src/tasks.c +++ b/src/tasks.c @@ -3,6 +3,8 @@ #include #include #include +#include "sha1.h" +#include "lookup_list.h" #define MAX_TASKS 5 @@ -13,6 +15,8 @@ typedef struct TASKS_str_linked_list{ struct TASKS_str_linked_list *next; } TASKS_str_linked_list; + +// sll : short for String Linked List void TASKS_sll_print(TASKS_str_linked_list *list){ printf("[ "); while(list != NULL){ @@ -121,8 +125,10 @@ bool TASKS_get_line(FILE *f, char *line, int *current_line_capacity){ while(true){ c = fgetc(f); - if(c == EOF) + if(c == EOF){ + line[i] = '\0'; return false; + } if(c == '\n'){ line[i] = '\0'; @@ -148,14 +154,17 @@ void TASKS_get_tasks(char *filename){ FILE *f = fopen(filename, "r"); assert(f != NULL); + bool to_loop = true; + bool semicolon = true; - while(TASKS_get_line(f, current_line, ¤t_line_capacity)){ + while(to_loop){ + to_loop = TASKS_get_line(f, current_line, ¤t_line_capacity); TASKS_strip_line(current_line); if(current_line[0] == '\0') continue; //* Uncomment to print the file read by program line by line *// - //printf("%s\n", current_line); + // printf("%s\n", current_line); // This length includes the \0 int current_line_len = 0; @@ -203,6 +212,7 @@ void TASKS_get_tasks(char *filename){ }else if(strcmp(current_section, "commands") == 0){ TASKS_sll_add(&tasks[number_of_tasks - 1].commands, TASKS_substr(current_line, 0, current_line_len - 2)); } + } fclose(f); @@ -223,6 +233,63 @@ void TASKS_do_all_tasks(){ } } +void TASKS_do_tasks_ifchange(char *filename){ + size_t filename_size = 0; + while(filename[filename_size++] != '\0'); + char *binary_filename= (char *) malloc(sizeof(char)* (filename_size+1)); + binary_filename[0] = '.'; + binary_filename[1] = '\0'; + strcat(binary_filename, filename); + + LookupList *map = NULL; + if(TASKS_file_exists(binary_filename)) + LookupList_load(&map, binary_filename); + + LookupList *new_map = NULL; + + for(int i = 0; i < number_of_tasks; i++){ + bool skip_task = true; + + TASKS_str_linked_list *icll = tasks[i].ifchange; + while(icll != NULL){ + char *file_sha1 = (char *) malloc(sizeof(char) * 50); + char stored_sha1[50]; + + SHA1_Result file_sha1_unformatted = SHA1_sha1file(icll->data); + sprintf(file_sha1, "%x%x%x%x%x",file_sha1_unformatted.h0, file_sha1_unformatted.h1,file_sha1_unformatted.h2, file_sha1_unformatted.h3, file_sha1_unformatted.h4); + + strcpy(stored_sha1,LookupList_get(map, icll->data, " ")); + LookupList_add(&new_map, icll->data, file_sha1); + if(strcmp(file_sha1, stored_sha1) != 0) + skip_task = false; + icll = icll->next; + } + + if(map == NULL) skip_task = false; + if(skip_task) continue; + + printf("[*] EXECUTING TASK : %s\n", tasks[i].name); + TASKS_str_linked_list *cll = tasks[i].commands; + while(cll != NULL){ + char *cmd = cll->data; + printf("+ %s\n", cmd); + system(cmd); + cll = cll->next; + } + printf("\n"); + } + + if(new_map != NULL){ + printf("\nSaving file named %s with sha1 values\n", binary_filename); + LookupList_print(new_map); + LookupList_store(new_map, binary_filename); + } + + // MAYBE : free all char *file_sha1 after storing on disk + + free(binary_filename); +} + int main(int argc, char *argv[]){ char *tasks_file = "main.tsk"; @@ -249,7 +316,9 @@ int main(int argc, char *argv[]){ } printf("\n<-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <-> <->\n\n"); - //* From here we just need to execute all tasks *// - TASKS_do_all_tasks(); + //* From here we just need to execute tasks *// + // TASKS_do_all_tasks(); + TASKS_do_tasks_ifchange(tasks_file); + return 0; } diff --git a/test.tsk b/test.tsk deleted file mode 100644 index 2d3ca1a..0000000 --- a/test.tsk +++ /dev/null @@ -1,15 +0,0 @@ -*Task 1 -#ifchange -testfile1 testfile2 - testfile3 testfile4 -testfile5 -#do -echo HELLO WORLD - -*Task 2 -#ifchange -file1 file2 file3 file4 - file5 file6 - file7 -#do -echo HI WORLD