From cdccc69c62579b0c13b35fad0728079652b8f3c9 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Tue, 31 Jan 2023 11:21:30 +0100 Subject: Move library source into src sub-directory Signed-off-by: David Oberhollenzer --- lib/compat/Makemodule.am | 18 +-- lib/compat/chdir.c | 34 ----- lib/compat/fnmatch.c | 305 --------------------------------------- lib/compat/getopt.c | 96 ------------ lib/compat/getopt_long.c | 95 ------------ lib/compat/getsubopt.c | 27 ---- lib/compat/mockups.c | 51 ------- lib/compat/path_to_windows.c | 43 ------ lib/compat/src/chdir.c | 34 +++++ lib/compat/src/fnmatch.c | 305 +++++++++++++++++++++++++++++++++++++++ lib/compat/src/getopt.c | 96 ++++++++++++ lib/compat/src/getopt_long.c | 95 ++++++++++++ lib/compat/src/getsubopt.c | 27 ++++ lib/compat/src/mockups.c | 51 +++++++ lib/compat/src/path_to_windows.c | 43 ++++++ lib/compat/src/strchrnul.c | 18 +++ lib/compat/src/strndup.c | 31 ++++ lib/compat/src/w32_perror.c | 33 +++++ lib/compat/src/w32_stdio.c | 125 ++++++++++++++++ lib/compat/src/w32_wmain.c | 83 +++++++++++ lib/compat/strchrnul.c | 18 --- lib/compat/strndup.c | 31 ---- lib/compat/w32_perror.c | 33 ----- lib/compat/w32_stdio.c | 125 ---------------- lib/compat/w32_wmain.c | 83 ----------- 25 files changed, 948 insertions(+), 952 deletions(-) delete mode 100644 lib/compat/chdir.c delete mode 100644 lib/compat/fnmatch.c delete mode 100644 lib/compat/getopt.c delete mode 100644 lib/compat/getopt_long.c delete mode 100644 lib/compat/getsubopt.c delete mode 100644 lib/compat/mockups.c delete mode 100644 lib/compat/path_to_windows.c create mode 100644 lib/compat/src/chdir.c create mode 100644 lib/compat/src/fnmatch.c create mode 100644 lib/compat/src/getopt.c create mode 100644 lib/compat/src/getopt_long.c create mode 100644 lib/compat/src/getsubopt.c create mode 100644 lib/compat/src/mockups.c create mode 100644 lib/compat/src/path_to_windows.c create mode 100644 lib/compat/src/strchrnul.c create mode 100644 lib/compat/src/strndup.c create mode 100644 lib/compat/src/w32_perror.c create mode 100644 lib/compat/src/w32_stdio.c create mode 100644 lib/compat/src/w32_wmain.c delete mode 100644 lib/compat/strchrnul.c delete mode 100644 lib/compat/strndup.c delete mode 100644 lib/compat/w32_perror.c delete mode 100644 lib/compat/w32_stdio.c delete mode 100644 lib/compat/w32_wmain.c (limited to 'lib/compat') diff --git a/lib/compat/Makemodule.am b/lib/compat/Makemodule.am index 06fc95e..be9bf8c 100644 --- a/lib/compat/Makemodule.am +++ b/lib/compat/Makemodule.am @@ -1,13 +1,9 @@ -libcompat_a_SOURCES = lib/compat/getsubopt.c -libcompat_a_SOURCES += lib/compat/strndup.c lib/compat/mockups.c -libcompat_a_SOURCES += lib/compat/chdir.c include/compat.h -libcompat_a_SOURCES += lib/compat/path_to_windows.c -libcompat_a_SOURCES += lib/compat/w32_perror.c -libcompat_a_SOURCES += lib/compat/w32_wmain.c -libcompat_a_SOURCES += lib/compat/w32_stdio.c -libcompat_a_SOURCES += lib/compat/fnmatch.c -libcompat_a_SOURCES += lib/compat/getopt.c -libcompat_a_SOURCES += lib/compat/getopt_long.c -libcompat_a_SOURCES += lib/compat/strchrnul.c +libcompat_a_SOURCES = include/compat.h lib/compat/src/getsubopt.c \ + lib/compat/src/strndup.c lib/compat/src/mockups.c \ + lib/compat/src/chdir.c lib/compat/src/path_to_windows.c \ + lib/compat/src/w32_perror.c lib/compat/src/w32_wmain.c \ + lib/compat/src/w32_stdio.c lib/compat/src/fnmatch.c \ + lib/compat/src/getopt.c lib/compat/src/getopt_long.c \ + lib/compat/src/strchrnul.c noinst_LIBRARIES += libcompat.a diff --git a/lib/compat/chdir.c b/lib/compat/chdir.c deleted file mode 100644 index f695e2a..0000000 --- a/lib/compat/chdir.c +++ /dev/null @@ -1,34 +0,0 @@ -/* SPDX-License-Identifier: GPL-3.0-or-later */ -/* - * chdir.c - * - * Copyright (C) 2019 David Oberhollenzer - */ -#include "config.h" -#include "compat.h" - -#ifdef _WIN32 -#include -#include - -int chdir(const char *path) -{ - WCHAR *wpath; - int ret; - - wpath = path_to_windows(path); - if (wpath == NULL) - return -1; - - if (!SetCurrentDirectoryW(wpath)) { - fprintf(stderr, "Switching to directory '%s': %ld\n", - path, GetLastError()); - ret = -1; - } else { - ret = 0; - } - - free(wpath); - return ret; -} -#endif diff --git a/lib/compat/fnmatch.c b/lib/compat/fnmatch.c deleted file mode 100644 index ed4dde1..0000000 --- a/lib/compat/fnmatch.c +++ /dev/null @@ -1,305 +0,0 @@ -/* - * An implementation of what I call the "Sea of Stars" algorithm for - * POSIX fnmatch(). The basic idea is that we factor the pattern into - * a head component (which we match first and can reject without ever - * measuring the length of the string), an optional tail component - * (which only exists if the pattern contains at least one star), and - * an optional "sea of stars", a set of star-separated components - * between the head and tail. After the head and tail matches have - * been removed from the input string, the components in the "sea of - * stars" are matched sequentially by searching for their first - * occurrence past the end of the previous match. - * - * - Rich Felker, April 2012 - */ - -#include "compat.h" - -#include -#include - -#ifndef HAVE_FNMATCH -#define END 0 -#define UNMATCHABLE -2 -#define BRACKET -3 -#define QUESTION -4 -#define STAR -5 - -static int str_next(const char *str, size_t n, size_t *step) -{ - if (!n) { - *step = 0; - return 0; - } - if (str[0] >= 128U) { - wchar_t wc; - int k = mbtowc(&wc, str, n); - if (k<0) { - *step = 1; - return -1; - } - *step = k; - return wc; - } - *step = 1; - return str[0]; -} - -static int pat_next(const char *pat, size_t m, size_t *step) -{ - int esc = 0; - if (!m || !*pat) { - *step = 0; - return END; - } - *step = 1; - if (pat[0]=='\\' && pat[1]) { - *step = 2; - pat++; - esc = 1; - goto escaped; - } - if (pat[0]=='[') { - size_t k = 1; - if (k= 128U) { - wchar_t wc; - int k = mbtowc(&wc, pat, m); - if (k<0) { - *step = 0; - return UNMATCHABLE; - } - *step = k + esc; - return wc; - } - return pat[0]; -} - -static int match_bracket(const char *p, int k, int kfold) -{ - wchar_t wc; - int inv = 0; - p++; - if (*p=='^' || *p=='!') { - inv = 1; - p++; - } - if (*p==']') { - if (k==']') return !inv; - p++; - } else if (*p=='-') { - if (k=='-') return !inv; - p++; - } - wc = p[-1]; - for (; *p != ']'; p++) { - if (p[0]=='-' && p[1]!=']') { - wchar_t wc2; - int l = mbtowc(&wc2, p+1, 4); - if (l < 0) return 0; - if (wc <= wc2) - if ((unsigned)k-wc <= wc2-wc || - (unsigned)kfold-wc <= wc2-wc) - return !inv; - p += l-1; - continue; - } - if (p[0]=='[' && (p[1]==':' || p[1]=='.' || p[1]=='=')) { - const char *p0 = p+2; - int z = p[1]; - p+=3; - while (p[-1]!=z || p[0]!=']') p++; - if (z == ':' && p-1-p0 < 16) { - char buf[16]; - memcpy(buf, p0, p-1-p0); - buf[p-1-p0] = 0; - if (iswctype(k, wctype(buf)) || - iswctype(kfold, wctype(buf))) - return !inv; - } - continue; - } - if (*p < 128U) { - wc = (unsigned char)*p; - } else { - int l = mbtowc(&wc, p, 4); - if (l < 0) return 0; - p += l-1; - } - if (wc==k || wc==kfold) return !inv; - } - return inv; -} - -static int fnmatch_internal(const char *pat, size_t m, const char *str, size_t n) -{ - const char *p, *ptail, *endpat; - const char *s, *stail, *endstr; - size_t pinc, sinc, tailcnt=0; - int c, k, kfold; - - for (;;) { - switch ((c = pat_next(pat, m, &pinc))) { - case UNMATCHABLE: - return FNM_NOMATCH; - case STAR: - pat++; - m--; - break; - default: - k = str_next(str, n, &sinc); - if (k <= 0) - return (c==END) ? 0 : FNM_NOMATCH; - str += sinc; - n -= sinc; - kfold = k; - if (c == BRACKET) { - if (!match_bracket(pat, k, kfold)) - return FNM_NOMATCH; - } else if (c != QUESTION && k != c && kfold != c) { - return FNM_NOMATCH; - } - pat+=pinc; - m-=pinc; - continue; - } - break; - } - - /* Compute real pat length if it was initially unknown/-1 */ - m = strnlen(pat, m); - endpat = pat + m; - - /* Find the last * in pat and count chars needed after it */ - for (p=ptail=pat; pstr && tailcnt; tailcnt--) { - if (s[-1] < 128U || MB_CUR_MAX==1) s--; - else while ((unsigned char)*--s-0x80U<0x40 && s>str); - } - if (tailcnt) return FNM_NOMATCH; - stail = s; - - /* Check that the pat and str tails match */ - p = ptail; - for (;;) { - c = pat_next(p, endpat-p, &pinc); - p += pinc; - if ((k = str_next(s, endstr-s, &sinc)) <= 0) { - if (c != END) return FNM_NOMATCH; - break; - } - s += sinc; - kfold = k; - if (c == BRACKET) { - if (!match_bracket(p-pinc, k, kfold)) - return FNM_NOMATCH; - } else if (c != QUESTION && k != c && kfold != c) { - return FNM_NOMATCH; - } - } - - /* We're all done with the tails now, so throw them out */ - endstr = stail; - endpat = ptail; - - /* Match pattern components until there are none left */ - while (pat 0) str += sinc; - else for (str++; str_next(str, endstr-str, &sinc)<0; str++); - } - - return 0; -} - -int fnmatch(const char *pat, const char *str, int flags) -{ - const char *s, *p; - size_t inc; - int c; - if (flags & FNM_PATHNAME) for (;;) { - for (s=str; *s && *s!='/'; s++); - for (p=pat; (c=pat_next(p, -1, &inc))!=END && c!='/'; p+=inc); - if (c!=*s) - return FNM_NOMATCH; - if (fnmatch_internal(pat, p-pat, str, s-str)) - return FNM_NOMATCH; - if (!c) return 0; - str = s+1; - pat = p+inc; - } - return fnmatch_internal(pat, -1, str, -1); -} -#endif /* HAVE_FNMATCH */ diff --git a/lib/compat/getopt.c b/lib/compat/getopt.c deleted file mode 100644 index 9876a87..0000000 --- a/lib/compat/getopt.c +++ /dev/null @@ -1,96 +0,0 @@ -#include "compat.h" - -#include -#include -#include -#include - -#ifndef HAVE_GETOPT -char *optarg; -int optind=1, opterr=1, optopt, optpos, optreset=0; - -void __getopt_msg(const char *a, const char *b, const char *c, size_t l) -{ - fputs(a, stderr); - fwrite(b, strlen(b), 1, stderr); - fwrite(c, 1, l, stderr); - putc('\n', stderr); -} - -int getopt(int argc, char * const argv[], const char *optstring) -{ - int i; - wchar_t c, d; - int k, l; - char *optchar; - - if (!optind || __optreset) { - optreset = 0; - optpos = 0; - optind = 1; - } - - if (optind >= argc || !argv[optind]) - return -1; - - if (argv[optind][0] != '-') { - if (optstring[0] == '-') { - optarg = argv[optind++]; - return 1; - } - return -1; - } - - if (!argv[optind][1]) - return -1; - - if (argv[optind][1] == '-' && !argv[optind][2]) - return optind++, -1; - - if (!optpos) optpos++; - if ((k = mbtowc(&c, argv[optind]+optpos, MB_LEN_MAX)) < 0) { - k = 1; - c = 0xfffd; /* replacement char */ - } - optchar = argv[optind]+optpos; - optpos += k; - - if (!argv[optind][optpos]) { - optind++; - optpos = 0; - } - - if (optstring[0] == '-' || optstring[0] == '+') - optstring++; - - i = 0; - d = 0; - do { - l = mbtowc(&d, optstring+i, MB_LEN_MAX); - if (l>0) i+=l; else i++; - } while (l && d != c); - - if (d != c || c == ':') { - optopt = c; - if (optstring[0] != ':' && opterr) - __getopt_msg(argv[0], ": unrecognized option: ", optchar, k); - return '?'; - } - if (optstring[i] == ':') { - optarg = 0; - if (optstring[i+1] != ':' || optpos) { - optarg = argv[optind++] + optpos; - optpos = 0; - } - if (optind > argc) { - optopt = c; - if (optstring[0] == ':') return ':'; - if (opterr) __getopt_msg(argv[0], - ": option requires an argument: ", - optchar, k); - return '?'; - } - } - return c; -} -#endif diff --git a/lib/compat/getopt_long.c b/lib/compat/getopt_long.c deleted file mode 100644 index 58354c3..0000000 --- a/lib/compat/getopt_long.c +++ /dev/null @@ -1,95 +0,0 @@ -#include "compat.h" - -#include -#include -#include -#include -#include -#include - -#ifndef HAVE_GETOPT_LONG -static void permute(char *const *argv, int dest, int src) -{ - char **av = (char **)argv; - char *tmp = av[src]; - int i; - for (i=src; i>dest; i--) - av[i] = av[i-1]; - av[dest] = tmp; -} - -int getopt_long(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx) -{ - optarg = 0; - if (longopts && argv[optind][0] == '-' && - (argv[optind][1] == '-' && argv[optind][2])) - { - int colon = optstring[optstring[0]=='+'||optstring[0]=='-']==':'; - int i, cnt, match; - char *arg, *opt, *start = argv[optind]+1; - for (cnt=i=0; longopts[i].name; i++) { - const char *name = longopts[i].name; - opt = start; - if (*opt == '-') opt++; - while (*opt && *opt != '=' && *opt == *name) - name++, opt++; - if (*opt && *opt != '=') continue; - arg = opt; - match = i; - if (!*name) { - cnt = 1; - break; - } - cnt++; - } - if (cnt==1) { - i = match; - opt = arg; - optind++; - if (*opt == '=') { - if (!longopts[i].has_arg) { - optopt = longopts[i].val; - if (colon || !opterr) - return '?'; - __getopt_msg(argv[0], - ": option does not take an argument: ", - longopts[i].name, - strlen(longopts[i].name)); - return '?'; - } - optarg = opt+1; - } else if (longopts[i].has_arg == required_argument) { - if (!(optarg = argv[optind])) { - optopt = longopts[i].val; - if (colon) return ':'; - if (!opterr) return '?'; - __getopt_msg(argv[0], - ": option requires an argument: ", - longopts[i].name, - strlen(longopts[i].name)); - return '?'; - } - optind++; - } - if (idx) *idx = i; - if (longopts[i].flag) { - *longopts[i].flag = longopts[i].val; - return 0; - } - return longopts[i].val; - } - if (argv[optind][1] == '-') { - optopt = 0; - if (!colon && opterr) - __getopt_msg(argv[0], cnt ? - ": option is ambiguous: " : - ": unrecognized option: ", - argv[optind]+2, - strlen(argv[optind]+2)); - optind++; - return '?'; - } - } - return getopt(argc, argv, optstring); -} -#endif diff --git a/lib/compat/getsubopt.c b/lib/compat/getsubopt.c deleted file mode 100644 index e6fea1a..0000000 --- a/lib/compat/getsubopt.c +++ /dev/null @@ -1,27 +0,0 @@ -#include "compat.h" - -#include -#include - -#ifndef HAVE_GETSUBOPT -int getsubopt(char **opt, char *const *keys, char **val) -{ - char *s = *opt; - int i; - - *val = NULL; - *opt = strchr(s, ','); - if (*opt) *(*opt)++ = 0; - else *opt = s + strlen(s); - - for (i=0; keys[i]; i++) { - size_t l = strlen(keys[i]); - if (strncmp(keys[i], s, l)) continue; - if (s[l] == '=') - *val = s + l + 1; - else if (s[l]) continue; - return i; - } - return -1; -} -#endif diff --git a/lib/compat/mockups.c b/lib/compat/mockups.c deleted file mode 100644 index 4c396ec..0000000 --- a/lib/compat/mockups.c +++ /dev/null @@ -1,51 +0,0 @@ -/* SPDX-License-Identifier: GPL-3.0-or-later */ -/* - * mockups.c - * - * Copyright (C) 2019 David Oberhollenzer - */ -#include "config.h" -#include "compat.h" - -#include - -#ifdef _WIN32 -int fchownat(int dirfd, const char *path, int uid, int gid, int flags) -{ - if (dirfd != AT_FDCWD) { - fputs("[FIXME] fchownat stub only supports AT_FDCWD!\n", - stderr); - return -1; - } - - if (flags != 0 && flags != AT_SYMLINK_NOFOLLOW) { - fputs("[FIXME] fchownat stub used with an unknown flag!\n", - stderr); - return -1; - } - - (void)path; - (void)uid; - (void)gid; - return 0; -} - -int fchmodat(int dirfd, const char *path, int mode, int flags) -{ - if (dirfd != AT_FDCWD) { - fputs("[FIXME] fchmodat stub only supports AT_FDCWD!\n", - stderr); - return -1; - } - - if (flags != 0 && flags != AT_SYMLINK_NOFOLLOW) { - fputs("[FIXME] fchmodat stub used with an unknown flag!\n", - stderr); - return -1; - } - - (void)path; - (void)mode; - return 0; -} -#endif diff --git a/lib/compat/path_to_windows.c b/lib/compat/path_to_windows.c deleted file mode 100644 index ff3a5d2..0000000 --- a/lib/compat/path_to_windows.c +++ /dev/null @@ -1,43 +0,0 @@ -/* SPDX-License-Identifier: GPL-3.0-or-later */ -/* - * path_to_windows.c - * - * Copyright (C) 2019 David Oberhollenzer - */ -#include "config.h" -#include "compat.h" - -#include -#include - -#if defined(_WIN32) || defined(__WINDOWS__) -WCHAR *path_to_windows(const char *input) -{ - WCHAR *wpath, *ptr; - DWORD length; - - length = MultiByteToWideChar(CP_UTF8, 0, input, -1, NULL, 0); - if (length <= 0) { - fprintf(stderr, "Converting UTF-8 path to UTF-16: %ld\n", - GetLastError()); - return NULL; - } - - wpath = calloc(sizeof(wpath[0]), length + 1); - if (wpath == NULL) { - fprintf(stderr, - "Converting UTF-8 path to UTF-16: out of memory\n"); - return NULL; - } - - MultiByteToWideChar(CP_UTF8, 0, input, -1, wpath, length + 1); - wpath[length] = '\0'; - - for (ptr = wpath; *ptr != '\0'; ++ptr) { - if (*ptr == '/') - *ptr = '\\'; - } - - return wpath; -} -#endif diff --git a/lib/compat/src/chdir.c b/lib/compat/src/chdir.c new file mode 100644 index 0000000..f695e2a --- /dev/null +++ b/lib/compat/src/chdir.c @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * chdir.c + * + * Copyright (C) 2019 David Oberhollenzer + */ +#include "config.h" +#include "compat.h" + +#ifdef _WIN32 +#include +#include + +int chdir(const char *path) +{ + WCHAR *wpath; + int ret; + + wpath = path_to_windows(path); + if (wpath == NULL) + return -1; + + if (!SetCurrentDirectoryW(wpath)) { + fprintf(stderr, "Switching to directory '%s': %ld\n", + path, GetLastError()); + ret = -1; + } else { + ret = 0; + } + + free(wpath); + return ret; +} +#endif diff --git a/lib/compat/src/fnmatch.c b/lib/compat/src/fnmatch.c new file mode 100644 index 0000000..ed4dde1 --- /dev/null +++ b/lib/compat/src/fnmatch.c @@ -0,0 +1,305 @@ +/* + * An implementation of what I call the "Sea of Stars" algorithm for + * POSIX fnmatch(). The basic idea is that we factor the pattern into + * a head component (which we match first and can reject without ever + * measuring the length of the string), an optional tail component + * (which only exists if the pattern contains at least one star), and + * an optional "sea of stars", a set of star-separated components + * between the head and tail. After the head and tail matches have + * been removed from the input string, the components in the "sea of + * stars" are matched sequentially by searching for their first + * occurrence past the end of the previous match. + * + * - Rich Felker, April 2012 + */ + +#include "compat.h" + +#include +#include + +#ifndef HAVE_FNMATCH +#define END 0 +#define UNMATCHABLE -2 +#define BRACKET -3 +#define QUESTION -4 +#define STAR -5 + +static int str_next(const char *str, size_t n, size_t *step) +{ + if (!n) { + *step = 0; + return 0; + } + if (str[0] >= 128U) { + wchar_t wc; + int k = mbtowc(&wc, str, n); + if (k<0) { + *step = 1; + return -1; + } + *step = k; + return wc; + } + *step = 1; + return str[0]; +} + +static int pat_next(const char *pat, size_t m, size_t *step) +{ + int esc = 0; + if (!m || !*pat) { + *step = 0; + return END; + } + *step = 1; + if (pat[0]=='\\' && pat[1]) { + *step = 2; + pat++; + esc = 1; + goto escaped; + } + if (pat[0]=='[') { + size_t k = 1; + if (k= 128U) { + wchar_t wc; + int k = mbtowc(&wc, pat, m); + if (k<0) { + *step = 0; + return UNMATCHABLE; + } + *step = k + esc; + return wc; + } + return pat[0]; +} + +static int match_bracket(const char *p, int k, int kfold) +{ + wchar_t wc; + int inv = 0; + p++; + if (*p=='^' || *p=='!') { + inv = 1; + p++; + } + if (*p==']') { + if (k==']') return !inv; + p++; + } else if (*p=='-') { + if (k=='-') return !inv; + p++; + } + wc = p[-1]; + for (; *p != ']'; p++) { + if (p[0]=='-' && p[1]!=']') { + wchar_t wc2; + int l = mbtowc(&wc2, p+1, 4); + if (l < 0) return 0; + if (wc <= wc2) + if ((unsigned)k-wc <= wc2-wc || + (unsigned)kfold-wc <= wc2-wc) + return !inv; + p += l-1; + continue; + } + if (p[0]=='[' && (p[1]==':' || p[1]=='.' || p[1]=='=')) { + const char *p0 = p+2; + int z = p[1]; + p+=3; + while (p[-1]!=z || p[0]!=']') p++; + if (z == ':' && p-1-p0 < 16) { + char buf[16]; + memcpy(buf, p0, p-1-p0); + buf[p-1-p0] = 0; + if (iswctype(k, wctype(buf)) || + iswctype(kfold, wctype(buf))) + return !inv; + } + continue; + } + if (*p < 128U) { + wc = (unsigned char)*p; + } else { + int l = mbtowc(&wc, p, 4); + if (l < 0) return 0; + p += l-1; + } + if (wc==k || wc==kfold) return !inv; + } + return inv; +} + +static int fnmatch_internal(const char *pat, size_t m, const char *str, size_t n) +{ + const char *p, *ptail, *endpat; + const char *s, *stail, *endstr; + size_t pinc, sinc, tailcnt=0; + int c, k, kfold; + + for (;;) { + switch ((c = pat_next(pat, m, &pinc))) { + case UNMATCHABLE: + return FNM_NOMATCH; + case STAR: + pat++; + m--; + break; + default: + k = str_next(str, n, &sinc); + if (k <= 0) + return (c==END) ? 0 : FNM_NOMATCH; + str += sinc; + n -= sinc; + kfold = k; + if (c == BRACKET) { + if (!match_bracket(pat, k, kfold)) + return FNM_NOMATCH; + } else if (c != QUESTION && k != c && kfold != c) { + return FNM_NOMATCH; + } + pat+=pinc; + m-=pinc; + continue; + } + break; + } + + /* Compute real pat length if it was initially unknown/-1 */ + m = strnlen(pat, m); + endpat = pat + m; + + /* Find the last * in pat and count chars needed after it */ + for (p=ptail=pat; pstr && tailcnt; tailcnt--) { + if (s[-1] < 128U || MB_CUR_MAX==1) s--; + else while ((unsigned char)*--s-0x80U<0x40 && s>str); + } + if (tailcnt) return FNM_NOMATCH; + stail = s; + + /* Check that the pat and str tails match */ + p = ptail; + for (;;) { + c = pat_next(p, endpat-p, &pinc); + p += pinc; + if ((k = str_next(s, endstr-s, &sinc)) <= 0) { + if (c != END) return FNM_NOMATCH; + break; + } + s += sinc; + kfold = k; + if (c == BRACKET) { + if (!match_bracket(p-pinc, k, kfold)) + return FNM_NOMATCH; + } else if (c != QUESTION && k != c && kfold != c) { + return FNM_NOMATCH; + } + } + + /* We're all done with the tails now, so throw them out */ + endstr = stail; + endpat = ptail; + + /* Match pattern components until there are none left */ + while (pat 0) str += sinc; + else for (str++; str_next(str, endstr-str, &sinc)<0; str++); + } + + return 0; +} + +int fnmatch(const char *pat, const char *str, int flags) +{ + const char *s, *p; + size_t inc; + int c; + if (flags & FNM_PATHNAME) for (;;) { + for (s=str; *s && *s!='/'; s++); + for (p=pat; (c=pat_next(p, -1, &inc))!=END && c!='/'; p+=inc); + if (c!=*s) + return FNM_NOMATCH; + if (fnmatch_internal(pat, p-pat, str, s-str)) + return FNM_NOMATCH; + if (!c) return 0; + str = s+1; + pat = p+inc; + } + return fnmatch_internal(pat, -1, str, -1); +} +#endif /* HAVE_FNMATCH */ diff --git a/lib/compat/src/getopt.c b/lib/compat/src/getopt.c new file mode 100644 index 0000000..9876a87 --- /dev/null +++ b/lib/compat/src/getopt.c @@ -0,0 +1,96 @@ +#include "compat.h" + +#include +#include +#include +#include + +#ifndef HAVE_GETOPT +char *optarg; +int optind=1, opterr=1, optopt, optpos, optreset=0; + +void __getopt_msg(const char *a, const char *b, const char *c, size_t l) +{ + fputs(a, stderr); + fwrite(b, strlen(b), 1, stderr); + fwrite(c, 1, l, stderr); + putc('\n', stderr); +} + +int getopt(int argc, char * const argv[], const char *optstring) +{ + int i; + wchar_t c, d; + int k, l; + char *optchar; + + if (!optind || __optreset) { + optreset = 0; + optpos = 0; + optind = 1; + } + + if (optind >= argc || !argv[optind]) + return -1; + + if (argv[optind][0] != '-') { + if (optstring[0] == '-') { + optarg = argv[optind++]; + return 1; + } + return -1; + } + + if (!argv[optind][1]) + return -1; + + if (argv[optind][1] == '-' && !argv[optind][2]) + return optind++, -1; + + if (!optpos) optpos++; + if ((k = mbtowc(&c, argv[optind]+optpos, MB_LEN_MAX)) < 0) { + k = 1; + c = 0xfffd; /* replacement char */ + } + optchar = argv[optind]+optpos; + optpos += k; + + if (!argv[optind][optpos]) { + optind++; + optpos = 0; + } + + if (optstring[0] == '-' || optstring[0] == '+') + optstring++; + + i = 0; + d = 0; + do { + l = mbtowc(&d, optstring+i, MB_LEN_MAX); + if (l>0) i+=l; else i++; + } while (l && d != c); + + if (d != c || c == ':') { + optopt = c; + if (optstring[0] != ':' && opterr) + __getopt_msg(argv[0], ": unrecognized option: ", optchar, k); + return '?'; + } + if (optstring[i] == ':') { + optarg = 0; + if (optstring[i+1] != ':' || optpos) { + optarg = argv[optind++] + optpos; + optpos = 0; + } + if (optind > argc) { + optopt = c; + if (optstring[0] == ':') return ':'; + if (opterr) __getopt_msg(argv[0], + ": option requires an argument: ", + optchar, k); + return '?'; + } + } + return c; +} +#endif diff --git a/lib/compat/src/getopt_long.c b/lib/compat/src/getopt_long.c new file mode 100644 index 0000000..58354c3 --- /dev/null +++ b/lib/compat/src/getopt_long.c @@ -0,0 +1,95 @@ +#include "compat.h" + +#include +#include +#include +#include +#include +#include + +#ifndef HAVE_GETOPT_LONG +static void permute(char *const *argv, int dest, int src) +{ + char **av = (char **)argv; + char *tmp = av[src]; + int i; + for (i=src; i>dest; i--) + av[i] = av[i-1]; + av[dest] = tmp; +} + +int getopt_long(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx) +{ + optarg = 0; + if (longopts && argv[optind][0] == '-' && + (argv[optind][1] == '-' && argv[optind][2])) + { + int colon = optstring[optstring[0]=='+'||optstring[0]=='-']==':'; + int i, cnt, match; + char *arg, *opt, *start = argv[optind]+1; + for (cnt=i=0; longopts[i].name; i++) { + const char *name = longopts[i].name; + opt = start; + if (*opt == '-') opt++; + while (*opt && *opt != '=' && *opt == *name) + name++, opt++; + if (*opt && *opt != '=') continue; + arg = opt; + match = i; + if (!*name) { + cnt = 1; + break; + } + cnt++; + } + if (cnt==1) { + i = match; + opt = arg; + optind++; + if (*opt == '=') { + if (!longopts[i].has_arg) { + optopt = longopts[i].val; + if (colon || !opterr) + return '?'; + __getopt_msg(argv[0], + ": option does not take an argument: ", + longopts[i].name, + strlen(longopts[i].name)); + return '?'; + } + optarg = opt+1; + } else if (longopts[i].has_arg == required_argument) { + if (!(optarg = argv[optind])) { + optopt = longopts[i].val; + if (colon) return ':'; + if (!opterr) return '?'; + __getopt_msg(argv[0], + ": option requires an argument: ", + longopts[i].name, + strlen(longopts[i].name)); + return '?'; + } + optind++; + } + if (idx) *idx = i; + if (longopts[i].flag) { + *longopts[i].flag = longopts[i].val; + return 0; + } + return longopts[i].val; + } + if (argv[optind][1] == '-') { + optopt = 0; + if (!colon && opterr) + __getopt_msg(argv[0], cnt ? + ": option is ambiguous: " : + ": unrecognized option: ", + argv[optind]+2, + strlen(argv[optind]+2)); + optind++; + return '?'; + } + } + return getopt(argc, argv, optstring); +} +#endif diff --git a/lib/compat/src/getsubopt.c b/lib/compat/src/getsubopt.c new file mode 100644 index 0000000..e6fea1a --- /dev/null +++ b/lib/compat/src/getsubopt.c @@ -0,0 +1,27 @@ +#include "compat.h" + +#include +#include + +#ifndef HAVE_GETSUBOPT +int getsubopt(char **opt, char *const *keys, char **val) +{ + char *s = *opt; + int i; + + *val = NULL; + *opt = strchr(s, ','); + if (*opt) *(*opt)++ = 0; + else *opt = s + strlen(s); + + for (i=0; keys[i]; i++) { + size_t l = strlen(keys[i]); + if (strncmp(keys[i], s, l)) continue; + if (s[l] == '=') + *val = s + l + 1; + else if (s[l]) continue; + return i; + } + return -1; +} +#endif diff --git a/lib/compat/src/mockups.c b/lib/compat/src/mockups.c new file mode 100644 index 0000000..4c396ec --- /dev/null +++ b/lib/compat/src/mockups.c @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * mockups.c + * + * Copyright (C) 2019 David Oberhollenzer + */ +#include "config.h" +#include "compat.h" + +#include + +#ifdef _WIN32 +int fchownat(int dirfd, const char *path, int uid, int gid, int flags) +{ + if (dirfd != AT_FDCWD) { + fputs("[FIXME] fchownat stub only supports AT_FDCWD!\n", + stderr); + return -1; + } + + if (flags != 0 && flags != AT_SYMLINK_NOFOLLOW) { + fputs("[FIXME] fchownat stub used with an unknown flag!\n", + stderr); + return -1; + } + + (void)path; + (void)uid; + (void)gid; + return 0; +} + +int fchmodat(int dirfd, const char *path, int mode, int flags) +{ + if (dirfd != AT_FDCWD) { + fputs("[FIXME] fchmodat stub only supports AT_FDCWD!\n", + stderr); + return -1; + } + + if (flags != 0 && flags != AT_SYMLINK_NOFOLLOW) { + fputs("[FIXME] fchmodat stub used with an unknown flag!\n", + stderr); + return -1; + } + + (void)path; + (void)mode; + return 0; +} +#endif diff --git a/lib/compat/src/path_to_windows.c b/lib/compat/src/path_to_windows.c new file mode 100644 index 0000000..ff3a5d2 --- /dev/null +++ b/lib/compat/src/path_to_windows.c @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * path_to_windows.c + * + * Copyright (C) 2019 David Oberhollenzer + */ +#include "config.h" +#include "compat.h" + +#include +#include + +#if defined(_WIN32) || defined(__WINDOWS__) +WCHAR *path_to_windows(const char *input) +{ + WCHAR *wpath, *ptr; + DWORD length; + + length = MultiByteToWideChar(CP_UTF8, 0, input, -1, NULL, 0); + if (length <= 0) { + fprintf(stderr, "Converting UTF-8 path to UTF-16: %ld\n", + GetLastError()); + return NULL; + } + + wpath = calloc(sizeof(wpath[0]), length + 1); + if (wpath == NULL) { + fprintf(stderr, + "Converting UTF-8 path to UTF-16: out of memory\n"); + return NULL; + } + + MultiByteToWideChar(CP_UTF8, 0, input, -1, wpath, length + 1); + wpath[length] = '\0'; + + for (ptr = wpath; *ptr != '\0'; ++ptr) { + if (*ptr == '/') + *ptr = '\\'; + } + + return wpath; +} +#endif diff --git a/lib/compat/src/strchrnul.c b/lib/compat/src/strchrnul.c new file mode 100644 index 0000000..7296060 --- /dev/null +++ b/lib/compat/src/strchrnul.c @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: LGPL-3.0-or-later */ +/* + * strchrnul.c + * + * Copyright (C) 2019 David Oberhollenzer + */ +#include "config.h" +#include "compat.h" + +#ifndef HAVE_STRCHRNUL +char *strchrnul(const char *s, int c) +{ + while (*s && *((unsigned char *)s) != c) + ++s; + + return (char *)s; +} +#endif diff --git a/lib/compat/src/strndup.c b/lib/compat/src/strndup.c new file mode 100644 index 0000000..7e77f6c --- /dev/null +++ b/lib/compat/src/strndup.c @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: LGPL-3.0-or-later */ +/* + * strndup.c + * + * Copyright (C) 2019 David Oberhollenzer + */ +#include "config.h" +#include "compat.h" + +#include +#include + +#ifndef HAVE_STRNDUP +char *strndup(const char *str, size_t max_len) +{ + size_t len = 0; + char *out; + + while (len < max_len && str[len] != '\0') + ++len; + + out = malloc(len + 1); + + if (out != NULL) { + memcpy(out, str, len); + out[len] = '\0'; + } + + return out; +} +#endif diff --git a/lib/compat/src/w32_perror.c b/lib/compat/src/w32_perror.c new file mode 100644 index 0000000..8c84191 --- /dev/null +++ b/lib/compat/src/w32_perror.c @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * w32_perror.c + * + * Copyright (C) 2019 David Oberhollenzer + */ +#include "config.h" +#include "compat.h" + +#include + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include + +void w32_perror(const char *str) +{ + DWORD nStatus = GetLastError(); + LPVOID msg = NULL; + + FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, nStatus, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR)&msg, 0, NULL); + + fprintf(stderr, "%s: %s\n", str, (const char *)msg); + + if (msg != NULL) + LocalFree(msg); +} +#endif diff --git a/lib/compat/src/w32_stdio.c b/lib/compat/src/w32_stdio.c new file mode 100644 index 0000000..c7f68d0 --- /dev/null +++ b/lib/compat/src/w32_stdio.c @@ -0,0 +1,125 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * w32_stdio.c + * + * Copyright (C) 2021 David Oberhollenzer + */ +#include "config.h" +#include "compat.h" + +#include +#include + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#include + +#undef fputc +#undef putc +#undef fputs +#undef fprintf +#undef printf + +static HANDLE get_handle(FILE *strm) +{ + if (strm != stdout && strm != stderr) + return INVALID_HANDLE_VALUE; + + return GetStdHandle(strm == stderr ? + STD_ERROR_HANDLE : STD_OUTPUT_HANDLE); +} + +static BOOL isatty(HANDLE hnd) +{ + if (hnd == INVALID_HANDLE_VALUE) + return FALSE; + + return (GetFileType(hnd) == FILE_TYPE_CHAR); +} + +int sqfs_tools_fputs(const char *str, FILE *strm) +{ + DWORD length; + WCHAR *wstr; + HANDLE hnd; + int ret; + + hnd = get_handle(strm); + if (!isatty(hnd)) + return fputs(str, strm); + + length = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0); + if (length <= 0) + return EOF; + + wstr = calloc(sizeof(wstr[0]), length); + if (wstr == NULL) + return EOF; + + MultiByteToWideChar(CP_UTF8, 0, str, -1, wstr, length); + + ret = WriteConsoleW(hnd, wstr, length, NULL, NULL) ? length : EOF; + + free(wstr); + return ret; +} + +int sqfs_tools_fputc(int c, FILE *strm) +{ + char str[2]; + + str[0] = c; + str[1] = '\0'; + + return sqfs_tools_fputs(str, strm); +} + +static int sqfs_printf_common(FILE *out, const char *fmt, va_list ap) +{ + int ret, len; + char *str; + + len = _vscprintf(fmt, ap); + if (len == -1) + return -1; + + str = malloc((size_t)len + 1); + if (str == NULL) + return -1; + + ret = vsprintf(str, fmt, ap); + if (ret == -1) { + free(str); + return -1; + } + + if (sqfs_tools_fputs(str, out) == EOF) + ret = -1; + + free(str); + return ret; +} + +int sqfs_tools_printf(const char *fmt, ...) +{ + va_list ap; + int ret; + + va_start(ap, fmt); + ret = sqfs_printf_common(stdout, fmt, ap); + va_end(ap); + return ret; +} + +int sqfs_tools_fprintf(FILE *strm, const char *fmt, ...) +{ + va_list ap; + int ret; + + va_start(ap, fmt); + ret = sqfs_printf_common(strm, fmt, ap); + va_end(ap); + return ret; +} +#endif diff --git a/lib/compat/src/w32_wmain.c b/lib/compat/src/w32_wmain.c new file mode 100644 index 0000000..9b3e354 --- /dev/null +++ b/lib/compat/src/w32_wmain.c @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * w32_wmain.c + * + * Copyright (C) 2021 David Oberhollenzer + */ +#include "config.h" +#include "compat.h" + +#include +#include + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#include + +#undef main + +int main(int argc, char **argv) +{ + WCHAR *cmdline, **argList; + int i, ret, utf8_argc; + char **utf8_argv; + (void)argc; + (void)argv; + + /* get the UTF-16 encoded command line arguments */ + cmdline = GetCommandLineW(); + argList = CommandLineToArgvW(cmdline, &utf8_argc); + if (argList == NULL) + goto fail_oom; + + /* convert to UTF-8 */ + utf8_argv = calloc(sizeof(utf8_argv[0]), utf8_argc); + if (utf8_argv == NULL) + goto fail_oom; + + for (i = 0; i < utf8_argc; ++i) { + DWORD length = WideCharToMultiByte(CP_UTF8, 0, argList[i], + -1, NULL, 0, NULL, NULL); + if (length <= 0) + goto fail_conv; + + utf8_argv[i] = calloc(1, length + 1); + if (utf8_argv[i] == NULL) + goto fail_oom; + + WideCharToMultiByte(CP_UTF8, 0, argList[i], -1, + utf8_argv[i], length + 1, NULL, NULL); + utf8_argv[i][length] = '\0'; + } + + LocalFree(argList); + argList = NULL; + + /* call the actual main function */ + ret = sqfs_tools_main(utf8_argc, utf8_argv); + + /* cleanup */ + for (i = 0; i < utf8_argc; ++i) + free(utf8_argv[i]); + + free(utf8_argv); + return ret; +fail_conv: + w32_perror("Converting UTF-16 argument to UTF-8"); + goto fail; +fail_oom: + fputs("out of memory\n", stderr); + goto fail; +fail: + if (utf8_argv != NULL) { + for (i = 0; i < utf8_argc; ++i) + free(utf8_argv[i]); + free(utf8_argv); + } + if (argList != NULL) { + LocalFree(argList); + } + return EXIT_FAILURE; +} +#endif diff --git a/lib/compat/strchrnul.c b/lib/compat/strchrnul.c deleted file mode 100644 index 7296060..0000000 --- a/lib/compat/strchrnul.c +++ /dev/null @@ -1,18 +0,0 @@ -/* SPDX-License-Identifier: LGPL-3.0-or-later */ -/* - * strchrnul.c - * - * Copyright (C) 2019 David Oberhollenzer - */ -#include "config.h" -#include "compat.h" - -#ifndef HAVE_STRCHRNUL -char *strchrnul(const char *s, int c) -{ - while (*s && *((unsigned char *)s) != c) - ++s; - - return (char *)s; -} -#endif diff --git a/lib/compat/strndup.c b/lib/compat/strndup.c deleted file mode 100644 index 7e77f6c..0000000 --- a/lib/compat/strndup.c +++ /dev/null @@ -1,31 +0,0 @@ -/* SPDX-License-Identifier: LGPL-3.0-or-later */ -/* - * strndup.c - * - * Copyright (C) 2019 David Oberhollenzer - */ -#include "config.h" -#include "compat.h" - -#include -#include - -#ifndef HAVE_STRNDUP -char *strndup(const char *str, size_t max_len) -{ - size_t len = 0; - char *out; - - while (len < max_len && str[len] != '\0') - ++len; - - out = malloc(len + 1); - - if (out != NULL) { - memcpy(out, str, len); - out[len] = '\0'; - } - - return out; -} -#endif diff --git a/lib/compat/w32_perror.c b/lib/compat/w32_perror.c deleted file mode 100644 index 8c84191..0000000 --- a/lib/compat/w32_perror.c +++ /dev/null @@ -1,33 +0,0 @@ -/* SPDX-License-Identifier: GPL-3.0-or-later */ -/* - * w32_perror.c - * - * Copyright (C) 2019 David Oberhollenzer - */ -#include "config.h" -#include "compat.h" - -#include - -#ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#include - -void w32_perror(const char *str) -{ - DWORD nStatus = GetLastError(); - LPVOID msg = NULL; - - FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, nStatus, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR)&msg, 0, NULL); - - fprintf(stderr, "%s: %s\n", str, (const char *)msg); - - if (msg != NULL) - LocalFree(msg); -} -#endif diff --git a/lib/compat/w32_stdio.c b/lib/compat/w32_stdio.c deleted file mode 100644 index c7f68d0..0000000 --- a/lib/compat/w32_stdio.c +++ /dev/null @@ -1,125 +0,0 @@ -/* SPDX-License-Identifier: GPL-3.0-or-later */ -/* - * w32_stdio.c - * - * Copyright (C) 2021 David Oberhollenzer - */ -#include "config.h" -#include "compat.h" - -#include -#include - -#ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#include -#include - -#undef fputc -#undef putc -#undef fputs -#undef fprintf -#undef printf - -static HANDLE get_handle(FILE *strm) -{ - if (strm != stdout && strm != stderr) - return INVALID_HANDLE_VALUE; - - return GetStdHandle(strm == stderr ? - STD_ERROR_HANDLE : STD_OUTPUT_HANDLE); -} - -static BOOL isatty(HANDLE hnd) -{ - if (hnd == INVALID_HANDLE_VALUE) - return FALSE; - - return (GetFileType(hnd) == FILE_TYPE_CHAR); -} - -int sqfs_tools_fputs(const char *str, FILE *strm) -{ - DWORD length; - WCHAR *wstr; - HANDLE hnd; - int ret; - - hnd = get_handle(strm); - if (!isatty(hnd)) - return fputs(str, strm); - - length = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0); - if (length <= 0) - return EOF; - - wstr = calloc(sizeof(wstr[0]), length); - if (wstr == NULL) - return EOF; - - MultiByteToWideChar(CP_UTF8, 0, str, -1, wstr, length); - - ret = WriteConsoleW(hnd, wstr, length, NULL, NULL) ? length : EOF; - - free(wstr); - return ret; -} - -int sqfs_tools_fputc(int c, FILE *strm) -{ - char str[2]; - - str[0] = c; - str[1] = '\0'; - - return sqfs_tools_fputs(str, strm); -} - -static int sqfs_printf_common(FILE *out, const char *fmt, va_list ap) -{ - int ret, len; - char *str; - - len = _vscprintf(fmt, ap); - if (len == -1) - return -1; - - str = malloc((size_t)len + 1); - if (str == NULL) - return -1; - - ret = vsprintf(str, fmt, ap); - if (ret == -1) { - free(str); - return -1; - } - - if (sqfs_tools_fputs(str, out) == EOF) - ret = -1; - - free(str); - return ret; -} - -int sqfs_tools_printf(const char *fmt, ...) -{ - va_list ap; - int ret; - - va_start(ap, fmt); - ret = sqfs_printf_common(stdout, fmt, ap); - va_end(ap); - return ret; -} - -int sqfs_tools_fprintf(FILE *strm, const char *fmt, ...) -{ - va_list ap; - int ret; - - va_start(ap, fmt); - ret = sqfs_printf_common(strm, fmt, ap); - va_end(ap); - return ret; -} -#endif diff --git a/lib/compat/w32_wmain.c b/lib/compat/w32_wmain.c deleted file mode 100644 index 9b3e354..0000000 --- a/lib/compat/w32_wmain.c +++ /dev/null @@ -1,83 +0,0 @@ -/* SPDX-License-Identifier: GPL-3.0-or-later */ -/* - * w32_wmain.c - * - * Copyright (C) 2021 David Oberhollenzer - */ -#include "config.h" -#include "compat.h" - -#include -#include - -#ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#include -#include - -#undef main - -int main(int argc, char **argv) -{ - WCHAR *cmdline, **argList; - int i, ret, utf8_argc; - char **utf8_argv; - (void)argc; - (void)argv; - - /* get the UTF-16 encoded command line arguments */ - cmdline = GetCommandLineW(); - argList = CommandLineToArgvW(cmdline, &utf8_argc); - if (argList == NULL) - goto fail_oom; - - /* convert to UTF-8 */ - utf8_argv = calloc(sizeof(utf8_argv[0]), utf8_argc); - if (utf8_argv == NULL) - goto fail_oom; - - for (i = 0; i < utf8_argc; ++i) { - DWORD length = WideCharToMultiByte(CP_UTF8, 0, argList[i], - -1, NULL, 0, NULL, NULL); - if (length <= 0) - goto fail_conv; - - utf8_argv[i] = calloc(1, length + 1); - if (utf8_argv[i] == NULL) - goto fail_oom; - - WideCharToMultiByte(CP_UTF8, 0, argList[i], -1, - utf8_argv[i], length + 1, NULL, NULL); - utf8_argv[i][length] = '\0'; - } - - LocalFree(argList); - argList = NULL; - - /* call the actual main function */ - ret = sqfs_tools_main(utf8_argc, utf8_argv); - - /* cleanup */ - for (i = 0; i < utf8_argc; ++i) - free(utf8_argv[i]); - - free(utf8_argv); - return ret; -fail_conv: - w32_perror("Converting UTF-16 argument to UTF-8"); - goto fail; -fail_oom: - fputs("out of memory\n", stderr); - goto fail; -fail: - if (utf8_argv != NULL) { - for (i = 0; i < utf8_argc; ++i) - free(utf8_argv[i]); - free(utf8_argv); - } - if (argList != NULL) { - LocalFree(argList); - } - return EXIT_FAILURE; -} -#endif -- cgit v1.2.3