// load a file into memory and run the buffer tests void loadfile(char *name) { FILE *file; char *buffer; unsigned long fileLen; //Open file file = fopen(name, "rb"); if (!file) { fprintf(stderr, "Unable to open file %s\n", name); return 0; } //Get file length fseek(file, 0, SEEK_END); fileLen=ftell(file); fseek(file, 0, SEEK_SET); //Allocate memory buffer=(char *)malloc(fileLen+1); if (!buffer) { fprintf(stderr, "Memory error!"); fclose(file); return 0; } //Read file contents into buffer fread(buffer, fileLen, 1, file); fclose(file); // process the buffer dump_buffer_hex(buffer, fileLen); shuffle_buffer(buffer, fileLen); printf("\npost shuffle buffer\n"); dump_buffer_hex(buffer, fileLen); printf("\npost unshuffle buffer\n"); write_buffer(name, buffer, fileLen); // unshuffle_buffer(buffer, fileLen); dump_buffer_hex(buffer, fileLen); free(buffer); }
int #ifdef DDKBUILD __cdecl #endif main (int argc, char *argv[]) { int ret = 1, i, j, rebuild; size_t size; char* file_name = NULL; char* junk; size_t* file_size = NULL; int64_t* file_time = NULL; FILE *fd, *header_fd; time_t header_time; struct NATIVE_STAT stbuf; struct tm* ltm; char internal_name[] = "file_###"; unsigned char* buffer = NULL; unsigned char last; char fullpath[MAX_PATH]; #if defined(_WIN32) wchar_t wfullpath[MAX_PATH]; #endif // Disable stdout bufferring setvbuf(stdout, NULL, _IONBF, 0); if (argc != 2) { fprintf(stderr, "You must supply a header name.\n"); return 1; } nb_embeddables = nb_embeddables_fixed; #if defined(USER_DIR) add_user_files(); #endif // Check if any of the embedded files have changed rebuild = 0; if (NATIVE_STAT(argv[1], &stbuf) == 0) { header_time = stbuf.st_mtime; // make sure to use modification time! for (i=0; i<nb_embeddables; i++) { if (embeddable[i].reuse_last) break; if (get_full_path(embeddable[i].file_name, fullpath, MAX_PATH)) { fprintf(stderr, "Unable to get full path for '%s'.\n", embeddable[i].file_name); goto out1; } if (NATIVE_STAT(fullpath, &stbuf) != 0) { printf("unable to stat '%s' - assuming rebuild needed\n", fullpath); rebuild = 1; break; } if (stbuf.st_mtime > header_time) { printf("detected change for '%s'\n", fullpath); rebuild = 1; break; } } if (!rebuild) { printf(" resources haven't changed - skipping step\n"); ret = 0; goto out1; } } size = sizeof(size_t)*nb_embeddables; file_size = malloc(size); if (file_size == NULL) goto out1; size = sizeof(int64_t)*nb_embeddables; file_time = malloc(size); if (file_time == NULL) goto out1; header_fd = fopen(argv[1], "w"); if (header_fd == NULL) { fprintf(stderr, "Can't create file '%s'.\n", argv[1]); goto out1; } fprintf(header_fd, "#pragma once\n"); for (i=0; i<nb_embeddables; i++) { if (embeddable[i].reuse_last) { continue; } if (get_full_path(embeddable[i].file_name, fullpath, MAX_PATH)) { fprintf(stderr, "Unable to get full path for '%s'.\n", embeddable[i].file_name); goto out2; } #if defined(_WIN32) MultiByteToWideChar(CP_UTF8, 0, fullpath, -1, wfullpath, MAX_PATH); wprintf(L" EMBED %s ", wfullpath); fd = _wfopen(wfullpath, L"rb"); #else printf(" EMBED %s ", fullpath); fd = fopen(fullpath, "rb"); #endif if (fd == NULL) { fprintf(stderr, "Couldn't open file '%s'.\n", fullpath); goto out2; } // Read the creation date memset(&stbuf, 0, sizeof(stbuf)); if ( (NATIVE_STAT(fullpath, &stbuf) == 0) && ((ltm = localtime(&stbuf.st_ctime)) != NULL) ) { printf("(%04d.%02d.%02d)\n", ltm->tm_year+1900, ltm->tm_mon+1, ltm->tm_mday); } else { printf("\n"); } file_time[i] = (int64_t)stbuf.st_ctime; fseek(fd, 0, SEEK_END); size = (size_t)ftell(fd); fseek(fd, 0, SEEK_SET); file_size[i] = size; buffer = (unsigned char*) malloc(size); if (buffer == NULL) { fprintf(stderr, "Couldn't allocate buffer.\n"); goto out3; } if (fread(buffer, 1, size, fd) != size) { fprintf(stderr, "Read error.\n"); goto out4; } fclose(fd); sprintf(internal_name, "file_%03X", (unsigned char)i); fprintf(header_fd, "const unsigned char %s[] = {", internal_name); dump_buffer_hex(header_fd, buffer, size); fprintf(header_fd, "};\n\n"); safe_free(buffer); } fprintf(header_fd, "struct res {\n" \ "\tchar* subdir;\n" \ "\tchar* name;\n" \ "\tsize_t size;\n" \ "\tint64_t creation_time;\n" \ "\tconst unsigned char* data;\n" \ "};\n\n"); fprintf(header_fd, "const struct res resource[] = {\n"); for (last=0,i=0; i<nb_embeddables; i++) { if (!embeddable[i].reuse_last) { last = (unsigned char)i; } sprintf(internal_name, "file_%03X", last); fprintf(header_fd, "\t{ \""); // Backslashes need to be escaped for (j=0; j<(int)strlen(embeddable[i].extraction_subdir); j++) { if ( (embeddable[i].extraction_subdir[j] == NATIVE_SEPARATOR) || (embeddable[i].extraction_subdir[j] == NON_NATIVE_SEPARATOR) ) { fputc('\\', header_fd); fputc('\\', header_fd); } else { fputc(embeddable[i].extraction_subdir[j], header_fd); } } basename_split(embeddable[i].file_name, &junk, &file_name); fprintf(header_fd, "\", \"%s\", %d, INT64_C(%"PRId64"), %s },\n", file_name, (int)file_size[last], file_time[last], internal_name); basename_free(embeddable[i].file_name); } fprintf(header_fd, "};\n"); fprintf(header_fd, "\nconst int nb_resources = sizeof(resource)/sizeof(resource[0]);\n"); fclose(header_fd); ret = 0; goto out1; out4: safe_free(buffer); out3: fclose(fd); out2: fclose(header_fd); // Must delete a failed file so that Make can relaunch its build NATIVE_UNLINK(argv[1]); out1: #if defined(USER_DIR) for (i=nb_embeddables_fixed; i<nb_embeddables; i++) { safe_free(embeddable[i].file_name); safe_free(embeddable[i].extraction_subdir); } if (embeddable != embeddable_fixed) { safe_free(embeddable); } #endif safe_free(file_size); safe_free(file_time); return ret; }