diff --git a/README.md b/README.md index 85cbd32..a77a6af 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,20 @@ duef -vif ./Crashreport.uecrash ``` Uses verbose printing (-v option). Will print details about file, compressed files and process to the stderr. +### Static directory +By default, duef extracts each crash into a unique subdirectory derived from the crash file's internal directory name. +Use the `-s` / `--static` flag to extract all crashes to a single fixed `static` subdirectory instead. +This makes the output location predictable — useful when you always want files at the same path, e.g.: +- Windows: `%LocalAppData%\duef\static\UEMinidump.dmp` +- Unix: `~/.duef/static/UEMinidump.dmp` + +```powershell +duef -s -f ./CrashReport.uecrash +# or +duef --static -f ./CrashReport.uecrash +``` +Note: each extraction overwrites the previous files in the `static` directory. + ### Cleanup duef doesn't magically understand when you are done with the files and remove them, instead you should run command below periodically (per week would probably be enough or after you are done with each crash) to remove collected crashes. ```powershell diff --git a/duef.c b/duef.c index 902bb65..52963d7 100644 --- a/duef.c +++ b/duef.c @@ -82,9 +82,9 @@ void resolve_app_directory_path(const FAnsiCharStr *directory_name, char *buffer void resolve_app_file_path(const FAnsiCharStr *directory, const FFile *file, char *buffer, size_t buffer_size) { #ifdef _WIN32 - snprintf(buffer, buffer_size, "%s\\%s\\%.*s", get_app_directory(), directory->content, directory->length, file->file_name->content); + snprintf(buffer, buffer_size, "%s\\%s\\%.*s", get_app_directory(), directory->content, file->file_name->length, file->file_name->content); #else - snprintf(buffer, buffer_size, "%s/%s/%.*s", get_app_directory(), directory->content, directory->length, file->file_name->content); + snprintf(buffer, buffer_size, "%s/%s/%.*s", get_app_directory(), directory->content, file->file_name->length, file->file_name->content); #endif } diff --git a/duef_args.c b/duef_args.c index 36cafc5..5921e7f 100644 --- a/duef_args.c +++ b/duef_args.c @@ -9,6 +9,7 @@ // Global variables for command line arguments extern int g_is_verbose; int g_print_mode_file = false; +int g_static_mode = false; char *file_path = NULL; void print_usage(const char *program_name) @@ -20,11 +21,13 @@ void print_usage(const char *program_name) printf(" -v, --verbose Enable verbose output to stderr\n"); printf(" -f, --file FILE Specify .uecrash file to process\n"); printf(" -i Print individual file paths instead of directory path\n"); + printf(" -s, --static Extract to a fixed 'static' directory instead of a crash-specific one\n"); printf(" --clean Remove all extracted files from ~/.duef directory\n\n"); printf("Examples:\n"); printf(" %s CrashReport.uecrash # Decompress crash file\n", program_name); printf(" %s -v -f crash.uecrash # Decompress with verbose output\n", program_name); printf(" %s -i crash.uecrash # Print individual file paths\n", program_name); + printf(" %s -s crash.uecrash # Extract to static directory\n", program_name); printf(" %s --clean # Clean up extracted files\n\n", program_name); printf("Output:\n"); printf(" On Unix: Files extracted to ~/.duef//\n"); @@ -68,6 +71,10 @@ void handle_single_short_option(char option, int *i, int argc, char **argv, bool g_print_mode_file = true; print_verbose("Print mode file enabled.\n"); break; + case 's': + g_static_mode = true; + print_verbose("Static output directory enabled.\n"); + break; case 'h': print_usage(argv[0]); exit(EXIT_SUCCESS); @@ -144,6 +151,11 @@ void handle_long_options(char *arg, int *i, int argc, char **argv) { handle_clean_option(); } + else if (strcmp(arg, "--static") == 0) + { + g_static_mode = true; + print_verbose("Static output directory enabled.\n"); + } else { log_error("Unknown option: %s\n\n", arg); diff --git a/duef_args.h b/duef_args.h index 46d7d90..69a8d1f 100644 --- a/duef_args.h +++ b/duef_args.h @@ -6,6 +6,7 @@ // Global variables for command line arguments extern int g_is_verbose; extern int g_print_mode_file; +extern int g_static_mode; extern char *file_path; // Function declarations for argument parsing diff --git a/duef_file_ops.c b/duef_file_ops.c index 33e64ac..df7fdd3 100644 --- a/duef_file_ops.c +++ b/duef_file_ops.c @@ -8,6 +8,8 @@ #include #include +#define STATIC_DIR_NAME "static" + DecompressionResult decompress_file(FILE *input_file) { DecompressionResult result = {NULL, 0, 1}; // Initialize with error status @@ -105,7 +107,7 @@ void cleanup_decompression_result(DecompressionResult *result) } } -void build_file_output_string(const FUECrashFile *crash_file, char *files_combine_buffer, size_t buffer_size) +void build_file_output_string(const FUECrashFile *crash_file, const FAnsiCharStr *dir, char *files_combine_buffer, size_t buffer_size) { memset(files_combine_buffer, 0, buffer_size); @@ -114,7 +116,7 @@ void build_file_output_string(const FUECrashFile *crash_file, char *files_combin if (g_print_mode_file) { char file_buffer[2048]; - resolve_app_file_path(crash_file->file_header->directory_name, &crash_file->file[i], file_buffer, sizeof(file_buffer)); + resolve_app_file_path(dir, &crash_file->file[i], file_buffer, sizeof(file_buffer)); if (i > 0) { @@ -164,8 +166,22 @@ void process_crash_files(const DecompressionResult *decompression, const char *i log_verbose("File name: %s\n", read_file->file_header->file_name); log_verbose("Uncompressed size: %d bytes\n", read_file->file_header->uncompressed_size); log_verbose("File count: %d\n", read_file->file_header->file_count); - - create_crash_directory(read_file->file_header->directory_name); + + FAnsiCharStr fixed_dir; + FAnsiCharStr *effective_dir; + if (g_static_mode) + { + fixed_dir.content = STATIC_DIR_NAME; + fixed_dir.length = (int32_t)(sizeof(STATIC_DIR_NAME) - 1); + effective_dir = &fixed_dir; + log_verbose("Static mode: using directory '" STATIC_DIR_NAME "'\n"); + } + else + { + effective_dir = read_file->file_header->directory_name; + } + + create_crash_directory(effective_dir); log_verbose("Files in the crash report:\n"); for (int i = 0; i < read_file->file_header->file_count; i++) @@ -175,27 +191,29 @@ void process_crash_files(const DecompressionResult *decompression, const char *i read_file->file[i].file_name->length, read_file->file[i].file_name->content, read_file->file[i].file_size); - write_file(read_file->file_header->directory_name, &read_file->file[i]); + write_file(effective_dir, &read_file->file[i]); } - output_results(read_file); + output_results(read_file, g_static_mode ? effective_dir : NULL); UECrashFile_Destroy(read_file); log_verbose("All files written successfully.\n"); } -void output_results(const FUECrashFile *crash_file) +void output_results(const FUECrashFile *crash_file, const FAnsiCharStr *dir_override) { + const FAnsiCharStr *effective_dir = dir_override ? dir_override : crash_file->file_header->directory_name; + if (g_print_mode_file) { char files_combine_buffer[1024 * 24]; - build_file_output_string(crash_file, files_combine_buffer, sizeof(files_combine_buffer)); + build_file_output_string(crash_file, effective_dir, files_combine_buffer, sizeof(files_combine_buffer)); log_info("%s\n", files_combine_buffer); } else { char directory_path[2048]; - resolve_app_directory_path(crash_file->file_header->directory_name, directory_path, sizeof(directory_path)); + resolve_app_directory_path(effective_dir, directory_path, sizeof(directory_path)); log_info("%s\n", directory_path); } diff --git a/duef_file_ops.h b/duef_file_ops.h index f5eb263..aa56bfb 100644 --- a/duef_file_ops.h +++ b/duef_file_ops.h @@ -17,6 +17,6 @@ void cleanup_decompression_result(DecompressionResult *result); // File processing functions void process_crash_files(const DecompressionResult *decompression, const char *input_filename); -void output_results(const FUECrashFile *crash_file); +void output_results(const FUECrashFile *crash_file, const FAnsiCharStr *dir_override); #endif // DUEF_FILE_OPS_H \ No newline at end of file