diff --git a/Makefile.am b/Makefile.am index e55ee321..15e43f83 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,7 +3,6 @@ check_PROGRAMS = testgen snapraid_SOURCES = \ snapraid.c \ - getopt.c \ md5.c \ tommy.c \ util.c \ @@ -131,8 +130,7 @@ cachegrind: DISTWIN = \ snapraid.txt \ snapraid.html \ - snapraid.exe \ - snapraid.rc + snapraid.exe distwindows: $(DISTWIN) rm -f $(PACKAGE)-$(VERSION)-windows-x86.zip diff --git a/check.c b/check.c index c5fd9016..c9ece0a5 100644 --- a/check.c +++ b/check.c @@ -26,17 +26,17 @@ /****************************************************************************/ /* check */ -static int state_check_process(int ret_on_error, struct snapraid_state* state, int fix, int parity_f, pos_t blockstart, pos_t blockmax) +static int state_check_process(int ret_on_error, struct snapraid_state* state, int fix, int parity_f, block_off_t blockstart, block_off_t blockmax) { struct snapraid_handle* handle; unsigned diskmax = tommy_array_size(&state->diskarr); - pos_t i; + block_off_t i; unsigned j; unsigned char* block_buffer; unsigned char* xor_buffer; int ret; - uint64_t count_size; - uint64_t count_block; + data_off_t count_size; + data_off_t count_block; time_t start; time_t last; unsigned error; @@ -271,11 +271,11 @@ static int state_check_process(int ret_on_error, struct snapraid_state* state, i return unrecoverable_error != 0 ? ret_on_error : 0; } -void state_check(struct snapraid_state* state, int fix, pos_t blockstart) +void state_check(struct snapraid_state* state, int fix, block_off_t blockstart) { char path[PATH_MAX]; - pos_t blockmax; - off_t size; + block_off_t blockmax; + data_off_t size; int ret; int f; @@ -285,7 +285,7 @@ void state_check(struct snapraid_state* state, int fix, pos_t blockstart) printf("Checking...\n"); blockmax = parity_resize(state); - size = blockmax * (off_t)state->block_size; + size = blockmax * (data_off_t)state->block_size; if (blockstart >= blockmax) { fprintf(stderr, "The specified starting block %u is bigger than the parity size %u.\n", blockstart, blockmax); @@ -313,4 +313,3 @@ void state_check(struct snapraid_state* state, int fix, pos_t blockstart) parity_close(path, f); } } - diff --git a/config.h b/config.h index 7ad51e89..eb91b443 100644 --- a/config.h +++ b/config.h @@ -11,6 +11,12 @@ /* Define to 1 if you have the header file. */ #define HAVE_FCNTL_H 1 +/* Define to 1 if you have the `ferror_unlocked' function. */ +#define HAVE_FERROR_UNLOCKED 1 + +/* Define to 1 if you have the `fgetc_unlocked' function. */ +#define HAVE_FGETC_UNLOCKED 1 + /* Define to 1 if you have the `fsync' function. */ #define HAVE_FSYNC 1 @@ -29,10 +35,6 @@ /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 -/* Define to 1 if your system has a GNU libc compatible `malloc' function, and - to 0 otherwise. */ -#define HAVE_MALLOC 1 - /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 @@ -104,6 +106,9 @@ /* Define to 1 if you have the `vsnprintf' function. */ #define HAVE_VSNPRINTF 1 +/* Define to 1 if assertions should be disabled. */ +/* #undef NDEBUG */ + /* Name of package */ #define PACKAGE "snapraid" @@ -131,6 +136,28 @@ /* Define to 1 if you can safely include both and . */ #define TIME_WITH_SYS_TIME 1 +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# define _ALL_SOURCE 1 +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# define _POSIX_PTHREAD_SEMANTICS 1 +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# define _TANDEM_SOURCE 1 +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# define __EXTENSIONS__ 1 +#endif + + /* Version number of package */ #define VERSION "0.1" @@ -149,12 +176,19 @@ /* Number of bits in a file offset, on hosts where this is settable. */ #define _FILE_OFFSET_BITS 64 -/* Enable GLIBC symbols */ -#define _GNU_SOURCE 1 - /* Define for large files, on AIX-style hosts. */ /* #undef _LARGE_FILES */ +/* Define to 1 if on MINIX. */ +/* #undef _MINIX */ + +/* Define to 2 if the system does not provide POSIX.1 features except with + this defined. */ +/* #undef _POSIX_1_SOURCE */ + +/* Define to 1 if you need to in order for `stat' and other things to work. */ +/* #undef _POSIX_SOURCE */ + /* Define for Solaris 2.5.1 so the uint32_t typedef from , , or is not used. If the typedef were allowed, the #define below would cause a syntax error. */ @@ -179,9 +213,6 @@ /* #undef inline */ #endif -/* Define to rpl_malloc if the replacement function should be used. */ -/* #undef malloc */ - /* Define to `long int' if does not define. */ /* #undef off_t */ diff --git a/configure.ac b/configure.ac index 1ad55355..74c469bb 100644 --- a/configure.ac +++ b/configure.ac @@ -8,11 +8,13 @@ AC_CANONICAL_HOST dnl Checks for programs. AC_PROG_CC +AC_USE_SYSTEM_EXTENSIONS dnl Checks for libraries. AC_SYS_LARGEFILE dnl Checks for header files. +AC_HEADER_ASSERT AC_HEADER_STDC AC_HEADER_DIRENT AC_HEADER_TIME @@ -32,16 +34,10 @@ AC_TYPE_UINT64_T AC_TYPE_UINT8_T dnl Checks for library functions. -AC_FUNC_MALLOC +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]) - -dnl Configure for 64 bit files -CFLAGS="$CFLAGS -D_FILE_OFFSET_BITS=64" - -dnl Enable GLIBC symbols -AC_DEFINE(_GNU_SOURCE,1,[Enable GLIBC symbols]) +AC_CHECK_FUNCS([ftruncate fsync posix_fallocate posix_fadvise pread pwrite fgetc_unlocked ferror_unlocked]) dnl Checks for architecture AC_C_BIGENDIAN diff --git a/elem.c b/elem.c index 0a530f47..8d442ee9 100644 --- a/elem.c +++ b/elem.c @@ -23,7 +23,7 @@ /****************************************************************************/ /* snapraid */ -pos_t block_file_pos(struct snapraid_block* block) +block_off_t block_file_pos(struct snapraid_block* block) { struct snapraid_file* file = block->file; @@ -37,7 +37,7 @@ pos_t block_file_pos(struct snapraid_block* block) unsigned block_file_size(struct snapraid_block* block, unsigned block_size) { - pos_t pos = block_file_pos(block); + block_off_t pos = block_file_pos(block); /* if it's the last block */ if (pos + 1 == block->file->blockmax) { @@ -53,10 +53,10 @@ unsigned block_file_size(struct snapraid_block* block, unsigned block_size) return block_size; } -struct snapraid_file* file_alloc(unsigned block_size, const char* sub, uint64_t size, time_t mtime) +struct snapraid_file* file_alloc(unsigned block_size, const char* sub, data_off_t size, time_t mtime) { struct snapraid_file* file; - pos_t i; + block_off_t i; file = malloc_nofail(sizeof(struct snapraid_file)); snprintf(file->sub, sizeof(file->sub), "%s", sub); diff --git a/elem.h b/elem.h index 5855655c..3a5784bf 100644 --- a/elem.h +++ b/elem.h @@ -38,10 +38,15 @@ #define POS_INVALID -1 /** - * Basic position type. + * Basic block position type. * With 32 bits and 128k blocks you can address 256 TB. */ -typedef uint32_t pos_t; +typedef uint32_t block_off_t; + +/** + * Basic data position type. + */ +typedef uint64_t data_off_t; struct snapraid_file; @@ -49,7 +54,7 @@ struct snapraid_file; * Block of a file. */ struct snapraid_block { - pos_t parity_pos; /**< Position of the block in the parity. */ + block_off_t parity_pos; /**< Position of the block in the parity. */ int is_hashed; /**< If the hash of the block is valid. */ struct snapraid_file* file; /**< Back pointer to the file owning this block. */ unsigned char hash[HASH_MAX]; /**< Hash of the block. */ @@ -60,9 +65,9 @@ struct snapraid_block { */ struct snapraid_file { char sub[PATH_MAX]; /**< Sub path of the file. Without the disk dir. The disk is implicit. */ - uint64_t size; /**< Size of the file. */ + data_off_t size; /**< Size of the file. */ struct snapraid_block* blockvec; /**< All the blocks of the file. */ - pos_t blockmax; /**< Number of blocks. */ + block_off_t blockmax; /**< Number of blocks. */ time_t mtime; /**< Modification time. */ int is_present; /**< If it's seen as present. */ @@ -77,7 +82,7 @@ struct snapraid_file { struct snapraid_disk { char name[PATH_MAX]; /**< Name of the disk. */ char dir[PATH_MAX]; /**< Mount point of the disk. */ - pos_t first_free_block; /**< First free searching block. */ + block_off_t first_free_block; /**< First free searching block. */ tommy_list filelist; /**< List of all the files. */ tommy_hashdyn fileset; /**< Hashtable by sub of all the files. */ tommy_array blockarr; /**< Block array of the disk. */ @@ -86,7 +91,7 @@ struct snapraid_disk { /** * Get the relative position of a block inside the file. */ -pos_t block_file_pos(struct snapraid_block* block); +block_off_t block_file_pos(struct snapraid_block* block); /** * Get the size in bytes of the block. @@ -94,7 +99,7 @@ pos_t block_file_pos(struct snapraid_block* block); */ unsigned block_file_size(struct snapraid_block* block, unsigned block_size); -struct snapraid_file* file_alloc(unsigned block_size, const char* sub, uint64_t size, time_t mtime); +struct snapraid_file* file_alloc(unsigned block_size, const char* sub, data_off_t size, time_t mtime); void file_free(struct snapraid_file* file); @@ -109,7 +114,7 @@ struct snapraid_disk* disk_alloc(const char* name, const char* dir); void disk_free(struct snapraid_disk* disk); -static inline struct snapraid_block* disk_block_get(struct snapraid_disk* disk, pos_t pos) +static inline struct snapraid_block* disk_block_get(struct snapraid_disk* disk, block_off_t pos) { if (pos < tommy_array_size(&disk->blockarr)) return tommy_array_get(&disk->blockarr, pos); diff --git a/getopt.c b/getopt.c deleted file mode 100644 index b8c070aa..00000000 --- a/getopt.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * This file is part of the Advance project. - * - * Copyright (C) 2001, 2002 Andrea Mazzoleni - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#if HAVE_CONFIG_H -#include -#endif - -#if !HAVE_GETOPT - -/* This source is extracted from the DJGPP LIBC library */ - -#define unconst(var, type) ((type)(var)) - -/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ -#include -#include - -int opterr = 1, optind = 1, optopt = 0; -char *optarg = 0; - -#define BADCH (int)'?' -#define EMSG "" - -int getopt(int nargc, char *const nargv[], const char *ostr) -{ - static const char *place = EMSG; /* option letter processing */ - char *oli; /* option letter list index */ - char *p; - - if (!*place) - { - if (optind >= nargc || *(place = nargv[optind]) != '-') - { - place = EMSG; - return(EOF); - } - if (place[1] && *++place == '-') - { - ++optind; - place = EMSG; - return(EOF); - } - } - - if ((optopt = (int)*place++) == (int)':' - || !(oli = strchr(ostr, optopt))) - { - /* - * if the user didn't specify '-' as an option, - * assume it means EOF. - */ - if (optopt == (int)'-') - return EOF; - if (!*place) - ++optind; - if (opterr) - { - if (!(p = strrchr(*nargv, '/'))) - p = *nargv; - else - ++p; - fprintf(stderr, "%s: illegal option -- %c\n", p, optopt); - } - return BADCH; - } - if (*++oli != ':') - { /* don't need argument */ - optarg = NULL; - if (!*place) - ++optind; - } - else - { /* need an argument */ - if (*place) /* no white space */ - optarg = unconst(place, char *); - else if (nargc <= ++optind) - { /* no arg */ - place = EMSG; - if (!(p = strrchr(*nargv, '/'))) - p = *nargv; - else - ++p; - if (opterr) - fprintf(stderr, "%s: option requires an argument -- %c\n", p, optopt); - return BADCH; - } - else /* white space */ - optarg = nargv[optind]; - place = EMSG; - ++optind; - } - return optopt; /* dump back option letter */ -} - -#endif - diff --git a/handle.c b/handle.c index 3fa579b4..bdae52e2 100644 --- a/handle.c +++ b/handle.c @@ -165,14 +165,26 @@ void handle_close(struct snapraid_handle* handle) int handle_read(int ret_on_error, struct snapraid_handle* handle, struct snapraid_block* block, unsigned char* block_buffer, unsigned block_size) { ssize_t read_ret; - off_t offset; + data_off_t offset; unsigned read_size; - offset = block_file_pos(block) * (off_t)block_size; + offset = block_file_pos(block) * (data_off_t)block_size; read_size = block_file_size(block, block_size); +#if HAVE_PREAD read_ret = pread(handle->f, block_buffer, read_size, offset); +#else + if (lseek(handle->f, offset, SEEK_SET) != offset) { + if (ret_on_error) + return ret_on_error; + + fprintf(stderr, "Error seeking file '%s'. %s.\n", handle->path, strerror(errno)); + exit(EXIT_FAILURE); + } + + read_ret = read(handle->f, block_buffer, read_size); +#endif if (read_ret != read_size) { if (ret_on_error) return ret_on_error; @@ -187,14 +199,23 @@ int handle_read(int ret_on_error, struct snapraid_handle* handle, struct snaprai void handle_write(struct snapraid_handle* handle, struct snapraid_block* block, unsigned char* block_buffer, unsigned block_size) { ssize_t write_ret; - off_t offset; + data_off_t offset; unsigned write_size; - offset = block_file_pos(block) * (off_t)block_size; + offset = block_file_pos(block) * (data_off_t)block_size; write_size = block_file_size(block, block_size); +#if HAVE_PWRITE write_ret = pwrite(handle->f, block_buffer, write_size, offset); +#else + if (lseek(handle->f, offset, SEEK_SET) != offset) { + fprintf(stderr, "Error seeking file '%s'. %s.\n", handle->path, strerror(errno)); + exit(EXIT_FAILURE); + } + + write_ret = write(handle->f, block_buffer, write_size); +#endif if (write_ret != write_size) { fprintf(stderr, "Error writing file '%s'. %s.\n", handle->path, strerror(errno)); exit(EXIT_FAILURE); diff --git a/md5.h b/md5.h index 70d33b41..729c0dd8 100644 --- a/md5.h +++ b/md5.h @@ -20,12 +20,8 @@ * Still in the public domain. */ -#ifndef MD5_H -#define MD5_H - -#ifdef __cplusplus -extern "C" { -#endif +#ifndef __MD5_H +#define __MD5_H #define MD5_SIZE 16 @@ -39,8 +35,4 @@ void md5_init(struct md5_t* context); void md5_update(struct md5_t* context, const unsigned char* buf, unsigned len); void md5_final(struct md5_t* context, unsigned char* digest); -#ifdef __cplusplus -} #endif - -#endif /* !MD5_H */ diff --git a/parity.c b/parity.c index 2d1de6f5..b4b9ea36 100644 --- a/parity.c +++ b/parity.c @@ -24,10 +24,10 @@ /****************************************************************************/ /* parity */ -pos_t parity_resize(struct snapraid_state* state) +block_off_t parity_resize(struct snapraid_state* state) { unsigned disk_count = tommy_array_size(&state->diskarr); - pos_t parity_block; + block_off_t parity_block; unsigned i; /* compute the size of the parity file */ @@ -36,7 +36,7 @@ pos_t parity_resize(struct snapraid_state* state) struct snapraid_disk* disk = tommy_array_get(&state->diskarr, i); /* start from the declared size */ - pos_t block = tommy_array_size(&disk->blockarr); + block_off_t block = tommy_array_size(&disk->blockarr); /* decrease the block until an allocated block */ while (block > 0 && tommy_array_get(&disk->blockarr, block - 1) == 0) @@ -49,7 +49,7 @@ pos_t parity_resize(struct snapraid_state* state) return parity_block; } -int parity_create(const char* path, off_t size) +int parity_create(const char* path, data_off_t size) { struct stat st; int ret; @@ -105,7 +105,9 @@ int parity_create(const char* path, off_t size) int parity_open(int ret_on_error, const char* path) { +#if HAVE_POSIX_FADVISE int ret; +#endif int f; f = open(path, O_RDONLY | O_BINARY); @@ -129,8 +131,9 @@ int parity_open(int ret_on_error, const char* path) return f; } -void parity_close(const char* path, int f) +void parity_sync(const char* path, int f) { +#if HAVE_FSYNC int ret; /* ensure that data changes are written to disk */ @@ -141,6 +144,12 @@ void parity_close(const char* path, int f) fprintf(stderr, "Error synching parity file '%s'. %s.\n", path, strerror(errno)); exit(EXIT_FAILURE); } +#endif +} + +void parity_close(const char* path, int f) +{ + int ret; ret = close(f); if (ret != 0) { @@ -149,14 +158,27 @@ void parity_close(const char* path, int f) } } -void parity_write(const char* path, int f, pos_t pos, unsigned char* block_buffer, unsigned block_size) +void parity_write(const char* path, int f, block_off_t pos, unsigned char* block_buffer, unsigned block_size) { ssize_t write_ret; - off_t offset; + data_off_t offset; - offset = pos * (off_t)block_size; + offset = pos * (data_off_t)block_size; +#if HAVE_PWRITE write_ret = pwrite(f, block_buffer, block_size, offset); +#else + if (lseek(f, offset, SEEK_SET) != offset) { + if (errno == ENOSPC) { + fprintf(stderr, "Failed to grow parity file '%s' due lack of space.\n", path); + } else { + fprintf(stderr, "Error seeking file '%s'. %s.\n", path, strerror(errno)); + } + exit(EXIT_FAILURE); + } + + write_ret = write(f, block_buffer, block_size); +#endif if (write_ret != block_size) { if (errno == ENOSPC) { fprintf(stderr, "Failed to grow parity file '%s' due lack of space.\n", path); @@ -167,21 +189,34 @@ void parity_write(const char* path, int f, pos_t pos, unsigned char* block_buffe } } -int parity_read(int ret_on_error, const char* path, int f, pos_t pos, unsigned char* block_buffer, unsigned block_size) +int parity_read(int ret_on_error, const char* path, int f, block_off_t pos, unsigned char* block_buffer, unsigned block_size) { ssize_t read_ret; - off_t offset; + data_off_t offset; /* if the file is not opened, return an error without trying */ if (f == -1 && ret_on_error) return -1; - offset = pos * (off_t)block_size; + offset = pos * (data_off_t)block_size; +#if HAVE_PREAD read_ret = pread(f, block_buffer, block_size, offset); +#else + if (lseek(f, offset, SEEK_SET) != offset) { + if (ret_on_error) + return ret_on_error; + + fprintf(stderr, "Error seeking file '%s'. %s.\n", path, strerror(errno)); + exit(EXIT_FAILURE); + } + + read_ret = read(f, block_buffer, block_size); +#endif if (read_ret != block_size) { if (ret_on_error) return ret_on_error; + fprintf(stderr, "Error reading file '%s'. %s.\n", path, strerror(errno)); exit(EXIT_FAILURE); } diff --git a/parity.h b/parity.h index 552f32b2..b81e608f 100644 --- a/parity.h +++ b/parity.h @@ -24,17 +24,19 @@ /** * Computes the size of the parity data in number of blocks. */ -pos_t parity_resize(struct snapraid_state* state); +block_off_t parity_resize(struct snapraid_state* state); -int parity_create(const char* path, off_t size); +int parity_create(const char* path, data_off_t size); int parity_open(int ret_on_error, const char* path); +void parity_sync(const char* path, int f); + void parity_close(const char* path, int f); -void parity_write(const char* parity_path, int parity_f, pos_t pos, unsigned char* block_buffer, unsigned block_size); +void parity_write(const char* parity_path, int parity_f, block_off_t pos, unsigned char* block_buffer, unsigned block_size); -int parity_read(int ret_on_error, const char* parity_path, int parity_f, pos_t pos, unsigned char* block_buffer, unsigned block_size); +int parity_read(int ret_on_error, const char* parity_path, int parity_f, block_off_t pos, unsigned char* block_buffer, unsigned block_size); #endif diff --git a/portable.h b/portable.h index a8738cf0..e12ba289 100644 --- a/portable.h +++ b/portable.h @@ -25,14 +25,9 @@ /***************************************************************************/ /* Config */ -#ifdef __WIN32__ -/* Customize for Windows Mingw/Cygwin */ -#define HAVE_SYS_TYPES_H 1 -#define HAVE_SYS_STAT_H 1 -#define HAVE_DIRENT_H 1 -#define TIME_WITH_SYS_TIME 1 -#define HAVE_SYS_TIME_H 1 -#define HAVE_UNISTD_H 1 +#ifdef __MINGW32__ /* Specific for MINGW */ +#define __MSVCRT_VERSION__ 0x0601 /* Define the MSVCRT version required */ +#include #endif /* Include some standard headers */ @@ -45,6 +40,7 @@ #include #include #include +#include #if HAVE_STDINT_H #include @@ -94,12 +90,6 @@ #include #endif -#if !HAVE_GETOPT -int getopt(int argc, char * const *argv, const char *options); -extern char *optarg; -extern int optind, opterr, optopt; -#endif - #if HAVE_GETOPT_LONG #define SWITCH_GETOPT_LONG(a,b) a #else @@ -110,5 +100,39 @@ extern int optind, opterr, optopt; #define O_BINARY 0 #endif +#ifdef __MINGW32__ /* Specific for MINGW */ + +/* Remap functions and types for 64 bit support */ +#define stat _stati64 +#define off_t off64_t +#define lseek lseek64 +#define fstat _fstati64 +#define HAVE_FTRUNCATE 1 +#define ftruncate _chsize_s +#define HAVE_FSYNC 1 +#define fsync _commit + +#define rename windows_atomic_rename +static inline int windows_atomic_rename(const char* a, const char* b) +{ + if (!MoveFileEx(a, b, MOVEFILE_REPLACE_EXISTING)) { + switch (GetLastError()) { + case ERROR_ACCESS_DENIED : + errno = EACCES; + break; + case ERROR_FILE_NOT_FOUND : + errno = ENOENT; + break; + default : + errno = EIO; + break; + } + return -1; + } + + return 0; +} +#endif + #endif diff --git a/scan.c b/scan.c index bd64b20f..b789559c 100644 --- a/scan.c +++ b/scan.c @@ -33,11 +33,11 @@ struct snapraid_scan { */ static void scan_file_remove(struct snapraid_state* state, struct snapraid_disk* disk, struct snapraid_file* file) { - pos_t i; + block_off_t i; /* free all the blocks of the file */ for(i=0;iblockmax;++i) { - pos_t block_pos = file->blockvec[i].parity_pos; + block_off_t block_pos = file->blockvec[i].parity_pos; /* adjust the first free position */ if (disk->first_free_block > block_pos) @@ -59,9 +59,9 @@ static void scan_file_remove(struct snapraid_state* state, struct snapraid_disk* */ static void scan_file_insert(struct snapraid_state* state, struct snapraid_disk* disk, struct snapraid_file* file) { - pos_t i; - pos_t block_max; - pos_t block_pos; + block_off_t i; + block_off_t block_max; + block_off_t block_pos; /* allocate the blocks of the file */ block_pos = disk->first_free_block; @@ -91,21 +91,15 @@ static void scan_file_insert(struct snapraid_state* state, struct snapraid_disk* tommy_list_insert_tail(&disk->filelist, &file->nodelist, file); } -static void scan_file(struct snapraid_scan* scan, struct snapraid_state* state, struct snapraid_disk* disk, const char* path, const char* sub) +static void scan_file(struct snapraid_scan* scan, struct snapraid_state* state, struct snapraid_disk* disk, const char* path, const char* sub, const struct stat* st) { - struct stat st; struct snapraid_file* file; - if (stat(path, &st) != 0) { - fprintf(stderr, "Error in stat file '%s'\n", path); - exit(EXIT_FAILURE); - } - /* check if the file already exists */ file = tommy_hashdyn_search(&disk->fileset, file_compare, sub, file_hash(sub)); if (file) { /* check if the file is the same */ - if (file->size == st.st_size && file->mtime == st.st_mtime) { + if (file->size == st->st_size && file->mtime == st->st_mtime) { /* mark as present */ ++scan->count_equal; file->is_present = 1; @@ -121,7 +115,7 @@ static void scan_file(struct snapraid_scan* scan, struct snapraid_state* state, /* create the new file */ ++scan->count_insert; - file = file_alloc(state->block_size, sub, st.st_size, st.st_mtime); + file = file_alloc(state->block_size, sub, st->st_size, st->st_mtime); file->is_present = 1; /* insert it */ @@ -140,13 +134,21 @@ static void scan_dir(struct snapraid_scan* scan, struct snapraid_state* state, s } while ((dd = readdir(d)) != 0) { - if (dd->d_type == DT_REG) { - char path_next[PATH_MAX]; + char path[PATH_MAX]; + struct stat st; + + snprintf(path, sizeof(path), "%s%s", dir, dd->d_name); + + if (stat(path, &st) != 0) { + fprintf(stderr, "Error in stat file '%s'\n", path); + exit(EXIT_FAILURE); + } + + if (S_ISREG(st.st_mode)) { char sub_next[PATH_MAX]; - snprintf(path_next, sizeof(path_next), "%s%s", dir, dd->d_name); snprintf(sub_next, sizeof(sub_next), "%s%s", sub, dd->d_name); - scan_file(scan, state, disk, path_next, sub_next); - } else if (dd->d_type == DT_DIR) { + scan_file(scan, state, disk, path, sub_next, &st); + } else if (S_ISDIR(st.st_mode)) { if (strcmp(dd->d_name, ".") != 0 && strcmp(dd->d_name, "..") != 0 && strcmp(dd->d_name, "lost+found") != 0 ) { char dir_next[PATH_MAX]; diff --git a/snapraid.c b/snapraid.c index d33fb716..b4ef02b5 100644 --- a/snapraid.c +++ b/snapraid.c @@ -79,8 +79,11 @@ int main(int argc, char* argv[]) const char* conf; struct snapraid_state state; int operation; - pos_t blockstart; + block_off_t blockstart; + /* intercept Ctrl+C */ + signal(SIGINT, &signal_handler); + /* defaults */ conf = "/etc/" PACKAGE ".conf"; verbose = 0; @@ -139,12 +142,6 @@ int main(int argc, char* argv[]) exit(EXIT_FAILURE); } - struct sigaction sig; - sig.sa_handler = signal_handler; - sigemptyset(&sig.sa_mask); - sig.sa_flags = 0; - sigaction(SIGINT, &sig, 0); - state_init(&state); state_config(&state, conf, verbose, force); diff --git a/state.c b/state.c index 64872826..721ac840 100644 --- a/state.c +++ b/state.c @@ -24,7 +24,7 @@ /** * Max length of a line in the configuration and state files. */ -#define LINE_MAX 1024 +#define TEXT_LINE_MAX 1024 void state_init(struct snapraid_state* state) { @@ -35,7 +35,7 @@ void state_init(struct snapraid_state* state) tommy_array_init(&state->diskarr); if (sizeof(off_t) < sizeof(uint64_t)) { - fprintf(stderr, "Internal inconsistency in off_t type size\n"); + fprintf(stderr, "Missing support for large files\n"); exit(EXIT_FAILURE); } } @@ -70,14 +70,14 @@ void state_config(struct snapraid_state* state, const char* path, int verbose, i line = 0; while (1) { - char buffer[LINE_MAX]; + char buffer[TEXT_LINE_MAX]; char* tag; char* s; int ret; ++line; - ret = strgets(buffer, LINE_MAX, f); + ret = strgets(buffer, TEXT_LINE_MAX, f); if (ret < 0) { fprintf(stderr, "Error reading the configuration file '%s' at line %u\n", path, line); exit(EXIT_FAILURE); @@ -182,14 +182,14 @@ void state_read(struct snapraid_state* state) line = 0; block_index = 0; while (1) { - char buffer[LINE_MAX]; + char buffer[TEXT_LINE_MAX]; char* tag; char* s; int ret; ++line; - ret = strgets(buffer, LINE_MAX, f); + ret = strgets(buffer, TEXT_LINE_MAX, f); if (ret < 0) { fprintf(stderr, "Error reading the state file '%s' at line %u\n", path, line); exit(EXIT_FAILURE); @@ -213,7 +213,7 @@ void state_read(struct snapraid_state* state) char* size; char* mtime; char* sub; - uint64_t v_size; + data_off_t v_size; uint64_t v_mtime; unsigned i; @@ -279,7 +279,7 @@ void state_read(struct snapraid_state* state) } else if (strcmp(tag, "blk") == 0) { char* pos; char* hash; - pos_t v_pos; + block_off_t v_pos; struct snapraid_block* block; char* e; @@ -381,7 +381,7 @@ void state_write(struct snapraid_state* state) /* for each file */ for(j=disk->filelist;j!=0;j=j->next) { - pos_t k; + block_off_t k; struct snapraid_file* file = j->data; int ret; @@ -423,10 +423,12 @@ void state_write(struct snapraid_state* state) exit(EXIT_FAILURE); } +#if HAVE_FSYNC if (fsync(fileno(f)) != 0) { fprintf(stderr, "Error writing the state file '%s' in fsync(). %s.\n", path, strerror(errno)); exit(EXIT_FAILURE); } +#endif if (fclose(f) != 0) { fprintf(stderr, "Error writing the state file '%s' in close(). %s.\n", path, strerror(errno)); @@ -446,7 +448,7 @@ void state_write(struct snapraid_state* state) #define PROGRESS_CLEAR " " -int state_progress(time_t* start, time_t* last, pos_t blockpos, pos_t blockmax, uint64_t count_block, uint64_t count_size) +int state_progress(time_t* start, time_t* last, block_off_t blockpos, block_off_t blockmax, data_off_t count_block, data_off_t count_size) { time_t now; @@ -463,7 +465,7 @@ int state_progress(time_t* start, time_t* last, pos_t blockpos, pos_t blockmax, if (delta > 5 && count_block > 0) { unsigned m, h; - uint64_t todo = blockmax - blockpos; + data_off_t todo = blockmax - blockpos; m = todo * delta / (60 * count_block); diff --git a/state.h b/state.h index 0b157b6b..ac11115a 100644 --- a/state.h +++ b/state.h @@ -59,14 +59,14 @@ void state_scan(struct snapraid_state* state); /** * Sync. */ -void state_sync(struct snapraid_state* state, pos_t blockstart); +void state_sync(struct snapraid_state* state, block_off_t blockstart); /** * Check. */ -void state_check(struct snapraid_state* state, int fix, pos_t blockstart); +void state_check(struct snapraid_state* state, int fix, block_off_t blockstart); -int state_progress(time_t* start, time_t* last, pos_t blockpos, pos_t blockmax, uint64_t count_block, uint64_t count_size); +int state_progress(time_t* start, time_t* last, block_off_t blockpos, block_off_t blockmax, data_off_t count_block, data_off_t count_size); #endif diff --git a/sync.c b/sync.c index 4d97c926..95091ba1 100644 --- a/sync.c +++ b/sync.c @@ -26,16 +26,16 @@ /****************************************************************************/ /* sync */ -static void state_sync_process(struct snapraid_state* state, int parity_f, pos_t blockstart, pos_t blockmax) +static void state_sync_process(struct snapraid_state* state, int parity_f, block_off_t blockstart, block_off_t blockmax) { struct snapraid_handle* handle; unsigned diskmax = tommy_array_size(&state->diskarr); - pos_t i; + block_off_t i; unsigned j; unsigned char* block_buffer; unsigned char* xor_buffer; - uint64_t count_size; - uint64_t count_block; + data_off_t count_size; + data_off_t count_block; time_t start; time_t last; @@ -138,17 +138,17 @@ static void state_sync_process(struct snapraid_state* state, int parity_f, pos_t free(xor_buffer); } -void state_sync(struct snapraid_state* state, pos_t blockstart) +void state_sync(struct snapraid_state* state, block_off_t blockstart) { char path[PATH_MAX]; - pos_t blockmax; - off_t size; + block_off_t blockmax; + data_off_t size; int f; printf("Syncing...\n"); blockmax = parity_resize(state); - size = blockmax * (off_t)state->block_size; + size = blockmax * (data_off_t)state->block_size; if (blockstart >= blockmax) { fprintf(stderr, "The specified starting block %u is bigger than the parity size %u.\n", blockstart, blockmax); @@ -160,6 +160,8 @@ void state_sync(struct snapraid_state* state, pos_t blockstart) state_sync_process(state, f, blockstart, blockmax); + parity_sync(path, f); + parity_close(path, f); } diff --git a/util.h b/util.h index 380a9a1d..7ea362b7 100644 --- a/util.h +++ b/util.h @@ -46,7 +46,11 @@ static inline int strgets(char* s, unsigned size, FILE* f) int c; while (1) { +#if HAVE_FGETC_UNLOCKED c = fgetc_unlocked(f); +#else + c = fgetc(f); +#endif if (c == EOF || c == '\n') break; @@ -59,7 +63,11 @@ static inline int strgets(char* s, unsigned size, FILE* f) } if (c == EOF) { +#if HAVE_FERROR_UNLOCKED if (ferror_unlocked(f)) { +#else + if (ferror(f)) { +#endif return -1; } if (i == s)