]> FriiDump Source - friidump.git/blob - libfriidump/xbox_ref/xbox_ref_log.c
FriiDump 0.5.3.10: add Redump evidence and optimize Xbox flow
[friidump.git] / libfriidump / xbox_ref / xbox_ref_log.c
1 #include "xbox_ref_log.h"
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <stdarg.h>
7 #include <ctype.h>
8
9 #ifdef _WIN32
10 #include <windows.h>
11 #endif
12
13 #ifndef MAX_PATH
14 #define MAX_PATH 260
15 #endif
16
17 static FILE *g_xbox_ref_log = NULL;
18 static char g_xbox_ref_log_path[MAX_PATH * 2] = {0};
19 static char g_xbox_ref_temp_path[MAX_PATH * 2] = {0};
20 static int g_xbox_ref_using_temp = 0;
21
22 static void xbox_ref_build_log_path(const char *target_filename, char drive_letter, char *out, size_t out_size, int *is_temp)
23 {
24     if (!out || out_size == 0)
25         return;
26
27     out[0] = '\0';
28     if (is_temp)
29         *is_temp = 0;
30
31     if (target_filename && target_filename[0]) {
32         snprintf(out, out_size, "%s.log", target_filename);
33         return;
34     }
35
36     if (drive_letter && isalpha((unsigned char)drive_letter))
37         snprintf(out, out_size, "friidump_%c.log", (char)tolower((unsigned char)drive_letter));
38     else
39         snprintf(out, out_size, "friidump.log");
40
41     if (is_temp)
42         *is_temp = 1;
43 }
44
45 static int xbox_ref_open_path(const char *path, int append)
46 {
47     if (!path || !path[0])
48         return 0;
49
50     g_xbox_ref_log = fopen(path, append ? "ab" : "wb");
51     if (!g_xbox_ref_log)
52         return 0;
53
54     strncpy(g_xbox_ref_log_path, path, sizeof(g_xbox_ref_log_path) - 1);
55     g_xbox_ref_log_path[sizeof(g_xbox_ref_log_path) - 1] = '\0';
56     return 1;
57 }
58
59 int xbox_ref_log_open_for_target(const char *target_filename, char drive_letter)
60 {
61     char path[MAX_PATH * 2];
62     int is_temp = 0;
63
64     xbox_ref_build_log_path(target_filename, drive_letter, path, sizeof(path), &is_temp);
65
66     if (g_xbox_ref_log && strcmp(g_xbox_ref_log_path, path) == 0)
67         return 1;
68
69     xbox_ref_log_close();
70
71     if (!xbox_ref_open_path(path, 0)) {
72         fprintf(stderr, "[FRIIDUMP][WARN] Could not create log file '%s'. Continuing without file logging.\n", path[0] ? path : "(none)");
73         return 0;
74     }
75
76     g_xbox_ref_using_temp = is_temp;
77     if (is_temp) {
78         strncpy(g_xbox_ref_temp_path, path, sizeof(g_xbox_ref_temp_path) - 1);
79         g_xbox_ref_temp_path[sizeof(g_xbox_ref_temp_path) - 1] = '\0';
80     } else {
81         g_xbox_ref_temp_path[0] = '\0';
82     }
83
84     xbox_ref_printf("[FRIIDUMP] Log file: %s\n", g_xbox_ref_log_path);
85     return 1;
86 }
87
88 int xbox_ref_log_retarget(const char *target_filename)
89 {
90     char final_path[MAX_PATH * 2];
91     int dummy = 0;
92
93     if (!target_filename || !target_filename[0])
94         return 0;
95
96     xbox_ref_build_log_path(target_filename, 0, final_path, sizeof(final_path), &dummy);
97     if (!final_path[0])
98         return 0;
99
100     if (strcmp(g_xbox_ref_log_path, final_path) == 0)
101         return 1;
102
103     if (!g_xbox_ref_log) {
104         return xbox_ref_open_path(final_path, 0);
105     }
106
107     xbox_ref_printf("[FRIIDUMP] Retargeting log file to: %s\n", final_path);
108     fclose(g_xbox_ref_log);
109     g_xbox_ref_log = NULL;
110
111     if (g_xbox_ref_using_temp && g_xbox_ref_temp_path[0]) {
112         remove(final_path);
113         if (rename(g_xbox_ref_temp_path, final_path) == 0) {
114             g_xbox_ref_using_temp = 0;
115             g_xbox_ref_temp_path[0] = '\0';
116             return xbox_ref_open_path(final_path, 1);
117         }
118     }
119
120     g_xbox_ref_using_temp = 0;
121     g_xbox_ref_temp_path[0] = '\0';
122     return xbox_ref_open_path(final_path, 1);
123 }
124
125 void xbox_ref_log_close(void)
126 {
127     if (g_xbox_ref_log) {
128         fflush(g_xbox_ref_log);
129         fclose(g_xbox_ref_log);
130     }
131     g_xbox_ref_log = NULL;
132     g_xbox_ref_log_path[0] = '\0';
133     g_xbox_ref_temp_path[0] = '\0';
134     g_xbox_ref_using_temp = 0;
135 }
136
137 int xbox_ref_log_is_open(void)
138 {
139     return g_xbox_ref_log != NULL;
140 }
141
142 const char *xbox_ref_log_path(void)
143 {
144     return g_xbox_ref_log_path[0] ? g_xbox_ref_log_path : NULL;
145 }
146
147 int xbox_ref_printf(const char *fmt, ...)
148 {
149     va_list ap;
150     va_list ap2;
151     int out;
152
153     va_start(ap, fmt);
154     va_copy(ap2, ap);
155     out = vprintf(fmt, ap);
156     fflush(stdout);
157     if (g_xbox_ref_log) {
158         vfprintf(g_xbox_ref_log, fmt, ap2);
159         fflush(g_xbox_ref_log);
160     }
161     va_end(ap2);
162     va_end(ap);
163     return out;
164 }
165
166 int xbox_ref_log_fprintf(FILE *stream, const char *fmt, ...)
167 {
168     va_list ap;
169     va_list ap2;
170     int out;
171
172     if (!stream)
173         stream = stdout;
174
175     va_start(ap, fmt);
176     va_copy(ap2, ap);
177     out = vfprintf(stream, fmt, ap);
178     fflush(stream);
179     if (g_xbox_ref_log) {
180         vfprintf(g_xbox_ref_log, fmt, ap2);
181         fflush(g_xbox_ref_log);
182     }
183     va_end(ap2);
184     va_end(ap);
185     return out;
186 }
187
188 int xbox_ref_console_printf(const char *fmt, ...)
189 {
190     va_list ap;
191     int out;
192
193     va_start(ap, fmt);
194     out = vprintf(fmt, ap);
195     fflush(stdout);
196     va_end(ap);
197     return out;
198 }
199
200 static void xbox_ref_hexdump_to_file(FILE *stream, const char *prefix, const uint8_t *data, size_t length, size_t limit, int truncated)
201 {
202     size_t i;
203     size_t shown = (limit && limit < length) ? limit : length;
204
205     if (!stream || !prefix)
206         return;
207
208     if (truncated)
209         fprintf(stream, "\n--- %s (%lu bytes; console showing first %lu bytes, full data in log) ---\n",
210                 prefix, (unsigned long)length, (unsigned long)shown);
211     else
212         fprintf(stream, "\n--- %s (%lu bytes) ---\n", prefix, (unsigned long)length);
213
214     for (i = 0; i < shown; i++) {
215         fprintf(stream, "%02X ", data ? data[i] : 0);
216         if ((i + 1) % 16 == 0)
217             fprintf(stream, "\n");
218     }
219     if (shown % 16 != 0)
220         fprintf(stream, "\n");
221     if (truncated)
222         fprintf(stream, "... [truncated on console; full %lu bytes written to log]\n", (unsigned long)length);
223     fprintf(stream, "---------------------------\n");
224     fflush(stream);
225 }
226
227 void xbox_ref_log_hexdump(const char *prefix, const uint8_t *data, size_t length, size_t console_limit)
228 {
229     int console_truncated = (console_limit > 0 && console_limit < length);
230
231     xbox_ref_hexdump_to_file(stdout, prefix, data, length, console_limit, console_truncated);
232
233     if (g_xbox_ref_log) {
234         /* The log is intentionally never truncated. */
235         xbox_ref_hexdump_to_file(g_xbox_ref_log, prefix, data, length, 0, 0);
236     }
237 }