diff --git a/configure.ac b/configure.ac index 923737bc..a7086c16 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,8 @@ AC_HEADER_DIRENT AC_HEADER_TIME AC_CHECK_HEADERS([fcntl.h stddef.h stdint.h stdlib.h string.h limits.h]) AC_CHECK_HEADERS([unistd.h getopt.h fnmatch.h io.h inttypes.h byteswap.h]) -AC_CHECK_HEADERS([sys/time.h sys/file.h sys/ioctl.h linux/fiemap.h linux/fs.h]) +AC_CHECK_HEADERS([sys/time.h sys/file.h sys/ioctl.h sys/vfs.h sys/statfs.h]) +AC_CHECK_HEADERS([linux/fiemap.h linux/fs.h]) dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST @@ -40,17 +41,32 @@ AC_TYPE_UINT64_T AC_TYPE_UINT8_T AC_TYPE_INT8_T AC_CHECK_MEMBERS([struct stat.st_mtim.tv_nsec, struct stat.st_mtimensec, struct stat.st_mtimespec.tv_nsec], [], [], [[ +#if HAVE_SYS_TYPES_H #include +#endif +#if HAVE_SYS_STAT_H #include +#endif +#if HAVE_UNISTD_H #include +#endif +]]) +AC_CHECK_MEMBERS([struct statfs.f_type], [], [], [[ +#if HAVE_SYS_VFS_H +#include +#endif +#if HAVE_SYS_STATFS_H +#include +#endif ]]) dnl Checks for library functions. AC_SYS_LARGEFILE AC_CHECK_FUNCS([memset strchr strerror strrchr mkdir gettimeofday strtoul]) AC_CHECK_FUNCS([getopt getopt_long snprintf vsnprintf]) -AC_CHECK_FUNCS([ftruncate fallocate fsync access posix_fallocate posix_fadvise pread pwrite getc_unlocked ferror_unlocked fnmatch]) -AC_CHECK_FUNCS([futimes futimens futimesat fstatat flock]) +AC_CHECK_FUNCS([ftruncate fallocate fsync access posix_fallocate posix_fadvise]) +AC_CHECK_FUNCS([pread pwrite getc_unlocked ferror_unlocked fnmatch]) +AC_CHECK_FUNCS([futimes futimens futimesat fstatat flock statfs]) dnl Checks for architecture AC_C_BIGENDIAN diff --git a/mingw.c b/mingw.c index 5ba518ab..7b1d75f1 100644 --- a/mingw.c +++ b/mingw.c @@ -1148,6 +1148,11 @@ int filephy(const char* file, struct stat* st, uint64_t* physical) return 0; } +int fstype(const char* path) +{ + return FSTYPE_UNKNOWN; +} + #undef strerror const char* windows_strerror(int err) diff --git a/portable.h b/portable.h index d8fd1b96..c9eab0b4 100644 --- a/portable.h +++ b/portable.h @@ -107,6 +107,14 @@ #include #endif +#if HAVE_SYS_VFS_H +#include +#endif + +#if HAVE_SYS_STATFS_H +#include +#endif + #if HAVE_GETOPT_H #include #endif @@ -173,6 +181,16 @@ int devuuid(uint64_t device, char* uuid, size_t size); */ int filephy(const char* path, struct stat* st, uint64_t* physical); +/* Types of filesystem */ +#define FSTYPE_UNKNOWN 0 +#define FSTYPE_FUSE 1 + +/** + * Get the filesystem type. + * Returns -1 on error or one of the FSTYPE define. + */ +int fstype(const char* path); + /** * Initializes the system. */ diff --git a/state.c b/state.c index a5a8b4bb..a470e1c1 100644 --- a/state.c +++ b/state.c @@ -113,6 +113,26 @@ static void state_config_check(struct snapraid_state* state, const char* path) #endif if (!state->opt.force_device) { + int ret; + + ret = fstype(disk->dir); + if (ret < 0) { + fprintf(stderr, "Error accessing disk '%s' to get the filesystem type. %s.\n", disk->dir, strerror(errno)); + exit(EXIT_FAILURE); + } + if (ret == FSTYPE_FUSE) { + fprintf(stderr, "Disk '%s' has a filesystem managed by FUSE.\n", disk->dir); + fprintf(stderr, "FUSE doesn't support persistent inodes, and it cannot be\n"); + fprintf(stderr, "used safely with SnapRAID.\n"); + + /* in "fix" we allow to continue anyway */ + if (strcmp(state->command, "fix") == 0) { + fprintf(stderr, "You can '%s' anyway, using 'snapraid --force-device %s'.\n", state->command, state->command); + } + + exit(EXIT_FAILURE); + } + for(j=i->next;j!=0;j=j->next) { struct snapraid_disk* other = j->data; if (disk->device == other->device) { @@ -675,6 +695,8 @@ static void state_map(struct snapraid_state* state) /* removes all the mapping without a disk */ /* this happens when a disk is removed from the configuration file */ + /* From SnapRAID 4.0 mappings are automatically removed if a disk is not used */ + /* when saving the content file, but we keep this code to import older content files. */ for(i=state->maplist;i!=0;) { struct snapraid_map* map = i->data; struct snapraid_disk* disk; diff --git a/unix.c b/unix.c index 41912895..21302895 100644 --- a/unix.c +++ b/unix.c @@ -168,6 +168,26 @@ int filephy(const char* path, struct stat* st, uint64_t* physical) return 0; } +int fstype(const char* path) +{ +/* statfs() is really not portable, and to limit possible incompatibility we limit it to Linux */ +/* for example, Solaris doesn't have the f_type field, BSD has it as "short" */ +#if HAVE_STATFS && HAVE_STRUCT_STATFS_F_TYPE && defined(__linux__) + struct statfs st; + + if (statfs(path, &st) != 0) + return -1; + + switch (st.f_type) { + case 0x65735546 : return FSTYPE_FUSE; + } +#else + (void)path; +#endif + + return FSTYPE_UNKNOWN; +} + void os_init(void) { }