fsarchiver-0.8.7/0000755000175000017500000000000014405612250010662 500000000000000fsarchiver-0.8.7/config.h.in0000644000175000017500000001131114405612237012627 00000000000000/* config.h.in. Generated from configure.ac by autoheader. */ /* Define to 1 if you have the header file. */ #undef HAVE_BZLIB_H /* Define to 1 if you have the header file. */ #undef HAVE_ENDIAN_H /* Define to 1 if you have the header file. */ #undef HAVE_EXECINFO_H /* Define to 1 if you have the header file. */ #undef HAVE_FCNTL_H /* Define to 1 if you have the header file. */ #undef HAVE_FNMATCH_H /* Define to 1 if you have the `fstatfs64' function. */ #undef HAVE_FSTATFS64 /* Define to 1 if you have the `fstatvfs64' function. */ #undef HAVE_FSTATVFS64 /* Define to 1 if you have the header file. */ #undef HAVE_GCRYPT_H /* Define to 1 if you have the header file. */ #undef HAVE_GETOPT_H /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the `pthread' library (-lpthread). */ #undef HAVE_LIBPTHREAD /* Define to 1 if you have the `lstat64' function. */ #undef HAVE_LSTAT64 /* Define to 1 if you have the `lutimes' function. */ #undef HAVE_LUTIMES /* Define to 1 if you have the header file. */ #undef HAVE_LZ4_H /* Define to 1 if you have the header file. */ #undef HAVE_LZO_LZO1X_H /* Define to 1 if you have the header file. */ #undef HAVE_MALLOC_H /* Define to 1 if you have the `mempcpy' function. */ #undef HAVE_MEMPCPY /* Define to 1 if you have the `open64' function. */ #undef HAVE_OPEN64 /* Define to 1 if you have the header file. */ #undef HAVE_PTHREAD_H /* Define to 1 if you have the `stat64' function. */ #undef HAVE_STAT64 /* Define to 1 if you have the header file. */ #undef HAVE_STDBOOL_H /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDIO_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the `strerror' function. */ #undef HAVE_STRERROR /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_MOUNT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_PARAM_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STATFS_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_TIME_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to 1 if you have the header file. */ #undef HAVE_WORDEXP_H /* Define to 1 if you have the header file. */ #undef HAVE_ZLIB_H /* Define to 1 if you have the header file. */ #undef HAVE_ZSTD_H /* Define to 1 to enable options for development */ #undef OPTION_DEVEL_SUPPORT /* Define to 1 to enable the support for lz4 compression */ #undef OPTION_LZ4_SUPPORT /* Define to 1 to enable the support for lzma compression */ #undef OPTION_LZMA_SUPPORT /* Define to 1 to enable the support for lzo compression */ #undef OPTION_LZO_SUPPORT /* Define to 1 to enable the support for zstd compression */ #undef OPTION_ZSTD_SUPPORT /* Define to 1 if OS is Linux */ #undef OS_LINUX /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define the version of the file format */ #undef PACKAGE_FILEFMT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define the date of the release */ #undef PACKAGE_RELDATE /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Major version number */ #undef PACKAGE_VERSION_A /* Medium version number */ #undef PACKAGE_VERSION_B /* Minor version number */ #undef PACKAGE_VERSION_C /* Patch version number */ #undef PACKAGE_VERSION_D /* Define to 1 if all of the C90 standard headers exist (not just the ones required in a freestanding environment). This macro is provided for backward compatibility; new code need not use it. */ #undef STDC_HEADERS /* Version number of package */ #undef VERSION /* Number of bits in a file offset, on hosts where this is settable. */ #undef _FILE_OFFSET_BITS /* Define for large files, on AIX-style hosts. */ #undef _LARGE_FILES fsarchiver-0.8.7/config.sub0000755000175000017500000010471414405612237012601 00000000000000#! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2021 Free Software Foundation, Inc. # shellcheck disable=SC2006,SC2268 # see below for rationale timestamp='2021-08-14' # This file 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 3 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, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # Please send patches to . # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # https://git.savannah.gnu.org/cgit/config.git/plain/config.sub # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. # The "shellcheck disable" line above the timestamp inhibits complaints # about features and limitations of the classic Bourne shell that were # superseded or lifted in POSIX. However, this script identifies a wide # variety of pre-POSIX systems that do not have POSIX shells at all, and # even some reasonably current systems (Solaris 10 as case-in-point) still # have a pre-POSIX /bin/sh. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Canonicalize a configuration name. Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright 1992-2021 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; *local*) # First pass through any local machine types. echo "$1" exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Split fields of configuration type # shellcheck disable=SC2162 saved_IFS=$IFS IFS="-" read field1 field2 field3 field4 <&2 exit 1 ;; *-*-*-*) basic_machine=$field1-$field2 basic_os=$field3-$field4 ;; *-*-*) # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two # parts maybe_os=$field2-$field3 case $maybe_os in nto-qnx* | linux-* | uclinux-uclibc* \ | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \ | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \ | storm-chaos* | os2-emx* | rtmk-nova*) basic_machine=$field1 basic_os=$maybe_os ;; android-linux) basic_machine=$field1-unknown basic_os=linux-android ;; *) basic_machine=$field1-$field2 basic_os=$field3 ;; esac ;; *-*) # A lone config we happen to match not fitting any pattern case $field1-$field2 in decstation-3100) basic_machine=mips-dec basic_os= ;; *-*) # Second component is usually, but not always the OS case $field2 in # Prevent following clause from handling this valid os sun*os*) basic_machine=$field1 basic_os=$field2 ;; zephyr*) basic_machine=$field1-unknown basic_os=$field2 ;; # Manufacturers dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \ | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \ | unicom* | ibm* | next | hp | isi* | apollo | altos* \ | convergent* | ncr* | news | 32* | 3600* | 3100* \ | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \ | ultra | tti* | harris | dolphin | highlevel | gould \ | cbm | ns | masscomp | apple | axis | knuth | cray \ | microblaze* | sim | cisco \ | oki | wec | wrs | winbond) basic_machine=$field1-$field2 basic_os= ;; *) basic_machine=$field1 basic_os=$field2 ;; esac ;; esac ;; *) # Convert single-component short-hands not valid as part of # multi-component configurations. case $field1 in 386bsd) basic_machine=i386-pc basic_os=bsd ;; a29khif) basic_machine=a29k-amd basic_os=udi ;; adobe68k) basic_machine=m68010-adobe basic_os=scout ;; alliant) basic_machine=fx80-alliant basic_os= ;; altos | altos3068) basic_machine=m68k-altos basic_os= ;; am29k) basic_machine=a29k-none basic_os=bsd ;; amdahl) basic_machine=580-amdahl basic_os=sysv ;; amiga) basic_machine=m68k-unknown basic_os= ;; amigaos | amigados) basic_machine=m68k-unknown basic_os=amigaos ;; amigaunix | amix) basic_machine=m68k-unknown basic_os=sysv4 ;; apollo68) basic_machine=m68k-apollo basic_os=sysv ;; apollo68bsd) basic_machine=m68k-apollo basic_os=bsd ;; aros) basic_machine=i386-pc basic_os=aros ;; aux) basic_machine=m68k-apple basic_os=aux ;; balance) basic_machine=ns32k-sequent basic_os=dynix ;; blackfin) basic_machine=bfin-unknown basic_os=linux ;; cegcc) basic_machine=arm-unknown basic_os=cegcc ;; convex-c1) basic_machine=c1-convex basic_os=bsd ;; convex-c2) basic_machine=c2-convex basic_os=bsd ;; convex-c32) basic_machine=c32-convex basic_os=bsd ;; convex-c34) basic_machine=c34-convex basic_os=bsd ;; convex-c38) basic_machine=c38-convex basic_os=bsd ;; cray) basic_machine=j90-cray basic_os=unicos ;; crds | unos) basic_machine=m68k-crds basic_os= ;; da30) basic_machine=m68k-da30 basic_os= ;; decstation | pmax | pmin | dec3100 | decstatn) basic_machine=mips-dec basic_os= ;; delta88) basic_machine=m88k-motorola basic_os=sysv3 ;; dicos) basic_machine=i686-pc basic_os=dicos ;; djgpp) basic_machine=i586-pc basic_os=msdosdjgpp ;; ebmon29k) basic_machine=a29k-amd basic_os=ebmon ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson basic_os=ose ;; gmicro) basic_machine=tron-gmicro basic_os=sysv ;; go32) basic_machine=i386-pc basic_os=go32 ;; h8300hms) basic_machine=h8300-hitachi basic_os=hms ;; h8300xray) basic_machine=h8300-hitachi basic_os=xray ;; h8500hms) basic_machine=h8500-hitachi basic_os=hms ;; harris) basic_machine=m88k-harris basic_os=sysv3 ;; hp300 | hp300hpux) basic_machine=m68k-hp basic_os=hpux ;; hp300bsd) basic_machine=m68k-hp basic_os=bsd ;; hppaosf) basic_machine=hppa1.1-hp basic_os=osf ;; hppro) basic_machine=hppa1.1-hp basic_os=proelf ;; i386mach) basic_machine=i386-mach basic_os=mach ;; isi68 | isi) basic_machine=m68k-isi basic_os=sysv ;; m68knommu) basic_machine=m68k-unknown basic_os=linux ;; magnum | m3230) basic_machine=mips-mips basic_os=sysv ;; merlin) basic_machine=ns32k-utek basic_os=sysv ;; mingw64) basic_machine=x86_64-pc basic_os=mingw64 ;; mingw32) basic_machine=i686-pc basic_os=mingw32 ;; mingw32ce) basic_machine=arm-unknown basic_os=mingw32ce ;; monitor) basic_machine=m68k-rom68k basic_os=coff ;; morphos) basic_machine=powerpc-unknown basic_os=morphos ;; moxiebox) basic_machine=moxie-unknown basic_os=moxiebox ;; msdos) basic_machine=i386-pc basic_os=msdos ;; msys) basic_machine=i686-pc basic_os=msys ;; mvs) basic_machine=i370-ibm basic_os=mvs ;; nacl) basic_machine=le32-unknown basic_os=nacl ;; ncr3000) basic_machine=i486-ncr basic_os=sysv4 ;; netbsd386) basic_machine=i386-pc basic_os=netbsd ;; netwinder) basic_machine=armv4l-rebel basic_os=linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony basic_os=newsos ;; news1000) basic_machine=m68030-sony basic_os=newsos ;; necv70) basic_machine=v70-nec basic_os=sysv ;; nh3000) basic_machine=m68k-harris basic_os=cxux ;; nh[45]000) basic_machine=m88k-harris basic_os=cxux ;; nindy960) basic_machine=i960-intel basic_os=nindy ;; mon960) basic_machine=i960-intel basic_os=mon960 ;; nonstopux) basic_machine=mips-compaq basic_os=nonstopux ;; os400) basic_machine=powerpc-ibm basic_os=os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson basic_os=ose ;; os68k) basic_machine=m68k-none basic_os=os68k ;; paragon) basic_machine=i860-intel basic_os=osf ;; parisc) basic_machine=hppa-unknown basic_os=linux ;; psp) basic_machine=mipsallegrexel-sony basic_os=psp ;; pw32) basic_machine=i586-unknown basic_os=pw32 ;; rdos | rdos64) basic_machine=x86_64-pc basic_os=rdos ;; rdos32) basic_machine=i386-pc basic_os=rdos ;; rom68k) basic_machine=m68k-rom68k basic_os=coff ;; sa29200) basic_machine=a29k-amd basic_os=udi ;; sei) basic_machine=mips-sei basic_os=seiux ;; sequent) basic_machine=i386-sequent basic_os= ;; sps7) basic_machine=m68k-bull basic_os=sysv2 ;; st2000) basic_machine=m68k-tandem basic_os= ;; stratus) basic_machine=i860-stratus basic_os=sysv4 ;; sun2) basic_machine=m68000-sun basic_os= ;; sun2os3) basic_machine=m68000-sun basic_os=sunos3 ;; sun2os4) basic_machine=m68000-sun basic_os=sunos4 ;; sun3) basic_machine=m68k-sun basic_os= ;; sun3os3) basic_machine=m68k-sun basic_os=sunos3 ;; sun3os4) basic_machine=m68k-sun basic_os=sunos4 ;; sun4) basic_machine=sparc-sun basic_os= ;; sun4os3) basic_machine=sparc-sun basic_os=sunos3 ;; sun4os4) basic_machine=sparc-sun basic_os=sunos4 ;; sun4sol2) basic_machine=sparc-sun basic_os=solaris2 ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun basic_os= ;; sv1) basic_machine=sv1-cray basic_os=unicos ;; symmetry) basic_machine=i386-sequent basic_os=dynix ;; t3e) basic_machine=alphaev5-cray basic_os=unicos ;; t90) basic_machine=t90-cray basic_os=unicos ;; toad1) basic_machine=pdp10-xkl basic_os=tops20 ;; tpf) basic_machine=s390x-ibm basic_os=tpf ;; udi29k) basic_machine=a29k-amd basic_os=udi ;; ultra3) basic_machine=a29k-nyu basic_os=sym1 ;; v810 | necv810) basic_machine=v810-nec basic_os=none ;; vaxv) basic_machine=vax-dec basic_os=sysv ;; vms) basic_machine=vax-dec basic_os=vms ;; vsta) basic_machine=i386-pc basic_os=vsta ;; vxworks960) basic_machine=i960-wrs basic_os=vxworks ;; vxworks68) basic_machine=m68k-wrs basic_os=vxworks ;; vxworks29k) basic_machine=a29k-wrs basic_os=vxworks ;; xbox) basic_machine=i686-pc basic_os=mingw32 ;; ymp) basic_machine=ymp-cray basic_os=unicos ;; *) basic_machine=$1 basic_os= ;; esac ;; esac # Decode 1-component or ad-hoc basic machines case $basic_machine in # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) cpu=hppa1.1 vendor=winbond ;; op50n) cpu=hppa1.1 vendor=oki ;; op60c) cpu=hppa1.1 vendor=oki ;; ibm*) cpu=i370 vendor=ibm ;; orion105) cpu=clipper vendor=highlevel ;; mac | mpw | mac-mpw) cpu=m68k vendor=apple ;; pmac | pmac-mpw) cpu=powerpc vendor=apple ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) cpu=m68000 vendor=att ;; 3b*) cpu=we32k vendor=att ;; bluegene*) cpu=powerpc vendor=ibm basic_os=cnk ;; decsystem10* | dec10*) cpu=pdp10 vendor=dec basic_os=tops10 ;; decsystem20* | dec20*) cpu=pdp10 vendor=dec basic_os=tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) cpu=m68k vendor=motorola ;; dpx2*) cpu=m68k vendor=bull basic_os=sysv3 ;; encore | umax | mmax) cpu=ns32k vendor=encore ;; elxsi) cpu=elxsi vendor=elxsi basic_os=${basic_os:-bsd} ;; fx2800) cpu=i860 vendor=alliant ;; genix) cpu=ns32k vendor=ns ;; h3050r* | hiux*) cpu=hppa1.1 vendor=hitachi basic_os=hiuxwe2 ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) cpu=hppa1.0 vendor=hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) cpu=m68000 vendor=hp ;; hp9k3[2-9][0-9]) cpu=m68k vendor=hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) cpu=hppa1.0 vendor=hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) cpu=hppa1.1 vendor=hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp cpu=hppa1.1 vendor=hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp cpu=hppa1.1 vendor=hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) cpu=hppa1.1 vendor=hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) cpu=hppa1.0 vendor=hp ;; i*86v32) cpu=`echo "$1" | sed -e 's/86.*/86/'` vendor=pc basic_os=sysv32 ;; i*86v4*) cpu=`echo "$1" | sed -e 's/86.*/86/'` vendor=pc basic_os=sysv4 ;; i*86v) cpu=`echo "$1" | sed -e 's/86.*/86/'` vendor=pc basic_os=sysv ;; i*86sol2) cpu=`echo "$1" | sed -e 's/86.*/86/'` vendor=pc basic_os=solaris2 ;; j90 | j90-cray) cpu=j90 vendor=cray basic_os=${basic_os:-unicos} ;; iris | iris4d) cpu=mips vendor=sgi case $basic_os in irix*) ;; *) basic_os=irix4 ;; esac ;; miniframe) cpu=m68000 vendor=convergent ;; *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*) cpu=m68k vendor=atari basic_os=mint ;; news-3600 | risc-news) cpu=mips vendor=sony basic_os=newsos ;; next | m*-next) cpu=m68k vendor=next case $basic_os in openstep*) ;; nextstep*) ;; ns2*) basic_os=nextstep2 ;; *) basic_os=nextstep3 ;; esac ;; np1) cpu=np1 vendor=gould ;; op50n-* | op60c-*) cpu=hppa1.1 vendor=oki basic_os=proelf ;; pa-hitachi) cpu=hppa1.1 vendor=hitachi basic_os=hiuxwe2 ;; pbd) cpu=sparc vendor=tti ;; pbb) cpu=m68k vendor=tti ;; pc532) cpu=ns32k vendor=pc532 ;; pn) cpu=pn vendor=gould ;; power) cpu=power vendor=ibm ;; ps2) cpu=i386 vendor=ibm ;; rm[46]00) cpu=mips vendor=siemens ;; rtpc | rtpc-*) cpu=romp vendor=ibm ;; sde) cpu=mipsisa32 vendor=sde basic_os=${basic_os:-elf} ;; simso-wrs) cpu=sparclite vendor=wrs basic_os=vxworks ;; tower | tower-32) cpu=m68k vendor=ncr ;; vpp*|vx|vx-*) cpu=f301 vendor=fujitsu ;; w65) cpu=w65 vendor=wdc ;; w89k-*) cpu=hppa1.1 vendor=winbond basic_os=proelf ;; none) cpu=none vendor=none ;; leon|leon[3-9]) cpu=sparc vendor=$basic_machine ;; leon-*|leon[3-9]-*) cpu=sparc vendor=`echo "$basic_machine" | sed 's/-.*//'` ;; *-*) # shellcheck disable=SC2162 saved_IFS=$IFS IFS="-" read cpu vendor <&2 exit 1 ;; esac ;; esac # Here we canonicalize certain aliases for manufacturers. case $vendor in digital*) vendor=dec ;; commodore*) vendor=cbm ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if test x$basic_os != x then # First recognize some ad-hoc caes, or perhaps split kernel-os, or else just # set os. case $basic_os in gnu/linux*) kernel=linux os=`echo "$basic_os" | sed -e 's|gnu/linux|gnu|'` ;; os2-emx) kernel=os2 os=`echo "$basic_os" | sed -e 's|os2-emx|emx|'` ;; nto-qnx*) kernel=nto os=`echo "$basic_os" | sed -e 's|nto-qnx|qnx|'` ;; *-*) # shellcheck disable=SC2162 saved_IFS=$IFS IFS="-" read kernel os <&2 exit 1 ;; esac # As a final step for OS-related things, validate the OS-kernel combination # (given a valid OS), if there is a kernel. case $kernel-$os in linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \ | linux-musl* | linux-relibc* | linux-uclibc* ) ;; uclinux-uclibc* ) ;; -dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* ) # These are just libc implementations, not actual OSes, and thus # require a kernel. echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2 exit 1 ;; kfreebsd*-gnu* | kopensolaris*-gnu*) ;; vxworks-simlinux | vxworks-simwindows | vxworks-spe) ;; nto-qnx*) ;; os2-emx) ;; *-eabi* | *-gnueabi*) ;; -*) # Blank kernel with real OS is always fine. ;; *-*) echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2 exit 1 ;; esac # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. case $vendor in unknown) case $cpu-$os in *-riscix*) vendor=acorn ;; *-sunos*) vendor=sun ;; *-cnk* | *-aix*) vendor=ibm ;; *-beos*) vendor=be ;; *-hpux*) vendor=hp ;; *-mpeix*) vendor=hp ;; *-hiux*) vendor=hitachi ;; *-unos*) vendor=crds ;; *-dgux*) vendor=dg ;; *-luna*) vendor=omron ;; *-genix*) vendor=ns ;; *-clix*) vendor=intergraph ;; *-mvs* | *-opened*) vendor=ibm ;; *-os400*) vendor=ibm ;; s390-* | s390x-*) vendor=ibm ;; *-ptx*) vendor=sequent ;; *-tpf*) vendor=ibm ;; *-vxsim* | *-vxworks* | *-windiss*) vendor=wrs ;; *-aux*) vendor=apple ;; *-hms*) vendor=hitachi ;; *-mpw* | *-macos*) vendor=apple ;; *-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*) vendor=atari ;; *-vos*) vendor=stratus ;; esac ;; esac echo "$cpu-$vendor-${kernel:+$kernel-}$os" exit # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: fsarchiver-0.8.7/AUTHORS0000644000175000017500000000000014405605077011651 00000000000000fsarchiver-0.8.7/internals/0000755000175000017500000000000014405605077012672 500000000000000fsarchiver-0.8.7/internals/MULTITHREADING0000644000175000017500000001441214405605077014657 00000000000000===================================================================== fsarchiver: Filesystem Archiver for Linux [http://www.fsarchiver.org] ===================================================================== About multi-threading --------------------- Today all the new processors are dual-core or quad-core. But all the standard compression tools are single threaded. It means that when you use "tar cfz" for "tar cfj", to compress a tarball using gzip or bzip2, you just use one cpu, so just 50% of 25% of the power you have. FSArchiver is multi-threaded if you use option "-j" to create several compression jobs, so that it can use all the power of your processors to compress faster. For instnace, compressing on an intel Q6600 quad-core with bzip2 is really fast, and with lzma it's not too slow. Implementation of the multi-threading ------------------------------------- FSArchiver is using three kinds of threads even if you don't use the option "-j". There is a main thread, a archive-io thread, and one or more compression/decompression threads. When you use option "-j" you just create more than one compression/decompression threads. To implement multi-threading, fsarchiver is using the pthread library (POSIX Pthread libraries). This is a standard threads implementation available on many operating systems. The most important thing in the multi-threading implementation is the queue which is implemented in queue.c. All the data that are read of written in a file first go in the queue. The queue is a list of items that have to be written: it can be either an header or a data block. The contents are split into blocks of few hundreds kilo-bytes. For instance, if you want to archive a 10MB file, it can be spitted into 50 datablocks. The queue must be big enough to contain multiple data blocks at a time. The compression/decompression threads are always searching for the first block to be processed in the queue, they process it, and update the block in the queue. For instance if the queue is able to store 10 data blocks at a given time, it means that a quad-core processor will have enough blocks to feed each of its cores, and then to use all the power of this processor. The size of the queue is defined by FSA_MAX_QUEUESIZE. It says how many data blocks can be stored in the queue at a given time. When this limit is reached, the thread which fills the queue will have to wait. Overview of the threads ----------------------- Here are how the threads work: a) when we write an archive (savefs / savedir): - the mainthread (create.c) is writing items to the queue - the compression thread is reading and writing in the queue - the archio thread is reading items to the disk (queue writer) b) when we read an archive (restfs / restrdir / archinfo): - the mainthread (extract.c) is reading items from the queue - the decompression thread is reading and writing in the queue - the archio thread is writing items to the disk (queue reader) Queue and synchronization ------------------------- The queue is what links all the threads together. It's a critical section of the code so it's very important that it contains no bug. The consistency of this queue is guaranteed with a mutex (to make sure that two threads can't change the same thing at the same time). It's very important that each function that locks this mutex unlocks it before it exits, else there will be a dead-lock. It's also useful to keep the queue management quite simple in order to avoid bugs. To synchronize threads, there are two attributes: a) end_of_archive: which is an attribute of the queue b) g_stopfillqueue which is a global variable outside of the queue c) g_abort is set when the user wants to stop. It's outside of the queue The threads have to play with these two attributes to manage events such as errors of the end of data. In a normal situation: 1. the queue writer puts data in the queue and sets end_of_archive to true when there are no more data to be written to the queue 2. the queue reader has to read data from the queue until end_of_archive is set to true and the queue is empty. In case of errors: a) when the user press Ctrl+C, the signal handler will set g_abort to true and the main thread has to manage that case. b) if the queue writer has a problem and wants to stop, it just has to set end_of_archive to true and the queue reader will stop reading it queue_set_end_of_queue(&g_queue, true); c) if the queue reader has a problem and wants to stop, it has to set g_stopfillqueue to true, to say to the queue writer that it has to stop. Then the queue writer checks g_stopfillqueue and stop filling the queue. Then the queue reader has to remove the remaining items from the queue, using queue_destroy_first_item() set_stopfillqueue(); // don't need any more data while (queue_get_end_of_queue(&g_queue)==false) queue_destroy_first_item(&g_queue); General rules for multi-threading: ---------------------------------- - all the important decisions (aborting, creating/destroying threads, ...) are taken in the main thread (implemented in either create.c or extract.c) - when there is an error, the first thing to do is to stop the source that fills the queue. If you are in the thread that reads the queue, you set g_stopfillqueue to true to stop the source of data and then process the remaining items which are still in the queue - in case of an error, a secondary thread has to make sure that the main thread is aware of that error (through a global variable or through the set_end_of_queue attribute if it's the queue writer) - in case of an error, always make sure the queue is empty before the current thread exits, so that the threads that are involved in the queue don't continue to wait for data. - the compression/decompression thread is in the middle of the chain. It exits when queue_get_end_of_queue(&g_queue)==false, so we must be sure that the queue is empty when we terminate with an error, else the compression thread will never exit and the program will hang. - only the main thread is involved in the management of the signals (when the users does Ctrl+C), the main threads must often checks that g_abort is set to false, and in case it's set to true, it must stops its own processing, and warn the secondary threads that they have to terminate. fsarchiver-0.8.7/internals/FILEFORMAT0000644000175000017500000002402714405605077014172 00000000000000===================================================================== fsarchiver: Filesystem Archiver for Linux [http://www.fsarchiver.org] ===================================================================== About the file format --------------------- The file format is made of two sort of structures: headers and data-blocks. The headers are all a dictionnary where the key is an integer. That way we can add new things in headers in next versions without having to break the file format. Global archive layout --------------------- 1) All fsarchiver archives are made of one or multiple volumes. Each volume starts with an FSA_MAGIC_VOLH header and terminates with a FSA_MAGIC_VOLF header. These headers are used to determine that the archive is the fsarchiver format, and which volume it is. 2) The beginning of the archive (which is always at the beginning of the first volume) contains an archive header (FSA_MAGIC_MAIN) where se store information such as the archive creation date. Then we write all the filesystem information header (FSA_MAGIC_FSIN). It stores things such as the filesystem type (ext3, reiserfs, ...), and all its attributes (label, uuid, space used, ...). Some of these attributes are specific to a particular filesystem. For instance, it saves the compatibility flags of ext2/ext3/ext4 filesystem so that fsarchiver can recreates a filesystem with the same properties. 3) Then the archive contains all the filesystems contents: there is an header that marks the beginning of a filesystem data (FSA_MAGIC_FSYB) and another header is used to mark its end (FSA_MAGIC_DATF). The filesystem contents is a list of object headers (FSA_MAGIC_OBJT) and data-blocks. 4) The archive splitting mechanism will never split the archive in the middle of an archive or datablock. An in-memory structure called s_writebuf has been created to store all the data which are written to the archive. All the bytes that are part of an header / block are first accumulated in a s_writebuf. When it's ready, it's passed to the write-to-archive function in charge of the file splitting. That way an s_writebuf is like an atomic item that cannot be splitted. The consequence it that it's not possible to respect exactly the volume size specified by the user, it will always be a bit smaller. About regular files management ------------------------------ Creating a normal tar.gz file is like compressing a tar file. It means if there is a corruption in the tar.gz file, we can't ungzip it and then we can untar it. Just a single corruption in one byte at the beginning of the file make it unreadable. For this reason fsarchiver is working the other way. It's like a gz.tar: we archive files that have already been compressed before. It provides a better safety for your data: if one byte if corrupt, we just ignore the current file and we can extract the next one. There is a problem with that: in case there are a lot of small files, like in the linux-sources-2.6, we compress each small files in a single data block of only few KB, which produces a bad compression ratio compared to compression of a big tar archive of all the small files. For that reason, all the small files are processed in a different way in fsarchiver-0.4.4 and later: it creates a set of small files that can fit in a single data block (256KB by default) and then it compresses a block which is quite big compared to the size of a single file. There is a threshold which is used to know whether a regular file will be considered as a small file (sharing a data block with other small files) or if it will be considered as a normal/big one having its own data blocks. This threshold depends of the size of a data block, which depends itself on the algirithm choosen to compress the data. In general, a data block is 256KB (it can be bigger) and the threshold will be 256KB/4 = 64KB. Empty files (size=0) are saved in a single regular file (as large files) and they have no footer (there is no need to have an md5 checksum for empty files) How files are stored in the archive ----------------------------------- There are many sort of objects in a filesystem: 1) special files (symbolic links, hard links, directories, ...) all these files just have one header in the archive. It contains all their attributes (name, permissions, xattr, time stats, ...) 2) normal/big regular files (bigger than the threshold) [REGFILE ] these files have their header first (FSA_MAGIC_OBJT) with the file attributes, and then one or several data blocks (depending on how big the file is), and then a file footer (FSA_MAGIC_FILF) with the md5sum of the contents for files which are not empty. The md5sum can't be written in the object header (before the data blocks) because it would require to read the file twice: first pass to compute the checksum, and a second pass to copy the contents the data blocks. (think about a very large file, say 5GB, which is written to an fsa archive which is split into small volumes, say 100MB) 3) small regular files (smaller than the threshold) [REGFILEM] small files are written to the archive when we have a full set of small files, or at the end of the savefs/savedir operation. during the savefs, all the small files are stored in a structure called s_regmulti. When this structure is full, it's copied to the archive and a new one is created. So we end up with the following data in the archive: we first write one object header (FSA_MAGIC_OBJT) for each small file in the s_regmulti. This headers contains extra keys (not found in object-header for normal files): DISKITEMKEY_MD5SUM, DISKITEMKEY_MULTIFILESCOUNT, DISKITEMKEY_MULTIFILESOFFSET. It's the md5sum for the file (we can compute it before it's written to disk because the files are quite small, and it saves an extra FSA_MAGIC_FILF footer), the number of small-files to expect in the current set (used at the extraction to know what read), and the offset of the data for the current file in the shrared data block. After the individual small-files headers, we write a single shared data-block (which is compressed and may be encrypted as any other data block). There is no header/footer after the shared data lock in the archive. About datablocks ---------------- Each data block which is written to the archive has its own header (FSA_MAGIC_BLKH). This header stores block attributes: original block size, compressed size, compression algorithm used, encryption algorithm used, offset of the first byte in the file, ... When both compression and encryption are used, the compression is done first. It's more efficient to process that way because the encryption algorithm will have less things to do because the compressed block is smaller. When the compression makes a block bigger than the original one, fsarchiver automatically ignores the compressed version and keeps the uncompressed block. About endianess --------------- fsarchiver should be endianess safe. All the integers are converted to little-endian before they are written to the disk. So it's neutral on intel platforms, and it requires a conversion on all the big-endian platforms. The only things that have to be converted are the integers which are part of the headers. These conversions don't pollute the source code since they are all converted in the functions that manage the headers: write-header-to-disk and read-header-from-disk functions. All the higer level functions in the code just have to add a number to the header, they don't have to worry about endianess. About headers ------------- All the information which is not the files contents itself (meta-data) are stored in a generic management system called headers. It's not just a normal C structure which is written to disk. A specific object oriented mechanism has been written for that. The headers are quite high-level data structures that are reused a lot in the sources. They provide endianess management, checksumming, and extensibility. Since the data are stored as a dictinnary, where the keys are 16bit integers, it will be possible to extend the headers in the future by adding new keys to add new information in the next versions. These headers are just implemented as s_dico in the program, and the magic and checksum are added when we write it to the archive file. Here is how an header is stored in an archive: - 32bit magic string used to identify the type of header it is - 32bit archive id (random number generated suring the savefs / savedir) - 16bit filesystem id (which filesystem of the archive it belongs to) - dictionary with its own internal data (length, 32bit checksum, ...) The random 32bit archive id is used to make sure the program won't be disturbed by nested archive in case the archive is corrupt. When an archive is corrupt, we can skip data and search for the next header using the known magic strings. In case we have nested archives, we could find the magic string that belongs to a nested archive. It won't be used since we also compare the random 32bit archive id, and the id of the nested archive header will be different so the program will know that it has to ignore that header and continue to search. About checksumming ------------------ Almost everything in the archive is checksummed to make sure the program will never silently restore corrupt data. The headers that contains all the meta-data (file names, permissions, attributes, ...) are checksummed using a 32bit fletcher32 checksum. The files contents are written in the archive as blocks of few hundreds kilo-bytes. Each block is compressed (except if the compression makes the block bigger) and it may also be encrypted (if the user provided a password). Each block also has its own 32bit fletcher32 checksum. All the files where size>0 also have an individual md5 checksum that makes sure the whole file is exactly the same as the original one (the blocks are checksummed but it allows to make sure we did not drop one of the block of a file for instance). Because of the md5 checksum, we can be sure that the program is aware of the corruption if it happens. fsarchiver-0.8.7/THANKS0000644000175000017500000000221114405605077011522 00000000000000===================================================================== fsarchiver: Filesystem Archiver for Linux [http://www.fsarchiver.org] ===================================================================== Special thanks to Clive Wagenaar who helped a lot by testing fsarchiver-0.3.x and found several important bugs and help in their resolutions. Special thanks to Leon Bene who reported a crash and who executed many tests using debugging version to identify the cause of the crash. It permitted to fix a critical integer overflow bug with the "u64 headerlen" when the total size of the attributes is more than 65535 bytes in the header. It has been fixed in fsarchiver-0.6.4. Many thanks to Marcos Mello who helped a lot improve the XFS support in fsarchiver-0.6.20. He found unexpected fsarchiver behaviors with new versions of the kernel and xfsprogs, did a lot of research regarding these components, and tested the XFS fixes in fsarchiver. He also provided fixes and documentation updates in fsarchiver-0.6.24. He also did a lot of research regarding EXT4 and helped improve the handling of extfs on very large block devices in fsarchiver-0.8.2. fsarchiver-0.8.7/COPYING0000644000175000017500000003543314405605077011656 00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS fsarchiver-0.8.7/INSTALL0000644000175000017500000003662614405612237011655 00000000000000Installation Instructions ************************* Copyright (C) 1994-1996, 1999-2002, 2004-2017, 2020-2021 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without warranty of any kind. Basic Installation ================== Briefly, the shell command './configure && make && make install' should configure, build, and install this package. The following more-detailed instructions are generic; see the 'README' file for instructions specific to this package. Some packages provide this 'INSTALL' file but do not implement all of the features documented below. The lack of an optional feature in a given package is not necessarily a bug. More recommendations for GNU packages can be found in *note Makefile Conventions: (standards)Makefile Conventions. The 'configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a 'Makefile' in each directory of the package. It may also create one or more '.h' files containing system-dependent definitions. Finally, it creates a shell script 'config.status' that you can run in the future to recreate the current configuration, and a file 'config.log' containing compiler output (useful mainly for debugging 'configure'). It can also use an optional file (typically called 'config.cache' and enabled with '--cache-file=config.cache' or simply '-C') that saves the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale cache files. If you need to do unusual things to compile the package, please try to figure out how 'configure' could check whether to do them, and mail diffs or instructions to the address given in the 'README' so they can be considered for the next release. If you are using the cache, and at some point 'config.cache' contains results you don't want to keep, you may remove or edit it. The file 'configure.ac' (or 'configure.in') is used to create 'configure' by a program called 'autoconf'. You need 'configure.ac' if you want to change it or regenerate 'configure' using a newer version of 'autoconf'. The simplest way to compile this package is: 1. 'cd' to the directory containing the package's source code and type './configure' to configure the package for your system. Running 'configure' might take a while. While running, it prints some messages telling which features it is checking for. 2. Type 'make' to compile the package. 3. Optionally, type 'make check' to run any self-tests that come with the package, generally using the just-built uninstalled binaries. 4. Type 'make install' to install the programs and any data files and documentation. When installing into a prefix owned by root, it is recommended that the package be configured and built as a regular user, and only the 'make install' phase executed with root privileges. 5. Optionally, type 'make installcheck' to repeat any self-tests, but this time using the binaries in their final installed location. This target does not install anything. Running this target as a regular user, particularly if the prior 'make install' required root privileges, verifies that the installation completed correctly. 6. You can remove the program binaries and object files from the source code directory by typing 'make clean'. To also remove the files that 'configure' created (so you can compile the package for a different kind of computer), type 'make distclean'. There is also a 'make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. 7. Often, you can also type 'make uninstall' to remove the installed files again. In practice, not all packages have tested that uninstallation works correctly, even though it is required by the GNU Coding Standards. 8. Some packages, particularly those that use Automake, provide 'make distcheck', which can by used by developers to test that all other targets like 'make install' and 'make uninstall' work correctly. This target is generally not run by end users. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the 'configure' script does not know about. Run './configure --help' for details on some of the pertinent environment variables. You can give 'configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you can use GNU 'make'. 'cd' to the directory where you want the object files and executables to go and run the 'configure' script. 'configure' automatically checks for the source code in the directory that 'configure' is in and in '..'. This is known as a "VPATH" build. With a non-GNU 'make', it is safer to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use 'make distclean' before reconfiguring for another architecture. On MacOS X 10.5 and later systems, you can create libraries and executables that work on multiple system types--known as "fat" or "universal" binaries--by specifying multiple '-arch' options to the compiler but only a single '-arch' option to the preprocessor. Like this: ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CPP="gcc -E" CXXCPP="g++ -E" This is not guaranteed to produce working output in all cases, you may have to build one architecture at a time and combine the results using the 'lipo' tool if you have problems. Installation Names ================== By default, 'make install' installs the package's commands under '/usr/local/bin', include files under '/usr/local/include', etc. You can specify an installation prefix other than '/usr/local' by giving 'configure' the option '--prefix=PREFIX', where PREFIX must be an absolute file name. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you pass the option '--exec-prefix=PREFIX' to 'configure', the package uses PREFIX as the prefix for installing programs and libraries. Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like '--bindir=DIR' to specify different values for particular kinds of files. Run 'configure --help' for a list of the directories you can set and what kinds of files go in them. In general, the default for these options is expressed in terms of '${prefix}', so that specifying just '--prefix' will affect all of the other directory specifications that were not explicitly provided. The most portable way to affect installation locations is to pass the correct locations to 'configure'; however, many packages provide one or both of the following shortcuts of passing variable assignments to the 'make install' command line to change installation locations without having to reconfigure or recompile. The first method involves providing an override variable for each affected directory. For example, 'make install prefix=/alternate/directory' will choose an alternate location for all directory configuration variables that were expressed in terms of '${prefix}'. Any directories that were specified during 'configure', but not in terms of '${prefix}', must each be overridden at install time for the entire installation to be relocated. The approach of makefile variable overrides for each directory variable is required by the GNU Coding Standards, and ideally causes no recompilation. However, some platforms have known limitations with the semantics of shared libraries that end up requiring recompilation when using this method, particularly noticeable in packages that use GNU Libtool. The second method involves providing the 'DESTDIR' variable. For example, 'make install DESTDIR=/alternate/directory' will prepend '/alternate/directory' before all installation names. The approach of 'DESTDIR' overrides is not required by the GNU Coding Standards, and does not work on platforms that have drive letters. On the other hand, it does better at avoiding recompilation issues, and works well even when some directory options were not specified in terms of '${prefix}' at 'configure' time. Optional Features ================= If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving 'configure' the option '--program-prefix=PREFIX' or '--program-suffix=SUFFIX'. Some packages pay attention to '--enable-FEATURE' options to 'configure', where FEATURE indicates an optional part of the package. They may also pay attention to '--with-PACKAGE' options, where PACKAGE is something like 'gnu-as' or 'x' (for the X Window System). The 'README' should mention any '--enable-' and '--with-' options that the package recognizes. For packages that use the X Window System, 'configure' can usually find the X include and library files automatically, but if it doesn't, you can use the 'configure' options '--x-includes=DIR' and '--x-libraries=DIR' to specify their locations. Some packages offer the ability to configure how verbose the execution of 'make' will be. For these packages, running './configure --enable-silent-rules' sets the default to minimal output, which can be overridden with 'make V=1'; while running './configure --disable-silent-rules' sets the default to verbose, which can be overridden with 'make V=0'. Particular systems ================== On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC is not installed, it is recommended to use the following options in order to use an ANSI C compiler: ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" and if that doesn't work, install pre-built binaries of GCC for HP-UX. HP-UX 'make' updates targets which have the same timestamps as their prerequisites, which makes it generally unusable when shipped generated files such as 'configure' are involved. Use GNU 'make' instead. On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot parse its '' header file. The option '-nodtk' can be used as a workaround. If GNU CC is not installed, it is therefore recommended to try ./configure CC="cc" and if that doesn't work, try ./configure CC="cc -nodtk" On Solaris, don't put '/usr/ucb' early in your 'PATH'. This directory contains several dysfunctional programs; working variants of these programs are available in '/usr/bin'. So, if you need '/usr/ucb' in your 'PATH', put it _after_ '/usr/bin'. On Haiku, software installed for all users goes in '/boot/common', not '/usr/local'. It is recommended to use the following options: ./configure --prefix=/boot/common Specifying the System Type ========================== There may be some features 'configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, 'configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the '--build=TYPE' option. TYPE can either be a short name for the system type, such as 'sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file 'config.sub' for the possible values of each field. If 'config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the option '--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with '--host=TYPE'. Sharing Defaults ================ If you want to set default values for 'configure' scripts to share, you can create a site shell script called 'config.site' that gives default values for variables like 'CC', 'cache_file', and 'prefix'. 'configure' looks for 'PREFIX/share/config.site' if it exists, then 'PREFIX/etc/config.site' if it exists. Or, you can set the 'CONFIG_SITE' environment variable to the location of the site script. A warning: not all 'configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to 'configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the 'configure' command line, using 'VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified 'gcc' to be used as the C compiler (unless it is overridden in the site shell script). Unfortunately, this technique does not work for 'CONFIG_SHELL' due to an Autoconf limitation. Until the limitation is lifted, you can use this workaround: CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash 'configure' Invocation ====================== 'configure' recognizes the following options to control how it operates. '--help' '-h' Print a summary of all of the options to 'configure', and exit. '--help=short' '--help=recursive' Print a summary of the options unique to this package's 'configure', and exit. The 'short' variant lists options used only in the top level, while the 'recursive' variant lists options also present in any nested packages. '--version' '-V' Print the version of Autoconf used to generate the 'configure' script, and exit. '--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally 'config.cache'. FILE defaults to '/dev/null' to disable caching. '--config-cache' '-C' Alias for '--cache-file=config.cache'. '--quiet' '--silent' '-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to '/dev/null' (any error messages will still be shown). '--srcdir=DIR' Look for the package's source code in directory DIR. Usually 'configure' can determine that directory automatically. '--prefix=DIR' Use DIR as the installation prefix. *note Installation Names:: for more details, including other options available for fine-tuning the installation locations. '--no-create' '-n' Run the configure checks, but stop before creating any output files. 'configure' also accepts some other, not widely useful, options. Run 'configure --help' for more details. fsarchiver-0.8.7/Makefile.in0000644000175000017500000006306614405612237012667 00000000000000# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ $(am__configure_deps) $(am__DIST_COMMON) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ cscope distdir distdir-am dist dist-all distcheck am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) \ config.h.in # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in AUTHORS \ COPYING ChangeLog INSTALL NEWS README THANKS compile \ config.guess config.sub depcomp install-sh missing DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ if test -d "$(distdir)"; then \ find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -rf "$(distdir)" \ || { sleep 5 && rm -rf "$(distdir)"; }; \ else :; fi am__post_remove_distdir = $(am__remove_distdir) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best DIST_TARGETS = dist-gzip # Exists only to be overridden by the user if desired. AM_DISTCHECK_DVI_TARGET = dvi distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BLKID_CFLAGS = @BLKID_CFLAGS@ BLKID_LIBS = @BLKID_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ COM_ERR_CFLAGS = @COM_ERR_CFLAGS@ COM_ERR_LIBS = @COM_ERR_LIBS@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_DEBUG_LEVEL = @DEFAULT_DEBUG_LEVEL@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ E2P_CFLAGS = @E2P_CFLAGS@ E2P_LIBS = @E2P_LIBS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ EXT2FS_CFLAGS = @EXT2FS_CFLAGS@ EXT2FS_LIBS = @EXT2FS_LIBS@ FSARCHIVER_LDFLAGS = @FSARCHIVER_LDFLAGS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LOGDIR = @LOGDIR@ LTLIBOBJS = @LTLIBOBJS@ LZMA_CFLAGS = @LZMA_CFLAGS@ LZMA_LIBS = @LZMA_LIBS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = src doc EXTRA_DIST = AUTHORS COPYING ChangeLog INSTALL NEWS README distrib internals autogen.sh MAINTAINERCLEANFILES = Makefile.in configure aclocal.m4 install-sh missing depcomp all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: am--refresh: Makefile @: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): config.h: stamp-h1 @test -f $@ || rm -f stamp-h1 @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status config.h $(srcdir)/config.h.in: $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f stamp-h1 touch $@ distclean-hdr: -rm -f config.h stamp-h1 # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscope: cscope.files test ! -s cscope.files \ || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) clean-cscope: -rm -f cscope.files cscope.files: clean-cscope cscopelist cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 $(am__post_remove_distdir) dist-lzip: distdir tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz $(am__post_remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) dist-zstd: distdir tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst $(am__post_remove_distdir) dist-tarZ: distdir @echo WARNING: "Support for distribution archives compressed with" \ "legacy program 'compress' is deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir @echo WARNING: "Support for shar distribution archives is" \ "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__post_remove_distdir) dist dist-all: $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' $(am__post_remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ *.tar.xz*) \ xz -dc $(distdir).tar.xz | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ *.tar.zst*) \ zstd -dc $(distdir).tar.zst | $(am__untar) ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build/sub \ && ../../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ --srcdir=../.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) $(AM_DISTCHECK_DVI_TARGET) \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ && cd "$$am__cwd" \ || exit 1 $(am__post_remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @test -n '$(distuninstallcheck_dir)' || { \ echo 'ERROR: trying to run $@ with an empty' \ '$$(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ $(am__cd) '$(distuninstallcheck_dir)' || { \ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-recursive all-am: Makefile config.h installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-recursive clean-am: clean-generic mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f Makefile distclean-am: clean-am distclean-generic distclean-hdr distclean-local \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(am__recursive_targets) all install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ am--refresh check check-am clean clean-cscope clean-generic \ cscope cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \ dist-gzip dist-hook dist-lzip dist-shar dist-tarZ dist-xz \ dist-zip dist-zstd distcheck distclean distclean-generic \ distclean-hdr distclean-local distclean-tags distcleancheck \ distdir distuninstallcheck dvi dvi-am html html-am info \ info-am install install-am install-data install-data-am \ install-dvi install-dvi-am install-exec install-exec-am \ install-html install-html-am install-info install-info-am \ install-man install-pdf install-pdf-am install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ pdf-am ps ps-am tags tags-am uninstall uninstall-am .PRECIOUS: Makefile static: rm -f src/fsarchiver $(MAKE) LDFLAGS="$(LDFLAGS) -static" distclean-local: rm -rf autom4te.cache rm -f config.h.in~ dist-hook: rm -rf `find $(distdir) -name .svn` # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: fsarchiver-0.8.7/missing0000755000175000017500000001533614405612237012216 00000000000000#! /bin/sh # Common wrapper for a few potentially missing GNU programs. scriptversion=2018-03-07.03; # UTC # Copyright (C) 1996-2021 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 1996. # 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, 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, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try '$0 --help' for more information" exit 1 fi case $1 in --is-lightweight) # Used by our autoconf macros to check whether the available missing # script is modern enough. exit 0 ;; --run) # Back-compat with the calling convention used by older automake. shift ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due to PROGRAM being missing or too old. Options: -h, --help display this help and exit -v, --version output version information and exit Supported PROGRAM values: aclocal autoconf autoheader autom4te automake makeinfo bison yacc flex lex help2man Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 'g' are ignored when checking the name. Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: unknown '$1' option" echo 1>&2 "Try '$0 --help' for more information" exit 1 ;; esac # Run the given program, remember its exit status. "$@"; st=$? # If it succeeded, we are done. test $st -eq 0 && exit 0 # Also exit now if we it failed (or wasn't found), and '--version' was # passed; such an option is passed most likely to detect whether the # program is present and works. case $2 in --version|--help) exit $st;; esac # Exit code 63 means version mismatch. This often happens when the user # tries to use an ancient version of a tool on a file that requires a # minimum version. if test $st -eq 63; then msg="probably too old" elif test $st -eq 127; then # Program was missing. msg="missing on your system" else # Program was found and executed, but failed. Give up. exit $st fi perl_URL=https://www.perl.org/ flex_URL=https://github.com/westes/flex gnu_software_URL=https://www.gnu.org/software program_details () { case $1 in aclocal|automake) echo "The '$1' program is part of the GNU Automake package:" echo "<$gnu_software_URL/automake>" echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/autoconf>" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; autoconf|autom4te|autoheader) echo "The '$1' program is part of the GNU Autoconf package:" echo "<$gnu_software_URL/autoconf/>" echo "It also requires GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; esac } give_advice () { # Normalize program name to check for. normalized_program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` printf '%s\n' "'$1' is $msg." configure_deps="'configure.ac' or m4 files included by 'configure.ac'" case $normalized_program in autoconf*) echo "You should only need it if you modified 'configure.ac'," echo "or m4 files included by it." program_details 'autoconf' ;; autoheader*) echo "You should only need it if you modified 'acconfig.h' or" echo "$configure_deps." program_details 'autoheader' ;; automake*) echo "You should only need it if you modified 'Makefile.am' or" echo "$configure_deps." program_details 'automake' ;; aclocal*) echo "You should only need it if you modified 'acinclude.m4' or" echo "$configure_deps." program_details 'aclocal' ;; autom4te*) echo "You might have modified some maintainer files that require" echo "the 'autom4te' program to be rebuilt." program_details 'autom4te' ;; bison*|yacc*) echo "You should only need it if you modified a '.y' file." echo "You may want to install the GNU Bison package:" echo "<$gnu_software_URL/bison/>" ;; lex*|flex*) echo "You should only need it if you modified a '.l' file." echo "You may want to install the Fast Lexical Analyzer package:" echo "<$flex_URL>" ;; help2man*) echo "You should only need it if you modified a dependency" \ "of a man page." echo "You may want to install the GNU Help2man package:" echo "<$gnu_software_URL/help2man/>" ;; makeinfo*) echo "You should only need it if you modified a '.texi' file, or" echo "any other file indirectly affecting the aspect of the manual." echo "You might want to install the Texinfo package:" echo "<$gnu_software_URL/texinfo/>" echo "The spurious makeinfo call might also be the consequence of" echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" echo "want to install GNU make:" echo "<$gnu_software_URL/make/>" ;; *) echo "You might have modified some files without having the proper" echo "tools for further handling them. Check the 'README' file, it" echo "often tells you about the needed prerequisites for installing" echo "this package. You may also peek at any GNU archive site, in" echo "case some other package contains this missing '$1' program." ;; esac } give_advice "$1" | sed -e '1s/^/WARNING: /' \ -e '2,$s/^/ /' >&2 # Propagate the correct exit status (expected to be 127 for a program # not found, 63 for a program that failed due to version mismatch). exit $st # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: fsarchiver-0.8.7/Makefile.am0000644000175000017500000000056314405605077012653 00000000000000SUBDIRS = src doc EXTRA_DIST = AUTHORS COPYING ChangeLog INSTALL NEWS README distrib internals autogen.sh static: rm -f src/fsarchiver $(MAKE) LDFLAGS="$(LDFLAGS) -static" distclean-local: rm -rf autom4te.cache rm -f config.h.in~ dist-hook: rm -rf `find $(distdir) -name .svn` MAINTAINERCLEANFILES = Makefile.in configure aclocal.m4 install-sh missing depcomp fsarchiver-0.8.7/doc/0000755000175000017500000000000014405612250011427 500000000000000fsarchiver-0.8.7/doc/Makefile.in0000644000175000017500000003561314405612237013431 00000000000000# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ subdir = doc ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } man8dir = $(mandir)/man8 am__installdirs = "$(DESTDIR)$(man8dir)" NROFF = nroff MANS = $(man_MANS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BLKID_CFLAGS = @BLKID_CFLAGS@ BLKID_LIBS = @BLKID_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ COM_ERR_CFLAGS = @COM_ERR_CFLAGS@ COM_ERR_LIBS = @COM_ERR_LIBS@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_DEBUG_LEVEL = @DEFAULT_DEBUG_LEVEL@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ E2P_CFLAGS = @E2P_CFLAGS@ E2P_LIBS = @E2P_LIBS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ EXT2FS_CFLAGS = @EXT2FS_CFLAGS@ EXT2FS_LIBS = @EXT2FS_LIBS@ FSARCHIVER_LDFLAGS = @FSARCHIVER_LDFLAGS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LOGDIR = @LOGDIR@ LTLIBOBJS = @LTLIBOBJS@ LZMA_CFLAGS = @LZMA_CFLAGS@ LZMA_LIBS = @LZMA_LIBS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ man_MANS = fsarchiver.8 EXTRA_DIST = $(man_MANS) MAINTAINERCLEANFILES = Makefile.in all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu doc/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-man8: $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(man_MANS)'; \ test -n "$(man8dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.8[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \ done; } uninstall-man8: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man8dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.8[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir) tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(MANS) installdirs: for dir in "$(DESTDIR)$(man8dir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-generic mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-man install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-man8 install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-man uninstall-man: uninstall-man8 .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic cscopelist-am \ ctags-am distclean distclean-generic distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-man8 install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ pdf-am ps ps-am tags-am uninstall uninstall-am uninstall-man \ uninstall-man8 .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: fsarchiver-0.8.7/doc/Makefile.am0000644000175000017500000000012514405605077013412 00000000000000man_MANS = fsarchiver.8 EXTRA_DIST = $(man_MANS) MAINTAINERCLEANFILES = Makefile.in fsarchiver-0.8.7/doc/fsarchiver.80000644000175000017500000002136214405605077013611 00000000000000.TH FSARCHIVER 8 "30 December 2009" .SH NAME fsarchiver \- filesystem archiver .SH DESCRIPTION fsarchiver is a system tool that allows you to save the contents of a filesystem to a compressed archive file. The filesystem contents can be restored on a device which has a different size and it can be restored on a different filesystem. Unlike tar/dar, fsarchiver also creates the filesystem when it extracts the data to devices. Everything is checksummed in the archive in order to protect the data. If the archive is corrupt, you just lose the current file, not the whole archive. .SH LINKS .SS Official project homepage: http://www.fsarchiver.org .SS Quick Start guide: http://www.fsarchiver.org/quickstart/ .SS Git repository: https://github.com/fdupoux/fsarchiver .SS Report a bug: https://github.com/fdupoux/fsarchiver/issues .SH SYNOPSIS .B fsarchiver [ .I options .B ] savefs .I archive .I device .B ... .PP .B fsarchiver [ .I options .B ] restfs .I archive .BI id= n ,dest= device [,mkfs= fstype ,mkfsopt= options ,label= \ newlabel ,uuid= newuuid ] .B ... .PP .B fsarchiver [ .I options .B ] savedir .I archive .I directory .B ... .PP .B fsarchiver [ .I options .B ] restdir .I archive destination .PP .B fsarchiver [ .I options .B ] archinfo .I archive .PP .B fsarchiver [ .I options .B ] probe [detailed] .SH COMMANDS .TP .B savefs Save .I device filesystem to .IR archive . .TP .B restfs Restore filesystems from .IR archive . This overwrites the existing data on .IR device . Zero-based index .I n indicates the part of the archive to restore. Optionally, a filesystem may be converted to .IR fstype and extra mkfs .IR options specified. .IR newlabel and .IR newuuid override values stored in the archive. .TP .B savedir Save .I directories to .I archive (similar to a compressed tarball). .TP .B restdir Restore data from .I archive which is not based on a filesystem to .IR destination . .TP .B archinfo Show information about an existing .I archive file and its contents. .TP .B probe Show list of filesystems detected on the disks. .SH "OPTIONS" .PP .IP "\fB\-h, \-\-help\fP" Show help and information about how to use fsarchiver with examples. .IP "\fB\-V, \-\-version\fP" Show program version and exit. .IP "\fB\-v, \-\-verbose\fP" Verbose mode (can be used several times to increase the level of details). The details will be printed to the console. .IP "\fB\-o, \-\-overwrite\fP" Overwrite the archive if it already exists instead of failing. .IP "\fB\-d, \-\-debug\fP" Debug mode (can be used several times to increase the level of details). The details will be written in /var/log/fsarchiver.log. .IP "\fB\-x, \-\-experimental\fP" Allow to save filesystems which support is considered experimental in fsarchiver. .IP "\fB\-A, \-\-allow-rw-mounted\fP" Allow to save a filesystem which is mounted in read-write (live backup). By default fsarchiver fails with an error if the device is mounted in read-write mode which allows modifications to be done on the filesystem during the backup. Modifications can drive to inconsistencies in the backup. Using LVM snapshots is the recommended way to make backups since it will provide consistency, but it is only available for filesystems which are on LVM logical volumes. Deleted files during the backup process are ignored when this option is used. .IP "\fB\-a, \-\-allow-no-acl-xattr\fP" Allow to save a filesystem when ACLs and extended attributes are not supported (or are disabled) by the kernel. By default fsarchiver fails with an error if it cannot access ACLs and extended attributes, since they would not be saved. If you do not need ACLs and extended attributes preserved then it is safe to use this option. .IP "\fB\-e pattern, \-\-exclude=pattern\fP" Exclude files and directories that match specified pattern. The pattern can contain shell wildcards such as * and ? or may be either a simple file/dir name or an absolute file/dir path. You must use quotes around the pattern each time you use wildcards, else it would be interpreted by the shell. The wildcards must be interpreted by fsarchiver. See examples below for more details about this option. .IP "\fB\-L label, \-\-label=label\fP" Set the label of the archive: it is just a comment about its contents. It can be used to remember a particular thing about the archive or the state of the filesystem for instance. .IP "\fB\-z level, \-\-compress=level\fP" Legacy compression levels are between 0 (very fast) and 9 (very good). The memory requirement increases a lot with the best compression levels, and it is multiplied by the number of compression threads (option -j). Level 9 is considered as an extreme compression level and requires an huge amount of memory to run. For more details please read this page: http://www.fsarchiver.org/compression/ .IP "\fB\-Z level, \-\-zstd=level\fP" Zstd compression levels are between 1 (very fast) and 22 (very good). The memory requirement increases a lot with the best compression levels, and it is multiplied by the number of compression threads (option -j). Levels above 20 are considered as extreme compression levels and requires an huge amount of memory to run. For more details please read this page: http://www.fsarchiver.org/compression/ .IP "\fB\-s mbsize, \-\-split=mbsize\fP" Split the archive into several files of mbsize megabytes each. .IP "\fB\-j count, \-\-jobs=count\fP" Create more than one (de)compression thread. Useful on multi-core CPUs. By default fsarchiver will only use one (de)compression thread (-j 1) and then only one logical processor will be used for the task. You should use this option if you have a multi-core CPU or more than one physical CPU on your computer. The typical way to use it is to specify the number of logical processors available so that all the processing power is used to (de)compress the archive very quickly. You may also want to use all logical processors but one so that your system stays responsive for other applications. .IP "\fB\-c password, \-\-cryptpass=password\fP" Encrypt/decrypt data in archive. Password length: 6 to 64 characters. You can either provide a real password or a dash (-c -). Use the dash if you do not want to provide the password in the command line. It will be prompted in the terminal instead. .SH EXAMPLES .SS save only one filesystem (/dev/sda1) to an archive: fsarchiver savefs /data/myarchive1.fsa /dev/sda1 .SS save two filesystems (/dev/sda1 and /dev/sdb1) to an archive: fsarchiver savefs /data/myarchive2.fsa /dev/sda1 /dev/sdb1 .SS restore the first filesystem from an archive (first = number 0): fsarchiver restfs /data/myarchive2.fsa id=0,dest=/dev/sda1 .SS restore the second filesystem from an archive (second = number 1): fsarchiver restfs /data/myarchive2.fsa id=1,dest=/dev/sdb1 .SS restore two filesystems from an archive (number 0 and 1): fsarchiver restfs /data/arch2.fsa id=0,dest=/dev/sda1 id=1,dest=/dev/sdb1 .SS restore a filesystem from an archive and convert it to reiserfs: fsarchiver restfs /data/myarchive1.fsa id=0,dest=/dev/sda1,mkfs=reiserfs .SS restore a filesystem from an archive and specify extra mkfs options: fsarchiver restfs /data/myarchive1.fsa id=0,dest=/dev/sda1,mkfs=ext4,mkfsopt="-I 256" .SS restore a filesystem from an archive and specify a new filesystem label: fsarchiver restfs /data/myarchive1.fsa id=0,dest=/dev/sda1,label=root .SS restore a filesystem from an archive and specify a new filesystem UUID: fsarchiver restfs /data/myarchive1.fsa id=0,dest=/dev/sda1,uuid=5f6e5f4f-dc2a-4dbd-a6ea-9ca997cde75e .SS save the contents of /usr/src/linux to an archive (similar to tar): fsarchiver savedir /data/linux-sources.fsa /usr/src/linux .SS save a filesystem (/dev/sda1) to an archive split into volumes of 680MB: fsarchiver savefs -s 680 /data/myarchive1.fsa /dev/sda1 .SS save a filesystem and exclude all files/dirs called 'pagefile.*': fsarchiver savefs /data/myarchive.fsa /dev/sda1 --exclude='pagefile.*' .SS generic exclude for 'share' such as '/usr/share' and '/usr/local/share': fsarchiver savefs /data/myarchive.fsa --exclude=share .SS absolute exclude valid for '/usr/share' but not for '/usr/local/share': fsarchiver savefs /data/myarchive.fsa --exclude=/usr/share .SS save a filesystem (/dev/sda1) to an encrypted archive: fsarchiver savefs -c mypassword /data/myarchive1.fsa /dev/sda1 .SS same as before but prompt for password in the terminal: fsarchiver savefs -c - /data/myarchive1.fsa /dev/sda1 .SS extract an archive made of simple files to /tmp/extract: fsarchiver restdir /data/linux-sources.fsa /tmp/extract .SS show information about an archive and its filesystems: fsarchiver archinfo /data/myarchive2.fsa .SH WARNING .B fsarchiver is considered stable for Linux filesystems such as EXT4 and XFS but unstable for NTFS. .SH AUTHOR fsarchiver was written by Francois Dupoux. It is released under the GPL2 (GNU General Public License version 2). This manpage was written by Ilya Barygin and Francois Dupoux. fsarchiver-0.8.7/NEWS0000644000175000017500000000036114405605077011312 00000000000000===================================================================== fsarchiver: Filesystem Archiver for Linux [http://www.fsarchiver.org] ===================================================================== The is no news for the moment fsarchiver-0.8.7/depcomp0000755000175000017500000005602014405612237012167 00000000000000#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2018-03-07.03; # UTC # Copyright (C) 1999-2021 Free Software Foundation, Inc. # 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, 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, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by 'PROGRAMS ARGS'. object Object file output by 'PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputting dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac # Get the directory component of the given path, and save it in the # global variables '$dir'. Note that this directory component will # be either empty or ending with a '/' character. This is deliberate. set_dir_from () { case $1 in */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; *) dir=;; esac } # Get the suffix-stripped basename of the given path, and save it the # global variable '$base'. set_base_from () { base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` } # If no dependency file was actually created by the compiler invocation, # we still have to create a dummy depfile, to avoid errors with the # Makefile "include basename.Plo" scheme. make_dummy_depfile () { echo "#dummy" > "$depfile" } # Factor out some common post-processing of the generated depfile. # Requires the auxiliary global variable '$tmpdepfile' to be set. aix_post_process_depfile () { # If the compiler actually managed to produce a dependency file, # post-process it. if test -f "$tmpdepfile"; then # Each line is of the form 'foo.o: dependency.h'. # Do two passes, one to just change these to # $object: dependency.h # and one to simply output # dependency.h: # which is needed to avoid the deleted-header problem. { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" } > "$depfile" rm -f "$tmpdepfile" else make_dummy_depfile fi } # A tabulation character. tab=' ' # A newline character. nl=' ' # Character ranges might be problematic outside the C locale. # These definitions help. upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ lower=abcdefghijklmnopqrstuvwxyz digits=0123456789 alpha=${upper}${lower} if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Avoid interferences from the environment. gccflag= dashmflag= # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvisualcpp fi if test "$depmode" = msvc7msys; then # This is just like msvc7 but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvc7 fi if test "$depmode" = xlc; then # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. gccflag=-qmakedep=gcc,-MF depmode=gcc fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. ## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. ## (see the conditional assignment to $gccflag above). ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). Also, it might not be ## supported by the other compilers which use the 'gcc' depmode. ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The second -e expression handles DOS-style file names with drive # letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the "deleted header file" problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. ## Some versions of gcc put a space before the ':'. On the theory ## that the space means something, we add a space to the output as ## well. hp depmode also adds that space, but also prefixes the VPATH ## to the object. Take care to not repeat it in the output. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like '#:fec' to the end of the # dependency line. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ | tr "$nl" ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" ;; xlc) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts '$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done aix_post_process_depfile ;; tcc) # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 # FIXME: That version still under development at the moment of writing. # Make that this statement remains true also for stable, released # versions. # It will wrap lines (doesn't matter whether long or short) with a # trailing '\', as in: # # foo.o : \ # foo.c \ # foo.h \ # # It will put a trailing '\' even on the last line, and will use leading # spaces rather than leading tabs (at least since its commit 0394caf7 # "Emit spaces for -MD"). "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. # We have to change lines of the first kind to '$object: \'. sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" # And for each line of the second kind, we have to emit a 'dep.h:' # dummy dependency, to avoid the deleted-header problem. sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" rm -f "$tmpdepfile" ;; ## The order of this option in the case statement is important, since the ## shell code in configure will try each of these formats in the order ## listed in this file. A plain '-MD' option would be understood by many ## compilers, so we must ensure this comes after the gcc and icc options. pgcc) # Portland's C compiler understands '-MD'. # Will always output deps to 'file.d' where file is the root name of the # source file under compilation, even if file resides in a subdirectory. # The object file name does not affect the name of the '.d' file. # pgcc 10.2 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using '\' : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... set_dir_from "$object" # Use the source, not the object, to determine the base name, since # that's sadly what pgcc will do too. set_base_from "$source" tmpdepfile=$base.d # For projects that build the same source file twice into different object # files, the pgcc approach of using the *source* file root name can cause # problems in parallel builds. Use a locking strategy to avoid stomping on # the same $tmpdepfile. lockdir=$base.d-lock trap " echo '$0: caught signal, cleaning up...' >&2 rmdir '$lockdir' exit 1 " 1 2 13 15 numtries=100 i=$numtries while test $i -gt 0; do # mkdir is a portable test-and-set. if mkdir "$lockdir" 2>/dev/null; then # This process acquired the lock. "$@" -MD stat=$? # Release the lock. rmdir "$lockdir" break else # If the lock is being held by a different process, wait # until the winning process is done or we timeout. while test -d "$lockdir" && test $i -gt 0; do sleep 1 i=`expr $i - 1` done fi i=`expr $i - 1` done trap - 1 2 13 15 if test $i -le 0; then echo "$0: failed to acquire lock after $numtries attempts" >&2 echo "$0: check lockdir '$lockdir'" >&2 exit 1 fi if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" # Add 'dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in 'foo.d' instead, so we check for that too. # Subdirectories are respected. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then # Libtool generates 2 separate objects for the 2 libraries. These # two compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir$base.o.d # libtool 1.5 tmpdepfile2=$dir.libs/$base.o.d # Likewise. tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d "$@" -MD fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done # Same post-processing that is required for AIX mode. aix_post_process_depfile ;; msvc7) if test "$libtool" = yes; then showIncludes=-Wc,-showIncludes else showIncludes=-showIncludes fi "$@" $showIncludes > "$tmpdepfile" stat=$? grep -v '^Note: including file: ' "$tmpdepfile" if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The first sed program below extracts the file names and escapes # backslashes for cygpath. The second sed program outputs the file # name when reading, but also accumulates all include files in the # hold buffer in order to output them again at the end. This only # works with sed implementations that can handle large buffers. sed < "$tmpdepfile" -n ' /^Note: including file: *\(.*\)/ { s//\1/ s/\\/\\\\/g p }' | $cygpath_u | sort -u | sed -n ' s/ /\\ /g s/\(.*\)/'"$tab"'\1 \\/p s/.\(.*\) \\/\1:/ H $ { s/.*/'"$tab"'/ G p }' >> "$depfile" echo >> "$depfile" # make sure the fragment doesn't end with a backslash rm -f "$tmpdepfile" ;; msvc7msys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for ':' # in the target name. This is to cope with DOS-style filenames: # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. "$@" $dashmflag | sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this sed invocation # correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -arch) eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" # makedepend may prepend the VPATH from the source file name to the object. # No need to regex-escape $object, excess matching of '.' is harmless. sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process the last invocation # correctly. Breaking it into two sed invocations is a workaround. sed '1,2d' "$tmpdepfile" \ | tr ' ' "$nl" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E \ | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" echo "$tab" >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: fsarchiver-0.8.7/distrib/0000755000175000017500000000000014405605077012333 500000000000000fsarchiver-0.8.7/distrib/rpm/0000755000175000017500000000000014405605077013131 500000000000000fsarchiver-0.8.7/distrib/rpm/fsarchiver.spec0000644000175000017500000000272414405612057016062 00000000000000Name: fsarchiver Version: 0.8.7 Release: 1%{?dist} Summary: Safe and flexible file-system backup/deployment tool Group: Applications/Archiving License: GPLv2 URL: http://www.fsarchiver.org Source0: https://github.com/fdupoux/%{name}/releases/download/%{version}/%{name}-%{version}.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: e2fsprogs-devel => 1.41.4 BuildRequires: libuuid-devel BuildRequires: libblkid-devel BuildRequires: e2fsprogs BuildRequires: libattr-devel BuildRequires: libgcrypt-devel BuildRequires: zlib-devel BuildRequires: bzip2-devel BuildRequires: lzo-devel BuildRequires: lz4-devel BuildRequires: xz-devel BuildRequires: libzstd-devel %description FSArchiver is a system tool that allows you to save the contents of a filesystem to a compressed archive file. The filesystem contents can be restored on a device which has a different size and it can be restored on a different filesystem. Unlike tar/dar, FSArchiver also creates the filesystem when it extracts the data to devices. Everything is checksummed in the archive in order to protect the data. If the archive is corrupt, you just lose the current file, not the whole archive. %prep %setup -q %build %configure make %{?_smp_mflags} %install rm -rf $RPM_BUILD_ROOT make install DESTDIR=$RPM_BUILD_ROOT %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root,-) %{_sbindir}/%{name} %{_mandir}/man8/%{name}* %doc COPYING README THANKS NEWS %changelog fsarchiver-0.8.7/src/0000755000175000017500000000000014405612250011451 500000000000000fsarchiver-0.8.7/src/comp_lz4.c0000644000175000017500000000362314405605077013301 00000000000000 /* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2017 Cristian Vazquez. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include "fsarchiver.h" #include "common.h" #include "comp_lz4.h" #include "error.h" #ifdef OPTION_LZ4_SUPPORT int compress_block_lz4(u64 origsize, u64 *compsize, u8 *origbuf, u8 *compbuf, u64 compbufsize, int level) { int destsize=compbufsize; int res; #define LZ4_VERSION (LZ4_VERSION_MAJOR*10 + LZ4_VERSION_MINOR) #if LZ4_VERSION >= 17 res=LZ4_compress_default((const char*)origbuf, (char*)compbuf, (int)origsize, destsize); if (res==0){ errprintf("LZ4_compress_default(): failed.\n"); return FSAERR_UNKNOWN; } #else res=LZ4_compress((const char*)origbuf, (char*)compbuf, (int)origsize); if (res==0){ errprintf("LZ4_compress(): failed.\n"); return FSAERR_UNKNOWN; } #endif // LZ4_VERSION if (res > 0){ *compsize=(u64)res; return FSAERR_SUCCESS; } return FSAERR_UNKNOWN; } int uncompress_block_lz4(u64 compsize, u64 *origsize, u8 *origbuf, u64 origbufsize, u8 *compbuf) { int destsize=origbufsize; int res; if((res=LZ4_decompress_safe((char*)compbuf, (char*)origbuf, compsize, destsize)) > 0){ *origsize=(u64)res; return FSAERR_SUCCESS; } errprintf("LZ4_decompress_safe() failed, res=%d\n", res); return FSAERR_UNKNOWN; } #endif //OPTION_LZ4_SUPPORT fsarchiver-0.8.7/src/oper_probe.h0000644000175000017500000000126714405605077013715 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifndef __OPER_PROBE_H__ #define __OPER_PROBE_H__ int oper_probe(bool details); #endif // __OPER_PROBE_H__ fsarchiver-0.8.7/src/archinfo.h0000644000175000017500000000160414405605077013345 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifndef __ARCHINFO_H__ #define __ARCHINFO_H__ struct s_dico; struct s_archreader; int archinfo_show_mainhead(struct s_archreader *ai, struct s_dico *dicomainhead); int archinfo_show_fshead(struct s_dico *dicofshead, int fsid); char *compalgostr(int algo); char *cryptalgostr(int algo); #endif // __ARCHINFO_H__ fsarchiver-0.8.7/src/archreader.h0000644000175000017500000000567014405605077013663 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifndef __ARCHREADER_H__ #define __ARCHREADER_H__ #include struct s_blockinfo; struct s_headinfo; struct s_dico; struct s_archreader; typedef struct s_archreader carchreader; struct s_archreader { int archfd; // file descriptor of the current volume (set to -1 when closed) u32 archid; // 32bit archive id for checking (random number generated at creation) u64 fscount; // how many filesystems in archive (valid only if archtype=filesystems) u32 archtype; // what has been saved in the archive: filesystems or directories u32 curvol; // current volume number, starts at 0, incremented when we change the volume u32 compalgo; // compression algorithm which has been used to create the archive u32 cryptalgo; // encryption algorithm which has been used to create the archive u32 complevel; // compression level which is specific to the compression algorithm u32 fsacomp; // fsa compression level given on the command line by the user u64 creattime; // archive create time (number of seconds since epoch) u64 minfsaver; // minimum fsarchiver version required to restore that archive u32 hasdirsinfohead; // true if the archive has a "DiRs" header (introduced in 0.6.7) int filefmtver; // set to 1 for "FsArCh_001" or 2 for "FsArCh_002" char filefmt[FSA_MAX_FILEFMTLEN]; // file format of that archive char creatver[FSA_MAX_PROGVERLEN]; // fsa version used to create archive char label[FSA_MAX_LABELLEN]; // archive label defined by the user char basepath[PATH_MAX]; // path of the first volume of an archive char volpath[PATH_MAX]; // path of the current volume of an archive }; int archreader_init(carchreader *ai); int archreader_destroy(carchreader *ai); int archreader_open(carchreader *ai); int archreader_close(carchreader *ai); int archreader_incvolume(carchreader *ai, bool waitkeypress); int archreader_volpath(carchreader *ai); int archreader_read_data(carchreader *ai, void *data, u64 size); int archreader_read_dico(carchreader *ai, struct s_dico *d); int archreader_read_volheader(carchreader *ai); int archreader_read_header(carchreader *ai, char *magic, struct s_dico **d, bool allowseek, u16 *fsid); int archreader_read_block(carchreader *ai, struct s_dico *in_blkdico, int in_skipblock, int *out_sumok, struct s_blockinfo *out_blkinfo); #endif // __ARCHREADER_H__ fsarchiver-0.8.7/src/strdico.h0000644000175000017500000000253614405605077013230 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifndef __STRDICO_H__ #define __STRDICO_H__ struct s_strdico; struct s_strdicoitem; typedef struct s_strdico cstrdico; typedef struct s_strdicoitem cstrdicoitem; struct s_strdico { cstrdicoitem *head; char *validkeys; }; struct s_strdicoitem { char *key; char *value; cstrdicoitem *next; }; cstrdico *strdico_alloc(); int strdico_destroy(cstrdico *d); int strdico_set_valid_keys(cstrdico *d, const char *keys); int strdico_parse_string(cstrdico *d, const char *strdefs); int strdico_set_value(cstrdico *d, const char *key, const char *value); int strdico_get_string(cstrdico *d, char *outbuffer, int outbufsize, const char *key); int strdico_get_s64(cstrdico *d, s64 *value, const char *key); int strdico_print(cstrdico *d); #endif // __STRDICO_H__ fsarchiver-0.8.7/src/common.c0000644000175000017500000004403414405605077013043 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_EXECINFO_H #include #endif #include "fsarchiver.h" #include "syncthread.h" #include "strlist.h" #include "common.h" #include "error.h" int stream_readline(FILE *f, char *buf, int buflen) { int i; char c; memset(buf, 0, buflen); for (i=0; (!feof(f)) && ((c=fgetc(f))!='\n') && (!feof(f)) && (i < buflen); i++) buf[i]=c; return i; } void concatenate_paths(char *buffer, int maxbufsize, char *p1, char *p2) { int i; memset(buffer, 0, maxbufsize); for (i=0; (p1[i]) && (p1[i]!='/' || p1[i+1]); i++) *(buffer++)=p1[i]; *(buffer++)='/'; while (*p2=='/') p2++; strlcatf(buffer, maxbufsize, "%s", p2); } char *format_size(u64 size, char *text, int max, char units) { double dSize; u64 llKiloB = 1024LL; u64 llMegaB = 1024LL * llKiloB; u64 llGigaB = 1024LL * llMegaB; u64 llTeraB = 1024LL * llGigaB; if ((units=='b') || ((units=='h') && size < llKiloB)) // In Bytes { snprintf(text, max, "%lld bytes", (long long)size); } else if ((units=='k') || ((units=='h') && size < llMegaB)) // In KiloBytes { dSize = ((double)size) / ((double)llKiloB); snprintf(text, max, "%.2f KB", (float) dSize); } else if ((units=='m') || ((units=='h') && size < llGigaB)) // In MegaBytes { dSize = ((double)size) / ((double)llMegaB); snprintf(text, max, "%.2f MB", (float) dSize); } else if ((units=='g') || ((units=='h') && size < llTeraB)) // In Gigabytes { dSize = ((double)size) / ((double)llGigaB); snprintf(text, max, "%.2f GB", (float) dSize); } else // bigger than 1TB { dSize = ((double)size) / ((double)llTeraB); snprintf(text, max, "%.2f TB", (float) dSize); } return text; } int mkdir_recursive(char *path) { char buffer[PATH_MAX]; struct stat64 statbuf; int len; int pos; len=strlen(path); for (pos=0; pos<=len; pos++) { if (path[pos]=='/' || path[pos]==0) { memset(buffer, 0, sizeof(buffer)); memcpy(buffer, path, pos); if (stat64(buffer, &statbuf)==-1 && errno==ENOENT) mkdir(buffer, 0755); } } return 0; } int extract_dirpath(char *filepath, char *dirbuf, int dirbufsize) { int i; snprintf(dirbuf, dirbufsize, "%s", filepath); for (i=0; (i=0) && (dirbuf[i]!='/')) dirbuf[i--]=0; if ((i>0) && (dirbuf[i]=='/')) dirbuf[i]=0; return 0; } int extract_basename(char *filepath, char *basenamebuf, int basenamebufsize) { int i; for (i=0; filepath[i]; i++); while ((i>0) && (filepath[i]!='/') && (filepath[i-1]!='/')) i--; snprintf(basenamebuf, basenamebufsize, "%s", &filepath[i]); return 0; } char *get_objtype_name(int objtype) { switch (objtype) { case OBJTYPE_DIR: return ("DIR "); case OBJTYPE_SYMLINK: return ("SYMLINK "); case OBJTYPE_REGFILEUNIQUE: return ("REGFILE "); case OBJTYPE_REGFILEMULTI: return ("REGFILEM"); case OBJTYPE_HARDLINK: return ("HARDLINK"); case OBJTYPE_CHARDEV: return ("CHARDEV "); case OBJTYPE_BLOCKDEV: return ("BLOCKDEV"); case OBJTYPE_FIFO: return ("FIFO "); case OBJTYPE_SOCKET: return ("SOCKET "); default: return ("UNKNOWN "); } } int is_dir_empty(char *path) { char fullpath[PATH_MAX]; struct stat64 statbuf; struct dirent *dir; DIR *dirdesc; dirdesc = opendir(path); if (!dirdesc) { sysprintf("cannot open directory %s\n", path); return -1; } while ((dir = readdir(dirdesc)) != NULL) { concatenate_paths(fullpath, sizeof(fullpath), path, dir->d_name); if (lstat64(fullpath, &statbuf)!=0) { sysprintf ("cannot stat %s\n", fullpath); closedir(dirdesc); return -1; } if (strcmp(dir->d_name,".")!=0 && strcmp(dir->d_name,"..")!=0) { closedir(dirdesc); return 1; // an item was found } } closedir(dirdesc); return 0; } // generate a non-null random u32 u32 generate_random_u32_id(void) { struct timeval now; u32 archid; memset(&now, 0, sizeof(struct timeval)); do { gettimeofday(&now, NULL); archid=((u32)now.tv_sec)^((u32)now.tv_usec); } while (archid==0); return archid; } u32 fletcher32(u8 *data, u32 len) { u32 sum1 = 0xffff, sum2 = 0xffff; while (len) { unsigned tlen = len > 360 ? 360 : len; len -= tlen; do { sum1 += *data++; sum2 += sum1; } while (--tlen); sum1 = (sum1 & 0xffff) + (sum1 >> 16); sum2 = (sum2 & 0xffff) + (sum2 >> 16); } // Second reduction step to reduce sums to 16 bits sum1 = (sum1 & 0xffff) + (sum1 >> 16); sum2 = (sum2 & 0xffff) + (sum2 >> 16); return sum2 << 16 | sum1; } int regfile_exists(char *filepath) { struct stat64 st; int res; res=stat64(filepath, &st); if ((res==0) && S_ISREG(st.st_mode)) return true; // file exists if (res==-1 && errno==ENOENT) return false; // does not exist return -1; // don't know } int getpathtoprog(char *buffer, int bufsize, char *prog) { char pathtest[PATH_MAX]; char delims[]=":\t\n"; char pathenv[4096]; char *saveptr=0; char *result; char *vp; int i; memset(buffer, 0, bufsize); if ((vp=getenv("PATH")) == NULL) return -1; snprintf(pathenv, sizeof(pathenv), "%s", vp); result=strtok_r(pathenv, delims, &saveptr); for(i=0; result != NULL; i++) { snprintf(pathtest, sizeof(pathtest), "%s/%s", result, prog); if (access(pathtest, X_OK)==0) { snprintf(buffer, bufsize, "%s", pathtest); return 0; } result = strtok_r(NULL, delims, &saveptr); } return -1; } int exec_command(char *command, int cmdbufsize, int *exitst, char *stdoutbuf, int stdoutsize, char *stderrbuf, int stderrsize, char *format, ...) { char pathtoprog[PATH_MAX]; // full path to the program to run const int max_argv=128; // maximum arguments to a command char *argv[max_argv]; // pointer to arguments processed by wordexp() int outpos=0; // how many bytes have already been stored in the buffer for stdout int errpos=0; // how many bytes have already been stored in the buffer for stderr int pfildes1[2]; int pfildes2[2]; wordexp_t p; int status; int mystdout; int mystderr; va_list ap; int cmdpid; int flags; int pid; int res; char c; int i; // init memset(pathtoprog, 0, sizeof(pathtoprog)); for (i=0; i < max_argv; argv[i++]=NULL); if (exitst) *exitst=-1; // format the string if (stdoutbuf && stdoutsize) memset(stdoutbuf, 0, stdoutsize); if (stderrbuf && stderrsize) memset(stderrbuf, 0, stderrsize); memset(command, 0, cmdbufsize); va_start(ap, format); vsnprintf(command, cmdbufsize, format, ap); va_end(ap); // do shell expansion to parse the quotes for args with spaces wordexp(command, &p, 0); // will require wordfree to free the memory for(i=0; (i < p.we_wordc) && (i command to be executed { close(pfildes1[0]); // close read end of pipe close(pfildes2[0]); // close read end of pipe dup2(pfildes1[1],1); // make 1 same as write-to end of pipe close(pfildes1[1]); // close excess fildes dup2(pfildes2[1],2); // make 1 same as write-to end of pipe close(pfildes2[1]); // close excess fildes setenv("LC_ALL", "C", 1); // kill internationalization execvp(pathtoprog, argv); errprintf("execvp(%s) failed\n", pathtoprog); // still around? exec failed wordfree(&p); exit(EXIT_FAILURE); } else // parent --> fsarchiver { mystdout=pfildes1[0]; mystderr=pfildes2[0]; cmdpid=pid; close(pfildes1[1]); // close write end of pipe close(pfildes2[1]); // close write end of pipe // set non blocking reads to make sure we dont block on read(stderr) when buffer for stdout is full for instance flags = fcntl(mystdout, F_GETFL, 0); fcntl(mystdout, F_SETFL, flags | O_NONBLOCK); flags = fcntl(mystderr, F_GETFL, 0); fcntl(mystderr, F_SETFL, flags | O_NONBLOCK); do { // read data stored in the stdout pipe (read to prevents the sub-process command from blocking on write) do { res=read(mystdout, &c, 1); if ((stdoutbuf!=NULL) && (res>0) && (outpos+1 < stdoutsize)) stdoutbuf[outpos++]=c; } while (res>0); // read data stored in the stderr pipe (read to prevents the sub-process command from blocking on write) do { res=read(mystderr, &c, 1); if ((stderrbuf!=NULL) && (res>0) && (errpos+1 < stderrsize)) stderrbuf[errpos++]=c; } while (res>0); usleep(100000); // don't spin the cpu } while ( ((res=waitpid(cmdpid, &status, WNOHANG))!=cmdpid) && (res!=-1) ); // read the remaining data in the pipes if ((stdoutbuf!=NULL) && (outpos+1 < stdoutsize)) read(mystdout, stdoutbuf+outpos, stdoutsize-outpos-1); if ((stderrbuf!=NULL) && (errpos+1 < stderrsize)) read(mystderr, stderrbuf+errpos, stderrsize-errpos-1); status = WIFSIGNALED(status) ? 128 + WTERMSIG(status) : WEXITSTATUS(status); msgprintf(MSG_VERB1, "command [%s] returned %d\n", command, status); if (exitst) *exitst=status; if ((stdoutbuf!=NULL) && (outpos>0)) msgprintf(MSG_DEBUG1, "\n----stdout----\n%s\n----stdout----\n\n", stdoutbuf); if ((stderrbuf!=NULL) && (errpos>0)) msgprintf(MSG_DEBUG1, "\n----stderr----\n%s\n----stderr----\n\n", stderrbuf); wordfree(&p); return 0; } } int generate_random_tmpdir(char *buffer, int bufsize, int n) { struct tm tbreak; time_t abstime; struct timeval tv; gettimeofday(&tv, NULL); abstime=tv.tv_sec; localtime_r(&abstime, &tbreak); snprintf(buffer, bufsize, "/tmp/fsa/%.4d%.2d%.2d-%.2d%.2d%.2d-%.8x-%.2d", tbreak.tm_year+1900, tbreak.tm_mon+1, tbreak.tm_mday, tbreak.tm_hour, tbreak.tm_min, tbreak.tm_sec, (u32)tv.tv_usec, n); return 0; } // returns true if magic is a valid magic-string int is_magic_valid(char *magic) { int i; for (i=0; valid_magic[i]!=NULL; i++) if (memcmp(magic, valid_magic[i], FSA_SIZEOF_MAGIC)==0) return true; return false; } // just copies the path if it has the right extension or add the extension int path_force_extension(char *buf, int bufsize, char *origpath, char *ext) { int oldlen, extlen; if (!buf || !origpath || !ext) { errprintf("a parameter is null\n"); return -1; } oldlen=strlen(origpath); extlen=strlen(ext); if ((oldlen < extlen) || memcmp(origpath+oldlen-extlen, ext, extlen)!=0) snprintf(buf, bufsize, "%s%s", origpath, ext); else // the extension has been found at the end of origpath snprintf(buf, bufsize, "%s", origpath); return 0; } // convert a binary md5 to an hexadecimal format char *format_md5(char *buf, int maxbuf, u8 *md5bin) { int i; memset(buf, 0, maxbuf); for (i=0; i<16; i++) strlcatf(buf, maxbuf, "%.2x", md5bin[i]); return buf; } char *format_time(char *buffer, int bufsize, u64 t) { struct tm timeres; time_t t2; if (!buffer) return NULL; t2=t; localtime_r(&t2, &timeres); snprintf(buffer, bufsize, "%.4d-%.2d-%.2d_%.2d-%.2d-%.2d", timeres.tm_year+1900, timeres.tm_mon+1, timeres.tm_mday, timeres.tm_hour, timeres.tm_min, timeres.tm_sec); return buffer; } // add a formatted string at the end of a buffer that already contains a string char *strlcatf(char *dest, int destbufsize, char *format, ...) { va_list ap; int len1; // if buffer already full, don't cat the second string if ((len1=strnlen(dest, destbufsize))==destbufsize) return dest; // at the new formatted string at the end of the first one va_start(ap, format); vsnprintf(dest+len1, destbufsize-len1, format, ap); va_end(ap); return dest; } int get_parent_dir_time_attrib(char *filepath, char *parentdirbuf, int bufsize, struct timeval *tv) { struct stat64 statbuf; extract_dirpath(filepath, parentdirbuf, bufsize); if (lstat64(parentdirbuf, &statbuf)!=0) { sysprintf("cannot lstat64(%s)\n", parentdirbuf); return -1; } if (!S_ISDIR(statbuf.st_mode)) { sysprintf("error: [%s] is not a directory\n", parentdirbuf); return -1; } // prepare structure to be passed to utimes tv[0].tv_usec=0; tv[0].tv_sec=statbuf.st_atime; tv[1].tv_usec=0; tv[1].tv_sec=statbuf.st_mtime; return 0; } int stats_show(cstats stats, int fsid) { msgprintf(MSG_FORCE, "Statistics for filesystem %d\n", fsid); msgprintf(MSG_FORCE, "* files successfully processed:....regfiles=%lld, directories=%lld, " "symlinks=%lld, hardlinks=%lld, specials=%lld\n", (long long)stats.cnt_regfile, (long long)stats.cnt_dir, (long long)stats.cnt_symlink, (long long)stats.cnt_hardlink, (long long)stats.cnt_special); msgprintf(MSG_FORCE, "* files with errors:...............regfiles=%lld, directories=%lld, " "symlinks=%lld, hardlinks=%lld, specials=%lld\n", (long long)stats.err_regfile, (long long)stats.err_dir, (long long)stats.err_symlink, (long long)stats.err_hardlink, (long long)stats.err_special); return 0; } u64 stats_errcount(cstats stats) { return stats.err_regfile+stats.err_dir+stats.err_symlink+stats.err_hardlink+stats.err_special; } int format_stacktrace(char *buffer, int bufsize) { #ifdef HAVE_EXECINFO_H const int stack_depth=20; void *temp[stack_depth]; char **strings; int nptrs; int i; // format the backtrace (advanced error info) memset(buffer, 0, bufsize); nptrs=backtrace(temp, stack_depth); strings=backtrace_symbols(temp, nptrs); if (strings!=NULL) { for (i = 0; i < nptrs; i++) strlcatf(buffer, bufsize, "%s\n", strings[i]); free(strings); } #endif return 0; } int exclude_check(cstrlist *patlist, char *string) { char pattern[1024]; int count; int i; count=strlist_count(patlist); for (i=0; i < count; i++) { strlist_getitem(patlist, i, pattern, sizeof(pattern)); if (fnmatch(pattern, string, 0)==0) return true; } return false; } int get_path_to_volume(char *newvolbuf, int bufsize, char *basepath, long curvol) { char prefix[PATH_MAX]; int pathlen; if ((pathlen=strlen(basepath))<4) // all archives terminates with ".fsa" { errprintf("archive has an invalid basepath: [%s]\n", basepath); return -1; } if (curvol==0) // first volume { if (realpath(basepath, newvolbuf)!=newvolbuf) snprintf(newvolbuf, bufsize, "%s", basepath); } else // not the first volume { memset(prefix, 0, sizeof(prefix)); memcpy(prefix, basepath, pathlen-2); snprintf(newvolbuf, bufsize, "%s%.2ld", prefix, (long)curvol); } return 0; } s64 get_device_size(char *partition) { s64 devsize; int fd; if ((fd=open64(partition, O_RDONLY|O_LARGEFILE))<0) return -1; if ((devsize=lseek64(fd, 0, SEEK_END))<0) return -1; close(fd); return devsize; } bool match_uname_r(char *ere) { int r; struct utsname ut; regex_t reg; if (uname(&ut) != 0) return false; // do not bother with invalid regex, since it is not user configurable if (regcomp(®, ere, REG_EXTENDED|REG_NOSUB) != 0) return false; r = !regexec(®, ut.release, 0, NULL, 0); msgprintf(MSG_VERB2, "match_uname_r(%s)=[%s], kernel=[%s]\n", ere, r ? "true" : "false", ut.release); return r; } fsarchiver-0.8.7/src/strlist.c0000644000175000017500000001370514405605077013260 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include "fsarchiver.h" #include "strlist.h" #include "common.h" #include "error.h" int strlist_init(cstrlist *l) { if (l==NULL) return -1; l->head=NULL; return 0; } int strlist_destroy(cstrlist *l) { if (l==NULL) return -1; strlist_empty(l); return 0; } int strlist_empty(cstrlist *l) { cstrlistitem *item, *next; if (l==NULL) return -1; for (item=l->head; item!=NULL; item=next) { next=item->next; free(item->str); free(item); } l->head=NULL; return 0; } int strlist_add(cstrlist *l, char *str) { cstrlistitem *item, *lnew; int len; if (!l || !str || !strlen(str)) { errprintf("invalid param\n"); return -1; } if (strlist_exists(l, str)==true) { errprintf("canot add dring: [%s] is already in the list\n", str); return -1; } if ((lnew=malloc(sizeof(cstrlistitem)))==NULL) { errprintf("malloc() failed\n"); return -1; } memset(lnew, 0, sizeof(cstrlistitem)); lnew->next=NULL; len=strlen(str); if ((lnew->str=malloc(len+1))==NULL) { errprintf("malloc() failed\n"); free(lnew); return -1; } memcpy(lnew->str, str, len+1); // go to the end of the item and check for duplicates if (l->head==NULL) // item is empty { l->head=lnew; } else // item is not empty { for (item=l->head; (item!=NULL) && (item->next!=NULL); item=item->next); item->next=lnew; } return 0; } int strlist_getitem(cstrlist *l, int index, char *buf, int bufsize) { cstrlistitem *item; int pos=0; if (!l || !buf || bufsize<=0) { errprintf("invalid param\n"); return -1; } for (item=l->head; (item!=NULL) && (pos++ < index); item=item->next); if (item!=NULL) { snprintf(buf, bufsize, "%s", item->str); return 0; } else { return -1; } } int strlist_remove(cstrlist *l, char *str) { cstrlistitem *item, *next; if (!l || !str) { errprintf("invalid param\n"); return -1; } if (!l->head) return -1; // not found // if item to remove found in first pos item=l->head; if (strcmp(item->str, str)==0) { free(item->str); l->head=item->next; free(item); return 0; // item removed } // item to remove not in first pos for (item=l->head; (item!=NULL) && (item->next!=NULL); item=item->next) { next=item->next; if (strcmp(next->str, str)==0) { free(next->str); item->next=next->next; free(next); return 0; // item removed } } return -1; // not found } char *strlist_merge(cstrlist *l, char *bufdat, int bufsize, char sep) { cstrlistitem *item; if (!l || !bufdat || bufsize<=0) { errprintf("invalid param\n"); return NULL; } // init memset(bufdat, 0, bufsize); // item to remove not in first pos for (item=l->head; item!=NULL; item=item->next) { if (item!=l->head) // not the first item: write separator strlcatf(bufdat, bufsize, "%c", sep); strlcatf(bufdat, bufsize, "%s", item->str); } return bufdat; } int strlist_exists(cstrlist *l, char *str) { cstrlistitem *item; if (!l || !str) { errprintf("invalid param\n"); return -1; // error } if (!l->head) return false; // not found // item to remove not in first pos for (item=l->head; item!=NULL; item=item->next) if (strcmp(item->str, str)==0) return true; // item found return false; // not found } int strlist_split(cstrlist *l, char *text, char sep) { char *textcopy; char delims[4]; char *saveptr; char *result; int len; if (!l || !text) { errprintf("invalid param\n"); return -1; } // init len=strlen(text); snprintf(delims, sizeof(delims), "%c", sep); strlist_empty(l); if ((textcopy=malloc(len+1))==NULL) { errprintf("malloc(%d) failed\n", len+1); return -1; } memcpy(textcopy, text, len+1); for (result=strtok_r(textcopy, delims, &saveptr); result!=NULL; result=strtok_r(NULL, delims, &saveptr)) { if (strlist_add(l, result)!=0) { errprintf("strlist_add(l, [%s]) failed\n", result); free(textcopy); return -1; } } free(textcopy); return 0; } int strlist_count(cstrlist *l) { cstrlistitem *item; int count=0; if (!l) { errprintf("invalid param\n"); return -1; // error } if (!l->head) { return 0; } else { for (item=l->head; (item!=NULL); item=item->next) count++; } return count; } int strlist_show(cstrlist *l) { cstrlistitem *item; int count=0; if (!l) { errprintf("invalid param\n"); return -1; // error } if (!l->head) { printf("list is empty"); } else { for (item=l->head; (item!=NULL); item=item->next) printf("item[%d]: [%s]\n", count++, item->str); } return 0; } fsarchiver-0.8.7/src/fs_vfat.h0000644000175000017500000000322014405605077013200 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifndef __FS_VFAT_H__ #define __FS_VFAT_H__ struct s_dico; struct s_strlist; int vfat_mkfs(struct s_dico *d, char *partition, char *fsoptions, char *mkfslabel, char *mkfsuuid); int vfat_getinfo(struct s_dico *d, char *devname); int vfat_mount(char *partition, char *mntbuf, char *fsbuf, int flags, char *mntinfo); int vfat_get_reqmntopt(char *partition, struct s_strlist *reqopt, struct s_strlist *badopt); int vfat_umount(char *partition, char *mntbuf); int vfat_test(char *devname); int vfat_check_compatibility(u64 compat, u64 ro_compat, u64 incompat, u64 log_incompat); #define VFAT_SB_MAGIC 0x55AA enum fat_type {FAT_TYPE_FAT32=0, FAT_TYPE_FAT16}; struct vfat_superblock { u8 jump[3]; u8 oem_id[8]; u16 u8s_per_sector; u8 sectors_per_cluster; u16 num_boot_sectors; u8 num_fats; u16 num_root_dir_ents; u16 total_sectors; u8 media_id; u16 sectors_per_fat; u16 sectors_per_track; u16 heads; u32 hidden_sectors; u32 total_sectors_large; u8 boot_code[474]; u16 magic; } __attribute__((packed)); #endif // __FS_VFAT_H__ fsarchiver-0.8.7/src/fs_vfat.c0000644000175000017500000001334514405605077013204 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include #include #include "fsarchiver.h" #include "dico.h" #include "common.h" #include "filesys.h" #include "strlist.h" #include "fs_vfat.h" #include "error.h" int vfat_mkfs(cdico *d, char *partition, char *fsoptions, char *mkfslabel, char *mkfsuuid) { char stdoutbuf[2048]; char command[2048]; char buffer[2048]; char mkfsopts[2048]; int exitst; u32 temp32; u16 temp16; memset(mkfsopts, 0, sizeof(mkfsopts)); // ---- check that mkfs.vfat is installed if (exec_command(command, sizeof(command), NULL, stdoutbuf, sizeof(stdoutbuf), NULL, 0, "mkfs.vfat --help")!=0) { errprintf("mkfs.vfat not found. please install dosfstools on your system or check the PATH.\n"); return -1; } // ---- set the correct type of FAT filesystem if ((dico_get_u16(d, 0, FSYSHEADKEY_FSVFATTYPE, &temp16)==0) && (temp16==FAT_TYPE_FAT16)) strlcatf(mkfsopts, sizeof(mkfsopts), " -F 16 "); else strlcatf(mkfsopts, sizeof(mkfsopts), " -F 32 "); // ---- filesystem label if (strlen(mkfslabel) > 0) strlcatf(mkfsopts, sizeof(mkfsopts), " -n '%.11s' ", mkfslabel); else if (dico_get_string(d, 0, FSYSHEADKEY_FSLABEL, buffer, sizeof(buffer))==0 && strlen(buffer)>0) strlcatf(mkfsopts, sizeof(mkfsopts), " -n '%.11s' ", buffer); // ---- filesystem serial if (strlen(mkfsuuid) > 0) strlcatf(mkfsopts, sizeof(mkfsopts), " -i '%.8s' ", mkfsuuid); else if (dico_get_u32(d, 0, FSYSHEADKEY_FSVFATSERIAL, &temp32)==0) strlcatf(mkfsopts, sizeof(mkfsopts), " -i '%08X' ", temp32); // ---- mkfsopt from command line strlcatf(mkfsopts, sizeof(mkfsopts), " %s ", fsoptions); // ---- create the new filesystem using mkfs.vfat if (exec_command(command, sizeof(command), &exitst, NULL, 0, NULL, 0, "mkfs.vfat %s %s", mkfsopts, partition)!=0 || exitst!=0) { errprintf("command [%s] failed\n", command); return -1; } return 0; } int vfat_getinfo(cdico *d, char *devname) { struct vfat_superblock sb; char label[512]; u32 serial; u32 temp32; u16 type; int ret=0; int fd; int res; memset(label, 0, sizeof(label)); memset(&sb, 0, sizeof(sb)); if ((fd=open64(devname, O_RDONLY|O_LARGEFILE))<0) { ret=-1; goto vfat_read_sb_return; } res=read(fd, &sb, sizeof(sb)); if (res!=sizeof(sb)) { ret=-1; goto vfat_read_sb_close; } // make sure we can find the magic number if (be16_to_cpu(sb.magic)!=VFAT_SB_MAGIC) { msgprintf(MSG_DEBUG1, "(be16_to_cpu(sb.magic)=%.2x) != (VFAT_SB_MAGIC=%.2x)\n", be16_to_cpu(sb.magic), VFAT_SB_MAGIC); ret=-1; goto vfat_read_sb_close; } // number of FATs must be 1 or 2 if (sb.num_fats != 1 && sb.num_fats != 2) { msgprintf(MSG_DEBUG1, "Invalid number of FAT tables: %d\n", (int)sb.num_fats); ret=-1; goto vfat_read_sb_close; } // num_root_dir_ents set to zero indicates a FAT32 if (sb.num_root_dir_ents == 0) { type=FAT_TYPE_FAT32; msgprintf(MSG_DEBUG1, "FAT_TYPE_FAT32\n"); memcpy(label, ((char*)&sb)+0x047, 11); memcpy(&temp32, ((char*)&sb)+0x043, 4); serial=le32_to_cpu(temp32); } else { type=FAT_TYPE_FAT16; msgprintf(MSG_DEBUG1, "FAT_TYPE_FAT16\n"); memcpy(label, ((char*)&sb)+0x02B, 11); memcpy(&temp32, ((char*)&sb)+0x027, 4); serial=le32_to_cpu(temp32); } // ---- type dico_add_u16(d, 0, FSYSHEADKEY_FSVFATTYPE, type); // ---- label msgprintf(MSG_DEBUG1, "vfat_label=[%s]\n", label); dico_add_string(d, 0, FSYSHEADKEY_FSLABEL, label); // ---- serial dico_add_u32(d, 0, FSYSHEADKEY_FSVFATSERIAL, serial); msgprintf(MSG_DEBUG1, "vfat_serial=[%08X]\n", serial); // ---- minimum fsarchiver version required to restore dico_add_u64(d, 0, FSYSHEADKEY_MINFSAVERSION, FSA_VERSION_BUILD(0, 8, 0, 0)); vfat_read_sb_close: close(fd); vfat_read_sb_return: return ret; } int vfat_mount(char *partition, char *mntbuf, char *fsbuf, int flags, char *mntinfo) { return generic_mount(partition, mntbuf, fsbuf, "", flags); } int vfat_umount(char *partition, char *mntbuf) { return generic_umount(mntbuf); } int vfat_test(char *devname) { struct vfat_superblock sb; int fd; if ((fd=open64(devname, O_RDONLY|O_LARGEFILE))<0) { msgprintf(MSG_DEBUG1, "open64(%s) failed\n", devname); return false; } memset(&sb, 0, sizeof(sb)); if (read(fd, &sb, sizeof(sb))!=sizeof(sb)) { close(fd); msgprintf(MSG_DEBUG1, "read failed\n"); return false; } // ---- check it is a VFAT file system if (be16_to_cpu(sb.magic)!=VFAT_SB_MAGIC) { close(fd); msgprintf(MSG_DEBUG1, "(be16_to_cpu(sb.magic)=%.2x) != (VFAT_SB_MAGIC=%.2x)\n", be16_to_cpu(sb.magic), VFAT_SB_MAGIC); return false; } close(fd); return true; } int vfat_get_reqmntopt(char *partition, cstrlist *reqopt, cstrlist *badopt) { if (!reqopt || !badopt) return -1; return 0; } fsarchiver-0.8.7/src/types.h0000644000175000017500000000440214405605077012717 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifndef __TYPES_H__ #define __TYPES_H__ #include #include #include #include #include typedef uint8_t u8; typedef int8_t s8; typedef uint16_t u16; typedef int16_t s16; typedef uint32_t u32; typedef int32_t s32; typedef uint64_t u64; typedef int64_t s64; #define le8_to_cpu(v) (v) #define cpu_to_le8(v) (v) #if __BYTE_ORDER == __BIG_ENDIAN // CPU == big endian (sparc, ppc, ...) # define cpu_to_le16(x) ((u16)(bswap_16(x))) # define le16_to_cpu(x) ((u16)(bswap_16(x))) # define cpu_to_le32(x) ((u32)(bswap_32(x))) # define le32_to_cpu(x) ((u32)(bswap_32(x))) # define cpu_to_le64(x) ((u64)(bswap_64(x))) # define le64_to_cpu(x) ((u64)(bswap_64(x))) # define be16_to_cpu(x) ((u16)(x)) # define cpu_to_be16(x) ((u16)(x)) # define be32_to_cpu(x) ((u32)(x)) # define cpu_to_be32(x) ((u32)(x)) # define be64_to_cpu(x) ((u64)(x)) # define cpu_to_be64(x) ((u64)(x)) #else // CPU == little endian (intel) # define cpu_to_le16(x) ((u16)(x)) # define le16_to_cpu(x) ((u16)(x)) # define cpu_to_le32(x) ((u32)(x)) # define le32_to_cpu(x) ((u32)(x)) # define cpu_to_le64(x) ((u64)(x)) # define le64_to_cpu(x) ((u64)(x)) # define be16_to_cpu(x) ((bswap_16(x))) # define cpu_to_be16(x) ((bswap_16(x))) # define be32_to_cpu(x) ((bswap_32(x))) # define cpu_to_be32(x) ((bswap_32(x))) # define be64_to_cpu(x) ((bswap_64(x))) # define cpu_to_be64(x) ((bswap_64(x))) #endif // atomic type. typedef struct { volatile int counter; } atomic_t; // read atomic variable #define atomic_read(v) ((v)->counter) // Set atomic variable #define atomic_set(v,i) (((v)->counter) = (i)) #endif // __TYPES_H__ fsarchiver-0.8.7/src/options.c0000644000175000017500000000664214405605077013251 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include "fsarchiver.h" #include "options.h" #include "error.h" coptions g_options; int options_init() { memset(&g_options, 0, sizeof(coptions)); if (strlist_init(&g_options.exclude)!=0) return -1; return 0; } int options_destroy() { if (strlist_destroy(&g_options.exclude)!=0) return -1; memset(&g_options, 0, sizeof(coptions)); return 0; } int options_select_compress_level(int opt) { switch (opt) { #ifdef OPTION_LZ4_SUPPORT case 0: // lz4 g_options.compressalgo=COMPRESS_LZ4; break; #else case 0: // lz4 errprintf("compression level %d is not available: lz4 has been disabled at compilation time\n", opt); return -1; #endif // OPTION_LZ4_SUPPORT #ifdef OPTION_LZO_SUPPORT case 1: // lzo g_options.compressalgo=COMPRESS_LZO; g_options.compresslevel=3; break; #else case 1: // lzo errprintf("compression level %d is not available: lzo has been disabled at compilation time\n", opt); return -1; #endif // OPTION_LZO_SUPPORT case 2: // gzip fast g_options.compressalgo=COMPRESS_GZIP; g_options.compresslevel=3; break; case 3: // gzip standard g_options.compressalgo=COMPRESS_GZIP; g_options.compresslevel=6; break; case 4: // gzip best g_options.compressalgo=COMPRESS_GZIP; g_options.compresslevel=9; break; case 5: // bzip2 fast g_options.compressalgo=COMPRESS_BZIP2; g_options.datablocksize=262144; g_options.compresslevel=2; break; case 6: // bzip2 good g_options.compressalgo=COMPRESS_BZIP2; g_options.datablocksize=524288; g_options.compresslevel=5; break; #ifdef OPTION_LZMA_SUPPORT case 7: // lzma fast g_options.compressalgo=COMPRESS_LZMA; g_options.datablocksize=262144; g_options.compresslevel=1; break; case 8: // lzma medium g_options.compressalgo=COMPRESS_LZMA; g_options.datablocksize=524288; g_options.compresslevel=6; break; case 9: // lzma best g_options.compressalgo=COMPRESS_LZMA; g_options.datablocksize=FSA_MAX_BLKSIZE; g_options.compresslevel=9; break; #else case 7: // lzma case 8: // lzma case 9: // lzma errprintf("compression level %d is not available: lzma has been disabled at compilation time\n", opt); return -1; #endif default: errprintf("invalid compression level: %d\n", opt); return -1; } return 0; } fsarchiver-0.8.7/src/crypto.h0000644000175000017500000000153514405605077013077 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifndef __CRYPTO_H__ #define __CRYPTO_H__ #include "types.h" int crypto_init(); int crypto_blowfish(u64 insize, u64 *outsize, u8 *inbuf, u8 *outbuf, u8 *password, int passlen, int enc); int crypto_random(u8 *buf, int bufsize); int crypto_cleanup(); #endif // __CRYPTO_H__ fsarchiver-0.8.7/src/writebuf.c0000644000175000017500000001753014405605077013403 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include "fsarchiver.h" #include "writebuf.h" #include "common.h" #include "error.h" #include "queue.h" #include "dico.h" cwritebuf *writebuf_alloc() { cwritebuf *wb; if ((wb=malloc(sizeof(cwritebuf)))==NULL) { errprintf("malloc(%d) failed: cannot allocate memory for writebuf\n", (int)sizeof(cwritebuf)); return NULL; } wb->size=0; wb->data=NULL; return wb; } int writebuf_destroy(cwritebuf *wb) { if (wb==NULL) { errprintf("wb is NULL\n"); return -1; } if (wb->data) { free(wb->data); wb->data=NULL; } wb->size=0; free(wb); return 0; } int writebuf_add_data(cwritebuf *wb, void *data, u64 size) { u64 newsize; if (wb==NULL) { errprintf("wb is NULL\n"); return -1; } if (size==0) { errprintf("size=0\n"); return -1; } newsize=wb->size+size; wb->data=realloc(wb->data, newsize+4); // "+4" required else the last byte of the buffer may be alterred (see release-0.3.3) if (!wb->data) { errprintf("realloc(oldsize=%ld, newsize=%ld) failed\n", (long)wb->size, (long)newsize+4); return -1; } memcpy(wb->data+wb->size, data, size); wb->size+=size; return 0; } int writebuf_add_dico(cwritebuf *wb, cdico *d, char *magic) { struct s_dicoitem *item; int itemnum; u32 headerlen; u32 checksum; u8 *buffer; u8 *bufpos; u16 temp16; u32 temp32; u16 count; if (!wb || !d) { errprintf("a parameter is null\n"); return -1; } // 0. debugging msgprintf(MSG_DEBUG2, "archio_write_dico(wb=%p, dico=%p, magic=[%c%c%c%c])\n", wb, d, magic[0], magic[1], magic[2], magic[3]); for (item=d->head; item!=NULL; item=item->next) if ((item->section==DICO_OBJ_SECTION_STDATTR) && (item->key==DISKITEMKEY_PATH) && (memcmp(magic, "ObJt", 4)==0)) msgprintf(MSG_DEBUG2, "filepath=[%s]\n", item->data); // 1. how many valid items there are count=dico_count_all_sections(d); msgprintf(MSG_DEBUG2, "dico_count_all_sections(dico=%p)=%d\n", d, (int)count); // 2. calculate len of header headerlen=sizeof(u16); // count for (item=d->head; item!=NULL; item=item->next) { headerlen+=sizeof(u8); // type headerlen+=sizeof(u8); // section headerlen+=sizeof(u16); // key headerlen+=sizeof(u16); // data size headerlen+=item->size; // data } msgprintf(MSG_DEBUG2, "calculated headerlen for that dico: headerlen=%d\n", (int)headerlen); // 3. allocate memory for header bufpos=buffer=malloc(headerlen); if (!buffer) { errprintf("cannot allocate memory for buffer"); return -1; } // 4. write items count in buffer temp16=cpu_to_le16(count); msgprintf(MSG_DEBUG2, "mempcpy items count to buffer: u16 count=%d\n", (int)count); bufpos=mempcpy(bufpos, &temp16, sizeof(temp16)); // 5. write all items in buffer for (item=d->head, itemnum=0; item!=NULL; item=item->next, itemnum++) { msgprintf(MSG_DEBUG2, "itemnum=%d (type=%d, section=%d, key=%d, size=%d)\n", (int)itemnum++, (int)item->type, (int)item->section, (int)item->key, (int)item->size); // a. write data type buffer bufpos=mempcpy(bufpos, &item->type, sizeof(item->type)); // b. write section to buffer bufpos=mempcpy(bufpos, &item->section, sizeof(item->section)); // c. write key to buffer temp16=cpu_to_le16(item->key); bufpos=mempcpy(bufpos, &temp16, sizeof(temp16)); // d. write sizeof(data) to buffer temp16=cpu_to_le16(item->size); bufpos=mempcpy(bufpos, &temp16, sizeof(temp16)); // e. write data to buffer if (item->size>0) bufpos=mempcpy(bufpos, item->data, item->size); } msgprintf(MSG_DEBUG2, "all %d items mempcopied to buffer\n", (int)itemnum); // 6. write header-len, header-data, header-checksum temp32=cpu_to_le32(headerlen); if (writebuf_add_data(wb, &temp32, sizeof(temp32))!=0) { free(buffer); return -1; } if (writebuf_add_data(wb, buffer, headerlen)!=0) { free(buffer); return -1; } checksum=fletcher32(buffer, headerlen); temp32=cpu_to_le32(checksum); if (writebuf_add_data(wb, &temp32, sizeof(temp32))!=0) { free(buffer); return -1; } free(buffer); msgprintf(MSG_DEBUG2, "end of archio_write_dico(wb=%p, dico=%p, magic=[%c%c%c%c])\n", wb, d, magic[0], magic[1], magic[2], magic[3]); return 0; } int writebuf_add_header(cwritebuf *wb, cdico *d, char *magic, u32 archid, u16 fsid) { u16 temp16; u32 temp32; if (!wb || !d || !magic) { errprintf("a parameter is null\n"); return -1; } // A. write dico magic string if (writebuf_add_data(wb, magic, FSA_SIZEOF_MAGIC)!=0) { errprintf("writebuf_add_data() failed to write FSA_SIZEOF_MAGIC\n"); return -2; } // B. write archive id temp32=cpu_to_le32(archid); if (writebuf_add_data(wb, &temp32, sizeof(temp32))!=0) { errprintf("writebuf_add_data() failed to write archid\n"); return -3; } // C. write filesystem id temp16=cpu_to_le16(fsid); if (writebuf_add_data(wb, &temp16, sizeof(temp16))!=0) { errprintf("writebuf_add_data() failed to write fsid\n"); return -3; } // D. write the dico of the header if (writebuf_add_dico(wb, d, magic) != 0) { errprintf("archio_write_dico() failed to write the header dico\n"); return -4; } return 0; } int writebuf_add_block(cwritebuf *wb, struct s_blockinfo *blkinfo, u32 archid, u16 fsid) { cdico *blkdico; // header written in file int res; if (!wb || !blkinfo) { errprintf("a parameter is null\n"); return -1; } if ((blkdico=dico_alloc())==NULL) { errprintf("dico_alloc() failed\n"); return -1; } if (blkinfo->blkarsize==0) { errprintf("blkinfo->blkarsize=0: block is empty\n"); return -1; } // prepare header dico_add_u64(blkdico, 0, BLOCKHEADITEMKEY_BLOCKOFFSET, blkinfo->blkoffset); dico_add_u32(blkdico, 0, BLOCKHEADITEMKEY_REALSIZE, blkinfo->blkrealsize); dico_add_u32(blkdico, 0, BLOCKHEADITEMKEY_ARSIZE, blkinfo->blkarsize); dico_add_u32(blkdico, 0, BLOCKHEADITEMKEY_COMPSIZE, blkinfo->blkcompsize); dico_add_u32(blkdico, 0, BLOCKHEADITEMKEY_ARCSUM, blkinfo->blkarcsum); dico_add_u16(blkdico, 0, BLOCKHEADITEMKEY_COMPRESSALGO, blkinfo->blkcompalgo); dico_add_u16(blkdico, 0, BLOCKHEADITEMKEY_ENCRYPTALGO, blkinfo->blkcryptalgo); // write block header res=writebuf_add_header(wb, blkdico, FSA_MAGIC_BLKH, archid, fsid); dico_destroy(blkdico); if (res!=0) { msgprintf(MSG_STACK, "cannot write FSA_MAGIC_BLKH block-header\n"); return -1; } // write block data if (writebuf_add_data(wb, blkinfo->blkdata, blkinfo->blkarsize)!=0) { msgprintf(MSG_STACK, "cannot write data block: writebuf_add_data() failed\n"); return -1; } return 0; } fsarchiver-0.8.7/src/common.h0000644000175000017500000000446514405605077013054 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifndef __COMMON_H__ #define __COMMON_H__ #include struct timeval; struct s_strlist; struct s_stats; int exec_command(char *command, int cmdbufsize, int *exitst, char *stdoutbuf, int stdoutsize, char *stderrbuf, int stderrsize, char *format, ...); int get_parent_dir_time_attrib(char *filepath, char *parentdirbuf, int bufsize, struct timeval *tv); void concatenate_paths(char *buffer, int maxbufsize, char *p1, char *p2); int path_force_extension(char *buf, int bufsize, char *origpath, char *ext); char *format_size(u64 size, char *text, int max, char units); int image_write_data(int fdarch, char *buffer, int buflen); int extract_dirpath(char *filepath, char *dirbuf, int dirbufsize); int extract_basename(char *filepath, char *basenamebuf, int basenamebufsize); int generate_random_tmpdir(char *buffer, int bufsize, int n); char *format_time(char *buffer, int bufsize, u64 t); int stream_readline(FILE *f, char *buf, int buflen); char *format_md5(char *buf, int maxbuf, u8 *md5bin); int getpathtoprog(char *buffer, int bufsize, char *prog); int mkdir_recursive(char *path); char *get_objtype_name(int objtype); int is_dir_empty(char *path); u32 generate_random_u32_id(void); u32 fletcher32(u8 *data, u32 len); int regfile_exists(char *filepath); int is_magic_valid(char *magic); char *strlcatf(char *dest, int destbufsize, char *format, ...) __attribute__ ((format (printf, 3, 4))); int format_stacktrace(char *buffer, int bufsize); int stats_show(struct s_stats, int fsid); u64 stats_errcount(struct s_stats stats); int exclude_check(struct s_strlist *patlist, char *string); int get_path_to_volume(char *newvolbuf, int bufsize, char *basepath, long curvol); s64 get_device_size(char *partition); bool match_uname_r(char *ere); #endif // __COMMON_H__ fsarchiver-0.8.7/src/regmulti.h0000644000175000017500000000370014405605077013403 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifndef __REGMULTI_H__ #define __REGMULTI_H__ struct s_dico; struct s_queue; struct s_regmulti; typedef struct s_regmulti cregmulti; struct s_regmulti { // common u32 count; // how many small files are in this struct u32 maxitems; // how many small files that struct can contains u32 maxblksize; // maximum size of a data block // linked list of headers struct s_dico *objhead[FSA_MAX_SMALLFILECOUNT]; // worst case: each file is just one byte: this is how many files we can store in the block // common block to be compressed char data[FSA_MAX_BLKSIZE]; u32 usedsize; // how many bytes are used in data }; int regmulti_empty(cregmulti *m); int regmulti_init(cregmulti *m, u32 maxblksize); int regmulti_count(cregmulti *m, struct s_dico *header, char *data, u32 datsize); bool regmulti_save_enough_space_for_new_file(cregmulti *m, u32 filesize); int regmulti_save_addfile(cregmulti *m, struct s_dico *header, char *data, u32 datsize); int regmulti_save_enqueue(cregmulti *m, struct s_queue *q, int fsid); int regmulti_rest_addheader(cregmulti *m, struct s_dico *header); int regmulti_rest_setdatablock(cregmulti *m, char *data, u32 datsize); int regmulti_rest_getfile(cregmulti *m, int index, struct s_dico **filehead, char *data, u64 *datsize, u32 bufsize); #endif // __REGMULTI_H__ fsarchiver-0.8.7/src/error.h0000644000175000017500000000456214405605077012713 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifndef __ERROR_H__ #define __ERROR_H__ struct s_stats; typedef struct s_stats cstats; struct s_stats { u64 cnt_regfile; u64 cnt_dir; u64 cnt_symlink; u64 cnt_hardlink; u64 cnt_special; u64 err_regfile; u64 err_dir; u64 err_symlink; u64 err_hardlink; u64 err_special; }; int fsaprintf(int level, bool showerrno, bool showloc, const char *file, const char *fct, int line, char *format, ...) __attribute__ ((format (printf, 7, 8))); // ---- message levels enum {MSG_FORCE=0, // always show this messages whatever the level is MSG_VERB1=1, // normal messages that have to be shown when verbose>=1 (fsarchive -v) MSG_VERB2=2, // detailed messages that have to be shown when verbose>=2 (fsarchive -vv) MSG_STACK=3, // messages shown when a function exists (propagate error at upper level) MSG_DEBUG1=4, // debugging messages level 1 (very basic info) MSG_DEBUG2=5, // debugging messages level 2 MSG_DEBUG3=6, // debugging messages level 3 MSG_DEBUG4=7, // debugging messages level 4 MSG_DEBUG5=8 // debugging messages level 5 (very detailed debug) }; char *error_int_to_string(s64 err); // use sysprintf to print an error that follows a libc function and to show errno #define sysprintf(fmt, args...) fsaprintf(0, true, true, __FILE__, __FUNCTION__, __LINE__, fmt, ## args) // use errprintf to print an error that does not come from a libc function #define errprintf(fmt, args...) fsaprintf(0, false, true, __FILE__, __FUNCTION__, __LINE__, fmt, ## args) // use msgprintf with a level to show normal messages or debug messages #define msgprintf(level, fmt, args...) fsaprintf(level, false, level>=3, __FILE__, __FUNCTION__, __LINE__, fmt, ## args) #endif // __ERROR_H__ fsarchiver-0.8.7/src/oper_restore.c0000644000175000017500000017254514405605077014274 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include "fsarchiver.h" #include "strdico.h" #include "dico.h" #include "common.h" #include "options.h" #include "oper_restore.h" #include "archreader.h" #include "archinfo.h" #include "filesys.h" #include "fs_ext2.h" #include "fs_reiserfs.h" #include "fs_reiser4.h" #include "fs_btrfs.h" #include "fs_xfs.h" #include "fs_jfs.h" #include "fs_ntfs.h" #include "thread_comp.h" #include "thread_archio.h" #include "syncthread.h" #include "regmulti.h" #include "crypto.h" #include "error.h" #include "datafile.h" #include "queue.h" typedef struct s_extractar { carchreader ai; int fsid; cstats stats; u64 cost_global; u64 cost_current; } cextractar; // returns true if this file of a parent directory has been excluded int is_filedir_excluded(char *relpath) { char dirpath[PATH_MAX]; char basename[PATH_MAX]; int pos; // check if that particular file has been excluded extract_basename(relpath, basename, sizeof(basename)); if ((exclude_check(&g_options.exclude, basename)==true) // is filename excluded ? || (exclude_check(&g_options.exclude, relpath)==true)) // is filepath excluded ? { msgprintf(MSG_VERB2, "file/dir=[%s] excluded because of its own name/path\n", relpath); return true; } // check if that file belongs to a directory which has been excluded snprintf(dirpath, sizeof(dirpath), "%s", relpath); for (pos=0; dirpath[pos]; pos++); // go to the end of the string while (pos>0) { // dirpath=parent_directory(dirpath) while ((pos>=0) && (dirpath[pos]!='/')) dirpath[pos--]=0; if ((pos>0) && (dirpath[pos]=='/')) dirpath[pos]=0; extract_basename(dirpath, basename, sizeof(basename)); if (strlen(dirpath)>1 && strlen(basename)>0) { if ((exclude_check(&g_options.exclude, basename)==true) || (exclude_check(&g_options.exclude, dirpath)==true)) { msgprintf(MSG_VERB2, "file/dir=[%s] excluded because of its parent=[%s]\n", relpath, dirpath); return true; // a parent directory is excluded } } } return false; // no exclusion found for that file } // convert an array of strings "id=x,dest=/dev/xxx,..." to an array of strdico int convert_argv_to_strdicos(cstrdico *dicoargv[], int argc, char *cmdargv[]) { cstrdico *tmpdico=NULL; char buffer[1024]; struct stat64 st; s64 temp64; int fsid; int i; for (i=0; (iFSA_MAX_FSPERARCH-1)) { errprintf("invalid filesystem id [%d]: it must match a valid filesystem id as shown by archinfo\n", fsid); strdico_destroy(tmpdico); return -1; } // read and check "dest=" key in the argument if (strdico_get_string(tmpdico, buffer, sizeof(buffer), "dest")!=0) { errprintf("cannot find \"dest=\" key in \"%s\"\n", cmdargv[i]); strdico_destroy(tmpdico); return -1; } if ((stat64(buffer, &st)!=0) || (!S_ISBLK(st.st_mode))) { errprintf("\"%s\" is not a valid block device\n", buffer); strdico_destroy(tmpdico); return -1; } // add the current argument to the list of the strdico objects if (dicoargv[fsid]!=NULL) { errprintf("you mentioned filesystem with id=%d multiple times, cannot continue\n", fsid); strdico_destroy(tmpdico); return -1; } dicoargv[fsid]=tmpdico; } return 0; } int extractar_listing_print_file(cextractar *exar, int objtype, char *relpath) { char strprogress[256]; s64 progress; memset(strprogress, 0, sizeof(strprogress)); if (exar->cost_global>0) { progress=(((exar->cost_current)*100)/(exar->cost_global)); if (progress>=0 && progress<=100) snprintf(strprogress, sizeof(strprogress), "[%3d%%]", (int)progress); } msgprintf(MSG_VERB1, "-[%.2d]%s[%s] %s\n", exar->fsid, strprogress, get_objtype_name(objtype), relpath); return 0; } int extractar_restore_attr_xattr(cextractar *exar, u32 objtype, char *fullpath, char *relpath, cdico *dicoattr) { char xattrname[2048]; char xattrvalue[65535]; u16 xattrdatasize; int xattrdicsize; int ret=0; int res; int i; // ---- restore extended attributes xattrdicsize=dico_count_one_section(dicoattr, DICO_OBJ_SECTION_XATTR); for (i=0; i < xattrdicsize; i+=2) { if (dico_get_string(dicoattr, DICO_OBJ_SECTION_XATTR, (u64)(i+0), xattrname, sizeof(xattrname))!=0) { errprintf("Cannot retrieve the name of an xattr for file %s: DICO_OBJ_SECTION_XATTR, key=%ld\n", relpath, (long)(i+0)); dico_show(dicoattr, DICO_OBJ_SECTION_XATTR, "xattr"); ret=-1; continue; } memset(xattrvalue, 0, sizeof(xattrvalue)); if (dico_get_data(dicoattr, DICO_OBJ_SECTION_XATTR, (u64)(i+1), xattrvalue, sizeof(xattrvalue), &xattrdatasize)!=0) { errprintf("Cannot retrieve the value of an xattr for file %s: DICO_OBJ_SECTION_XATTR, key=%ld\n", relpath, (long)(i+1)); dico_show(dicoattr, DICO_OBJ_SECTION_XATTR, "xattr"); ret=-1; continue; } if ((res=lsetxattr(fullpath, xattrname, xattrvalue, xattrdatasize, 0))!=0) { sysprintf("xattr:lsetxattr(%s,%s) failed\n", relpath, xattrname); ret=-1; } else // success { msgprintf(MSG_VERB2, " xattr:lsetxattr(%s, %s)=%d\n", relpath, xattrname, res); } } return ret; } int extractar_restore_attr_windows(cextractar *exar, u32 objtype, char *fullpath, char *relpath, cdico *dicoattr) { char xattrname[2048]; char xattrvalue[65535]; u16 xattrdatasize; int xattrdicsize; int ret=0; int res; int i; xattrdicsize=dico_count_one_section(dicoattr, DICO_OBJ_SECTION_WINATTR); for (i=0; i < xattrdicsize; i+=2) { if (dico_get_string(dicoattr, DICO_OBJ_SECTION_WINATTR, (u64)(i+0), xattrname, sizeof(xattrname))!=0) { errprintf("Cannot retrieve the name of an winattr for file %s\n", relpath); dico_show(dicoattr, DICO_OBJ_SECTION_WINATTR, "winattr"); ret=-1; continue; } memset(xattrvalue, 0, sizeof(xattrvalue)); if (dico_get_data(dicoattr, DICO_OBJ_SECTION_WINATTR, (u64)(i+1), xattrvalue, sizeof(xattrvalue), &xattrdatasize)!=0) { errprintf("Cannot retrieve the value of an winattr for file %s\n", relpath); ret=-1; continue; } if ((res=lsetxattr(fullpath, xattrname, xattrvalue, xattrdatasize, 0))!=0) { sysprintf("winattr:lsetxattr(%s,%s) failed\n", relpath, xattrname); ret=-1; } else // success { msgprintf(MSG_VERB2, " winattr:lsetxattr(%s, %s)=%d\n", relpath, xattrname, res); } } return ret; } int extractar_restore_attr_std(cextractar *exar, u32 objtype, char *fullpath, char *relpath, cdico *dicoattr) { u32 mode, uid, gid; u64 atime, mtime; // ---- restore standard attributes (permissions, owner, ...) if (dico_get_u32(dicoattr, DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_MODE, &mode)!=0) return -1; if (dico_get_u32(dicoattr, DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_UID, &uid)!=0) return -2; if (dico_get_u32(dicoattr, DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_GID, &gid)!=0) return -3; if (dico_get_u64(dicoattr, DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_ATIME, &atime)!=0) return -4; if (dico_get_u64(dicoattr, DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_MTIME, &mtime)!=0) return -5; if (lchown(fullpath, (uid_t)uid, (gid_t)gid)!=0) { sysprintf("Cannot lchown(%s) which is %s\n", fullpath, get_objtype_name(objtype)); return -6; } if (objtype!=OBJTYPE_SYMLINK) { if (chmod(fullpath, (mode_t)mode)!=0) { sysprintf("chmod(%s, %lld) failed\n", fullpath, (long long)mode); return -7; } } // set the values for atime/mtime struct timeval tv[2]; tv[0].tv_usec=0; tv[0].tv_sec=atime; tv[1].tv_usec=0; tv[1].tv_sec=mtime; if (objtype!=OBJTYPE_SYMLINK) // not a symlink { if (utimes(fullpath, tv)!=0) { sysprintf("utimes(%s) failed\n", relpath); return -8; } } #ifdef HAVE_LUTIMES else // object is a symlink { // lutimes not implemented on rhel5: don't fail for symlinks lutimes(fullpath, tv); } #endif // HAVE_LUTIMES return 0; } int extractar_restore_attr_everything(cextractar *exar, int objtype, char *fullpath, char *relpath, cdico *dicoattr) { int res=0; // ---- restore standard attributes res+=extractar_restore_attr_std(exar, objtype, fullpath, relpath, dicoattr); // ---- restore extended attributes res+=extractar_restore_attr_xattr(exar, objtype, fullpath, relpath, dicoattr); // ---- restore windows attributes res+=extractar_restore_attr_windows(exar, objtype, fullpath, relpath, dicoattr); return (res==0)?(0):(-1); } int extractar_restore_obj_symlink(cextractar *exar, char *fullpath, char *relpath, char *destdir, cdico *d, int objtype, int fstype) { char parentdir[PATH_MAX]; struct timeval tv[2]; char buffer[PATH_MAX]; u64 targettype; int fdtemp; // update cost statistics and progress bar exar->cost_current+=FSA_COST_PER_FILE; // check the list of excluded files/dirs if (is_filedir_excluded(relpath)==true) goto extractar_restore_obj_symlink_err; // update progress bar extractar_listing_print_file(exar, objtype, relpath); // create parent directory first extract_dirpath(fullpath, parentdir, sizeof(parentdir)); mkdir_recursive(parentdir); // backup parent dir atime/mtime get_parent_dir_time_attrib(fullpath, parentdir, sizeof(parentdir), tv); if (dico_get_string(d, DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_SYMLINK, buffer, PATH_MAX)<0) { errprintf("Cannot read field=symlink for file=[%s]\n", fullpath); goto extractar_restore_obj_symlink_err; } // in ntfs a symlink has to be recreated as a standard file or directory (depending on what the target is) if ((dico_get_u64(d, DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_LINKTARGETTYPE, &targettype)==0) && (strcmp(filesys[fstype].name, "ntfs")==0)) { switch (targettype) { case OBJTYPE_DIR: msgprintf(MSG_DEBUG1, "LINK: mklink=[%s], target=[%s], targettype=DIR\n", relpath, buffer); if (mkdir_recursive(fullpath)!=0) { errprintf("Cannot create directory for ntfs symlink: path=[%s]\n", fullpath); goto extractar_restore_obj_symlink_err; } break; case OBJTYPE_REGFILEUNIQUE: msgprintf(MSG_DEBUG1, "LINK: mklink=[%s], target=[%s], targettype=REGFILE\n", relpath, buffer); if ( (fdtemp=creat(fullpath, 0644)) < 0) { errprintf("Cannot create file for ntfs symlink: path=[%s]\n", fullpath); goto extractar_restore_obj_symlink_err; } close(fdtemp); break; default: msgprintf(MSG_DEBUG1, "LINK: mklink=[%s], target=[%s], targettype=UNKNOWN\n", relpath, buffer); errprintf("Unexpected target type for ntfs symlink: path=[%s]\n", fullpath); goto extractar_restore_obj_symlink_err; break; } } else // normal symbolic link for linux filesystems { msgprintf(MSG_DEBUG1, "LINK: symlink=[%s], target=[%s] (normal symlink)\n", relpath, buffer); if (symlink(buffer, fullpath)<0) { sysprintf("symlink(%s, %s) failed\n", buffer, fullpath); goto extractar_restore_obj_symlink_err; } } if (extractar_restore_attr_everything(exar, objtype, fullpath, relpath, d)!=0) { msgprintf(MSG_STACK, "cannot restore file attributes for file [%s]\n", relpath); goto extractar_restore_obj_symlink_err; } // restore parent dir mtime/atime if (utimes(parentdir, tv)!=0) { sysprintf("utimes(%s) failed\n", parentdir); goto extractar_restore_obj_symlink_err; } dico_destroy(d); exar->stats.cnt_symlink++; return 0; // success extractar_restore_obj_symlink_err: dico_destroy(d); exar->stats.err_symlink++; return 0; // non fatal error } int extractar_restore_obj_hardlink(cextractar *exar, char *fullpath, char *relpath, char *destdir, cdico *d, int objtype, int fstype) { char parentdir[PATH_MAX]; struct timeval tv[2]; char buffer[PATH_MAX]; char regfile[PATH_MAX]; int res; // update cost statistics and progress bar exar->cost_current+=FSA_COST_PER_FILE; // check the list of excluded files/dirs if (is_filedir_excluded(relpath)==true) goto extractar_restore_obj_hardlink_err; // create parent directory first extract_dirpath(fullpath, parentdir, sizeof(parentdir)); mkdir_recursive(parentdir); // backup parent dir atime/mtime get_parent_dir_time_attrib(fullpath, parentdir, sizeof(parentdir), tv); // update progress bar extractar_listing_print_file(exar, objtype, relpath); if (dico_get_string(d, DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_HARDLINK, buffer, PATH_MAX)<0) { msgprintf(MSG_STACK, "dico_get_string(DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_HARDLINK) failed\n"); goto extractar_restore_obj_hardlink_err; } concatenate_paths(regfile, PATH_MAX, destdir, buffer); if ((res=link(regfile, fullpath))!=0) { sysprintf("link(%s, %s) failed\n", regfile, fullpath); goto extractar_restore_obj_hardlink_err; } if (extractar_restore_attr_everything(exar, objtype, fullpath, relpath, d)!=0) { msgprintf(MSG_STACK, "cannot restore file attributes for file [%s]\n", relpath); goto extractar_restore_obj_hardlink_err; } // restore parent dir mtime/atime if (utimes(parentdir, tv)!=0) { sysprintf("utimes(%s) failed\n", parentdir); goto extractar_restore_obj_hardlink_err; } dico_destroy(d); exar->stats.cnt_hardlink++; return 0; // success extractar_restore_obj_hardlink_err: dico_destroy(d); exar->stats.err_hardlink++; return 0; // non fatal error } int extractar_restore_obj_devfile(cextractar *exar, char *fullpath, char *relpath, char *destdir, cdico *d, int objtype, int fstype) { char parentdir[PATH_MAX]; struct timeval tv[2]; u64 dev; u32 mode; // update cost statistics and progress bar exar->cost_current+=FSA_COST_PER_FILE; // check the list of excluded files/dirs if (is_filedir_excluded(relpath)==true) goto extractar_restore_obj_devfile_err; // create parent directory first extract_dirpath(fullpath, parentdir, sizeof(parentdir)); mkdir_recursive(parentdir); // backup parent dir atime/mtime get_parent_dir_time_attrib(fullpath, parentdir, sizeof(parentdir), tv); // update progress bar extractar_listing_print_file(exar, objtype, relpath); if (dico_get_u64(d, DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_RDEV, &dev)!=0) goto extractar_restore_obj_devfile_err; if (dico_get_u32(d, DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_MODE, &mode)!=0) goto extractar_restore_obj_devfile_err; if (mknod(fullpath, mode, dev)!=0) { sysprintf("mknod failed on [%s]\n", relpath); goto extractar_restore_obj_devfile_err; } if (extractar_restore_attr_everything(exar, objtype, fullpath, relpath, d)!=0) { msgprintf(MSG_STACK, "cannot restore file attributes for file [%s]\n", relpath); goto extractar_restore_obj_devfile_err; } // restore parent dir mtime/atime if (utimes(parentdir, tv)!=0) { sysprintf("utimes(%s) failed\n", parentdir); goto extractar_restore_obj_devfile_err; } dico_destroy(d); exar->stats.cnt_special++; return 0; // success extractar_restore_obj_devfile_err: dico_destroy(d); exar->stats.err_special++; return 0; // non fatal error } int extractar_restore_obj_directory(cextractar *exar, char *fullpath, char *relpath, char *destdir, cdico *d, int objtype, int fstype) { char parentdir[PATH_MAX]; struct timeval tv[2]; // update cost statistics and progress bar exar->cost_current+=FSA_COST_PER_FILE; // check the list of excluded files/dirs if (is_filedir_excluded(relpath)==true) goto extractar_restore_obj_directory_err; // create parent directory first extract_dirpath(fullpath, parentdir, sizeof(parentdir)); mkdir_recursive(parentdir); // backup parent dir atime/mtime get_parent_dir_time_attrib(fullpath, parentdir, sizeof(parentdir), tv); // update progress bar extractar_listing_print_file(exar, objtype, relpath); mkdir_recursive(fullpath); if (extractar_restore_attr_everything(exar, objtype, fullpath, relpath, d)!=0) { msgprintf(MSG_STACK, "cannot restore file attributes for file [%s]\n", relpath); goto extractar_restore_obj_directory_err; } // restore parent dir mtime/atime if (utimes(parentdir, tv)!=0) { sysprintf("utimes(%s) failed\n", parentdir); goto extractar_restore_obj_directory_err; } dico_destroy(d); exar->stats.cnt_dir++; return 0; // success extractar_restore_obj_directory_err: dico_destroy(d); exar->stats.err_dir++; return 0; // non fatal error } int extractar_restore_obj_regfile_multi(cextractar *exar, char *destdir, cdico *dicofirstfile, int objtype, int fstype) // d = obj-header of first small file { cdatafile *datafile=NULL; char databuf[FSA_MAX_SMALLFILESIZE]; char basename[PATH_MAX]; cdico *filehead=NULL; char magic[FSA_SIZEOF_MAGIC+1]; char fullpath[PATH_MAX]; char relpath[PATH_MAX]; char parentdir[PATH_MAX]; struct timeval tv[2]; struct s_blockinfo blkinfo; cregmulti regmulti; u8 md5sumcalc[16]; u8 md5sumorig[16]; int errors; u32 filescount; u32 tmpobjtype; u64 datsize; s64 lres; int res; int i; // init errors=0; memset(&blkinfo, 0, sizeof(blkinfo)); regmulti_init(®multi, FSA_MAX_BLKSIZE); datafile=datafile_alloc(); // ---- dequeue header for each small file which is part of that group if (dico_get_u32(dicofirstfile, 0, DISKITEMKEY_MULTIFILESCOUNT, &filescount)!=0) { errprintf("cannot read DISKITEMKEY_MULTIFILESCOUNT from header in archive\n"); return -1; } if (regmulti_rest_addheader(®multi, dicofirstfile)!=0) { errprintf("rest_addheader() failed\n"); return -1; } for (i=1; i < filescount; i++) // first header was a special case (received from calling function) { if (queue_dequeue_header(&g_queue, &filehead, magic, NULL)<=0) { errprintf("queue_dequeue_header() failed: cannot read multireg object header\n"); errors++; return -1; } if (memcmp(magic, FSA_MAGIC_OBJT, FSA_SIZEOF_MAGIC)!=0) { errprintf("header is not what we expected: found=[%s] and expected=[%s]\n", magic, FSA_MAGIC_OBJT); return -1; } if (regmulti_rest_addheader(®multi, filehead)!=0) { errprintf("rest_addheader() failed for file %d\n", i); return -1; } } // ---- dequeue the block which contains data for several small files if ((lres=queue_dequeue_block(&g_queue, &blkinfo))<=0) { errprintf("queue_dequeue_block()=%ld=%s failed\n", (long)lres, error_int_to_string(lres)); return -1; } if (regmulti_rest_setdatablock(®multi, blkinfo.blkdata, blkinfo.blkrealsize)!=0) { errprintf("regmulti_rest_setdatablock() failed\n"); return -1; } free(blkinfo.blkdata); // free memory allocated by the thread_io_reader // ---- create the set of small files using the regmulti structure for (i=0; i < filescount; i++) { // get header and data for a small file from the regmulti structure if (regmulti_rest_getfile(®multi, i, &filehead, databuf, &datsize, sizeof(databuf))!=0) { errprintf("rest_addheader() failed for file %d\n", i); filehead=NULL; // else dico_destroy would fail goto extractar_restore_obj_regfile_multi_err; } if (dico_get_u32(filehead, DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_OBJTYPE, &tmpobjtype)!=0) { errprintf("Cannot read object type\n"); goto extractar_restore_obj_regfile_multi_err; } if ((res=dico_get_data(filehead, DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_PATH, relpath, sizeof(relpath), NULL))!=0) { errprintf("Cannot read DISKITEMKEY_PATH from header, res=%d, key=%d\n", res, DISKITEMKEY_PATH); dico_show(filehead, DICO_OBJ_SECTION_STDATTR, "DISKITEMKEY_PATH"); goto extractar_restore_obj_regfile_multi_err; } concatenate_paths(fullpath, sizeof(fullpath), destdir, relpath); extract_basename(fullpath, basename, sizeof(basename)); // update cost statistics and progress bar exar->cost_current+=FSA_COST_PER_FILE; exar->cost_current+=datsize; // filesize // check the list of excluded files/dirs if (is_filedir_excluded(relpath)!=true) { // create parent directory if necessary extract_dirpath(fullpath, parentdir, sizeof(parentdir)); mkdir_recursive(parentdir); // backup parent dir atime/mtime get_parent_dir_time_attrib(fullpath, parentdir, sizeof(parentdir), tv); extractar_listing_print_file(exar, tmpobjtype, relpath); if (dico_get_data(filehead, DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_MD5SUM, md5sumorig, 16, NULL)) { errprintf("cannot get md5sum from file footer for file=[%s]\n", relpath); dico_show(filehead, DICO_OBJ_SECTION_STDATTR, "filehead"); goto extractar_restore_obj_regfile_multi_err; } if (datafile_open_write(datafile, fullpath, false, false)<0) goto extractar_restore_obj_regfile_multi_err; res=datafile_write(datafile, databuf, datsize); datafile_close(datafile, md5sumcalc, sizeof(md5sumcalc)); if (res!=FSAERR_SUCCESS) { errprintf("removing %s\n", fullpath); unlink(fullpath); return -1; } if (memcmp(md5sumcalc, md5sumorig, 16)!=0) { errprintf("cannot restore file %s, the data block (which is shared by multiple files) is corrupt\n", relpath); res=truncate(fullpath, 0); // don't leave corrupt data in the file goto extractar_restore_obj_regfile_multi_err; } if (extractar_restore_attr_everything(exar, objtype, fullpath, relpath, filehead)!=0) { msgprintf(MSG_STACK, "cannot restore file attributes for file [%s]\n", relpath); goto extractar_restore_obj_regfile_multi_err; } // restore parent dir mtime/atime if (utimes(parentdir, tv)!=0) { sysprintf("utimes(%s) failed\n", parentdir); goto extractar_restore_obj_regfile_multi_err; } exar->stats.cnt_regfile++; } dico_destroy(filehead); continue; // success on that file extractar_restore_obj_regfile_multi_err: dico_destroy(filehead); exar->stats.err_regfile++; continue; } datafile_destroy(datafile); return 0; } int extractar_restore_obj_regfile_unique(cextractar *exar, char *fullpath, char *relpath, char *destdir, cdico *d, int objtype, int fstype) // large or empty files { char magic[FSA_SIZEOF_MAGIC+1]; struct s_blockinfo blkinfo; char parentdir[PATH_MAX]; cdatafile *datafile=NULL; cdico *footerdico=NULL; bool fatalerr=false; // error for restoration globally bool minorerr=false; // error for current file only bool delfile=false; struct timeval tv[2]; u8 md5sumcalc[16]; u8 md5sumorig[16]; int excluded=false; bool sparse=false; u64 filesize=0; u64 filepos=0; u64 flags=0; s64 lres; // init memset(&blkinfo, 0, sizeof(blkinfo)); memset(magic, 0, sizeof(magic)); datafile=datafile_alloc(); if (dico_get_u64(d, DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_SIZE, &filesize)!=0) { errprintf("Cannot read filesize DISKITEMKEY_SIZE from archive for file=[%s]\n", relpath); minorerr=true; } sparse=((dico_get_u64(d, DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_FLAGS, &flags)==0) && (flags&FSA_FILEFLAGS_SPARSE)); // update cost statistics and progress bar exar->cost_current+=FSA_COST_PER_FILE; exar->cost_current+=filesize; // check the list of excluded files/dirs if (is_filedir_excluded(relpath)==true) { excluded=true; } else if (minorerr==false) // file not excluded and no error yet { // create parent directory first extract_dirpath(fullpath, parentdir, sizeof(parentdir)); mkdir_recursive(parentdir); // backup parent dir atime/mtime get_parent_dir_time_attrib(fullpath, parentdir, sizeof(parentdir), tv); // show progress bar extractar_listing_print_file(exar, objtype, relpath); } if ((minorerr==false) && (datafile_open_write(datafile, fullpath, excluded, sparse)<0)) minorerr=true; msgprintf(MSG_DEBUG2, "restore_obj_regfile_unique(file=%s, size=%lld)\n", relpath, (long long)filesize); for (filepos=0; (minorerr==false) && (filesize>0) && (filepos < filesize) && (get_interrupted()==false); filepos+=blkinfo.blkrealsize) { if ((lres=queue_dequeue_block(&g_queue, &blkinfo))<=0) { errprintf("queue_dequeue_block()=%ld=%s for file(%s) failed\n", (long)lres, error_int_to_string(lres), relpath); delfile=true; minorerr=true; break; } if (blkinfo.blkoffset!=filepos) { errprintf("file offset do not match for file(%s) failed: filepos=%lld, blkinfo.blkoffset=%lld, blkinfo.blkrealsize=%lld\n", relpath, (long long)filepos, (long long)blkinfo.blkoffset, (long long)blkinfo.blkrealsize); free(blkinfo.blkdata); delfile=true; minorerr=true; break; } if (datafile_write(datafile, blkinfo.blkdata, blkinfo.blkrealsize)!=FSAERR_SUCCESS) { free(blkinfo.blkdata); delfile=true; minorerr=true; fatalerr=true; break; } free(blkinfo.blkdata); } if ((minorerr==false) && (datafile_close(datafile, md5sumcalc, sizeof(md5sumcalc))!=0)) minorerr=true; if ((minorerr==false) && (excluded==false)) { if (extractar_restore_attr_everything(exar, objtype, fullpath, relpath, d)!=0) { msgprintf(MSG_STACK, "cannot restore file attributes for file [%s]\n", relpath); minorerr=true; } // restore parent dir mtime/atime if (utimes(parentdir, tv)!=0) { sysprintf("utimes(%s) failed\n", parentdir); minorerr=true; } } // empty files have no footer (no need for a checksum) if ((fatalerr==false) && (filesize>0)) { if (queue_dequeue_header(&g_queue, &footerdico, magic, NULL)<=0) { errprintf("queue_dequeue_header() failed: cannot read footer dico\n"); minorerr=true; goto restore_obj_regfile_unique_end; } if (excluded!=true) { if (memcmp(magic, FSA_MAGIC_FILF, FSA_SIZEOF_MAGIC)!=0) { errprintf("header is not what we expected: found=[%s] and expected=[%s]\n", magic, FSA_MAGIC_FILF); minorerr=true; goto restore_obj_regfile_unique_end; } if (dico_get_data(footerdico, 0, BLOCKFOOTITEMKEY_MD5SUM, md5sumorig, 16, NULL)) { errprintf("cannot get md5sum from file footer for file=[%s]\n", relpath); minorerr=true; goto restore_obj_regfile_unique_end; } if (memcmp(md5sumcalc, md5sumorig, 16)!=0) { errprintf("cannot restore file %s, file is corrupt\n", relpath); delfile=true; // don't leave corrupt data in the file minorerr=true; goto restore_obj_regfile_unique_end; } } } restore_obj_regfile_unique_end: if (delfile==true) { errprintf("removing %s\n", fullpath); unlink(fullpath); } if (excluded!=true) { if (minorerr==true) exar->stats.err_regfile++; else exar->stats.cnt_regfile++; } if (get_interrupted()==true) errprintf("operation has been interrupted\n"); dico_destroy(footerdico); dico_destroy(d); datafile_destroy(datafile); return (fatalerr==false)?(0):(-1); } int extractar_restore_object(cextractar *exar, int *errors, char *destdir, cdico *dicoattr, int fstype) { char relpath[PATH_MAX]; char fullpath[PATH_MAX]; u64 filesize; u32 objtype; int res; // init *errors=0; if (dico_get_data(dicoattr, DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_PATH, relpath, sizeof(relpath), NULL)!=0) return -1; if (dico_get_u32(dicoattr, DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_OBJTYPE, &objtype)!=0) return -2; if (dico_get_u64(dicoattr, DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_SIZE, &filesize)!=0) return -3; concatenate_paths(fullpath, sizeof(fullpath), destdir, relpath); // ---- recreate specific object on the filesystem switch (objtype) { case OBJTYPE_DIR: msgprintf(MSG_DEBUG2, "objtype=OBJTYPE_DIR, path=[%s]\n", relpath); res=extractar_restore_obj_directory(exar, fullpath, relpath, destdir, dicoattr, objtype, fstype); break; case OBJTYPE_SYMLINK: msgprintf(MSG_DEBUG2, "objtype=OBJTYPE_SYMLINK, path=[%s]\n", relpath); res=extractar_restore_obj_symlink(exar, fullpath, relpath, destdir, dicoattr, objtype, fstype); break; case OBJTYPE_HARDLINK: msgprintf(MSG_DEBUG2, "objtype=OBJTYPE_HARDLINK, path=[%s]\n", relpath); res=extractar_restore_obj_hardlink(exar, fullpath, relpath, destdir, dicoattr, objtype, fstype); break; case OBJTYPE_CHARDEV: msgprintf(MSG_DEBUG2, "objtype=OBJTYPE_CHARDEV, path=[%s]\n", relpath); res=extractar_restore_obj_devfile(exar, fullpath, relpath, destdir, dicoattr, objtype, fstype); break; case OBJTYPE_BLOCKDEV: msgprintf(MSG_DEBUG2, "objtype=OBJTYPE_BLOCKDEV, path=[%s]\n", relpath); res=extractar_restore_obj_devfile(exar, fullpath, relpath, destdir, dicoattr, objtype, fstype); break; case OBJTYPE_FIFO: msgprintf(MSG_DEBUG2, "objtype=OBJTYPE_FIFO, path=[%s]\n", relpath); res=extractar_restore_obj_devfile(exar, fullpath, relpath, destdir, dicoattr, objtype, fstype); break; case OBJTYPE_SOCKET: msgprintf(MSG_DEBUG2, "objtype=OBJTYPE_SOCKET, path=[%s]\n", relpath); res=extractar_restore_obj_devfile(exar, fullpath, relpath, destdir, dicoattr, objtype, fstype); break; case OBJTYPE_REGFILEUNIQUE: msgprintf(MSG_DEBUG2, "objtype=OBJTYPE_REGFILEUNIQUE, path=[%s]\n", relpath); if ((res=extractar_restore_obj_regfile_unique(exar, fullpath, relpath, destdir, dicoattr, objtype, fstype))<0) { msgprintf(MSG_STACK, "restore_obj_regfile_unique(%s) failed with res=%d\n", relpath, res); return -1; } break; case OBJTYPE_REGFILEMULTI: msgprintf(MSG_DEBUG2, "objtype=OBJTYPE_REGFILEMULTI, path=[%s]\n", relpath); if ((res=extractar_restore_obj_regfile_multi(exar, destdir, dicoattr, objtype, fstype))<0) { msgprintf(MSG_STACK, "restore_obj_regfile_multi(%s) failed with res=%d\n", relpath, res); return -1; } break; default: errprintf("Unknown objtype %d\n", objtype); return -3; } if (res!=0) // value returned by restore_obj_xxx() { errprintf("Restoring file=[%s], objtype=[%s] failed\n", fullpath, get_objtype_name(objtype)); return -1; } return 0; } int extractar_extract_read_objects(cextractar *exar, int *errors, char *destdir, int fstype) { char magic[FSA_SIZEOF_MAGIC+1]; cdico *dicoattr=NULL; int headerisend; int headerisobj; u16 checkfsid; int curerr; int type; int res; // init memset(magic, 0, sizeof(magic)); *errors=0; do { // skip the garbage (just ignore everything until the next FSA_MAGIC_OBJT) // in case the archive is corrupt and random data has been added / removed in the archive do { if (queue_check_next_item(&g_queue, &type, magic)!=0) { errprintf("queue_check_next_item() failed: cannot read object from archive\n"); return -1; } headerisobj=(memcmp(magic, FSA_MAGIC_OBJT, FSA_SIZEOF_MAGIC)==0); headerisend=(memcmp(magic, FSA_MAGIC_DATF, FSA_SIZEOF_MAGIC)==0); if (headerisobj!=true && headerisend!=true) // did not find expected header: skip garbage in archive { errprintf("unexpected header found in archive, skipping it: type=%d, magic=[%s]\n", type, (type==QITEM_TYPE_HEADER)?(magic):"-block-"); if (queue_destroy_first_item(&g_queue)!=0) { errprintf("queue_destroy_first_item() failed: cannot read object from archive\n"); return -1; } } } while ((headerisobj!=true) && (headerisend!=true)); if (headerisobj==true) // if it's an object header { // read object header from archive while (queue_dequeue_header(&g_queue, &dicoattr, magic, &checkfsid)<=0) { errprintf("queue_dequeue_header() failed\n"); (*errors)++; } if (checkfsid==exar->fsid) // if filesystem-id is correct { if ((res=extractar_restore_object(exar, &curerr, destdir, dicoattr, fstype))!=0) { msgprintf(MSG_STACK, "restore_object() failed with res=%d\n", res); //dico_destroy(dicoattr); return -1; // fatal error } } else // wrong filesystem-id { errprintf("restore_object(): object has a wrong filesystem id: found=[%d], expected=[%d]\n", checkfsid, exar->fsid); (*errors)++; } //dico_destroy(dicoattr); } } while ((headerisend!=true) && (get_abort()==false)); return 0; } int extractar_read_mainhead(cextractar *exar, cdico **dicomainhead) { u8 bufcheckclear[FSA_CHECKPASSBUF_SIZE+8]; u8 bufcheckcrypt[FSA_CHECKPASSBUF_SIZE+8]; char magic[FSA_SIZEOF_MAGIC+1]; u16 cryptbufsize; u8 md5sumar[16]; u8 md5sumnew[16]; u64 clearsize; int passlen; u32 temp32; assert(exar); assert(dicomainhead); // init memset(magic, 0, sizeof(magic)); if (queue_dequeue_header(&g_queue, dicomainhead, magic, NULL)<=0) { errprintf("queue_dequeue_header() failed: cannot read main header\n"); return -1; } if (memcmp(magic, FSA_MAGIC_MAIN, FSA_SIZEOF_MAGIC)!=0) { errprintf("header is not what we expected: found=[%s] and expected=[%s]\n", magic, FSA_MAGIC_MAIN); return -1; } if (dico_get_u32(*dicomainhead, 0, MAINHEADKEY_ARCHTYPE, &exar->ai.archtype)!=0) { errprintf("cannot find MAINHEADKEY_ARCHTYPE in main-header\n"); return -1; } if (exar->ai.archtype==ARCHTYPE_FILESYSTEMS && dico_get_u64(*dicomainhead, 0, MAINHEADKEY_FSCOUNT, &exar->ai.fscount)!=0) { errprintf("cannot find MAINHEADKEY_FSCOUNT in main-header\n"); return -1; } if (dico_get_u32(*dicomainhead, 0, MAINHEADKEY_ARCHIVEID, &exar->ai.archid)!=0) { errprintf("cannot find MAINHEADKEY_ARCHIVEID in main-header\n"); return -1; } if (dico_get_data(*dicomainhead, 0, MAINHEADKEY_FILEFORMATVER, exar->ai.filefmt, FSA_MAX_FILEFMTLEN, NULL)!=0) { errprintf("cannot find MAINHEADKEY_FILEFORMATVER in main-header\n"); return -1; } if (dico_get_data(*dicomainhead, 0, MAINHEADKEY_PROGVERCREAT, exar->ai.creatver, FSA_MAX_PROGVERLEN, NULL)!=0) { errprintf("cannot find MAINHEADKEY_PROGVERCREAT in main-header\n"); return -1; } if (dico_get_data(*dicomainhead, 0, MAINHEADKEY_ARCHLABEL, exar->ai.label, FSA_MAX_LABELLEN, NULL)!=0) { errprintf("cannot find MAINHEADKEY_ARCHLABEL in main-header\n"); return -1; } if (dico_get_u32(*dicomainhead, 0, MAINHEADKEY_COMPRESSALGO, &exar->ai.compalgo)!=0) { errprintf("cannot find MAINHEADKEY_COMPRESSALGO in main-header\n"); return -1; } if (dico_get_u32(*dicomainhead, 0, MAINHEADKEY_ENCRYPTALGO, &exar->ai.cryptalgo)!=0) { errprintf("cannot find MAINHEADKEY_ENCRYPTALGO in main-header\n"); return -1; } if (dico_get_u32(*dicomainhead, 0, MAINHEADKEY_COMPRESSLEVEL, &exar->ai.complevel)!=0) { errprintf("cannot find MAINHEADKEY_COMPRESSLEVEL in main-header\n"); return -1; } if (dico_get_u32(*dicomainhead, 0, MAINHEADKEY_FSACOMPLEVEL, &exar->ai.fsacomp)!=0) { errprintf("cannot find MAINHEADKEY_FSACOMPLEVEL in main-header\n"); return -1; } if (dico_get_u64(*dicomainhead, 0, MAINHEADKEY_CREATTIME, &exar->ai.creattime)!=0) { errprintf("cannot find MAINHEADKEY_CREATTIME in main-header\n"); return -1; } // MAINHEADKEY_HASDIRSINFOHEAD has been introduced in fsarchiver-0.6.7: don't fail if missing if (dico_get_u32(*dicomainhead, 0, MAINHEADKEY_HASDIRSINFOHEAD, &temp32)==0) exar->ai.hasdirsinfohead=temp32; // check the file format. New versions based on "FsArCh_002" also understand "FsArCh_001" which is very close (and "FsArCh_00Y"=="FsArCh_001") if (strcmp(exar->ai.filefmt, FSA_FILEFORMAT)!=0 && strcmp(exar->ai.filefmt, "FsArCh_00Y")!=0 && strcmp(exar->ai.filefmt, "FsArCh_001")!=0) { errprintf("This archive is based on a different file format: [%s]. Cannot continue.\n", exar->ai.filefmt); errprintf("It has been created with fsarchiver [%s], you should extrat the archive using that version.\n", exar->ai.creatver); errprintf("The current version of the program is [%s], and it's based on format [%s]\n", FSA_VERSION, FSA_FILEFORMAT); return -1; } // read minimum fsarchiver version requirement if (dico_get_u64(*dicomainhead, 0, MAINHEADKEY_MINFSAVERSION, &exar->ai.minfsaver)!=0) exar->ai.minfsaver=FSA_VERSION_BUILD(0, 0, 0, 0); // not defined // if encryption is enabled, check the password is correct using the encrypted random buffer saved in the archive if (exar->ai.cryptalgo!=ENCRYPT_NONE) { memset(md5sumar, 0, sizeof(md5sumar)); memset(md5sumnew, 0, sizeof(md5sumnew)); if (dico_get_data(*dicomainhead, 0, MAINHEADKEY_BUFCHECKPASSCRYPTBUF, bufcheckcrypt, sizeof(bufcheckcrypt), &cryptbufsize)!=0) { errprintf("cannot find MAINHEADKEY_BUFCHECKPASSCRYPTBUF in main-header\n"); return -1; } if (dico_get_data(*dicomainhead, 0, MAINHEADKEY_BUFCHECKPASSCLEARMD5, md5sumar, sizeof(md5sumar)+99, NULL)!=0) { errprintf("cannot find MAINHEADKEY_BUFCHECKPASSCLEARMD5 in main-header\n"); return -1; } passlen=(g_options.encryptpass==NULL)?(0):(strlen((char*)g_options.encryptpass)); if ((g_options.encryptpass==NULL) || (passlenFSA_MAX_PASSLEN)) { errprintf("you have to provide the password which was used to create archive, no password given on the command line\n"); return -1; } if (crypto_blowfish(cryptbufsize, &clearsize, bufcheckcrypt, bufcheckclear, g_options.encryptpass, strlen((char*)g_options.encryptpass), false)==0) gcry_md_hash_buffer(GCRY_MD_MD5, md5sumnew, bufcheckclear, clearsize); if (memcmp(md5sumar, md5sumnew, 16)!=0) { errprintf("you have to provide the password which was used to create archive, cannot decrypt the test buffer.\n"); return -1; } } return 0; } int extractar_filesystem_extract(cextractar *exar, cdico *dicofs, cstrdico *dicocmdline) { char filesystem[FSA_MAX_FSNAMELEN]; char text[FSA_MAX_FSNAMELEN]; char fsbuf[FSA_MAX_FSNAMELEN]; char magic[FSA_SIZEOF_MAGIC+1]; char mountinfo[4096]; char partition[1024]; char mkfsoptions[1024]; char mkfslabel[1024]; char mkfsuuid[1024]; char tempbuf[1024]; cdico *dicobegin=NULL; cdico *dicoend=NULL; char mntbuf[PATH_MAX]; u64 fsbytestotal; u64 fsbytesused; char optbuf[128]; int readwrite; int errors=0; u64 minver; u64 curver; int fstype; int ret=0; int res; // init memset(magic, 0, sizeof(magic)); memset(partition, 0, sizeof(partition)); memset(mkfslabel, 0, sizeof(mkfslabel)); memset(mkfsuuid, 0, sizeof(mkfsuuid)); // read destination partition from dicocmdline if (strdico_get_string(dicocmdline, partition, sizeof(partition), "dest")!=0) { errprintf("strdico_get_string(dicocmdline, 'dest') failed\n"); return -1; } // check that the minimum fsarchiver version required is ok if (dico_get_u64(dicofs, 0, FSYSHEADKEY_MINFSAVERSION, &minver)!=0) minver=FSA_VERSION_BUILD(0, 6, 4, 0); // fsarchiver-0.6.4 is the first fsa version having fileformat="FsArCh_002" curver=FSA_VERSION_BUILD(PACKAGE_VERSION_A, PACKAGE_VERSION_B, PACKAGE_VERSION_C, PACKAGE_VERSION_D); msgprintf(MSG_VERB2, "Current fsarchiver version: %d.%d.%d.%d\n", (int)FSA_VERSION_GET_A(curver), (int)FSA_VERSION_GET_B(curver), (int)FSA_VERSION_GET_C(curver), (int)FSA_VERSION_GET_D(curver)); msgprintf(MSG_VERB2, "Minimum fsarchiver version for that filesystem: %d.%d.%d.%d\n", (int)FSA_VERSION_GET_A(minver), (int)FSA_VERSION_GET_B(minver), (int)FSA_VERSION_GET_C(minver), (int)FSA_VERSION_GET_D(minver)); if (curver < minver) { errprintf("This filesystem can only be restored with fsarchiver %d.%d.%d.%d or more recent\n", (int)FSA_VERSION_GET_A(minver), (int)FSA_VERSION_GET_B(minver), (int)FSA_VERSION_GET_C(minver), (int)FSA_VERSION_GET_D(minver)); return -1; } // check the partition is not mounted res=generic_get_mntinfo(partition, &readwrite, mntbuf, sizeof(mntbuf), optbuf, sizeof(optbuf), fsbuf, sizeof(fsbuf)); if (res==0) { errprintf("partition [%s] is mounted on [%s].\ncannot restore an archive to a partition " "which is mounted, unmount it first: umount %s\n", partition, mntbuf, mntbuf); return -1; } // ---- read filesystem-header from archive if (queue_dequeue_header(&g_queue, &dicobegin, magic, NULL)<=0) { errprintf("queue_dequeue_header() failed: cannot read file system dico\n"); return -1; } dico_destroy(dicobegin); if (memcmp(magic, FSA_MAGIC_FSYB, FSA_SIZEOF_MAGIC)!=0) { errprintf("header is not what we expected: found=[%s] and expected=[%s]\n", magic, FSA_MAGIC_FSYB); return -1; } // if a filesystem to use was specified: overwrite the default one if (strdico_get_string(dicocmdline, tempbuf, sizeof(tempbuf), "mkfs")==0) { snprintf(filesystem, sizeof(filesystem), "%s", tempbuf); } else if ((dico_get_string(dicofs, 0, FSYSHEADKEY_FILESYSTEM, filesystem, sizeof(filesystem)))<0) { errprintf("dico_get_string(FSYSHEADKEY_FILESYSTEM) failed\n"); return -1; } // read make file system options from dicocmdline if (strdico_get_string(dicocmdline, mkfsoptions, sizeof(mkfsoptions), "mkfsopt")!=0) { msgprintf(MSG_VERB2,"strdico_get_string(dicocmdline, 'mkfsopt') doesn't exist\n"); } if (strdico_get_string(dicocmdline, mkfslabel, sizeof(mkfslabel), "label")!=0) { msgprintf(MSG_VERB2,"strdico_get_string(dicocmdline, 'label') doesn't exist\n"); } if (strdico_get_string(dicocmdline, mkfsuuid, sizeof(mkfsuuid), "uuid")!=0) { msgprintf(MSG_VERB2,"strdico_get_string(dicocmdline, 'uuid') doesn't exist\n"); } if (dico_get_u64(dicofs, 0, FSYSHEADKEY_BYTESTOTAL, &fsbytestotal)!=0) { errprintf("dico_get_string(FSYSHEADKEY_BYTESTOTAL) failed\n"); return -1; } if (dico_get_u64(dicofs, 0, FSYSHEADKEY_BYTESUSED, &fsbytesused)!=0) { errprintf("dico_get_string(FSYSHEADKEY_BYTESUSED) failed\n"); return -1; } msgprintf(MSG_VERB2, "filesystem_type=[%s]\n", filesystem); msgprintf(MSG_VERB2, "filesystem_mkfsoptions=[%s]\n", mkfsoptions); msgprintf(MSG_VERB2, "filesystem_mkfslabel=[%s]\n", mkfslabel); msgprintf(MSG_VERB2, "filesystem_mkfsuuid=[%s]\n", mkfsuuid); msgprintf(MSG_VERB2, "filesystem_space_total=[%s]\n", format_size(fsbytestotal, text, sizeof(text), 'h')); msgprintf(MSG_VERB2, "filesystem_space_used=[%s]\n", format_size(fsbytesused, text, sizeof(text), 'h')); // get index of the filesystem in the filesystem table if (generic_get_fstype(filesystem, &fstype)!=0) { errprintf("filesystem [%s] is not supported by fsarchiver\n", filesystem); return -1; } // ---- make the filesystem if (filesys[fstype].mkfs(dicofs, partition, mkfsoptions, mkfslabel, mkfsuuid)!=0) { errprintf("cannot make filesystem %s on partition %s\n", filesystem, partition); return -1; } // ---- mount the new filesystem mkdir_recursive(mntbuf); generate_random_tmpdir(mntbuf, sizeof(mntbuf), 0); mkdir_recursive(mntbuf); if ((dico_get_string(dicofs, 0, FSYSHEADKEY_MOUNTINFO, mountinfo, sizeof(mountinfo)))<0) memset(mountinfo, 0, sizeof(mountinfo)); msgprintf(MSG_VERB1, "Mount information: [%s]\n", mountinfo); if (filesys[fstype].mount(partition, mntbuf, filesys[fstype].name, 0, mountinfo)!=0) { errprintf("partition [%s] cannot be mounted on %s. cannot continue.\n", partition, mntbuf); return -1; } if (extractar_extract_read_objects(exar, &errors, mntbuf, fstype)!=0) { msgprintf(MSG_STACK, "extract_read_objects(%s) failed\n", mntbuf); ret=-1; goto filesystem_extract_umount; } else if (errors>0) { msgprintf(MSG_DEBUG1, "extract_read_objects(%s) worked with errors\n", mntbuf); ret=-1; goto filesystem_extract_umount; } // read "end of file-system" header from archive if (queue_dequeue_header(&g_queue, &dicoend, magic, NULL)<=0) { errprintf("queue_dequeue_header() failed\n"); ret=-1; goto filesystem_extract_umount; } dico_destroy(dicoend); if ((get_interrupted()==false) && (memcmp(magic, FSA_MAGIC_DATF, FSA_SIZEOF_MAGIC)!=0)) { errprintf("header is not what we expected: found=[%s] and expected=[%s]\n", magic, FSA_MAGIC_DATF); goto filesystem_extract_umount; } filesystem_extract_umount: if (filesys[fstype].umount(partition, mntbuf)!=0) { sysprintf("cannot umount %s\n", mntbuf); ret=-1; } else { rmdir(mntbuf); // remove temp dir created by fsarchiver } return ret; } int oper_restore(char *archive, int argc, char **argv, int oper) { cdico *dicofsinfo[FSA_MAX_FSPERARCH]; cstrdico *dicoargv[FSA_MAX_FSPERARCH]; pthread_t thread_decomp[FSA_MAX_COMPJOBS]; char magic[FSA_SIZEOF_MAGIC+1]; cdico *dicomainhead=NULL; cdico *dirsinfo=NULL; pthread_t thread_reader; struct stat64 st; char *destdir; cextractar exar; u64 totalerr=0; u64 fscost; u64 curver; int errors=0; int ret=0; int i; // init memset(&exar, 0, sizeof(exar)); exar.cost_global=0; exar.cost_current=0; archreader_init(&exar.ai); // init misc data struct to zero for (i=0; i 0) { msgprintf(MSG_VERB2, "Current fsarchiver version: %d.%d.%d.%d\n", (int)FSA_VERSION_GET_A(curver), (int)FSA_VERSION_GET_B(curver), (int)FSA_VERSION_GET_C(curver), (int)FSA_VERSION_GET_D(curver)); msgprintf(MSG_VERB2, "Minimum fsarchiver version for that archive: %d.%d.%d.%d\n", (int)FSA_VERSION_GET_A(exar.ai.minfsaver), (int)FSA_VERSION_GET_B(exar.ai.minfsaver), (int)FSA_VERSION_GET_C(exar.ai.minfsaver), (int)FSA_VERSION_GET_D(exar.ai.minfsaver)); } if (((oper==OPER_RESTFS) || (oper==OPER_RESTDIR)) && (curver < exar.ai.minfsaver)) { errprintf("This archive can only be restored with fsarchiver %d.%d.%d.%d or more recent\n", (int)FSA_VERSION_GET_A(exar.ai.minfsaver), (int)FSA_VERSION_GET_B(exar.ai.minfsaver), (int)FSA_VERSION_GET_C(exar.ai.minfsaver), (int)FSA_VERSION_GET_D(exar.ai.minfsaver)); goto do_extract_error; } // show archive information if command is OPER_ARCHINFO if (oper==OPER_ARCHINFO && archinfo_show_mainhead(&exar.ai, dicomainhead)!=0) { errprintf("archinfo_show_mainhead(%s) failed\n", archive); goto do_extract_error; } // check that the operation requested on the command line matches the archive type switch (exar.ai.archtype) { case ARCHTYPE_DIRECTORIES: if (oper==OPER_RESTFS) { errprintf("this archive does not contain filesystems, cannot use \"restfs\". Try \"restdir\" instead.\n"); goto do_extract_error; } break; case ARCHTYPE_FILESYSTEMS: if (oper==OPER_RESTDIR) { errprintf("this archive does not contain simple directories, cannot use \"restdir\". Try \"restfs\" instead.\n"); goto do_extract_error; } break; default: errprintf("this archive has an unknown type: %d, cannot continue\n", exar.ai.archtype); goto do_extract_error; } // check the user did not specify an invalid filesystem id (id >= fscount) for (i=0; (i= exar.ai.fscount)) { errprintf("invalid filesystem id: [%d]. the filesystem id must be an integer between 0 and %d\n", (int)i, (int)(exar.ai.fscount-1)); goto do_extract_error; } } // read the fsinfo header for each filesystem for (i=0; (exar.ai.archtype==ARCHTYPE_FILESYSTEMS) && (i < exar.ai.fscount) && (i= 0.6.7 // so that they don't have error when they try to restore an archive which has that header if ((exar.ai.archtype==ARCHTYPE_DIRECTORIES) && (exar.ai.hasdirsinfohead==true)) { if (queue_dequeue_header(&g_queue, &dirsinfo, magic, NULL)<=0) { errprintf("queue_dequeue_header() failed: cannot read the dirsinfo header\n"); goto do_extract_error; } if (memcmp(magic, FSA_MAGIC_DIRS, FSA_SIZEOF_MAGIC)!=0) { errprintf("header is not what we expected: found=[%s] and expected=[%s]\n", magic, FSA_MAGIC_DIRS); goto do_extract_error; } if ((dirsinfo!=NULL) && (dico_get_u64(dirsinfo, 0, DIRSINFOKEY_TOTALCOST, &exar.cost_global)!=0)) { errprintf("cannot read DIRSINFOKEY_TOTALCOST in dirsinfo\n"); goto do_extract_error; } } if ((oper==OPER_RESTFS) || (oper==OPER_RESTDIR)) { if ((exar.ai.cryptalgo!=ENCRYPT_NONE) && (g_options.encryptalgo!=ENCRYPT_BLOWFISH)) { errprintf("this archive has been encrypted, you have to provide a password on the command line using option '-c'\n"); goto do_extract_error; } if (exar.ai.archtype==ARCHTYPE_FILESYSTEMS) { // extract filesystem contents for (i=0; (i < exar.ai.fscount) && (i < FSA_MAX_FSPERARCH) && (get_abort()==false); i++) { if (dicoargv[i]!=NULL) // that filesystem has been requested on the command line { exar.fsid=i; memset(&exar.stats, 0, sizeof(exar.stats)); // init stats to zero msgprintf(MSG_VERB1, "============= extracting filesystem %d =============\n", i); if (extractar_filesystem_extract(&exar, dicofsinfo[i], dicoargv[i])!=0) { msgprintf(MSG_STACK, "extract_filesystem(%d) failed\n", i); goto do_extract_error; } if (get_abort()==false) stats_show(exar.stats, i); totalerr+=stats_errcount(exar.stats); } // else: the thread_archio automatically skips filesystem when g_fsbitmap[fsid]==0 } } else if (exar.ai.archtype==ARCHTYPE_DIRECTORIES) { exar.fsid=0; destdir=argv[0]; if (stat64(destdir, &st)!=0) { switch (errno) { case ENOENT: sysprintf("%s does not exist, cannot continue\n", destdir); break; default: sysprintf("fstat64(%s) failed\n", destdir); break; } goto do_extract_error; } if (!S_ISDIR(st.st_mode)) { errprintf("%s is not a valid directory, cannot continue\n", destdir); goto do_extract_error; } memset(&exar.stats, 0, sizeof(exar.stats)); // init stats to zero if (extractar_extract_read_objects(&exar, &errors, destdir, 0)!=0) // TODO: get the right fstype { errprintf("extract_read_objects(%s) failed\n", destdir); goto do_extract_error; } stats_show(exar.stats, 0); totalerr+=stats_errcount(exar.stats); } else { errprintf("unsupported archtype: %d\n", exar.ai.archtype); goto do_extract_error; } } if (get_abort()==true) msgprintf(MSG_FORCE, "operation aborted by user\n"); if (get_abort()==false && get_stopfillqueue()==false) goto do_extract_success; do_extract_error: msgprintf(MSG_DEBUG1, "THREAD-MAIN2: exit error\n"); ret=-1; do_extract_success: msgprintf(MSG_DEBUG1, "THREAD-MAIN2: exit\n"); set_stopfillqueue(); // ask thread-archio to terminate msgprintf(MSG_DEBUG2, "queue_count_items_todo(&g_queue)=%d\n", (int)queue_count_items_todo(&g_queue)); while (queue_count_items_todo(&g_queue)>0) // let thread_compress process all the pending blocks { msgprintf(MSG_DEBUG2, "queue_count_items_todo(): %ld\n", (long)queue_count_items_todo(&g_queue)); usleep(10000); } msgprintf(MSG_DEBUG2, "queue_count_items_todo(&g_queue)=%d\n", (int)queue_count_items_todo(&g_queue)); // now we are sure that thread_compress is not working on an item in the queue so we can empty the queue while (get_secthreads()>0 && queue_get_end_of_queue(&g_queue)==false) queue_destroy_first_item(&g_queue); msgprintf(MSG_DEBUG1, "THREAD-MAIN2: queue is now empty\n"); // the queue is empty, so thread_compress should now exit for (i=0; (i0) ret=-1; dico_destroy(dicomainhead); archreader_destroy(&exar.ai); return ret; } fsarchiver-0.8.7/src/fs_xfs.h0000644000175000017500000002451114405605077013046 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifndef __FS_XFS_H__ #define __FS_XFS_H__ struct s_dico; struct s_strlist; /* * Super block * Fits into a sector-sized buffer at address 0 of each allocation group. * Only the first of these is ever updated except during growfs. */ #define XFS_SB_MAGIC 0x58465342 /* 'XFSB' */ #define XFS_SB_VERSION_1 1 /* 5.3, 6.0.1, 6.1 */ #define XFS_SB_VERSION_2 2 /* 6.2 - attributes */ #define XFS_SB_VERSION_3 3 /* 6.2 - new inode version */ #define XFS_SB_VERSION_4 4 /* 6.2+ - bitmask version */ #define XFS_SB_VERSION_5 5 /* CRC enabled filesystem */ #define XFS_SB_VERSION_NUMBITS 0x000f #define XFS_SB_VERSION_ALLFBITS 0xfff0 #define XFS_SB_VERSION_ATTRBIT 0x0010 #define XFS_SB_VERSION_NLINKBIT 0x0020 #define XFS_SB_VERSION_QUOTABIT 0x0040 #define XFS_SB_VERSION_ALIGNBIT 0x0080 #define XFS_SB_VERSION_DALIGNBIT 0x0100 #define XFS_SB_VERSION_SHAREDBIT 0x0200 #define XFS_SB_VERSION_LOGV2BIT 0x0400 #define XFS_SB_VERSION_SECTORBIT 0x0800 #define XFS_SB_VERSION_EXTFLGBIT 0x1000 #define XFS_SB_VERSION_DIRV2BIT 0x2000 #define XFS_SB_VERSION_BORGBIT 0x4000 /* ASCII only case-insens. */ #define XFS_SB_VERSION_MOREBITSBIT 0x8000 int xfs_mkfs(struct s_dico *d, char *partition, char *fsoptions, char *mkfslabel, char *mkfsuuid); int xfs_getinfo(struct s_dico *d, char *devname); int xfs_mount(char *partition, char *mntbuf, char *fsbuf, int flags, char *mntinfo); int xfs_get_reqmntopt(char *partition, struct s_strlist *reqopt, struct s_strlist *badopt); int xfs_umount(char *partition, char *mntbuf); int xfs_test(char *devname); int xfs_check_compatibility(u64 compat, u64 ro_compat, u64 incompat, u64 log_incompat); typedef uint32_t xfs_agblock_t; /* blockno in alloc. group */ typedef uint32_t xfs_extlen_t; /* extent length in blocks */ typedef uint32_t xfs_agnumber_t; /* allocation group number */ typedef int32_t xfs_extnum_t; /* # of extents in a file */ typedef int16_t xfs_aextnum_t; /* # extents in an attribute fork */ typedef int64_t xfs_fsize_t; /* bytes in a file */ typedef uint64_t xfs_ufsize_t; /* unsigned bytes in a file */ typedef int32_t xfs_suminfo_t; /* type of bitmap summary info */ typedef int32_t xfs_rtword_t; /* word type for bitmap manipulations */ typedef int64_t xfs_lsn_t; /* log sequence number */ typedef int32_t xfs_tid_t; /* transaction identifier */ typedef uint32_t xfs_dablk_t; /* dir/attr block number (in file) */ typedef uint32_t xfs_dahash_t; /* dir/attr hash value */ typedef uint16_t xfs_prid_t; /* prid_t truncated to 16bits in XFS */ /* * These types are 64 bits on disk but are either 32 or 64 bits in memory. * Disk based types: */ typedef uint64_t xfs_fsblock_t; /* blockno in filesystem (agno|agbno) */ typedef uint64_t xfs_rfsblock_t; /* blockno in filesystem (raw) */ typedef uint64_t xfs_rtblock_t; /* extent (block) in realtime area */ typedef uint64_t xfs_dfiloff_t; /* block number in a file */ typedef uint64_t xfs_dfilblks_t; /* number of blocks in a file */ typedef __s64 xfs_off_t; /* type */ typedef __u64 xfs_ino_t; /* type */ typedef __s64 xfs_daddr_t; /* type */ typedef char * xfs_caddr_t; /* type */ typedef __u32 xfs_dev_t; typedef __u32 xfs_nlink_t; /* * Superblock - in core version. Must match the ondisk version below. * Must be padded to 64 bit alignment. */ struct xfs_sb { uint32_t sb_magicnum; /* magic number == XFS_SB_MAGIC */ uint32_t sb_blocksize; /* logical block size, bytes */ xfs_rfsblock_t sb_dblocks; /* number of data blocks */ xfs_rfsblock_t sb_rblocks; /* number of realtime blocks */ xfs_rtblock_t sb_rextents; /* number of realtime extents */ uuid_t sb_uuid; /* user-visible file system unique id */ xfs_fsblock_t sb_logstart; /* starting block of log if internal */ xfs_ino_t sb_rootino; /* root inode number */ xfs_ino_t sb_rbmino; /* bitmap inode for realtime extents */ xfs_ino_t sb_rsumino; /* summary inode for rt bitmap */ xfs_agblock_t sb_rextsize; /* realtime extent size, blocks */ xfs_agblock_t sb_agblocks; /* size of an allocation group */ xfs_agnumber_t sb_agcount; /* number of allocation groups */ xfs_extlen_t sb_rbmblocks; /* number of rt bitmap blocks */ xfs_extlen_t sb_logblocks; /* number of log blocks */ uint16_t sb_versionnum; /* header version == XFS_SB_VERSION */ uint16_t sb_sectsize; /* volume sector size, bytes */ uint16_t sb_inodesize; /* inode size, bytes */ uint16_t sb_inopblock; /* inodes per block */ char sb_fname[12]; /* file system name */ uint8_t sb_blocklog; /* log2 of sb_blocksize */ uint8_t sb_sectlog; /* log2 of sb_sectsize */ uint8_t sb_inodelog; /* log2 of sb_inodesize */ uint8_t sb_inopblog; /* log2 of sb_inopblock */ uint8_t sb_agblklog; /* log2 of sb_agblocks (rounded up) */ uint8_t sb_rextslog; /* log2 of sb_rextents */ uint8_t sb_inprogress; /* mkfs is in progress, don't mount */ uint8_t sb_imax_pct; /* max % of fs for inode space */ /* statistics */ /* * These fields must remain contiguous. If you really * want to change their layout, make sure you fix the * code in xfs_trans_apply_sb_deltas(). */ uint64_t sb_icount; /* allocated inodes */ uint64_t sb_ifree; /* free inodes */ uint64_t sb_fdblocks; /* free data blocks */ uint64_t sb_frextents; /* free realtime extents */ /* * End contiguous fields. */ xfs_ino_t sb_uquotino; /* user quota inode */ xfs_ino_t sb_gquotino; /* group quota inode */ uint16_t sb_qflags; /* quota flags */ uint8_t sb_flags; /* misc. flags */ uint8_t sb_shared_vn; /* shared version number */ xfs_extlen_t sb_inoalignmt; /* inode chunk alignment, fsblocks */ uint32_t sb_unit; /* stripe or raid unit */ uint32_t sb_width; /* stripe or raid width */ uint8_t sb_dirblklog; /* log2 of dir block size (fsbs) */ uint8_t sb_logsectlog; /* log2 of the log sector size */ uint16_t sb_logsectsize; /* sector size for the log, bytes */ uint32_t sb_logsunit; /* stripe unit size for the log */ uint32_t sb_features2; /* additional feature bits */ /* * bad features2 field as a result of failing to pad the sb structure to * 64 bits. Some machines will be using this field for features2 bits. * Easiest just to mark it bad and not use it for anything else. * * This is not kept up to date in memory; it is always overwritten by * the value in sb_features2 when formatting the incore superblock to * the disk buffer. */ uint32_t sb_bad_features2; /* version 5 superblock fields start here */ /* feature masks */ uint32_t sb_features_compat; uint32_t sb_features_ro_compat; uint32_t sb_features_incompat; uint32_t sb_features_log_incompat; uint32_t sb_crc; /* superblock crc */ xfs_extlen_t sb_spino_align; /* sparse inode chunk alignment */ xfs_ino_t sb_pquotino; /* project quota inode */ xfs_lsn_t sb_lsn; /* last write sequence */ uuid_t sb_meta_uuid; /* metadata file system unique id */ /* must be padded to 64 bit alignment */ }; // XFS features used in XFS version 5 only #define XFS_SB_FEAT_RO_COMPAT_FINOBT (1 << 0) /* free inode btree */ #define XFS_SB_FEAT_RO_COMPAT_RMAPBT (1 << 1) /* reverse map btree */ #define XFS_SB_FEAT_RO_COMPAT_REFLINK (1 << 2) /* reflinked files */ #define XFS_SB_FEAT_RO_COMPAT_INOBTCNT (1 << 3) /* inobt block counts */ #define XFS_SB_FEAT_INCOMPAT_FTYPE (1 << 0) /* filetype in dirent */ #define XFS_SB_FEAT_INCOMPAT_SPINODES (1 << 1) /* sparse inode chunks */ #define XFS_SB_FEAT_INCOMPAT_META_UUID (1 << 2) /* metadata UUID */ #define XFS_SB_FEAT_INCOMPAT_BIGTIME (1 << 3) /* large timestamps */ #define XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR (1 << 4) /* needs xfs_repair */ #define XFS_SB_FEAT_INCOMPAT_NREXT64 (1 << 5) /* large extent counters */ // features supported by the current fsarchiver version #define FSA_XFS_FEATURE_COMPAT_SUPP (u64)(0) #define FSA_XFS_FEATURE_RO_COMPAT_SUPP (u64)(XFS_SB_FEAT_RO_COMPAT_FINOBT|\ XFS_SB_FEAT_RO_COMPAT_RMAPBT|\ XFS_SB_FEAT_RO_COMPAT_REFLINK|\ XFS_SB_FEAT_RO_COMPAT_INOBTCNT) #define FSA_XFS_FEATURE_INCOMPAT_SUPP (u64)(XFS_SB_FEAT_INCOMPAT_FTYPE|\ XFS_SB_FEAT_INCOMPAT_SPINODES|\ XFS_SB_FEAT_INCOMPAT_META_UUID|\ XFS_SB_FEAT_INCOMPAT_BIGTIME|\ XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR|\ XFS_SB_FEAT_INCOMPAT_NREXT64) #define FSA_XFS_FEATURE_LOG_INCOMPAT_SUPP (u64)(0) #endif // __FS_XFS_H__ fsarchiver-0.8.7/src/comp_bzip2.c0000644000175000017500000000372614405605077013622 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include "fsarchiver.h" #include "common.h" #include "comp_bzip2.h" #include "error.h" int compress_block_bzip2(u64 origsize, u64 *compsize, u8 *origbuf, u8 *compbuf, u64 compbufsize, int level) { unsigned int destsize=compbufsize; switch (BZ2_bzBuffToBuffCompress((char*)compbuf, &destsize, (char*)origbuf, origsize, 9, 0, 30)) { case BZ_OK: *compsize=(u64)destsize; return FSAERR_SUCCESS; case BZ_MEM_ERROR: errprintf("BZ2_bzBuffToBuffCompress(): BZIP2 compression failed " "with an out of memory error.\nYou should use a lower " "compression level to reduce the memory requirement.\n"); return FSAERR_ENOMEM; default: return FSAERR_UNKNOWN; } return FSAERR_UNKNOWN; } int uncompress_block_bzip2(u64 compsize, u64 *origsize, u8 *origbuf, u64 origbufsize, u8 *compbuf) { unsigned int destsize=origbufsize; int res; switch ((res=BZ2_bzBuffToBuffDecompress((char*)origbuf, &destsize, (char*)compbuf, compsize, 0, 0))) { case BZ_OK: *origsize=(u64)destsize; return FSAERR_SUCCESS; default: errprintf("BZ2_bzBuffToBuffDecompress() failed, res=%d\n", res); return FSAERR_UNKNOWN; } return FSAERR_UNKNOWN; } fsarchiver-0.8.7/src/oper_save.h0000644000175000017500000000133114405605077013534 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifndef __OPER_SAVE_H__ #define __OPER_SAVE_H__ int oper_save(char *archive, int argc, char **argv, int archtype); #endif // __OPER_SAVE_H__ fsarchiver-0.8.7/src/Makefile.in0000644000175000017500000031144614405612237013454 00000000000000# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ sbin_PROGRAMS = fsarchiver$(EXEEXT) subdir = src ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(sbindir)" PROGRAMS = $(sbin_PROGRAMS) am_fsarchiver_OBJECTS = fsarchiver-fsarchiver.$(OBJEXT) \ fsarchiver-oper_save.$(OBJEXT) \ fsarchiver-oper_restore.$(OBJEXT) \ fsarchiver-oper_probe.$(OBJEXT) \ fsarchiver-thread_archio.$(OBJEXT) \ fsarchiver-archreader.$(OBJEXT) \ fsarchiver-archwriter.$(OBJEXT) fsarchiver-writebuf.$(OBJEXT) \ fsarchiver-archinfo.$(OBJEXT) fsarchiver-thread_comp.$(OBJEXT) \ fsarchiver-comp_gzip.$(OBJEXT) fsarchiver-comp_bzip2.$(OBJEXT) \ fsarchiver-comp_lzma.$(OBJEXT) fsarchiver-comp_lzo.$(OBJEXT) \ fsarchiver-comp_lz4.$(OBJEXT) fsarchiver-comp_zstd.$(OBJEXT) \ fsarchiver-crypto.$(OBJEXT) fsarchiver-fs_ntfs.$(OBJEXT) \ fsarchiver-fs_ext2.$(OBJEXT) fsarchiver-fs_reiserfs.$(OBJEXT) \ fsarchiver-fs_reiser4.$(OBJEXT) fsarchiver-fs_btrfs.$(OBJEXT) \ fsarchiver-fs_xfs.$(OBJEXT) fsarchiver-fs_jfs.$(OBJEXT) \ fsarchiver-fs_vfat.$(OBJEXT) fsarchiver-common.$(OBJEXT) \ fsarchiver-dico.$(OBJEXT) fsarchiver-strdico.$(OBJEXT) \ fsarchiver-dichl.$(OBJEXT) fsarchiver-queue.$(OBJEXT) \ fsarchiver-error.$(OBJEXT) fsarchiver-syncthread.$(OBJEXT) \ fsarchiver-datafile.$(OBJEXT) fsarchiver-strlist.$(OBJEXT) \ fsarchiver-regmulti.$(OBJEXT) fsarchiver-options.$(OBJEXT) \ fsarchiver-logfile.$(OBJEXT) fsarchiver-filesys.$(OBJEXT) \ fsarchiver-devinfo.$(OBJEXT) fsarchiver_OBJECTS = $(am_fsarchiver_OBJECTS) am__DEPENDENCIES_1 = fsarchiver_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) fsarchiver_LINK = $(CCLD) $(fsarchiver_CFLAGS) $(CFLAGS) \ $(fsarchiver_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/fsarchiver-archinfo.Po \ ./$(DEPDIR)/fsarchiver-archreader.Po \ ./$(DEPDIR)/fsarchiver-archwriter.Po \ ./$(DEPDIR)/fsarchiver-common.Po \ ./$(DEPDIR)/fsarchiver-comp_bzip2.Po \ ./$(DEPDIR)/fsarchiver-comp_gzip.Po \ ./$(DEPDIR)/fsarchiver-comp_lz4.Po \ ./$(DEPDIR)/fsarchiver-comp_lzma.Po \ ./$(DEPDIR)/fsarchiver-comp_lzo.Po \ ./$(DEPDIR)/fsarchiver-comp_zstd.Po \ ./$(DEPDIR)/fsarchiver-crypto.Po \ ./$(DEPDIR)/fsarchiver-datafile.Po \ ./$(DEPDIR)/fsarchiver-devinfo.Po \ ./$(DEPDIR)/fsarchiver-dichl.Po ./$(DEPDIR)/fsarchiver-dico.Po \ ./$(DEPDIR)/fsarchiver-error.Po \ ./$(DEPDIR)/fsarchiver-filesys.Po \ ./$(DEPDIR)/fsarchiver-fs_btrfs.Po \ ./$(DEPDIR)/fsarchiver-fs_ext2.Po \ ./$(DEPDIR)/fsarchiver-fs_jfs.Po \ ./$(DEPDIR)/fsarchiver-fs_ntfs.Po \ ./$(DEPDIR)/fsarchiver-fs_reiser4.Po \ ./$(DEPDIR)/fsarchiver-fs_reiserfs.Po \ ./$(DEPDIR)/fsarchiver-fs_vfat.Po \ ./$(DEPDIR)/fsarchiver-fs_xfs.Po \ ./$(DEPDIR)/fsarchiver-fsarchiver.Po \ ./$(DEPDIR)/fsarchiver-logfile.Po \ ./$(DEPDIR)/fsarchiver-oper_probe.Po \ ./$(DEPDIR)/fsarchiver-oper_restore.Po \ ./$(DEPDIR)/fsarchiver-oper_save.Po \ ./$(DEPDIR)/fsarchiver-options.Po \ ./$(DEPDIR)/fsarchiver-queue.Po \ ./$(DEPDIR)/fsarchiver-regmulti.Po \ ./$(DEPDIR)/fsarchiver-strdico.Po \ ./$(DEPDIR)/fsarchiver-strlist.Po \ ./$(DEPDIR)/fsarchiver-syncthread.Po \ ./$(DEPDIR)/fsarchiver-thread_archio.Po \ ./$(DEPDIR)/fsarchiver-thread_comp.Po \ ./$(DEPDIR)/fsarchiver-writebuf.Po am__mv = mv -f AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(fsarchiver_SOURCES) DIST_SOURCES = $(fsarchiver_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BLKID_CFLAGS = @BLKID_CFLAGS@ BLKID_LIBS = @BLKID_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ COM_ERR_CFLAGS = @COM_ERR_CFLAGS@ COM_ERR_LIBS = @COM_ERR_LIBS@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_DEBUG_LEVEL = @DEFAULT_DEBUG_LEVEL@ DEFS = @DEFS@ -D_REENTRANT -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE -D_GNU_SOURCE DEPDIR = @DEPDIR@ E2P_CFLAGS = @E2P_CFLAGS@ E2P_LIBS = @E2P_LIBS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ EXT2FS_CFLAGS = @EXT2FS_CFLAGS@ EXT2FS_LIBS = @EXT2FS_LIBS@ FSARCHIVER_LDFLAGS = @FSARCHIVER_LDFLAGS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LOGDIR = @LOGDIR@ LTLIBOBJS = @LTLIBOBJS@ LZMA_CFLAGS = @LZMA_CFLAGS@ LZMA_LIBS = @LZMA_LIBS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ fsarchiver_SOURCES = fsarchiver.c oper_save.c oper_restore.c oper_probe.c \ thread_archio.c archreader.c archwriter.c writebuf.c archinfo.c \ thread_comp.c comp_gzip.c comp_bzip2.c comp_lzma.c comp_lzo.c comp_lz4.c \ comp_zstd.c crypto.c fs_ntfs.c fs_ext2.c fs_reiserfs.c fs_reiser4.c \ fs_btrfs.c fs_xfs.c fs_jfs.c fs_vfat.c common.c dico.c strdico.c dichl.c \ queue.c error.c syncthread.c datafile.c strlist.c regmulti.c options.c \ logfile.c filesys.c devinfo.c noinst_HEADERS = fsarchiver.h oper_save.h oper_restore.h oper_probe.h \ thread_archio.h archreader.h archwriter.h writebuf.h archinfo.h \ thread_comp.h comp_gzip.h comp_bzip2.h comp_lzma.h comp_lzo.h comp_lz4.h \ comp_zstd.h crypto.h fs_ntfs.h fs_ext2.h fs_reiserfs.h fs_reiser4.h \ fs_btrfs.h fs_xfs.h fs_jfs.h fs_vfat.h common.h dico.h strdico.h dichl.h \ queue.h error.h syncthread.h datafile.h strlist.h regmulti.h options.h \ logfile.h types.h filesys.h devinfo.h fsarchiver_LDADD = -lpthread -lrt \ $(LZMA_LIBS) \ $(EXT2FS_LIBS) \ $(COM_ERR_LIBS) \ $(E2P_LIBS) \ $(BLKID_LIBS) \ $(UUID_LIBS) fsarchiver_CFLAGS = @CFLAGS@ -Wall -std=gnu99 -rdynamic -ggdb \ $(LZMA_CFLAGS) \ $(EXT2FS_CFLAGS) \ $(COM_ERR_CFLAGS) \ $(E2P_CFLAGS) \ $(BLKID_CFLAGS) \ $(UUID_CFLAGS) fsarchiver_LDFLAGS = @FSARCHIVER_LDFLAGS@ MAINTAINERCLEANFILES = Makefile.in all: all-am .SUFFIXES: .SUFFIXES: .c .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ } \ ; done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(sbindir)" && rm -f $$files clean-sbinPROGRAMS: -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS) fsarchiver$(EXEEXT): $(fsarchiver_OBJECTS) $(fsarchiver_DEPENDENCIES) $(EXTRA_fsarchiver_DEPENDENCIES) @rm -f fsarchiver$(EXEEXT) $(AM_V_CCLD)$(fsarchiver_LINK) $(fsarchiver_OBJECTS) $(fsarchiver_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-archinfo.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-archreader.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-archwriter.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-common.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-comp_bzip2.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-comp_gzip.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-comp_lz4.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-comp_lzma.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-comp_lzo.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-comp_zstd.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-crypto.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-datafile.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-devinfo.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-dichl.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-dico.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-error.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-filesys.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-fs_btrfs.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-fs_ext2.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-fs_jfs.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-fs_ntfs.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-fs_reiser4.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-fs_reiserfs.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-fs_vfat.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-fs_xfs.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-fsarchiver.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-logfile.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-oper_probe.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-oper_restore.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-oper_save.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-options.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-queue.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-regmulti.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-strdico.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-strlist.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-syncthread.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-thread_archio.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-thread_comp.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsarchiver-writebuf.Po@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` fsarchiver-fsarchiver.o: fsarchiver.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-fsarchiver.o -MD -MP -MF $(DEPDIR)/fsarchiver-fsarchiver.Tpo -c -o fsarchiver-fsarchiver.o `test -f 'fsarchiver.c' || echo '$(srcdir)/'`fsarchiver.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-fsarchiver.Tpo $(DEPDIR)/fsarchiver-fsarchiver.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsarchiver.c' object='fsarchiver-fsarchiver.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-fsarchiver.o `test -f 'fsarchiver.c' || echo '$(srcdir)/'`fsarchiver.c fsarchiver-fsarchiver.obj: fsarchiver.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-fsarchiver.obj -MD -MP -MF $(DEPDIR)/fsarchiver-fsarchiver.Tpo -c -o fsarchiver-fsarchiver.obj `if test -f 'fsarchiver.c'; then $(CYGPATH_W) 'fsarchiver.c'; else $(CYGPATH_W) '$(srcdir)/fsarchiver.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-fsarchiver.Tpo $(DEPDIR)/fsarchiver-fsarchiver.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fsarchiver.c' object='fsarchiver-fsarchiver.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-fsarchiver.obj `if test -f 'fsarchiver.c'; then $(CYGPATH_W) 'fsarchiver.c'; else $(CYGPATH_W) '$(srcdir)/fsarchiver.c'; fi` fsarchiver-oper_save.o: oper_save.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-oper_save.o -MD -MP -MF $(DEPDIR)/fsarchiver-oper_save.Tpo -c -o fsarchiver-oper_save.o `test -f 'oper_save.c' || echo '$(srcdir)/'`oper_save.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-oper_save.Tpo $(DEPDIR)/fsarchiver-oper_save.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='oper_save.c' object='fsarchiver-oper_save.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-oper_save.o `test -f 'oper_save.c' || echo '$(srcdir)/'`oper_save.c fsarchiver-oper_save.obj: oper_save.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-oper_save.obj -MD -MP -MF $(DEPDIR)/fsarchiver-oper_save.Tpo -c -o fsarchiver-oper_save.obj `if test -f 'oper_save.c'; then $(CYGPATH_W) 'oper_save.c'; else $(CYGPATH_W) '$(srcdir)/oper_save.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-oper_save.Tpo $(DEPDIR)/fsarchiver-oper_save.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='oper_save.c' object='fsarchiver-oper_save.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-oper_save.obj `if test -f 'oper_save.c'; then $(CYGPATH_W) 'oper_save.c'; else $(CYGPATH_W) '$(srcdir)/oper_save.c'; fi` fsarchiver-oper_restore.o: oper_restore.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-oper_restore.o -MD -MP -MF $(DEPDIR)/fsarchiver-oper_restore.Tpo -c -o fsarchiver-oper_restore.o `test -f 'oper_restore.c' || echo '$(srcdir)/'`oper_restore.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-oper_restore.Tpo $(DEPDIR)/fsarchiver-oper_restore.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='oper_restore.c' object='fsarchiver-oper_restore.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-oper_restore.o `test -f 'oper_restore.c' || echo '$(srcdir)/'`oper_restore.c fsarchiver-oper_restore.obj: oper_restore.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-oper_restore.obj -MD -MP -MF $(DEPDIR)/fsarchiver-oper_restore.Tpo -c -o fsarchiver-oper_restore.obj `if test -f 'oper_restore.c'; then $(CYGPATH_W) 'oper_restore.c'; else $(CYGPATH_W) '$(srcdir)/oper_restore.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-oper_restore.Tpo $(DEPDIR)/fsarchiver-oper_restore.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='oper_restore.c' object='fsarchiver-oper_restore.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-oper_restore.obj `if test -f 'oper_restore.c'; then $(CYGPATH_W) 'oper_restore.c'; else $(CYGPATH_W) '$(srcdir)/oper_restore.c'; fi` fsarchiver-oper_probe.o: oper_probe.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-oper_probe.o -MD -MP -MF $(DEPDIR)/fsarchiver-oper_probe.Tpo -c -o fsarchiver-oper_probe.o `test -f 'oper_probe.c' || echo '$(srcdir)/'`oper_probe.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-oper_probe.Tpo $(DEPDIR)/fsarchiver-oper_probe.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='oper_probe.c' object='fsarchiver-oper_probe.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-oper_probe.o `test -f 'oper_probe.c' || echo '$(srcdir)/'`oper_probe.c fsarchiver-oper_probe.obj: oper_probe.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-oper_probe.obj -MD -MP -MF $(DEPDIR)/fsarchiver-oper_probe.Tpo -c -o fsarchiver-oper_probe.obj `if test -f 'oper_probe.c'; then $(CYGPATH_W) 'oper_probe.c'; else $(CYGPATH_W) '$(srcdir)/oper_probe.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-oper_probe.Tpo $(DEPDIR)/fsarchiver-oper_probe.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='oper_probe.c' object='fsarchiver-oper_probe.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-oper_probe.obj `if test -f 'oper_probe.c'; then $(CYGPATH_W) 'oper_probe.c'; else $(CYGPATH_W) '$(srcdir)/oper_probe.c'; fi` fsarchiver-thread_archio.o: thread_archio.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-thread_archio.o -MD -MP -MF $(DEPDIR)/fsarchiver-thread_archio.Tpo -c -o fsarchiver-thread_archio.o `test -f 'thread_archio.c' || echo '$(srcdir)/'`thread_archio.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-thread_archio.Tpo $(DEPDIR)/fsarchiver-thread_archio.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='thread_archio.c' object='fsarchiver-thread_archio.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-thread_archio.o `test -f 'thread_archio.c' || echo '$(srcdir)/'`thread_archio.c fsarchiver-thread_archio.obj: thread_archio.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-thread_archio.obj -MD -MP -MF $(DEPDIR)/fsarchiver-thread_archio.Tpo -c -o fsarchiver-thread_archio.obj `if test -f 'thread_archio.c'; then $(CYGPATH_W) 'thread_archio.c'; else $(CYGPATH_W) '$(srcdir)/thread_archio.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-thread_archio.Tpo $(DEPDIR)/fsarchiver-thread_archio.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='thread_archio.c' object='fsarchiver-thread_archio.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-thread_archio.obj `if test -f 'thread_archio.c'; then $(CYGPATH_W) 'thread_archio.c'; else $(CYGPATH_W) '$(srcdir)/thread_archio.c'; fi` fsarchiver-archreader.o: archreader.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-archreader.o -MD -MP -MF $(DEPDIR)/fsarchiver-archreader.Tpo -c -o fsarchiver-archreader.o `test -f 'archreader.c' || echo '$(srcdir)/'`archreader.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-archreader.Tpo $(DEPDIR)/fsarchiver-archreader.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='archreader.c' object='fsarchiver-archreader.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-archreader.o `test -f 'archreader.c' || echo '$(srcdir)/'`archreader.c fsarchiver-archreader.obj: archreader.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-archreader.obj -MD -MP -MF $(DEPDIR)/fsarchiver-archreader.Tpo -c -o fsarchiver-archreader.obj `if test -f 'archreader.c'; then $(CYGPATH_W) 'archreader.c'; else $(CYGPATH_W) '$(srcdir)/archreader.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-archreader.Tpo $(DEPDIR)/fsarchiver-archreader.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='archreader.c' object='fsarchiver-archreader.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-archreader.obj `if test -f 'archreader.c'; then $(CYGPATH_W) 'archreader.c'; else $(CYGPATH_W) '$(srcdir)/archreader.c'; fi` fsarchiver-archwriter.o: archwriter.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-archwriter.o -MD -MP -MF $(DEPDIR)/fsarchiver-archwriter.Tpo -c -o fsarchiver-archwriter.o `test -f 'archwriter.c' || echo '$(srcdir)/'`archwriter.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-archwriter.Tpo $(DEPDIR)/fsarchiver-archwriter.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='archwriter.c' object='fsarchiver-archwriter.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-archwriter.o `test -f 'archwriter.c' || echo '$(srcdir)/'`archwriter.c fsarchiver-archwriter.obj: archwriter.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-archwriter.obj -MD -MP -MF $(DEPDIR)/fsarchiver-archwriter.Tpo -c -o fsarchiver-archwriter.obj `if test -f 'archwriter.c'; then $(CYGPATH_W) 'archwriter.c'; else $(CYGPATH_W) '$(srcdir)/archwriter.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-archwriter.Tpo $(DEPDIR)/fsarchiver-archwriter.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='archwriter.c' object='fsarchiver-archwriter.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-archwriter.obj `if test -f 'archwriter.c'; then $(CYGPATH_W) 'archwriter.c'; else $(CYGPATH_W) '$(srcdir)/archwriter.c'; fi` fsarchiver-writebuf.o: writebuf.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-writebuf.o -MD -MP -MF $(DEPDIR)/fsarchiver-writebuf.Tpo -c -o fsarchiver-writebuf.o `test -f 'writebuf.c' || echo '$(srcdir)/'`writebuf.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-writebuf.Tpo $(DEPDIR)/fsarchiver-writebuf.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='writebuf.c' object='fsarchiver-writebuf.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-writebuf.o `test -f 'writebuf.c' || echo '$(srcdir)/'`writebuf.c fsarchiver-writebuf.obj: writebuf.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-writebuf.obj -MD -MP -MF $(DEPDIR)/fsarchiver-writebuf.Tpo -c -o fsarchiver-writebuf.obj `if test -f 'writebuf.c'; then $(CYGPATH_W) 'writebuf.c'; else $(CYGPATH_W) '$(srcdir)/writebuf.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-writebuf.Tpo $(DEPDIR)/fsarchiver-writebuf.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='writebuf.c' object='fsarchiver-writebuf.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-writebuf.obj `if test -f 'writebuf.c'; then $(CYGPATH_W) 'writebuf.c'; else $(CYGPATH_W) '$(srcdir)/writebuf.c'; fi` fsarchiver-archinfo.o: archinfo.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-archinfo.o -MD -MP -MF $(DEPDIR)/fsarchiver-archinfo.Tpo -c -o fsarchiver-archinfo.o `test -f 'archinfo.c' || echo '$(srcdir)/'`archinfo.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-archinfo.Tpo $(DEPDIR)/fsarchiver-archinfo.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='archinfo.c' object='fsarchiver-archinfo.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-archinfo.o `test -f 'archinfo.c' || echo '$(srcdir)/'`archinfo.c fsarchiver-archinfo.obj: archinfo.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-archinfo.obj -MD -MP -MF $(DEPDIR)/fsarchiver-archinfo.Tpo -c -o fsarchiver-archinfo.obj `if test -f 'archinfo.c'; then $(CYGPATH_W) 'archinfo.c'; else $(CYGPATH_W) '$(srcdir)/archinfo.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-archinfo.Tpo $(DEPDIR)/fsarchiver-archinfo.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='archinfo.c' object='fsarchiver-archinfo.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-archinfo.obj `if test -f 'archinfo.c'; then $(CYGPATH_W) 'archinfo.c'; else $(CYGPATH_W) '$(srcdir)/archinfo.c'; fi` fsarchiver-thread_comp.o: thread_comp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-thread_comp.o -MD -MP -MF $(DEPDIR)/fsarchiver-thread_comp.Tpo -c -o fsarchiver-thread_comp.o `test -f 'thread_comp.c' || echo '$(srcdir)/'`thread_comp.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-thread_comp.Tpo $(DEPDIR)/fsarchiver-thread_comp.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='thread_comp.c' object='fsarchiver-thread_comp.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-thread_comp.o `test -f 'thread_comp.c' || echo '$(srcdir)/'`thread_comp.c fsarchiver-thread_comp.obj: thread_comp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-thread_comp.obj -MD -MP -MF $(DEPDIR)/fsarchiver-thread_comp.Tpo -c -o fsarchiver-thread_comp.obj `if test -f 'thread_comp.c'; then $(CYGPATH_W) 'thread_comp.c'; else $(CYGPATH_W) '$(srcdir)/thread_comp.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-thread_comp.Tpo $(DEPDIR)/fsarchiver-thread_comp.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='thread_comp.c' object='fsarchiver-thread_comp.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-thread_comp.obj `if test -f 'thread_comp.c'; then $(CYGPATH_W) 'thread_comp.c'; else $(CYGPATH_W) '$(srcdir)/thread_comp.c'; fi` fsarchiver-comp_gzip.o: comp_gzip.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-comp_gzip.o -MD -MP -MF $(DEPDIR)/fsarchiver-comp_gzip.Tpo -c -o fsarchiver-comp_gzip.o `test -f 'comp_gzip.c' || echo '$(srcdir)/'`comp_gzip.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-comp_gzip.Tpo $(DEPDIR)/fsarchiver-comp_gzip.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='comp_gzip.c' object='fsarchiver-comp_gzip.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-comp_gzip.o `test -f 'comp_gzip.c' || echo '$(srcdir)/'`comp_gzip.c fsarchiver-comp_gzip.obj: comp_gzip.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-comp_gzip.obj -MD -MP -MF $(DEPDIR)/fsarchiver-comp_gzip.Tpo -c -o fsarchiver-comp_gzip.obj `if test -f 'comp_gzip.c'; then $(CYGPATH_W) 'comp_gzip.c'; else $(CYGPATH_W) '$(srcdir)/comp_gzip.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-comp_gzip.Tpo $(DEPDIR)/fsarchiver-comp_gzip.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='comp_gzip.c' object='fsarchiver-comp_gzip.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-comp_gzip.obj `if test -f 'comp_gzip.c'; then $(CYGPATH_W) 'comp_gzip.c'; else $(CYGPATH_W) '$(srcdir)/comp_gzip.c'; fi` fsarchiver-comp_bzip2.o: comp_bzip2.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-comp_bzip2.o -MD -MP -MF $(DEPDIR)/fsarchiver-comp_bzip2.Tpo -c -o fsarchiver-comp_bzip2.o `test -f 'comp_bzip2.c' || echo '$(srcdir)/'`comp_bzip2.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-comp_bzip2.Tpo $(DEPDIR)/fsarchiver-comp_bzip2.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='comp_bzip2.c' object='fsarchiver-comp_bzip2.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-comp_bzip2.o `test -f 'comp_bzip2.c' || echo '$(srcdir)/'`comp_bzip2.c fsarchiver-comp_bzip2.obj: comp_bzip2.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-comp_bzip2.obj -MD -MP -MF $(DEPDIR)/fsarchiver-comp_bzip2.Tpo -c -o fsarchiver-comp_bzip2.obj `if test -f 'comp_bzip2.c'; then $(CYGPATH_W) 'comp_bzip2.c'; else $(CYGPATH_W) '$(srcdir)/comp_bzip2.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-comp_bzip2.Tpo $(DEPDIR)/fsarchiver-comp_bzip2.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='comp_bzip2.c' object='fsarchiver-comp_bzip2.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-comp_bzip2.obj `if test -f 'comp_bzip2.c'; then $(CYGPATH_W) 'comp_bzip2.c'; else $(CYGPATH_W) '$(srcdir)/comp_bzip2.c'; fi` fsarchiver-comp_lzma.o: comp_lzma.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-comp_lzma.o -MD -MP -MF $(DEPDIR)/fsarchiver-comp_lzma.Tpo -c -o fsarchiver-comp_lzma.o `test -f 'comp_lzma.c' || echo '$(srcdir)/'`comp_lzma.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-comp_lzma.Tpo $(DEPDIR)/fsarchiver-comp_lzma.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='comp_lzma.c' object='fsarchiver-comp_lzma.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-comp_lzma.o `test -f 'comp_lzma.c' || echo '$(srcdir)/'`comp_lzma.c fsarchiver-comp_lzma.obj: comp_lzma.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-comp_lzma.obj -MD -MP -MF $(DEPDIR)/fsarchiver-comp_lzma.Tpo -c -o fsarchiver-comp_lzma.obj `if test -f 'comp_lzma.c'; then $(CYGPATH_W) 'comp_lzma.c'; else $(CYGPATH_W) '$(srcdir)/comp_lzma.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-comp_lzma.Tpo $(DEPDIR)/fsarchiver-comp_lzma.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='comp_lzma.c' object='fsarchiver-comp_lzma.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-comp_lzma.obj `if test -f 'comp_lzma.c'; then $(CYGPATH_W) 'comp_lzma.c'; else $(CYGPATH_W) '$(srcdir)/comp_lzma.c'; fi` fsarchiver-comp_lzo.o: comp_lzo.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-comp_lzo.o -MD -MP -MF $(DEPDIR)/fsarchiver-comp_lzo.Tpo -c -o fsarchiver-comp_lzo.o `test -f 'comp_lzo.c' || echo '$(srcdir)/'`comp_lzo.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-comp_lzo.Tpo $(DEPDIR)/fsarchiver-comp_lzo.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='comp_lzo.c' object='fsarchiver-comp_lzo.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-comp_lzo.o `test -f 'comp_lzo.c' || echo '$(srcdir)/'`comp_lzo.c fsarchiver-comp_lzo.obj: comp_lzo.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-comp_lzo.obj -MD -MP -MF $(DEPDIR)/fsarchiver-comp_lzo.Tpo -c -o fsarchiver-comp_lzo.obj `if test -f 'comp_lzo.c'; then $(CYGPATH_W) 'comp_lzo.c'; else $(CYGPATH_W) '$(srcdir)/comp_lzo.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-comp_lzo.Tpo $(DEPDIR)/fsarchiver-comp_lzo.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='comp_lzo.c' object='fsarchiver-comp_lzo.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-comp_lzo.obj `if test -f 'comp_lzo.c'; then $(CYGPATH_W) 'comp_lzo.c'; else $(CYGPATH_W) '$(srcdir)/comp_lzo.c'; fi` fsarchiver-comp_lz4.o: comp_lz4.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-comp_lz4.o -MD -MP -MF $(DEPDIR)/fsarchiver-comp_lz4.Tpo -c -o fsarchiver-comp_lz4.o `test -f 'comp_lz4.c' || echo '$(srcdir)/'`comp_lz4.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-comp_lz4.Tpo $(DEPDIR)/fsarchiver-comp_lz4.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='comp_lz4.c' object='fsarchiver-comp_lz4.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-comp_lz4.o `test -f 'comp_lz4.c' || echo '$(srcdir)/'`comp_lz4.c fsarchiver-comp_lz4.obj: comp_lz4.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-comp_lz4.obj -MD -MP -MF $(DEPDIR)/fsarchiver-comp_lz4.Tpo -c -o fsarchiver-comp_lz4.obj `if test -f 'comp_lz4.c'; then $(CYGPATH_W) 'comp_lz4.c'; else $(CYGPATH_W) '$(srcdir)/comp_lz4.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-comp_lz4.Tpo $(DEPDIR)/fsarchiver-comp_lz4.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='comp_lz4.c' object='fsarchiver-comp_lz4.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-comp_lz4.obj `if test -f 'comp_lz4.c'; then $(CYGPATH_W) 'comp_lz4.c'; else $(CYGPATH_W) '$(srcdir)/comp_lz4.c'; fi` fsarchiver-comp_zstd.o: comp_zstd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-comp_zstd.o -MD -MP -MF $(DEPDIR)/fsarchiver-comp_zstd.Tpo -c -o fsarchiver-comp_zstd.o `test -f 'comp_zstd.c' || echo '$(srcdir)/'`comp_zstd.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-comp_zstd.Tpo $(DEPDIR)/fsarchiver-comp_zstd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='comp_zstd.c' object='fsarchiver-comp_zstd.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-comp_zstd.o `test -f 'comp_zstd.c' || echo '$(srcdir)/'`comp_zstd.c fsarchiver-comp_zstd.obj: comp_zstd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-comp_zstd.obj -MD -MP -MF $(DEPDIR)/fsarchiver-comp_zstd.Tpo -c -o fsarchiver-comp_zstd.obj `if test -f 'comp_zstd.c'; then $(CYGPATH_W) 'comp_zstd.c'; else $(CYGPATH_W) '$(srcdir)/comp_zstd.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-comp_zstd.Tpo $(DEPDIR)/fsarchiver-comp_zstd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='comp_zstd.c' object='fsarchiver-comp_zstd.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-comp_zstd.obj `if test -f 'comp_zstd.c'; then $(CYGPATH_W) 'comp_zstd.c'; else $(CYGPATH_W) '$(srcdir)/comp_zstd.c'; fi` fsarchiver-crypto.o: crypto.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-crypto.o -MD -MP -MF $(DEPDIR)/fsarchiver-crypto.Tpo -c -o fsarchiver-crypto.o `test -f 'crypto.c' || echo '$(srcdir)/'`crypto.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-crypto.Tpo $(DEPDIR)/fsarchiver-crypto.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='crypto.c' object='fsarchiver-crypto.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-crypto.o `test -f 'crypto.c' || echo '$(srcdir)/'`crypto.c fsarchiver-crypto.obj: crypto.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-crypto.obj -MD -MP -MF $(DEPDIR)/fsarchiver-crypto.Tpo -c -o fsarchiver-crypto.obj `if test -f 'crypto.c'; then $(CYGPATH_W) 'crypto.c'; else $(CYGPATH_W) '$(srcdir)/crypto.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-crypto.Tpo $(DEPDIR)/fsarchiver-crypto.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='crypto.c' object='fsarchiver-crypto.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-crypto.obj `if test -f 'crypto.c'; then $(CYGPATH_W) 'crypto.c'; else $(CYGPATH_W) '$(srcdir)/crypto.c'; fi` fsarchiver-fs_ntfs.o: fs_ntfs.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-fs_ntfs.o -MD -MP -MF $(DEPDIR)/fsarchiver-fs_ntfs.Tpo -c -o fsarchiver-fs_ntfs.o `test -f 'fs_ntfs.c' || echo '$(srcdir)/'`fs_ntfs.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-fs_ntfs.Tpo $(DEPDIR)/fsarchiver-fs_ntfs.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fs_ntfs.c' object='fsarchiver-fs_ntfs.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-fs_ntfs.o `test -f 'fs_ntfs.c' || echo '$(srcdir)/'`fs_ntfs.c fsarchiver-fs_ntfs.obj: fs_ntfs.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-fs_ntfs.obj -MD -MP -MF $(DEPDIR)/fsarchiver-fs_ntfs.Tpo -c -o fsarchiver-fs_ntfs.obj `if test -f 'fs_ntfs.c'; then $(CYGPATH_W) 'fs_ntfs.c'; else $(CYGPATH_W) '$(srcdir)/fs_ntfs.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-fs_ntfs.Tpo $(DEPDIR)/fsarchiver-fs_ntfs.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fs_ntfs.c' object='fsarchiver-fs_ntfs.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-fs_ntfs.obj `if test -f 'fs_ntfs.c'; then $(CYGPATH_W) 'fs_ntfs.c'; else $(CYGPATH_W) '$(srcdir)/fs_ntfs.c'; fi` fsarchiver-fs_ext2.o: fs_ext2.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-fs_ext2.o -MD -MP -MF $(DEPDIR)/fsarchiver-fs_ext2.Tpo -c -o fsarchiver-fs_ext2.o `test -f 'fs_ext2.c' || echo '$(srcdir)/'`fs_ext2.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-fs_ext2.Tpo $(DEPDIR)/fsarchiver-fs_ext2.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fs_ext2.c' object='fsarchiver-fs_ext2.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-fs_ext2.o `test -f 'fs_ext2.c' || echo '$(srcdir)/'`fs_ext2.c fsarchiver-fs_ext2.obj: fs_ext2.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-fs_ext2.obj -MD -MP -MF $(DEPDIR)/fsarchiver-fs_ext2.Tpo -c -o fsarchiver-fs_ext2.obj `if test -f 'fs_ext2.c'; then $(CYGPATH_W) 'fs_ext2.c'; else $(CYGPATH_W) '$(srcdir)/fs_ext2.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-fs_ext2.Tpo $(DEPDIR)/fsarchiver-fs_ext2.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fs_ext2.c' object='fsarchiver-fs_ext2.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-fs_ext2.obj `if test -f 'fs_ext2.c'; then $(CYGPATH_W) 'fs_ext2.c'; else $(CYGPATH_W) '$(srcdir)/fs_ext2.c'; fi` fsarchiver-fs_reiserfs.o: fs_reiserfs.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-fs_reiserfs.o -MD -MP -MF $(DEPDIR)/fsarchiver-fs_reiserfs.Tpo -c -o fsarchiver-fs_reiserfs.o `test -f 'fs_reiserfs.c' || echo '$(srcdir)/'`fs_reiserfs.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-fs_reiserfs.Tpo $(DEPDIR)/fsarchiver-fs_reiserfs.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fs_reiserfs.c' object='fsarchiver-fs_reiserfs.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-fs_reiserfs.o `test -f 'fs_reiserfs.c' || echo '$(srcdir)/'`fs_reiserfs.c fsarchiver-fs_reiserfs.obj: fs_reiserfs.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-fs_reiserfs.obj -MD -MP -MF $(DEPDIR)/fsarchiver-fs_reiserfs.Tpo -c -o fsarchiver-fs_reiserfs.obj `if test -f 'fs_reiserfs.c'; then $(CYGPATH_W) 'fs_reiserfs.c'; else $(CYGPATH_W) '$(srcdir)/fs_reiserfs.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-fs_reiserfs.Tpo $(DEPDIR)/fsarchiver-fs_reiserfs.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fs_reiserfs.c' object='fsarchiver-fs_reiserfs.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-fs_reiserfs.obj `if test -f 'fs_reiserfs.c'; then $(CYGPATH_W) 'fs_reiserfs.c'; else $(CYGPATH_W) '$(srcdir)/fs_reiserfs.c'; fi` fsarchiver-fs_reiser4.o: fs_reiser4.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-fs_reiser4.o -MD -MP -MF $(DEPDIR)/fsarchiver-fs_reiser4.Tpo -c -o fsarchiver-fs_reiser4.o `test -f 'fs_reiser4.c' || echo '$(srcdir)/'`fs_reiser4.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-fs_reiser4.Tpo $(DEPDIR)/fsarchiver-fs_reiser4.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fs_reiser4.c' object='fsarchiver-fs_reiser4.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-fs_reiser4.o `test -f 'fs_reiser4.c' || echo '$(srcdir)/'`fs_reiser4.c fsarchiver-fs_reiser4.obj: fs_reiser4.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-fs_reiser4.obj -MD -MP -MF $(DEPDIR)/fsarchiver-fs_reiser4.Tpo -c -o fsarchiver-fs_reiser4.obj `if test -f 'fs_reiser4.c'; then $(CYGPATH_W) 'fs_reiser4.c'; else $(CYGPATH_W) '$(srcdir)/fs_reiser4.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-fs_reiser4.Tpo $(DEPDIR)/fsarchiver-fs_reiser4.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fs_reiser4.c' object='fsarchiver-fs_reiser4.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-fs_reiser4.obj `if test -f 'fs_reiser4.c'; then $(CYGPATH_W) 'fs_reiser4.c'; else $(CYGPATH_W) '$(srcdir)/fs_reiser4.c'; fi` fsarchiver-fs_btrfs.o: fs_btrfs.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-fs_btrfs.o -MD -MP -MF $(DEPDIR)/fsarchiver-fs_btrfs.Tpo -c -o fsarchiver-fs_btrfs.o `test -f 'fs_btrfs.c' || echo '$(srcdir)/'`fs_btrfs.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-fs_btrfs.Tpo $(DEPDIR)/fsarchiver-fs_btrfs.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fs_btrfs.c' object='fsarchiver-fs_btrfs.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-fs_btrfs.o `test -f 'fs_btrfs.c' || echo '$(srcdir)/'`fs_btrfs.c fsarchiver-fs_btrfs.obj: fs_btrfs.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-fs_btrfs.obj -MD -MP -MF $(DEPDIR)/fsarchiver-fs_btrfs.Tpo -c -o fsarchiver-fs_btrfs.obj `if test -f 'fs_btrfs.c'; then $(CYGPATH_W) 'fs_btrfs.c'; else $(CYGPATH_W) '$(srcdir)/fs_btrfs.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-fs_btrfs.Tpo $(DEPDIR)/fsarchiver-fs_btrfs.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fs_btrfs.c' object='fsarchiver-fs_btrfs.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-fs_btrfs.obj `if test -f 'fs_btrfs.c'; then $(CYGPATH_W) 'fs_btrfs.c'; else $(CYGPATH_W) '$(srcdir)/fs_btrfs.c'; fi` fsarchiver-fs_xfs.o: fs_xfs.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-fs_xfs.o -MD -MP -MF $(DEPDIR)/fsarchiver-fs_xfs.Tpo -c -o fsarchiver-fs_xfs.o `test -f 'fs_xfs.c' || echo '$(srcdir)/'`fs_xfs.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-fs_xfs.Tpo $(DEPDIR)/fsarchiver-fs_xfs.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fs_xfs.c' object='fsarchiver-fs_xfs.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-fs_xfs.o `test -f 'fs_xfs.c' || echo '$(srcdir)/'`fs_xfs.c fsarchiver-fs_xfs.obj: fs_xfs.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-fs_xfs.obj -MD -MP -MF $(DEPDIR)/fsarchiver-fs_xfs.Tpo -c -o fsarchiver-fs_xfs.obj `if test -f 'fs_xfs.c'; then $(CYGPATH_W) 'fs_xfs.c'; else $(CYGPATH_W) '$(srcdir)/fs_xfs.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-fs_xfs.Tpo $(DEPDIR)/fsarchiver-fs_xfs.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fs_xfs.c' object='fsarchiver-fs_xfs.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-fs_xfs.obj `if test -f 'fs_xfs.c'; then $(CYGPATH_W) 'fs_xfs.c'; else $(CYGPATH_W) '$(srcdir)/fs_xfs.c'; fi` fsarchiver-fs_jfs.o: fs_jfs.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-fs_jfs.o -MD -MP -MF $(DEPDIR)/fsarchiver-fs_jfs.Tpo -c -o fsarchiver-fs_jfs.o `test -f 'fs_jfs.c' || echo '$(srcdir)/'`fs_jfs.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-fs_jfs.Tpo $(DEPDIR)/fsarchiver-fs_jfs.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fs_jfs.c' object='fsarchiver-fs_jfs.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-fs_jfs.o `test -f 'fs_jfs.c' || echo '$(srcdir)/'`fs_jfs.c fsarchiver-fs_jfs.obj: fs_jfs.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-fs_jfs.obj -MD -MP -MF $(DEPDIR)/fsarchiver-fs_jfs.Tpo -c -o fsarchiver-fs_jfs.obj `if test -f 'fs_jfs.c'; then $(CYGPATH_W) 'fs_jfs.c'; else $(CYGPATH_W) '$(srcdir)/fs_jfs.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-fs_jfs.Tpo $(DEPDIR)/fsarchiver-fs_jfs.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fs_jfs.c' object='fsarchiver-fs_jfs.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-fs_jfs.obj `if test -f 'fs_jfs.c'; then $(CYGPATH_W) 'fs_jfs.c'; else $(CYGPATH_W) '$(srcdir)/fs_jfs.c'; fi` fsarchiver-fs_vfat.o: fs_vfat.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-fs_vfat.o -MD -MP -MF $(DEPDIR)/fsarchiver-fs_vfat.Tpo -c -o fsarchiver-fs_vfat.o `test -f 'fs_vfat.c' || echo '$(srcdir)/'`fs_vfat.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-fs_vfat.Tpo $(DEPDIR)/fsarchiver-fs_vfat.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fs_vfat.c' object='fsarchiver-fs_vfat.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-fs_vfat.o `test -f 'fs_vfat.c' || echo '$(srcdir)/'`fs_vfat.c fsarchiver-fs_vfat.obj: fs_vfat.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-fs_vfat.obj -MD -MP -MF $(DEPDIR)/fsarchiver-fs_vfat.Tpo -c -o fsarchiver-fs_vfat.obj `if test -f 'fs_vfat.c'; then $(CYGPATH_W) 'fs_vfat.c'; else $(CYGPATH_W) '$(srcdir)/fs_vfat.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-fs_vfat.Tpo $(DEPDIR)/fsarchiver-fs_vfat.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fs_vfat.c' object='fsarchiver-fs_vfat.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-fs_vfat.obj `if test -f 'fs_vfat.c'; then $(CYGPATH_W) 'fs_vfat.c'; else $(CYGPATH_W) '$(srcdir)/fs_vfat.c'; fi` fsarchiver-common.o: common.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-common.o -MD -MP -MF $(DEPDIR)/fsarchiver-common.Tpo -c -o fsarchiver-common.o `test -f 'common.c' || echo '$(srcdir)/'`common.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-common.Tpo $(DEPDIR)/fsarchiver-common.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common.c' object='fsarchiver-common.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-common.o `test -f 'common.c' || echo '$(srcdir)/'`common.c fsarchiver-common.obj: common.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-common.obj -MD -MP -MF $(DEPDIR)/fsarchiver-common.Tpo -c -o fsarchiver-common.obj `if test -f 'common.c'; then $(CYGPATH_W) 'common.c'; else $(CYGPATH_W) '$(srcdir)/common.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-common.Tpo $(DEPDIR)/fsarchiver-common.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common.c' object='fsarchiver-common.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-common.obj `if test -f 'common.c'; then $(CYGPATH_W) 'common.c'; else $(CYGPATH_W) '$(srcdir)/common.c'; fi` fsarchiver-dico.o: dico.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-dico.o -MD -MP -MF $(DEPDIR)/fsarchiver-dico.Tpo -c -o fsarchiver-dico.o `test -f 'dico.c' || echo '$(srcdir)/'`dico.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-dico.Tpo $(DEPDIR)/fsarchiver-dico.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dico.c' object='fsarchiver-dico.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-dico.o `test -f 'dico.c' || echo '$(srcdir)/'`dico.c fsarchiver-dico.obj: dico.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-dico.obj -MD -MP -MF $(DEPDIR)/fsarchiver-dico.Tpo -c -o fsarchiver-dico.obj `if test -f 'dico.c'; then $(CYGPATH_W) 'dico.c'; else $(CYGPATH_W) '$(srcdir)/dico.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-dico.Tpo $(DEPDIR)/fsarchiver-dico.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dico.c' object='fsarchiver-dico.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-dico.obj `if test -f 'dico.c'; then $(CYGPATH_W) 'dico.c'; else $(CYGPATH_W) '$(srcdir)/dico.c'; fi` fsarchiver-strdico.o: strdico.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-strdico.o -MD -MP -MF $(DEPDIR)/fsarchiver-strdico.Tpo -c -o fsarchiver-strdico.o `test -f 'strdico.c' || echo '$(srcdir)/'`strdico.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-strdico.Tpo $(DEPDIR)/fsarchiver-strdico.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='strdico.c' object='fsarchiver-strdico.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-strdico.o `test -f 'strdico.c' || echo '$(srcdir)/'`strdico.c fsarchiver-strdico.obj: strdico.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-strdico.obj -MD -MP -MF $(DEPDIR)/fsarchiver-strdico.Tpo -c -o fsarchiver-strdico.obj `if test -f 'strdico.c'; then $(CYGPATH_W) 'strdico.c'; else $(CYGPATH_W) '$(srcdir)/strdico.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-strdico.Tpo $(DEPDIR)/fsarchiver-strdico.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='strdico.c' object='fsarchiver-strdico.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-strdico.obj `if test -f 'strdico.c'; then $(CYGPATH_W) 'strdico.c'; else $(CYGPATH_W) '$(srcdir)/strdico.c'; fi` fsarchiver-dichl.o: dichl.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-dichl.o -MD -MP -MF $(DEPDIR)/fsarchiver-dichl.Tpo -c -o fsarchiver-dichl.o `test -f 'dichl.c' || echo '$(srcdir)/'`dichl.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-dichl.Tpo $(DEPDIR)/fsarchiver-dichl.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dichl.c' object='fsarchiver-dichl.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-dichl.o `test -f 'dichl.c' || echo '$(srcdir)/'`dichl.c fsarchiver-dichl.obj: dichl.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-dichl.obj -MD -MP -MF $(DEPDIR)/fsarchiver-dichl.Tpo -c -o fsarchiver-dichl.obj `if test -f 'dichl.c'; then $(CYGPATH_W) 'dichl.c'; else $(CYGPATH_W) '$(srcdir)/dichl.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-dichl.Tpo $(DEPDIR)/fsarchiver-dichl.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dichl.c' object='fsarchiver-dichl.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-dichl.obj `if test -f 'dichl.c'; then $(CYGPATH_W) 'dichl.c'; else $(CYGPATH_W) '$(srcdir)/dichl.c'; fi` fsarchiver-queue.o: queue.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-queue.o -MD -MP -MF $(DEPDIR)/fsarchiver-queue.Tpo -c -o fsarchiver-queue.o `test -f 'queue.c' || echo '$(srcdir)/'`queue.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-queue.Tpo $(DEPDIR)/fsarchiver-queue.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='queue.c' object='fsarchiver-queue.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-queue.o `test -f 'queue.c' || echo '$(srcdir)/'`queue.c fsarchiver-queue.obj: queue.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-queue.obj -MD -MP -MF $(DEPDIR)/fsarchiver-queue.Tpo -c -o fsarchiver-queue.obj `if test -f 'queue.c'; then $(CYGPATH_W) 'queue.c'; else $(CYGPATH_W) '$(srcdir)/queue.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-queue.Tpo $(DEPDIR)/fsarchiver-queue.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='queue.c' object='fsarchiver-queue.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-queue.obj `if test -f 'queue.c'; then $(CYGPATH_W) 'queue.c'; else $(CYGPATH_W) '$(srcdir)/queue.c'; fi` fsarchiver-error.o: error.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-error.o -MD -MP -MF $(DEPDIR)/fsarchiver-error.Tpo -c -o fsarchiver-error.o `test -f 'error.c' || echo '$(srcdir)/'`error.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-error.Tpo $(DEPDIR)/fsarchiver-error.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='error.c' object='fsarchiver-error.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-error.o `test -f 'error.c' || echo '$(srcdir)/'`error.c fsarchiver-error.obj: error.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-error.obj -MD -MP -MF $(DEPDIR)/fsarchiver-error.Tpo -c -o fsarchiver-error.obj `if test -f 'error.c'; then $(CYGPATH_W) 'error.c'; else $(CYGPATH_W) '$(srcdir)/error.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-error.Tpo $(DEPDIR)/fsarchiver-error.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='error.c' object='fsarchiver-error.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-error.obj `if test -f 'error.c'; then $(CYGPATH_W) 'error.c'; else $(CYGPATH_W) '$(srcdir)/error.c'; fi` fsarchiver-syncthread.o: syncthread.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-syncthread.o -MD -MP -MF $(DEPDIR)/fsarchiver-syncthread.Tpo -c -o fsarchiver-syncthread.o `test -f 'syncthread.c' || echo '$(srcdir)/'`syncthread.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-syncthread.Tpo $(DEPDIR)/fsarchiver-syncthread.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='syncthread.c' object='fsarchiver-syncthread.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-syncthread.o `test -f 'syncthread.c' || echo '$(srcdir)/'`syncthread.c fsarchiver-syncthread.obj: syncthread.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-syncthread.obj -MD -MP -MF $(DEPDIR)/fsarchiver-syncthread.Tpo -c -o fsarchiver-syncthread.obj `if test -f 'syncthread.c'; then $(CYGPATH_W) 'syncthread.c'; else $(CYGPATH_W) '$(srcdir)/syncthread.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-syncthread.Tpo $(DEPDIR)/fsarchiver-syncthread.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='syncthread.c' object='fsarchiver-syncthread.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-syncthread.obj `if test -f 'syncthread.c'; then $(CYGPATH_W) 'syncthread.c'; else $(CYGPATH_W) '$(srcdir)/syncthread.c'; fi` fsarchiver-datafile.o: datafile.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-datafile.o -MD -MP -MF $(DEPDIR)/fsarchiver-datafile.Tpo -c -o fsarchiver-datafile.o `test -f 'datafile.c' || echo '$(srcdir)/'`datafile.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-datafile.Tpo $(DEPDIR)/fsarchiver-datafile.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='datafile.c' object='fsarchiver-datafile.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-datafile.o `test -f 'datafile.c' || echo '$(srcdir)/'`datafile.c fsarchiver-datafile.obj: datafile.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-datafile.obj -MD -MP -MF $(DEPDIR)/fsarchiver-datafile.Tpo -c -o fsarchiver-datafile.obj `if test -f 'datafile.c'; then $(CYGPATH_W) 'datafile.c'; else $(CYGPATH_W) '$(srcdir)/datafile.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-datafile.Tpo $(DEPDIR)/fsarchiver-datafile.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='datafile.c' object='fsarchiver-datafile.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-datafile.obj `if test -f 'datafile.c'; then $(CYGPATH_W) 'datafile.c'; else $(CYGPATH_W) '$(srcdir)/datafile.c'; fi` fsarchiver-strlist.o: strlist.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-strlist.o -MD -MP -MF $(DEPDIR)/fsarchiver-strlist.Tpo -c -o fsarchiver-strlist.o `test -f 'strlist.c' || echo '$(srcdir)/'`strlist.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-strlist.Tpo $(DEPDIR)/fsarchiver-strlist.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='strlist.c' object='fsarchiver-strlist.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-strlist.o `test -f 'strlist.c' || echo '$(srcdir)/'`strlist.c fsarchiver-strlist.obj: strlist.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-strlist.obj -MD -MP -MF $(DEPDIR)/fsarchiver-strlist.Tpo -c -o fsarchiver-strlist.obj `if test -f 'strlist.c'; then $(CYGPATH_W) 'strlist.c'; else $(CYGPATH_W) '$(srcdir)/strlist.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-strlist.Tpo $(DEPDIR)/fsarchiver-strlist.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='strlist.c' object='fsarchiver-strlist.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-strlist.obj `if test -f 'strlist.c'; then $(CYGPATH_W) 'strlist.c'; else $(CYGPATH_W) '$(srcdir)/strlist.c'; fi` fsarchiver-regmulti.o: regmulti.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-regmulti.o -MD -MP -MF $(DEPDIR)/fsarchiver-regmulti.Tpo -c -o fsarchiver-regmulti.o `test -f 'regmulti.c' || echo '$(srcdir)/'`regmulti.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-regmulti.Tpo $(DEPDIR)/fsarchiver-regmulti.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regmulti.c' object='fsarchiver-regmulti.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-regmulti.o `test -f 'regmulti.c' || echo '$(srcdir)/'`regmulti.c fsarchiver-regmulti.obj: regmulti.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-regmulti.obj -MD -MP -MF $(DEPDIR)/fsarchiver-regmulti.Tpo -c -o fsarchiver-regmulti.obj `if test -f 'regmulti.c'; then $(CYGPATH_W) 'regmulti.c'; else $(CYGPATH_W) '$(srcdir)/regmulti.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-regmulti.Tpo $(DEPDIR)/fsarchiver-regmulti.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regmulti.c' object='fsarchiver-regmulti.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-regmulti.obj `if test -f 'regmulti.c'; then $(CYGPATH_W) 'regmulti.c'; else $(CYGPATH_W) '$(srcdir)/regmulti.c'; fi` fsarchiver-options.o: options.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-options.o -MD -MP -MF $(DEPDIR)/fsarchiver-options.Tpo -c -o fsarchiver-options.o `test -f 'options.c' || echo '$(srcdir)/'`options.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-options.Tpo $(DEPDIR)/fsarchiver-options.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='options.c' object='fsarchiver-options.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-options.o `test -f 'options.c' || echo '$(srcdir)/'`options.c fsarchiver-options.obj: options.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-options.obj -MD -MP -MF $(DEPDIR)/fsarchiver-options.Tpo -c -o fsarchiver-options.obj `if test -f 'options.c'; then $(CYGPATH_W) 'options.c'; else $(CYGPATH_W) '$(srcdir)/options.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-options.Tpo $(DEPDIR)/fsarchiver-options.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='options.c' object='fsarchiver-options.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-options.obj `if test -f 'options.c'; then $(CYGPATH_W) 'options.c'; else $(CYGPATH_W) '$(srcdir)/options.c'; fi` fsarchiver-logfile.o: logfile.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-logfile.o -MD -MP -MF $(DEPDIR)/fsarchiver-logfile.Tpo -c -o fsarchiver-logfile.o `test -f 'logfile.c' || echo '$(srcdir)/'`logfile.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-logfile.Tpo $(DEPDIR)/fsarchiver-logfile.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='logfile.c' object='fsarchiver-logfile.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-logfile.o `test -f 'logfile.c' || echo '$(srcdir)/'`logfile.c fsarchiver-logfile.obj: logfile.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-logfile.obj -MD -MP -MF $(DEPDIR)/fsarchiver-logfile.Tpo -c -o fsarchiver-logfile.obj `if test -f 'logfile.c'; then $(CYGPATH_W) 'logfile.c'; else $(CYGPATH_W) '$(srcdir)/logfile.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-logfile.Tpo $(DEPDIR)/fsarchiver-logfile.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='logfile.c' object='fsarchiver-logfile.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-logfile.obj `if test -f 'logfile.c'; then $(CYGPATH_W) 'logfile.c'; else $(CYGPATH_W) '$(srcdir)/logfile.c'; fi` fsarchiver-filesys.o: filesys.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-filesys.o -MD -MP -MF $(DEPDIR)/fsarchiver-filesys.Tpo -c -o fsarchiver-filesys.o `test -f 'filesys.c' || echo '$(srcdir)/'`filesys.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-filesys.Tpo $(DEPDIR)/fsarchiver-filesys.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='filesys.c' object='fsarchiver-filesys.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-filesys.o `test -f 'filesys.c' || echo '$(srcdir)/'`filesys.c fsarchiver-filesys.obj: filesys.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-filesys.obj -MD -MP -MF $(DEPDIR)/fsarchiver-filesys.Tpo -c -o fsarchiver-filesys.obj `if test -f 'filesys.c'; then $(CYGPATH_W) 'filesys.c'; else $(CYGPATH_W) '$(srcdir)/filesys.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-filesys.Tpo $(DEPDIR)/fsarchiver-filesys.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='filesys.c' object='fsarchiver-filesys.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-filesys.obj `if test -f 'filesys.c'; then $(CYGPATH_W) 'filesys.c'; else $(CYGPATH_W) '$(srcdir)/filesys.c'; fi` fsarchiver-devinfo.o: devinfo.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-devinfo.o -MD -MP -MF $(DEPDIR)/fsarchiver-devinfo.Tpo -c -o fsarchiver-devinfo.o `test -f 'devinfo.c' || echo '$(srcdir)/'`devinfo.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-devinfo.Tpo $(DEPDIR)/fsarchiver-devinfo.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='devinfo.c' object='fsarchiver-devinfo.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-devinfo.o `test -f 'devinfo.c' || echo '$(srcdir)/'`devinfo.c fsarchiver-devinfo.obj: devinfo.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -MT fsarchiver-devinfo.obj -MD -MP -MF $(DEPDIR)/fsarchiver-devinfo.Tpo -c -o fsarchiver-devinfo.obj `if test -f 'devinfo.c'; then $(CYGPATH_W) 'devinfo.c'; else $(CYGPATH_W) '$(srcdir)/devinfo.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fsarchiver-devinfo.Tpo $(DEPDIR)/fsarchiver-devinfo.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='devinfo.c' object='fsarchiver-devinfo.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(fsarchiver_CFLAGS) $(CFLAGS) -c -o fsarchiver-devinfo.obj `if test -f 'devinfo.c'; then $(CYGPATH_W) 'devinfo.c'; else $(CYGPATH_W) '$(srcdir)/devinfo.c'; fi` ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(sbindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-generic clean-sbinPROGRAMS mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/fsarchiver-archinfo.Po -rm -f ./$(DEPDIR)/fsarchiver-archreader.Po -rm -f ./$(DEPDIR)/fsarchiver-archwriter.Po -rm -f ./$(DEPDIR)/fsarchiver-common.Po -rm -f ./$(DEPDIR)/fsarchiver-comp_bzip2.Po -rm -f ./$(DEPDIR)/fsarchiver-comp_gzip.Po -rm -f ./$(DEPDIR)/fsarchiver-comp_lz4.Po -rm -f ./$(DEPDIR)/fsarchiver-comp_lzma.Po -rm -f ./$(DEPDIR)/fsarchiver-comp_lzo.Po -rm -f ./$(DEPDIR)/fsarchiver-comp_zstd.Po -rm -f ./$(DEPDIR)/fsarchiver-crypto.Po -rm -f ./$(DEPDIR)/fsarchiver-datafile.Po -rm -f ./$(DEPDIR)/fsarchiver-devinfo.Po -rm -f ./$(DEPDIR)/fsarchiver-dichl.Po -rm -f ./$(DEPDIR)/fsarchiver-dico.Po -rm -f ./$(DEPDIR)/fsarchiver-error.Po -rm -f ./$(DEPDIR)/fsarchiver-filesys.Po -rm -f ./$(DEPDIR)/fsarchiver-fs_btrfs.Po -rm -f ./$(DEPDIR)/fsarchiver-fs_ext2.Po -rm -f ./$(DEPDIR)/fsarchiver-fs_jfs.Po -rm -f ./$(DEPDIR)/fsarchiver-fs_ntfs.Po -rm -f ./$(DEPDIR)/fsarchiver-fs_reiser4.Po -rm -f ./$(DEPDIR)/fsarchiver-fs_reiserfs.Po -rm -f ./$(DEPDIR)/fsarchiver-fs_vfat.Po -rm -f ./$(DEPDIR)/fsarchiver-fs_xfs.Po -rm -f ./$(DEPDIR)/fsarchiver-fsarchiver.Po -rm -f ./$(DEPDIR)/fsarchiver-logfile.Po -rm -f ./$(DEPDIR)/fsarchiver-oper_probe.Po -rm -f ./$(DEPDIR)/fsarchiver-oper_restore.Po -rm -f ./$(DEPDIR)/fsarchiver-oper_save.Po -rm -f ./$(DEPDIR)/fsarchiver-options.Po -rm -f ./$(DEPDIR)/fsarchiver-queue.Po -rm -f ./$(DEPDIR)/fsarchiver-regmulti.Po -rm -f ./$(DEPDIR)/fsarchiver-strdico.Po -rm -f ./$(DEPDIR)/fsarchiver-strlist.Po -rm -f ./$(DEPDIR)/fsarchiver-syncthread.Po -rm -f ./$(DEPDIR)/fsarchiver-thread_archio.Po -rm -f ./$(DEPDIR)/fsarchiver-thread_comp.Po -rm -f ./$(DEPDIR)/fsarchiver-writebuf.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-sbinPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/fsarchiver-archinfo.Po -rm -f ./$(DEPDIR)/fsarchiver-archreader.Po -rm -f ./$(DEPDIR)/fsarchiver-archwriter.Po -rm -f ./$(DEPDIR)/fsarchiver-common.Po -rm -f ./$(DEPDIR)/fsarchiver-comp_bzip2.Po -rm -f ./$(DEPDIR)/fsarchiver-comp_gzip.Po -rm -f ./$(DEPDIR)/fsarchiver-comp_lz4.Po -rm -f ./$(DEPDIR)/fsarchiver-comp_lzma.Po -rm -f ./$(DEPDIR)/fsarchiver-comp_lzo.Po -rm -f ./$(DEPDIR)/fsarchiver-comp_zstd.Po -rm -f ./$(DEPDIR)/fsarchiver-crypto.Po -rm -f ./$(DEPDIR)/fsarchiver-datafile.Po -rm -f ./$(DEPDIR)/fsarchiver-devinfo.Po -rm -f ./$(DEPDIR)/fsarchiver-dichl.Po -rm -f ./$(DEPDIR)/fsarchiver-dico.Po -rm -f ./$(DEPDIR)/fsarchiver-error.Po -rm -f ./$(DEPDIR)/fsarchiver-filesys.Po -rm -f ./$(DEPDIR)/fsarchiver-fs_btrfs.Po -rm -f ./$(DEPDIR)/fsarchiver-fs_ext2.Po -rm -f ./$(DEPDIR)/fsarchiver-fs_jfs.Po -rm -f ./$(DEPDIR)/fsarchiver-fs_ntfs.Po -rm -f ./$(DEPDIR)/fsarchiver-fs_reiser4.Po -rm -f ./$(DEPDIR)/fsarchiver-fs_reiserfs.Po -rm -f ./$(DEPDIR)/fsarchiver-fs_vfat.Po -rm -f ./$(DEPDIR)/fsarchiver-fs_xfs.Po -rm -f ./$(DEPDIR)/fsarchiver-fsarchiver.Po -rm -f ./$(DEPDIR)/fsarchiver-logfile.Po -rm -f ./$(DEPDIR)/fsarchiver-oper_probe.Po -rm -f ./$(DEPDIR)/fsarchiver-oper_restore.Po -rm -f ./$(DEPDIR)/fsarchiver-oper_save.Po -rm -f ./$(DEPDIR)/fsarchiver-options.Po -rm -f ./$(DEPDIR)/fsarchiver-queue.Po -rm -f ./$(DEPDIR)/fsarchiver-regmulti.Po -rm -f ./$(DEPDIR)/fsarchiver-strdico.Po -rm -f ./$(DEPDIR)/fsarchiver-strlist.Po -rm -f ./$(DEPDIR)/fsarchiver-syncthread.Po -rm -f ./$(DEPDIR)/fsarchiver-thread_archio.Po -rm -f ./$(DEPDIR)/fsarchiver-thread_comp.Po -rm -f ./$(DEPDIR)/fsarchiver-writebuf.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-sbinPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-generic clean-sbinPROGRAMS cscopelist-am ctags ctags-am \ distclean distclean-compile distclean-generic distclean-tags \ distdir dvi dvi-am html html-am info info-am install \ install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-sbinPROGRAMS install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-sbinPROGRAMS .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: fsarchiver-0.8.7/src/filesys.h0000644000175000017500000000407314405605077013235 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifndef __FILESYS_H__ #define __FILESYS_H__ #define PROGVER(x, y, z) (((u64)x)<<16)+(((u64)y)<<8)+(((u64)z)<<0) struct s_strlist; struct s_dico; struct s_filesys; typedef struct s_filesys cfilesys; struct s_filesys { char *name; int (*mount)(char *partition, char *mntbuf, char *fsname, int flags, char *mntinfo); int (*umount)(char *partition, char *mntbuf); int (*getinfo)(struct s_dico *d, char *devname); int (*mkfs)(struct s_dico *d, char *partition, char *fsoptions, char *mkfslabel, char *mkfsuuid); int (*test)(char *partition); int (*reqmntopt)(char *partition, struct s_strlist *reqopt, struct s_strlist *badopt); bool support_for_xattr; bool support_for_acls; bool winattr; bool savesymtargettype; // we have to know the type of the target to recreate a symlink on ntfs bool stable; // say if the fsarchiver support for this filesystem is considered stable or not }; extern cfilesys filesys[]; int devcmp(char *dev1, char *dev2); int generic_get_spacestats(char *dev, char *mnt, char *text, int textlen); int generic_get_fsrwstatus(char *options); int generic_get_fstype(char *fsname, int *fstype); int generic_get_mntinfo(char *devname, int *readwrite, char *mntbuf, int maxmntbuf, char *optbuf, int maxoptbuf, char *fsbuf, int maxfsbuf); int generic_mount(char *partition, char *mntbuf, char *fsbuf, char *mntopt, int flags); char *format_prog_version(u64 version, char *bufdat, int buflen); int generic_umount(char *mntbuf); #endif // __FILESYS_H__ fsarchiver-0.8.7/src/archreader.c0000644000175000017500000004021214405605077013645 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include #include #include #include "fsarchiver.h" #include "dico.h" #include "common.h" #include "options.h" #include "archreader.h" #include "queue.h" #include "comp_gzip.h" #include "comp_bzip2.h" #include "error.h" int archreader_init(carchreader *ai) { assert(ai); memset(ai, 0, sizeof(struct s_archreader)); ai->cryptalgo=ENCRYPT_NULL; ai->compalgo=COMPRESS_NULL; ai->fsacomp=-1; ai->complevel=-1; ai->archfd=-1; ai->archid=0; ai->curvol=0; ai->filefmtver=0; ai->hasdirsinfohead=false; return 0; } int archreader_destroy(carchreader *ai) { assert(ai); return 0; } int archreader_open(carchreader *ai) { struct stat64 st; char volhead[64]; int magiclen; assert(ai); // on the archive volume ai->archfd=open64(ai->volpath, O_RDONLY|O_LARGEFILE); if (ai->archfd<0) { sysprintf ("cannot open archive %s\n", ai->volpath); return -1; } // check the archive volume is a regular file if (fstat64(ai->archfd, &st)!=0) { sysprintf("fstat64(%s) failed\n", ai->volpath); return -1; } if (!S_ISREG(st.st_mode)) { errprintf("%s is not a regular file, cannot continue\n", ai->volpath); close(ai->archfd); return -1; } // read file format version and rewind to beginning of the volume if (read(ai->archfd, volhead, sizeof(volhead))!=sizeof(volhead)) { sysprintf("cannot read magic from %s\n", ai->volpath); close(ai->archfd); return -1; } if (lseek64(ai->archfd, 0, SEEK_SET)!=0) { sysprintf("cannot rewind volume %s\n", ai->volpath); close(ai->archfd); return -1; } // interpret magic an get file format version magiclen=strlen(FSA_FILEFORMAT); if ((memcmp(volhead+40, "FsArCh_001", magiclen)==0) || (memcmp(volhead+40, "FsArCh_00Y", magiclen)==0)) { ai->filefmtver=1; } else if (memcmp(volhead+42, "FsArCh_002", magiclen)==0) { ai->filefmtver=2; } else { errprintf("%s is not a supported fsarchiver file format\n", ai->volpath); close(ai->archfd); return -1; } msgprintf(MSG_VERB2, "Detected fileformat=%d in archive %s\n", (int)ai->filefmtver, ai->volpath); return 0; } int archreader_close(carchreader *ai) { assert(ai); if (ai->archfd<0) return -1; lockf(ai->archfd, F_ULOCK, 0); close(ai->archfd); ai->archfd=-1; return 0; } int archreader_volpath(carchreader *ai) { int res; res=get_path_to_volume(ai->volpath, PATH_MAX, ai->basepath, ai->curvol); return res; } int archreader_incvolume(carchreader *ai, bool waitkeypress) { assert(ai); ai->curvol++; return archreader_volpath(ai); } int archreader_read_data(carchreader *ai, void *data, u64 size) { long lres; assert(ai); if ((lres=read(ai->archfd, (char*)data, (long)size))!=(long)size) { sysprintf("read failed: read(size=%ld)=%ld\n", (long)size, lres); return -1; } return 0; } int archreader_read_dico(carchreader *ai, cdico *d) { u16 size; u32 headerlen; u32 origsum; u32 newsum; u8 *buffer; u8 *bufpos; u16 temp16; u32 temp32; u8 section; u16 count; u8 type; u16 key; int i; assert(ai); assert(d); // header-len, header-data, header-checksum switch (ai->filefmtver) { case 1: if (archreader_read_data(ai, &temp16, sizeof(temp16))!=0) { errprintf("imgdisk_read_data() failed\n"); return OLDERR_FATAL; } headerlen=le16_to_cpu(temp16); break; case 2: if (archreader_read_data(ai, &temp32, sizeof(temp32))!=0) { errprintf("imgdisk_read_data() failed\n"); return OLDERR_FATAL; } headerlen=le32_to_cpu(temp32); break; default: errprintf("Fatal error: invalid file format version: ai->filefmtver=%d\n", ai->filefmtver); return OLDERR_FATAL; } bufpos=buffer=malloc(headerlen); if (!buffer) { errprintf("cannot allocate memory for header\n"); return FSAERR_ENOMEM; } if (archreader_read_data(ai, buffer, headerlen)!=0) { errprintf("cannot read header data\n"); free(buffer); return OLDERR_FATAL; } if (archreader_read_data(ai, &temp32, sizeof(temp32))!=0) { errprintf("cannot read header checksum\n"); free(buffer); return OLDERR_FATAL; } origsum=le32_to_cpu(temp32); // check header-data integrity using checksum newsum=fletcher32(buffer, headerlen); if (newsum!=origsum) { errprintf("bad checksum for header\n"); free(buffer); return OLDERR_MINOR; // header corrupt --> skip file } // read count from buffer memcpy(&temp16, bufpos, sizeof(temp16)); bufpos+=sizeof(temp16); count=le16_to_cpu(temp16); // read items for (i=0; i < count; i++) { // a. read type from buffer memcpy(&type, bufpos, sizeof(type)); bufpos+=sizeof(section); // b. read section from buffer memcpy(§ion, bufpos, sizeof(section)); bufpos+=sizeof(section); // c. read key from buffer memcpy(&temp16, bufpos, sizeof(temp16)); bufpos+=sizeof(temp16); key=le16_to_cpu(temp16); // d. read sizeof(data) memcpy(&temp16, bufpos, sizeof(temp16)); bufpos+=sizeof(temp16); size=le16_to_cpu(temp16); // e. add item to dico if (dico_add_generic(d, section, key, bufpos, size, type)!=0) return OLDERR_FATAL; bufpos+=size; } free(buffer); return FSAERR_SUCCESS; } int archreader_read_header(carchreader *ai, char *magic, cdico **d, bool allowseek, u16 *fsid) { s64 curpos; u16 temp16; u32 temp32; u32 archid; int res; assert(ai); assert(d); assert(fsid); // init memset(magic, 0, FSA_SIZEOF_MAGIC); *fsid=FSA_FILESYSID_NULL; *d=NULL; if ((*d=dico_alloc())==NULL) { errprintf("dico_alloc() failed\n"); return OLDERR_FATAL; } // search for next read header marker and magic (it may be further if corruption in archive) if ((curpos=lseek64(ai->archfd, 0, SEEK_CUR))<0) { sysprintf("lseek64() failed to get the current position in archive\n"); return OLDERR_FATAL; } if ((res=archreader_read_data(ai, magic, FSA_SIZEOF_MAGIC))!=FSAERR_SUCCESS) { msgprintf(MSG_STACK, "cannot read header magic: res=%d\n", res); return OLDERR_FATAL; } // we don't want to search for the magic if it's a volume header if (is_magic_valid(magic)!=true && allowseek!=true) { errprintf("cannot read header magic: this is not a valid fsarchiver file, or it has been created with a different version.\n"); return OLDERR_FATAL; } while (is_magic_valid(magic)!=true) { if (lseek64(ai->archfd, curpos++, SEEK_SET)<0) { sysprintf("lseek64(pos=%lld, SEEK_SET) failed\n", (long long)curpos); return OLDERR_FATAL; } if ((res=archreader_read_data(ai, magic, FSA_SIZEOF_MAGIC))!=FSAERR_SUCCESS) { msgprintf(MSG_STACK, "cannot read header magic: res=%d\n", res); return OLDERR_FATAL; } } // read the archive id if ((res=archreader_read_data(ai, &temp32, sizeof(temp32)))!=FSAERR_SUCCESS) { msgprintf(MSG_STACK, "cannot read archive-id in header: res=%d\n", res); return OLDERR_FATAL; } archid=le32_to_cpu(temp32); if (ai->archid) // only check archive-id if it's known (when main header has been read) { if (archid!=ai->archid) { errprintf("archive-id in header does not match: archid=[%.8x], expected=[%.8x]\n", archid, ai->archid); return OLDERR_MINOR; } } // read the filesystem id if ((res=archreader_read_data(ai, &temp16, sizeof(temp16)))!=FSAERR_SUCCESS) { msgprintf(MSG_STACK, "cannot read filesystem-id in header: res=%d\n", res); return OLDERR_FATAL; } *fsid=le16_to_cpu(temp16); // read the dico of the header if ((res=archreader_read_dico(ai, *d))!=FSAERR_SUCCESS) { msgprintf(MSG_STACK, "imgdisk_read_dico() failed\n"); return res; } return FSAERR_SUCCESS; } int archreader_read_volheader(carchreader *ai) { char creatver[FSA_MAX_PROGVERLEN]; char filefmt[FSA_MAX_FILEFMTLEN]; char magic[FSA_SIZEOF_MAGIC]; cdico *d; u32 volnum; u32 readid; u16 fsid; int res; int ret=0; // init assert(ai); memset(magic, 0, sizeof(magic)); // ---- a. read header from archive file if ((res=archreader_read_header(ai, magic, &d, false, &fsid))!=FSAERR_SUCCESS) { errprintf("archreader_read_header() failed to read the archive header\n"); return -1; } // ---- b. check the magic is what we expected if (strncmp(magic, FSA_MAGIC_VOLH, FSA_SIZEOF_MAGIC)!=0) { errprintf("magic is not what we expected: found=[%s] and expected=[%s]\n", magic, FSA_MAGIC_VOLH); ret=-1; goto archio_read_volheader_error; } if (dico_get_u32(d, 0, VOLUMEHEADKEY_ARCHID, &readid)!=0) { errprintf("cannot get VOLUMEHEADKEY_ARCHID from the volume header\n"); ret=-1; goto archio_read_volheader_error; } // ---- c. check the archive id if (ai->archid==0) // archid not know: this is the first volume { ai->archid=readid; } else if (readid!=ai->archid) // archid known: not the first volume { errprintf("wrong header id: found=%.8x and expected=%.8x\n", readid, ai->archid); ret=-1; goto archio_read_volheader_error; } // ---- d. check the volnum if (dico_get_u32(d, 0, VOLUMEHEADKEY_VOLNUM, &volnum)!=0) { errprintf("cannot get VOLUMEHEADKEY_VOLNUM from the volume header\n"); ret=-1; goto archio_read_volheader_error; } if (volnum!=ai->curvol) // not the right volume number { errprintf("wrong volume number in [%s]: volnum is %d and we need volnum %d\n", ai->volpath, (int)volnum, (int)ai->curvol); ret=-1; goto archio_read_volheader_error; } // ---- d. check the the file format if (dico_get_data(d, 0, VOLUMEHEADKEY_FILEFORMATVER, filefmt, FSA_MAX_FILEFMTLEN, NULL)!=0) { errprintf("cannot find VOLUMEHEADKEY_FILEFORMATVER in main-header\n"); ret=-1; goto archio_read_volheader_error; } if (ai->filefmt[0]==0) // filefmt not know: this is the first volume { memcpy(ai->filefmt, filefmt, FSA_MAX_FILEFMTLEN); } else if (strncmp(filefmt, ai->filefmt, FSA_MAX_FILEFMTLEN)!=0) { errprintf("This archive is based on a different file format: [%s]. Cannot continue.\n", ai->filefmt); errprintf("It has been created with fsarchiver [%s], you should extrat the archive using that version.\n", ai->creatver); errprintf("The current version of the program is [%s], and it's based on format [%s]\n", FSA_VERSION, FSA_FILEFORMAT); ret=-1; goto archio_read_volheader_error; } if (dico_get_data(d, 0, VOLUMEHEADKEY_PROGVERCREAT, creatver, FSA_MAX_PROGVERLEN, NULL)!=0) { errprintf("cannot find VOLUMEHEADKEY_PROGVERCREAT in main-header\n"); ret=-1; goto archio_read_volheader_error; } if (ai->creatver[0]==0) memcpy(ai->creatver, creatver, FSA_MAX_PROGVERLEN); archio_read_volheader_error: dico_destroy(d); return ret; } int archreader_read_block(carchreader *ai, cdico *in_blkdico, int in_skipblock, int *out_sumok, struct s_blockinfo *out_blkinfo) { u32 arblockcsumorig; u32 arblockcsumcalc; u32 curblocksize; // data size u64 blockoffset; // offset of the block in the file u16 compalgo; // compression algo used u16 cryptalgo; // encryption algo used u32 finalsize; // compressed block size u32 compsize; u8 *buffer; assert(ai); assert(out_sumok); assert(in_blkdico); assert(out_blkinfo); // init memset(out_blkinfo, 0, sizeof(struct s_blockinfo)); *out_sumok=-1; if (dico_get_u64(in_blkdico, 0, BLOCKHEADITEMKEY_BLOCKOFFSET, &blockoffset)!=0) { msgprintf(3, "cannot get blockoffset from block-header\n"); return -1; } if (dico_get_u32(in_blkdico, 0, BLOCKHEADITEMKEY_REALSIZE, &curblocksize)!=0 || curblocksize>FSA_MAX_BLKSIZE) { msgprintf(3, "cannot get blocksize from block-header\n"); return -1; } if (dico_get_u16(in_blkdico, 0, BLOCKHEADITEMKEY_COMPRESSALGO, &compalgo)!=0) { msgprintf(3, "cannot get BLOCKHEADITEMKEY_COMPRESSALGO from block-header\n"); return -1; } if (dico_get_u16(in_blkdico, 0, BLOCKHEADITEMKEY_ENCRYPTALGO, &cryptalgo)!=0) { msgprintf(3, "cannot get BLOCKHEADITEMKEY_ENCRYPTALGO from block-header\n"); return -1; } if (dico_get_u32(in_blkdico, 0, BLOCKHEADITEMKEY_ARSIZE, &finalsize)!=0) { msgprintf(3, "cannot get BLOCKHEADITEMKEY_ARSIZE from block-header\n"); return -1; } if (dico_get_u32(in_blkdico, 0, BLOCKHEADITEMKEY_COMPSIZE, &compsize)!=0) { msgprintf(3, "cannot get BLOCKHEADITEMKEY_COMPSIZE from block-header\n"); return -1; } if (dico_get_u32(in_blkdico, 0, BLOCKHEADITEMKEY_ARCSUM, &arblockcsumorig)!=0) { msgprintf(3, "cannot get BLOCKHEADITEMKEY_ARCSUM from block-header\n"); return -1; } if (in_skipblock==true) // the main thread does not need that block (block belongs to a filesys we want to skip) { if (lseek64(ai->archfd, (long)finalsize, SEEK_CUR)<0) { sysprintf("cannot skip block (finalsize=%ld) failed\n", (long)finalsize); return -1; } return 0; } // ---- allocate memory if ((buffer=malloc(finalsize))==NULL) { errprintf("cannot allocate block: malloc(%d) failed\n", finalsize); return FSAERR_ENOMEM; } if (read(ai->archfd, buffer, (long)finalsize)!=(long)finalsize) { sysprintf("cannot read block (finalsize=%ld) failed\n", (long)finalsize); free(buffer); return -1; } // prepare blkinfo out_blkinfo->blkdata=(char*)buffer; out_blkinfo->blkrealsize=curblocksize; out_blkinfo->blkoffset=blockoffset; out_blkinfo->blkarcsum=arblockcsumorig; out_blkinfo->blkcompalgo=compalgo; out_blkinfo->blkcryptalgo=cryptalgo; out_blkinfo->blkarsize=finalsize; out_blkinfo->blkcompsize=compsize; // ---- checksum arblockcsumcalc=fletcher32(buffer, finalsize); if (arblockcsumcalc!=arblockcsumorig) // bad checksum { errprintf("block is corrupt at offset=%ld, blksize=%ld\n", (long)blockoffset, (long)curblocksize); free(out_blkinfo->blkdata); if ((out_blkinfo->blkdata=malloc(curblocksize))==NULL) { errprintf("cannot allocate block: malloc(%d) failed\n", curblocksize); return FSAERR_ENOMEM; } memset(out_blkinfo->blkdata, 0, curblocksize); *out_sumok=false; // go to the beginning of the corrupted contents so that the next header is searched here if (lseek64(ai->archfd, -(long long)finalsize, SEEK_CUR)<0) { errprintf("lseek64() failed\n"); } } else // no corruption detected { *out_sumok=true; } return 0; } fsarchiver-0.8.7/src/comp_lz4.h0000644000175000017500000000167114405605077013307 00000000000000 /* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2017 Cristian Vazquez. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifndef __COMPRESS_LZ4_H__ #define __COMPRESS_LZ4_H__ #ifdef OPTION_LZ4_SUPPORT #include int compress_block_lz4(u64 origsize, u64 *compsize, u8 *origbuf, u8 *compbuf, u64 compbufsize, int level); int uncompress_block_lz4(u64 compsize, u64 *origsize, u8 *origbuf, u64 origbufsize, u8 *compbuf); #endif // OPTION_LZ4_SUPPORT #endif // __COMPRESS_LZ4_H__ fsarchiver-0.8.7/src/fs_xfs.c0000644000175000017500000004417514405605077013051 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include #include #include "fsarchiver.h" #include "dico.h" #include "common.h" #include "fs_xfs.h" #include "filesys.h" #include "strlist.h" #include "error.h" // POSIX Extended Regular Expression to match RHEL 7 kernel releases #define RHEL7_KERNEL_ERE "[[:digit:]]+\\.el7(uek)?\\." int xfs_check_compatibility(u64 compat, u64 ro_compat, u64 incompat, u64 log_incompat) { int errors=0; msgprintf(MSG_DEBUG1, "xfs features: compat=[%ld]\n", (long)compat); msgprintf(MSG_DEBUG1, "xfs features: ro_compat=[%ld]\n", (long)ro_compat); msgprintf(MSG_DEBUG1, "xfs features: incompat=[%ld]\n", (long)incompat); msgprintf(MSG_DEBUG1, "xfs features: log_incompat=[%ld]\n", (long)log_incompat); // to preserve the filesystem attributes, fsa must know all the features including the COMPAT ones if (compat & ~FSA_XFS_FEATURE_COMPAT_SUPP) errors++; if (ro_compat & ~FSA_XFS_FEATURE_RO_COMPAT_SUPP) errors++; if (incompat & ~FSA_XFS_FEATURE_INCOMPAT_SUPP) errors++; if (log_incompat & ~FSA_XFS_FEATURE_LOG_INCOMPAT_SUPP) errors++; if (errors > 0) { errprintf("this filesystem has XFS features which are not supported by this fsarchiver version.\n"); return -1; } else { return 0; } } int xfs_mkfs(cdico *d, char *partition, char *fsoptions, char *mkfslabel, char *mkfsuuid) { char stdoutbuf[2048]; char command[2048]; char buffer[2048]; char mkfsopts[2048]; char xadmopts[2048]; char uuid[64]; u64 xfstoolsver; int exitst; u64 temp64; u64 xfsver; int x, y, z; int optval; u64 sb_features_compat=0; u64 sb_features_ro_compat=0; u64 sb_features_incompat=0; u64 sb_features_log_incompat=0; // ---- check that mkfs is installed and get its version if (exec_command(command, sizeof(command), NULL, stdoutbuf, sizeof(stdoutbuf), NULL, 0, "mkfs.xfs -V")!=0) { errprintf("mkfs.xfs not found. please install xfsprogs on your system or check the PATH.\n"); return -1; } x=y=z=0; sscanf(stdoutbuf, "mkfs.xfs version %d.%d.%d", &x, &y, &z); if (x==0 && y==0) { errprintf("Can't parse mkfs.xfs version number: x=y=0\n"); return -1; } xfstoolsver=PROGVER(x,y,z); msgprintf(MSG_VERB2, "Detected mkfs.xfs version %d.%d.%d\n", x, y, z); memset(mkfsopts, 0, sizeof(mkfsopts)); memset(xadmopts, 0, sizeof(xadmopts)); memset(uuid, 0, sizeof(uuid)); if (strlen(mkfslabel) > 0) strlcatf(mkfsopts, sizeof(mkfsopts), " -L '%.12s' ", mkfslabel); else if (dico_get_string(d, 0, FSYSHEADKEY_FSLABEL, buffer, sizeof(buffer))==0 && strlen(buffer)>0) strlcatf(mkfsopts, sizeof(mkfsopts), " -L '%.12s' ", buffer); if ((dico_get_u64(d, 0, FSYSHEADKEY_FSXFSBLOCKSIZE, &temp64)==0) && (temp64%512==0) && (temp64>=512) && (temp64<=65536)) strlcatf(mkfsopts, sizeof(mkfsopts), " -b size=%ld ", (long)temp64); // ---- get xfs features attributes from the archive dico_get_u64(d, 0, FSYSHEADKEY_FSXFSFEATURECOMPAT, &sb_features_compat); dico_get_u64(d, 0, FSYSHEADKEY_FSXFSFEATUREROCOMPAT, &sb_features_ro_compat); dico_get_u64(d, 0, FSYSHEADKEY_FSXFSFEATUREINCOMPAT, &sb_features_incompat); dico_get_u64(d, 0, FSYSHEADKEY_FSXFSFEATURELOGINCOMPAT, &sb_features_log_incompat); // ---- check fsarchiver is aware of all the filesystem features used on that filesystem if (xfs_check_compatibility(sb_features_compat, sb_features_ro_compat, sb_features_incompat, sb_features_log_incompat)!=0) return -1; // Preserve XFS V4 if the original filesystem was V4 or if it was saved with // fsarchiver <= 0.6.19 which does not store the version in the metadata: // create XFS V4 if unsure for better compatibility if ((dico_get_u64(d, 0, FSYSHEADKEY_FSXFSVERSION, &temp64)!=0) || (temp64==XFS_SB_VERSION_4)) xfsver = XFS_SB_VERSION_4; else xfsver = XFS_SB_VERSION_5; // Unfortunately it is impossible to preserve XFS V5 UUID (stamped on every metadata // block) with mkfs.xfs < 4.3.0. Restoring with a new random UUID could prevent the // system from booting if this is a boot/root filesystem because grub/fstab often // use UUID to identify it. Hence it is much safer restore as XFS V4 in this case. // More details: https://github.com/fdupoux/fsarchiver/issues/4 if ((xfsver==XFS_SB_VERSION_5) && (xfstoolsver < PROGVER(4,3,0))) { xfsver = XFS_SB_VERSION_4; // Do not preserve the XFS version msgprintf(MSG_FORCE, "It is impossible to restore this filesystem as XFS V5 and preserve its UUID\n" "with mkfs.xfs < 4.3.0. This filesystem will be restored as XFS V4 instead\n" "as this is a much safer option (preserving the UUID may be required on\n" "boot/root filesystems for the operating system to be able to start). If you\n" "really need XFS V5, please upgrade xfsprogs to version 4.3.0 or more recent\n" "and rerun this operation\n"); } // Determine if the "crc" mkfs option should be enabled (checksum) // - checksum must be disabled if we want to recreate XFS V4 filesystem // - checksum must be enabled if we want to recreate XFS V5 filesystem if (xfstoolsver >= PROGVER(3,2,0)) // only use "crc" option when it is supported by mkfs { optval = (xfsver==XFS_SB_VERSION_5); strlcatf(mkfsopts, sizeof(mkfsopts), " -m crc=%d ", (int)optval); } // Determine if the "finobt" mkfs option should be enabled (free inode btree) // - starting with linux-3.16 XFS has added a btree that tracks free inodes // - this feature relies on the V5 on-disk format but it is optional // - this feature is enabled by default when using xfsprogs-3.2.3 or later // - this feature will be enabled if the original filesystem was XFS V5 and had it if (xfstoolsver >= PROGVER(3,2,1)) // only use "finobt" option when it is supported by mkfs { optval = ((xfsver==XFS_SB_VERSION_5) && (sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_FINOBT)); strlcatf(mkfsopts, sizeof(mkfsopts), " -m finobt=%d ", (int)optval); } // Determine if the "rmapbt" mkfs option should be enabled (reverse mapping btree) // - starting with linux-4.8 XFS has added a btree that maps filesystem blocks to their owner // - this feature relies on the V5 on-disk format but it is optional // - this feature will be enabled if the original filesystem was XFS V5 and had it if (xfstoolsver >= PROGVER(4,8,0)) // only use "rmapbt" option when it is supported by mkfs { optval = ((xfsver==XFS_SB_VERSION_5) && (sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_RMAPBT)); strlcatf(mkfsopts, sizeof(mkfsopts), " -m rmapbt=%d ", (int)optval); } // Determine if the "reflink" mkfs option should be enabled // - starting with linux-4.9 XFS has added support for reflinked files // - this feature relies on the V5 on-disk format but it is optional // - this feature is enabled by default when using xfsprogs-5.1.0 or later // - this feature will be enabled if the original filesystem was XFS V5 and had it if (xfstoolsver >= PROGVER(4,9,0)) // only use "reflink" option when it is supported by mkfs { optval = ((xfsver==XFS_SB_VERSION_5) && (sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_REFLINK)); strlcatf(mkfsopts, sizeof(mkfsopts), " -m reflink=%d ", (int)optval); } // Determine if the "inobtcount" mkfs option should be enabled (inobt block counts) // - starting with linux-5.10 XFS has added block usage counters for inode btrees // to reduce mount times // - this optional feature relies on the V5 on-disk format and on the "finobt" // (free inode btree) mkfs option being enabled // - this feature is enabled by default when using xfsprogs-5.15.0 or later // - this feature will be enabled if the original filesystem was XFS V5 and had it if (xfstoolsver >= PROGVER(5,10,0)) // only use "inobtcount" option when it is supported by mkfs { optval = ((xfsver==XFS_SB_VERSION_5) && (sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_INOBTCNT)); strlcatf(mkfsopts, sizeof(mkfsopts), " -m inobtcount=%d ", (int)optval); } // Determine if the "bigtime" mkfs option should be enabled (large timestamps) // - starting with linux-5.10 XFS has added support for larger inode timestamps, beyond january 2038 // - this feature relies on the V5 on-disk format but it is optional // - this feature is enabled by default when using xfsprogs-5.15.0 or later // - this feature will be enabled if the original filesystem was XFS V5 and had it if (xfstoolsver >= PROGVER(5,10,0)) // only use "bigtime" option when it is supported by mkfs { optval = ((xfsver==XFS_SB_VERSION_5) && (sb_features_incompat & XFS_SB_FEAT_INCOMPAT_BIGTIME)); strlcatf(mkfsopts, sizeof(mkfsopts), " -m bigtime=%d ", (int)optval); } // Attempt to preserve filesystem UUID // - mkfs.xfs' "-m uuid=" option was added in version 4.3.0 and is the best way to set UUID // - XFS V4 UUID can be successfully set using either xfs_admin or mkfs.xfs >= 4.3.0 // - XFS V5 UUID, on the other hand, can't be set by xfs_admin without enabling a superblock // incompat flag which bumps minimal kernel version to linux-4.3 and sets two different UUIDs // in the filesystem: user-visible and metadata. For this reason XFS version is forced to V4 // if xfsprogs < 4.3.0 if (strlen(mkfsuuid) > 0) snprintf(uuid, sizeof(uuid), "%s", mkfsuuid); else if (dico_get_string(d, 0, FSYSHEADKEY_FSUUID, buffer, sizeof(buffer))==0) snprintf(uuid, sizeof(uuid), "%s", buffer); if (strlen(uuid)==36) { if (xfstoolsver >= PROGVER(4,3,0)) strlcatf(mkfsopts, sizeof(mkfsopts), " -m uuid=%s ", uuid); else strlcatf(xadmopts, sizeof(xadmopts), " -U %s ", uuid); } // Determine if the "ftype" mkfs option should be enabled (filetype in dirent) // - this feature allows the inode type to be stored in the directory structure // - this feature is madatory on XFS V5 (always enabled) but it is optional on XFS V4 // - mkfs.xfs 4.2.0 enabled it by default on XFS V4 filesystems // - the "ftype" option must be specified after the "crc" option in mkfs.xfs < 4.2.0: // https://git.kernel.org/pub/scm/fs/xfs/xfsprogs-dev.git/commit/?id=b990de8ba4e2df2bc76a140799d3ddb4a0eac4ce // - do not set ftype=1 with crc=1 as mkfs.xfs may fail (at least with xfsprogs-3.2.2) // - XFS V4 with ftype=1 is supported since linux-3.13. We purposely always disable it // on V4 filesystems to keep them compatible with older kernels if (xfstoolsver >= PROGVER(3,2,0)) // only use "ftype" option when it is supported by mkfs { // ftype is already set to 1 when it is XFS V5 if (xfsver==XFS_SB_VERSION_4) strlcatf(mkfsopts, sizeof(mkfsopts), " -n ftype=0 "); } // Determine if the "sparse" mkfs option should be enabled (sparse inode allocation) // - starting with linux-4.2 XFS can allocate discontinuous inode chunks // - this feature relies on the V5 on-disk format but it is optional // - this feature is enabled by default when using xfsprogs-4.16.0 or later // - this feature will be enabled if the original filesystem was XFS V5 and had it // - this feature is supported since mkfs.xfs 4.2.0 // - mkfs.xfs 4.5.0 in RHEL 7.3 carries a custom patch removing the option if (xfstoolsver >= PROGVER(4,2,0) && !match_uname_r(RHEL7_KERNEL_ERE)) // only use "sparse" option when it is supported by mkfs { optval = ((xfsver==XFS_SB_VERSION_5) && (sb_features_incompat & XFS_SB_FEAT_INCOMPAT_SPINODES)); strlcatf(mkfsopts, sizeof(mkfsopts), " -i sparse=%d ", (int)optval); } // Determine if the "nrext64" mkfs option should be enabled (large extent counters) // - starting with linux-5.19 XFS has added support for larger number of per-file extents // - this feature relies on the V5 on-disk format but it is optional // - this feature will be enabled if the original filesystem was XFS V5 and had it if (xfstoolsver >= PROGVER(5,19,0)) // only use "nrext64" option when it is supported by mkfs { optval = ((xfsver==XFS_SB_VERSION_5) && (sb_features_incompat & XFS_SB_FEAT_INCOMPAT_NREXT64)); strlcatf(mkfsopts, sizeof(mkfsopts), " -i nrext64=%d ", (int)optval); } // ---- mkfsopt from command line strlcatf(mkfsopts, sizeof(mkfsopts), " %s ", fsoptions); // ---- create the new filesystem using mkfs.xfs if (exec_command(command, sizeof(command), &exitst, NULL, 0, NULL, 0, "mkfs.xfs -f %s %s", mkfsopts, partition)!=0 || exitst!=0) { errprintf("command [%s] failed\n", command); return -1; } // ---- use xfs_admin to set the UUID if not already done with mkfs.xfs if (xadmopts[0]) { if (exec_command(command, sizeof(command), &exitst, NULL, 0, NULL, 0, "xfs_admin %s %s", xadmopts, partition)!=0 || exitst!=-0) { errprintf("command [%s] failed\n", command); return -1; } } return 0; } int xfs_getinfo(cdico *d, char *devname) { struct xfs_sb sb; char uuid[512]; u64 xfsver; u32 temp32; int ret=0; int fd; int res; u64 sb_features_compat=0; u64 sb_features_ro_compat=0; u64 sb_features_incompat=0; u64 sb_features_log_incompat=0; if ((fd=open64(devname, O_RDONLY|O_LARGEFILE))<0) { ret=-1; goto xfs_read_sb_return; } res=read(fd, &sb, sizeof(sb)); if (res!=sizeof(sb)) { ret=-1; goto xfs_read_sb_close; } // ---- check it's an XFS file system if (be32_to_cpu(sb.sb_magicnum) != XFS_SB_MAGIC) { ret=-1; msgprintf(3, "sb.sb_magicnum!=XFS_SB_MAGIC\n"); goto xfs_read_sb_close; } // ---- check XFS filesystem version xfsver=be16_to_cpu(sb.sb_versionnum) & XFS_SB_VERSION_NUMBITS; switch (xfsver) { case XFS_SB_VERSION_4: case XFS_SB_VERSION_5: msgprintf(MSG_DEBUG1, "Detected XFS filesystem version %d\n", (int)xfsver); dico_add_u64(d, 0, FSYSHEADKEY_FSXFSVERSION, xfsver); break; default: ret=-1; msgprintf(MSG_STACK, "Invalid XFS filesystem version: version=[%d]\n", (int)xfsver); goto xfs_read_sb_close; break; } // ---- label msgprintf(MSG_DEBUG1, "xfs_label=[%s]\n", sb.sb_fname); dico_add_string(d, 0, FSYSHEADKEY_FSLABEL, (char*)sb.sb_fname); // ---- uuid /*if ((str=e2p_uuid2str(&sb.sb_uuid))!=NULL) dico_add_string(d, 0, FSYSHEADKEY_FSUUID, str);*/ memset(uuid, 0, sizeof(uuid)); uuid_unparse_lower((u8*)&sb.sb_uuid, uuid); dico_add_string(d, 0, FSYSHEADKEY_FSUUID, uuid); msgprintf(MSG_DEBUG1, "xfs_uuid=[%s]\n", uuid); // ---- block size temp32=be32_to_cpu(sb.sb_blocksize); if ((temp32%512!=0) || (temp32<512) || (temp32>65536)) { ret=-1; msgprintf(3, "xfs_blksize=[%ld] is an invalid xfs block size\n", (long)temp32); goto xfs_read_sb_close; } dico_add_u64(d, 0, FSYSHEADKEY_FSXFSBLOCKSIZE, temp32); msgprintf(MSG_DEBUG1, "xfs_blksize=[%ld]\n", (long)temp32); // ---- get filesystem features (will all be set to 0 if this is XFS V4) if (xfsver == XFS_SB_VERSION_5) { sb_features_compat=be32_to_cpu(sb.sb_features_compat); sb_features_ro_compat=be32_to_cpu(sb.sb_features_ro_compat); sb_features_incompat=be32_to_cpu(sb.sb_features_incompat); sb_features_log_incompat=be32_to_cpu(sb.sb_features_log_incompat); } // ---- check fsarchiver is aware of all the filesystem features used on that filesystem if (xfs_check_compatibility(sb_features_compat, sb_features_ro_compat, sb_features_incompat, sb_features_log_incompat)!=0) return -1; // ---- store features in the archive metadata dico_add_u64(d, 0, FSYSHEADKEY_FSXFSFEATURECOMPAT, (u64)sb_features_compat); dico_add_u64(d, 0, FSYSHEADKEY_FSXFSFEATUREROCOMPAT, (u64)sb_features_ro_compat); dico_add_u64(d, 0, FSYSHEADKEY_FSXFSFEATUREINCOMPAT, (u64)sb_features_incompat); dico_add_u64(d, 0, FSYSHEADKEY_FSXFSFEATURELOGINCOMPAT, (u64)sb_features_log_incompat); // ---- minimum fsarchiver version required to restore dico_add_u64(d, 0, FSYSHEADKEY_MINFSAVERSION, FSA_VERSION_BUILD(0, 6, 20, 0)); xfs_read_sb_close: close(fd); xfs_read_sb_return: return ret; } int xfs_mount(char *partition, char *mntbuf, char *fsbuf, int flags, char *mntinfo) { return generic_mount(partition, mntbuf, fsbuf, "nouuid", flags); } int xfs_umount(char *partition, char *mntbuf) { return generic_umount(mntbuf); } int xfs_test(char *devname) { struct xfs_sb sb; int fd; if ((fd=open64(devname, O_RDONLY|O_LARGEFILE))<0) { msgprintf(MSG_DEBUG1, "open64(%s) failed\n", devname); return false; } memset(&sb, 0, sizeof(sb)); if (read(fd, &sb, sizeof(sb))!=sizeof(sb)) { close(fd); msgprintf(MSG_DEBUG1, "read failed\n"); return false; } // ---- check it's an XFS file system if (be32_to_cpu(sb.sb_magicnum) != XFS_SB_MAGIC) { close(fd); msgprintf(MSG_DEBUG1, "(be32_to_cpu(sb.sb_magicnum)=%.8x) != (XFS_SB_MAGIC=%.8x)\n", be32_to_cpu(sb.sb_magicnum), XFS_SB_MAGIC); return false; } close(fd); return true; } int xfs_get_reqmntopt(char *partition, cstrlist *reqopt, cstrlist *badopt) { if (!reqopt || !badopt) return -1; return 0; } fsarchiver-0.8.7/src/dichl.h0000644000175000017500000000214214405605077012635 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifndef __DICHL_H__ #define __DICHL_H__ #include "types.h" struct s_dichl; typedef struct s_dichl cdichl; struct s_dichlitem; typedef struct s_dichlitem cdichlitem; struct s_dichl { cdichlitem *head; }; struct s_dichlitem { u64 key1; u64 key2; char *str; cdichlitem *next; }; cdichl *dichl_alloc(); int dichl_destroy(cdichl *d); int dichl_add(cdichl *d, u64 key1, u64 key2, char *str); int dichl_get(cdichl *d, u64 key1, u64 key2, char *buf, int bufsize); #endif // __DICHL_H__ fsarchiver-0.8.7/src/Makefile.am0000644000175000017500000000332714405605077013443 00000000000000sbin_PROGRAMS = fsarchiver fsarchiver_SOURCES = fsarchiver.c oper_save.c oper_restore.c oper_probe.c \ thread_archio.c archreader.c archwriter.c writebuf.c archinfo.c \ thread_comp.c comp_gzip.c comp_bzip2.c comp_lzma.c comp_lzo.c comp_lz4.c \ comp_zstd.c crypto.c fs_ntfs.c fs_ext2.c fs_reiserfs.c fs_reiser4.c \ fs_btrfs.c fs_xfs.c fs_jfs.c fs_vfat.c common.c dico.c strdico.c dichl.c \ queue.c error.c syncthread.c datafile.c strlist.c regmulti.c options.c \ logfile.c filesys.c devinfo.c noinst_HEADERS = fsarchiver.h oper_save.h oper_restore.h oper_probe.h \ thread_archio.h archreader.h archwriter.h writebuf.h archinfo.h \ thread_comp.h comp_gzip.h comp_bzip2.h comp_lzma.h comp_lzo.h comp_lz4.h \ comp_zstd.h crypto.h fs_ntfs.h fs_ext2.h fs_reiserfs.h fs_reiser4.h \ fs_btrfs.h fs_xfs.h fs_jfs.h fs_vfat.h common.h dico.h strdico.h dichl.h \ queue.h error.h syncthread.h datafile.h strlist.h regmulti.h options.h \ logfile.h types.h filesys.h devinfo.h fsarchiver_LDADD = -lpthread -lrt \ $(LZMA_LIBS) \ $(EXT2FS_LIBS) \ $(COM_ERR_LIBS) \ $(E2P_LIBS) \ $(BLKID_LIBS) \ $(UUID_LIBS) fsarchiver_CFLAGS = @CFLAGS@ -Wall -std=gnu99 -rdynamic -ggdb \ $(LZMA_CFLAGS) \ $(EXT2FS_CFLAGS) \ $(COM_ERR_CFLAGS) \ $(E2P_CFLAGS) \ $(BLKID_CFLAGS) \ $(UUID_CFLAGS) fsarchiver_LDFLAGS = @FSARCHIVER_LDFLAGS@ DEFS=@DEFS@ -D_REENTRANT -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE -D_GNU_SOURCE MAINTAINERCLEANFILES = Makefile.in fsarchiver-0.8.7/src/logfile.c0000644000175000017500000000356414405605077013177 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include #include #include #include #include #include "fsarchiver.h" #include "logfile.h" #include "common.h" #include "error.h" int g_logfile=-1; int logfile_open() { char logpath[PATH_MAX]; char timestamp[1024]; char *logdir="/var/log"; format_time(timestamp, sizeof(timestamp), time(NULL)); snprintf(logpath, sizeof(logpath), "%s/fsarchiver_%s_%ld.log", logdir, timestamp, (long)getpid()); mkdir_recursive(logdir); g_logfile=open64(logpath, O_RDWR|O_CREAT|O_TRUNC|O_LARGEFILE, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); if (g_logfile>=0) { msgprintf(MSG_VERB1, "Creating logfile in %s\n", logpath); msgprintf(MSG_VERB1, "Running fsarchiver version=[%s], fileformat=[%s]\n", FSA_VERSION, FSA_FILEFORMAT); return FSAERR_SUCCESS; } else { sysprintf("Cannot create logfile in %s\n", logpath); return FSAERR_UNKNOWN; } } int logfile_close() { close(g_logfile); return FSAERR_SUCCESS; } int logfile_write(char *str, int len) { if (g_logfile>=0) return write(g_logfile, str, len); else return FSAERR_UNKNOWN; } fsarchiver-0.8.7/src/comp_lzo.c0000644000175000017500000000360114405605077013370 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include "fsarchiver.h" #include "comp_lzo.h" #include "error.h" #ifdef OPTION_LZO_SUPPORT int compress_block_lzo(u64 origsize, u64 *compsize, u8 *origbuf, u8 *compbuf, u64 compbufsize, int level) { lzo_uint destsize=(lzo_uint)compbufsize; char workmem[LZO1X_1_MEM_COMPRESS]; switch (lzo1x_1_compress((lzo_bytep)origbuf, (lzo_uint)origsize, (lzo_bytep)compbuf, (lzo_uintp)&destsize, (lzo_voidp)workmem)) { case LZO_E_OK: *compsize=(u64)destsize; return FSAERR_SUCCESS; case LZO_E_OUT_OF_MEMORY: return FSAERR_ENOMEM; default: return FSAERR_UNKNOWN; } return FSAERR_UNKNOWN; } int uncompress_block_lzo(u64 compsize, u64 *origsize, u8 *origbuf, u64 origbufsize, u8 *compbuf) { lzo_uint new_len=origbufsize; int res; switch ((res=lzo1x_decompress_safe(compbuf, compsize, origbuf, &new_len, NULL))) { case LZO_E_OK: *origsize=(u64)new_len; return FSAERR_SUCCESS; case LZO_E_OUT_OF_MEMORY: return FSAERR_ENOMEM; default: errprintf("lzo1x_decompress_safe() failed, res=%d\n", res); return FSAERR_UNKNOWN; } return FSAERR_UNKNOWN; } #endif // OPTION_LZO_SUPPORT fsarchiver-0.8.7/src/syncthread.c0000644000175000017500000000473014405605077013716 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include "fsarchiver.h" #include "fsarchiver.h" #include "syncthread.h" #include "queue.h" // queue use to share data between the three sort of threads cqueue g_queue; // filesystem bitmap used by do_extract() to say to threadio_readimg which filesystems to skip // eg: "g_fsbitmap[0]=1,g_fsbitmap[1]=0" means that we want to read filesystem 0 and skip fs 1 u8 g_fsbitmap[FSA_MAX_FSPERARCH]; // g_stopfillqueue is set to true when the threads that reads the queue wants to stop // either because there is an error or because it does not need the next data atomic_t g_stopfillqueue={ (false) }; atomic_t g_aborted={ (false) }; void set_stopfillqueue() { atomic_set(&g_stopfillqueue, true); } bool get_stopfillqueue() { return atomic_read(&g_stopfillqueue); } // how many secondary threads are running (compression/decompression and archio threads) atomic_t g_secthreads={ (0) }; void inc_secthreads() { (void)__sync_add_and_fetch(&g_secthreads.counter, 1); } void dec_secthreads() { (void)__sync_sub_and_fetch(&g_secthreads.counter, 1); } int get_secthreads() { return atomic_read(&g_secthreads); } bool get_interrupted() { return (get_abort()==true || get_stopfillqueue()==true); } // get_abort() returns true if a SIGINT/SIGTERM has been received (interrupted by the user) int get_abort() { int mysigs[]={SIGINT, SIGTERM, -1}; sigset_t mask_set; sigpending(&mask_set); int i; if (atomic_read(&g_aborted)==true) return true; if (sigpending(&mask_set)==0) { for (i=0; mysigs[i]!=-1; i++) { if (sigismember(&mask_set, mysigs[i])) { //msgprintf(MSG_FORCE, "get_terminate(): received signal %d\n", mysigs[i]); atomic_set(&g_aborted, true); return true; } } } return false; } fsarchiver-0.8.7/src/dico.h0000644000175000017500000000434214405605077012474 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifndef __DICO_H__ #define __DICO_H__ #include "types.h" enum {DICO_ESUCCESS=0, DICO_ENOENT, DICO_EINVAL, DICO_EBADSIZE, DICO_EFULL, DICO_EMEM, DICO_EDUPLICATE, DICO_EINVALCHAR}; enum {DICTYPE_NULL=0, DICTYPE_U8, DICTYPE_U16, DICTYPE_U32, DICTYPE_U64, DICTYPE_DATA, DICTYPE_STRING}; struct s_dico; struct s_dicoitem; typedef struct s_dico cdico; typedef struct s_dicoitem cdicoitem; struct s_dico { struct s_dicoitem *head; }; struct s_dicoitem { u8 type; u8 section; u16 key; u16 size; char *data; cdicoitem *next; }; cdico *dico_alloc(); int dico_destroy(cdico *d); int dico_show(cdico *d, u8 section, char *debugtxt); int dico_count_all_sections(cdico *d); int dico_count_one_section(cdico *d, u8 section); int dico_add_data(cdico *d, u8 section, u16 key, const void *data, u16 size); int dico_add_generic(cdico *d, u8 section, u16 key, const void *data, u16 size, u8 type); int dico_get_generic(cdico *d, u8 section, u16 key, void *data, u16 maxsize, u16 *size); int dico_get_data(cdico *d, u8 section, u16 key, void *data, u16 maxsize, u16 *size); int dico_add_u16(cdico *d, u8 section, u16 key, u16 data); int dico_add_u32(cdico *d, u8 section, u16 key, u32 data); int dico_add_u64(cdico *d, u8 section, u16 key, u64 data); int dico_get_u16(cdico *d, u8 section, u16 key, u16 *data); int dico_get_u32(cdico *d, u8 section, u16 key, u32 *data); int dico_get_u64(cdico *d, u8 section, u16 key, u64 *data); int dico_add_string(cdico *d, u8 section, u16 key, const char *szstring); int dico_get_string(cdico *d, u8 section, u16 key, char *buffer, u16 bufsize); #endif // __DICO_H__ fsarchiver-0.8.7/src/datafile.c0000644000175000017500000001133114405605077013316 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include #include #include #include #include "fsarchiver.h" #include "datafile.h" #include "common.h" #include "error.h" struct s_datafile { int fd; // file descriptor bool simul; // simulation: don't write anything if true bool open; // true when file is open even if simulation bool sparse; // true if that's a sparse file char path[PATH_MAX]; // path to file gcry_md_hd_t md5ctx; // struct for md5 }; cdatafile *datafile_alloc() { cdatafile *f; if ((f=malloc(sizeof(cdatafile)))==NULL) return NULL; f->path[0]=0; f->fd=-1; f->simul=false; f->open=false; f->sparse=false; return f; } int datafile_destroy(cdatafile *f) { assert(f); if (f->open) datafile_close(f, NULL, 0); free(f); return 0; } int datafile_open_write(cdatafile *f, char *path, bool simul, bool sparse) { assert(f); if (f->open) { errprintf("File is already open\n"); return -1; } if (simul==false) { errno=0; if ((f->fd=open64(path, O_RDWR|O_CREAT|O_TRUNC|O_LARGEFILE, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH))<0) { if (errno==ENOSPC) { sysprintf("can't write file [%s]: no space left on device\n", path); return -1; // fatal error } else { sysprintf("Cannot open %s for writing\n", path); return -1; } } } if (gcry_md_open(&f->md5ctx, GCRY_MD_MD5, 0) != GPG_ERR_NO_ERROR) { errprintf("gcry_md_open() failed\n"); return -1; } snprintf(f->path, PATH_MAX, "%s", path); f->simul=simul; f->open=true; f->sparse=sparse; return 0; } int datafile_is_block_zero(cdatafile *f, char *data, u64 len) { bool zero=true; u64 pos; for (pos=0; (posopen) { errprintf("File is not open\n"); return FSAERR_NOTOPEN; } if (f->simul==false) { if ((f->sparse==true) && (datafile_is_block_zero(f, data, len))) { if (lseek64(f->fd, len, SEEK_CUR)<0) { sysprintf("Can't lseek64() in file [%s]\n", f->path); return FSAERR_SEEK; } } else { errno=0; if ((lres=write(f->fd, data, len))!=len) // error { if ((errno==ENOSPC) || ((lres>0) && (lres < len))) { sysprintf("Can't write file [%s]: no space left on device\n", f->path); return FSAERR_ENOSPC; } else // another error { sysprintf("cannot write %s: size=%ld\n", f->path, (long)len); return FSAERR_WRITE; } } } } gcry_md_write(f->md5ctx, data, len); return FSAERR_SUCCESS; } int datafile_close(cdatafile *f, u8 *md5bufdat, int md5bufsize) { char md5store[16]; u8 *md5tmp; int res=0; assert(f); if (!f->open) { errprintf("File is not open\n"); return -1; } if ((md5tmp=gcry_md_read(f->md5ctx, GCRY_MD_MD5))==NULL) { errprintf("gcry_md_read() failed\n"); return -1; } memcpy(md5store, md5tmp, 16); gcry_md_close(f->md5ctx); if (md5bufdat!=NULL) { if (md5bufsize < 16) { errprintf("Buffer too small for md5 checksum\n"); return -1; } memcpy(md5bufdat, md5store, 16); } if ((f->open==true) && (f->simul==false)) { if ((f->sparse==true) && (ftruncate(f->fd, lseek64(f->fd, 0, SEEK_CUR))<0)) { sysprintf("ftruncate() failed for file [%s]\n", f->path); res=-1; } res=min(close(f->fd), res); } f->open=false; f->path[0]=0; f->fd=-1; return res; } fsarchiver-0.8.7/src/fs_btrfs.h0000644000175000017500000001444714405605077013375 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifndef __FS_BTRFS_H__ #define __FS_BTRFS_H__ struct s_dico; struct s_strlist; int btrfs_mkfs(struct s_dico *d, char *partition, char *fsoptions, char *mkfslabel, char *mkfsuuid); int btrfs_getinfo(struct s_dico *d, char *devname); int btrfs_mount(char *partition, char *mntbuf, char *fsbuf, int flags, char *mntinfo); int btrfs_umount(char *partition, char *mntbuf); int btrfs_check_support_for_features(u64 compat, u64 incompat, u64 ro_compat); int btrfs_get_reqmntopt(char *partition, struct s_strlist *reqopt, struct s_strlist *badopt); int btrfs_test(char *devname); // compat flags: official definition from linux-5.15/fs/btrfs/ctree.h // and linux-5.15/include/uapi/linux/btrfs.h #define BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE (1ULL << 0) #define BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID (1ULL << 1) #define BTRFS_FEATURE_COMPAT_RO_VERITY (1ULL << 2) #define BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF (1ULL << 0) #define BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL (1ULL << 1) #define BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS (1ULL << 2) #define BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO (1ULL << 3) #define BTRFS_FEATURE_INCOMPAT_COMPRESS_ZSTD (1ULL << 4) #define BTRFS_FEATURE_INCOMPAT_BIG_METADATA (1ULL << 5) #define BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF (1ULL << 6) #define BTRFS_FEATURE_INCOMPAT_RAID56 (1ULL << 7) #define BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA (1ULL << 8) #define BTRFS_FEATURE_INCOMPAT_NO_HOLES (1ULL << 9) #define BTRFS_FEATURE_INCOMPAT_METADATA_UUID (1ULL << 10) #define BTRFS_FEATURE_INCOMPAT_RAID1C34 (1ULL << 11) #define BTRFS_FEATURE_INCOMPAT_ZONED (1ULL << 12) // compat flags: btrfs features that this fsarchiver version supports #define FSA_BTRFS_FEATURE_COMPAT_SUPP 0ULL #define FSA_BTRFS_FEATURE_COMPAT_RO_SUPP \ (BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE | \ BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID | \ BTRFS_FEATURE_COMPAT_RO_VERITY) #define FSA_BTRFS_FEATURE_INCOMPAT_SUPP \ (BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF | \ BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL | \ BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS | \ BTRFS_FEATURE_INCOMPAT_BIG_METADATA | \ BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO | \ BTRFS_FEATURE_INCOMPAT_COMPRESS_ZSTD | \ BTRFS_FEATURE_INCOMPAT_RAID56 | \ BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF | \ BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA | \ BTRFS_FEATURE_INCOMPAT_NO_HOLES | \ BTRFS_FEATURE_INCOMPAT_METADATA_UUID | \ BTRFS_FEATURE_INCOMPAT_RAID1C34 | \ BTRFS_FEATURE_INCOMPAT_ZONED) // disk layout definitions #define BTRFS_SUPER_MAGIC 0x9123683E #define BTRFS_MAGIC "_BHRfS_M" #define BTRFS_SUPER_INFO_OFFSET (64 * 1024) #define BTRFS_SUPER_INFO_SIZE 4096 #define BTRFS_SUPER_MIRROR_MAX 3 #define BTRFS_SUPER_MIRROR_SHIFT 12 #define BTRFS_NAME_LEN 255 #define BTRFS_CSUM_SIZE 32 #define BTRFS_CSUM_TYPE_CRC32 0 #define BTRFS_FSID_SIZE 16 #define BTRFS_HEADER_FLAG_WRITTEN (1 << 0) #define BTRFS_SYSTEM_CHUNK_ARRAY_SIZE 2048 #define BTRFS_LABEL_SIZE 256 #define BTRFS_UUID_SIZE 16 static inline u64 btrfs_sb_offset(int mirror) { u64 start = 16 * 1024; if (mirror) return start << (BTRFS_SUPER_MIRROR_SHIFT * mirror); return BTRFS_SUPER_INFO_OFFSET; } struct btrfs_dev_item { /* the internal btrfs device id */ __le64 devid; /* size of the device */ __le64 total_bytes; /* bytes used */ __le64 bytes_used; /* optimal io alignment for this device */ __le32 io_align; /* optimal io width for this device */ __le32 io_width; /* minimal io size for this device */ __le32 sector_size; /* type and info about this device */ __le64 type; /* expected generation for this device */ __le64 generation; /* * starting byte of this partition on the device, * to allowr for stripe alignment in the future */ __le64 start_offset; /* grouping information for allocation decisions */ __le32 dev_group; /* seek speed 0-100 where 100 is fastest */ u8 seek_speed; /* bandwidth 0-100 where 100 is fastest */ u8 bandwidth; /* btrfs generated uuid for this device */ u8 uuid[BTRFS_UUID_SIZE]; /* uuid of FS who owns this device */ u8 fsid[BTRFS_UUID_SIZE]; } __attribute__ ((__packed__)); /* * the super block basically lists the main trees of the FS * it currently lacks any block count etc etc */ struct btrfs_super_block { u8 csum[BTRFS_CSUM_SIZE]; /* the first 4 fields must match struct btrfs_header */ u8 fsid[BTRFS_FSID_SIZE]; /* FS specific uuid */ __le64 bytenr; /* this block number */ __le64 flags; /* allowed to be different from the btrfs_header from here own down */ __le64 magic; __le64 generation; __le64 root; __le64 chunk_root; __le64 log_root; /* this will help find the new super based on the log root */ __le64 log_root_transid; __le64 total_bytes; __le64 bytes_used; __le64 root_dir_objectid; __le64 num_devices; __le32 sectorsize; __le32 nodesize; __le32 leafsize; __le32 stripesize; __le32 sys_chunk_array_size; __le64 chunk_root_generation; __le64 compat_flags; __le64 compat_ro_flags; __le64 incompat_flags; __le16 csum_type; u8 root_level; u8 chunk_root_level; u8 log_root_level; struct btrfs_dev_item dev_item; char label[BTRFS_LABEL_SIZE]; /* future expansion */ __le64 reserved[32]; u8 sys_chunk_array[BTRFS_SYSTEM_CHUNK_ARRAY_SIZE]; } __attribute__ ((__packed__)); #endif // __FS_BTRFS_H__ fsarchiver-0.8.7/src/datafile.h0000644000175000017500000000177514405605077013336 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifndef __DATAFILE_H__ #define __DATAFILE_H__ #include "types.h" struct s_datafile; typedef struct s_datafile cdatafile; cdatafile *datafile_alloc(); int datafile_destroy(cdatafile *f); int datafile_open_write(cdatafile *f, char *path, bool simul, bool sparse); int datafile_write(cdatafile *f, char *data, u64 len); int datafile_close(cdatafile *f, u8 *md5bufdat, int md5bufsize); #endif // __DATAFILE_H__ fsarchiver-0.8.7/src/thread_archio.h0000644000175000017500000000140214405605077014344 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifndef __THREAD_WRITER_H__ #define __THREAD_WRITER_H__ #include void *thread_writer_fct(void *args); void *thread_reader_fct(void *args); #endif // __THREAD_WRITER_H__ fsarchiver-0.8.7/src/thread_comp.c0000644000175000017500000003325114405605077014037 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include #include "fsarchiver.h" #include "common.h" #include "options.h" #include "comp_gzip.h" #include "comp_bzip2.h" #include "comp_lzma.h" #include "comp_lzo.h" #include "comp_lz4.h" #include "comp_zstd.h" #include "crypto.h" #include "syncthread.h" #include "thread_comp.h" #include "error.h" #include "queue.h" int compress_block_generic(struct s_blockinfo *blkinfo) { char *bufcomp=NULL; int attempt=0; int compalgo; int complevel; u64 compsize; u64 bufsize; int res; #ifdef OPTION_ZSTD_SUPPORT bool zstd=true; #else bool zstd=false; #endif bufsize = (blkinfo->blkrealsize) + (blkinfo->blkrealsize / 16) + 64 + 3; // alloc bigger buffer else lzo will crash if ((bufcomp=malloc(bufsize))==NULL) { errprintf("malloc(%ld) failed: out of memory\n", (long)bufsize); return -1; } // compression level/algo to use for the first attempt compalgo=g_options.compressalgo; complevel=g_options.compresslevel; // compress the block do { switch (compalgo) { #ifdef OPTION_LZO_SUPPORT case COMPRESS_LZO: res=compress_block_lzo(blkinfo->blkrealsize, &compsize, (u8*)blkinfo->blkdata, (void*)bufcomp, bufsize, complevel); blkinfo->blkcompalgo=COMPRESS_LZO; break; #endif // OPTION_LZO_SUPPORT case COMPRESS_GZIP: res=compress_block_gzip(blkinfo->blkrealsize, &compsize, (u8*)blkinfo->blkdata, (void*)bufcomp, bufsize, complevel); blkinfo->blkcompalgo=COMPRESS_GZIP; break; case COMPRESS_BZIP2: res=compress_block_bzip2(blkinfo->blkrealsize, &compsize, (u8*)blkinfo->blkdata, (void*)bufcomp, bufsize, complevel); blkinfo->blkcompalgo=COMPRESS_BZIP2; break; #ifdef OPTION_LZMA_SUPPORT case COMPRESS_LZMA: res=compress_block_lzma(blkinfo->blkrealsize, &compsize, (u8*)blkinfo->blkdata, (void*)bufcomp, bufsize, complevel); blkinfo->blkcompalgo=COMPRESS_LZMA; break; #endif // OPTION_LZMA_SUPPORT #ifdef OPTION_LZ4_SUPPORT case COMPRESS_LZ4: res=compress_block_lz4(blkinfo->blkrealsize, &compsize, (u8*)blkinfo->blkdata, (void*)bufcomp, bufsize, complevel); blkinfo->blkcompalgo=COMPRESS_LZ4; break; #endif // OPTION_LZ4_SUPPORT #ifdef OPTION_ZSTD_SUPPORT case COMPRESS_ZSTD: res=compress_block_zstd(blkinfo->blkrealsize, &compsize, (u8*)blkinfo->blkdata, (void*)bufcomp, bufsize, complevel); blkinfo->blkcompalgo=COMPRESS_ZSTD; break; #endif // OPTION_ZSTD_SUPPORT default: free(bufcomp); errprintf("unsupported compression algorithm: %d\n", compalgo); return -1; } // retry if high compression was used and compression failed because of FSAERR_ENOMEM // at this point, if zstd is not supported, compalgo == COMPRESS_ZSTD cannot be true if (res == FSAERR_ENOMEM && ((compalgo == COMPRESS_ZSTD && complevel > FSA_DEF_COMPRESS_LEVEL) || compalgo != FSA_DEF_COMPRESS_ALGO)) { errprintf("attempt to compress the current block using an alternative algorithm (\"%s%d\")\n", zstd ? "-Z" : "-z", zstd ? FSA_DEF_COMPRESS_LEVEL : FSA_DEF_FSACOMP_LEVEL); compalgo = FSA_DEF_COMPRESS_ALGO; complevel = FSA_DEF_COMPRESS_LEVEL; } } while ((res == FSAERR_ENOMEM) && (attempt++ == 0)); // check compression status and efficiency if ((res==FSAERR_SUCCESS) && (compsize < blkinfo->blkrealsize)) // compression worked and saved space { free(blkinfo->blkdata); // free old buffer (with uncompressed data) blkinfo->blkdata=bufcomp; // new buffer (with compressed data) blkinfo->blkcompsize=compsize; // size after compression and before encryption blkinfo->blkarsize=compsize; // in case there is no encryption to set this //errprintf("COMP_DBG: block successfully compressed using algorithm %d level %d\n", compalgo, complevel); } else // compressed version is bigger or compression failed: keep the original block { memcpy(bufcomp, blkinfo->blkdata, blkinfo->blkrealsize); free(blkinfo->blkdata); // free old buffer blkinfo->blkdata=bufcomp; // new buffer blkinfo->blkcompsize=blkinfo->blkrealsize; // size after compression and before encryption blkinfo->blkarsize=blkinfo->blkrealsize; // in case there is no encryption to set this blkinfo->blkcompalgo=COMPRESS_NONE; //errprintf("COMP_DBG: block copied uncompressed, attempted using algorithm %d level %d\n", compalgo, complevel); } u64 cryptsize; char *bufcrypt=NULL; if (g_options.encryptalgo==ENCRYPT_BLOWFISH) { if ((bufcrypt=malloc(bufsize+8))==NULL) { errprintf("malloc(%ld) failed: out of memory\n", (long)bufsize+8); return -1; } if ((res=crypto_blowfish(blkinfo->blkcompsize, &cryptsize, (u8*)bufcomp, (u8*)bufcrypt, g_options.encryptpass, strlen((char*)g_options.encryptpass), 1))!=0) { errprintf("crypt_block_blowfish() failed with res=%d\n", res); return -1; } free(bufcomp); blkinfo->blkdata=bufcrypt; blkinfo->blkarsize=cryptsize; blkinfo->blkcryptalgo=ENCRYPT_BLOWFISH; } else { blkinfo->blkcryptalgo=ENCRYPT_NONE; } // calculates the final block checksum (block as it will be stored in the archive) blkinfo->blkarcsum=fletcher32((void*)blkinfo->blkdata, blkinfo->blkarsize); return 0; } int decompress_block_generic(struct s_blockinfo *blkinfo) { u64 checkorigsize; char *bufcomp=NULL; int res; // allocate memory for uncompressed data if ((bufcomp=malloc(blkinfo->blkrealsize))==NULL) { errprintf("malloc(%ld) failed: cannot allocate memory for compressed block\n", (long)blkinfo->blkrealsize); return -1; } // check the block checksum if (fletcher32((u8*)blkinfo->blkdata, blkinfo->blkarsize)!=(blkinfo->blkarcsum)) { errprintf("block is corrupt at blockoffset=%ld, blksize=%ld\n", (long)blkinfo->blkoffset, (long)blkinfo->blkrealsize); memset(bufcomp, 0, blkinfo->blkrealsize); } else // data not corrupted, decompresses the block { if ((blkinfo->blkcryptalgo!=ENCRYPT_NONE) && (g_options.encryptalgo!=ENCRYPT_BLOWFISH)) { msgprintf(MSG_DEBUG1, "this archive has been encrypted, you have to provide a password " "on the command line using option '-c'\n"); free (bufcomp); return -1; } char *bufcrypt=NULL; u64 clearsize; if (blkinfo->blkcryptalgo==ENCRYPT_BLOWFISH) { if ((bufcrypt=malloc(blkinfo->blkrealsize+8))==NULL) { errprintf("malloc(%ld) failed: out of memory\n", (long)blkinfo->blkrealsize+8); free(bufcomp); return -1; } if ((res=crypto_blowfish(blkinfo->blkarsize, &clearsize, (u8*)blkinfo->blkdata, (u8*)bufcrypt, g_options.encryptpass, strlen((char*)g_options.encryptpass), 0))!=0) { errprintf("crypt_block_blowfish() failed\n"); free(bufcomp); return -1; } if (clearsize!=blkinfo->blkcompsize) { errprintf("clearsize does not match blkcompsize: clearsize=%ld and blkcompsize=%ld\n", (long)clearsize, (long)blkinfo->blkcompsize); free(bufcomp); return -1; } free(blkinfo->blkdata); blkinfo->blkdata=bufcrypt; } switch (blkinfo->blkcompalgo) { case COMPRESS_NONE: memcpy(bufcomp, blkinfo->blkdata, blkinfo->blkarsize); res=0; break; #ifdef OPTION_LZO_SUPPORT case COMPRESS_LZO: if ((res=uncompress_block_lzo(blkinfo->blkcompsize, &checkorigsize, (void*)bufcomp, blkinfo->blkrealsize, (u8*)blkinfo->blkdata))!=0) { errprintf("uncompress_block_lzo()=%d failed: finalsize=%ld and checkorigsize=%ld\n", res, (long)blkinfo->blkarsize, (long)checkorigsize); memset(bufcomp, 0, blkinfo->blkrealsize); // TODO: inc(error_counter); } break; #endif // OPTION_LZO_SUPPORT case COMPRESS_GZIP: if ((res=uncompress_block_gzip(blkinfo->blkcompsize, &checkorigsize, (void*)bufcomp, blkinfo->blkrealsize, (u8*)blkinfo->blkdata))!=0) { errprintf("uncompress_block_gzip()=%d failed: finalsize=%ld and checkorigsize=%ld\n", res, (long)blkinfo->blkarsize, (long)checkorigsize); memset(bufcomp, 0, blkinfo->blkrealsize); // TODO: inc(error_counter); } break; case COMPRESS_BZIP2: if ((res=uncompress_block_bzip2(blkinfo->blkcompsize, &checkorigsize, (void*)bufcomp, blkinfo->blkrealsize, (u8*)blkinfo->blkdata))!=0) { errprintf("uncompress_block_bzip2()=%d failed: finalsize=%ld and checkorigsize=%ld\n", res, (long)blkinfo->blkarsize, (long)checkorigsize); memset(bufcomp, 0, blkinfo->blkrealsize); // TODO: inc(error_counter); } break; #ifdef OPTION_LZMA_SUPPORT case COMPRESS_LZMA: if ((res=uncompress_block_lzma(blkinfo->blkcompsize, &checkorigsize, (void*)bufcomp, blkinfo->blkrealsize, (u8*)blkinfo->blkdata))!=0) { errprintf("uncompress_block_lzma()=%d failed: finalsize=%ld and checkorigsize=%ld\n", res, (long)blkinfo->blkarsize, (long)checkorigsize); memset(bufcomp, 0, blkinfo->blkrealsize); // TODO: inc(error_counter); } break; #endif // OPTION_LZMA_SUPPORT #ifdef OPTION_LZ4_SUPPORT case COMPRESS_LZ4: if ((res=uncompress_block_lz4(blkinfo->blkcompsize, &checkorigsize, (void*)bufcomp, blkinfo->blkrealsize, (u8*)blkinfo->blkdata))!=0) { errprintf("uncompress_block_lz4()=%d failed: finalsize=%ld and checkorigsize=%ld\n", res, (long)blkinfo->blkarsize, (long)checkorigsize); memset(bufcomp, 0, blkinfo->blkrealsize); // TODO: inc(error_counter); } break; #endif // OPTION_LZ4_SUPPORT #ifdef OPTION_ZSTD_SUPPORT case COMPRESS_ZSTD: if ((res=uncompress_block_zstd(blkinfo->blkcompsize, &checkorigsize, (void*)bufcomp, blkinfo->blkrealsize, (u8*)blkinfo->blkdata))!=0) { errprintf("uncompress_block_zstd()=%d failed: finalsize=%ld and checkorigsize=%ld\n", res, (long)blkinfo->blkarsize, (long)checkorigsize); memset(bufcomp, 0, blkinfo->blkrealsize); // TODO: inc(error_counter); } break; #endif // OPTION_ZSTD_SUPPORT default: errprintf("unsupported compression algorithm: %d\n", blkinfo->blkcompalgo); return -1; } free(blkinfo->blkdata); // free old buffer (with compressed data) blkinfo->blkdata=bufcomp; // pointer to new buffer with uncompressed data } return 0; } int compression_function(int oper) { struct s_blockinfo blkinfo; s64 blknum; int res; while (queue_get_end_of_queue(&g_queue)==false) { if ((blknum=queue_get_first_block_todo(&g_queue, &blkinfo))>0) // block found { switch (oper) { case COMPTHR_COMPRESS: res=compress_block_generic(&blkinfo); break; case COMPTHR_DECOMPRESS: res=decompress_block_generic(&blkinfo); break; default: errprintf("oper is invalid: %d\n", oper); goto thread_comp_fct_error; } if (res!=0) { msgprintf(MSG_STACK, "compress_block()=%d failed\n", res); goto thread_comp_fct_error; } // don't check for errors: it's normal to fail when we terminate after a problem queue_replace_block(&g_queue, blknum, &blkinfo, QITEM_STATUS_DONE); } } msgprintf(MSG_DEBUG1, "THREAD-COMP: exit success\n"); return 0; thread_comp_fct_error: get_stopfillqueue(); msgprintf(MSG_DEBUG1, "THREAD-COMP: exit error\n"); return 0; } void *thread_comp_fct(void *args) { inc_secthreads(); compression_function(COMPTHR_COMPRESS); dec_secthreads(); return NULL; } void *thread_decomp_fct(void *args) { inc_secthreads(); compression_function(COMPTHR_DECOMPRESS); dec_secthreads(); return NULL; } fsarchiver-0.8.7/src/fs_jfs.h0000644000175000017500000001105614405605077013030 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifndef __FS_JFS_H__ #define __FS_JFS_H__ struct s_dico; struct s_strlist; int jfs_mkfs(struct s_dico *d, char *partition, char *fsoptions, char *mkfslabel, char *mkfsuuid); int jfs_getinfo(struct s_dico *d, char *devname); int jfs_mount(char *partition, char *mntbuf, char *fsbuf, int flags, char *mntinfo); int jfs_get_reqmntopt(char *partition, struct s_strlist *reqopt, struct s_strlist *badopt); int jfs_umount(char *partition, char *mntbuf); int jfs_test(char *devname); // make the magic number something a human could read #define JFS_MAGIC "JFS1" /* Magic word */ #define LV_NAME_SIZE 11 /* MUST BE 11 for OS/2 boot sector */ #define JFS_SUPER1_OFF 0x8000 /* primary superblock */ /* * physical xd (pxd) */ typedef struct { unsigned len:24; unsigned addr1:8; u32 addr2; } pxd_t; /* * Almost identical to Linux's timespec, but not quite */ struct timestruc_t { u32 tv_sec; u32 tv_nsec; }; /* * aggregate superblock * * The name superblock is too close to super_block, so the name has been * changed to jfs_superblock. The utilities are still using the old name. */ struct jfs_superblock { char s_magic[4]; /* 4: magic number */ u32 s_version; /* 4: version number */ u64 s_size; /* 8: aggregate size in hardware/LVM blocks; * VFS: number of blocks */ u32 s_bsize; /* 4: aggregate block size in bytes; * VFS: fragment size */ u16 s_l2bsize; /* 2: log2 of s_bsize */ u16 s_l2bfactor; /* 2: log2(s_bsize/hardware block size) */ u32 s_pbsize; /* 4: hardware/LVM block size in bytes */ u16 s_l2pbsize; /* 2: log2 of s_pbsize */ u16 pad; /* 2: padding necessary for alignment */ u32 s_agsize; /* 4: allocation group size in aggr. blocks */ u32 s_flag; /* 4: aggregate attributes: * see jfs_filsys.h */ u32 s_state; /* 4: mount/unmount/recovery state: * see jfs_filsys.h */ u32 s_compress; /* 4: > 0 if data compression */ pxd_t s_ait2; /* 8: first extent of secondary * aggregate inode table */ pxd_t s_aim2; /* 8: first extent of secondary * aggregate inode map */ u32 s_logdev; /* 4: device address of log */ u32 s_logserial; /* 4: log serial number at aggregate mount */ pxd_t s_logpxd; /* 8: inline log extent */ pxd_t s_fsckpxd; /* 8: inline fsck work space extent */ struct timestruc_t s_time; /* 8: time last updated */ u32 s_fsckloglen; /* 4: Number of filesystem blocks reserved for * the fsck service log. * N.B. These blocks are divided among the * versions kept. This is not a per * version size. * N.B. These blocks are included in the * length field of s_fsckpxd. */ s8 s_fscklog; /* 1: which fsck service log is most recent * 0 => no service log data yet * 1 => the first one * 2 => the 2nd one */ char s_fpack[11]; /* 11: file system volume name * N.B. This must be 11 bytes to * conform with the OS/2 BootSector * requirements * Only used when s_version is 1 */ /* extendfs() parameter under s_state & FM_EXTENDFS */ u64 s_xsize; /* 8: extendfs s_size */ pxd_t s_xfsckpxd; /* 8: extendfs fsckpxd */ pxd_t s_xlogpxd; /* 8: extendfs logpxd */ /* - 128 byte boundary - */ char s_uuid[16]; /* 16: 128-bit uuid for volume */ char s_label[16]; /* 16: volume label */ char s_loguuid[16]; /* 16: 128-bit uuid for log device */ }; #endif // __FS_JFS_H__ fsarchiver-0.8.7/src/comp_lzo.h0000644000175000017500000000167514405605077013406 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifndef __COMPRESS_LZO_H__ #define __COMPRESS_LZO_H__ #ifdef OPTION_LZO_SUPPORT #include int compress_block_lzo(u64 origsize, u64 *compsize, u8 *origbuf, u8 *compbuf, u64 compbufsize, int level); int uncompress_block_lzo(u64 compsize, u64 *origsize, u8 *origbuf, u64 origbufsize, u8 *compbuf); #endif // OPTION_LZO_SUPPORT #endif // __COMPRESS_LZO_H__ fsarchiver-0.8.7/src/comp_lzma.h0000644000175000017500000000165414405605077013542 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifndef __COMPRESS_LZMA_H__ #define __COMPRESS_LZMA_H__ #ifdef OPTION_LZMA_SUPPORT int compress_block_lzma(u64 origsize, u64 *compsize, u8 *origbuf, u8 *compbuf, u64 compbufsize, int level); int uncompress_block_lzma(u64 compsize, u64 *origsize, u8 *origbuf, u64 origbufsize, u8 *compbuf); #endif // OPTION_LZMA_SUPPORT #endif // __COMPRESS_LZMA_H__ fsarchiver-0.8.7/src/comp_lzma.c0000644000175000017500000000757014405605077013540 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include "fsarchiver.h" #include "common.h" #include "comp_lzma.h" #include "error.h" #ifdef OPTION_LZMA_SUPPORT #include int compress_block_lzma(u64 origsize, u64 *compsize, u8 *origbuf, u8 *compbuf, u64 compbufsize, int level) { lzma_stream lzma = LZMA_STREAM_INIT; int res; // init lzma structures lzma.next_in = origbuf; lzma.avail_in = origsize; lzma.next_out = compbuf; lzma.avail_out = compbufsize; // Initialize a coder to the lzma_stream if ((res=lzma_easy_encoder(&lzma, level, LZMA_CHECK_CRC32))!=LZMA_OK) { switch (res) { case LZMA_MEM_ERROR: errprintf("lzma_easy_encoder(%d): LZMA compression failed " "with an out of memory error.\nYou should use a lower " "compression level to reduce the memory requirement.\n", level); lzma_end(&lzma); return FSAERR_ENOMEM; default: errprintf("lzma_easy_encoder(%d) failed with res=%d\n", level, res); lzma_end(&lzma); return FSAERR_UNKNOWN; } } if ((res=lzma_code(&lzma, LZMA_RUN))!=LZMA_OK) { errprintf("lzma_code(LZMA_RUN) failed with res=%d\n", res); lzma_end(&lzma); return FSAERR_UNKNOWN; } if ((res=lzma_code(&lzma, LZMA_FINISH))!=LZMA_STREAM_END && res!=LZMA_OK) { errprintf("lzma_code(LZMA_FINISH) failed with res=%d\n", res); lzma_end(&lzma); return FSAERR_UNKNOWN; } *compsize=(u64)(lzma.total_out); lzma_end(&lzma); return FSAERR_SUCCESS; } int uncompress_block_lzma(u64 compsize, u64 *origsize, u8 *origbuf, u64 origbufsize, u8 *compbuf) { lzma_stream lzma = LZMA_STREAM_INIT; u64 maxmemlimit=3ULL*1024ULL*1024ULL*1024ULL; u64 memlimit=96*1024*1024; int res; // init lzma structures lzma.next_in = compbuf; lzma.avail_in = compsize; lzma.next_out = origbuf; lzma.avail_out = origbufsize; // Initialize a coder to the lzma_stream if ((res=lzma_auto_decoder(&lzma, memlimit, 0))!=LZMA_OK) { errprintf("lzma_auto_decoder() failed with res=%d\n", res); lzma_end(&lzma); return FSAERR_UNKNOWN; } do // retry if lzma_code() returns LZMA_MEMLIMIT_ERROR (increase the memory limit) { if ((res=lzma_code(&lzma, LZMA_RUN)) != LZMA_STREAM_END) // if error { if (res == LZMA_MEMLIMIT_ERROR) // we have to raise the memory limit { memlimit+=64*1024*1024; lzma_memlimit_set(&lzma, memlimit); msgprintf(MSG_VERB2, "lzma_memlimit_set(%lld)\n", (long long)memlimit); } else // another error { errprintf("lzma_code(LZMA_RUN) failed with res=%d\n", res); lzma_end(&lzma); return FSAERR_UNKNOWN; } } } while ((res == LZMA_MEMLIMIT_ERROR) && (memlimit < maxmemlimit)); *origsize=(u64)(lzma.total_out); lzma_end(&lzma); switch (res) { case LZMA_STREAM_END: return FSAERR_SUCCESS; case LZMA_MEMLIMIT_ERROR: return FSAERR_ENOMEM; default: return FSAERR_UNKNOWN; } } #endif // OPTION_LZMA_SUPPORT fsarchiver-0.8.7/src/fs_ext2.c0000644000175000017500000007020314405605077013122 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include #include "fsarchiver.h" #include "dico.h" #include "common.h" #include "strlist.h" #include "filesys.h" #include "fs_ext2.h" #include "error.h" // e2fsprogs version required to work on ext2, ext3, ext4 u64 e2fsprogs_minver[]={PROGVER(1,39,0), PROGVER(1,39,0), PROGVER(1,41,0)}; struct mntopt { unsigned int mask; const char *string; }; struct s_features { char *name; // name of that feature int mask; // identifier for that feature int compat; // compat type for that feature (see e2p.h) int firstfs; // type of the first filesystem to support it u64 firste2p; // first e2fsprogs version that supports that feature }; // These are the features to be passed on the command line (cf "man ext4") // // metadata_csum_seed feature allows UUID change on mounted filesystems and configures an incompat // flag (EXT4_FEATURE_INCOMPAT_CSUM_SEED) bumping minimum kernel version to linux-4.4. Since // FSArchiver always creates the filesystem from scratch and sets up the UUID via mke2fs -U in // case metadata_csum is going to be used (mke2fs 1.43+), metadata_csum_seed brings no value for // us and therefore is not preserved (i.e. present in FSA_FEATURE_INCOMPAT_SUPP but not listed // below). Users can easily enable it with tune2fs if desired. // struct s_features mkfeatures[] = // cf e2fsprogs-1.47.0/lib/e2p/feature.c { {"has_journal", FSA_EXT3_FEATURE_COMPAT_HAS_JOURNAL, E2P_FEATURE_COMPAT, EXTFSTYPE_EXT3, PROGVER(1,39,0)}, {"ext_attr", FSA_EXT2_FEATURE_COMPAT_EXT_ATTR, E2P_FEATURE_COMPAT, EXTFSTYPE_EXT2, PROGVER(1,40,5)}, {"resize_inode", FSA_EXT2_FEATURE_COMPAT_RESIZE_INODE, E2P_FEATURE_COMPAT, EXTFSTYPE_EXT2, PROGVER(1,39,0)}, {"dir_index", FSA_EXT2_FEATURE_COMPAT_DIR_INDEX, E2P_FEATURE_COMPAT, EXTFSTYPE_EXT2, PROGVER(1,33,0)}, {"sparse_super2", FSA_EXT4_FEATURE_COMPAT_SPARSE_SUPER2, E2P_FEATURE_COMPAT, EXTFSTYPE_EXT4, PROGVER(1,42,10)}, {"fast_commit", FSA_EXT4_FEATURE_COMPAT_FAST_COMMIT, E2P_FEATURE_COMPAT, EXTFSTYPE_EXT4, PROGVER(1,46,0)}, {"orphan_file", FSA_EXT4_FEATURE_COMPAT_ORPHAN_FILE, E2P_FEATURE_COMPAT, EXTFSTYPE_EXT4, PROGVER(1,47,0)}, {"filetype", FSA_EXT2_FEATURE_INCOMPAT_FILETYPE, E2P_FEATURE_INCOMPAT, EXTFSTYPE_EXT2, PROGVER(1,16,0)}, {"extent", FSA_EXT4_FEATURE_INCOMPAT_EXTENTS, E2P_FEATURE_INCOMPAT, EXTFSTYPE_EXT4, PROGVER(1,41,0)}, {"journal_dev", FSA_EXT3_FEATURE_INCOMPAT_JOURNAL_DEV, E2P_FEATURE_INCOMPAT, EXTFSTYPE_EXT3, PROGVER(1,39,0)}, {"flex_bg", FSA_EXT4_FEATURE_INCOMPAT_FLEX_BG, E2P_FEATURE_INCOMPAT, EXTFSTYPE_EXT4, PROGVER(1,41,0)}, {"meta_bg", FSA_EXT2_FEATURE_INCOMPAT_META_BG, E2P_FEATURE_INCOMPAT, EXTFSTYPE_EXT2, PROGVER(1,39,0)}, {"mmp", FSA_EXT4_FEATURE_INCOMPAT_MMP, E2P_FEATURE_INCOMPAT, EXTFSTYPE_EXT4, PROGVER(1,42,0)}, {"64bit", FSA_EXT4_FEATURE_INCOMPAT_64BIT, E2P_FEATURE_INCOMPAT, EXTFSTYPE_EXT4, PROGVER(1,42,0)}, {"inline_data", FSA_EXT4_FEATURE_INCOMPAT_INLINEDATA, E2P_FEATURE_INCOMPAT, EXTFSTYPE_EXT4, PROGVER(1,43,0)}, {"ea_inode", FSA_EXT4_FEATURE_INCOMPAT_EA_INODE, E2P_FEATURE_INCOMPAT, EXTFSTYPE_EXT4, PROGVER(1,44,0)}, {"large_dir", FSA_EXT4_FEATURE_INCOMPAT_LARGEDIR, E2P_FEATURE_INCOMPAT, EXTFSTYPE_EXT4, PROGVER(1,44,0)}, {"large_file", FSA_EXT2_FEATURE_RO_COMPAT_LARGE_FILE, E2P_FEATURE_RO_INCOMPAT, EXTFSTYPE_EXT2, PROGVER(1,40,7)}, {"huge_file", FSA_EXT4_FEATURE_RO_COMPAT_HUGE_FILE, E2P_FEATURE_RO_INCOMPAT, EXTFSTYPE_EXT4, PROGVER(1,41,0)}, {"sparse_super", FSA_EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER, E2P_FEATURE_RO_INCOMPAT, EXTFSTYPE_EXT2, PROGVER(1,8,0)}, {"uninit_bg", FSA_EXT4_FEATURE_RO_COMPAT_GDT_CSUM, E2P_FEATURE_RO_INCOMPAT, EXTFSTYPE_EXT4, PROGVER(1,41,0)}, {"dir_nlink", FSA_EXT4_FEATURE_RO_COMPAT_DIR_NLINK, E2P_FEATURE_RO_INCOMPAT, EXTFSTYPE_EXT4, PROGVER(1,41,0)}, {"extra_isize", FSA_EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE, E2P_FEATURE_RO_INCOMPAT, EXTFSTYPE_EXT4, PROGVER(1,41,0)}, {"bigalloc", FSA_EXT4_FEATURE_RO_COMPAT_BIGALLOC, E2P_FEATURE_RO_INCOMPAT, EXTFSTYPE_EXT4, PROGVER(1,42,0)}, {"metadata_csum", FSA_EXT4_FEATURE_RO_COMPAT_METADATA_CSUM, E2P_FEATURE_RO_INCOMPAT, EXTFSTYPE_EXT4, PROGVER(1,43,0)}, {"project", FSA_EXT4_FEATURE_RO_COMPAT_PROJECT, E2P_FEATURE_RO_INCOMPAT, EXTFSTYPE_EXT4, PROGVER(1,43,0)}, {NULL, 0, 0, 0, 0}, }; char *format_fstype(int fstype) { switch (fstype) { case EXTFSTYPE_EXT2: return "ext2"; case EXTFSTYPE_EXT3: return "ext3"; case EXTFSTYPE_EXT4: return "ext4"; default: return "invalid"; } } int ext2_mkfs(cdico *d, char *partition, char *fsoptions, char *mkfslabel, char *mkfsuuid) { return extfs_mkfs(d, partition, EXTFSTYPE_EXT2, fsoptions, mkfslabel, mkfsuuid); } int ext3_mkfs(cdico *d, char *partition, char *fsoptions, char *mkfslabel, char *mkfsuuid) { return extfs_mkfs(d, partition, EXTFSTYPE_EXT3, fsoptions, mkfslabel, mkfsuuid); } int ext4_mkfs(cdico *d, char *partition, char *fsoptions, char *mkfslabel, char *mkfsuuid) { return extfs_mkfs(d, partition, EXTFSTYPE_EXT4, fsoptions, mkfslabel, mkfsuuid); } int extfs_get_fstype_from_compat_flags(u32 compat, u32 incompat, u32 ro_compat) { int fstype=EXTFSTYPE_EXT2; // distinguish between ext3 and ext2 if (compat & FSA_EXT3_FEATURE_COMPAT_HAS_JOURNAL) fstype=EXTFSTYPE_EXT3; // any features which ext2 doesn't understand if ((ro_compat & FSA_EXT2_FEATURE_RO_COMPAT_UNSUPPORTED) || (incompat & FSA_EXT2_FEATURE_INCOMPAT_UNSUPPORTED)) fstype=EXTFSTYPE_EXT3; // ext4 has at least one feature which ext3 doesn't understand if ((ro_compat & FSA_EXT3_FEATURE_RO_COMPAT_UNSUPPORTED) || (incompat & FSA_EXT3_FEATURE_INCOMPAT_UNSUPPORTED)) fstype=EXTFSTYPE_EXT4; return fstype; } int extfs_check_compatibility(u64 compat, u64 incompat, u64 ro_compat) { // to preserve the filesystem attributes, fsa must know all the features including the COMPAT ones if (compat & ~FSA_FEATURE_COMPAT_SUPP) return -1; if (incompat & ~FSA_FEATURE_INCOMPAT_SUPP) return -1; if (ro_compat & ~FSA_FEATURE_RO_COMPAT_SUPP) return -1; // TODO: check journal features /*if (!(flags & EXT2_FLAG_JOURNAL_DEV_OK) && (fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) goto check_support_for_features_error;*/ return 0; } int extfs_mkfs(cdico *d, char *partition, int extfstype, char *fsoptions, char *mkfslabel, char *mkfsuuid) { cstrlist strfeatures; u64 features_tab[3]; u64 fsextrevision; int origextfstype; char buffer[2048]; char command[2048]; char options[2048]; char uuid[64]; bool mke2fsuuid=false; char temp[1024]; char progname[64]; u64 e2fstoolsver; int compat_type; s64 devblkcount; u64 devblksize; u64 devisize; s64 threshold64bit; s64 devsize; u64 temp64; int exitst; int ret=0; int i; // init memset(options, 0, sizeof(options)); memset(uuid, 0, sizeof(uuid)); snprintf(progname, sizeof(progname), "mke2fs"); strlist_init(&strfeatures); // ---- check that mkfs is installed and get its version if (exec_command(command, sizeof(command), NULL, NULL, 0, NULL, 0, "%s -V", progname)!=0) { errprintf("%s not found. please install a recent e2fsprogs on your system or check the PATH.\n", progname); ret=-1; goto extfs_mkfs_cleanup; } e2fstoolsver=check_prog_version(progname); // ---- check what is the extfs block size to use if (dico_get_u64(d, 0, FSYSHEADKEY_FSEXTBLOCKSIZE, &devblksize)!=0) devblksize=4096; // ---- check what is the extfs inode size to use if (dico_get_u64(d, 0, FSYSHEADKEY_FSINODESIZE, &devisize)!=0) devisize=256; // ---- filesystem revision (good-old-rev or dynamic) if (dico_get_u64(d, 0, FSYSHEADKEY_FSEXTREVISION, &fsextrevision)!=0) fsextrevision=EXT2_DYNAMIC_REV; // don't fail (case of fs conversion to extfs) // "mke2fs -q" prevents problems in exec_command when too many output details printed strlcatf(options, sizeof(options), " -q "); // "mke2fs -F" removes confirmation prompt when device is a whole disk such as /dev/sda strlcatf(options, sizeof(options), " -F "); strlcatf(options, sizeof(options), " -b %ld ", (long)devblksize); // ---- set the advanced filesystem settings from the dico if (strlen(mkfslabel) > 0) strlcatf(options, sizeof(options), " -L '%.16s' ", mkfslabel); else if (dico_get_string(d, 0, FSYSHEADKEY_FSLABEL, buffer, sizeof(buffer))==0 && strlen(buffer)>0) strlcatf(options, sizeof(options), " -L '%.16s' ", buffer); // ---- determine which UUID must be set on this filesystem if (strlen(mkfsuuid) > 0) snprintf(uuid, sizeof(uuid), "%s", mkfsuuid); else if (dico_get_string(d, 0, FSYSHEADKEY_FSUUID, buffer, sizeof(buffer))==0) snprintf(uuid, sizeof(uuid), "%s", buffer); // ---- set UUID with mke2fs if supported if (e2fstoolsver>=PROGVER(1,41,4) && strlen(uuid)==36) { strlcatf(options, sizeof(options), " -U %s ", uuid); mke2fsuuid=true; } // ---- get original filesystem features (if the original filesystem was an ext{2,3,4}) if (dico_get_u64(d, 0, FSYSHEADKEY_FSEXTFEATURECOMPAT, &features_tab[E2P_FEATURE_COMPAT])!=0 || dico_get_u64(d, 0, FSYSHEADKEY_FSEXTFEATUREINCOMPAT, &features_tab[E2P_FEATURE_INCOMPAT])!=0 || dico_get_u64(d, 0, FSYSHEADKEY_FSEXTFEATUREROCOMPAT, &features_tab[E2P_FEATURE_RO_INCOMPAT])!=0 || fsextrevision==EXT2_GOOD_OLD_REV) { // dont fail the original filesystem may not be ext{2,3,4}. in that case set defaults features // ext2 revision 0 does not have features, set defaults too in case user wants to upgrade it features_tab[E2P_FEATURE_COMPAT]=EXT2_FEATURE_COMPAT_RESIZE_INODE|\ EXT2_FEATURE_COMPAT_DIR_INDEX|\ EXT2_FEATURE_COMPAT_EXT_ATTR; features_tab[E2P_FEATURE_INCOMPAT]=EXT2_FEATURE_INCOMPAT_FILETYPE; features_tab[E2P_FEATURE_RO_INCOMPAT]=EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER; } // ---- check that fsarchiver is aware of all the filesystem features used on that filesystem if (extfs_check_compatibility(features_tab[E2P_FEATURE_COMPAT], features_tab[E2P_FEATURE_INCOMPAT], features_tab[E2P_FEATURE_RO_INCOMPAT])!=0) { errprintf("this filesystem has ext{2,3,4} features which are not supported by this fsarchiver version.\n"); ret=-1; goto extfs_mkfs_cleanup; } // ---- get original filesystem type origextfstype=extfs_get_fstype_from_compat_flags(features_tab[E2P_FEATURE_COMPAT], features_tab[E2P_FEATURE_INCOMPAT], features_tab[E2P_FEATURE_RO_INCOMPAT]); msgprintf(MSG_VERB2, "the filesystem type determined by the original filesystem features is [%s]\n", format_fstype(origextfstype)); // remove all the features not supported by the filesystem to create (conversion = downgrade fs) for (i=0; mkfeatures[i].name; i++) { compat_type=mkfeatures[i].compat; if (mkfeatures[i].firstfs > extfstype) features_tab[compat_type] &= ~mkfeatures[i].mask; } // add new features if the filesystem to create is newer than the filesystem type that was backed up // eg: user did a "savefs" of an ext3 and does a "restfs mkfs=ext4" --> add features to force ext4 // it's a bit more difficult because we only want to add such a feature if no feature of the new // filesystem is currently enabled. msgprintf(MSG_VERB2, "the filesystem type to create considering the command options is [%s]\n", format_fstype(extfstype)); if (origextfstype==EXTFSTYPE_EXT2 && extfstype>EXTFSTYPE_EXT2) // upgrade ext2 to ext{3,4} { fsextrevision=EXT2_DYNAMIC_REV; features_tab[E2P_FEATURE_COMPAT]|=EXT3_FEATURE_COMPAT_HAS_JOURNAL; } if (origextfstype=EXTFSTYPE_EXT4) // upgrade ext{2,3} to ext4 { // ext4 default features from mke2fs 1.41: // extents,huge_file,flex_bg,uninit_bg,dir_nlink,extra_isize // recent mke2fs versions enable more features, but we are conservative here fsextrevision=EXT2_DYNAMIC_REV; devisize=256; features_tab[E2P_FEATURE_INCOMPAT]|=EXT3_FEATURE_INCOMPAT_EXTENTS|\ EXT4_FEATURE_INCOMPAT_FLEX_BG; features_tab[E2P_FEATURE_RO_INCOMPAT]|=EXT4_FEATURE_RO_COMPAT_DIR_NLINK|\ EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE|\ EXT4_FEATURE_RO_COMPAT_GDT_CSUM|\ EXT4_FEATURE_RO_COMPAT_HUGE_FILE; } // get size of the target device if ((devsize=get_device_size(partition))<0) { errprintf("failed to check the size of the target device: [%s]\n", partition); ret=-1; goto extfs_mkfs_cleanup; } // special logic required if the target device is equal or more than 2^32 blocks long devblkcount=devsize/devblksize; threshold64bit=(1LL<<32LL); msgprintf(MSG_VERB2, "the filesystem block size is %ld bytes long\n", (long)devblksize); msgprintf(MSG_VERB2, "device [%s] size is %lld bytes (%lld blocks) long\n", partition, (long long)devsize, (long long)devblkcount); if (devblkcount >= threshold64bit) { msgprintf(MSG_VERB1, "device [%s] is at least %lld blocks long and requires ext4\n" "with the [64bit] feature\n", partition, (long long)threshold64bit); if (extfstype feature [%s]=YES\n", mkfeatures[i].name); strlist_add(&strfeatures, mkfeatures[i].name); } else { msgprintf(MSG_VERB2, "--> feature [%s]=NO\n", mkfeatures[i].name); snprintf(temp, sizeof(temp), "^%s", mkfeatures[i].name); // exclude feature strlist_add(&strfeatures, temp); } } } // inode size strlcatf(options, sizeof(options), " -I %ld ", (long)devisize); // filesystem revision: good-old-rev or dynamic strlcatf(options, sizeof(options), " -r %d ", (int)fsextrevision); // if extfs revision is dynamic and there are features in the list if (fsextrevision!=EXT2_GOOD_OLD_REV && strlist_count(&strfeatures)>0) { strlist_merge(&strfeatures, temp, sizeof(temp), ','); strlcatf(options, sizeof(options), " -O %s ", temp); msgprintf(MSG_VERB2, "features: mkfs_options+=[-O %s]\n", temp); } // ---- check mke2fs version requirement msgprintf(MSG_VERB2, "mke2fs version detected: %s\n", format_prog_version(e2fstoolsver, temp, sizeof(temp))); msgprintf(MSG_VERB2, "mke2fs version required: %s\n", format_prog_version(e2fsprogs_minver[extfstype], temp, sizeof(temp))); if (e2fstoolsver < e2fsprogs_minver[extfstype]) { errprintf("mke2fs was found but is too old, please upgrade to a version %s or more recent.\n", format_prog_version(e2fsprogs_minver[extfstype], temp, sizeof(temp))); ret=-1; goto extfs_mkfs_cleanup; } // ---- extended options if (dico_get_u64(d, 0, FSYSHEADKEY_FSEXTEOPTRAIDSTRIDE, &temp64)==0) strlcatf(options, sizeof(options), " -E stride=%ld ", (long)temp64); if ((dico_get_u64(d, 0, FSYSHEADKEY_FSEXTEOPTRAIDSTRIPEWIDTH, &temp64)==0) && e2fstoolsver>=PROGVER(1,40,7)) strlcatf(options, sizeof(options), " -E stripe-width=%ld ", (long)temp64); // ---- mkfsopt from command line strlcatf(options, sizeof(options), " %s ", fsoptions); // ---- execute mke2fs msgprintf(MSG_VERB2, "exec: %s\n", command); if (exec_command(command, sizeof(command), &exitst, NULL, 0, NULL, 0, "%s %s %s", progname, options, partition)!=0 || exitst!=0) { errprintf("command [%s] failed with return status=%d\n", command, exitst); ret=-1; goto extfs_mkfs_cleanup; } // ---- use tune2fs to set the other advanced options memset(options, 0, sizeof(options)); if (!mke2fsuuid && strlen(uuid)==36) strlcatf(options, sizeof(options), " -U %s ", uuid); if (dico_get_string(d, 0, FSYSHEADKEY_FSEXTDEFMNTOPT, buffer, sizeof(buffer))==0 && strlen(buffer)>0) strlcatf(options, sizeof(options), " -o %s ", buffer); if (dico_get_u64(d, 0, FSYSHEADKEY_FSEXTFSCKMAXMNTCOUNT, &temp64)==0) strlcatf(options, sizeof(options), " -c %ld ", (long)temp64); if (dico_get_u64(d, 0, FSYSHEADKEY_FSEXTFSCKCHECKINTERVAL, &temp64)==0) strlcatf(options, sizeof(options), " -i %ldd ", (long)(temp64/86400L)); if (options[0]) { if (exec_command(command, sizeof(command), &exitst, NULL, 0, NULL, 0, "tune2fs %s %s", options, partition)!=0 || exitst!=0) { errprintf("command [%s] failed with return status=%d\n", command, exitst); ret=-1; goto extfs_mkfs_cleanup; } // if UUID was not set by mke2fs, we have e2fsprogs < 1.41.4 // tune2fs will mess up ext4 filesystem when changing its UUID // http://marc.info/?l=linux-ext4&m=123246035924487&w=2 if (extfstype==EXTFSTYPE_EXT4 && !mke2fsuuid) { if (exec_command(command, sizeof(command), &exitst, NULL, 0, NULL, 0, "e2fsck -fy %s", partition)!=0 || (exitst!=0 && exitst!=1)) { errprintf("command [%s] failed with return status=%d\n", command, exitst); ret=-1; goto extfs_mkfs_cleanup; } } } extfs_mkfs_cleanup: strlist_destroy(&strfeatures); return ret; } int extfs_getinfo(cdico *d, char *devname) { struct fsa_ext2_sb *super; blk_t use_superblock=0; int use_blocksize=0; char uuid[512]; ext2_filsys fs; int origextfstype; char mntopt[1024]; char label[80]; u32 mask, m; int count; int i; // ---- open partition if (ext2fs_open(devname, EXT2_FLAG_JOURNAL_DEV_OK | EXT2_FLAG_SOFTSUPP_FEATURES, use_superblock, use_blocksize, unix_io_manager, &fs)!=0) { errprintf("ext2fs_open(%s) failed\n", devname); return -1; } super=(struct fsa_ext2_sb *)fs->super; // --- label memset(label, 0, sizeof(label)); if (super->s_volume_name[0]) { memset(label, 0, sizeof(label)); strncpy(label, super->s_volume_name, sizeof(super->s_volume_name)); } dico_add_string(d, 0, FSYSHEADKEY_FSLABEL, label); // ---- uuid /*if ((str=e2p_uuid2str(super->s_uuid))!=NULL) dico_add_string(d, 0, FSYSHEADKEY_FSUUID, str);*/ memset(uuid, 0, sizeof(uuid)); uuid_unparse_lower((u8*)super->s_uuid, uuid); dico_add_string(d, 0, FSYSHEADKEY_FSUUID, uuid); msgprintf(MSG_DEBUG1, "extfs_uuid=[%s]\n", uuid); // ---- block size dico_add_u64(d, 0, FSYSHEADKEY_FSEXTBLOCKSIZE, EXT2_BLOCK_SIZE(super)); // ---- filesystem revision (good-old-rev or dynamic) dico_add_u64(d, 0, FSYSHEADKEY_FSEXTREVISION, super->s_rev_level); // ---- inode size if (super->s_rev_level >= EXT2_DYNAMIC_REV) dico_add_u64(d, 0, FSYSHEADKEY_FSINODESIZE, super->s_inode_size); else dico_add_u64(d, 0, FSYSHEADKEY_FSINODESIZE, EXT2_GOOD_OLD_INODE_SIZE); // Good old rev // ---- extended options if (super->s_raid_stride > 0) { dico_add_u64(d, 0, FSYSHEADKEY_FSEXTEOPTRAIDSTRIDE, super->s_raid_stride); msgprintf(MSG_DEBUG1, "extfs_raid_stride: %u\n", super->s_raid_stride); } if (super->s_raid_stripe_width > 0) { dico_add_u64(d, 0, FSYSHEADKEY_FSEXTEOPTRAIDSTRIPEWIDTH, super->s_raid_stripe_width); msgprintf(MSG_DEBUG1, "extfs_raid_stripe_width: %u\n", super->s_raid_stripe_width); } // ---- fsck details: max_mount_count and check_interval dico_add_u64(d, 0, FSYSHEADKEY_FSEXTFSCKMAXMNTCOUNT, max(super->s_max_mnt_count,0)); dico_add_u64(d, 0, FSYSHEADKEY_FSEXTFSCKCHECKINTERVAL, super->s_checkinterval); msgprintf(MSG_DEBUG1, "extfs_max_mount_count: %ld\n", (long)max(super->s_max_mnt_count,0)); msgprintf(MSG_DEBUG1, "extfs_check_interval: %ld\n", (long)super->s_checkinterval); // ---- default mount options memset(mntopt, 0, sizeof(mntopt)); count=0; mask=super->s_default_mount_opts; if (mask & EXT3_DEFM_JMODE) { strlcatf(mntopt, sizeof(mntopt), "%s", e2p_mntopt2string(mask & EXT3_DEFM_JMODE)); count++; } for (i=0, m=1; i < 32; i++, m<<=1) { if (m & EXT3_DEFM_JMODE) continue; if (mask & m) { if (count++) strlcatf(mntopt, sizeof(mntopt), ","); strlcatf(mntopt, sizeof(mntopt), "%s", e2p_mntopt2string(m)); } } dico_add_string(d, 0, FSYSHEADKEY_FSEXTDEFMNTOPT, mntopt); msgprintf(MSG_DEBUG1, "default mount options: [%s]\n", mntopt); // ---- filesystem features dico_add_u64(d, 0, FSYSHEADKEY_FSEXTFEATURECOMPAT, (u64)super->s_feature_compat); dico_add_u64(d, 0, FSYSHEADKEY_FSEXTFEATUREINCOMPAT, (u64)super->s_feature_incompat); dico_add_u64(d, 0, FSYSHEADKEY_FSEXTFEATUREROCOMPAT, (u64)super->s_feature_ro_compat); origextfstype=extfs_get_fstype_from_compat_flags((u64)super->s_feature_compat, (u64)super->s_feature_incompat, (u64)super->s_feature_ro_compat); msgprintf(MSG_DEBUG1, "the filesystem type determined by the features is [%s]\n", format_fstype(origextfstype)); // ---- check that fsarchiver is aware of all the filesystem features used on that filesystem if (extfs_check_compatibility((u64)super->s_feature_compat, (u64)super->s_feature_incompat, (u64)super->s_feature_ro_compat)!=0) { errprintf("this filesystem has ext{2,3,4} features which are not supported by this fsarchiver version.\n"); return -1; } // ---- minimum fsarchiver version required to restore dico_add_u64(d, 0, FSYSHEADKEY_MINFSAVERSION, FSA_VERSION_BUILD(0, 6, 4, 0)); ext2fs_close(fs); return 0; } int extfs_mount(char *partition, char *mntbuf, char *fsbuf, int flags, char *mntinfo) { blk_t use_superblock=0; int use_blocksize=0; ext2_filsys fs; int origextfstype; char fsname[32]; msgprintf(MSG_DEBUG1, "extfs_mount(partition=[%s], mnt=[%s], fsbuf=[%s])\n", partition, mntbuf, fsbuf); if (ext2fs_open(partition, EXT2_FLAG_JOURNAL_DEV_OK | EXT2_FLAG_SOFTSUPP_FEATURES, use_superblock, use_blocksize, unix_io_manager, &fs)!=0) { msgprintf(MSG_DEBUG1, "ext2fs_open(%s) failed\n", partition); return -1; } origextfstype=extfs_get_fstype_from_compat_flags((u64)fs->super->s_feature_compat, (u64)fs->super->s_feature_incompat, (u64)fs->super->s_feature_ro_compat); snprintf(fsname, sizeof(fsname), "%s", format_fstype(origextfstype)); msgprintf(MSG_VERB2, "the filesystem of [%s] type determined by the features is [%s]\n", partition, fsname); ext2fs_close(fs); if (strcmp(fsname, fsbuf)!=0) { msgprintf(MSG_DEBUG1, "extfs_mount: the filesystem requested [%s] does not match the filesystem detected [%s]\n", fsbuf, fsname); return -1; } return generic_mount(partition, mntbuf, fsbuf, "user_xattr,acl", flags); } int extfs_umount(char *partition, char *mntbuf) { return generic_umount(mntbuf); } int extfs_test(char *partition, int extfstype) // returns true if it's that sort of filesystem { blk_t use_superblock=0; int use_blocksize=0; int extfstypedetected; ext2_filsys fs; if (ext2fs_open(partition, EXT2_FLAG_JOURNAL_DEV_OK | EXT2_FLAG_SOFTSUPP_FEATURES, use_superblock, use_blocksize, unix_io_manager, &fs)!=0) return false; extfstypedetected=extfs_get_fstype_from_compat_flags((u64)fs->super->s_feature_compat, (u64)fs->super->s_feature_incompat, (u64)fs->super->s_feature_ro_compat); msgprintf(MSG_DEBUG1, "the filesystem type determined by the extfs features is [%s]\n", format_fstype(extfstypedetected)); ext2fs_close(fs); // if detected is what is tested, say yes return (extfstypedetected==extfstype); } int ext2_test(char *partition) { return extfs_test(partition, EXTFSTYPE_EXT2); } int ext3_test(char *partition) { return extfs_test(partition, EXTFSTYPE_EXT3); } int ext4_test(char *partition) { return extfs_test(partition, EXTFSTYPE_EXT4); } int extfs_get_reqmntopt(char *partition, cstrlist *reqopt, cstrlist *badopt) { if (!reqopt || !badopt) return -1; strlist_add(badopt, "nouser_xattr"); strlist_add(badopt, "noacl"); return 0; } u64 check_prog_version(char *prog) { char stderrbuf[2048]; char command[2048]; char options[1024]; char temp1[1024]; char delims[]="\n\r"; char *saveptr; char *result; int foundversion; int x, y, z; // init memset(options, 0, sizeof(options)); memset(stderrbuf, 0, sizeof(stderrbuf)); if (exec_command(command, sizeof(command), NULL, NULL, 0, stderrbuf, sizeof(stderrbuf), "%s -V", prog)!=0) { errprintf("program %s was not found or has bad permissions.\n", prog); return -1; } foundversion=false; result=strtok_r(stderrbuf, delims, &saveptr); while (result != NULL && foundversion==false) { if ((memcmp(result, prog, strlen(prog))==0)) foundversion=true; else result = strtok_r(NULL, delims, &saveptr); } if (foundversion==false) { errprintf("can't parse %s version number: no match\n", prog); return 0; } x=y=z=0; sscanf(result, "%1023s %d.%d.%d", temp1, &x, &y, &z); if (x==0 && y==0) { errprintf("can't parse %s version number: x=y=0\n", prog); return 0; } return PROGVER(x,y,z); } fsarchiver-0.8.7/src/dico.c0000644000175000017500000002073014405605077012466 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include #include "fsarchiver.h" #include "dico.h" #include "common.h" #include "error.h" cdico *dico_alloc() { cdico *d; if ((d=malloc(sizeof(cdico)))==NULL) return NULL; d->head=NULL; return d; } int dico_destroy(cdico *d) { cdicoitem *item, *next; if (d==NULL) return -1; item=d->head; while (item!=NULL) { next=item->next; if (item->data!=NULL) free(item->data); free(item); item=next; } free(d); return 0; } int dico_add_data(cdico *d, u8 section, u16 key, const void *data, u16 size) { return dico_add_generic(d, section, key, data, size, DICTYPE_DATA); } // add an item to the dico, fails if an item with that (section,key) already exists int dico_add_generic(cdico *d, u8 section, u16 key, const void *data, u16 size, u8 type) { cdicoitem *item, *lnew, *last; assert (d); // allocate object lnew=malloc(sizeof(cdicoitem)); if (!lnew) { errprintf("malloc(%ld) failed: out of memory\n", (long)sizeof(cdicoitem)); return -3; } memset(lnew, 0, sizeof(cdicoitem)); // go to the end of the item and check for duplicates if (d->head==NULL) // item is empty { d->head=lnew; } else // item is not empty { for (item=d->head; item!=NULL; item=item->next) { last=item; if (item->section==section && item->key==key) { errprintf("dico_add_generic(): item with key=%ld is already in dico\n", (long)item->key); return -3; } } last->next=lnew; } // copy key lnew->key=key; lnew->section=section; lnew->size=size; lnew->type=type; lnew->data=NULL; // allocate memory for data if (size > 0) { lnew->data=malloc(size); if (!lnew->data) { errprintf("malloc(%ld) failed: out of memory\n", (long)size); return -3; } // copy data memcpy(lnew->data, data, size); } return 0; } int dico_get_data(cdico *d, u8 section, u16 key, void *data, u16 maxsize, u16 *size) { return dico_get_generic(d, section, key, data, maxsize, size); } int dico_get_generic(cdico *d, u8 section, u16 key, void *data, u16 maxsize, u16 *size) { cdicoitem *item; assert(d); assert(data); // size can be NULL if the user does not want to know the size if (size!=NULL) *size=0; if (d->head==NULL) { msgprintf(MSG_DEBUG1, "dico is empty\n"); return -1; } if (maxsize<1) { msgprintf(MSG_DEBUG1, "case1: maxsize=%d\n", maxsize); return -3; } for (item=d->head; item!=NULL; item=item->next) { if ((item!=NULL) && (item->key==key && item->section==section)) { if (item->size > maxsize) // item is too big { msgprintf(MSG_DEBUG1, "case2: (item->size > maxsize): item->size =%d, maxsize=%d\n", item->size, maxsize); return -4; } if ((item->size>0) && (item->data!=NULL)) // there may be no data (size==0) memcpy(data, item->data, item->size); if (size!=NULL) *size=item->size; return 0; } } msgprintf(MSG_DEBUG1, "case3: not found\n"); return -5; // not found } int dico_count_one_section(cdico *d, u8 section) { cdicoitem *item; int count; assert(d); count=0; for (item=d->head; item!=NULL; item=item->next) if (item->section==section) count++; return count; } int dico_count_all_sections(cdico *d) { cdicoitem *item; int count; assert(d); count=0; for (item=d->head; item!=NULL; item=item->next) count++; return count; } int dico_add_u16(cdico *d, u8 section, u16 key, u16 data) { u16 ledata; assert(d); ledata=cpu_to_le16(data); return dico_add_generic(d, section, key, &ledata, sizeof(ledata), DICTYPE_U16); } int dico_add_u32(cdico *d, u8 section, u16 key, u32 data) { u32 ledata; assert(d); ledata=cpu_to_le32(data); return dico_add_generic(d, section, key, &ledata, sizeof(ledata), DICTYPE_U32); } int dico_add_u64(cdico *d, u8 section, u16 key, u64 data) { u64 ledata; assert (d); ledata=cpu_to_le64(data); return dico_add_generic(d, section, key, &ledata, sizeof(ledata), DICTYPE_U64); } int dico_add_string(cdico *d, u8 section, u16 key, const char *szstring) { u16 len; assert(d); assert(szstring); len=strlen(szstring); return dico_add_generic(d, section, key, szstring, len+1, DICTYPE_STRING); } int dico_get_u16(cdico *d, u8 section, u16 key, u16 *data) { u16 ledata; u16 size; assert(d); assert(data); *data=0; if (dico_get_data(d, section, key, &ledata, sizeof(ledata), &size)!=0) return -1; *data=le16_to_cpu(ledata); return 0; } int dico_get_u32(cdico *d, u8 section, u16 key, u32 *data) { u32 ledata; u16 size; assert(d); assert(data); *data=0; if (dico_get_data(d, section, key, &ledata, sizeof(ledata), &size)!=0) return -1; *data=le32_to_cpu(ledata); return 0; } int dico_get_u64(cdico *d, u8 section, u16 key, u64 *data) { u64 ledata; u16 size; assert(d); assert(data); *data=0; if (dico_get_data(d, section, key, &ledata, sizeof(ledata), &size)!=0) return -1; *data=le64_to_cpu(ledata); return 0; } int dico_get_string(cdico *d, u8 section, u16 key, char *buffer, u16 bufsize) { u16 size; assert(d); assert(buffer); memset(buffer, 0, bufsize); return dico_get_data(d, section, key, buffer, bufsize, &size); } int dico_show(cdico *d, u8 section, char *debugtxt) { char buffer[2048]; char text[2048]; cdicoitem *item; assert(d); msgprintf(MSG_FORCE, "\n-----------------debug-dico-begin(%s)---------------\n", debugtxt); if (d->head) { for (item=d->head; item!=NULL; item=item->next) { if (item->section==section) { snprintf(buffer, sizeof(buffer), "key=[%ld], sizeof(data)=[%d], ", (long)item->key, (int)item->size); switch (item->type) { case DICTYPE_U8: snprintf(text, sizeof(text), "type=u8, size=[%d]", (int)item->size); break; case DICTYPE_U16: snprintf(text, sizeof(text), "type=u16, size=[%d]", (int)item->size); break; case DICTYPE_U32: snprintf(text, sizeof(text), "type=u32, size=[%d]", (int)item->size); break; case DICTYPE_U64: snprintf(text, sizeof(text), "type=u64, size=[%d]", (int)item->size); break; case DICTYPE_STRING: snprintf(text, sizeof(text), "type=str, size=[%d], data=[%s]", (int)item->size, (char*)item->data); break; case DICTYPE_DATA: snprintf(text, sizeof(text), "type=dat, size=[%d]", (int)item->size); break; default: snprintf(text, sizeof(text), "type=unknown"); break; } strlcatf(buffer, sizeof(buffer) ,"%s", text); msgprintf(MSG_FORCE, "%s\n", buffer); } } } else { msgprintf(MSG_FORCE, "dico is empty\n"); } msgprintf(MSG_FORCE, "-----------------debug-dico-end(%s)------------------\n\n", debugtxt); return 0; } fsarchiver-0.8.7/src/comp_zstd.c0000644000175000017500000000306714405605077013556 00000000000000 /* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include "fsarchiver.h" #include "common.h" #include "comp_zstd.h" #include "error.h" #ifdef OPTION_ZSTD_SUPPORT int compress_block_zstd(u64 origsize, u64 *compsize, u8 *origbuf, u8 *compbuf, u64 compbufsize, int level) { int res=0; if (ZSTD_isError((res=ZSTD_compress((char*)compbuf, compbufsize, (const char*)origbuf, (int)origsize, level)))) { errprintf("ZSTD_compress(): failed: res=%d\n", res); return FSAERR_UNKNOWN; } else { *compsize=(u64)res; return FSAERR_SUCCESS; } } int uncompress_block_zstd(u64 compsize, u64 *origsize, u8 *origbuf, u64 origbufsize, u8 *compbuf) { int res=0; if (ZSTD_isError((res=ZSTD_decompress((char*)origbuf, origbufsize, (char*)compbuf, compsize)))) { errprintf("ZSTD_decompress(): failed: res=%d\n", res); return FSAERR_UNKNOWN; } else { *origsize=(u64)res; return FSAERR_SUCCESS; } } #endif // OPTION_ZSTD_SUPPORT fsarchiver-0.8.7/src/fs_reiserfs.c0000644000175000017500000001367514405605077014074 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include #include #include "fsarchiver.h" #include "fsarchiver.h" #include "dico.h" #include "common.h" #include "fs_reiserfs.h" #include "filesys.h" #include "strlist.h" #include "error.h" int reiserfs_mkfs(cdico *d, char *partition, char *fsoptions, char *mkfslabel, char *mkfsuuid) { char command[2048]; char buffer[2048]; char options[2048]; int exitst; u64 temp64; // ---- check mkreiserfs is available if (exec_command(command, sizeof(command), NULL, NULL, 0, NULL, 0, "mkreiserfs -V")!=0) { errprintf("mkreiserfs not found. please install reiserfsprogs-3.6 on your system or check the PATH.\n"); return -1; } // ---- set the advanced filesystem settings from the dico memset(options, 0, sizeof(options)); if (strlen(mkfslabel) > 0) strlcatf(options, sizeof(options), " -l '%.16s' ", mkfslabel); else if (dico_get_string(d, 0, FSYSHEADKEY_FSLABEL, buffer, sizeof(buffer))==0 && strlen(buffer)>0) strlcatf(options, sizeof(options), " -l '%.16s' ", buffer); if (dico_get_u64(d, 0, FSYSHEADKEY_FSREISERBLOCKSIZE, &temp64)==0) strlcatf(options, sizeof(options), " -b %ld ", (long)temp64); if (strlen(mkfsuuid) > 0) strlcatf(options, sizeof(options), " -u %s ", mkfsuuid); else if (dico_get_string(d, 0, FSYSHEADKEY_FSUUID, buffer, sizeof(buffer))==0 && strlen(buffer)==36) strlcatf(options, sizeof(options), " -u %s ", buffer); // ---- mkfsopt from command line strlcatf(options, sizeof(options), " %s ", fsoptions); if (exec_command(command, sizeof(command), &exitst, NULL, 0, NULL, 0, "mkreiserfs -f %s %s", options, partition)!=0 || exitst!=0) { errprintf("command [%s] failed\n", command); return -1; } return 0; } int reiserfs_getinfo(cdico *d, char *devname) { struct reiserfs_super_block sb; char uuid[512]; u16 temp16; int ret=0; int fd=-1; int res; if ((fd=open64(devname, O_RDONLY|O_LARGEFILE))<0) { ret=-1; errprintf("cannot open(%s, O_RDONLY)\n", devname); goto reiserfs_read_sb_return; } if (lseek(fd, REISERFS_DISK_OFFSET_IN_BYTES, SEEK_SET)!=REISERFS_DISK_OFFSET_IN_BYTES) { ret=-2; errprintf("cannot lseek(fd, REISERFS_DISK_OFFSET_IN_BYTES, SEEK_SET) on %s\n", devname); goto reiserfs_read_sb_close; } res=read(fd, &sb, sizeof(sb)); if (res!=sizeof(sb)) { ret=-3; errprintf("cannot read the reiserfs superblock on device [%s]\n", devname); goto reiserfs_read_sb_close; } if (strncmp(sb.s_v1.s_magic, REISERFS_SUPER_MAGIC_STRING, strlen(REISERFS_SUPER_MAGIC_STRING)) == 0) dico_add_string(d, 0, FSYSHEADKEY_FSVERSION, "reiserfs-3.5"); else if (strncmp(sb.s_v1.s_magic, REISER2FS_SUPER_MAGIC_STRING, strlen(REISER2FS_SUPER_MAGIC_STRING)) == 0) dico_add_string(d, 0, FSYSHEADKEY_FSVERSION, "reiserfs-3.6"); else { ret=-4; errprintf("magic different from expectations superblock on %s: magic=[%s]\n", devname, sb.s_v1.s_magic); goto reiserfs_read_sb_close; } msgprintf(MSG_DEBUG1, "reiserfs_magic=[%s]\n", sb.s_v1.s_magic); // ---- label msgprintf(MSG_DEBUG1, "reiserfs_label=[%s]\n", sb.s_label); dico_add_string(d, 0, FSYSHEADKEY_FSLABEL, (char*)sb.s_label); // ---- uuid /*if ((str=e2p_uuid2str(sb.s_uuid))!=NULL) dico_add_string(d, 0, FSYSHEADKEY_FSUUID, str);*/ memset(uuid, 0, sizeof(uuid)); uuid_unparse_lower((u8*)sb.s_uuid, uuid); dico_add_string(d, 0, FSYSHEADKEY_FSUUID, uuid); msgprintf(MSG_DEBUG1, "reiserfs_uuid=[%s]\n", uuid); // ---- block size temp16=le16_to_cpu(sb.s_v1.s_blocksize); dico_add_u64(d, 0, FSYSHEADKEY_FSREISERBLOCKSIZE, temp16); msgprintf(MSG_DEBUG1, "reiserfs_blksize=[%ld]\n", (long)temp16); // ---- minimum fsarchiver version required to restore dico_add_u64(d, 0, FSYSHEADKEY_MINFSAVERSION, FSA_VERSION_BUILD(0, 6, 4, 0)); reiserfs_read_sb_close: close(fd); reiserfs_read_sb_return: return ret; } int reiserfs_mount(char *partition, char *mntbuf, char *fsbuf, int flags, char *mntinfo) { return generic_mount(partition, mntbuf, fsbuf, "user_xattr,acl", flags); } int reiserfs_umount(char *partition, char *mntbuf) { return generic_umount(mntbuf); } int reiserfs_test(char *devname) { struct reiserfs_super_block sb; int fd=-1; if ((fd=open64(devname, O_RDONLY|O_LARGEFILE))<0) return false; if (lseek(fd, REISERFS_DISK_OFFSET_IN_BYTES, SEEK_SET)!=REISERFS_DISK_OFFSET_IN_BYTES) { close(fd); return false; } if (read(fd, &sb, sizeof(sb))!=sizeof(sb)) { close(fd); return false; } if ((strncmp(sb.s_v1.s_magic, REISERFS_SUPER_MAGIC_STRING, strlen(REISERFS_SUPER_MAGIC_STRING)) != 0) && (strncmp(sb.s_v1.s_magic, REISER2FS_SUPER_MAGIC_STRING, strlen(REISER2FS_SUPER_MAGIC_STRING)) != 0)) { close(fd); return false; } close(fd); return true; } int reiserfs_get_reqmntopt(char *partition, cstrlist *reqopt, cstrlist *badopt) { if (!reqopt || !badopt) return -1; strlist_add(badopt, "nouser_xattr"); strlist_add(badopt, "noacl"); return 0; } fsarchiver-0.8.7/src/fs_ntfs.c0000644000175000017500000002323414405605077013214 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include #include "fsarchiver.h" #include "devinfo.h" #include "dico.h" #include "common.h" #include "fs_ntfs.h" #include "filesys.h" #include "strlist.h" #include "error.h" int ntfs_mkfs(cdico *d, char *partition, char *fsoptions, char *mkfslabel, char *mkfsuuid) { char command[2048]; char buffer[2048]; char options[2048]; int exitst; u64 temp64; u32 temp32; u16 temp16; // there is no option that just displays the version and return 0 in mkfs.ntfs if (exec_command(command, sizeof(command), NULL, NULL, 0, NULL, 0, "mkfs.ntfs")!=0) { errprintf("mkfs.ntfs not found. please install ntfsprogs-2.0.0 on your system or check the PATH.\n"); return -1; } // ---- set the advanced filesystem settings from the dico memset(options, 0, sizeof(options)); if (strlen(mkfslabel) > 0) strlcatf(options, sizeof(options), " --label '%s' ", mkfslabel); else if (dico_get_string(d, 0, FSYSHEADKEY_FSLABEL, buffer, sizeof(buffer))==0 && strlen(buffer)>0) strlcatf(options, sizeof(options), " --label '%s' ", buffer); if (dico_get_u16(d, 0, FSYSHEADKEY_NTFSSECTORSIZE, &temp16)==0) strlcatf(options, sizeof(options), " -s %ld ", (long)temp16); if (dico_get_u32(d, 0, FSYSHEADKEY_NTFSCLUSTERSIZE, &temp32)==0) strlcatf(options, sizeof(options), " -c %ld ", (long)temp32); // ---- mkfsopt from command line strlcatf(options, sizeof(options), " %s ", fsoptions); if (exec_command(command, sizeof(command), &exitst, NULL, 0, NULL, 0, "mkfs.ntfs -f %s %s", options, partition)!=0 || exitst!=0) { errprintf("command [%s] failed\n", command); return -1; } // ---- preserve ntfs uuid (attribute saved only with fsarchiver>=0.5.8) if (dico_get_u64(d, 0, FSYSHEADKEY_NTFSUUID, &temp64)==0) ntfs_replace_uuid(partition, cpu_to_le64(temp64)); return 0; } int ntfs_getinfo(cdico *d, char *devname) { struct s_devinfo devinfo; struct s_ntfsinfo info; char bootsect[512]; int fd=-1; if (((fd=open64(devname, O_RDONLY|O_LARGEFILE))<0) || (read(fd, bootsect, sizeof(bootsect))!=sizeof(bootsect)) || (close(fd)<0)) { sysprintf("cannot open device or read bootsector on %s\n", devname); return -1; } // check signature in the boot sector if (memcmp(bootsect+3, "NTFS", 4) != 0) { errprintf("cannot find the ntfs signature on %s\n", devname); return -1; } // get device label from common code in libbklid if (get_devinfo(&devinfo, devname, -1, -1)!=0) { errprintf("get_devinfo(%s) failed\n", devname); return -1; } info.bytes_per_sector = le16_to_cpu(*((u16*)(bootsect+0xB))); info.sectors_per_clusters = le8_to_cpu(*((u8*)(bootsect+0xD))); info.bytes_per_cluster = info.bytes_per_sector * info.sectors_per_clusters; info.uuid = le64_to_cpu(*((u64*)(bootsect+0x48))); msgprintf(MSG_VERB2, "bytes_per_sector=[%lld]\n", (long long)info.bytes_per_sector); msgprintf(MSG_VERB2, "sectors_per_clusters=[%lld]\n", (long long)info.sectors_per_clusters); msgprintf(MSG_VERB2, "bytes_per_cluster=[%lld]\n", (long long)info.bytes_per_cluster); msgprintf(MSG_VERB2, "uuid=[%016llX]\n", (long long unsigned int)info.uuid); dico_add_u16(d, 0, FSYSHEADKEY_NTFSSECTORSIZE, info.bytes_per_sector); dico_add_u32(d, 0, FSYSHEADKEY_NTFSCLUSTERSIZE, info.bytes_per_cluster); dico_add_u64(d, 0, FSYSHEADKEY_NTFSUUID, info.uuid); // get label from library dico_add_string(d, 0, FSYSHEADKEY_FSLABEL, devinfo.label); msgprintf(MSG_VERB2, "ntfs_label=[%s]\n", devinfo.label); // minimum fsarchiver version required to restore dico_add_u64(d, 0, FSYSHEADKEY_MINFSAVERSION, FSA_VERSION_BUILD(0, 6, 4, 0)); // save mount options used at savefs so that restfs can use consistent mount options dico_add_string(d, 0, FSYSHEADKEY_MOUNTINFO, "streams_interface=xattr"); // may change in the future return 0; } int ntfs_mount(char *partition, char *mntbuf, char *fsbuf, int flags, char *mntinfo) { char minversion[1024]; char streamif[1024]; int year=0, month=0, day=0; char stderrbuf[2048]; char command[2048]; char options[1024]; char delims[]="\n\r"; char *saveptr; char *result; u64 instver=0; int exitst; // init memset(options, 0, sizeof(options)); memset(stderrbuf, 0, sizeof(stderrbuf)); snprintf(minversion, sizeof(minversion), "ntfs-3g %.4d.%.2d.%.2d (standard release)", NTFS3G_MINVER_Y, NTFS3G_MINVER_M, NTFS3G_MINVER_D); // check that mount.ntfs-3g is available (don't check the exit status, it's not supposed to be 0) if (exec_command(command, sizeof(command), NULL, NULL, 0, stderrbuf, sizeof(stderrbuf), "ntfs-3g -h")!=0) { errprintf("ntfs-3g not found. please install %s\n" "or a newer version on your system or check the PATH.\n", minversion); return -1; } // check if there is a recent ntfs-3g version installed result=strtok_r(stderrbuf, delims, &saveptr); while (result != NULL && instver==0) { if (sscanf(result, "ntfs-3g %4d.%2d.%2d ", &year, &month, &day)==3) { instver=NTFS3G_VERSION(year, month, day); msgprintf(MSG_VERB2, "ntfs-3g detected version: year=[%.4d], month=[%.2d], day=[%.2d]\n", year, month, day); } result = strtok_r(NULL, delims, &saveptr); } if (instver < NTFS3G_VERSION(NTFS3G_MINVER_Y, NTFS3G_MINVER_M, NTFS3G_MINVER_D)) { errprintf("fsarchiver requires %s to operate. The detected version is too old\n", minversion); return -1; } else { msgprintf(MSG_VERB2, "ntfs-3g has been found: version is %d.%d.%d\n", year, month, day); } // if mntinfo is specified, check which mount option was used at savefs and use the same for consistency snprintf(streamif, sizeof(streamif), "xattr"); // set the default "streams_interface" (may change in the future) if ((mntinfo!=NULL) && (strlen(mntinfo)>0)) // if a mntinfo has been specified, respect its options { if (strstr(mntinfo, "streams_interface=xattr")!=NULL) // if "xattr" was used during savefs then use it for restfs snprintf(streamif, sizeof(streamif), "xattr"); else if (strstr(mntinfo, "streams_interface=windows")!=NULL) // if "windows" was used during savefs then use it for restfs snprintf(streamif, sizeof(streamif), "windows"); } // set mount options strlcatf(options, sizeof(options), " -o streams_interface=%s -o efs_raw ", streamif); if (flags & MS_RDONLY) strlcatf(options, sizeof(options), " -o ro "); // ---- set the advanced filesystem settings from the dico if (exec_command(command, sizeof(command), &exitst, NULL, 0, NULL, 0, "ntfs-3g %s %s %s", options, partition, mntbuf)!=0 || exitst!=0) { errprintf("command [%s] failed, make sure a recent version of ntfs-3g is installed\n", command); return -1; } return 0; } int ntfs_umount(char *partition, char *mntbuf) { char command[2048]; int existst; if (exec_command(command, sizeof(command), NULL, NULL, 0, NULL, 0, "fusermount")!=0) { errprintf("fusermount not found. please install fuse on your system or check the PATH.\n"); return -1; } if (exec_command(command, sizeof(command), &existst, NULL, 0, NULL, 0, "fusermount -u %s", mntbuf)!=0 || existst!=0) { errprintf("cannot unmount [%s]\n", mntbuf); return -1; } return 0; } int ntfs_test(char *devname) { char bootsect[16384]; int fd=-1; if ((fd=open64(devname, O_RDONLY|O_LARGEFILE))<0) return false; if (read(fd, bootsect, sizeof(bootsect))!=sizeof(bootsect)) { close(fd); return false; } if (memcmp(bootsect+3, "NTFS", 4) != 0) { close(fd); return false; } close(fd); return true; } int ntfs_get_reqmntopt(char *partition, cstrlist *reqopt, cstrlist *badopt) { if (!reqopt || !badopt) return -1; strlist_add(reqopt, "streams_interface=xattr"); // may change in the future return 0; } int ntfs_replace_uuid(char *devname, u64 uuid) { u8 bootsect[512]; int fd=-1; if ((fd=open64(devname, O_RDWR|O_LARGEFILE))<0) { errprintf("cannot open(%s, O_RDWR)\n", devname); return -1; } if (read(fd, bootsect, sizeof(bootsect))!=sizeof(bootsect)) { errprintf("cannot read the boot sector on %s\n", devname); close(fd); return -1; } memcpy(bootsect+0x48, &uuid, sizeof(uuid)); if (lseek(fd, 0, SEEK_SET)!=0) { errprintf("lseek(fd, 0, SEEK_SET) failed\n"); close(fd); return -1; } if (write(fd, bootsect, sizeof(bootsect))!=sizeof(bootsect)) { errprintf("cannot modify the boot sector on %s\n", devname); close(fd); return -1; } close(fd); return 0; } fsarchiver-0.8.7/src/oper_save.c0000644000175000017500000015522714405605077013545 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "fsarchiver.h" #include "dico.h" #include "dichl.h" #include "archwriter.h" #include "options.h" #include "common.h" #include "oper_save.h" #include "strlist.h" #include "filesys.h" #include "fs_ext2.h" #include "fs_xfs.h" #include "fs_reiserfs.h" #include "fs_reiser4.h" #include "fs_jfs.h" #include "fs_btrfs.h" #include "fs_ntfs.h" #include "thread_comp.h" #include "thread_archio.h" #include "syncthread.h" #include "regmulti.h" #include "crypto.h" #include "error.h" #include "queue.h" #ifndef ENOATTR #define ENOATTR ENODATA #endif typedef struct s_savear { carchwriter ai; cregmulti regmulti; cdichl *dichardlinks; cstats stats; int fstype; int fsid; u64 objectid; u64 cost_global; u64 cost_current; } csavear; typedef struct s_devinfo { char devpath[PATH_MAX]; char partmount[PATH_MAX]; bool mountedbyfsa; int fstype; } cdevinfo; int createar_obj_regfile_multi(csavear *save, cdico *header, char *relpath, char *fullpath, u64 filesize) { char databuf[FSA_MAX_SMALLFILESIZE]; u8 md5sum[16]; int ret=0; int res; int fd; // The checksum will be in the obj-header not in a file footer if ((fd=open64(fullpath, O_RDONLY|O_LARGEFILE))<0) { sysprintf("Cannot open small file %s for reading\n", relpath); return -1; } msgprintf(MSG_DEBUG1, "backup_obj_regfile_multi(file=%s, size=%lld)\n", relpath, (long long)filesize); res=read(fd, databuf, (long)filesize); close(fd); if (res!=filesize) { if (res>=0 && resregmulti, filesize)==false) { if (regmulti_save_enqueue(&save->regmulti, &g_queue, save->fsid)!=0) { errprintf("Cannot queue last block of small-files\n"); return -1; } regmulti_empty(&save->regmulti); } // copy current small file to the shared-block if (regmulti_save_addfile(&save->regmulti, header, databuf, filesize)!=0) { errprintf("Cannot add small-file %s to regmulti structure\n", relpath); return -1; } return ret; } int createar_obj_regfile_unique(csavear *save, cdico *header, char *relpath, char *fullpath, u64 filesize) // large or empty files { cdico *footerdico=NULL; struct s_blockinfo blkinfo; gcry_md_hd_t md5ctx; u32 curblocksize; bool eof=false; u64 remaining; char text[256]; u8 *origblock; u8 *md5tmp; u8 md5sum[16]; u64 filepos; int ret=0; int res; int fd; if (gcry_md_open(&md5ctx, GCRY_MD_MD5, 0) != GPG_ERR_NO_ERROR) { errprintf("gcry_md_open() failed\n"); return -1; } if ((fd=open64(fullpath, O_RDONLY|O_LARGEFILE))<0) { sysprintf("Cannot open %s for reading\n", relpath); return -1; } // write header with file attributes (only if open64() works) queue_add_header(&g_queue, header, FSA_MAGIC_OBJT, save->fsid); msgprintf(MSG_DEBUG1, "backup_obj_regfile_unique(file=%s, size=%lld)\n", relpath, (long long)filesize); for (filepos=0; (filesize>0) && (filepos < filesize) && (get_interrupted()==false); filepos+=curblocksize) { remaining=filesize-filepos; curblocksize=min(remaining, g_options.datablocksize); msgprintf(MSG_DEBUG2, "----> filepos=%lld, remaining=%lld, curblocksize=%lld\n", (long long)filepos, (long long)remaining, (long long)curblocksize); origblock=malloc(curblocksize); if (!origblock) { errprintf("malloc(%ld) failed: cannot allocate data block\n", (long)origblock); ret=-1; goto backup_obj_regfile_unique_error; } if (eof==false) // file has not been truncated: read the next block { if ((res=read(fd, origblock, (long)curblocksize))!=curblocksize) { ret=-1; if (res>=0 && resfsid; if (queue_add_block(&g_queue, &blkinfo, QITEM_STATUS_TODO)!=0) { sysprintf("queue_add_block(%s) failed\n", relpath); ret=-1; goto backup_obj_regfile_unique_error; } } if (get_interrupted()==true) { errprintf("operation has been interrupted\n"); ret=-1; goto backup_obj_regfile_unique_error; } // write the footer with the global md5sum if ((md5tmp=gcry_md_read(md5ctx, GCRY_MD_MD5))==NULL) { errprintf("gcry_md_read() failed\n"); ret=-1; goto backup_obj_regfile_unique_error; } memcpy(md5sum, md5tmp, 16); gcry_md_close(md5ctx); msgprintf(MSG_DEBUG1, "--> finished loop for file=%s, size=%lld, md5=[%s]\n", relpath, (long long)filesize, format_md5(text, sizeof(text), md5sum)); // don't write the footer for empty files (checksum does not make sense --> don't waste space in the archive) if (filesize>0) { if ((footerdico=dico_alloc())==NULL) { errprintf("dico_alloc() failed\n"); ret=-1; goto backup_obj_regfile_unique_error; } dico_add_data(footerdico, 0, BLOCKFOOTITEMKEY_MD5SUM, md5sum, 16); if (queue_add_header(&g_queue, footerdico, FSA_MAGIC_FILF, save->fsid)!=0) { msgprintf(MSG_VERB2, "Cannot write footer for file %s\n", relpath); ret=-1; goto backup_obj_regfile_unique_error; } } backup_obj_regfile_unique_error: close(fd); return ret; } int createar_item_xattr(csavear *save, char *root, char *relpath, struct stat64 *statbuf, cdico *d) { char fullpath[PATH_MAX]; char *valbuf=NULL; char buffer[4096]; s64 attrsize; int valsize=0; int listlen; u64 attrcnt; int ret=0; int pos; int len; // init concatenate_paths(fullpath, sizeof(fullpath), root, relpath); attrcnt=0; memset(buffer, 0, sizeof(buffer)); listlen=llistxattr(fullpath, buffer, sizeof(buffer)-1); msgprintf(MSG_DEBUG2, "xattr:llistxattr(%s)=%d\n", relpath, listlen); for (pos=0; (pos65535LL) { errprintf("file [%s] has an xattr [%s] with data too big (size=%ld, maxsize=64k)\n", relpath, buffer+pos, (long)attrsize); ret=-1; continue; // copy the next xattr } errno=0; if ((valbuf=malloc(attrsize+1))==NULL) { sysprintf("malloc(%ld) failed\n", (long)(attrsize+1)); ret=-1; continue; // ignore the current xattr } errno=0; valsize=lgetxattr(fullpath, buffer+pos, valbuf, attrsize); msgprintf(MSG_VERB2, " xattr:lgetxattr(%s,%s)=%d\n", relpath, buffer+pos, valsize); if (valsize>=0) { msgprintf(MSG_VERB2, " xattr:lgetxattr(%s,%s)=%d: [%s]\n", relpath, buffer+pos, valsize, buffer+pos); msgprintf(MSG_DEBUG2, " xattr:lgetxattr(%s)=%d: [%s]=[%s]\n", relpath, valsize, buffer+pos, valbuf); msgprintf(MSG_DEBUG2, " xattr:dico_add_string(%s, xattr): key=%d, name=[%s]\n", relpath, (int)(2*attrcnt)+0, buffer+pos); dico_add_string(d, DICO_OBJ_SECTION_XATTR, (2*attrcnt)+0, buffer+pos); msgprintf(MSG_DEBUG2, " xattr:dico_add_data(%s, xattr): key=%d, data (size=[%d])\n", relpath, (int)(2*attrcnt)+1, valsize); dico_add_data(d, DICO_OBJ_SECTION_XATTR, (2*attrcnt)+1, valbuf, valsize); attrcnt++; free(valbuf); } else if (errno!=ENOATTR) // if the attribute exists and we cannot read it { sysprintf(" xattr:lgetxattr(%s,%s)=%d\n", relpath, buffer+pos, valsize); ret=-1; free(valbuf); continue; // copy the next xattr } else // errno==ENOATTR hence the attribute does not exist { msgprintf(MSG_VERB2, " xattr:lgetxattr-win(%s,%s)=-1: errno==ENOATTR\n", relpath, buffer+pos); free(valbuf); } } return ret; } int createar_item_winattr(csavear *save, char *root, char *relpath, struct stat64 *statbuf, cdico *d) { char fullpath[PATH_MAX]; char *valbuf=NULL; int valsize=0; s64 attrsize; u64 attrcnt; int ret=0; int i; char *winattr[]= {"system.ntfs_acl", "system.ntfs_attrib", "system.ntfs_reparse_data", "system.ntfs_times", "system.ntfs_dos_name", NULL}; // init concatenate_paths(fullpath, sizeof(fullpath), root, relpath); attrcnt=0; for (i=0; winattr[i]; i++) { if ((strcmp(relpath, "/")==0) && (strcmp(winattr[i], "system.ntfs_dos_name")==0)) // the root inode does not require a short name continue; errno=0; if ((attrsize=lgetxattr(fullpath, winattr[i], NULL, 0)) < 0) // get the size of the attribute { if (errno!=ENOATTR) { sysprintf(" winattr:lgetxattr(%s,%s): returned negative attribute size\n", relpath, winattr[i]); // output if there are any other error ret=-1; } continue; // ignore the current xattr } msgprintf(MSG_VERB2, " winattr:file=[%s], attrcnt=%d, name=[%s], size=%ld\n", relpath, (int)attrcnt, winattr[i], (long)attrsize); if (attrsize>65535LL) { errprintf("file [%s] has an xattr [%s] with data size=%ld too big (max xattr size is 65535)\n", relpath, winattr[i], (long)attrsize); ret=-1; continue; // ignore the current xattr } errno=0; if ((valbuf=malloc(attrsize+1))==NULL) { sysprintf("malloc(%d) failed\n", (int)(attrsize+1)); ret=-1; continue; // ignore the current xattr } valsize=lgetxattr(fullpath, winattr[i], valbuf, attrsize); msgprintf(MSG_VERB2, " winattr:lgetxattr-win(%s,%s)=%d\n", relpath, winattr[i], valsize); if (valsize>=0) { msgprintf(MSG_VERB2, " winattr:dico_add_string(%s, winattr): key=%d, name=[%s]\n", relpath, (int)(2*attrcnt)+0, winattr[i]); dico_add_string(d, DICO_OBJ_SECTION_WINATTR, (2*attrcnt)+0, winattr[i]); msgprintf(MSG_VERB2, " winattr:dico_add_data(%s, winattr): key=%d, data (size=[%d])\n", relpath, (int)(2*attrcnt)+1, valsize); dico_add_data(d, DICO_OBJ_SECTION_WINATTR, (2*attrcnt)+1, valbuf, valsize); free(valbuf); attrcnt++; } else if (errno!=ENOATTR) // if the attribute exists and we cannot read it { sysprintf(" winattr:lgetxattr(%s,%s)=%d\n", relpath, winattr[i], valsize); ret=-1; free(valbuf); continue; // ignore the current xattr } else // errno==ENOATTR hence the attribute does not exist { msgprintf(MSG_VERB2, " winattr:lgetxattr-win(%s,%s)=-1: errno==ENOATTR\n", relpath, winattr[i]); free(valbuf); } } return ret; } int createar_item_stdattr(csavear *save, char *root, char *relpath, struct stat64 *statbuf, cdico *d, int *objtype, u64 *filecost) { struct stat64 stattarget; char fullpath[PATH_MAX]; char buffer[PATH_MAX]; char buffer2[PATH_MAX]; char directory[PATH_MAX]; char *linktarget=NULL; u64 flags; int res; int i; // init flags=0; *objtype=OBJTYPE_NULL; *filecost=FSA_COST_PER_FILE; // fixed cost per file concatenate_paths(fullpath, sizeof(fullpath), root, relpath); msgprintf(MSG_DEBUG2, "Adding [%.5lld]=[%s]\n", (long long)save->objectid, relpath); if (dico_add_u64(d, DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_OBJECTID, (u64)(save->objectid)++)!=0) { errprintf("dico_add_u64(DICO_OBJ_SECTION_STDATTR) failed\n"); return -1; } if (dico_add_string(d, DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_PATH, relpath)!=0) { errprintf("dico_add_string(DICO_OBJ_SECTION_STDATTR) failed\n"); return -1; } if (dico_add_u64(d, DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_SIZE, (u64)statbuf->st_size)!=0) { errprintf("dico_add_u64(DICO_OBJ_SECTION_STDATTR) failed\n"); return -1; } if (dico_add_u32(d, DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_MODE, (u32)statbuf->st_mode)!=0) { errprintf("dico_add_u32(DICO_OBJ_SECTION_STDATTR) failed\n"); return -1; } if (dico_add_u32(d, DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_UID, (u32)statbuf->st_uid)!=0) { errprintf("dico_add_u32(DICO_OBJ_SECTION_STDATTR) failed\n"); return -1; } if (dico_add_u32(d, DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_GID, (u32)statbuf->st_gid)!=0) { errprintf("dico_add_u32(gid) failed\n"); return -1; } if (dico_add_u64(d, DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_ATIME, (u32)statbuf->st_atime)!=0) { errprintf("dico_add_u32(DICO_OBJ_SECTION_STDATTR) failed\n"); return -1; } if (dico_add_u64(d, DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_MTIME, (u32)statbuf->st_mtime)!=0) { errprintf("dico_add_u32(DICO_OBJ_SECTION_STDATTR) failed\n"); return -1; } // 2. copy specific properties to the dico switch (statbuf->st_mode & S_IFMT) { case S_IFDIR: *objtype=OBJTYPE_DIR; break; case S_IFLNK: // save path of the target of the symlink *objtype=OBJTYPE_SYMLINK; memset(buffer, 0, sizeof(buffer)); memset(buffer2, 0, sizeof(buffer2)); if ((readlink(fullpath, buffer, sizeof(buffer)))<0) { sysprintf("readlink(%s) failed\n", fullpath); return -1; } // fix path as ntfs-3g>=2010.3.6 may return an absolute path that includes the mount directory linktarget=buffer; if (memcmp(linktarget, "/tmp/fsa/", 9)==0) { for (i=0; i<3; i++) { if (linktarget[0]=='/') linktarget++; while (linktarget[0]!=0 && linktarget[0]!='/') linktarget++; } } msgprintf(MSG_DEBUG1, "fixed-readlink([%s])=[%s]\n", fullpath, linktarget); dico_add_string(d, DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_SYMLINK, linktarget); // save type of the target of the symlink (required to recreate ntfs symlinks) if (filesys[save->fstype].savesymtargettype==true) { if (linktarget[0]=='/') // absolute symbolic link { snprintf(buffer2, sizeof(buffer2), "%s", buffer); msgprintf(MSG_DEBUG1, "absolute-symlink: fullpath=[%s] --> lstat64=[%s]\n", fullpath, buffer2); } else // relative symbolic link { extract_dirpath(fullpath, directory, sizeof(directory)); concatenate_paths(buffer2, sizeof(buffer2), directory, linktarget); msgprintf(MSG_DEBUG1, "relative-symlink: fullpath=[%s] --> lstat64=[%s]\n", fullpath, buffer2); } if (lstat64(buffer2, &stattarget)==0) { switch (stattarget.st_mode & S_IFMT) { case S_IFDIR: dico_add_u64(d, DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_LINKTARGETTYPE, OBJTYPE_DIR); msgprintf(MSG_DEBUG1, "LINK: link=[%s], target=[%s]=DIR\n", relpath, buffer2); break; case S_IFREG: dico_add_u64(d, DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_LINKTARGETTYPE, OBJTYPE_REGFILEUNIQUE); msgprintf(MSG_DEBUG1, "LINK: link=[%s], target=[%s]=REGFILE\n", relpath, buffer2); break; default: msgprintf(MSG_DEBUG1, "LINK: link=[%s], target=[%s]=UNKNOWN\n", relpath, buffer2); break; } } } break; case S_IFREG: if (statbuf->st_nlink>1) // there are several links to that inode: there are hard links { res=dichl_get(save->dichardlinks, (u64)statbuf->st_rdev, (u64)statbuf->st_ino, buffer, sizeof(buffer)); if (res==0) // inode already seen --> hard link { dico_add_string(d, DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_HARDLINK, buffer); *objtype=OBJTYPE_HARDLINK; } else // next link to thar inode will be an hard link { dichl_add(save->dichardlinks, (u64)statbuf->st_rdev, (u64)statbuf->st_ino, relpath); } } if (*objtype==OBJTYPE_NULL) // not an hard-link: it's a regular file or the first link when multiple links found { // don't allow reg-files with hardlinks to be copied as a small-file with other small-files // the file would be copied later in the archive (when the block for small files is ready) // and then the hardlink may come before the regfile (first link to that object) // case 1: file smaller than threshold: pack its data with other small files in a single compressed block *filecost+=statbuf->st_size; if ((statbuf->st_size > 0) && (statbuf->st_size < g_options.smallfilethresh) && (statbuf->st_nlink==1)) *objtype=OBJTYPE_REGFILEMULTI; else // case 2: file having hardlinks or larger than the threshold *objtype=OBJTYPE_REGFILEUNIQUE; // empty files are considered as OBJTYPE_REGFILEUNIQUE (statbuf->st_size==0) } if (*objtype==OBJTYPE_REGFILEUNIQUE || *objtype==OBJTYPE_REGFILEMULTI) { if (((u64)statbuf->st_blocks) * ((u64)DEV_BSIZE) < ((u64)statbuf->st_size)) flags|=FSA_FILEFLAGS_SPARSE; } break; case S_IFCHR: dico_add_u64(d, DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_RDEV, statbuf->st_rdev); *objtype=OBJTYPE_CHARDEV; break; case S_IFBLK: dico_add_u64(d, DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_RDEV, statbuf->st_rdev); *objtype=OBJTYPE_BLOCKDEV; break; case S_IFIFO: dico_add_u64(d, DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_RDEV, statbuf->st_rdev); *objtype=OBJTYPE_FIFO; break; case S_IFSOCK: dico_add_u64(d, DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_RDEV, statbuf->st_rdev); *objtype=OBJTYPE_SOCKET; break; default: errprintf("unknown item %s\n", fullpath); return -1; break; } dico_add_u32(d, DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_OBJTYPE, *objtype); if (flags!=0) dico_add_u64(d, DICO_OBJ_SECTION_STDATTR, DISKITEMKEY_FLAGS, flags); return 0; } int createar_save_file(csavear *save, char *root, char *relpath, struct stat64 *statbuf, u64 *costeval) { char fullpath[PATH_MAX]; char strprogress[256]; cdico *dicoattr; int attrerrors=0; u64 filecost; s64 progress; int objtype; int res; // init concatenate_paths(fullpath, sizeof(fullpath), root, relpath); // don't backup the archive file itself if (archwriter_is_path_to_curvol(&save->ai, fullpath)==true) { errprintf("file [%s] ignored: it's the current archive file\n", fullpath); save->stats.err_regfile++; return 0; // not a fatal error, oper must continue } // ---- backup standard file attributes if ((dicoattr=dico_alloc())==NULL) { errprintf("dico_alloc() failed\n"); return -1; // fatal error } if (createar_item_stdattr(save, root, relpath, statbuf, dicoattr, &objtype, &filecost)!=0) { msgprintf(MSG_STACK, "backup_item_stdattr() failed: cannot read standard attributes on [%s]\n", relpath); attrerrors++; } // --- cost required for the progression info if (costeval!=NULL) { *costeval+=filecost; dico_destroy(dicoattr); return 0; } // ---- backup other file attributes (xattr + winattr) // selinux can present fake xattrs // do not try to save them if not supported by the filesystem, otherwise restoration will fail if (filesys[save->fstype].support_for_xattr==true) { if (createar_item_xattr(save, root, relpath, statbuf, dicoattr)!=0) { msgprintf(MSG_STACK, "backup_item_xattr() failed: cannot prepare xattr-dico for item %s\n", relpath); attrerrors++; } } if (filesys[save->fstype].winattr==true) { if (createar_item_winattr(save, root, relpath, statbuf, dicoattr)!=0) { msgprintf(MSG_STACK, "backup_item_winattr() failed: cannot prepare winattr-dico for item %s\n", relpath); attrerrors++; } } // ---- file details and progress bar if (get_interrupted()==false) { memset(strprogress, 0, sizeof(strprogress)); if (save->cost_global>0) { save->cost_current+=filecost; progress=((save->cost_current)*100)/(save->cost_global); if (progress>=0 && progress<=100) snprintf(strprogress, sizeof(strprogress), "[%3d%%]", (int)progress); } msgprintf(MSG_VERB1, "-[%.2d]%s[%s] %s\n", save->fsid, strprogress, get_objtype_name(objtype), relpath); } // ---- backup file contents for regfiles switch (objtype) { case OBJTYPE_DIR: if (attrerrors>0) { save->stats.err_dir++; dico_destroy(dicoattr); return 0; // error is not fatal, operation must continue } if (queue_add_header(&g_queue, dicoattr, FSA_MAGIC_OBJT, save->fsid)!=0) { errprintf("queue_add_header(%s) failed\n", relpath); return -1; // fatal error } save->stats.cnt_dir++; break; case OBJTYPE_SYMLINK: if (attrerrors>0) { save->stats.err_symlink++; dico_destroy(dicoattr); return 0; // error is not fatal, operation must continue } if (queue_add_header(&g_queue, dicoattr, FSA_MAGIC_OBJT, save->fsid)!=0) { errprintf("queue_add_header(%s) failed\n", relpath); return -1; // fatal error } save->stats.cnt_symlink++; break; case OBJTYPE_HARDLINK: if (attrerrors>0) { save->stats.err_hardlink++; dico_destroy(dicoattr); return 0; // error is not fatal, operation must continue } if (queue_add_header(&g_queue, dicoattr, FSA_MAGIC_OBJT, save->fsid)!=0) { errprintf("queue_add_header(%s) failed\n", relpath); return -1; // fatal error } save->stats.cnt_hardlink++; break; case OBJTYPE_CHARDEV: case OBJTYPE_BLOCKDEV: case OBJTYPE_FIFO: case OBJTYPE_SOCKET: if (attrerrors>0) { save->stats.err_special++; dico_destroy(dicoattr); return 0; // error is not fatal, operation must continue } if (queue_add_header(&g_queue, dicoattr, FSA_MAGIC_OBJT, save->fsid)!=0) { errprintf("queue_add_header(%s) failed\n", relpath); return -1; // fatal error } save->stats.cnt_special++; break; case OBJTYPE_REGFILEUNIQUE: if (attrerrors>0) { save->stats.err_regfile++; dico_destroy(dicoattr); return 0; // error is not fatal, operation must continue } if ((res=createar_obj_regfile_unique(save, dicoattr, relpath, fullpath, statbuf->st_size))!=0) { msgprintf(MSG_STACK, "backup_obj_regfile_unique(%s)=%d failed\n", relpath, res); save->stats.err_regfile++; return 0; // not a fatal error, oper must continue } else { save->stats.cnt_regfile++; } break; case OBJTYPE_REGFILEMULTI: if (attrerrors>0) { save->stats.err_regfile++; dico_destroy(dicoattr); return 0; // error is not fatal, operation must continue } if ((res=createar_obj_regfile_multi(save, dicoattr, relpath, fullpath, statbuf->st_size))!=0) { msgprintf(MSG_STACK, "backup_obj_regfile_multi(%s)=%d failed\n", relpath, res); save->stats.err_regfile++; return 0; // not a fatal error, oper must continue } else { save->stats.cnt_regfile++; } break; default: // unknown type errprintf("invalid object type: %ld for file %s\n", (long)objtype, relpath); return -1; // fatal error break; } return 0; } int createar_save_directory(csavear *save, char *root, char *path, u64 *costeval) { char fulldirpath[PATH_MAX]; char fullpath[PATH_MAX]; char relpath[PATH_MAX]; struct stat64 statbuf; struct dirent *dir; DIR *dirdesc; int ret=0; // init concatenate_paths(fulldirpath, sizeof(fulldirpath), root, path); if (!(dirdesc=opendir(fulldirpath))) { sysprintf("cannot open directory %s\n", fulldirpath); return 0; // not a fatal error, oper must continue } // backup the directory itself (important for the root of the filesystem) if (lstat64(fulldirpath, &statbuf)!=0) { sysprintf("cannot lstat64(%s)\n", fulldirpath); ret=-1; goto backup_dir_err; } // save info about the directory itself if (createar_save_file(save, root, path, &statbuf, costeval)!=0) { errprintf("createar_save_file(%s,%s) failed\n", root, path); ret=-1; goto backup_dir_err; } while (((dir = readdir(dirdesc)) != NULL) && (get_interrupted()==false)) { // ---- ignore "." and ".." and ignore mount-points if (strcmp(dir->d_name,".")==0 || strcmp(dir->d_name,"..")==0) continue; // ignore "." and ".." // ---- calculate paths concatenate_paths(relpath, sizeof(relpath), path, dir->d_name); concatenate_paths(fullpath, sizeof(fullpath), fulldirpath, dir->d_name); // ---- get details about current file if (lstat64(fullpath, &statbuf)!=0) { if (g_options.allowsaverw==0) { sysprintf("cannot lstat64(%s)\n", fullpath); ret=-1; goto backup_dir_err; } else { sysprintf("cannot lstat64(%s), ignoring\n", fullpath); continue; // not a fatal error with option '-A' } } // check the list of excluded files/dirs if ((exclude_check(&g_options.exclude, dir->d_name)==true) // is filename excluded ? || (exclude_check(&g_options.exclude, relpath)==true)) // is filepath excluded ? { if (costeval==NULL) // dont log twice (eval + real) msgprintf(MSG_VERB2, "file/dir=[%s] excluded\n", relpath); continue; } // backup contents before the directory itself so that the dir-attributes are written after the dir contents if (S_ISDIR(statbuf.st_mode)) { if (createar_save_directory(save, root, relpath, costeval)!=0) { msgprintf(MSG_STACK, "createar_save_directory(%s) failed\n", relpath); ret=-1; goto backup_dir_err; } } else // not a directory { if (createar_save_file(save, root, relpath, &statbuf, costeval)!=0) { msgprintf(MSG_STACK, "createar_save_directory(%s) failed\n", relpath); ret=-1; goto backup_dir_err; } } } backup_dir_err: closedir(dirdesc); return ret; } int createar_save_directory_wrapper(csavear *save, char *root, char *path, u64 *costeval) { int ret; if ((save->dichardlinks=dichl_alloc())==NULL) { errprintf("dichardlinks=dichl_alloc() failed\n"); return -1; } if (regmulti_init(&save->regmulti, g_options.datablocksize)!=0) { errprintf("regmulti_init failed\n"); return -1; } ret=createar_save_directory(save, root, path, costeval); // put all small files that are in the last block to the queue if (regmulti_save_enqueue(&save->regmulti, &g_queue, save->fsid)!=0) { errprintf("Cannot queue last block of small-files\n"); return -1; } // dico for hard links not required anymore dichl_destroy(save->dichardlinks); return ret; } int createar_write_mainhead(csavear *save, int archtype, int fscount) { u8 bufcheckclear[FSA_CHECKPASSBUF_SIZE+8]; u8 bufcheckcrypt[FSA_CHECKPASSBUF_SIZE+8]; u64 cryptsize; u8 md5sum[16]; struct timeval now; cdico *d; if (!save) { errprintf("ai is NULL\n"); return -1; } // init gettimeofday(&now, NULL); if ((d=dico_alloc())==NULL) { errprintf("dico_alloc() failed\n"); return -1; } dico_add_string(d, 0, MAINHEADKEY_FILEFORMATVER, FSA_FILEFORMAT); dico_add_string(d, 0, MAINHEADKEY_PROGVERCREAT, FSA_VERSION); dico_add_string(d, 0, MAINHEADKEY_ARCHLABEL, g_options.archlabel); dico_add_u64(d, 0, MAINHEADKEY_CREATTIME, now.tv_sec); dico_add_u32(d, 0, MAINHEADKEY_ARCHIVEID, save->ai.archid); dico_add_u32(d, 0, MAINHEADKEY_ARCHTYPE, archtype); dico_add_u32(d, 0, MAINHEADKEY_COMPRESSALGO, g_options.compressalgo); dico_add_u32(d, 0, MAINHEADKEY_COMPRESSLEVEL, g_options.compresslevel); dico_add_u32(d, 0, MAINHEADKEY_ENCRYPTALGO, g_options.encryptalgo); dico_add_u32(d, 0, MAINHEADKEY_FSACOMPLEVEL, g_options.fsacomplevel); dico_add_u32(d, 0, MAINHEADKEY_HASDIRSINFOHEAD, true); // minimum fsarchiver version required to restore that archive dico_add_u64(d, 0, MAINHEADKEY_MINFSAVERSION, FSA_VERSION_BUILD(0, 6, 4, 0)); if (archtype==ARCHTYPE_FILESYSTEMS) { dico_add_u64(d, 0, MAINHEADKEY_FSCOUNT, fscount); } // if encryption is enabled, save the md5sum of a random buffer to check the password if (g_options.encryptalgo!=ENCRYPT_NONE) { memset(md5sum, 0, sizeof(md5sum)); crypto_random(bufcheckclear, FSA_CHECKPASSBUF_SIZE); crypto_blowfish(FSA_CHECKPASSBUF_SIZE, &cryptsize, bufcheckclear, bufcheckcrypt, g_options.encryptpass, strlen((char*)g_options.encryptpass), true); gcry_md_hash_buffer(GCRY_MD_MD5, md5sum, bufcheckclear, FSA_CHECKPASSBUF_SIZE); assert(dico_add_data(d, 0, MAINHEADKEY_BUFCHECKPASSCLEARMD5, md5sum, 16)==0); assert(dico_add_data(d, 0, MAINHEADKEY_BUFCHECKPASSCRYPTBUF, bufcheckcrypt, FSA_CHECKPASSBUF_SIZE)==0); } if (queue_add_header(&g_queue, d, FSA_MAGIC_MAIN, FSA_FILESYSID_NULL)!=0) { errprintf("cannot write dico for main header\n"); dico_destroy(d); return -1; } return 0; } int filesystem_mount_partition(cdevinfo *devinfo, cdico *dicofsinfo, u16 fsid) { char fsbuf[FSA_MAX_FSNAMELEN]; struct statvfs64 statfsbuf; cstrlist reqmntopt; cstrlist badmntopt; cstrlist curmntopt; int showwarningcount1=0; int showwarningcount2=0; int errorattr=false; char temp[PATH_MAX]; char curmntdir[PATH_MAX]; char optbuf[128]; u64 fsbytestotal; u64 fsbytesused; int readwrite; int tmptype; int count; int res; int i; res=generic_get_mntinfo(devinfo->devpath, &readwrite, curmntdir, sizeof(curmntdir), optbuf, sizeof(optbuf), fsbuf, sizeof(fsbuf)); if (res==0) // partition is already mounted { devinfo->mountedbyfsa=false; //snprintf(partmnt, PATH_MAX, "%s", curmntdir); // return the mount point to main savefs function msgprintf(MSG_DEBUG1, "generic_get_mntinfo(%s): mnt=[%s], opt=[%s], fs=[%s], rw=[%d]\n", devinfo->devpath, curmntdir, optbuf, fsbuf, readwrite); if (readwrite==1 && g_options.allowsaverw==0) { errprintf("partition [%s] is mounted read/write. please mount it read-only \n" "and then try again. you can do \"mount -o remount,ro %s\". you can \n" "also run fsarchiver with option '-A' if you know what you are doing.\n", devinfo->devpath, devinfo->devpath); return -1; } if (generic_get_fstype(fsbuf, &devinfo->fstype)!=0) { if (strcmp(fsbuf, "fuseblk")==0) errprintf("partition [%s] is using a fuse based filesystem (probably ntfs-3g). Unmount it and try again\n", devinfo->devpath); else errprintf("filesystem of partition [%s] is not supported by fsarchiver: filesystem=[%s]\n", devinfo->devpath, fsbuf); return -1; } // check the filesystem is mounted with the right mount-options (to preserve acl and xattr) strlist_init(&reqmntopt); strlist_init(&badmntopt); strlist_init(&curmntopt); if (filesys[devinfo->fstype].reqmntopt(devinfo->devpath, &reqmntopt, &badmntopt)!=0) { errprintf("cannot get the required mount options for partition=[%s]\n", devinfo->devpath); strlist_empty(&reqmntopt); strlist_empty(&badmntopt); return -1; } strlist_split(&curmntopt, optbuf, ','); msgprintf(MSG_DEBUG2, "mount options found for partition=[%s]: [%s]\n", devinfo->devpath, strlist_merge(&curmntopt, temp, sizeof(temp), ',')); msgprintf(MSG_DEBUG2, "mount options required for partition=[%s]: [%s]\n", devinfo->devpath, strlist_merge(&reqmntopt, temp, sizeof(temp), ',')); msgprintf(MSG_DEBUG2, "mount options to avoid for partition=[%s]: [%s]\n", devinfo->devpath, strlist_merge(&badmntopt, temp, sizeof(temp), ',')); count=strlist_count(&reqmntopt); for (i=0; i < count; i++) { strlist_getitem(&reqmntopt, i, optbuf, sizeof(optbuf)); msgprintf(MSG_DEBUG2, "checking there is reqmntopt[%d]=[%s]\n", i, optbuf); if (strlist_exists(&curmntopt, optbuf)!=true) { if (showwarningcount1==0) errprintf("partition [%s] has to be mounted with options [%s] in order to preserve " "all its attributes. you can use mount with option remount to do that.\n", devinfo->devpath, strlist_merge(&reqmntopt, temp, sizeof(temp), ',')); if (g_options.dontcheckmountopts==true) { if (showwarningcount1++ == 0) // show this warning only once errprintf("fsarchiver will continue anyway since the option '-a' was used\n"); } else // don't ignore the mount options { errprintf("fsarchiver cannot continue, you can use option '-a' to ignore " "the mount options (xattr or acl may not be preserved)\n"); return -1; } } } count=strlist_count(&badmntopt); for (i=0; i < count; i++) { strlist_getitem(&badmntopt, i, optbuf, sizeof(optbuf)); msgprintf(MSG_DEBUG2, "checking there is not badmntopt[%d]=[%s]\n", i, optbuf); if (strlist_exists(&curmntopt, optbuf)==true) { if (showwarningcount2==0) errprintf("partition [%s] has to be mounted without options [%s] in order to preserve all its attributes\n", devinfo->devpath, strlist_merge(&badmntopt, temp, sizeof(temp), ',')); if (g_options.dontcheckmountopts==true) { if (showwarningcount2++ == 0) // show this warning only once errprintf("fsarchiver will continue anyway since the option '-a' was used\n"); } else // don't ignore the mount options { errprintf("fsarchiver cannot continue, you can use option '-a' to ignore " "the mount options (xattr or acl may not be preserverd)\n"); return -1; } } } strlist_empty(&reqmntopt); strlist_empty(&badmntopt); strlist_empty(&curmntopt); // create a "mount --bind" for that mounted partition (to see behind its mount points) mkdir_recursive(devinfo->partmount); if (mount(curmntdir, devinfo->partmount, NULL, MS_BIND|MS_RDONLY, NULL)!=0) { errprintf("mount(src=[%s], target=[%s], NULL, MS_BIND|MS_RDONLY, NULL) failed\n", curmntdir, devinfo->partmount); return -1; } devinfo->mountedbyfsa=true; } else // partition not yet mounted { mkdir_recursive(devinfo->partmount); msgprintf(MSG_DEBUG1, "partition %s is not mounted\n", devinfo->devpath); for (tmptype=-1, i=0; (filesys[i].name) && (tmptype==-1); i++) { if ((filesys[i].test(devinfo->devpath)==true) && (filesys[i].mount(devinfo->devpath, devinfo->partmount, filesys[i].name, MS_RDONLY, NULL)==0)) { tmptype=i; msgprintf(MSG_DEBUG1, "partition %s successfully mounted on [%s] as [%s]\n", devinfo->devpath, devinfo->partmount, filesys[i].name); } } if (tmptype==-1) { errprintf("cannot mount partition [%s]: filesystem may not be supported by either fsarchiver or the kernel.\n", devinfo->devpath); return -1; } devinfo->fstype=tmptype; devinfo->mountedbyfsa=true; } // Make sure users are aware if they save filesystems with experimental support in fsarchiver if ((g_options.experimental==false) && (filesys[devinfo->fstype].stable==false)) { errprintf("You must enable support for experimental features in order to save %s filesystems with fsarchiver.\n", filesys[devinfo->fstype].name); return -1; } // Make sure support for extended attributes is enabled if this filesystem supports it if (g_options.dontcheckmountopts==false) { errorattr=false; if (filesys[devinfo->fstype].support_for_xattr==true) { errno=0; res=lgetxattr(devinfo->partmount, "user.fsa_test_xattr", temp, sizeof(temp)); msgprintf(MSG_DEBUG1, "lgetxattr(\"%s\", \"user.fsa_test_attr\", buf, bufsize)=[%d] and errno=[%d]\n", devinfo->partmount, (int)res, (int)errno); // errno should be set to ENOATTR if we are able to read extended attributes if ((res!=0) && (errno==ENOTSUP)) { errprintf("fsarchiver is unable to access extended attributes on device [%s].\n", devinfo->devpath); errorattr=true; } } if (filesys[devinfo->fstype].support_for_acls==true) { errno=0; res=lgetxattr(devinfo->partmount, "system.posix_acl_access", temp, sizeof(temp)); msgprintf(MSG_DEBUG1, "lgetxattr(\"%s\", \"system.posix_acl_access\", buf, bufsize)=[%d] and errno=[%d]\n", devinfo->partmount, (int)res, (int)errno); // errno should be set to ENOATTR if we are able to read ACLs if ((res!=0) && (errno==ENOTSUP)) { errprintf("fsarchiver is unable to access ACLs on device [%s].\n", devinfo->devpath); errorattr=true; } } if (errorattr==true) { errprintf("Cannot continue, you can use option '-a' to ignore " "support for xattr and acl (they will not be preserved)\n"); return -1; } } // get space statistics if (statvfs64(devinfo->partmount, &statfsbuf)!=0) { errprintf("statvfs64(%s) failed\n", devinfo->partmount); return -1; } fsbytestotal=(u64)statfsbuf.f_frsize*(u64)statfsbuf.f_blocks; fsbytesused=fsbytestotal-((u64)statfsbuf.f_frsize*(u64)statfsbuf.f_bfree); dico_add_string(dicofsinfo, 0, FSYSHEADKEY_FILESYSTEM, filesys[devinfo->fstype].name); dico_add_string(dicofsinfo, 0, FSYSHEADKEY_MNTPATH, devinfo->partmount); dico_add_string(dicofsinfo, 0, FSYSHEADKEY_ORIGDEV, devinfo->devpath); dico_add_u64(dicofsinfo, 0, FSYSHEADKEY_BYTESTOTAL, fsbytestotal); dico_add_u64(dicofsinfo, 0, FSYSHEADKEY_BYTESUSED, fsbytesused); if (filesys[devinfo->fstype].getinfo(dicofsinfo, devinfo->devpath)!=0) { errprintf("cannot save filesystem attributes for partition %s\n", devinfo->devpath); return -1; } return 0; } int createar_oper_savefs(csavear *save, cdevinfo *devinfo) { cdico *dicobegin=NULL; cdico *dicoend=NULL; int ret=0; // write "begin of filesystem" header if ((dicobegin=dico_alloc())==NULL) { errprintf("dicostart=dico_alloc() failed\n"); return -1; } queue_add_header(&g_queue, dicobegin, FSA_MAGIC_FSYB, save->fsid); // init filesystem data struct save->fstype=devinfo->fstype; // main task ret=createar_save_directory_wrapper(save, devinfo->partmount, "/", NULL); // write "end of filesystem" header if ((dicoend=dico_alloc())==NULL) { errprintf("dicoend=dico_alloc() failed\n"); return -1; } // TODO: add stats about files count in that dico queue_add_header(&g_queue, dicoend, FSA_MAGIC_DATF, save->fsid); return ret; } int createar_oper_savedir(csavear *save, char *rootdir) { char fullpath[PATH_MAX]; char currentdir[PATH_MAX]; if (rootdir[0]=='/') // absolute path { snprintf(fullpath, sizeof(fullpath), "%s", rootdir); createar_save_directory_wrapper(save, "/", fullpath, NULL); } else // relative path { concatenate_paths(fullpath, sizeof(fullpath), getcwd(currentdir, sizeof(currentdir)), rootdir); createar_save_directory_wrapper(save, ".", rootdir, NULL); } return 0; } int oper_save(char *archive, int argc, char **argv, int archtype) { pthread_t thread_comp[FSA_MAX_COMPJOBS]; cdico *dicofsinfo[FSA_MAX_FSPERARCH]; cdevinfo devinfo[FSA_MAX_FSPERARCH]; pthread_t thread_writer; u64 cost_evalfs=0; u64 totalerr=0; cdico *dicoend=NULL; cdico *dirsinfo=NULL; struct stat64 st; csavear save; int ret=0; int i; // init memset(&save, 0, sizeof(save)); save.cost_global=0; // init archive archwriter_init(&save.ai); archwriter_generate_id(&save.ai); // pass options to archive path_force_extension(save.ai.basepath, PATH_MAX, archive, ".fsa"); // init misc data struct to zero thread_writer=0; for (i=0; i0) ret=-1; archwriter_destroy(&save.ai); return ret; } fsarchiver-0.8.7/src/fsarchiver.h0000644000175000017500000002177014405605077013716 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifndef __FSARCHIVER_H__ #define __FSARCHIVER_H__ #include "types.h" // ----------------------------- min and max ----------------------------- #if !defined(min) # define min(a, b) ((a) < (b) ? (a) : (b)) #endif #if !defined(max) # define max(a, b) ((a) > (b) ? (a) : (b)) #endif // -------------------------------- fsarchiver commands --------------------------------------------- enum {OPER_NULL=0, OPER_SAVEFS, OPER_RESTFS, OPER_SAVEDIR, OPER_RESTDIR, OPER_ARCHINFO, OPER_PROBE}; // ----------------------------------- dico sections ------------------------------------------------ enum {DICO_OBJ_SECTION_STDATTR=0, DICO_OBJ_SECTION_XATTR=1, DICO_OBJ_SECTION_WINATTR=2}; // ----------------------------------- archive types ------------------------------------------------ enum {ARCHTYPE_NULL=0, ARCHTYPE_FILESYSTEMS, ARCHTYPE_DIRECTORIES}; // ----------------------------------- volume header and footer ------------------------------------- enum {VOLUMEHEADKEY_VOLNUM, VOLUMEHEADKEY_ARCHID, VOLUMEHEADKEY_FILEFORMATVER, VOLUMEHEADKEY_PROGVERCREAT}; enum {VOLUMEFOOTKEY_VOLNUM, VOLUMEFOOTKEY_ARCHID, VOLUMEFOOTKEY_LASTVOL}; // ----------------------------------- algorithms used to process data------------------------------- enum {COMPRESS_NULL=0, COMPRESS_NONE, COMPRESS_LZO, COMPRESS_GZIP, COMPRESS_BZIP2, COMPRESS_LZMA, COMPRESS_LZ4, COMPRESS_ZSTD}; enum {ENCRYPT_NULL=0, ENCRYPT_NONE, ENCRYPT_BLOWFISH}; // ----------------------------------- dico keys ---------------------------------------------------- enum {OBJTYPE_NULL=0, OBJTYPE_DIR, OBJTYPE_SYMLINK, OBJTYPE_HARDLINK, OBJTYPE_CHARDEV, OBJTYPE_BLOCKDEV, OBJTYPE_FIFO, OBJTYPE_SOCKET, OBJTYPE_REGFILEUNIQUE, OBJTYPE_REGFILEMULTI}; enum {DISKITEMKEY_NULL=0, DISKITEMKEY_OBJECTID, DISKITEMKEY_PATH, DISKITEMKEY_OBJTYPE, DISKITEMKEY_SYMLINK, DISKITEMKEY_HARDLINK, DISKITEMKEY_RDEV, DISKITEMKEY_MODE, DISKITEMKEY_SIZE, DISKITEMKEY_UID, DISKITEMKEY_GID, DISKITEMKEY_ATIME, DISKITEMKEY_MTIME, DISKITEMKEY_MD5SUM, DISKITEMKEY_MULTIFILESCOUNT, DISKITEMKEY_MULTIFILESOFFSET, DISKITEMKEY_LINKTARGETTYPE, DISKITEMKEY_FLAGS}; enum {BLOCKHEADITEMKEY_NULL=0, BLOCKHEADITEMKEY_REALSIZE, BLOCKHEADITEMKEY_BLOCKOFFSET, BLOCKHEADITEMKEY_COMPRESSALGO, BLOCKHEADITEMKEY_ENCRYPTALGO, BLOCKHEADITEMKEY_ARSIZE, BLOCKHEADITEMKEY_COMPSIZE, BLOCKHEADITEMKEY_ARCSUM}; enum {BLOCKFOOTITEMKEY_NULL=0, BLOCKFOOTITEMKEY_MD5SUM}; enum {MAINHEADKEY_NULL=0, MAINHEADKEY_FILEFORMATVER, MAINHEADKEY_PROGVERCREAT, MAINHEADKEY_ARCHIVEID, MAINHEADKEY_CREATTIME, MAINHEADKEY_ARCHLABEL, MAINHEADKEY_ARCHTYPE, MAINHEADKEY_FSCOUNT, MAINHEADKEY_COMPRESSALGO, MAINHEADKEY_COMPRESSLEVEL, MAINHEADKEY_ENCRYPTALGO, MAINHEADKEY_BUFCHECKPASSCLEARMD5, MAINHEADKEY_BUFCHECKPASSCRYPTBUF, MAINHEADKEY_FSACOMPLEVEL, MAINHEADKEY_MINFSAVERSION, MAINHEADKEY_HASDIRSINFOHEAD}; enum {FSYSHEADKEY_NULL=0, FSYSHEADKEY_FILESYSTEM, FSYSHEADKEY_MNTPATH, FSYSHEADKEY_BYTESTOTAL, FSYSHEADKEY_BYTESUSED, FSYSHEADKEY_FSLABEL, FSYSHEADKEY_FSUUID, FSYSHEADKEY_FSINODESIZE, FSYSHEADKEY_FSVERSION, FSYSHEADKEY_FSEXTDEFMNTOPT, FSYSHEADKEY_FSEXTREVISION, FSYSHEADKEY_FSEXTBLOCKSIZE, FSYSHEADKEY_FSEXTFEATURECOMPAT, FSYSHEADKEY_FSEXTFEATUREINCOMPAT, FSYSHEADKEY_FSEXTFEATUREROCOMPAT, FSYSHEADKEY_FSREISERBLOCKSIZE, FSYSHEADKEY_FSREISER4BLOCKSIZE, FSYSHEADKEY_FSXFSBLOCKSIZE, FSYSHEADKEY_FSBTRFSSECTORSIZE, FSYSHEADKEY_NTFSSECTORSIZE, FSYSHEADKEY_NTFSCLUSTERSIZE, FSYSHEADKEY_BTRFSFEATURECOMPAT, FSYSHEADKEY_BTRFSFEATUREINCOMPAT, FSYSHEADKEY_BTRFSFEATUREROCOMPAT, FSYSHEADKEY_NTFSUUID, FSYSHEADKEY_MINFSAVERSION, FSYSHEADKEY_MOUNTINFO, FSYSHEADKEY_ORIGDEV, FSYSHEADKEY_TOTALCOST, FSYSHEADKEY_FSEXTFSCKMAXMNTCOUNT, FSYSHEADKEY_FSEXTFSCKCHECKINTERVAL, FSYSHEADKEY_FSEXTEOPTRAIDSTRIPEWIDTH, FSYSHEADKEY_FSEXTEOPTRAIDSTRIDE, FSYSHEADKEY_FSINODEBLOCKSPERGROUP, FSYSHEADKEY_FSXFSVERSION, FSYSHEADKEY_FSXFSFEATURECOMPAT, FSYSHEADKEY_FSXFSFEATUREROCOMPAT, FSYSHEADKEY_FSXFSFEATUREINCOMPAT, FSYSHEADKEY_FSXFSFEATURELOGINCOMPAT, FSYSHEADKEY_FSVFATTYPE, FSYSHEADKEY_FSVFATSERIAL}; enum {DIRSINFOKEY_NULL=0, DIRSINFOKEY_TOTALCOST}; // -------------------------------- fsarchiver errors --------------------------------------------- enum {FSAERR_SUCCESS=0, // success FSAERR_UNKNOWN=-1, // uknown error (default code that means error) FSAERR_ENOMEM=-2, // out of memory error FSAERR_EINVAL=-3, // invalid parameter FSAERR_ENOENT=-4, // entry not found FSAERR_ENDOFFILE=-5, // end of file/queue FSAERR_WRONGTYPE=-6, // wrong type of data FSAERR_NOTOPEN=-7, // resource has been closed FSAERR_ENOSPC=-8, // no space left on device FSAERR_SEEK=-9, // lseek64 error FSAERR_READ=-10, // read error FSAERR_WRITE=-11 // write error }; // -------------------------------- old errors codes --------------------------------------------- enum {OLDERR_FATAL=1, OLDERR_MINOR=2}; // ----------------------------- fsarchiver const ------------------------ #define FSA_VERSION PACKAGE_VERSION #define FSA_RELDATE PACKAGE_RELDATE #define FSA_FILEFORMAT PACKAGE_FILEFMT #define FSA_GCRYPT_VERSION "1.2.3" #define FSA_MAX_FILEFMTLEN 32 #define FSA_MAX_PROGVERLEN 32 #define FSA_MAX_FSNAMELEN 128 #define FSA_MAX_DEVLEN 256 #define FSA_MAX_UUIDLEN 128 #define FSA_MAX_BLKDEVICES 256 #define FSA_MAX_FSPERARCH 128 #define FSA_MAX_COMPJOBS 32 #define FSA_MAX_QUEUESIZE 32 #define FSA_MAX_BLKSIZE 921600 #define FSA_DEF_BLKSIZE 524288 #ifdef OPTION_ZSTD_SUPPORT #define FSA_DEF_COMPRESS_ALGO COMPRESS_ZSTD #define FSA_DEF_COMPRESS_LEVEL 8 #else #define FSA_DEF_COMPRESS_ALGO COMPRESS_GZIP #define FSA_DEF_COMPRESS_LEVEL 6 #endif #define FSA_DEF_FSACOMP_LEVEL 3 // legacy -z mapping for gzip level 6 #define FSA_MAX_SMALLFILECOUNT 512 // there can be up to FSA_MAX_SMALLFILECOUNT files copied in a single data block #define FSA_MAX_SMALLFILESIZE 131072 // files smaller than that will be grouped with other small files in a single data block #define FSA_COST_PER_FILE 16384 // how much it cost to copy an empty file/dir/link: used to eval the progress bar #define FSA_MAX_LABELLEN 512 #define FSA_MIN_PASSLEN 6 #define FSA_MAX_PASSLEN 64 #define FSA_FILESYSID_NULL 0xFFFF #define FSA_CHECKPASSBUF_SIZE 4096 #define FSA_FILEFLAGS_SPARSE 1<<0 // set when a regfile is a sparse file // ----------------------------- fsarchiver magics -------------------------------------------------- #define FSA_SIZEOF_MAGIC 4 #define FSA_MAGIC_VOLH "FsA0" // volume header (one per volume at the very beginning) #define FSA_MAGIC_VOLF "FsAE" // volume footer (one per volume at the very end) #define FSA_MAGIC_MAIN "ArCh" // archive header (one per archive at the beginning of the first volume) #define FSA_MAGIC_FSIN "FsIn" // filesys info (one per filesystem at the beginning of the archive) #define FSA_MAGIC_FSYB "FsYs" // filesys begin (one per filesystem when the filesys contents start) #define FSA_MAGIC_DIRS "DiRs" // dirs info (one per archive after mainhead before flat dirs/files) #define FSA_MAGIC_OBJT "ObJt" // object header (one per object: regfiles, dirs, symlinks, ...) #define FSA_MAGIC_BLKH "BlKh" // datablk header (one per data block, each regfile may have [0-n]) #define FSA_MAGIC_FILF "FiLf" // filedat footer (one per regfile, after the list of data blocks) #define FSA_MAGIC_DATF "DaEn" // data footer (one per file system, at the end of its contents, or after the contents of the flatfiles) // ------------ global variables --------------------------- extern char *valid_magic[]; // -------------------------------- version_number to u64 ------------------------------------------- #define FSA_VERSION_BUILD(a, b, c, d) ((u64)((((u64)a&0xFFFF)<<48)+(((u64)b&0xFFFF)<<32)+(((u64)c&0xFFFF)<<16)+(((u64)d&0xFFFF)<<0))) #define FSA_VERSION_GET_A(ver) ((((u64)ver)>>48)&0xFFFF) #define FSA_VERSION_GET_B(ver) ((((u64)ver)>>32)&0xFFFF) #define FSA_VERSION_GET_C(ver) ((((u64)ver)>>16)&0xFFFF) #define FSA_VERSION_GET_D(ver) ((((u64)ver)>>0)&0xFFFF) #endif // __FSARCHIVER_H__ fsarchiver-0.8.7/src/writebuf.h0000644000175000017500000000223714405605077013406 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifndef __WRITEBUF_H__ #define __WRITEBUF_H__ struct s_dico; struct s_blockinfo; struct s_writebuf; typedef struct s_writebuf cwritebuf; struct s_writebuf { char *data; u64 size; }; cwritebuf *writebuf_alloc(); int writebuf_destroy(cwritebuf *wb); int writebuf_add_data(cwritebuf *wb, void *data, u64 size); int writebuf_add_dico(cwritebuf *wb, struct s_dico *d, char *magic); int writebuf_add_header(cwritebuf *wb, struct s_dico *d, char *magic, u32 archid, u16 fsid); int writebuf_add_block(cwritebuf *wb, struct s_blockinfo *blkinfo, u32 archid, u16 fsid); #endif // __WRITEBUF_H__ fsarchiver-0.8.7/src/queue.c0000644000175000017500000005004314405605077012674 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include #include #include #include #include "fsarchiver.h" #include "queue.h" #include "dico.h" #include "common.h" #include "syncthread.h" #include "error.h" struct timespec get_timeout() { struct timespec t; clock_gettime(CLOCK_REALTIME, &t); t.tv_sec++; return t; } s64 queue_init(cqueue *q, s64 blkmax) { pthread_mutexattr_t attr; if (!q) { errprintf("q is NULL\n"); return FSAERR_EINVAL; } // ---- init default attributes q->head=NULL; q->curitemnum=1; q->itemcount=0; q->blkcount=0; q->blkmax=blkmax; q->endofqueue=false; // ---- init pthread structures assert(pthread_mutexattr_init(&attr)==0); assert(pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK)==0); if (pthread_mutex_init(&q->mutex, &attr)!=0) { msgprintf(3, "pthread_mutex_init failed\n"); return FSAERR_UNKNOWN; } if (pthread_cond_init(&q->cond,NULL)!=0) { msgprintf(3, "pthread_cond_init failed\n"); return FSAERR_UNKNOWN; } return FSAERR_SUCCESS; } s64 queue_destroy(cqueue *q) { cqueueitem *cur; cqueueitem *next; if (!q) { errprintf("q is NULL\n"); return FSAERR_EINVAL; } assert(pthread_mutex_lock(&q->mutex)==0); for (cur=q->head; cur!=NULL; cur=next) { next=cur->next; free(cur); } q->head=NULL; q->itemcount=0; assert(pthread_mutex_unlock(&q->mutex)==0); assert(pthread_mutex_destroy(&q->mutex)==0); assert(pthread_cond_destroy(&q->cond)==0); return FSAERR_SUCCESS; } s64 queue_set_end_of_queue(cqueue *q, bool state) { if (!q) { errprintf("q is NULL\n"); return FSAERR_EINVAL; } assert(pthread_mutex_lock(&q->mutex)==0); q->endofqueue=state; assert(pthread_mutex_unlock(&q->mutex)==0); pthread_cond_broadcast(&q->cond); return FSAERR_SUCCESS; } bool queue_get_end_of_queue(cqueue *q) { bool res; if (!q) { errprintf("q is NULL\n"); return FSAERR_EINVAL; } assert(pthread_mutex_lock(&q->mutex)==0); res=((q->itemcount<1) && (q->endofqueue==true)); assert(pthread_mutex_unlock(&q->mutex)==0); return res; } bool queuelocked_get_end_of_queue(cqueue *q) { bool res; if (!q) { errprintf("q is NULL\n"); return FSAERR_EINVAL; } res=((q->itemcount<1) && (q->endofqueue==true)); return res; } // runs with the mutex unlocked (external users) s64 queue_count(cqueue *q) { s64 itemcount; if (!q) { errprintf("q is NULL\n"); return FSAERR_EINVAL; } assert(pthread_mutex_lock(&q->mutex)==0); itemcount = q->itemcount; assert(pthread_mutex_unlock(&q->mutex)==0); return itemcount; } // how many items in the queue have a particular status s64 queue_count_status(cqueue *q, int status) { cqueueitem *cur; int count=0; if (!q) { errprintf("q is NULL\n"); return FSAERR_EINVAL; } assert(pthread_mutex_lock(&q->mutex)==0); for (cur=q->head; cur!=NULL; cur=cur->next) { if (status==QITEM_STATUS_NULL || cur->status==status) count++; } assert(pthread_mutex_unlock(&q->mutex)==0); return count; } // add a block at the end of the queue s64 queue_add_block(cqueue *q, cblockinfo *blkinfo, int status) { cqueueitem *item; cqueueitem *cur; if (!q || !blkinfo) { errprintf("a parameter is NULL\n"); return FSAERR_EINVAL; } // create the new item in memory item=malloc(sizeof(cqueueitem)); if (!item) { errprintf("malloc(%ld) failed: out of memory\n", (long)sizeof(cqueueitem)); return FSAERR_ENOMEM; } item->type=QITEM_TYPE_BLOCK; item->status=status; item->blkinfo=*blkinfo; item->next=NULL; assert(pthread_mutex_lock(&q->mutex)==0); // does not make sense to add item on a queue where endofqueue is true if (q->endofqueue==true) { free (item); assert(pthread_mutex_unlock(&q->mutex)==0); return FSAERR_ENDOFFILE; } // wait while (queue-is-full) to let the other threads remove items first while (q->blkcount > q->blkmax) { struct timespec t=get_timeout(); pthread_cond_timedwait(&q->cond, &q->mutex, &t); } if (q->head==NULL) // if list empty: item is head { q->head=item; } else // list not empty: add items at the end { for (cur=q->head; (cur!=NULL) && (cur->next!=NULL); cur=cur->next); cur->next=item; } q->blkcount++; q->itemcount++; item->itemnum=q->curitemnum++; assert(pthread_mutex_unlock(&q->mutex)==0); pthread_cond_broadcast(&q->cond); return FSAERR_SUCCESS; } s64 queue_add_header(cqueue *q, cdico *d, char *magic, u16 fsid) { cheadinfo headinfo; if (!q || !d || !magic) { errprintf("parameter is null\n"); return FSAERR_EINVAL; } memset(&headinfo, 0, sizeof(headinfo)); memcpy(headinfo.magic, magic, FSA_SIZEOF_MAGIC); headinfo.fsid=fsid; headinfo.dico=d; return queue_add_header_internal(q, &headinfo); } s64 queue_add_header_internal(cqueue *q, cheadinfo *headinfo) { cqueueitem *item; cqueueitem *cur; if (!q || !headinfo) { errprintf("parameter is null\n"); return FSAERR_EINVAL; } // create the new item in memory item=malloc(sizeof(cqueueitem)); if (!item) { errprintf("malloc(%ld) failed: out of memory 1\n", (long)sizeof(cqueueitem)); return FSAERR_ENOMEM; } item->headinfo=*headinfo; item->type=QITEM_TYPE_HEADER; item->status=QITEM_STATUS_DONE; item->next=NULL; assert(pthread_mutex_lock(&q->mutex)==0); // does not make sense to add item on a queue where endofqueue is true if (q->endofqueue==true) { free(item); assert(pthread_mutex_unlock(&q->mutex)==0); return FSAERR_ENDOFFILE; } // wait while (queue-is-full) to let the other threads remove items first while (q->blkcount > q->blkmax) { struct timespec t=get_timeout(); pthread_cond_timedwait(&q->cond, &q->mutex, &t); } item->itemnum=q->curitemnum++; if (q->head==NULL) // if list empty { q->head=item; } else // list not empty { for (cur=q->head; (cur!=NULL) && (cur->next!=NULL); cur=cur->next); cur->next=item; } q->itemcount++; assert(pthread_mutex_unlock(&q->mutex)==0); pthread_cond_broadcast(&q->cond); return FSAERR_SUCCESS; } // function called by the compression thread when a block has been compressed s64 queue_replace_block(cqueue *q, s64 itemnum, cblockinfo *blkinfo, int newstatus) { cqueueitem *cur; if (!q || !blkinfo) { errprintf("a parameter is null\n"); return FSAERR_EINVAL; } assert(pthread_mutex_lock(&q->mutex)==0); if (q->head==NULL) { assert(pthread_mutex_unlock(&q->mutex)==0); msgprintf(MSG_DEBUG1, "q->head is NULL: list is empty\n"); return FSAERR_ENOENT; // item not found } for (cur=q->head; cur!=NULL; cur=cur->next) { if (cur->itemnum==itemnum) // block found { cur->status=newstatus; cur->blkinfo=*blkinfo; assert(pthread_mutex_unlock(&q->mutex)==0); pthread_cond_broadcast(&q->cond); return FSAERR_SUCCESS; } } assert(pthread_mutex_unlock(&q->mutex)==0); return FSAERR_ENOENT; // not found } // get number of items to be processed s64 queue_count_items_todo(cqueue *q) { cqueueitem *cur; s64 count=0; if (!q) { errprintf("a parameter is null\n"); return FSAERR_EINVAL; } assert(pthread_mutex_lock(&q->mutex)==0); for (cur=q->head; cur!=NULL; cur=cur->next) { if ((cur->type==QITEM_TYPE_BLOCK) && (cur->status!=QITEM_STATUS_DONE)) count++; } assert(pthread_mutex_unlock(&q->mutex)==0); return count; } // the compression thread requires the first block which has not yet been compressed s64 queue_get_first_block_todo(cqueue *q, cblockinfo *blkinfo) { cqueueitem *cur; s64 itemfound=-1; int res; if (!q || !blkinfo) { errprintf("a parameter is null\n"); return FSAERR_EINVAL; } assert(pthread_mutex_lock(&q->mutex)==0); while (queuelocked_get_end_of_queue(q)==false) { for (cur=q->head; cur!=NULL; cur=cur->next) { if ((cur->type==QITEM_TYPE_BLOCK) && (cur->status==QITEM_STATUS_TODO)) { *blkinfo=cur->blkinfo; cur->status=QITEM_STATUS_PROGRESS; itemfound=cur->itemnum; assert(pthread_mutex_unlock(&q->mutex)==0); pthread_cond_broadcast(&q->cond); return itemfound; // ">0" means item found } } struct timespec t=get_timeout(); if ((res=pthread_cond_timedwait(&q->cond, &q->mutex, &t))!=0 && res!=ETIMEDOUT) { assert(pthread_mutex_unlock(&q->mutex)==0); return FSAERR_UNKNOWN; } } // if it failed at the other end of the queue assert(pthread_mutex_unlock(&q->mutex)==0); if (queuelocked_get_end_of_queue(q)) return FSAERR_ENDOFFILE; else return FSAERR_UNKNOWN; } // the writer thread requires the first block of the queue if it ready to go //s64 queue_dequeue_first(cqueue *q, int *type, char *magic, cdico **dico, cblockinfo *blkinfo) s64 queue_dequeue_first(cqueue *q, int *type, cheadinfo *headinfo, cblockinfo *blkinfo) { cqueueitem *cur=NULL; s64 itemfound=-1; int ret; if (!q || !headinfo || !blkinfo) { errprintf("a parameter is null\n"); return FSAERR_EINVAL; } assert(pthread_mutex_lock(&q->mutex)==0); while (queuelocked_get_end_of_queue(q)==false) { if (((cur=q->head)!=NULL) && (cur->status==QITEM_STATUS_DONE)) { if (cur->type==QITEM_TYPE_BLOCK) // item to dequeue is a block { q->blkcount--; *type=cur->type; itemfound=cur->itemnum; *blkinfo=cur->blkinfo; q->head=cur->next; free(cur); q->itemcount--; assert(pthread_mutex_unlock(&q->mutex)==0); pthread_cond_broadcast(&q->cond); return itemfound; // ">0" means item found } else if (cur->type==QITEM_TYPE_HEADER) // item to dequeue is a dico { *headinfo=cur->headinfo; *type=cur->type; itemfound=cur->itemnum; q->head=cur->next; free(cur); q->itemcount--; assert(pthread_mutex_unlock(&q->mutex)==0); pthread_cond_broadcast(&q->cond); return itemfound; // ">0" means item found } else { errprintf("invalid item type in queue\n"); assert(pthread_mutex_unlock(&q->mutex)==0); return FSAERR_EINVAL; } } struct timespec t=get_timeout(); pthread_cond_timedwait(&q->cond, &q->mutex, &t); } // if it failed at the other end of the queue ret=(queuelocked_get_end_of_queue(q)==true)?FSAERR_ENDOFFILE:FSAERR_UNKNOWN; assert(pthread_mutex_unlock(&q->mutex)==0); return ret; } // the extract function wants to read headers from the queue s64 queue_dequeue_block(cqueue *q, cblockinfo *blkinfo) { cqueueitem *cur; s64 itemnum; if (!q || !blkinfo) { errprintf("a parameter is null\n"); return FSAERR_EINVAL; } assert(pthread_mutex_lock(&q->mutex)==0); // while ((first-item-of-the-queue-is-not-ready) && (not-at-the-end-of-the-queue)) while ( (((cur=q->head)==NULL) || (cur->status!=QITEM_STATUS_DONE)) && (queuelocked_get_end_of_queue(q)==false) ) { struct timespec t=get_timeout(); pthread_cond_timedwait(&q->cond, &q->mutex, &t); } // if it failed at the other end of the queue if (queuelocked_get_end_of_queue(q)) { assert(pthread_mutex_unlock(&q->mutex)==0); return FSAERR_ENDOFFILE; } cur=q->head; assert(cur!=NULL); // queuelocked_is_first_block_ready means there is at least one block in the queue // test the first item if ((cur->type==QITEM_TYPE_BLOCK) && (cur->status==QITEM_STATUS_DONE)) { *blkinfo=cur->blkinfo; q->head=cur->next; itemnum=cur->itemnum; free(cur); q->blkcount--; q->itemcount--; assert(pthread_mutex_unlock(&q->mutex)==0); pthread_cond_broadcast(&q->cond); return itemnum; } else { errprintf("dequeue - wrong type of data in the queue: wanted a block, found an header\n"); assert(pthread_mutex_unlock(&q->mutex)==0); pthread_cond_broadcast(&q->cond); return FSAERR_WRONGTYPE; // ok but not found } } s64 queue_dequeue_header(cqueue *q, cdico **d, char *magicbuf, u16 *fsid) { cheadinfo headinfo; s64 lres; if (!q || !d || !magicbuf) { errprintf("a parameter is null\n"); return FSAERR_EINVAL; } if ((lres=queue_dequeue_header_internal(q, &headinfo))<=0) { msgprintf(MSG_STACK, "queue_dequeue_header_internal() failed\n"); return lres; } memcpy(magicbuf, headinfo.magic, FSA_SIZEOF_MAGIC); *d=headinfo.dico; if (fsid!=NULL) *fsid=headinfo.fsid; return lres; } s64 queue_dequeue_header_internal(cqueue *q, cheadinfo *headinfo) { cqueueitem *cur; s64 itemnum; if (!q || !headinfo) { errprintf("a parameter is null\n"); return FSAERR_EINVAL; } assert(pthread_mutex_lock(&q->mutex)==0); // while ((first-item-of-the-queue-is-not-ready) && (not-at-the-end-of-the-queue)) while ( (((cur=q->head)==NULL) || (cur->status!=QITEM_STATUS_DONE)) && (queuelocked_get_end_of_queue(q)==false) ) { struct timespec t=get_timeout(); pthread_cond_timedwait(&q->cond, &q->mutex, &t); } // if it failed at the other end of the queue if (queuelocked_get_end_of_queue(q)) { assert(pthread_mutex_unlock(&q->mutex)==0); return FSAERR_ENDOFFILE; } cur=q->head; assert (cur!=NULL); // queuelocked_is_first_block_ready means there is at least one block in the queue // test the first item switch (cur->type) { case QITEM_TYPE_HEADER: q->head=cur->next; *headinfo=cur->headinfo; itemnum=cur->itemnum; free(cur); q->itemcount--; assert(pthread_mutex_unlock(&q->mutex)==0); pthread_cond_broadcast(&q->cond); return itemnum; case QITEM_TYPE_BLOCK: errprintf("dequeue - wrong type of data in the queue: expected a dico and found a block\n"); assert(pthread_mutex_unlock(&q->mutex)==0); pthread_cond_broadcast(&q->cond); return FSAERR_WRONGTYPE; // ok but not found default: // should never happen errprintf("dequeue - wrong type of data in the queue: expected a dico and found an unknown item\n"); assert(pthread_mutex_unlock(&q->mutex)==0); pthread_cond_broadcast(&q->cond); return FSAERR_WRONGTYPE; // ok but not found } } // returns true if the first item in queue is a dico or a block which is ready bool queuelocked_is_first_item_ready(cqueue *q) { cqueueitem *cur; if (!q) { errprintf("a parameter is null\n"); return false; // not found } if ((cur=q->head)==NULL) return false; // list empty else if (cur->type==QITEM_TYPE_HEADER) return true; // a dico is always ready else if ((cur->type==QITEM_TYPE_BLOCK) && (cur->status==QITEM_STATUS_DONE)) return true; // a block which has been prepared is ready else // other cases: block not yet prepared return false; } // say what the next item which is ready in the queue is but do not remove it s64 queue_check_next_item(cqueue *q, int *type, char *magic) { cqueueitem *cur; if (!q || !type || !magic) { errprintf("a parameter is null\n"); return FSAERR_EINVAL; } memset(magic, 0, FSA_SIZEOF_MAGIC); *type=0; assert(pthread_mutex_lock(&q->mutex)==0); // while ((first-item-of-the-queue-is-not-ready) && (not-at-the-end-of-the-queue)) while ( (((cur=q->head)==NULL) || (cur->status!=QITEM_STATUS_DONE)) && (queuelocked_get_end_of_queue(q)==false) ) { struct timespec t=get_timeout(); pthread_cond_timedwait(&q->cond, &q->mutex, &t); } // if it failed at the other end of the queue if (queuelocked_get_end_of_queue(q)) { assert(pthread_mutex_unlock(&q->mutex)==0); return FSAERR_ENDOFFILE; } // test the first item if (((cur=q->head)!=NULL) && (cur->status==QITEM_STATUS_DONE)) { if (cur->type==QITEM_TYPE_BLOCK) // item to dequeue is a block { *type=cur->type; memset(magic, 0, FSA_SIZEOF_MAGIC); assert(pthread_mutex_unlock(&q->mutex)==0); return FSAERR_SUCCESS; } else if (cur->type==QITEM_TYPE_HEADER) // item to dequeue is a dico { memcpy(magic, cur->headinfo.magic, FSA_SIZEOF_MAGIC); // header contents *type=cur->type; assert(pthread_mutex_unlock(&q->mutex)==0); return FSAERR_SUCCESS; } else { errprintf("invalid item type in queue: type=%d\n", cur->type); assert(pthread_mutex_unlock(&q->mutex)==0); return FSAERR_EINVAL; } } assert(pthread_mutex_unlock(&q->mutex)==0); pthread_cond_broadcast(&q->cond); return FSAERR_ENOENT; // not found } // destroy the first item in the queue (similar to dequeue but do not read it) s64 queue_destroy_first_item(cqueue *q) { cqueueitem *cur; if (!q) { errprintf("a parameter is null\n"); return FSAERR_EINVAL; } assert(pthread_mutex_lock(&q->mutex)==0); // while ((first-item-of-the-queue-is-not-ready or first-item-is-being-processed-by-comp-thread) && (not-at-the-end-of-the-queue)) while ( (((cur=q->head)==NULL) || (cur->status==QITEM_STATUS_PROGRESS)) && (queuelocked_get_end_of_queue(q)==false) ) { struct timespec t=get_timeout(); pthread_cond_timedwait(&q->cond, &q->mutex, &t); } // if it failed at the other end of the queue if (queuelocked_get_end_of_queue(q)) { assert(pthread_mutex_unlock(&q->mutex)==0); return FSAERR_ENDOFFILE; } cur=q->head; assert(cur!=NULL); // queuelocked_is_first_block_ready means there is at least one block in the queue switch (cur->type) { case QITEM_TYPE_BLOCK: q->blkcount--; free(cur->blkinfo.blkdata); break; case QITEM_TYPE_HEADER: dico_destroy(cur->headinfo.dico); break; } q->head=cur->next; free(cur); q->itemcount--; assert(pthread_mutex_unlock(&q->mutex)==0); pthread_cond_broadcast(&q->cond); return FSAERR_SUCCESS; } fsarchiver-0.8.7/src/comp_gzip.h0000644000175000017500000000156114405605077013545 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifndef __COMPRESS_GZIP_H__ #define __COMPRESS_GZIP_H__ int compress_block_gzip(u64 origsize, u64 *compsize, u8 *origbuf, u8 *compbuf, u64 compbufsize, int level); int uncompress_block_gzip(u64 compsize, u64 *origsize, u8 *origbuf, u64 origbufsize, u8 *compbuf); #endif // __COMPRESS_GZIP_H__ fsarchiver-0.8.7/src/comp_zstd.h0000644000175000017500000000170014405605077013553 00000000000000 /* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifndef __COMPRESS_ZSTD_H__ #define __COMPRESS_ZSTD_H__ #ifdef OPTION_ZSTD_SUPPORT #include int compress_block_zstd(u64 origsize, u64 *compsize, u8 *origbuf, u8 *compbuf, u64 compbufsize, int level); int uncompress_block_zstd(u64 compsize, u64 *origsize, u8 *origbuf, u64 origbufsize, u8 *compbuf); #endif // OPTION_ZSTD_SUPPORT #endif // __COMPRESS_ZSTD_H__ fsarchiver-0.8.7/src/fsarchiver.c0000644000175000017500000005164314405605077013713 00000000000000/* * fsarchiver: Filesystem Archiver * * Copyright (C) 2008-2018 Francois Dupoux. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * 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. * * Homepage: http://www.fsarchiver.org */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include #include "fsarchiver.h" #include "dico.h" #include "common.h" #include "oper_restore.h" #include "oper_save.h" #include "oper_probe.h" #include "archinfo.h" #include "syncthread.h" #include "comp_lzo.h" #include "comp_lz4.h" #include "crypto.h" #include "options.h" #include "logfile.h" #include "error.h" #include "queue.h" char *valid_magic[]={FSA_MAGIC_MAIN, FSA_MAGIC_VOLH, FSA_MAGIC_VOLF, FSA_MAGIC_FSIN, FSA_MAGIC_FSYB, FSA_MAGIC_DATF, FSA_MAGIC_OBJT, FSA_MAGIC_BLKH, FSA_MAGIC_FILF, FSA_MAGIC_DIRS, NULL}; void usage(char *progname, bool examples) { int lzo, lzma, lz4, zstd; #ifdef OPTION_LZO_SUPPORT lzo=true; #else lzo=false; #endif // OPTION_LZO_SUPPORT #ifdef OPTION_LZMA_SUPPORT lzma=true; #else lzma=false; #endif // OPTION_LZMA_SUPPORT #ifdef OPTION_LZ4_SUPPORT lz4=true; #else lz4=false; #endif // OPTION_lZ4_SUPPORT #ifdef OPTION_ZSTD_SUPPORT zstd=true; #else zstd=false; #endif // OPTION_ZSTD_SUPPORT msgprintf(MSG_FORCE, "====> fsarchiver version %s (%s) - http://www.fsarchiver.org <====\n", FSA_VERSION, FSA_RELDATE); msgprintf(MSG_FORCE, "Distributed under the GPL v2 license (GNU General Public License v2).\n"); msgprintf(MSG_FORCE, " * usage: %s [] [ [ [...]]]\n", progname); msgprintf(MSG_FORCE, "\n"); msgprintf(MSG_FORCE, " * savefs: save filesystems to an archive file (backup a device to a file)\n"); msgprintf(MSG_FORCE, " * restfs: restore filesystems from an archive (overwrites the existing data)\n"); msgprintf(MSG_FORCE, " * savedir: save directories to the archive (similar to a compressed tarball)\n"); msgprintf(MSG_FORCE, " * restdir: restore data from an archive which is not based on a filesystem\n"); msgprintf(MSG_FORCE, " * archinfo: show information about an existing archive file and its contents\n"); msgprintf(MSG_FORCE, " * probe [detailed]: show list of filesystems detected on the disks\n"); msgprintf(MSG_FORCE, "\n"); msgprintf(MSG_FORCE, " -o: overwrite the archive if it already exists instead of failing\n"); msgprintf(MSG_FORCE, " -v: verbose mode (can be used several times to increase the level of details)\n"); msgprintf(MSG_FORCE, " -d: debug mode (can be used several times to increase the level of details)\n"); msgprintf(MSG_FORCE, " -A: allow to save a filesystem which is mounted in read-write (live backup)\n"); msgprintf(MSG_FORCE, " -a: allow to save a filesystem when acls and xattrs are not supported\n"); msgprintf(MSG_FORCE, " -x: enable support for experimental features (they are disabled by default)\n"); msgprintf(MSG_FORCE, " -e : exclude files and directories that match that pattern\n"); msgprintf(MSG_FORCE, " -L