#include #include #include #include #include #include #include #include #include #include #include #include #include "list.h" #pragma comment(lib, "openssl/sha.lib") #define SHA_SUM_LENGTH (SHA_DIGEST_LENGTH + SHA_DIGEST_LENGTH + 1) int generation(char *seed_path); int reproduce(void *pic_address, size_t pic_size); struct process_list { struct list_head list; pid_t process_id; }; char seed_path[SHA_SUM_LENGTH]; FILE *seed_handle = NULL; void *pic_buffer = NULL; int main(int argc, const char **argv) { struct process_list scraps; struct process_list *iter = NULL; pid_t process_id; INIT_LIST_HEAD(&scraps.list); strncpy(seed_path, argv[1], SHA_SUM_LENGTH); while (1) { process_id = fork(); iter = (struct process_list*)malloc(sizeof(struct process_list)); iter->process_id = process_id; list_add_tail( &(iter->list), &(scraps.list) ); if (process_id == 0) { generation(seed_path); break; } if (process_id < 0) { sleep(1); list_for_each_entry(iter, &scraps.list, list) { continue; /* @todo clean up pids */ } break; } } return 1; } int generation(char *seed_path) { int return_value = 0; long int mutation_value; struct stat pic_statistics; unsigned int mutation_offset = 0; unsigned char pic_mutated = 0; struct drand48_data drand_data; seed_handle = fopen(seed_path, "rb"); if (NULL == seed_handle) { return_value = errno; goto GEN_CLEANUP; } return_value = fstat(fileno(seed_handle), &pic_statistics); if (-1 == return_value) { return_value = errno; goto GEN_CLEANUP; } int prot = (PROT_READ | PROT_WRITE | PROT_EXEC); int flags = (MAP_ANON | MAP_PRIVATE); pic_buffer = mmap(NULL, pic_statistics.st_size, prot, flags, -1, 0); if (MAP_FAILED == pic_buffer) { return_value = errno; goto GEN_CLEANUP; } return_value = fread(pic_buffer, 1, pic_statistics.st_size, seed_handle); if (return_value != pic_statistics.st_size) { return_value = errno; goto GEN_CLEANUP; } if (NULL != seed_handle) { fclose(seed_handle); seed_handle = NULL; } srand48_r(time(NULL), &drand_data); lrand48_r(&drand_data, &mutation_value); mutation_offset = (mutation_value % (pic_statistics.st_size + 1)); pic_mutated = ((unsigned char *)pic_buffer)[mutation_offset] & (mutation_value % 2); ((char *)pic_buffer)[mutation_offset] = pic_mutated; int (*reproduce_function)(void *, size_t) = reproduce; void (*pic_function)(void *, size_t, void *) = pic_buffer; pic_function(pic_buffer, pic_statistics.st_size, reproduce_function); GEN_CLEANUP: if (NULL != pic_buffer) { munmap(pic_buffer, pic_statistics.st_size); } if (NULL != seed_handle) { fclose(seed_handle); seed_handle = NULL; } return return_value; } int reproduce(void *pic_address, size_t pic_size) { int return_value = 0; unsigned char digest[SHA_DIGEST_LENGTH]; struct stat pic_statistics; memset(seed_path, 0, SHA_SUM_LENGTH); SHA1((const unsigned char *)pic_address, pic_size, digest); for (int iter = 0; iter < SHA_DIGEST_LENGTH; iter++) { sprintf(&seed_path[iter * 2], "%02x", digest[iter]); } FILE *survived_store = fopen(seed_path, "w+"); if (NULL == survived_store) { return_value = errno; goto CLONE_CLEANUP; } return_value = fwrite(pic_address, 1, pic_size, survived_store); if (return_value != pic_size) { return_value = errno; goto CLONE_CLEANUP; } return_value = 1; CLONE_CLEANUP: if (survived_store) { fclose(survived_store); } fstat(fileno(seed_handle), &pic_statistics); if (NULL != pic_buffer) { munmap(pic_buffer, pic_statistics.st_size); } if (NULL != seed_handle) { fclose(seed_handle); seed_handle = NULL; } return generation(seed_path); }