diff --git a/Makefile.am b/Makefile.am index 2808ad5d..c2645362 100644 --- a/Makefile.am +++ b/Makefile.am @@ -12,7 +12,8 @@ snapraid_SOURCES = \ sync.c \ check.c \ parity.c \ - handle.c + handle.c \ + fnmatch.c noinst_HEADERS = \ portable.h \ @@ -31,7 +32,8 @@ noinst_HEADERS = \ tommyarray.c \ tommyhash.c \ tommyhashdyn.c \ - tommylist.c + tommylist.c \ + fnmatch.h mktest_SOURCES = \ mktest.c @@ -65,36 +67,36 @@ check-local: mkdir test/disk2 mkdir test/disk3 echo --- As empty, sync and check - $(VALGRIND) ./snapraid -c $(srcdir)/test.conf sync - $(VALGRIND) ./snapraid -c $(srcdir)/test.conf check + $(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf sync + $(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf check echo --- Create some files, sync and check - ./mktest generate 1 3 1000 4000 - $(VALGRIND) ./snapraid -c $(srcdir)/test.conf sync - $(VALGRIND) ./snapraid -c $(srcdir)/test.conf check + $(TESTENV) ./mktest$(EXEEXT) generate 1 3 1000 4000 + $(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf sync + $(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf check echo --- Create some more files, sync and check - ./mktest generate 2 3 1000 4000 - $(VALGRIND) ./snapraid -c $(srcdir)/test.conf sync - $(VALGRIND) ./snapraid -c $(srcdir)/test.conf check + $(TESTENV) ./mktest$(EXEEXT) generate 2 3 1000 4000 + $(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf sync + $(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf check echo --- Delete some files, fix and check rm test/disk1/a* - $(VALGRIND) ./snapraid -c $(srcdir)/test.conf check 2>/dev/null - $(VALGRIND) ./snapraid -c $(srcdir)/test.conf fix 2>/dev/null - $(VALGRIND) ./snapraid -c $(srcdir)/test.conf check + $(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf check 2>/dev/null + $(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf fix 2>/dev/null + $(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf check echo --- Delete the parity, fix and check rm test/parity - $(VALGRIND) ./snapraid -c $(srcdir)/test.conf check 2>/dev/null - $(VALGRIND) ./snapraid -c $(srcdir)/test.conf fix 2>/dev/null - $(VALGRIND) ./snapraid -c $(srcdir)/test.conf check + $(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf check 2>/dev/null + $(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf fix 2>/dev/null + $(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf check echo --- Corrupt the parity, fix and check - ./mktest damage 1 10 10000 test/parity - $(VALGRIND) ./snapraid -c $(srcdir)/test.conf check 2>/dev/null - $(VALGRIND) ./snapraid -c $(srcdir)/test.conf fix 2>/dev/null - $(VALGRIND) ./snapraid -c $(srcdir)/test.conf check + $(TESTENV) ./mktest$(EXEEXT) damage 1 10 10000 test/parity + $(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf check 2>/dev/null + $(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf fix 2>/dev/null + $(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf check echo --- Corrupt some files, fix and check - ./mktest damage 1 1 500 test/disk2/b* - $(VALGRIND) ./snapraid -c $(srcdir)/test.conf check 2>/dev/null - $(VALGRIND) ./snapraid -c $(srcdir)/test.conf fix 2>/dev/null - $(VALGRIND) ./snapraid -c $(srcdir)/test.conf check + $(TESTENV) ./mktest$(EXEEXT) damage 1 1 500 test/disk2/b* + $(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf check 2>/dev/null + $(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf fix 2>/dev/null + $(TESTENV) ./snapraid$(EXEEXT) -c $(srcdir)/test.conf check echo Success! # Valgrind testing @@ -141,7 +143,8 @@ cachegrind: DISTWIN = \ snapraid.txt \ snapraid.html \ - snapraid.exe + snapraid.exe \ + snapraid.conf.example distwindows: $(DISTWIN) rm -f $(PACKAGE)-$(VERSION)-windows-x86.zip diff --git a/configure.ac b/configure.ac index 716bcf13..bd31841d 100644 --- a/configure.ac +++ b/configure.ac @@ -10,6 +10,7 @@ dnl Checks for programs. AC_PROG_CC AC_USE_SYSTEM_EXTENSIONS AC_CHECK_PROG([VALGRIND],[valgrind],[valgrind --leak-check=full --track-fds=yes --error-exitcode=1],[]) +AC_CHECK_PROG([WINE],[wine],[wine],[]) dnl Checks for libraries. AC_SYS_LARGEFILE @@ -19,7 +20,7 @@ AC_HEADER_ASSERT AC_HEADER_STDC AC_HEADER_DIRENT AC_HEADER_TIME -AC_CHECK_HEADERS([fcntl.h stddef.h stdint.h stdlib.h string.h sys/time.h unistd.h getopt.h fnmatch.h]) +AC_CHECK_HEADERS([fcntl.h stddef.h stdint.h stdlib.h string.h sys/time.h unistd.h getopt.h fnmatch.h io.h]) dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST @@ -38,7 +39,7 @@ dnl Checks for library functions. AC_SYS_LARGEFILE AC_CHECK_FUNCS([memset strchr strerror strrchr]) AC_CHECK_FUNCS([getopt getopt_long snprintf vsnprintf]) -AC_CHECK_FUNCS([ftruncate fsync posix_fallocate posix_fadvise pread pwrite fgetc_unlocked ferror_unlocked]) +AC_CHECK_FUNCS([ftruncate fsync posix_fallocate posix_fadvise pread pwrite fgetc_unlocked ferror_unlocked fnmatch]) dnl Checks for architecture AC_C_BIGENDIAN @@ -46,6 +47,13 @@ AC_C_BIGENDIAN dnl Checks for compiler AC_CHECK_CC_OPT([-Wall], CFLAGS="$CFLAGS -Wall", []) +dnl Checks for test environment +AS_CASE([$host], + [*-*-mingw*], [TESTENV="$WINE"], + [TESTENV="$VALGRIND"] +) +AC_SUBST([TESTENV]) + AC_CONFIG_FILES([Makefile]) AC_OUTPUT diff --git a/fnmatch.c b/fnmatch.c new file mode 100644 index 00000000..ea916c04 --- /dev/null +++ b/fnmatch.c @@ -0,0 +1,496 @@ +/* Copyright (C) 1991, 92, 93, 96, 97, 98, 99 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#if HAVE_CONFIG_H +# include +#endif + +#if !HAVE_FNMATCH + +/* Enable GNU extensions in fnmatch.h. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif + +#include +#if HAVE_FNMATCH_H +#include +#else +#include "fnmatch.h" +#endif +#include + +#if HAVE_STRING_H || defined _LIBC +# include +#else +# include +#endif + +#if defined STDC_HEADERS || defined _LIBC +# include +#endif + +/* For platforms which support the ISO C amendment 1 functionality we + support user defined character classes. */ +#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) +/* Solaris 2.5 has a bug: must be included before . */ +# include +# include +#endif + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#if defined _LIBC || !defined __GNU_LIBRARY__ + + +# if defined STDC_HEADERS || !defined isascii +# define ISASCII(c) 1 +# else +# define ISASCII(c) isascii(c) +# endif + +# ifdef isblank +# define ISBLANK(c) (ISASCII (c) && isblank (c)) +# else +# define ISBLANK(c) ((c) == ' ' || (c) == '\t') +# endif +# ifdef isgraph +# define ISGRAPH(c) (ISASCII (c) && isgraph (c)) +# else +# define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c)) +# endif + +# define ISPRINT(c) (ISASCII (c) && isprint (c)) +# define ISDIGIT(c) (ISASCII (c) && isdigit (c)) +# define ISALNUM(c) (ISASCII (c) && isalnum (c)) +# define ISALPHA(c) (ISASCII (c) && isalpha (c)) +# define ISCNTRL(c) (ISASCII (c) && iscntrl (c)) +# define ISLOWER(c) (ISASCII (c) && islower (c)) +# define ISPUNCT(c) (ISASCII (c) && ispunct (c)) +# define ISSPACE(c) (ISASCII (c) && isspace (c)) +# define ISUPPER(c) (ISASCII (c) && isupper (c)) +# define ISXDIGIT(c) (ISASCII (c) && isxdigit (c)) + +# define STREQ(s1, s2) ((strcmp (s1, s2) == 0)) + +# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) +/* The GNU C library provides support for user-defined character classes + and the functions from ISO C amendment 1. */ +# ifdef CHARCLASS_NAME_MAX +# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX +# else +/* This shouldn't happen but some implementation might still have this + problem. Use a reasonable default value. */ +# define CHAR_CLASS_MAX_LENGTH 256 +# endif + +# ifdef _LIBC +# define IS_CHAR_CLASS(string) __wctype (string) +# else +# define IS_CHAR_CLASS(string) wctype (string) +# endif +# else +# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ + +# define IS_CHAR_CLASS(string) \ + (STREQ (string, "alpha") || STREQ (string, "upper") \ + || STREQ (string, "lower") || STREQ (string, "digit") \ + || STREQ (string, "alnum") || STREQ (string, "xdigit") \ + || STREQ (string, "space") || STREQ (string, "print") \ + || STREQ (string, "punct") || STREQ (string, "graph") \ + || STREQ (string, "cntrl") || STREQ (string, "blank")) +# endif + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +# if !defined _LIBC && !defined getenv +extern char *getenv (); +# endif + +# ifndef errno +extern int errno; +# endif + +/* This function doesn't exist on most systems. */ + +# if !defined HAVE___STRCHRNUL && !defined _LIBC +static char * +__strchrnul (s, c) + const char *s; + int c; +{ + char *result = strchr (s, c); + if (result == NULL) + result = strchr (s, '\0'); + return result; +} +# endif + +# ifndef internal_function +/* Inside GNU libc we mark some function in a special way. In other + environments simply ignore the marking. */ +# define internal_function +# endif + +/* Match STRING against the filename pattern PATTERN, returning zero if + it matches, nonzero if not. */ +static int internal_fnmatch __P ((const char *pattern, const char *string, + int no_leading_period, int flags)) + internal_function; +static int +internal_function +internal_fnmatch (pattern, string, no_leading_period, flags) + const char *pattern; + const char *string; + int no_leading_period; + int flags; +{ + register const char *p = pattern, *n = string; + register unsigned char c; + +/* Note that this evaluates C many times. */ +# ifdef _LIBC +# define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c)) +# else +# define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c)) +# endif + + while ((c = *p++) != '\0') + { + c = FOLD (c); + + switch (c) + { + case '?': + if (*n == '\0') + return FNM_NOMATCH; + else if (*n == '/' && (flags & FNM_FILE_NAME)) + return FNM_NOMATCH; + else if (*n == '.' && no_leading_period + && (n == string + || (n[-1] == '/' && (flags & FNM_FILE_NAME)))) + return FNM_NOMATCH; + break; + + case '\\': + if (!(flags & FNM_NOESCAPE)) + { + c = *p++; + if (c == '\0') + /* Trailing \ loses. */ + return FNM_NOMATCH; + c = FOLD (c); + } + if (FOLD ((unsigned char) *n) != c) + return FNM_NOMATCH; + break; + + case '*': + if (*n == '.' && no_leading_period + && (n == string + || (n[-1] == '/' && (flags & FNM_FILE_NAME)))) + return FNM_NOMATCH; + + for (c = *p++; c == '?' || c == '*'; c = *p++) + { + if (*n == '/' && (flags & FNM_FILE_NAME)) + /* A slash does not match a wildcard under FNM_FILE_NAME. */ + return FNM_NOMATCH; + else if (c == '?') + { + /* A ? needs to match one character. */ + if (*n == '\0') + /* There isn't another character; no match. */ + return FNM_NOMATCH; + else + /* One character of the string is consumed in matching + this ? wildcard, so *??? won't match if there are + less than three characters. */ + ++n; + } + } + + if (c == '\0') + /* The wildcard(s) is/are the last element of the pattern. + If the name is a file name and contains another slash + this does mean it cannot match. */ + return ((flags & FNM_FILE_NAME) && strchr (n, '/') != NULL + ? FNM_NOMATCH : 0); + else + { + const char *endp; + + endp = __strchrnul (n, (flags & FNM_FILE_NAME) ? '/' : '\0'); + + if (c == '[') + { + int flags2 = ((flags & FNM_FILE_NAME) + ? flags : (flags & ~FNM_PERIOD)); + + for (--p; n < endp; ++n) + if (internal_fnmatch (p, n, + (no_leading_period + && (n == string + || (n[-1] == '/' + && (flags + & FNM_FILE_NAME)))), + flags2) + == 0) + return 0; + } + else if (c == '/' && (flags & FNM_FILE_NAME)) + { + while (*n != '\0' && *n != '/') + ++n; + if (*n == '/' + && (internal_fnmatch (p, n + 1, flags & FNM_PERIOD, + flags) == 0)) + return 0; + } + else + { + int flags2 = ((flags & FNM_FILE_NAME) + ? flags : (flags & ~FNM_PERIOD)); + + if (c == '\\' && !(flags & FNM_NOESCAPE)) + c = *p; + c = FOLD (c); + for (--p; n < endp; ++n) + if (FOLD ((unsigned char) *n) == c + && (internal_fnmatch (p, n, + (no_leading_period + && (n == string + || (n[-1] == '/' + && (flags + & FNM_FILE_NAME)))), + flags2) == 0)) + return 0; + } + } + + /* If we come here no match is possible with the wildcard. */ + return FNM_NOMATCH; + + case '[': + { + /* Nonzero if the sense of the character class is inverted. */ + static int posixly_correct; + register int not; + char cold; + + if (posixly_correct == 0) + posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1; + + if (*n == '\0') + return FNM_NOMATCH; + + if (*n == '.' && no_leading_period && (n == string + || (n[-1] == '/' + && (flags + & FNM_FILE_NAME)))) + return FNM_NOMATCH; + + if (*n == '/' && (flags & FNM_FILE_NAME)) + /* `/' cannot be matched. */ + return FNM_NOMATCH; + + not = (*p == '!' || (posixly_correct < 0 && *p == '^')); + if (not) + ++p; + + c = *p++; + for (;;) + { + unsigned char fn = FOLD ((unsigned char) *n); + + if (!(flags & FNM_NOESCAPE) && c == '\\') + { + if (*p == '\0') + return FNM_NOMATCH; + c = FOLD ((unsigned char) *p); + ++p; + + if (c == fn) + goto matched; + } + else if (c == '[' && *p == ':') + { + /* Leave room for the null. */ + char str[CHAR_CLASS_MAX_LENGTH + 1]; + size_t c1 = 0; +# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) + wctype_t wt; +# endif + const char *startp = p; + + for (;;) + { + if (c1 == CHAR_CLASS_MAX_LENGTH) + /* The name is too long and therefore the pattern + is ill-formed. */ + return FNM_NOMATCH; + + c = *++p; + if (c == ':' && p[1] == ']') + { + p += 2; + break; + } + if (c < 'a' || c >= 'z') + { + /* This cannot possibly be a character class name. + Match it as a normal range. */ + p = startp; + c = '['; + goto normal_bracket; + } + str[c1++] = c; + } + str[c1] = '\0'; + +# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) + wt = IS_CHAR_CLASS (str); + if (wt == 0) + /* Invalid character class name. */ + return FNM_NOMATCH; + + if (__iswctype (__btowc ((unsigned char) *n), wt)) + goto matched; +# else + if ((STREQ (str, "alnum") && ISALNUM ((unsigned char) *n)) + || (STREQ (str, "alpha") && ISALPHA ((unsigned char) *n)) + || (STREQ (str, "blank") && ISBLANK ((unsigned char) *n)) + || (STREQ (str, "cntrl") && ISCNTRL ((unsigned char) *n)) + || (STREQ (str, "digit") && ISDIGIT ((unsigned char) *n)) + || (STREQ (str, "graph") && ISGRAPH ((unsigned char) *n)) + || (STREQ (str, "lower") && ISLOWER ((unsigned char) *n)) + || (STREQ (str, "print") && ISPRINT ((unsigned char) *n)) + || (STREQ (str, "punct") && ISPUNCT ((unsigned char) *n)) + || (STREQ (str, "space") && ISSPACE ((unsigned char) *n)) + || (STREQ (str, "upper") && ISUPPER ((unsigned char) *n)) + || (STREQ (str, "xdigit") && ISXDIGIT ((unsigned char) *n))) + goto matched; +# endif + } + else if (c == '\0') + /* [ (unterminated) loses. */ + return FNM_NOMATCH; + else + { + normal_bracket: + if (FOLD (c) == fn) + goto matched; + + cold = c; + c = *p++; + + if (c == '-' && *p != ']') + { + /* It is a range. */ + unsigned char cend = *p++; + if (!(flags & FNM_NOESCAPE) && cend == '\\') + cend = *p++; + if (cend == '\0') + return FNM_NOMATCH; + + if (cold <= fn && fn <= FOLD (cend)) + goto matched; + + c = *p++; + } + } + + if (c == ']') + break; + } + + if (!not) + return FNM_NOMATCH; + break; + + matched: + /* Skip the rest of the [...] that already matched. */ + while (c != ']') + { + if (c == '\0') + /* [... (unterminated) loses. */ + return FNM_NOMATCH; + + c = *p++; + if (!(flags & FNM_NOESCAPE) && c == '\\') + { + if (*p == '\0') + return FNM_NOMATCH; + /* XXX 1003.2d11 is unclear if this is right. */ + ++p; + } + else if (c == '[' && *p == ':') + { + do + if (*++p == '\0') + return FNM_NOMATCH; + while (*p != ':' || p[1] == ']'); + p += 2; + c = *p; + } + } + if (not) + return FNM_NOMATCH; + } + break; + + default: + if (c != FOLD ((unsigned char) *n)) + return FNM_NOMATCH; + } + + ++n; + } + + if (*n == '\0') + return 0; + + if ((flags & FNM_LEADING_DIR) && *n == '/') + /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */ + return 0; + + return FNM_NOMATCH; + +# undef FOLD +} + + +int +fnmatch (pattern, string, flags) + const char *pattern; + const char *string; + int flags; +{ + return internal_fnmatch (pattern, string, flags & FNM_PERIOD, flags); +} + +#endif /* _LIBC or not __GNU_LIBRARY__. */ + +#endif diff --git a/fnmatch.h b/fnmatch.h new file mode 100644 index 00000000..cc3ec379 --- /dev/null +++ b/fnmatch.h @@ -0,0 +1,84 @@ +/* Copyright (C) 1991, 92, 93, 96, 97, 98, 99 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _FNMATCH_H +#define _FNMATCH_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined __cplusplus || (defined __STDC__ && __STDC__) || defined WINDOWS32 +# if !defined __GLIBC__ || !defined __P +# undef __P +# define __P(protos) protos +# endif +#else /* Not C++ or ANSI C. */ +# undef __P +# define __P(protos) () +/* We can get away without defining `const' here only because in this file + it is used only inside the prototype for `fnmatch', which is elided in + non-ANSI C where `const' is problematical. */ +#endif /* C++ or ANSI C. */ + +#ifndef const +# if (defined __STDC__ && __STDC__) || defined __cplusplus +# define __const const +# else +# define __const +# endif +#endif + +/* We #undef these before defining them because some losing systems + (HP-UX A.08.07 for example) define these in . */ +#undef FNM_PATHNAME +#undef FNM_NOESCAPE +#undef FNM_PERIOD + +/* Bits set in the FLAGS argument to `fnmatch'. */ +#define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */ +#define FNM_NOESCAPE (1 << 1) /* Backslashes don't quote special chars. */ +#define FNM_PERIOD (1 << 2) /* Leading `.' is matched only explicitly. */ + +#if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 2 || defined _GNU_SOURCE +# define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */ +# define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */ +# define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */ +#endif + +/* Value returned by `fnmatch' if STRING does not match PATTERN. */ +#define FNM_NOMATCH 1 + +/* This value is returned if the implementation does not support + `fnmatch'. Since this is not the case here it will never be + returned but the conformance test suites still require the symbol + to be defined. */ +#ifdef _XOPEN_SOURCE +# define FNM_NOSYS (-1) +#endif + +/* Match NAME against the filename pattern PATTERN, + returning zero if it matches, FNM_NOMATCH if not. */ +extern int fnmatch __P ((__const char *__pattern, __const char *__name, + int __flags)); + +#ifdef __cplusplus +} +#endif + +#endif /* fnmatch.h */ diff --git a/mktest.c b/mktest.c index 98251f61..c1e76968 100644 --- a/mktest.c +++ b/mktest.c @@ -47,7 +47,7 @@ void generate(int disk, int size) snprintf(path, sizeof(path), "test/disk%d/%s", disk, name); - f = fopen(path, "w"); + f = fopen(path, "wb"); if (!f) { fprintf(stderr, "Error writing %s\n", path); exit(EXIT_FAILURE); @@ -59,7 +59,6 @@ void generate(int disk, int size) --count; } - fclose(f); } @@ -70,7 +69,7 @@ void damage(const char* path, int size) off_t start; int count; - f = fopen(path, "r+"); + f = fopen(path, "r+b"); if (!f) { fprintf(stderr, "Error writing %s\n", path); exit(EXIT_FAILURE); @@ -130,7 +129,12 @@ int main(int argc, char* argv[]) for(i=0;i +#else +#include "fnmatch.h" +#endif + +#if HAVE_IO_H +#include #endif #if HAVE_GETOPT_LONG @@ -112,10 +118,58 @@ #define lseek lseek64 #define fstat _fstati64 #define HAVE_FTRUNCATE 1 -#define ftruncate _chsize_s +#define ftruncate windows_ftruncate #define HAVE_FSYNC 1 #define fsync _commit +static inline int windows_ftruncate(int fd, off64_t off) +{ + HANDLE h; + LARGE_INTEGER pos; + + if (fd == -1) { + errno = EBADF; + return -1; + } + + h = (HANDLE)_get_osfhandle(fd); + if (h == INVALID_HANDLE_VALUE) { + errno = EBADF; + return -1; + } + + pos.QuadPart = off; + if (!SetFilePointerEx(h, pos, 0, FILE_BEGIN)) { + DWORD error = GetLastError(); + switch (error) { + case ERROR_INVALID_HANDLE : + errno = EBADF; + break; + default: + errno = EIO; + break; + } + return -1; + } + + if (!SetEndOfFile(h)) { + DWORD error = GetLastError(); + switch (error) { + case ERROR_INVALID_HANDLE : + errno = EBADF; + break; + case ERROR_ACCESS_DENIED : + errno = EACCES; + break; + default: + errno = EIO; + break; + } + return -1; + } + return 0; +} + #define rename windows_atomic_rename static inline int windows_atomic_rename(const char* a, const char* b) { diff --git a/snapraid.conf.example b/snapraid.conf.example index 29abdb8b..e710b2ca 100644 --- a/snapraid.conf.example +++ b/snapraid.conf.example @@ -29,8 +29,8 @@ exclude *.bak exclude tmp/ exclude /lost+found/ -# Define the block size in kilo bytes (1024 bytes). -# Format: "block_size SIZE_IN_KB" -# Default value is 256 -> 256 kilo bytes +# Define the block size in kibi bytes (1024 bytes). +# Format: "block_size SIZE_IN_KiB" +# Default value is 256 -> 256 kibi bytes -> 262144 bytes block_size 256 diff --git a/state.c b/state.c index bdd37580..4dcc23cc 100644 --- a/state.c +++ b/state.c @@ -179,7 +179,7 @@ void state_read(struct snapraid_state* state) count_block = 0; pathcpy(path, sizeof(path), state->content); - f = fopen(state->content, "r"); + f = fopen(state->content, "rt"); if (!f) { /* if not found, assume empty */ if (errno == ENOENT) @@ -397,7 +397,7 @@ void state_write(struct snapraid_state* state) printf("Saving state...\n"); pathprint(path, sizeof(path), "%s.tmp", state->content); - f = fopen(path, "w"); + f = fopen(path, "wt"); if (!f) { fprintf(stderr, "Error opening for writing the content file '%s'\n", path); exit(EXIT_FAILURE);