diff --git a/tools/fpack.c b/tools/fpack.c index de418d6..929fa58 100644 --- a/tools/fpack.c +++ b/tools/fpack.c @@ -1,58 +1,20 @@ #if !defined(_WIN32) -#define _FILE_OFFSET_BITS 64 #define _POSIX_C_SOURCE 200809L #endif #include "fpk.h" -#include #include #include #include #include #include -#include #ifdef _WIN32 #include -#include #define PROGRAM_NAME "fpack.exe" -#define fpack_fseek64(f, off, whence) _fseeki64((f), (off), (whence)) -#define fpack_ftell64(f) _ftelli64((f)) #else #include #define PROGRAM_NAME "fpack" -#define fpack_fseek64(f, off, whence) fseeko((f), (off_t)(off), (whence)) -#define fpack_ftell64(f) ftello((f)) -#endif - -#ifdef _WIN32 -static wchar_t *utf8_to_wide(const char *s) -{ - int wlen = MultiByteToWideChar(CP_UTF8, 0, s, -1, NULL, 0); - wchar_t *w; - - if (wlen <= 0) - return NULL; - w = malloc((size_t)wlen * sizeof(wchar_t)); - if (!w) - return NULL; - MultiByteToWideChar(CP_UTF8, 0, s, -1, w, wlen); - return w; -} - -static char *wide_to_utf8(const wchar_t *w) -{ - int len = WideCharToMultiByte(CP_UTF8, 0, w, -1, NULL, 0, NULL, NULL); - char *s; - - if (len <= 0) - return NULL; - s = malloc((size_t)len); - if (!s) - return NULL; - WideCharToMultiByte(CP_UTF8, 0, w, -1, s, len, NULL, NULL); - return s; -} #endif static double now_seconds(void) @@ -127,19 +89,6 @@ static char *dup_str(const char *s) return out; } -static char *join_path(const char *dir, const char *name) -{ - size_t dir_len = strlen(dir); - size_t name_len = strlen(name); - char *out = malloc(dir_len + 1 + name_len + 1); - - memcpy(out, dir, dir_len); - out[dir_len] = '/'; - memcpy(out + dir_len + 1, name, name_len); - out[dir_len + 1 + name_len] = '\0'; - return out; -} - #ifdef _WIN32 #define IS_PATH_SEP(c) ((c) == '/' || (c) == '\\') #else @@ -177,94 +126,15 @@ static char *derive_output_name(const char *input_dir) return out; } -static void normalize_path(char *s) +static int on_add(const char *path, uint64_t size, void *ctx) { - for (; *s; s++) { - if (*s == '\\') - *s = '/'; - } -} - -static void *read_file(const char *path, size_t *out_size) -{ - FILE *fp; - int64_t len; - void *buf; -#ifdef _WIN32 - wchar_t *wpath = utf8_to_wide(path); - - if (!wpath) - return NULL; - fp = _wfopen(wpath, L"rb"); - free(wpath); -#else - fp = fopen(path, "rb"); -#endif - if (!fp) - return NULL; - - if (fpack_fseek64(fp, 0, SEEK_END) != 0) { - fclose(fp); - return NULL; - } - len = fpack_ftell64(fp); - if (len < 0 || fpack_fseek64(fp, 0, SEEK_SET) != 0) { - fclose(fp); - return NULL; - } - - buf = malloc((size_t)len); - if (!buf) { - fclose(fp); - return NULL; - } - - if (fread(buf, 1, (size_t)len, fp) != (size_t)len) { - free(buf); - fclose(fp); - return NULL; - } - - fclose(fp); - *out_size = (size_t)len; - return buf; -} - -static int add_file(struct fpk_writer *w, const char *path, size_t base_len) -{ - const char *rel_path = path + base_len; - void *data; - size_t size; - char *norm; - - if (interrupted) - return 0; - - while (*rel_path == '/') - rel_path++; - - norm = dup_str(rel_path); - normalize_path(norm); - - data = read_file(path, &size); - if (!data) { - fprintf(stderr, "fpack: cannot read: %s\n", path); - free(norm); - return 0; - } - - if (fpk_writer_add(w, norm, data, size) != 0) { - fprintf(stderr, "fpack: cannot add: %s\n", norm); - free(data); - free(norm); - return 0; - } + (void)ctx; entry_count++; total_bytes += size; if (flags & FPACK_VERBOSE) - printf(" %s (%lu bytes)\n", norm, (unsigned long)size); + printf(" %s (%lu bytes)\n", path, (unsigned long)size); if (flags & FPACK_PROGRESS) { printf("\rpacked %lu files (%lu bytes)", @@ -272,111 +142,9 @@ static int add_file(struct fpk_writer *w, const char *path, size_t base_len) fflush(stdout); } - free(data); - free(norm); - return 1; + return !interrupted; } -#ifdef _WIN32 -static int add_dir(struct fpk_writer *w, const char *dir, size_t base_len) -{ - char *pattern = join_path(dir, "*"); - wchar_t *wpattern = utf8_to_wide(pattern); - WIN32_FIND_DATAW fd; - HANDLE h; - - free(pattern); - if (!wpattern) { - fprintf(stderr, "fpack: cannot open directory: %s\n", dir); - return 0; - } - - h = FindFirstFileW(wpattern, &fd); - free(wpattern); - if (h == INVALID_HANDLE_VALUE) { - fprintf(stderr, "fpack: cannot open directory: %s\n", dir); - return 0; - } - - do { - char *name = wide_to_utf8(fd.cFileName); - char *path; - - if (!name || name[0] == '.') { - free(name); - continue; - } - - path = join_path(dir, name); - free(name); - - if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - if (!add_dir(w, path, base_len)) { - free(path); - FindClose(h); - return 0; - } - } else if (!add_file(w, path, base_len)) { - free(path); - FindClose(h); - return 0; - } - - free(path); - } while (FindNextFileW(h, &fd)); - - FindClose(h); - return 1; -} -#else -static int add_dir(struct fpk_writer *w, const char *dir, size_t base_len) -{ - DIR *d; - struct dirent *ent; - - d = opendir(dir); - if (!d) { - fprintf(stderr, "fpack: cannot open directory: %s\n", dir); - return 0; - } - - while ((ent = readdir(d)) != NULL) { - char *path; - struct stat st; - - if (ent->d_name[0] == '.') - continue; - - path = join_path(dir, ent->d_name); - - if (stat(path, &st) != 0) { - fprintf(stderr, "fpack: cannot stat: %s\n", path); - free(path); - continue; - } - - if (S_ISDIR(st.st_mode)) { - if (!add_dir(w, path, base_len)) { - free(path); - closedir(d); - return 0; - } - } else if (S_ISREG(st.st_mode)) { - if (!add_file(w, path, base_len)) { - free(path); - closedir(d); - return 0; - } - } - - free(path); - } - - closedir(d); - return 1; -} -#endif - static void usage(void) { fprintf(stderr, "usage: %s [-o output.fpk] [-p] [-q] [-v] input_dir\n", PROGRAM_NAME); @@ -404,7 +172,6 @@ int main(int argc, char **argv) const char *output_arg = NULL; const char *input_dir; char *output; - size_t base_len; struct fpk_writer *w; int c; double start_time; @@ -439,10 +206,6 @@ int main(int argc, char **argv) start_time = now_seconds(); - base_len = strlen(input_dir); - while (base_len > 0 && IS_PATH_SEP(input_dir[base_len - 1])) - base_len--; - w = fpk_writer_open(output); if (!w) { fprintf(stderr, "fpack: cannot create: %s\n", output); @@ -452,7 +215,7 @@ int main(int argc, char **argv) signal(SIGINT, handle_sigint); - if (!add_dir(w, input_dir, base_len)) { + if (fpk_writer_add_dir(w, input_dir, on_add, NULL) != 0) { fpk_writer_close(w); if (interrupted) { remove(output); @@ -460,6 +223,7 @@ int main(int argc, char **argv) free(output); return 130; } + fprintf(stderr, "fpack: failed while packing: %s\n", input_dir); free(output); return 1; }