make tests build on Windows
authorWolf Vollprecht <w.vollprecht@gmail.com>
Wed, 5 Jan 2022 17:09:24 +0000 (18:09 +0100)
committerWolf Vollprecht <w.vollprecht@gmail.com>
Fri, 7 Jan 2022 09:08:36 +0000 (10:08 +0100)
26 files changed:
.github/workflows/main.yml
include/zck.h.in
meson.build
src/lib/win32/basename.c [new file with mode: 0644]
src/lib/win32/dirent.h [new file with mode: 0644]
src/lib/win32/ftruncate.c [new file with mode: 0644]
src/lib/zck_private.h
src/memmem.c
src/meson.build
src/unzck.c
src/util_common.h
src/zck.c
src/zck_delta_size.c
src/zck_dl.c
src/zck_gen_zdict.c
src/zck_read_header.c
test/copy_chunks.c
test/empty.c
test/invalid_input_checksum.c
test/lib/util.h
test/meson.build
test/optelems.c
test/read_single_chunk.c
test/read_single_comp_chunk.c
test/shacheck.c
test/zck_cmp_uncomp.c

index d33adad359f21d0d9081d19f45eeeb5e43025d67..fd4315cda1c68fbcc62de2a13ed0aff4a5c50436 100644 (file)
@@ -18,6 +18,11 @@ jobs:
     name: Compile and Run Tests
     steps:
       - uses: actions/checkout@v2
+      - uses: actions/checkout@v2
+        with:
+          repository: wolfv/argp-standalone
+          path: argp-standalone
+
       - name: install mamba
         uses: mamba-org/provision-with-micromamba@main
         with:
@@ -35,6 +40,15 @@ jobs:
         run: |
           cd builddir
           ninja test
+      - name: Compile argp-standalone
+        shell: cmd /C CALL {0}
+        if: runner.os == 'Windows'
+        run: |
+          CALL micromamba activate zchunk_test_env
+          cd argp-standalone
+          meson setup builddir
+          meson compile -C builddir --prefix=%CONDA_PREFIX%\Library
+          meson install -C builddir
       - name: Compile zchunk
         shell: cmd /C CALL {0}
         if: runner.os == 'Windows'
index 0ca5c5fb49c8376274671baabd19fe9c60afd3f9..263c2ea46a1fc9b269c5b5412e0efc39d533b145 100644 (file)
@@ -75,6 +75,12 @@ typedef size_t (*zck_wcb)(void *ptr, size_t l, size_t c, void *dl_v);
     #define ZCK_PUBLIC_API __attribute__((visibility("default")))
 #endif
 
+#ifdef _WIN32
+#define ZCK_LOG_ERROR(...) fprintf(stderr, __VA_ARGS__)
+#else
+#define ZCK_LOG_ERROR(...) dprintf(STDERR_FILENO, __VA_ARGS__)
+#endif
+
 /*******************************************************************
  * Reading a zchunk file
  *******************************************************************/
index 34fecbecb2379cd1a1ce973e5597dd64ebf99d82..02d704ea46562e1d48d17a55d86a560fbdc47cd1 100644 (file)
@@ -40,14 +40,6 @@ else
     curl_dep = dependency('libcurl')
 endif
 
-if build_machine.system() != 'windows'
-    if build_machine.system() == 'darwin' or build_machine.system() == 'freebsd' or not cc.links('#include <argp.h>\nstatic error_t parse_opt (int key, char *arg, struct argp_state *state) { argp_usage(state); return 0; }; void main() {}')
-       argplib = cc.find_library('argp')
-    else
-       argplib = dependency('', required : false)
-    endif
-endif
-
 if get_option('with-openssl') == 'disabled'
     openssl_dep = dependency('', required : false)
 else
@@ -67,9 +59,16 @@ if host_machine.system() == 'windows'
     inc += include_directories('src/lib/win32')
 endif
 
+if build_machine.system() == 'windows' or build_machine.system() == 'darwin' or build_machine.system() == 'freebsd' or not cc.links('#include <argp.h>\nstatic error_t parse_opt (int key, char *arg, struct argp_state *state) { argp_usage(state); return 0; }; void main() {}')
+   inc += include_directories(get_option('prefix') / 'include')
+   argplib = cc.find_library('argp', dirs : get_option('prefix') / 'lib')
+else
+   argplib = dependency('', required : false)
+endif
+
 subdir('include')
 subdir('src')
-if not get_option('coverity') and host_machine.system() != 'windows'
+if not get_option('coverity')
     subdir('test')
 endif
 
