Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions duef.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
12 changes: 12 additions & 0 deletions duef_args.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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/<directory>/\n");
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions duef_args.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
36 changes: 27 additions & 9 deletions duef_file_ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include <string.h>
#include <stdint.h>

#define STATIC_DIR_NAME "static"

DecompressionResult decompress_file(FILE *input_file)
{
DecompressionResult result = {NULL, 0, 1}; // Initialize with error status
Expand Down Expand Up @@ -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);

Expand All @@ -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)
{
Expand Down Expand Up @@ -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++)
Expand All @@ -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);
}

Expand Down
2 changes: 1 addition & 1 deletion duef_file_ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Loading