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:
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'
#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
*******************************************************************/
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
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
--- /dev/null
+#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
--- /dev/null
+/*
+ * 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
--- /dev/null
+#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
void *ctx;
};
+#ifndef CURLINC_CURL_H
typedef void CURL;
+#endif
typedef struct zckMP {
int state;
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;
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
+)
*/
#define _GNU_SOURCE
+#define STDERR_FILENO 2
#include <assert.h>
#include <stdlib.h>
#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>
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
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);
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;
}
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);
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;
}
}
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;
}
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);
if(!good_exit)
exit(1);
exit(0);
-}
+}
\ No newline at end of file
#define BUF_SIZE 32768
#endif
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
void version();
#endif
#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>
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;
}
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);
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);
}
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);
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);
}
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) {
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);
/* 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);
}
}
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));
zck_free(&zck);
close(dst_fd);
-}
+}
\ No newline at end of file
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);
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);
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);
(long unsigned)zck_get_chunk_count(zck_tgt));
zck_free(&zck_tgt);
zck_free(&zck_src);
-}
+}
\ No newline at end of file
/*
- * 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:
* 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;
};
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;
}
break;
case ARGP_KEY_END:
- if (state->arg_num < 1) {
+ if (state->arg_num < 2) {
argp_usage (state);
return EINVAL;
}
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
*/
#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>
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/";
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;
perror("ERROR: ");
return NULL;
}
+#endif
} else {
dir = calloc(strlen(old_dir) + 1, 1);
assert(dir);
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);
}
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;
}
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);
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;
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;
}
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;
}
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);
}
}
if(!good_exit)
exit(1);
exit(0);
-}
+}
\ No newline at end of file
* 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>
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("");
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);
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"), ' ');
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,
}
zck_free(&zck);
return 1-valid_cks;
-}
+}
\ No newline at end of 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"
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);
}
/* 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);
zck_free(&src_zck);
free(path);
return 0;
-}
+}
\ No newline at end of file
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);
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);
zck_free(&zck);
free(data);
return 0;
-}
+}
\ No newline at end of file
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);
* 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;
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')
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);
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);
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);
#include <fcntl.h>
#include <errno.h>
#include <zck.h>
+#ifndef _WIN32
#include <sys/wait.h>
+#endif
#include "zck_private.h"
#include "util.h"
args[i] = untaint(argv[i+3]);
int status;
+#ifdef _WIN32
+ status = system(cmd);
+#else
pid_t child_pid;
child_pid = fork();
} 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);
free(args[i]);
free(args);
return 0;
-}
+}
\ No newline at end of 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";
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);
/*
* 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);
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) {
}
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);
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),
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