Address some portability issues

This commit is contained in:
Andrea Mazzoleni 2011-03-12 10:09:59 +01:00
parent d25b55d393
commit 496971e9c9
18 changed files with 248 additions and 247 deletions

View file

@ -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

17
check.c
View file

@ -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);
}
}

View file

@ -11,6 +11,12 @@
/* Define to 1 if you have the <fcntl.h> 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 <inttypes.h> 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 <memory.h> 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 <sys/time.h> and <time.h>. */
#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 <sys/synch.h>,
<pthread.h>, or <semaphore.h> 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 <sys/types.h> does not define. */
/* #undef off_t */

View file

@ -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

8
elem.c
View file

@ -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);

23
elem.h
View file

@ -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);

113
getopt.c
View file

@ -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 <config.h>
#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 <string.h>
#include <stdio.h>
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

View file

@ -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);

12
md5.h
View file

@ -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 */

View file

@ -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);
}

View file

@ -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

View file

@ -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 <windows.h>
#endif
/* Include some standard headers */
@ -45,6 +40,7 @@
#include <assert.h>
#include <errno.h>
#include <signal.h>
#include <limits.h>
#if HAVE_STDINT_H
#include <stdint.h>
@ -94,12 +90,6 @@
#include <getopt.h>
#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

40
scan.c
View file

@ -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;i<file->blockmax;++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];

View file

@ -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);

24
state.c
View file

@ -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);

View file

@ -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

18
sync.c
View file

@ -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);
}

8
util.h
View file

@ -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)