From 40a2527096d3d64d7d1d2fca05dab43b58bd1d44 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 16 Apr 2026 11:25:21 +0000 Subject: [PATCH 1/3] feat: add -s/--static flag for fixed output directory Agent-Logs-Url: https://github.com/yldrefruz/duef/sessions/b05a303e-1dfb-43e7-9220-1968babd16b2 Co-authored-by: yldrefruz <30903352+yldrefruz@users.noreply.github.com> --- README.md | 14 ++++++++++++++ duef_args.c | 12 ++++++++++++ duef_args.h | 1 + duef_file_ops.c | 35 +++++++++++++++++++++++++++++++---- 4 files changed, 58 insertions(+), 4 deletions(-) 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_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..23753ce 100644 --- a/duef_file_ops.c +++ b/duef_file_ops.c @@ -164,8 +164,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 static_dir; + FAnsiCharStr *effective_dir; + if (g_static_mode) + { + static_dir.content = "static"; + static_dir.length = (int32_t)strlen("static"); + effective_dir = &static_dir; + log_verbose("Static mode: using directory 'static'\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,10 +189,23 @@ 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); + if (g_static_mode) + { + FUECrashFile tmp_crash_file; + FFileHeader tmp_header; + tmp_header = *read_file->file_header; + tmp_header.directory_name = effective_dir; + tmp_crash_file.file_header = &tmp_header; + tmp_crash_file.file = read_file->file; + output_results(&tmp_crash_file); + } + else + { + output_results(read_file); + } UECrashFile_Destroy(read_file); log_verbose("All files written successfully.\n"); From 655215e66b92f97674cb91dbddfac62080ea8358 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 16 Apr 2026 11:29:14 +0000 Subject: [PATCH 2/3] refactor: use STATIC_DIR_NAME constant and clean up output_results Agent-Logs-Url: https://github.com/yldrefruz/duef/sessions/b05a303e-1dfb-43e7-9220-1968babd16b2 Co-authored-by: yldrefruz <30903352+yldrefruz@users.noreply.github.com> --- duef_file_ops.c | 39 +++++++++++++++------------------------ duef_file_ops.h | 2 +- 2 files changed, 16 insertions(+), 25 deletions(-) diff --git a/duef_file_ops.c b/duef_file_ops.c index 23753ce..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) { @@ -165,14 +167,14 @@ void process_crash_files(const DecompressionResult *decompression, const char *i 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); - FAnsiCharStr static_dir; + FAnsiCharStr fixed_dir; FAnsiCharStr *effective_dir; if (g_static_mode) { - static_dir.content = "static"; - static_dir.length = (int32_t)strlen("static"); - effective_dir = &static_dir; - log_verbose("Static mode: using directory 'static'\n"); + 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 { @@ -192,37 +194,26 @@ void process_crash_files(const DecompressionResult *decompression, const char *i write_file(effective_dir, &read_file->file[i]); } - if (g_static_mode) - { - FUECrashFile tmp_crash_file; - FFileHeader tmp_header; - tmp_header = *read_file->file_header; - tmp_header.directory_name = effective_dir; - tmp_crash_file.file_header = &tmp_header; - tmp_crash_file.file = read_file->file; - output_results(&tmp_crash_file); - } - else - { - 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 From 8b0de8050890d819337c65005db9885a1d376eb6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 16 Apr 2026 11:39:27 +0000 Subject: [PATCH 3/3] fix: use file->file_name->length in resolve_app_file_path Agent-Logs-Url: https://github.com/yldrefruz/duef/sessions/345fd239-e5cb-4e22-9f6b-0ae0d2dcda9d Co-authored-by: yldrefruz <30903352+yldrefruz@users.noreply.github.com> --- duef.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 }