From b3dccab6a6abd5d1b59dc5c2d596948e26523398 Mon Sep 17 00:00:00 2001 From: Julien Vanier Date: Fri, 2 May 2025 09:16:25 -0400 Subject: [PATCH] Add Windows compatibility Make build compatible with Windows using MSYS2 MINGW64 compiler. Add a small compatibility file for functions that don't exist in MINGW64. Signed-off-by: Julien Vanier --- Makefile | 6 +++--- firehose.c | 7 ++++--- ks.c | 8 +++++--- oscompat.c | 16 ++++++++++++++++ oscompat.h | 25 +++++++++++++++++++++++++ program.c | 1 + qdl.c | 6 +++++- ramdump.c | 5 +++++ sahara.c | 52 ++++++++++++++++++++++++++++++++-------------------- usb.c | 3 +-- ux.c | 22 ++++++++++++++++++++++ 11 files changed, 119 insertions(+), 32 deletions(-) create mode 100644 oscompat.c create mode 100644 oscompat.h diff --git a/Makefile b/Makefile index be1c904..8e03d57 100644 --- a/Makefile +++ b/Makefile @@ -6,14 +6,14 @@ CFLAGS += -O2 -Wall -g `pkg-config --cflags libxml-2.0 libusb-1.0` LDFLAGS += `pkg-config --libs libxml-2.0 libusb-1.0` prefix := /usr/local -QDL_SRCS := firehose.c qdl.c sahara.c util.c patch.c program.c read.c ufs.c usb.c ux.c +QDL_SRCS := firehose.c qdl.c sahara.c util.c patch.c program.c read.c ufs.c usb.c ux.c oscompat.c QDL_OBJS := $(QDL_SRCS:.c=.o) -RAMDUMP_SRCS := ramdump.c sahara.c usb.c util.c ux.c +RAMDUMP_SRCS := ramdump.c sahara.c usb.c util.c ux.c oscompat.c RAMDUMP_OBJS := $(RAMDUMP_SRCS:.c=.o) KS_OUT := ks -KS_SRCS := ks.c sahara.c util.c ux.c +KS_SRCS := ks.c sahara.c util.c ux.c oscompat.c KS_OBJS := $(KS_SRCS:.c=.o) default: $(QDL) $(RAMDUMP) $(KS_OUT) diff --git a/firehose.c b/firehose.c index cbd2263..2e805e7 100644 --- a/firehose.c +++ b/firehose.c @@ -36,22 +36,20 @@ #include #include #include -#include #include #include -#include #include #include #include #include #include -#include #include #include #include #include #include "qdl.h" #include "ufs.h" +#include "oscompat.h" enum { FIREHOSE_ACK = 0, @@ -534,7 +532,10 @@ static int firehose_read_op(struct qdl_device *qdl, struct read_op *read_op, int } left -= chunk_size; +#ifndef _WIN32 + // on mac/linux, every other response is empty expect_empty = true; +#endif } ret = firehose_read(qdl, 10000, firehose_generic_parser, NULL); diff --git a/ks.c b/ks.c index 71ccd07..8ac665e 100644 --- a/ks.c +++ b/ks.c @@ -2,20 +2,22 @@ #include #include #include -#include #include #include #include -#include #include #include #include #include #include -#include #include #include "qdl.h" +#include "oscompat.h" + +#ifdef _WIN32 +const char *__progname = "ks"; +#endif static struct qdl_device qdl; diff --git a/oscompat.c b/oscompat.c new file mode 100644 index 0000000..171a72d --- /dev/null +++ b/oscompat.c @@ -0,0 +1,16 @@ +#include "oscompat.h" + +#ifdef _WIN32 + +const char *__progname = "qdl"; + +void timeradd(const struct timeval *a, const struct timeval *b, struct timeval *result) { + result->tv_sec = a->tv_sec + b->tv_sec; + result->tv_usec = a->tv_usec + b->tv_usec; + if (result->tv_usec >= 1000000) { + result->tv_sec += 1; + result->tv_usec -= 1000000; + } +} + +#endif // _WIN32 \ No newline at end of file diff --git a/oscompat.h b/oscompat.h new file mode 100644 index 0000000..7dea409 --- /dev/null +++ b/oscompat.h @@ -0,0 +1,25 @@ +#ifndef __OSCOMPAT_H__ +#define __OSCOMPAT_H__ + +#ifndef _WIN32 + +#include + +#else // _WIN32 + +#include +#include + +// TODO: improve err functions + +#define err(code, ...) do { ux_err(__VA_ARGS__); exit(code); } while(false) +#define errx(code, ...) do { ux_err(__VA_ARGS__); exit(code); } while(false) +#define warn(...) ux_info(__VA_ARGS__) +#define warnx(...) ux_info(__VA_ARGS__) + + +void timeradd(const struct timeval *a, const struct timeval *b, struct timeval *result); + +#endif + +#endif \ No newline at end of file diff --git a/program.c b/program.c index 9c456c8..6b3358d 100644 --- a/program.c +++ b/program.c @@ -28,6 +28,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ +#define _FILE_OFFSET_BITS 64 #include #include #include diff --git a/qdl.c b/qdl.c index 6c60143..7fa2f85 100644 --- a/qdl.c +++ b/qdl.c @@ -29,7 +29,6 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -#include #include #include #include @@ -42,6 +41,11 @@ #include "qdl.h" #include "patch.h" #include "ufs.h" +#include "oscompat.h" + +#ifdef _WIN32 +const char *__progname = "qdl"; +#endif #define MAX_USBFS_BULK_SIZE (16*1024) diff --git a/ramdump.c b/ramdump.c index 84aca57..89ac984 100644 --- a/ramdump.c +++ b/ramdump.c @@ -5,6 +5,11 @@ #include "qdl.h" +#ifdef _WIN32 +const char *__progname = "ramdump"; +#endif + + bool qdl_debug; static void print_usage(void) diff --git a/sahara.c b/sahara.c index 54ef0a1..dfe6b0d 100644 --- a/sahara.c +++ b/sahara.c @@ -32,20 +32,17 @@ #include #include #include -#include #include #include -#include #include -#include #include #include #include #include #include -#include #include #include "qdl.h" +#include "oscompat.h" #define MIN(x, y) ((x) < (y) ? (x) : (y)) @@ -305,7 +302,7 @@ static int sahara_done(struct qdl_device *qdl, struct sahara_pkt *pkt) static ssize_t sahara_debug64_one(struct qdl_device *qdl, struct sahara_debug_region64 region, - int ramdump_dir) + const char *ramdump_path) { struct sahara_pkt read_req; uint64_t remain; @@ -319,7 +316,10 @@ static ssize_t sahara_debug64_one(struct qdl_device *qdl, if (!buf) return -1; - fd = openat(ramdump_dir, region.filename, O_WRONLY | O_CREAT, 0644); + char path[PATH_MAX]; + snprintf(path, sizeof(path), "%s/%s", ramdump_path, region.filename); + + fd = open(path, O_WRONLY | O_CREAT, 0644); if (fd < 0) { warn("failed to open \"%s\"", region.filename); return -1; @@ -361,6 +361,27 @@ out: return 0; } +// simple pattern matching function supporting * and ? +bool pattern_match(const char *pattern, const char *string) { + if (*pattern == '\0' && *string == '\0') + return true; + + if (*pattern == '*') { + return pattern_match(pattern + 1, string) || + (*string != '\0' && pattern_match(pattern, string + 1)); + } + + if (*pattern == '?') { + return (*string != '\0') && pattern_match(pattern + 1, string + 1); + } + + if (*pattern == *string) { + return pattern_match(pattern + 1, string + 1); + } + + return false; +} + static bool sahara_debug64_filter(const char *filename, const char *filter) { bool anymatch = false; @@ -373,7 +394,7 @@ static bool sahara_debug64_filter(const char *filename, const char *filter) tmp = strdup(filter); for (s = strtok_r(tmp, ",", &ptr); s; s = strtok_r(NULL, ",", &ptr)) { - if (fnmatch(s, filename, 0) == 0) { + if (pattern_match(s, filename)) { anymatch = true; break; } @@ -384,7 +405,7 @@ static bool sahara_debug64_filter(const char *filename, const char *filter) } static void sahara_debug64(struct qdl_device *qdl, struct sahara_pkt *pkt, - int ramdump_dir, const char *filter) + const char *ramdump_path, const char *filter) { struct sahara_debug_region64 *table; struct sahara_pkt read_req; @@ -418,7 +439,8 @@ static void sahara_debug64(struct qdl_device *qdl, struct sahara_pkt *pkt, ux_debug("%-2d: type 0x%" PRIx64 " address: 0x%" PRIx64 " length: 0x%" PRIx64 " region: %s filename: %s\n", i, table[i].type, table[i].addr, table[i].length, table[i].region, table[i].filename); - n = sahara_debug64_one(qdl, table[i], ramdump_dir); + + n = sahara_debug64_one(qdl, table[i], ramdump_path); if (n < 0) break; } @@ -432,18 +454,11 @@ int sahara_run(struct qdl_device *qdl, char *img_arr[], bool single_image, const char *ramdump_path, const char *ramdump_filter) { struct sahara_pkt *pkt; - int ramdump_dir = -1; char buf[4096]; char tmp[32]; bool done = false; int n; - if (ramdump_path) { - ramdump_dir = open(ramdump_path, O_DIRECTORY); - if (ramdump_dir < 0) - err(1, "failed to open directory for ramdump output"); - } - while (!done) { n = qdl_read(qdl, buf, sizeof(buf), 1000); if (n < 0) @@ -473,7 +488,7 @@ int sahara_run(struct qdl_device *qdl, char *img_arr[], bool single_image, done = true; break; case SAHARA_MEM_DEBUG64_CMD: - sahara_debug64(qdl, pkt, ramdump_dir, ramdump_filter); + sahara_debug64(qdl, pkt, ramdump_path, ramdump_filter); break; case SAHARA_READ_DATA64_CMD: sahara_read64(qdl, pkt, img_arr, single_image); @@ -490,8 +505,5 @@ int sahara_run(struct qdl_device *qdl, char *img_arr[], bool single_image, } } - if (ramdump_dir >= 0) - close(ramdump_dir); - return done ? 0 : -1; } diff --git a/usb.c b/usb.c index 38edf58..84fe42e 100644 --- a/usb.c +++ b/usb.c @@ -1,12 +1,11 @@ -#include #include -#include #include #include #include #include #include #include +#include "oscompat.h" #include "qdl.h" diff --git a/ux.c b/ux.c index c12552f..c867e82 100644 --- a/ux.c +++ b/ux.c @@ -1,5 +1,9 @@ #include +#ifdef _WIN32 +#include +#else #include +#endif #include #include @@ -36,6 +40,22 @@ static void ux_clear_line(void) ux_cur_line_length = 0; } +#ifdef _WIN32 + +void ux_init(void) +{ + CONSOLE_SCREEN_BUFFER_INFO csbi; + int columns; + + HANDLE stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE); + if (GetConsoleScreenBufferInfo(stdoutHandle, &csbi)) { + columns = csbi.srWindow.Right - csbi.srWindow.Left + 1; + ux_width = MIN(columns, UX_PROGRESS_SIZE_MAX); + } +} + +#else + void ux_init(void) { struct winsize w; @@ -46,6 +66,8 @@ void ux_init(void) ux_width = MIN(w.ws_col, UX_PROGRESS_SIZE_MAX); } +#endif + void ux_err(const char *fmt, ...) { va_list ap;