diff --git a/src/lib/win32/basename.c b/src/lib/win32/basename.c
new file mode 100644 (file)
index 0000000..0d6a8e5
--- /dev/null
@@ -0,0 +1,24 @@
+#include <stdio.h>
+#include <windows.h>
+
+char* basename(char* path)
+{
+    // char full_path[MAX_PATH], drive[MAX_PATH], dir[MAX_PATH], filename[MAX_PATH], ext[MAX_PATH];
+
+    // printf("Input: %s", path);
+
+    // _fullpath(full_path, path, MAX_PATH);
+    // printf("Input: %s", full_path);
+
+    // _splitpath(full_path, drive, dir, filename, ext);
+
+    // printf("%s, %s, %s, %s", drive, dir, filename, ext);
+
+    // const char* res = malloc(MAX_PATH);
+    // sprintf(res, "%s%s", filename, ext);
+    // printf("Result: %s", res);
+    char *p = strrchr (path, '\\');
+    return p ? p + 1 : (char *) path;
+
+    // return res;
+}
\ No newline at end of file
diff --git a/src/lib/win32/dirent.h b/src/lib/win32/dirent.h
new file mode 100644 (file)
index 0000000..a26f7a7
--- /dev/null
@@ -0,0 +1,1027 @@
+/*
+ * Dirent interface for Microsoft Visual Studio
+ *
+ * Copyright (C) 1998-2019 Toni Ronkko
+ * This file is part of dirent.  Dirent may be freely distributed
+ * under the MIT license.  For all details and documentation, see
+ * https://github.com/tronkko/dirent
+ */
+#ifndef DIRENT_H
+#define DIRENT_H
+
+/* Hide warnings about unreferenced local functions */
+#if defined(__clang__)
+#      pragma clang diagnostic ignored "-Wunused-function"
+#elif defined(_MSC_VER)
+#      pragma warning(disable:4505)
+#elif defined(__GNUC__)
+#      pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
+/*
+ * Include windows.h without Windows Sockets 1.1 to prevent conflicts with
+ * Windows Sockets 2.0.
+ */
+#ifndef WIN32_LEAN_AND_MEAN
+#      define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <wchar.h>
+#include <string.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <ctype.h>
+
+/* Indicates that d_type field is available in dirent structure */
+#define _DIRENT_HAVE_D_TYPE
+
+/* Indicates that d_namlen field is available in dirent structure */
+#define _DIRENT_HAVE_D_NAMLEN
+
+/* Entries missing from MSVC 6.0 */
+#if !defined(FILE_ATTRIBUTE_DEVICE)
+#      define FILE_ATTRIBUTE_DEVICE 0x40
+#endif
+
+/* File type and permission flags for stat(), general mask */
+#if !defined(S_IFMT)
+#      define S_IFMT _S_IFMT
+#endif
+
+/* Directory bit */
+#if !defined(S_IFDIR)
+#      define S_IFDIR _S_IFDIR
+#endif
+
+/* Character device bit */
+#if !defined(S_IFCHR)
+#      define S_IFCHR _S_IFCHR
+#endif
+
+/* Pipe bit */
+#if !defined(S_IFFIFO)
+#      define S_IFFIFO _S_IFFIFO
+#endif
+
+/* Regular file bit */
+#if !defined(S_IFREG)
+#      define S_IFREG _S_IFREG
+#endif
+
+/* Read permission */
+#if !defined(S_IREAD)
+#      define S_IREAD _S_IREAD
+#endif
+
+/* Write permission */
+#if !defined(S_IWRITE)
+#      define S_IWRITE _S_IWRITE
+#endif
+
+/* Execute permission */
+#if !defined(S_IEXEC)
+#      define S_IEXEC _S_IEXEC
+#endif
+
+/* Pipe */
+#if !defined(S_IFIFO)
+#      define S_IFIFO _S_IFIFO
+#endif
+
+/* Block device */
+#if !defined(S_IFBLK)
+#      define S_IFBLK 0
+#endif
+
+/* Link */
+#if !defined(S_IFLNK)
+#      define S_IFLNK 0
+#endif
+
+/* Socket */
+#if !defined(S_IFSOCK)
+#      define S_IFSOCK 0
+#endif
+
+/* Read user permission */
+#if !defined(S_IRUSR)
+#      define S_IRUSR S_IREAD
+#endif
+
+/* Write user permission */
+#if !defined(S_IWUSR)
+#      define S_IWUSR S_IWRITE
+#endif
+
+/* Execute user permission */
+#if !defined(S_IXUSR)
+#      define S_IXUSR 0
+#endif
+
+/* Read group permission */
+#if !defined(S_IRGRP)
+#      define S_IRGRP 0
+#endif
+
+/* Write group permission */
+#if !defined(S_IWGRP)
+#      define S_IWGRP 0
+#endif
+
+/* Execute group permission */
+#if !defined(S_IXGRP)
+#      define S_IXGRP 0
+#endif
+
+/* Read others permission */
+#if !defined(S_IROTH)
+#      define S_IROTH 0
+#endif
+
+/* Write others permission */
+#if !defined(S_IWOTH)
+#      define S_IWOTH 0
+#endif
+
+/* Execute others permission */
+#if !defined(S_IXOTH)
+#      define S_IXOTH 0
+#endif
+
+/* Maximum length of file name */
+#if !defined(PATH_MAX)
+#      define PATH_MAX MAX_PATH
+#endif
+#if !defined(FILENAME_MAX)
+#      define FILENAME_MAX MAX_PATH
+#endif
+#if !defined(NAME_MAX)
+#      define NAME_MAX FILENAME_MAX
+#endif
+
+/* File type flags for d_type */
+#define DT_UNKNOWN 0
+#define DT_REG S_IFREG
+#define DT_DIR S_IFDIR
+#define DT_FIFO S_IFIFO
+#define DT_SOCK S_IFSOCK
+#define DT_CHR S_IFCHR
+#define DT_BLK S_IFBLK
+#define DT_LNK S_IFLNK
+
+/* Macros for converting between st_mode and d_type */
+#define IFTODT(mode) ((mode) & S_IFMT)
+#define DTTOIF(type) (type)
+
+/*
+ * File type macros.  Note that block devices, sockets and links cannot be
+ * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are
+ * only defined for compatibility.  These macros should always return false
+ * on Windows.
+ */
+#if !defined(S_ISFIFO)
+#      define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
+#endif
+#if !defined(S_ISDIR)
+#      define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
+#endif
+#if !defined(S_ISREG)
+#      define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
+#endif
+#if !defined(S_ISLNK)
+#      define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
+#endif
+#if !defined(S_ISSOCK)
+#      define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
+#endif
+#if !defined(S_ISCHR)
+#      define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
+#endif
+#if !defined(S_ISBLK)
+#      define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
+#endif
+
+/* Return the exact length of the file name without zero terminator */
+#define _D_EXACT_NAMLEN(p) ((p)->d_namlen)
+
+/* Return the maximum size of a file name */
+#define _D_ALLOC_NAMLEN(p) ((PATH_MAX)+1)
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Wide-character version */
+struct _wdirent {
+       /* Always zero */
+       long d_ino;
+
+       /* File position within stream */
+       long d_off;
+
+       /* Structure size */
+       unsigned short d_reclen;
+
+       /* Length of name without \0 */
+       size_t d_namlen;
+
+       /* File type */
+       int d_type;
+
+       /* File name */
+       wchar_t d_name[PATH_MAX+1];
+};
+typedef struct _wdirent _wdirent;
+
+struct _WDIR {
+       /* Current directory entry */
+       struct _wdirent ent;
+
+       /* Private file data */
+       WIN32_FIND_DATAW data;
+
+       /* True if data is valid */
+       int cached;
+
+       /* Win32 search handle */
+       HANDLE handle;
+
+       /* Initial directory name */
+       wchar_t *patt;
+};
+typedef struct _WDIR _WDIR;
+
+/* Multi-byte character version */
+struct dirent {
+       /* Always zero */
+       long d_ino;
+
+       /* File position within stream */
+       long d_off;
+
+       /* Structure size */
+       unsigned short d_reclen;
+
+       /* Length of name without \0 */
+       size_t d_namlen;
+
+       /* File type */
+       int d_type;
+
+       /* File name */
+       char d_name[PATH_MAX+1];
+};
+typedef struct dirent dirent;
+
+struct DIR {
+       struct dirent ent;
+       struct _WDIR *wdirp;
+};
+typedef struct DIR DIR;
+
+
+/* Dirent functions */
+static DIR *opendir(const char *dirname);
+static _WDIR *_wopendir(const wchar_t *dirname);
+
+static struct dirent *readdir(DIR *dirp);
+static struct _wdirent *_wreaddir(_WDIR *dirp);
+
+static int readdir_r(
+       DIR *dirp, struct dirent *entry, struct dirent **result);
+static int _wreaddir_r(
+       _WDIR *dirp, struct _wdirent *entry, struct _wdirent **result);
+
+static int closedir(DIR *dirp);
+static int _wclosedir(_WDIR *dirp);
+
+static void rewinddir(DIR* dirp);
+static void _wrewinddir(_WDIR* dirp);
+
+static int scandir(const char *dirname, struct dirent ***namelist,
+       int (*filter)(const struct dirent*),
+       int (*compare)(const struct dirent**, const struct dirent**));
+
+static int alphasort(const struct dirent **a, const struct dirent **b);
+
+static int versionsort(const struct dirent **a, const struct dirent **b);
+
+static int strverscmp(const char *a, const char *b);
+
+/* For compatibility with Symbian */
+#define wdirent _wdirent
+#define WDIR _WDIR
+#define wopendir _wopendir
+#define wreaddir _wreaddir
+#define wclosedir _wclosedir
+#define wrewinddir _wrewinddir
+
+/* Compatibility with older Microsoft compilers and non-Microsoft compilers */
+#if !defined(_MSC_VER) || _MSC_VER < 1400
+#      define wcstombs_s dirent_wcstombs_s
+#      define mbstowcs_s dirent_mbstowcs_s
+#endif
+
+/* Optimize dirent_set_errno() away on modern Microsoft compilers */
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+#      define dirent_set_errno _set_errno
+#endif
+
+
+/* Internal utility functions */
+static WIN32_FIND_DATAW *dirent_first(_WDIR *dirp);
+static WIN32_FIND_DATAW *dirent_next(_WDIR *dirp);
+
+#if !defined(_MSC_VER) || _MSC_VER < 1400
+static int dirent_mbstowcs_s(
+       size_t *pReturnValue, wchar_t *wcstr, size_t sizeInWords,
+       const char *mbstr, size_t count);
+#endif
+
+#if !defined(_MSC_VER) || _MSC_VER < 1400
+static int dirent_wcstombs_s(
+       size_t *pReturnValue, char *mbstr, size_t sizeInBytes,
+       const wchar_t *wcstr, size_t count);
+#endif
+
+#if !defined(_MSC_VER) || _MSC_VER < 1400
+static void dirent_set_errno(int error);
+#endif
+
+
+/*
+ * Open directory stream DIRNAME for read and return a pointer to the
+ * internal working area that is used to retrieve individual directory
+ * entries.
+ */
+static _WDIR *_wopendir(const wchar_t *dirname)
+{
+       wchar_t *p;
+
+       /* Must have directory name */
+       if (dirname == NULL || dirname[0] == '\0') {
+               dirent_set_errno(ENOENT);
+               return NULL;
+       }
+
+       /* Allocate new _WDIR structure */
+       _WDIR *dirp = (_WDIR*) malloc(sizeof(struct _WDIR));
+       if (!dirp)
+               return NULL;
+
+       /* Reset _WDIR structure */
+       dirp->handle = INVALID_HANDLE_VALUE;
+       dirp->patt = NULL;
+       dirp->cached = 0;
+
+       /*
+        * Compute the length of full path plus zero terminator
+        *
+        * Note that on WinRT there's no way to convert relative paths
+        * into absolute paths, so just assume it is an absolute path.
+        */
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+       /* Desktop */
+       DWORD n = GetFullPathNameW(dirname, 0, NULL, NULL);
+#else
+       /* WinRT */
+       size_t n = wcslen(dirname);
+#endif
+
+       /* Allocate room for absolute directory name and search pattern */
+       dirp->patt = (wchar_t*) malloc(sizeof(wchar_t) * n + 16);
+       if (dirp->patt == NULL)
+               goto exit_closedir;
+
+       /*
+        * Convert relative directory name to an absolute one.  This
+        * allows rewinddir() to function correctly even when current
+        * working directory is changed between opendir() and rewinddir().
+        *
+        * Note that on WinRT there's no way to convert relative paths
+        * into absolute paths, so just assume it is an absolute path.
+        */
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+       /* Desktop */
+       n = GetFullPathNameW(dirname, n, dirp->patt, NULL);
+       if (n <= 0)
+               goto exit_closedir;
+#else
+       /* WinRT */
+       wcsncpy_s(dirp->patt, n+1, dirname, n);
+#endif
+
+       /* Append search pattern \* to the directory name */
+       p = dirp->patt + n;
+       switch (p[-1]) {
+       case '\\':
+       case '/':
+       case ':':
+               /* Directory ends in path separator, e.g. c:\temp\ */
+               /*NOP*/;
+               break;
+
+       default:
+               /* Directory name doesn't end in path separator */
+               *p++ = '\\';
+       }
+       *p++ = '*';
+       *p = '\0';
+
+       /* Open directory stream and retrieve the first entry */
+       if (!dirent_first(dirp))
+               goto exit_closedir;
+
+       /* Success */
+       return dirp;
+
+       /* Failure */
+exit_closedir:
+       _wclosedir(dirp);
+       return NULL;
+}
+
+/*
+ * Read next directory entry.
+ *
+ * Returns pointer to static directory entry which may be overwritten by
+ * subsequent calls to _wreaddir().
+ */
+static struct _wdirent *_wreaddir(_WDIR *dirp)
+{
+       /*
+        * Read directory entry to buffer.  We can safely ignore the return
+        * value as entry will be set to NULL in case of error.
+        */
+       struct _wdirent *entry;
+       (void) _wreaddir_r(dirp, &dirp->ent, &entry);
+
+       /* Return pointer to statically allocated directory entry */
+       return entry;
+}
+
+/*
+ * Read next directory entry.
+ *
+ * Returns zero on success.  If end of directory stream is reached, then sets
+ * result to NULL and returns zero.
+ */
+static int _wreaddir_r(
+       _WDIR *dirp, struct _wdirent *entry, struct _wdirent **result)
+{
+       /* Read next directory entry */
+       WIN32_FIND_DATAW *datap = dirent_next(dirp);
+       if (!datap) {
+               /* Return NULL to indicate end of directory */
+               *result = NULL;
+               return /*OK*/0;
+       }
+
+       /*
+        * Copy file name as wide-character string.  If the file name is too
+        * long to fit in to the destination buffer, then truncate file name
+        * to PATH_MAX characters and zero-terminate the buffer.
+        */
+       size_t n = 0;
+       while (n < PATH_MAX && datap->cFileName[n] != 0) {
+               entry->d_name[n] = datap->cFileName[n];
+               n++;
+       }
+       entry->d_name[n] = 0;
+
+       /* Length of file name excluding zero terminator */
+       entry->d_namlen = n;
+
+       /* File type */
+       DWORD attr = datap->dwFileAttributes;
+       if ((attr & FILE_ATTRIBUTE_DEVICE) != 0)
+               entry->d_type = DT_CHR;
+       else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0)
+               entry->d_type = DT_DIR;
+       else
+               entry->d_type = DT_REG;
+
+       /* Reset dummy fields */
+       entry->d_ino = 0;
+       entry->d_off = 0;
+       entry->d_reclen = sizeof(struct _wdirent);
+
+       /* Set result address */
+       *result = entry;
+       return /*OK*/0;
+}
+
+/*
+ * Close directory stream opened by opendir() function.  This invalidates the
+ * DIR structure as well as any directory entry read previously by
+ * _wreaddir().
+ */
+static int _wclosedir(_WDIR *dirp)
+{
+       if (!dirp) {
+               dirent_set_errno(EBADF);
+               return /*failure*/-1;
+       }
+
+       /* Release search handle */
+       if (dirp->handle != INVALID_HANDLE_VALUE)
+               FindClose(dirp->handle);
+
+       /* Release search pattern */
+       free(dirp->patt);
+
+       /* Release directory structure */
+       free(dirp);
+       return /*success*/0;
+}
+
+/*
+ * Rewind directory stream such that _wreaddir() returns the very first
+ * file name again.
+ */
+static void _wrewinddir(_WDIR* dirp)
+{
+       if (!dirp)
+               return;
+
+       /* Release existing search handle */
+       if (dirp->handle != INVALID_HANDLE_VALUE)
+               FindClose(dirp->handle);
+
+       /* Open new search handle */
+       dirent_first(dirp);
+}
+
+/* Get first directory entry */
+static WIN32_FIND_DATAW *dirent_first(_WDIR *dirp)
+{
+       if (!dirp)
+               return NULL;
+
+       /* Open directory and retrieve the first entry */
+       dirp->handle = FindFirstFileExW(
+               dirp->patt, FindExInfoStandard, &dirp->data,
+               FindExSearchNameMatch, NULL, 0);
+       if (dirp->handle == INVALID_HANDLE_VALUE)
+               goto error;
+
+       /* A directory entry is now waiting in memory */
+       dirp->cached = 1;
+       return &dirp->data;
+
+error:
+       /* Failed to open directory: no directory entry in memory */
+       dirp->cached = 0;
+
+       /* Set error code */
+       DWORD errorcode = GetLastError();
+       switch (errorcode) {
+       case ERROR_ACCESS_DENIED:
+               /* No read access to directory */
+               dirent_set_errno(EACCES);
+               break;
+
+       case ERROR_DIRECTORY:
+               /* Directory name is invalid */
+               dirent_set_errno(ENOTDIR);
+               break;
+
+       case ERROR_PATH_NOT_FOUND:
+       default:
+               /* Cannot find the file */
+               dirent_set_errno(ENOENT);
+       }
+       return NULL;
+}
+
+/* Get next directory entry */
+static WIN32_FIND_DATAW *dirent_next(_WDIR *dirp)
+{
+       /* Is the next directory entry already in cache? */
+       if (dirp->cached) {
+               /* Yes, a valid directory entry found in memory */
+               dirp->cached = 0;
+               return &dirp->data;
+       }
+
+       /* No directory entry in cache */
+       if (dirp->handle == INVALID_HANDLE_VALUE)
+               return NULL;
+
+       /* Read the next directory entry from stream */
+       if (FindNextFileW(dirp->handle, &dirp->data) == FALSE)
+               goto exit_close;
+
+       /* Success */
+       return &dirp->data;
+
+       /* Failure */
+exit_close:
+       FindClose(dirp->handle);
+       dirp->handle = INVALID_HANDLE_VALUE;
+       return NULL;
+}
+
+/* Open directory stream using plain old C-string */
+static DIR *opendir(const char *dirname)
+{
+       /* Must have directory name */
+       if (dirname == NULL || dirname[0] == '\0') {
+               dirent_set_errno(ENOENT);
+               return NULL;
+       }
+
+       /* Allocate memory for DIR structure */
+       struct DIR *dirp = (DIR*) malloc(sizeof(struct DIR));
+       if (!dirp)
+               return NULL;
+
+       /* Convert directory name to wide-character string */
+       wchar_t wname[PATH_MAX + 1];
+       size_t n;
+       int error = mbstowcs_s(&n, wname, PATH_MAX + 1, dirname, PATH_MAX+1);
+       if (error)
+               goto exit_failure;
+
+       /* Open directory stream using wide-character name */
+       dirp->wdirp = _wopendir(wname);
+       if (!dirp->wdirp)
+               goto exit_failure;
+
+       /* Success */
+       return dirp;
+
+       /* Failure */
+exit_failure:
+       free(dirp);
+       return NULL;
+}
+
+/* Read next directory entry */
+static struct dirent *readdir(DIR *dirp)
+{
+       /*
+        * Read directory entry to buffer.  We can safely ignore the return
+        * value as entry will be set to NULL in case of error.
+        */
+       struct dirent *entry;
+       (void) readdir_r(dirp, &dirp->ent, &entry);
+
+       /* Return pointer to statically allocated directory entry */
+       return entry;
+}
+
+/*
+ * Read next directory entry into called-allocated buffer.
+ *
+ * Returns zero on success.  If the end of directory stream is reached, then
+ * sets result to NULL and returns zero.
+ */
+static int readdir_r(
+       DIR *dirp, struct dirent *entry, struct dirent **result)
+{
+       /* Read next directory entry */
+       WIN32_FIND_DATAW *datap = dirent_next(dirp->wdirp);
+       if (!datap) {
+               /* No more directory entries */
+               *result = NULL;
+               return /*OK*/0;
+       }
+
+       /* Attempt to convert file name to multi-byte string */
+       size_t n;
+       int error = wcstombs_s(
+               &n, entry->d_name, PATH_MAX + 1,
+               datap->cFileName, PATH_MAX + 1);
+
+       /*
+        * If the file name cannot be represented by a multi-byte string, then
+        * attempt to use old 8+3 file name.  This allows the program to
+        * access files although file names may seem unfamiliar to the user.
+        *
+        * Be ware that the code below cannot come up with a short file name
+        * unless the file system provides one.  At least VirtualBox shared
+        * folders fail to do this.
+        */
+       if (error && datap->cAlternateFileName[0] != '\0') {
+               error = wcstombs_s(
+                       &n, entry->d_name, PATH_MAX + 1,
+                       datap->cAlternateFileName, PATH_MAX + 1);
+       }
+
+       if (!error) {
+               /* Length of file name excluding zero terminator */
+               entry->d_namlen = n - 1;
+
+               /* File attributes */
+               DWORD attr = datap->dwFileAttributes;
+               if ((attr & FILE_ATTRIBUTE_DEVICE) != 0)
+                       entry->d_type = DT_CHR;
+               else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0)
+                       entry->d_type = DT_DIR;
+               else
+                       entry->d_type = DT_REG;
+
+               /* Reset dummy fields */
+               entry->d_ino = 0;
+               entry->d_off = 0;
+               entry->d_reclen = sizeof(struct dirent);
+       } else {
+               /*
+                * Cannot convert file name to multi-byte string so construct
+                * an erroneous directory entry and return that.  Note that
+                * we cannot return NULL as that would stop the processing
+                * of directory entries completely.
+                */
+               entry->d_name[0] = '?';
+               entry->d_name[1] = '\0';
+               entry->d_namlen = 1;
+               entry->d_type = DT_UNKNOWN;
+               entry->d_ino = 0;
+               entry->d_off = -1;
+               entry->d_reclen = 0;
+       }
+
+       /* Return pointer to directory entry */
+       *result = entry;
+       return /*OK*/0;
+}
+
+/* Close directory stream */
+static int closedir(DIR *dirp)
+{
+       int ok;
+
+       if (!dirp)
+               goto exit_failure;
+
+       /* Close wide-character directory stream */
+       ok = _wclosedir(dirp->wdirp);
+       dirp->wdirp = NULL;
+
+       /* Release multi-byte character version */
+       free(dirp);
+       return ok;
+
+exit_failure:
+       /* Invalid directory stream */
+       dirent_set_errno(EBADF);
+       return /*failure*/-1;
+}
+
+/* Rewind directory stream to beginning */
+static void rewinddir(DIR* dirp)
+{
+       if (!dirp)
+               return;
+
+       /* Rewind wide-character string directory stream */
+       _wrewinddir(dirp->wdirp);
+}
+
+/* Scan directory for entries */
+static int scandir(
+       const char *dirname, struct dirent ***namelist,
+       int (*filter)(const struct dirent*),
+       int (*compare)(const struct dirent**, const struct dirent**))
+{
+       int result;
+
+       /* Open directory stream */
+       DIR *dir = opendir(dirname);
+       if (!dir) {
+               /* Cannot open directory */
+               return /*Error*/ -1;
+       }
+
+       /* Read directory entries to memory */
+       struct dirent *tmp = NULL;
+       struct dirent **files = NULL;
+       size_t size = 0;
+       size_t allocated = 0;
+       while (1) {
+               /* Allocate room for a temporary directory entry */
+               if (!tmp) {
+                       tmp = (struct dirent*) malloc(sizeof(struct dirent));
+                       if (!tmp)
+                               goto exit_failure;
+               }
+
+               /* Read directory entry to temporary area */
+               struct dirent *entry;
+               if (readdir_r(dir, tmp, &entry) != /*OK*/0)
+                       goto exit_failure;
+
+               /* Stop if we already read the last directory entry */
+               if (entry == NULL)
+                       goto exit_success;
+
+               /* Determine whether to include the entry in results */
+               if (filter && !filter(tmp))
+                       continue;
+
+               /* Enlarge pointer table to make room for another pointer */
+               if (size >= allocated) {
+                       /* Compute number of entries in the new table */
+                       size_t num_entries = size * 2 + 16;
+
+                       /* Allocate new pointer table or enlarge existing */
+                       void *p = realloc(files, sizeof(void*) * num_entries);
+                       if (!p)
+                               goto exit_failure;
+
+                       /* Got the memory */
+                       files = (dirent**) p;
+                       allocated = num_entries;
+               }
+
+               /* Store the temporary entry to ptr table */
+               files[size++] = tmp;
+               tmp = NULL;
+       }
+
+exit_failure:
+       /* Release allocated file entries */
+       for (size_t i = 0; i < size; i++) {
+               free(files[i]);
+       }
+
+       /* Release the pointer table */
+       free(files);
+       files = NULL;
+
+       /* Exit with error code */
+       result = /*error*/ -1;
+       goto exit_status;
+
+exit_success:
+       /* Sort directory entries */
+       qsort(files, size, sizeof(void*),
+               (int (*) (const void*, const void*)) compare);
+
+       /* Pass pointer table to caller */
+       if (namelist)
+               *namelist = files;
+
+       /* Return the number of directory entries read */
+       result = (int) size;
+
+exit_status:
+       /* Release temporary directory entry, if we had one */
+       free(tmp);
+
+       /* Close directory stream */
+       closedir(dir);
+       return result;
+}
+
+/* Alphabetical sorting */
+static int alphasort(const struct dirent **a, const struct dirent **b)
+{
+       return strcoll((*a)->d_name, (*b)->d_name);
+}
+
+/* Sort versions */
+static int versionsort(const struct dirent **a, const struct dirent **b)
+{
+       return strverscmp((*a)->d_name, (*b)->d_name);
+}
+
+/* Compare strings */
+static int strverscmp(const char *a, const char *b)
+{
+       size_t i = 0;
+       size_t j;
+
+       /* Find first difference */
+       while (a[i] == b[i]) {
+               if (a[i] == '\0') {
+                       /* No difference */
+                       return 0;
+               }
+               ++i;
+       }
+
+       /* Count backwards and find the leftmost digit */
+       j = i;
+       while (j > 0 && isdigit(a[j-1])) {
+               --j;
+       }
+
+       /* Determine mode of comparison */
+       if (a[j] == '0' || b[j] == '0') {
+               /* Find the next non-zero digit */
+               while (a[j] == '0' && a[j] == b[j]) {
+                       j++;
+               }
+
+               /* String with more digits is smaller, e.g 002 < 01 */
+               if (isdigit(a[j])) {
+                       if (!isdigit(b[j])) {
+                               return -1;
+                       }
+               } else if (isdigit(b[j])) {
+                       return 1;
+               }
+       } else if (isdigit(a[j]) && isdigit(b[j])) {
+               /* Numeric comparison */
+               size_t k1 = j;
+               size_t k2 = j;
+
+               /* Compute number of digits in each string */
+               while (isdigit(a[k1])) {
+                       k1++;
+               }
+               while (isdigit(b[k2])) {
+                       k2++;
+               }
+
+               /* Number with more digits is bigger, e.g 999 < 1000 */
+               if (k1 < k2)
+                       return -1;
+               else if (k1 > k2)
+                       return 1;
+       }
+
+       /* Alphabetical comparison */
+       return (int) ((unsigned char) a[i]) - ((unsigned char) b[i]);
+}
+
+/* Convert multi-byte string to wide character string */
+#if !defined(_MSC_VER) || _MSC_VER < 1400
+static int dirent_mbstowcs_s(
+       size_t *pReturnValue, wchar_t *wcstr,
+       size_t sizeInWords, const char *mbstr, size_t count)
+{
+       /* Older Visual Studio or non-Microsoft compiler */
+       size_t n = mbstowcs(wcstr, mbstr, sizeInWords);
+       if (wcstr && n >= count)
+               return /*error*/ 1;
+
+       /* Zero-terminate output buffer */
+       if (wcstr && sizeInWords) {
+               if (n >= sizeInWords)
+                       n = sizeInWords - 1;
+               wcstr[n] = 0;
+       }
+
+       /* Length of multi-byte string with zero terminator */
+       if (pReturnValue) {
+               *pReturnValue = n + 1;
+       }
+
+       /* Success */
+       return 0;
+}
+#endif
+
+/* Convert wide-character string to multi-byte string */
+#if !defined(_MSC_VER) || _MSC_VER < 1400
+static int dirent_wcstombs_s(
+       size_t *pReturnValue, char *mbstr,
+       size_t sizeInBytes, const wchar_t *wcstr, size_t count)
+{
+       /* Older Visual Studio or non-Microsoft compiler */
+       size_t n = wcstombs(mbstr, wcstr, sizeInBytes);
+       if (mbstr && n >= count)
+               return /*error*/1;
+
+       /* Zero-terminate output buffer */
+       if (mbstr && sizeInBytes) {
+               if (n >= sizeInBytes) {
+                       n = sizeInBytes - 1;
+               }
+               mbstr[n] = '\0';
+       }
+
+       /* Length of resulting multi-bytes string WITH zero-terminator */
+       if (pReturnValue) {
+               *pReturnValue = n + 1;
+       }
+
+       /* Success */
+       return 0;
+}
+#endif
+
+/* Set errno variable */
+#if !defined(_MSC_VER) || _MSC_VER < 1400
+static void dirent_set_errno(int error)
+{
+       /* Non-Microsoft compiler or older Microsoft compiler */
+       errno = error;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif /*DIRENT_H*/
\ No newline at end of file
diff --git a/src/lib/win32/ftruncate.c b/src/lib/win32/ftruncate.c
new file mode 100644 (file)
index 0000000..3227732
--- /dev/null
@@ -0,0 +1,21 @@
+#include <windows.h>
+#include <stdio.h>
+
+#include <io.h>
+
+int ftruncate(int fd, LONGLONG length)
+{
+    FILE* fp = fdopen(fd, "wb");
+    LARGE_INTEGER lisize;
+    lisize.QuadPart = length;
+    if (lisize.QuadPart < 0) {
+        return -1;
+    }
+    if (!fp) {
+        return -1;
+    }
+    else if (SetFilePointerEx(fp, lisize, NULL, FILE_BEGIN) == 0 || SetEndOfFile(fp) == 0) {
+        return -1;
+    }
+    return 0;
+}
\ No newline at end of file
index 889efe00a3181adb4ba0b74c66de3107a24b39b0..77a8c5fde1fee3847f43ebe1ac988503165c8176 100644 (file)
@@ -111,7 +111,9 @@ struct zckHash {
     void *ctx;
 };
 
+#ifndef CURLINC_CURL_H
 typedef void CURL;
+#endif
 
 typedef struct zckMP {
     int state;
index e72501b9c25482a2c0890d844e67461878f51795..f7dc20f04a78a8274d8725e70ff7be0a9b85bd20 100644 (file)
@@ -37,7 +37,11 @@ void *memmem(const void *haystack, size_t n, const void *needle, size_t m)
     if (m > n || !m || !n)
         return NULL;
 
+#ifndef _WIN32
     if (__builtin_expect((m > 1), 1)) {
+#else
+    if (m > 1) {
+#endif
         const unsigned char*  y = (const unsigned char*) haystack;
         const unsigned char*  x = (const unsigned char*) needle;
         size_t                j = 0;
index b0316dd435f60555628de7aeba9b7ec0f07c9ca3..bea4ea499ac6c60f7cbbbbaf5872bc0f011d5e7e 100644 (file)
@@ -1,52 +1,56 @@
 subdir('lib')
 
-if host_machine.system() != 'windows'
-    zck = executable(
-        'zck',
-        ['zck.c', 'util_common.c'],
-        include_directories: inc,
-        dependencies: argplib,
-        link_with: zcklib,
-        install: true
-    )
-    unzck = executable(
-        'unzck',
-        ['unzck.c', 'util_common.c'],
-        include_directories: inc,
-        dependencies: argplib,
-        link_with: zcklib,
-        install: true
-    )
-    zckdl = executable(
-        'zckdl',
-        ['zck_dl.c', 'util_common.c'],
-        include_directories: inc,
-        dependencies: [argplib, curl_dep],
-        link_with: zcklib,
-        install: true
-    )
-    zck_gen_zdict = executable(
-        'zck_gen_zdict',
-        ['zck_gen_zdict.c', 'util_common.c'],
-        include_directories: inc,
-        dependencies: argplib,
-        link_with: zcklib,
-        install: true
-    )
-    zck_read_header = executable(
-        'zck_read_header',
-        ['zck_read_header.c', 'util_common.c'],
-        include_directories: inc,
-        dependencies: argplib,
-        link_with: zcklib,
-        install: true
-    )
-    zck_delta_size = executable(
-        'zck_delta_size',
-        ['zck_delta_size.c', 'util_common.c', 'memmem.c'],
-        include_directories: inc,
-        dependencies: argplib,
-        link_with: zcklib,
-        install: true
-    )
+if host_machine.system() == 'windows'
+    extra_win_src = ['lib/win32/basename.c', 'lib/win32/ftruncate.c']
+else
+    extra_win_src = []
 endif
+
+zck = executable(
+    'zck',
+    ['zck.c', 'util_common.c', 'memmem.c'] + extra_win_src,
+    include_directories: inc,
+    dependencies: argplib,
+    link_with: zcklib,
+    install: true
+)
+unzck = executable(
+    'unzck',
+    ['unzck.c', 'util_common.c'] + extra_win_src,
+    include_directories: inc,
+    dependencies: argplib,
+    link_with: zcklib,
+    install: true
+)
+zckdl = executable(
+    'zckdl',
+    ['zck_dl.c', 'util_common.c'] + extra_win_src,
+    include_directories: inc,
+    dependencies: [argplib, curl_dep],
+    link_with: zcklib,
+    install: true
+)
+zck_gen_zdict = executable(
+    'zck_gen_zdict',
+    ['zck_gen_zdict.c', 'util_common.c'] + extra_win_src,
+    include_directories: inc,
+    dependencies: argplib,
+    link_with: zcklib,
+    install: true
+)
+zck_read_header = executable(
+    'zck_read_header',
+    ['zck_read_header.c', 'util_common.c'] + extra_win_src,
+    include_directories: inc,
+    dependencies: argplib,
+    link_with: zcklib,
+    install: true
+)
+zck_delta_size = executable(
+    'zck_delta_size',
+    ['zck_delta_size.c', 'util_common.c', 'memmem.c'] + extra_win_src,
+    include_directories: inc,
+    dependencies: argplib,
+    link_with: zcklib,
+    install: true
+)
index 7cfe9e14583ad37d91eb980886e24def18c97a1c..5c9f0fd684d02405a6e40942c73b9993fae14c0c 100644 (file)
@@ -25,6 +25,7 @@
  */
 
 #define _GNU_SOURCE
+#define STDERR_FILENO 2
 
 #include <assert.h>
 #include <stdlib.h>
@@ -35,7 +36,9 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#ifndef _WIN32
 #include <libgen.h>
+#endif
 #include <unistd.h>
 #include <argp.h>
 #include <zck.h>
@@ -124,17 +127,20 @@ int main (int argc, char *argv[]) {
     if(!arguments.std_out) {
         if(strlen(arguments.args[0]) < 5 ||
            strcmp(arguments.args[0] + strlen(arguments.args[0]) - 4, ".zck") != 0) {
-            dprintf(STDERR_FILENO, "Not a *.zck file: %s\n", arguments.args[0]);
+            ZCK_LOG_ERROR("Not a *.zck file: %s\n", arguments.args[0]);
             exit(1);
         }
     }
-    int src_fd = open(arguments.args[0], O_RDONLY);
+    int src_fd = open(arguments.args[0], O_RDONLY | O_BINARY);
     if(src_fd < 0) {
-        dprintf(STDERR_FILENO, "Unable to open %s\n", arguments.args[0]);
+        ZCK_LOG_ERROR("Unable to open %s\n", arguments.args[0]);
         perror("");
         exit(1);
     }
-    char *base_name = basename(arguments.args[0]);
+    // char *base_name = basename(arguments.args[0]);
+    char* base_name = arguments.args[0];
+    // printf("Basename pointer: %d", base_name);
+    // printf("Got basename: %s", base_name);
     char *out_name = NULL;
     if(arguments.dict)
         out_name = calloc(strlen(base_name) + 3, 1); // len .zck -> .zdict = +2
@@ -145,11 +151,15 @@ int main (int argc, char *argv[]) {
     if(arguments.dict)
         snprintf(out_name + strlen(base_name) - 4, 7, ".zdict");
 
+#ifdef _WIN32
+    int dst_fd = _fileno(stdout);
+#else
     int dst_fd = STDOUT_FILENO;
+#endif
     if(!arguments.std_out) {
-        dst_fd = open(out_name, O_TRUNC | O_WRONLY | O_CREAT, 0666);
+        dst_fd = open(out_name, O_TRUNC | O_WRONLY | O_CREAT | O_BINARY, 0666);
         if(dst_fd < 0) {
-            dprintf(STDERR_FILENO, "Unable to open %s", out_name);
+            ZCK_LOG_ERROR("Unable to open %s", out_name);
             perror("");
             free(out_name);
             exit(1);
@@ -161,7 +171,7 @@ int main (int argc, char *argv[]) {
     char *data = NULL;
     zckCtx *zck = zck_create();
     if(!zck_init_read(zck, src_fd)) {
-        dprintf(STDERR_FILENO, "%s", zck_get_error(zck));
+        ZCK_LOG_ERROR("%s", zck_get_error(zck));
         goto error2;
     }
 
@@ -170,7 +180,7 @@ int main (int argc, char *argv[]) {
         zckChunk *dict = zck_get_first_chunk(zck);
         ssize_t dict_size = zck_get_chunk_size(dict);
         if(dict_size < 0) {
-            dprintf(STDERR_FILENO, "%s", zck_get_error(zck));
+            ZCK_LOG_ERROR("%s", zck_get_error(zck));
             goto error2;
         }
         data = calloc(dict_size, 1);
@@ -178,24 +188,24 @@ int main (int argc, char *argv[]) {
         ssize_t read_size = zck_get_chunk_data(dict, data, dict_size);
         if(read_size != dict_size) {
             if(read_size < 0)
-                dprintf(STDERR_FILENO, "%s", zck_get_error(zck));
+                ZCK_LOG_ERROR("%s", zck_get_error(zck));
             else
-                dprintf(STDERR_FILENO,
+                ZCK_LOG_ERROR(
                         "Dict size doesn't match expected size: %li != %li\n",
                         read_size, dict_size);
             goto error2;
         }
         if(write(dst_fd, data, dict_size) != dict_size) {
-            dprintf(STDERR_FILENO, "Error writing to %s\n", out_name);
+            ZCK_LOG_ERROR("Error writing to %s\n", out_name);
             goto error2;
         }
         if(dict_size > 0) {
             int ret = zck_get_chunk_valid(dict);
             if(ret < 1) {
                 if(ret == -1)
-                    dprintf(STDERR_FILENO, "Data checksum failed verification\n");
+                    ZCK_LOG_ERROR("Data checksum failed verification\n");
                 else
-                    dprintf(STDERR_FILENO, "%s", zck_get_error(zck));
+                    ZCK_LOG_ERROR("%s", zck_get_error(zck));
                 goto error2;
             }
         }
@@ -205,7 +215,7 @@ int main (int argc, char *argv[]) {
     int ret = zck_validate_data_checksum(zck);
     if(ret < 1) {
         if(ret == -1)
-            dprintf(STDERR_FILENO, "Data checksum failed verification\n");
+            ZCK_LOG_ERROR("Data checksum failed verification\n");
         goto error2;
     }
 
@@ -215,23 +225,23 @@ int main (int argc, char *argv[]) {
     while(true) {
         ssize_t read = zck_read(zck, data, BUF_SIZE);
         if(read < 0) {
-            dprintf(STDERR_FILENO, "%s", zck_get_error(zck));
+            ZCK_LOG_ERROR("%s", zck_get_error(zck));
             goto error2;
         }
         if(read == 0)
             break;
         if(write(dst_fd, data, read) != read) {
-            dprintf(STDERR_FILENO, "Error writing to %s\n", out_name);
+            ZCK_LOG_ERROR("Error writing to %s\n", out_name);
             goto error2;
         }
         total += read;
     }
     if(!zck_close(zck)) {
-        dprintf(STDERR_FILENO, "%s", zck_get_error(zck));
+        ZCK_LOG_ERROR("%s", zck_get_error(zck));
         goto error2;
     }
     if(arguments.log_level <= ZCK_LOG_INFO)
-        dprintf(STDERR_FILENO, "Decompressed %lu bytes\n", (unsigned long)total);
+        ZCK_LOG_ERROR("Decompressed %lu bytes\n", (unsigned long)total);
     good_exit = true;
 error2:
     free(data);
@@ -244,4 +254,4 @@ error2:
     if(!good_exit)
         exit(1);
     exit(0);
-}
+}
\ No newline at end of file
index 82e132d62c0e68e4cf2432b8f837fe8eaade7431..60d240368338c6cc4c8ab344dd8469ae8fba1ce7 100644 (file)
@@ -8,6 +8,10 @@
 #define BUF_SIZE 32768
 #endif
 
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
 void version();
 
 #endif
index c6cf5c57cb828391f3470ef968ade6527a426fd9..e3ae55b94c98e351116a48e26acab969c23f8bb6 100644 (file)
--- a/src/zck.c
+++ b/src/zck.c
@@ -35,7 +35,9 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#ifndef _WIN32
 #include <libgen.h>
+#endif
 #include <unistd.h>
 #include <argp.h>
 #include <zck.h>
@@ -106,7 +108,7 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) {
             else if (!strcmp(arg, "sha512_128"))
                 arguments->chunk_hashtype = ZCK_HASH_SHA512_128;
             else {
-                dprintf(STDERR_FILENO, "Wrong value for chunk hashtype. \n "
+                ZCK_LOG_ERROR("Wrong value for chunk hashtype. \n "
                         "It should be one of sha1|sha256|sha512|sha512_128 instead of %s\n", arg);
                 return -EINVAL;
             }
@@ -170,7 +172,8 @@ int main (int argc, char *argv[]) {
     char *base_name = NULL;
     char *out_name = NULL;
     if(arguments.output == NULL) {
-        base_name = basename(arguments.args[0]);
+        // base_name = basename(arguments.args[0]);
+        base_name = arguments.args[0];
         out_name = malloc(strlen(base_name) + 5);
         assert(out_name);
         snprintf(out_name, strlen(base_name) + 5, "%s.zck", base_name);
@@ -185,10 +188,10 @@ int main (int argc, char *argv[]) {
     char *dict = NULL;
     off_t dict_size = 0;
     if(arguments.dict != NULL) {
-        int dict_fd = open(arguments.dict, O_RDONLY);
+        int dict_fd = open(arguments.dict, O_RDONLY | O_BINARY);
         if(dict_fd < 0) {
-            dprintf(STDERR_FILENO, "Unable to open dictionary %s for reading",
-                    arguments.dict);
+            ZCK_LOG_ERROR("Unable to open dictionary %s for reading",
+                          arguments.dict);
             perror("");
             exit(1);
         }
@@ -211,9 +214,9 @@ int main (int argc, char *argv[]) {
         close(dict_fd);
     }
 
-    int dst_fd = open(out_name, O_TRUNC | O_WRONLY | O_CREAT, 0666);
+    int dst_fd = open(out_name, O_TRUNC | O_WRONLY | O_CREAT | O_BINARY, 0666);
     if(dst_fd < 0) {
-        dprintf(STDERR_FILENO, "Unable to open %s", out_name);
+        ZCK_LOG_ERROR("Unable to open %s", out_name);
         perror("");
         if(dict) {
             free(dict);
@@ -225,12 +228,12 @@ int main (int argc, char *argv[]) {
 
     zckCtx *zck = zck_create();
     if(zck == NULL) {
-        dprintf(STDERR_FILENO, "%s", zck_get_error(NULL));
+        ZCK_LOG_ERROR("%s", zck_get_error(NULL));
         zck_clear_error(NULL);
         exit(1);
     }
     if(!zck_init_write(zck, dst_fd)) {
-        dprintf(STDERR_FILENO, "Unable to write to %s: %s", out_name,
+        ZCK_LOG_ERROR("Unable to write to %s: %s", out_name,
                 zck_get_error(zck));
         exit(1);
     }
@@ -239,56 +242,56 @@ int main (int argc, char *argv[]) {
     if(arguments.compression_format) {
         if(strncmp(arguments.compression_format, "zstd", 4) == 0) {
             if(!zck_set_ioption(zck, ZCK_COMP_TYPE, ZCK_COMP_ZSTD)) {
-                dprintf(STDERR_FILENO, "%s\n", zck_get_error(zck));
+                ZCK_LOG_ERROR("%s\n", zck_get_error(zck));
                 exit(1);
             }
         } else if(strncmp(arguments.compression_format, "none", 4) == 0) {
             if(!zck_set_ioption(zck, ZCK_COMP_TYPE, ZCK_COMP_NONE)) {
-                dprintf(STDERR_FILENO, "%s\n", zck_get_error(zck));
+                ZCK_LOG_ERROR("%s\n", zck_get_error(zck));
                 exit(1);
             }
         } else {
-            dprintf(STDERR_FILENO, "Unknown compression type: %s\n", arguments.compression_format);
+            ZCK_LOG_ERROR("Unknown compression type: %s\n", arguments.compression_format);
             exit(1);
         }
     }
     if(dict_size > 0) {
         if(!zck_set_soption(zck, ZCK_COMP_DICT, dict, dict_size)) {
-            dprintf(STDERR_FILENO, "%s\n", zck_get_error(zck));
+            ZCK_LOG_ERROR("%s\n", zck_get_error(zck));
             exit(1);
         }
     }
     free(dict);
     if(arguments.manual_chunk) {
         if(!zck_set_ioption(zck, ZCK_MANUAL_CHUNK, 1)) {
-            dprintf(STDERR_FILENO, "%s\n", zck_get_error(zck));
+            ZCK_LOG_ERROR("%s\n", zck_get_error(zck));
             exit(1);
         }
     }
     if(arguments.uncompressed) {
         if(!zck_set_ioption(zck, ZCK_UNCOMP_HEADER, 1)) {
-            dprintf(STDERR_FILENO, "%s\n", zck_get_error(zck));
+            ZCK_LOG_ERROR("%s\n", zck_get_error(zck));
             exit(1);
         }
     }
     if (arguments.chunk_hashtype != ZCK_HASH_UNKNOWN) {
         if(!zck_set_ioption(zck, ZCK_HASH_CHUNK_TYPE, arguments.chunk_hashtype)) {
-            dprintf(STDERR_FILENO, "Unable to set hash type %s\n", zck_get_error(zck));
+            ZCK_LOG_ERROR("Unable to set hash type %s\n", zck_get_error(zck));
             exit(1);
         }
     }
     char *data;
-    int in_fd = open(arguments.args[0], O_RDONLY);
+    int in_fd = open(arguments.args[0], O_RDONLY | O_BINARY);
     off_t in_size = 0;
     if(in_fd < 0) {
-        dprintf(STDERR_FILENO, "Unable to open %s for reading",
+        ZCK_LOG_ERROR("Unable to open %s for reading",
                 arguments.args[0]);
         perror("");
         exit(1);
     }
     in_size = lseek(in_fd, 0, SEEK_END);
     if(in_size < 0) {
-        dprintf(STDERR_FILENO, "Unable to seek to end of input file");
+        ZCK_LOG_ERROR("Unable to seek to end of input file");
         exit(1);
     }
     if(lseek(in_fd, 0, SEEK_SET) < 0) {
@@ -299,7 +302,7 @@ int main (int argc, char *argv[]) {
         data = malloc(in_size);
         assert(data);
         if(read(in_fd, data, in_size) < in_size) {
-            dprintf(STDERR_FILENO, "Unable to read from input file\n");
+            ZCK_LOG_ERROR("Unable to read from input file\n");
             exit(1);
         }
         close(in_fd);
@@ -331,7 +334,7 @@ int main (int argc, char *argv[]) {
         /* Buzhash rolling window */
         } else {
             if(zck_write(zck, data, in_size) < 0) {
-                dprintf(STDERR_FILENO, "%s", zck_get_error(zck));
+                ZCK_LOG_ERROR("%s", zck_get_error(zck));
                 exit(1);
             }
         }
@@ -342,7 +345,7 @@ int main (int argc, char *argv[]) {
         exit(1);
     }
     if(arguments.log_level <= ZCK_LOG_INFO) {
-        dprintf(STDERR_FILENO, "Wrote %lu bytes in %lu chunks\n",
+        ZCK_LOG_ERROR("Wrote %lu bytes in %lu chunks\n",
                 (unsigned long)(zck_get_data_length(zck) +
                                 zck_get_header_length(zck)),
                 (long)zck_get_chunk_count(zck));
@@ -350,4 +353,4 @@ int main (int argc, char *argv[]) {
 
     zck_free(&zck);
     close(dst_fd);
-}
+}
\ No newline at end of file
index 81fb3901f6db99fddb3b0ebf18bdbf75ed6df5b4..8fdc5388de384f130fbecde1e2c155a76aaa72cd 100644 (file)
@@ -109,42 +109,42 @@ int main (int argc, char *argv[]) {
 
     zck_set_log_level(arguments.log_level);
 
-    int src_fd = open(arguments.args[0], O_RDONLY);
+    int src_fd = open(arguments.args[0], O_RDONLY | O_BINARY);
     if(src_fd < 0) {
-        dprintf(STDERR_FILENO, "Unable to open %s\n", arguments.args[0]);
+        ZCK_LOG_ERROR("Unable to open %s\n", arguments.args[0]);
         perror("");
         exit(1);
     }
     zckCtx *zck_src = zck_create();
     if(zck_src == NULL) {
-        dprintf(STDERR_FILENO, "%s", zck_get_error(NULL));
+        ZCK_LOG_ERROR("%s", zck_get_error(NULL));
         zck_clear_error(NULL);
         exit(1);
     }
     if(!zck_init_read(zck_src, src_fd)) {
-        dprintf(STDERR_FILENO, "Error reading %s: %s", arguments.args[0],
+        ZCK_LOG_ERROR("Error reading %s: %s", arguments.args[0],
                 zck_get_error(zck_src));
         zck_free(&zck_src);
         exit(1);
     }
     close(src_fd);
 
-    int tgt_fd = open(arguments.args[1], O_RDONLY);
+    int tgt_fd = open(arguments.args[1], O_RDONLY | O_BINARY);
     if(tgt_fd < 0) {
-        dprintf(STDERR_FILENO, "Unable to open %s\n", arguments.args[1]);
+        ZCK_LOG_ERROR("Unable to open %s\n", arguments.args[1]);
         perror("");
         zck_free(&zck_src);
         exit(1);
     }
     zckCtx *zck_tgt = zck_create();
     if(zck_tgt == NULL) {
-        dprintf(STDERR_FILENO, "%s", zck_get_error(NULL));
+        ZCK_LOG_ERROR("%s", zck_get_error(NULL));
         zck_clear_error(NULL);
         zck_free(&zck_src);
         exit(1);
     }
     if(!zck_init_read(zck_tgt, tgt_fd)) {
-        dprintf(STDERR_FILENO, "Error reading %s: %s", arguments.args[1],
+        ZCK_LOG_ERROR("Error reading %s: %s", arguments.args[1],
                 zck_get_error(zck_tgt));
         zck_free(&zck_src);
         zck_free(&zck_tgt);
@@ -153,10 +153,10 @@ int main (int argc, char *argv[]) {
     close(tgt_fd);
 
     if(zck_get_chunk_hash_type(zck_tgt) != zck_get_chunk_hash_type(zck_src)) {
-        dprintf(STDERR_FILENO, "ERROR: Chunk hash types don't match:\n");
-        dprintf(STDERR_FILENO, "   %s: %s\n", arguments.args[0],
+        ZCK_LOG_ERROR("ERROR: Chunk hash types don't match:\n");
+        ZCK_LOG_ERROR("   %s: %s\n", arguments.args[0],
                 zck_hash_name_from_type(zck_get_chunk_hash_type(zck_tgt)));
-        dprintf(STDERR_FILENO, "   %s: %s\n", arguments.args[1],
+        ZCK_LOG_ERROR("   %s: %s\n", arguments.args[1],
                 zck_hash_name_from_type(zck_get_chunk_hash_type(zck_src)));
         zck_free(&zck_src);
         zck_free(&zck_tgt);
@@ -168,7 +168,7 @@ int main (int argc, char *argv[]) {
         exit(1);
 
     if(!zck_compare_chunk_digest(tgt_idx, src_idx))
-        dprintf(STDERR_FILENO, "WARNING: Dicts don't match\n");
+        ZCK_LOG_ERROR("WARNING: Dicts don't match\n");
     ssize_t dl_size = zck_get_header_length(zck_tgt);
     if(dl_size < 0)
         exit(1);
@@ -197,4 +197,4 @@ int main (int argc, char *argv[]) {
            (long unsigned)zck_get_chunk_count(zck_tgt));
     zck_free(&zck_tgt);
     zck_free(&zck_src);
-}
+}
\ No newline at end of file
index b19471ef7f8310cd0384a5a686b10859335489cc..8fdc5388de384f130fbecde1e2c155a76aaa72cd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018, 2020 Jonathan Dieter <jdieter@gmail.com>
+ * Copyright 2018 Jonathan Dieter <jdieter@gmail.com>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -24,8 +24,6 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#define _GNU_SOURCE
-
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
-#include <libgen.h>
 #include <unistd.h>
-#include <errno.h>
 #include <argp.h>
 #include <zck.h>
-#include <curl/curl.h>
 
 #include "util_common.h"
 
-static char doc[] = "zckdl - Download zchunk file";
+static char doc[] = "zck_delta_size - Calculate the difference between"
+                    " two zchunk files";
 
-static char args_doc[] = "<file>";
+static char args_doc[] = "<file 1> <file 2>";
 
 static struct argp_option options[] = {
-    {"verbose",        'v',  0,        0, "Increase verbosity"},
-    {"quiet",          'q',  0,        0,
-     "Only show warnings (can be specified twice to only show errors)"},
-    {"source",         's', "FILE",    0, "File to use as delta source"},
-    {"fail-no-ranges", 1000, 0,        0,
-     "If server doesn't support ranges, fail instead of downloading full file"},
-    {"version",        'V',  0,        0, "Show program version"},
+    {"verbose", 'v', 0,        0,
+     "Increase verbosity (can be specified more than once for debugging)"},
+    {"version", 'V', 0,        0, "Show program version"},
     { 0 }
 };
 
-static int range_attempt[] = {
-    255,
-    127,
-    7,
-    2,
-    1
-};
-
 struct arguments {
-  char *args[1];
+  char *args[2];
   zck_log_type log_level;
-  char *source;
-  int fail_no_ranges;
   bool exit;
 };
 
@@ -82,31 +64,17 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) {
 
     switch (key) {
         case 'v':
-            if(arguments->log_level > ZCK_LOG_INFO)
-                arguments->log_level = ZCK_LOG_INFO;
             arguments->log_level--;
             if(arguments->log_level < ZCK_LOG_DDEBUG)
                 arguments->log_level = ZCK_LOG_DDEBUG;
             break;
-        case 'q':
-            if(arguments->log_level < ZCK_LOG_INFO)
-                arguments->log_level = ZCK_LOG_INFO;
-            arguments->log_level += 1;
-            if(arguments->log_level > ZCK_LOG_NONE)
-                arguments->log_level = ZCK_LOG_NONE;
-            break;
-        case 's':
-            arguments->source = arg;
-            break;
         case 'V':
             version();
             arguments->exit = true;
             break;
-        case 1000:
-            arguments->fail_no_ranges = 1;
-            break;
+
         case ARGP_KEY_ARG:
-            if (state->arg_num >= 1) {
+            if (state->arg_num >= 2) {
                 argp_usage (state);
                 return EINVAL;
             }
@@ -115,7 +83,7 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) {
             break;
 
         case ARGP_KEY_END:
-            if (state->arg_num < 1) {
+            if (state->arg_num < 2) {
                 argp_usage (state);
                 return EINVAL;
             }
@@ -129,355 +97,104 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) {
 
 static struct argp argp = {options, parse_opt, args_doc, doc};
 
-typedef struct dlCtx {
-    CURL *curl;
-    zckDL *dl;
-    int fail_no_ranges;
-    int range_fail;
-    int max_ranges;
-} dlCtx;
-
-/* Fail if dl_ctx->fail_no_ranges is set and we get a 200 response */
-size_t dl_header_cb(char *b, size_t l, size_t c, void *dl_v) {
-    dlCtx *dl_ctx = (dlCtx*)dl_v;
-    if(dl_ctx->fail_no_ranges) {
-        long code = -1;
-        curl_easy_getinfo(dl_ctx->curl, CURLINFO_RESPONSE_CODE, &code);
-        if(code == 200) {
-            dl_ctx->range_fail = 1;
-            return 0;
-        }
-    }
-    return zck_header_cb(b, l, c, dl_ctx->dl);
-}
-
-/* Return 0 on error, -1 on 200 response (if dl_ctx->fail_no_ranges),
- * and 1 on complete success */
-int dl_range(dlCtx *dl_ctx, char *url, char *range, int is_chunk) {
-    if(dl_ctx == NULL || dl_ctx->dl == NULL) {
-        free(range);
-        dprintf(STDERR_FILENO, "Struct not defined\n");
-        return 0;
-    }
-
-    CURL *curl = dl_ctx->curl;
-    CURLcode res;
-
-    curl_easy_setopt(curl, CURLOPT_URL, url);
-    curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
-    curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, dl_header_cb);
-    curl_easy_setopt(curl, CURLOPT_HEADERDATA, dl_ctx);
-    if(is_chunk)
-        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, zck_write_chunk_cb);
-    else
-        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, zck_write_zck_header_cb);
-    curl_easy_setopt(curl, CURLOPT_WRITEDATA, dl_ctx->dl);
-    curl_easy_setopt(curl, CURLOPT_RANGE, range);
-    res = curl_easy_perform(curl);
-    free(range);
-
-    if(dl_ctx->range_fail)
-        return -1;
-
-    if(res != CURLE_OK) {
-        dprintf(STDERR_FILENO, "Download failed: %s\n",
-                curl_easy_strerror(res));
-        return 0;
-    }
-    long code;
-    curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &code);
-    if (code != 206 && code != 200) {
-        dprintf(STDERR_FILENO, "HTTP Error: %li when downloading %s\n", code,
-                url);
-        return 0;
-    }
-
-
-    return 1;
-}
-
-
-int dl_byte_range(dlCtx *dl_ctx, char *url, int start, int end) {
-    char *range = NULL;
-    zck_dl_reset(dl_ctx->dl);
-    if(start > -1 && end > -1)
-        range = zck_get_range(start, end);
-    return dl_range(dl_ctx, url, range, 0);
-}
-
-int dl_bytes(dlCtx *dl_ctx, char *url, size_t bytes, size_t start,
-             size_t *buffer_len, int log_level) {
-    if(start + bytes > *buffer_len) {
-        zckDL *dl = dl_ctx->dl;
-
-        int fd = zck_get_fd(zck_dl_get_zck(dl));
-
-        if(lseek(fd, *buffer_len, SEEK_SET) == -1) {
-            dprintf(STDERR_FILENO, "Seek to download location failed: %s\n",
-                    strerror(errno));
-            return 0;
-        }
-        if(*buffer_len >= start + bytes)
-            return 1;
-
-        int retval = dl_byte_range(dl_ctx, url, *buffer_len,
-                                   (start + bytes) - 1);
-        if(retval < 1)
-            return retval;
-
-        if(log_level <= ZCK_LOG_DEBUG)
-            dprintf(STDERR_FILENO, "Downloading %lu bytes at position %lu\n",
-                    (unsigned long)start+bytes-*buffer_len,
-                    (unsigned long)*buffer_len);
-        *buffer_len += start + bytes - *buffer_len;
-        if(lseek(fd, start, SEEK_SET) == -1) {
-            dprintf(STDERR_FILENO,
-                    "Seek to byte %lu of temporary file failed: %s\n",
-                    (unsigned long)start, strerror(errno));
-            return 0;
-        }
-    }
-    return 1;
-}
-
-int dl_header(CURL *curl, zckDL *dl, char *url, int fail_no_ranges,
-              int log_level) {
-    size_t buffer_len = 0;
-    size_t start = 0;
-
-    dlCtx dl_ctx = {0};
-    dl_ctx.fail_no_ranges = 1;
-    dl_ctx.dl = dl;
-    dl_ctx.curl = curl;
-    dl_ctx.max_ranges = 1;
-
-    /* Download minimum download size and read magic and hash type */
-    int retval = dl_bytes(&dl_ctx, url, zck_get_min_download_size(), start,
-                          &buffer_len, log_level);
-    if(retval < 1)
-        return retval;
-
-    zckCtx *zck = zck_dl_get_zck(dl);
-    if(zck == NULL)
-        return 0;
-
-    if(!zck_read_lead(zck))
-        return 0;
-    start = zck_get_lead_length(zck);
-    if(!dl_bytes(&dl_ctx, url, zck_get_header_length(zck) - start,
-                 start, &buffer_len, log_level))
-        return 0;
-    if(!zck_read_header(zck))
-        return 0;
-    return 1;
-}
-
 int main (int argc, char *argv[]) {
     struct arguments arguments = {0};
 
     /* Defaults */
-    arguments.log_level = ZCK_LOG_INFO;
+    arguments.log_level = ZCK_LOG_ERROR;
 
-    int retval = argp_parse (&argp, argc, argv, 0, 0, &arguments);
+    int retval = argp_parse(&argp, argc, argv, 0, 0, &arguments);
     if(retval || arguments.exit)
         exit(retval);
 
-    curl_global_init(CURL_GLOBAL_ALL);
-
     zck_set_log_level(arguments.log_level);
 
-    zckCtx *zck_src = NULL;
-    if(arguments.source) {
-        int src_fd = open(arguments.source, O_RDONLY);
-        if(src_fd < 0) {
-            dprintf(STDERR_FILENO, "Unable to open %s\n", arguments.source);
-            perror("");
-            exit(10);
-        }
-        zck_src = zck_create();
-        if(zck_src == NULL) {
-            dprintf(STDERR_FILENO, "%s", zck_get_error(NULL));
-            zck_clear_error(NULL);
-            exit(10);
-        }
-        if(!zck_init_read(zck_src, src_fd)) {
-            dprintf(STDERR_FILENO, "Unable to open %s: %s", arguments.source,
-                    zck_get_error(zck_src));
-            exit(10);
-        }
+    int src_fd = open(arguments.args[0], O_RDONLY | O_BINARY);
+    if(src_fd < 0) {
+        ZCK_LOG_ERROR("Unable to open %s\n", arguments.args[0]);
+        perror("");
+        exit(1);
     }
-
-    CURL *curl_ctx = curl_easy_init();
-    if(!curl_ctx) {
-        dprintf(STDERR_FILENO, "Unable to allocate %lu bytes for curl context\n",
-                (unsigned long)sizeof(CURL));
-        exit(10);
+    zckCtx *zck_src = zck_create();
+    if(zck_src == NULL) {
+        ZCK_LOG_ERROR("%s", zck_get_error(NULL));
+        zck_clear_error(NULL);
+        exit(1);
     }
+    if(!zck_init_read(zck_src, src_fd)) {
+        ZCK_LOG_ERROR("Error reading %s: %s", arguments.args[0],
+                zck_get_error(zck_src));
+        zck_free(&zck_src);
+        exit(1);
+    }
+    close(src_fd);
 
-    char *outname = basename(arguments.args[0]);
-    int dst_fd = open(outname, O_RDWR | O_CREAT, 0666);
-    if(dst_fd < 0) {
-        dprintf(STDERR_FILENO, "Unable to open %s: %s\n", outname,
-                strerror(errno));
-        exit(10);
+    int tgt_fd = open(arguments.args[1], O_RDONLY | O_BINARY);
+    if(tgt_fd < 0) {
+        ZCK_LOG_ERROR("Unable to open %s\n", arguments.args[1]);
+        perror("");
+        zck_free(&zck_src);
+        exit(1);
     }
     zckCtx *zck_tgt = zck_create();
     if(zck_tgt == NULL) {
-        dprintf(STDERR_FILENO, "%s", zck_get_error(NULL));
-        zck_clear_error(NULL);
-        exit(10);
-    }
-    if(!zck_init_adv_read(zck_tgt, dst_fd)) {
-        dprintf(STDERR_FILENO, "%s", zck_get_error(zck_tgt));
-        exit(10);
-    }
-
-    zckDL *dl = zck_dl_init(zck_tgt);
-    if(dl == NULL) {
-        dprintf(STDERR_FILENO, "%s", zck_get_error(NULL));
+        ZCK_LOG_ERROR("%s", zck_get_error(NULL));
         zck_clear_error(NULL);
-        exit(10);
-    }
-
-    int exit_val = 0;
-
-    retval = dl_header(curl_ctx, dl, arguments.args[0],
-                       arguments.fail_no_ranges, arguments.log_level);
-    if(!retval) {
-        exit_val = 10;
-        goto out;
-    }
-
-    /* The server doesn't support ranges */
-    if(retval == -1) {
-        if(arguments.fail_no_ranges) {
-            dprintf(STDERR_FILENO,
-                    "Server doesn't support ranges and --fail-no-ranges was "
-                    "set\n");
-            exit_val = 2;
-            goto out;
-        }
-        /* Download the full file */
-        lseek(dst_fd, 0, SEEK_SET);
-        if(ftruncate(dst_fd, 0) < 0) {
-            perror(NULL);
-            exit_val = 10;
-            goto out;
-        }
-        dlCtx dl_ctx = {0};
-        dl_ctx.dl = dl;
-        dl_ctx.curl = curl_ctx;
-        dl_ctx.max_ranges = 0;
-        if(!dl_byte_range(&dl_ctx, arguments.args[0], -1, -1)) {
-            exit_val = 10;
-            goto out;
-        }
-        lseek(dst_fd, 0, SEEK_SET);
-        if(!zck_read_lead(zck_tgt) || !zck_read_header(zck_tgt)) {
-            exit_val = 10;
-            goto out;
-        }
-    } else {
-        /* If file is already fully downloaded, let's get out of here! */
-        int retval = zck_find_valid_chunks(zck_tgt);
-        if(retval == 0) {
-            exit_val = 10;
-            goto out;
-        }
-        if(retval == 1) {
-            printf("Missing chunks: 0\n");
-            printf("Downloaded %lu bytes\n",
-                (long unsigned)zck_dl_get_bytes_downloaded(dl));
-            if(ftruncate(dst_fd, zck_get_length(zck_tgt)) < 0) {
-                perror(NULL);
-                exit_val = 10;
-                goto out;
+        zck_free(&zck_src);
+        exit(1);
+    }
+    if(!zck_init_read(zck_tgt, tgt_fd)) {
+        ZCK_LOG_ERROR("Error reading %s: %s", arguments.args[1],
+                zck_get_error(zck_tgt));
+        zck_free(&zck_src);
+        zck_free(&zck_tgt);
+        exit(1);
+    }
+    close(tgt_fd);
+
+    if(zck_get_chunk_hash_type(zck_tgt) != zck_get_chunk_hash_type(zck_src)) {
+        ZCK_LOG_ERROR("ERROR: Chunk hash types don't match:\n");
+        ZCK_LOG_ERROR("   %s: %s\n", arguments.args[0],
+                zck_hash_name_from_type(zck_get_chunk_hash_type(zck_tgt)));
+        ZCK_LOG_ERROR("   %s: %s\n", arguments.args[1],
+                zck_hash_name_from_type(zck_get_chunk_hash_type(zck_src)));
+        zck_free(&zck_src);
+        zck_free(&zck_tgt);
+        exit(1);
+    }
+    zckChunk *tgt_idx = zck_get_first_chunk(zck_tgt);
+    zckChunk *src_idx = zck_get_first_chunk(zck_src);
+    if(tgt_idx == NULL || src_idx == NULL)
+        exit(1);
+
+    if(!zck_compare_chunk_digest(tgt_idx, src_idx))
+        ZCK_LOG_ERROR("WARNING: Dicts don't match\n");
+    ssize_t dl_size = zck_get_header_length(zck_tgt);
+    if(dl_size < 0)
+        exit(1);
+    ssize_t total_size = zck_get_header_length(zck_tgt);
+    ssize_t matched_chunks = 0;
+    for(tgt_idx = zck_get_first_chunk(zck_tgt); tgt_idx;
+        tgt_idx = zck_get_next_chunk(tgt_idx)) {
+        bool found = false;
+        for(src_idx = zck_get_first_chunk(zck_src); src_idx;
+            src_idx = zck_get_next_chunk(src_idx)) {
+            if(zck_compare_chunk_digest(tgt_idx, src_idx)) {
+                found = true;
+                break;
             }
-            exit_val = 0;
-            goto out;
-        }
-        if(zck_src && !zck_copy_chunks(zck_src, zck_tgt)) {
-            exit_val = 10;
-            goto out;
         }
-        zck_reset_failed_chunks(zck_tgt);
-        dlCtx dl_ctx = {0};
-        dl_ctx.dl = dl;
-        dl_ctx.curl = curl_ctx;
-        dl_ctx.max_ranges = range_attempt[0];
-        dl_ctx.fail_no_ranges = 1;
-        int ra_index = 0;
-        printf("Missing chunks: %i\n", zck_missing_chunks(zck_tgt));
-        while(zck_missing_chunks(zck_tgt) > 0) {
-            dl_ctx.range_fail = 0;
-            zck_dl_reset(dl);
-            zckRange *range = zck_get_missing_range(zck_tgt, dl_ctx.max_ranges);
-            if(range == NULL || !zck_dl_set_range(dl, range)) {
-                exit_val = 10;
-                goto out;
-            }
-            while(range_attempt[ra_index] > 1 &&
-                  range_attempt[ra_index+1] > zck_get_range_count(range))
-                ra_index++;
-            char *range_string = zck_get_range_char(zck_src, range);
-            if(range_string == NULL) {
-                exit_val = 10;
-                goto out;
-            }
-            int retval = dl_range(&dl_ctx, arguments.args[0], range_string, 1);
-            if(retval == -1) {
-                if(dl_ctx.max_ranges > 1) {
-                    ra_index += 1;
-                    dl_ctx.max_ranges = range_attempt[ra_index];
-                }
-                dprintf(STDERR_FILENO,
-                        "Tried downloading too many ranges, reducing to %i\n",
-                        dl_ctx.max_ranges);
-            }
-            if(!zck_dl_set_range(dl, NULL)) {
-                exit_val = 10;
-                goto out;
-            }
-            zck_range_free(&range);
-            if(!retval) {
-                exit_val = 1;
-                goto out;
-            }
+        if(!found) {
+            dl_size += zck_get_chunk_comp_size(tgt_idx);
+        } else {
+            matched_chunks += 1;
         }
+        total_size += zck_get_chunk_comp_size(tgt_idx);
     }
-    printf("Downloaded %lu bytes\n",
-           (long unsigned)zck_dl_get_bytes_downloaded(dl));
-    if(ftruncate(dst_fd, zck_get_length(zck_tgt)) < 0) {
-        perror(NULL);
-        exit_val = 10;
-        goto out;
-    }
-
-    switch(zck_validate_data_checksum(zck_tgt)) {
-        case -1:
-            exit_val = 1;
-            break;
-        case 0:
-            exit_val = 1;
-            break;
-        default:
-            break;
-    }
-out:
-    if(exit_val > 0) {
-        if(zck_is_error(NULL)) {
-            dprintf(STDERR_FILENO, "%s", zck_get_error(NULL));
-            zck_clear_error(NULL);
-        }
-        if(zck_is_error(zck_src))
-            dprintf(STDERR_FILENO, "%s", zck_get_error(zck_src));
-        if(zck_is_error(zck_tgt))
-            dprintf(STDERR_FILENO, "%s", zck_get_error(zck_tgt));
-    }
-    zck_dl_free(&dl);
+    printf("Would download %li of %li bytes\n", (long)dl_size,
+           (long)total_size);
+    printf("Matched %li of %lu chunks\n", (long)matched_chunks,
+           (long unsigned)zck_get_chunk_count(zck_tgt));
     zck_free(&zck_tgt);
     zck_free(&zck_src);
-    curl_easy_cleanup(curl_ctx);
-    curl_global_cleanup();
-    exit(exit_val);
-}
+}
\ No newline at end of file
index e1885a065ff78e712511a13304eae085cb611290..a20ee3dcf2cd1dfceba7b7487a317f8e3c2dd975 100644 (file)
@@ -25,6 +25,7 @@
  */
 
 #define _GNU_SOURCE
+#define STDERR_FILENO 2
 
 #include <assert.h>
 #include <stdlib.h>
 #include <stdbool.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#ifndef _WIN32
 #include <sys/wait.h>
+#endif
 #include <fcntl.h>
+#ifndef _WIN32
 #include <libgen.h>
+#endif
 #include <dirent.h>
 #include <unistd.h>
 #include <argp.h>
@@ -119,8 +124,12 @@ static struct argp argp = {options, parse_opt, args_doc, doc};
 char *get_tmp_dir(char *old_dir) {
     char *dir = NULL;
     if(old_dir == NULL) {
-        char template[] = "zcktempXXXXXX";
+        char* template = "zcktempXXXXXX";
+        #ifdef _WIN32
+        char *tmpdir = getenv("TEMP");
+        #else
         char *tmpdir = getenv("TMPDIR");
+        #endif
 
         if(tmpdir == NULL) {
             tmpdir = "/tmp/";
@@ -129,6 +138,37 @@ char *get_tmp_dir(char *old_dir) {
             return NULL;
         }
 
+#ifdef _WIN32
+        char* prev_cwd;
+
+        // Get the current working directory:
+        if ((prev_cwd = _getcwd( NULL, 0 )) == NULL)
+        {
+            ZCK_LOG_ERROR("Could not find current workdir");
+            return NULL;
+        }
+        if (chdir(tmpdir) != 0)
+        {
+            ZCK_LOG_ERROR("Could not change to Temp Dir");
+            return NULL;
+        }
+        printf("generating temp name: ... \n");
+        errno_t err = _mktemp_s(template, 14);
+        if (err)
+        {
+            ZCK_LOG_ERROR("Could not generate temporary name");
+            return NULL;
+        }
+        if (_mkdir(template) != 0)
+        {
+            ZCK_LOG_ERROR("Could not create temp folder");
+            return NULL;
+        }
+        assert(chdir(template) == 0);
+        char* res = _getcwd(NULL, 0);
+        assert(chdir(prev_cwd));
+        return res;
+#else
         char *base_dir = calloc(strlen(template) + strlen(tmpdir) + 2, 1);
         assert(base_dir);
         int i=0;
@@ -146,6 +186,7 @@ char *get_tmp_dir(char *old_dir) {
             perror("ERROR: ");
             return NULL;
         }
+#endif
     } else {
         dir = calloc(strlen(old_dir) + 1, 1);
         assert(dir);
@@ -169,9 +210,9 @@ int main (int argc, char *argv[]) {
 
     zck_set_log_level(arguments.log_level);
 
-    int src_fd = open(arguments.args[0], O_RDONLY);
+    int src_fd = open(arguments.args[0], O_RDONLY | O_BINARY);
     if(src_fd < 0) {
-        dprintf(STDERR_FILENO, "Unable to open %s\n", arguments.args[0]);
+        ZCK_LOG_ERROR("Unable to open %s\n", arguments.args[0]);
         perror("");
         exit(1);
     }
@@ -191,14 +232,14 @@ int main (int argc, char *argv[]) {
     char *data = NULL;
     zckCtx *zck = zck_create();
     if(!zck_init_read(zck, src_fd)) {
-        dprintf(STDERR_FILENO, "%s", zck_get_error(zck));
+        ZCK_LOG_ERROR("%s", zck_get_error(zck));
         goto error2;
     }
 
     int ret = zck_validate_data_checksum(zck);
     if(ret < 1) {
         if(ret == -1)
-            dprintf(STDERR_FILENO, "Data checksum failed verification\n");
+            ZCK_LOG_ERROR("Data checksum failed verification\n");
         goto error2;
     }
 
@@ -209,7 +250,7 @@ int main (int argc, char *argv[]) {
             continue;
         ssize_t chunk_size = zck_get_chunk_size(idx);
         if(chunk_size < 0) {
-            dprintf(STDERR_FILENO, "%s", zck_get_error(zck));
+            ZCK_LOG_ERROR("%s", zck_get_error(zck));
             goto error2;
         }
         data = calloc(chunk_size, 1);
@@ -217,9 +258,9 @@ int main (int argc, char *argv[]) {
         ssize_t read_size = zck_get_chunk_data(idx, data, chunk_size);
         if(read_size != chunk_size) {
             if(read_size < 0)
-                dprintf(STDERR_FILENO, "%s", zck_get_error(zck));
+                ZCK_LOG_ERROR("%s", zck_get_error(zck));
             else
-                dprintf(STDERR_FILENO,
+                ZCK_LOG_ERROR(
                         "Chunk %li size doesn't match expected size: %li != %li\n",
                         zck_get_chunk_number(idx), read_size, chunk_size);
             goto error2;
@@ -229,15 +270,15 @@ int main (int argc, char *argv[]) {
         assert(dict_block);
         snprintf(dict_block, strlen(dir) + strlen(out_name) + 12, "%s/%s.%li",
                  dir, out_name, zck_get_chunk_number(idx));
-        int dst_fd = open(dict_block, O_TRUNC | O_WRONLY | O_CREAT, 0666);
+        int dst_fd = open(dict_block, O_TRUNC | O_WRONLY | O_CREAT | O_BINARY, 0666);
         if(dst_fd < 0) {
-            dprintf(STDERR_FILENO, "Unable to open %s", dict_block);
+            ZCK_LOG_ERROR("Unable to open %s", dict_block);
             perror("");
             free(dict_block);
             goto error2;
         }
         if(write(dst_fd, data, chunk_size) != chunk_size) {
-            dprintf(STDERR_FILENO, "Error writing to %s\n", dict_block);
+            ZCK_LOG_ERROR("Error writing to %s\n", dict_block);
             free(dict_block);
             goto error2;
         }
@@ -248,36 +289,47 @@ int main (int argc, char *argv[]) {
     snprintf(out_name + strlen(base_name) - 4, 7, ".zdict");
 
     if(!zck_close(zck)) {
-        dprintf(STDERR_FILENO, "%s", zck_get_error(zck));
+        ZCK_LOG_ERROR("%s", zck_get_error(zck));
         goto error2;
     }
 
     /* Create dictionary */
+#ifdef _WIN32
+    char buf[5000];
+    sprintf(buf, "zstd --train '%s' -r -o '%s'", dir, out_name);
+    int w = system(buf);
+    if (w < 0)
+    {
+        ZCK_LOG_ERROR("Error generating dict\n");
+        goto error2;
+    }
+#else
     int pid = fork();
     if(pid == 0) {
         execl("/usr/bin/zstd", "zstd", "--train", dir, "-r", "-o", out_name, NULL);
-        dprintf(STDERR_FILENO, "Unable to find /usr/bin/zstd\n");
+        ZCK_LOG_ERROR("Unable to find /usr/bin/zstd\n");
         exit(1);
     }
     int wstatus = 0;
     int w = waitpid(pid, &wstatus, 0);
+
     if (w == -1) {
-        dprintf(STDERR_FILENO, "Error waiting for zstd\n");
+        ZCK_LOG_ERROR("Error waiting for zstd\n");
         perror("");
         goto error2;
     }
     if(WEXITSTATUS(wstatus) != 0) {
-        dprintf(STDERR_FILENO, "Error generating dict\n");
+        ZCK_LOG_ERROR("Error generating dict\n");
         goto error2;
     }
-
+#endif
     /* Clean up temporary directory */
     if(!arguments.dir) {
         struct dirent *dp;
         DIR *dfd;
 
         if ((dfd = opendir(dir)) == NULL) {
-            dprintf(STDERR_FILENO, "Unable to read %s\n", dir);
+            ZCK_LOG_ERROR("Unable to read %s\n", dir);
             goto error2;
         }
 
@@ -289,23 +341,23 @@ int main (int argc, char *argv[]) {
             snprintf(full_path, strlen(dir) + strlen(dp->d_name) + 2, "%s/%s",
                      dir, dp->d_name);
             if(unlink(full_path) != 0) {
-                dprintf(STDERR_FILENO, "Unable to remove %s\n", full_path);
+                ZCK_LOG_ERROR("Unable to remove %s\n", full_path);
                 perror("");
                 err = true;
             } else {
                 if(arguments.log_level <= ZCK_LOG_INFO)
-                    dprintf(STDERR_FILENO, "Removed %s\n", full_path);
+                    ZCK_LOG_ERROR("Removed %s\n", full_path);
             }
             free(full_path);
         }
         closedir(dfd);
         if(!err) {
             if(rmdir(dir) != 0) {
-                dprintf(STDERR_FILENO, "Unable to remove %s\n", dir);
+                ZCK_LOG_ERROR("Unable to remove %s\n", dir);
                 perror("");
             }
         } else {
-            dprintf(STDERR_FILENO, "Errors encountered, not removing %s\n",
+            ZCK_LOG_ERROR("Errors encountered, not removing %s\n",
                     dir);
         }
     }
@@ -320,4 +372,4 @@ error2:
     if(!good_exit)
         exit(1);
     exit(0);
-}
+}
\ No newline at end of file
index 5a3b37c9bb3964068198606eaef6090cc44b564e..5c6acbbb8adb13e2999a6b151c8a93526655d6ba 100644 (file)
@@ -23,6 +23,7 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  */
+#define STDERR_FILENO 2
 
 #include <stdlib.h>
 #include <stdio.h>
@@ -123,7 +124,7 @@ int main (int argc, char *argv[]) {
 
     zck_set_log_level(arguments.log_level);
 
-    int src_fd = open(arguments.args[0], O_RDONLY);
+    int src_fd = open(arguments.args[0], O_RDONLY | O_BINARY);
     if(src_fd < 0) {
         printf("Unable to open %s\n", arguments.args[0]);
         perror("");
@@ -132,12 +133,12 @@ int main (int argc, char *argv[]) {
 
     zckCtx *zck = zck_create();
     if(zck == NULL) {
-        dprintf(STDERR_FILENO, "%s", zck_get_error(NULL));
+        ZCK_LOG_ERROR("%s", zck_get_error(NULL));
         zck_clear_error(NULL);
         exit(1);
     }
     if(!zck_init_read(zck, src_fd)) {
-        dprintf(STDERR_FILENO, "Error reading zchunk header: %s",
+        ZCK_LOG_ERROR("Error reading zchunk header: %s",
                 zck_get_error(zck));
         zck_free(&zck);
         exit(1);
@@ -172,16 +173,16 @@ int main (int argc, char *argv[]) {
             chk=zck_get_next_chunk(chk)) {
             char *digest = zck_get_chunk_digest(chk);
             if(digest == NULL) {
-                dprintf(STDERR_FILENO, "%s", zck_get_error(zck));
+                ZCK_LOG_ERROR("%s", zck_get_error(zck));
                 exit(1);
             }
             char *digest_uncompressed = zck_get_chunk_digest_uncompressed(chk);
             if (!digest_uncompressed)
                 digest_uncompressed = "";
 
-           if (chk == zck_get_first_chunk(zck)) {
-                   bool has_uncompressed = (strlen(digest_uncompressed) > 0);
-                   if (has_uncompressed)
+        if (chk == zck_get_first_chunk(zck)) {
+            bool has_uncompressed = (strlen(digest_uncompressed) > 0);
+            if (has_uncompressed)
                         printf("       Chunk Checksum %*cChecksum uncompressed %*c       Start    Comp size         Size\n",
                            (((int)zck_get_chunk_digest_size(zck) * 2) - (int)strlen("Checksum")), ' ',
                            ((int)zck_get_chunk_digest_size(zck) * 2) - (int)strlen("Uncompressed Checksum"), ' ');
@@ -189,7 +190,7 @@ int main (int argc, char *argv[]) {
                         printf("       Chunk Checksum %*c        Start    Comp size         Size\n",
                               (((int)zck_get_chunk_digest_size(zck) * 2) - (int)strlen("Checksum")), ' ');
 
-           }
+        }
             printf("%12lu %s %s %12lu %12lu %12lu",
                    (long unsigned)zck_get_chunk_number(chk),
                    digest,
@@ -215,4 +216,4 @@ int main (int argc, char *argv[]) {
     }
     zck_free(&zck);
     return 1-valid_cks;
-}
+}
\ No newline at end of file
index 111132c65c0b2901b1a5b89a200de2df1f00db73..f4890691b28af00fa4f844ef41868bf50387dd19 100644 (file)
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#ifndef _WIN32
 #include <libgen.h>
+#endif
 #include <errno.h>
 #include <zck.h>
-#include <libgen.h>
 #include "zck_private.h"
 #include "util.h"
 
@@ -45,12 +46,12 @@ int main (int argc, char *argv[]) {
     strcpy(path, argv[1]);
 
     char *base_name = basename(path);
-    int in = open(argv[1], O_RDONLY);
+    int in = open(argv[1], O_RDONLY | O_BINARY);
     if(in < 0) {
         perror("Unable to open LICENSE.header.new.nodict.fodt.zck for reading");
         exit(1);
     }
-    int tgt = open(base_name, O_RDWR | O_CREAT, 0666);
+    int tgt = open(base_name, O_RDWR | O_CREAT | O_BINARY, 0666);
     if(tgt < 0) {
         perror("Unable to open LICENSE.header.new.nodict.fodt.zck for writing");
         exit(1);
@@ -75,7 +76,7 @@ int main (int argc, char *argv[]) {
     }
 
     /* Open source zchunk file and read header */
-    int src = open(argv[2], O_RDONLY);
+    int src = open(argv[2], O_RDONLY | O_BINARY);
     if(src < 0) {
         perror("Unable to open LICENSE.nodict.fodt.zck for reading");
         exit(1);
@@ -120,4 +121,4 @@ int main (int argc, char *argv[]) {
     zck_free(&src_zck);
     free(path);
     return 0;
-}
+}
\ No newline at end of file
index 92bf2ae7216324739d0dcbb7abe5eb31bfe1f4bb..28dbac2ff8a629f6392b3aaeea8350f100e1ad96 100644 (file)
@@ -41,7 +41,7 @@ static char *checksum="8efaeb8e7b3d51a943353f7e6ca4a22266f18c3ef10478b20d50040f4
 
 int main (int argc, char *argv[]) {
     /* Create empty zchunk file */
-    int out = open("empty.zck", O_WRONLY | O_CREAT | O_TRUNC, 0666);
+    int out = open("empty.zck", O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
     if(out < 0) {
         perror("Unable to open empty.zck for writing");
         exit(1);
@@ -60,7 +60,7 @@ int main (int argc, char *argv[]) {
     zck_free(&zck);
 
     /* Open zchunk file and check that checksum matches */
-    int in = open("empty.zck", O_RDONLY);
+    int in = open("empty.zck", O_RDONLY | O_BINARY);
     if(in < 0) {
         perror("Unable to open empty.zck for reading");
         exit(1);
@@ -108,4 +108,4 @@ int main (int argc, char *argv[]) {
     zck_free(&zck);
     free(data);
     return 0;
-}
+}
\ No newline at end of file
index 0e08081f0916a3f0eb055803b8a3def27fe376fa..de07252a0006176f8ae21d2ff72a98108d2cb736 100644 (file)
@@ -39,7 +39,7 @@
 
 int main (int argc, char *argv[]) {
     /* Open zchunk file and verify that an invalid checksum will fail */
-    int in = open(argv[1], O_RDONLY);
+    int in = open(argv[1], O_RDONLY | O_BINARY);
     if(in < 0) {
         perror("Unable to open empty.optelems.zck for reading");
         exit(1);
index 6e5257468d4bbc528b10bf9a4dfd910dec5c88c5..e291237bc0671b66e02852d9223730b65c9276d0 100644 (file)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  */
+#ifdef _WIN32
+#define ZCK_WARN_UNUSED
+#else
+#define ZCK_WARN_UNUSED __attribute__ ((warn_unused_result))
+#endif
+
+// O_BINARY is not defined on UNIX systems so we define it here for
+// portability purposes
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
 
 char *get_hash(char *data, size_t length, int type)
-    __attribute__ ((warn_unused_result));
+    ZCK_WARN_UNUSED;
 
index ffef3d9b953c8e3436b5d1ca886c71eb8d42a974..ceaa53d5c0d0ff7dfc2ef42ab358b5107d3d17c1 100644 (file)
@@ -1,35 +1,59 @@
 util_sources = []
 subdir('lib')
-incdir = include_directories(['lib', '../src/lib', '../include'])
+incdir = [include_directories(['lib', '../src/lib', '../include'])]
+if build_machine.system() == 'windows'
+    incdir += include_directories('../src/lib/win32')
+endif
+
+if host_machine.system() == 'windows'
+    preprocessor_defines = '-DZCHUNK_STATIC_LIB=1'
+    win_basename = ['../src/lib/win32/basename.c']
+else
+    preprocessor_defines = []
+    win_basename = []
+endif
+
+
 empty = executable('empty', ['empty.c'] + util_sources,
                    include_directories: incdir,
-                   dependencies: [zstd_dep, openssl_dep])
+                   dependencies: [zstd_dep, openssl_dep],
+                   c_args: preprocessor_defines)
 optelems = executable('optelems', ['optelems.c'] + util_sources,
                      include_directories: incdir,
-                     dependencies: [zstd_dep, openssl_dep])
-copy_chunks = executable('copy_chunks', ['copy_chunks.c'] + util_sources,
+                     dependencies: [zstd_dep, openssl_dep],
+                     c_args: preprocessor_defines)
+copy_chunks = executable('copy_chunks', ['copy_chunks.c'] + win_basename + util_sources,
                      include_directories: incdir,
-                     dependencies: [zstd_dep, openssl_dep])
+                     dependencies: [zstd_dep, openssl_dep],
+                     c_args: preprocessor_defines)
 
 invalid_input_checksum = executable('invalid_input_checksum',
                                     ['invalid_input_checksum.c'] + util_sources,
                                     include_directories: incdir,
-                                    dependencies: [zstd_dep, openssl_dep])
+                                    dependencies: [zstd_dep, openssl_dep],
+                                    c_args: preprocessor_defines)
 read_single_chunk = executable('read_single_chunk',
                                ['read_single_chunk.c'] + util_sources,
                                include_directories: incdir,
-                               dependencies: [zstd_dep, openssl_dep])
+                               dependencies: [zstd_dep, openssl_dep],
+                               c_args: preprocessor_defines)
 read_single_comp_chunk = executable('read_single_comp_chunk',
                                     ['read_single_comp_chunk.c'] + util_sources,
                                     include_directories: incdir,
-                                    dependencies: [zstd_dep, openssl_dep])
-shacheck = executable('shacheck', ['shacheck.c'] + util_sources, include_directories: incdir, dependencies: [zstd_dep, openssl_dep])
+                                    dependencies: [zstd_dep, openssl_dep],
+                                    c_args: preprocessor_defines)
+shacheck = executable('shacheck', 
+                      ['shacheck.c'] + util_sources,
+                      include_directories: incdir,
+                      dependencies: [zstd_dep, openssl_dep],
+                      c_args: preprocessor_defines)
 zck_cmp_uncomp = executable(
     'zck_cmp_uncomp',
     ['zck_cmp_uncomp.c'],
-    include_directories: incdir,
+    include_directories: inc + incdir,
     dependencies: argplib,
     link_with: zcklib,
+    c_args: preprocessor_defines,
     install: false
 )
 file_path = join_paths(meson.source_root(), 'test/files')
index ab96890c4c81bfba2f601ab09d4ff9fff7edc182..f6d53167a13e3f6795bdce317a95a3cae18dcadf 100644 (file)
@@ -42,7 +42,7 @@ int main (int argc, char *argv[]) {
     char data[1000] = {0};
 
     /* Open zchunk file and verify that zck->has_optional_elems is set */
-    int in = open(argv[1], O_RDONLY);
+    int in = open(argv[1], O_RDONLY | O_BINARY);
     if(in < 0) {
         perror("Unable to open empty.optelems.zck for reading");
         exit(1);
index 432cb5df3657d4d6fc1975c07e374576102b67bd..6d19799caa65854ccfe921b961ae3123f921a73c 100644 (file)
@@ -42,7 +42,7 @@ char *echecksum =
 
 int main (int argc, char *argv[]) {
     /* Open zchunk file and verify second checksum */
-    int in = open(argv[1], O_RDONLY);
+    int in = open(argv[1], O_RDONLY | O_BINARY);
     if(in < 0) {
         perror("Unable to open LICENSE.dict.fodt.zck for reading");
         exit(1);
index 82c94ed37d3fc65dd2c275a1052d2cd19d14f0a5..61ecedc4756aa108f43130eac8195c4810b3bc43 100644 (file)
@@ -42,7 +42,7 @@ char *echecksum =
 
 int main (int argc, char *argv[]) {
     /* Open zchunk file and verify second checksum */
-    int in = open(argv[1], O_RDONLY);
+    int in = open(argv[1], O_RDONLY | O_BINARY);
     if(in < 0) {
         perror("Unable to open LICENSE.dict.fodt.zck for reading");
         exit(1);
index 5b098d4817dbfb8bf0235a9d41135bd21f0a5353..995434299cc9babca00a57268dbc0eb314b72905 100644 (file)
@@ -34,7 +34,9 @@
 #include <fcntl.h>
 #include <errno.h>
 #include <zck.h>
+#ifndef _WIN32
 #include <sys/wait.h>
+#endif
 #include "zck_private.h"
 #include "util.h"
 
@@ -65,6 +67,9 @@ int main (int argc, char *argv[]) {
         args[i] = untaint(argv[i+3]);
 
     int status;
+#ifdef _WIN32
+    status = system(cmd);
+#else
     pid_t child_pid;
 
     child_pid = fork();
@@ -78,13 +83,14 @@ int main (int argc, char *argv[]) {
     } else {
         waitpid(child_pid, &status, 0);
     }
+#endif
     if (status != 0) {
         printf("Error running command\n");
         exit(1);
     }
 
     /* Open zchunk file and check that checksum matches */
-    int in = open(outf, O_RDONLY);
+    int in = open(outf, O_RDONLY | O_BINARY);
     if(in < 0) {
         perror("");
         printf("Unable to open %s for reading", outf);
@@ -111,4 +117,4 @@ int main (int argc, char *argv[]) {
         free(args[i]);
     free(args);
     return 0;
-}
+}
\ No newline at end of file
index f7952c11bd6a3896084a67d86273f41e13e71da4..38dceed827e411ca4a1bc7683696a3eee0d0b615 100644 (file)
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#ifndef _WIN32
 #include <libgen.h>
+#endif
 #include <unistd.h>
 #include <argp.h>
 #include <zck.h>
+#include "util.h"
 
 #define BUFSIZE 16384
 static char doc[] = "zck_gen_header - Compare a file with a zck and reports which chunks changed";
@@ -119,30 +122,30 @@ int main (int argc, char *argv[]) {
         exit(retval);
 
     if (argc < 1) {
-               dprintf(STDERR_FILENO, "Usage : %s filename", argv[0]);
-               exit(1);
+        ZCK_LOG_ERROR("Usage : %s filename", argv[0]);
+        exit(1);
     }
 
     zck_set_log_level(arguments.log_level);
-    int dst_fd = open("/dev/null", O_TRUNC | O_WRONLY | O_CREAT, 0666);
+    int dst_fd = open("/dev/null", O_TRUNC | O_WRONLY | O_CREAT | O_BINARY, 0666);
 
     zckCtx *zckSrc = zck_create();
     zckCtx *zckDst = zck_create();
     if(!zckSrc || !zckDst) {
-        dprintf(STDERR_FILENO, "%s", zck_get_error(NULL));
+        ZCK_LOG_ERROR("%s", zck_get_error(NULL));
         zck_clear_error(NULL);
         exit(1);
     }
     if(!zck_init_write(zckSrc, dst_fd)) {
-        dprintf(STDERR_FILENO, "Unable to write %s ",
+        ZCK_LOG_ERROR("Unable to write %s ",
                 zck_get_error(zckSrc));
         exit(1);
     }
    
-    int in_fd = open(arguments.args[0], O_RDONLY);
+    int in_fd = open(arguments.args[0], O_RDONLY | O_BINARY);
     off_t in_size = 0;
     if(in_fd < 0) {
-        dprintf(STDERR_FILENO, "Unable to open %s for reading",
+        ZCK_LOG_ERROR("Unable to open %s for reading",
                 arguments.args[0]);
         perror("");
         exit(1);
@@ -151,16 +154,16 @@ int main (int argc, char *argv[]) {
     /*
      * Read header in the zck file
      */
-    int zck_fd = open(arguments.args[1], O_RDONLY);
+    int zck_fd = open(arguments.args[1], O_RDONLY | O_BINARY);
     if(zck_fd < 0) {
-        dprintf(STDERR_FILENO, "Unable to open %s for reading",
+        ZCK_LOG_ERROR("Unable to open %s for reading",
                 arguments.args[1]);
         perror("");
         exit(1);
     }
 
     if(!zck_init_read(zckDst, zck_fd)) {
-        dprintf(STDERR_FILENO, "Error reading zchunk header: %s",
+        ZCK_LOG_ERROR("Error reading zchunk header: %s",
                 zck_get_error(zckDst));
         zck_free(&zckSrc);
         zck_free(&zckDst);
@@ -169,7 +172,7 @@ int main (int argc, char *argv[]) {
 
     in_size = lseek(in_fd, 0, SEEK_END);
     if(in_size < 0) {
-        dprintf(STDERR_FILENO, "Unable to seek to end of input file");
+        ZCK_LOG_ERROR("Unable to seek to end of input file");
         exit(1);
     }
     if(lseek(in_fd, 0, SEEK_SET) < 0) {
@@ -178,33 +181,33 @@ int main (int argc, char *argv[]) {
     }
 
     if(!zck_set_ioption(zckSrc, ZCK_UNCOMP_HEADER, 1)) {
-        dprintf(STDERR_FILENO, "%s\n", zck_get_error(zckSrc));
+        ZCK_LOG_ERROR("%s\n", zck_get_error(zckSrc));
         exit(1);
     }
     if(!zck_set_ioption(zckSrc, ZCK_COMP_TYPE, ZCK_COMP_NONE))
         exit(1);
     if(!zck_set_ioption(zckSrc, ZCK_HASH_CHUNK_TYPE, ZCK_HASH_SHA256)) {
-        dprintf(STDERR_FILENO, "Unable to set hash type %s\n", zck_get_error(zckSrc));
+        ZCK_LOG_ERROR("Unable to set hash type %s\n", zck_get_error(zckSrc));
         exit(1);
     }
 
     char *buf = malloc(BUFSIZE);
     if (!buf) {
-        dprintf(STDERR_FILENO, "Unable to allocate buffer\n");
+        ZCK_LOG_ERROR("Unable to allocate buffer\n");
         exit(1);
     }
     ssize_t n;
     while ((n = read(in_fd, buf, BUFSIZE)) > 0) {
         if (zck_write(zckSrc, buf, n) < 0) {
-            dprintf(STDERR_FILENO, "zck_write failed: %s\n", zck_get_error(zckSrc));
+            ZCK_LOG_ERROR("zck_write failed: %s\n", zck_get_error(zckSrc));
             exit(1);
         }
     }
     /*
      * Start comparison
      */
-    dprintf(STDOUT_FILENO, "Compare original image with chunks in zck\n");
-    dprintf(STDOUT_FILENO, "-----------------------------------------\n");
+    printf("Compare original image with chunks in zck\n");
+    printf("-----------------------------------------\n");
     
     zck_generate_hashdb(zckSrc);
     zck_find_matching_chunks(zckSrc, zckDst);
@@ -213,7 +216,7 @@ int main (int argc, char *argv[]) {
     size_t todwl = 0;
     size_t reuse = 0;
     while (iter) {
-        dprintf(STDOUT_FILENO, "%12lu %s %s %12lu %12lu\n",
+        printf("%12lu %s %s %12lu %12lu\n",
                 zck_get_chunk_number(iter),
                 zck_get_chunk_valid(iter) ? "SRC" : "DST",
                 zck_get_chunk_digest_uncompressed(iter),
@@ -229,12 +232,12 @@ int main (int argc, char *argv[]) {
         iter = zck_get_next_chunk(iter);
     }
 
-    dprintf (STDOUT_FILENO, "\n\nTotal to be reused : %12lu\n", reuse);
-    dprintf (STDOUT_FILENO, "Total to be downloaded : %12lu\n", todwl);
+    printf("\n\nTotal to be reused : %12lu\n", reuse);
+    printf("Total to be downloaded : %12lu\n", todwl);
 
     close(in_fd);
     close(zck_fd);
     zck_free(&zckSrc);
     zck_free(&zckDst);
     close(dst_fd);
-}
+}
\ No newline at end of file