dar-2.7.15/ 0000755 0001750 0001750 00000000000 14640025216 007355 5 0000000 0000000 dar-2.7.15/depcomp 0000755 0001750 0001750 00000056020 14215102164 010651 0000000 0000000 #! /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:
dar-2.7.15/src/ 0000755 0001750 0001750 00000000000 14640025216 010144 5 0000000 0000000 dar-2.7.15/src/libdar/ 0000755 0001750 0001750 00000000000 14640025215 011400 5 0000000 0000000 dar-2.7.15/src/libdar/cat_etoile.hpp 0000644 0001750 0001750 00000007776 14636066467 014205 0000000 0000000 /*********************************************************************/
// dar - disk archive - a backup/restoration program
// Copyright (C) 2002-2024 Denis Corbin
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// to contact the author, see the AUTHOR file
/*********************************************************************/
/// \file cat_etoile.hpp
/// \brief class holding an cat_inode object that get pointed by multiple mirage objects (smart pointers) to record hard links in a catalogue
/// \ingroup Private
#ifndef CAT_ETOILE_HPP
#define CAT_ETOILE_HPP
#include "../my_config.h"
extern "C"
{
} // end extern "C"
#include
#include "cat_inode.hpp"
namespace libdar
{
/// \addtogroup Private
/// @{
/// the hard link implementation
/// etoile means star in French. See a star as a point from which are thrown many ray of light
class cat_etoile
{
public:
/// build an object
///\param[in] host is an inode, it must not be a directory (this would throw an Erange exception)
///\param[in] etiquette_number is the identifier of this multiply linked structure
///\note the given cat_inode is now managed by the cat_etoile object
cat_etoile(cat_inode *host, const infinint & etiquette_number);
cat_etoile(const cat_etoile & ref) = delete; // copy constructor not allowed for this class
cat_etoile(cat_etoile && ref) = delete;
cat_etoile & operator = (const cat_etoile & ref) = delete; // assignment not allowed for this class
cat_etoile & operator = (cat_etoile && ref) = delete;
~cat_etoile() { delete hosted; };
void add_ref(void *ref);
void drop_ref(void *ref);
infinint get_ref_count() const { return refs.size(); };
cat_inode *get_inode() const { return hosted; };
infinint get_etiquette() const { return etiquette; };
void change_etiquette(const infinint & new_val) { etiquette = new_val; };
void disable_reduction_to_normal_inode() { tags.reduceable = 0; };
bool cannot_reduce_to_normal_inode() const { return tags.reduceable == 0; };
bool is_counted() const { return tags.counted; };
bool is_wrote() const { return tags.wrote; };
bool is_dumped() const { return tags.dumped; };
void set_counted(bool val) { tags.counted = val ? 1 : 0; };
void set_wrote(bool val) { tags.wrote = val ? 1 : 0; };
void set_dumped(bool val) { tags.dumped = val ? 1 : 0; };
// return the address of the first mirage that triggered the creation of this mirage
// if this object is destroyed afterward this call returns nullptr
const void *get_first_ref() const { if(refs.size() == 0) throw SRC_BUG; return refs.front(); };
private:
/// bitfield used to record pointed to inode information
struct bool_tags
{
unsigned counted : 1; ///< whether the inode has been counted
unsigned wrote : 1; ///< whether the inode has its data copied to archive
unsigned dumped : 1; ///< whether the inode information has been dumped in the catalogue
unsigned reduceable : 1; ///< whether the inode can be reduce to normal inode
unsigned : 4; ///< padding to get byte boundary and reserved for future use.
bool_tags() { counted = wrote = dumped = 0; reduceable = 1; };
};
std::list refs; ///< list of pointers to the mirages objects, in the order of their creation
cat_inode *hosted;
infinint etiquette;
bool_tags tags;
};
/// @}
} // end of namespace
#endif
dar-2.7.15/src/libdar/op_tools.cpp 0000644 0001750 0001750 00000026753 14636066467 013722 0000000 0000000 /*********************************************************************/
// dar - disk archive - a backup/restoration program
// Copyright (C) 2002-2024 Denis Corbin
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// to contact the author, see the AUTHOR file
/*********************************************************************/
#include "../my_config.h"
#include "op_tools.hpp"
#include "nls_swap.hpp"
#include "tools.hpp"
#include "cat_all_entrees.hpp"
using namespace std;
namespace libdar
{
over_action_data op_tools_crit_ask_user_for_data_action(user_interaction & dialog, const string & full_name, const cat_entree *already_here, const cat_entree *dolly)
{
over_action_data ret = data_undefined;
NLS_SWAP_IN;
try
{
const string confirm = gettext("yes");
bool loop = true;
string resp;
while(loop)
{
dialog.printf(gettext("Conflict found while selecting the file to retain in the resulting archive:"));
dialog.printf(gettext("User Decision requested for data of file %S"), &full_name);
op_tools_crit_show_entry_info(dialog, full_name, already_here, dolly);
resp = dialog.get_string(gettext("\nYour decision about file's data:\n[P]reserve\n[O]verwrite\nmark [S]aved and preserve\nmark saved and overwri[T]e\n[R]emove\n[*] keep undefined\n[A]bort\n Your Choice? "), true);
if(resp.size() != 1)
dialog.message(gettext("Please answer by the character between brackets ('[' and ']') and press return"));
else
{
switch(*resp.begin())
{
case 'P':
ret = data_preserve;
loop = false;
break;
case 'O':
ret = data_overwrite;
loop = false;
break;
case 'S':
ret = data_preserve_mark_already_saved;
loop = false;
break;
case 'T':
ret = data_overwrite_mark_already_saved;
loop = false;
break;
case 'R':
ret = data_remove;
loop = false;
break;
case '*':
ret = data_undefined;
loop = false;
break;
case 'A':
resp = dialog.get_string(tools_printf(gettext("Warning, are you sure you want to abort (please answer \"%S\" to confirm)? "), &confirm), true);
if(resp == confirm)
throw Ethread_cancel(false, 0);
else
dialog.message(gettext("Cancellation no confirmed"));
break;
default:
dialog.message(string(gettext("Unknown choice: ")) + resp);
}
}
}
}
catch(...)
{
NLS_SWAP_OUT;
throw;
}
NLS_SWAP_OUT;
return ret;
}
over_action_ea op_tools_crit_ask_user_for_EA_action(user_interaction & dialog, const string & full_name, const cat_entree *already_here, const cat_entree *dolly)
{
over_action_ea ret = EA_undefined;
NLS_SWAP_IN;
try
{
const string confirm = gettext("yes");
bool loop = true;
string resp;
while(loop)
{
dialog.printf(gettext("Conflict found while selecting the file to retain in the resulting archive:"));
dialog.printf(gettext("User Decision requested for EA of file %S"), &full_name);
op_tools_crit_show_entry_info(dialog, full_name, already_here, dolly);
resp = dialog.get_string(gettext("\nYour decision about file's EA:\n[p]reserve\n[o]verwrite\nmark [s]aved and preserve\nmark saved and overwri[t]e\n[m]erge EA and preserve\nmerge EA a[n]d overwrite\n[r]emove\n[*] keep undefined\n[a]bort\n Your choice? "), true);
if(resp.size() != 1)
dialog.message(gettext("Please answer by the character between brackets ('[' and ']') and press return"));
else
{
switch(*resp.begin())
{
case 'p':
ret = EA_preserve;
loop = false;
break;
case 'o':
ret = EA_overwrite;
loop = false;
break;
case 's':
ret = EA_preserve_mark_already_saved;
loop = false;
break;
case 't':
ret = EA_overwrite_mark_already_saved;
loop = false;
break;
case 'm':
ret = EA_merge_preserve;
loop = false;
break;
case 'n':
ret = EA_merge_overwrite;
loop = false;
break;
case 'r':
ret = EA_clear;
loop = false;
break;
case '*':
ret = EA_undefined;
loop = false;
break;
case 'a':
resp = dialog.get_string(tools_printf(gettext("Warning, are you sure you want to abort (please answer \"%S\" to confirm)? "), &confirm), true);
if(resp == confirm)
throw Ethread_cancel(false, 0);
else
dialog.message(gettext("Cancellation no confirmed"));
break;
default:
dialog.message(string(gettext("Unknown choice: ")) + resp);
}
}
}
}
catch(...)
{
NLS_SWAP_OUT;
throw;
}
NLS_SWAP_OUT;
return ret;
}
over_action_ea op_tools_crit_ask_user_for_FSA_action(user_interaction & dialog, const string & full_name, const cat_entree *already_here, const cat_entree *dolly)
{
over_action_ea ret = EA_undefined;
NLS_SWAP_IN;
try
{
const string confirm = gettext("yes");
bool loop = true;
string resp;
while(loop)
{
dialog.printf(gettext("Conflict found while selecting the file to retain in the resulting archive:"));
dialog.printf(gettext("User Decision requested for FSA of file %S"), &full_name);
op_tools_crit_show_entry_info(dialog, full_name, already_here, dolly);
resp = dialog.get_string(gettext("\nYour decision about file's FSA:\n[p]reserve\n[o]verwrite\nmark [s]aved and preserve\nmark saved and overwri[t]e\n[*] keep undefined\n[a]bort\n Your choice? "), true);
if(resp.size() != 1)
dialog.message(gettext("Please answer by the character between brackets ('[' and ']') and press return"));
else
{
switch(*resp.begin())
{
case 'p':
ret = EA_preserve;
loop = false;
break;
case 'o':
ret = EA_overwrite;
loop = false;
break;
case 's':
ret = EA_preserve_mark_already_saved;
loop = false;
break;
case 't':
ret = EA_overwrite_mark_already_saved;
loop = false;
break;
case '*':
ret = EA_undefined;
loop = false;
break;
case 'a':
resp = dialog.get_string(tools_printf(gettext("Warning, are you sure you want to abort (please answer \"%S\" to confirm)? "), &confirm), true);
if(resp == confirm)
throw Ethread_cancel(false, 0);
else
dialog.message(gettext("Cancellation no confirmed"));
break;
default:
dialog.message(string(gettext("Unknown choice: ")) + resp);
}
}
}
}
catch(...)
{
NLS_SWAP_OUT;
throw;
}
NLS_SWAP_OUT;
return ret;
}
void op_tools_crit_show_entry_info(user_interaction & dialog, const string & full_name, const cat_entree *already_here, const cat_entree *dolly)
{
NLS_SWAP_IN;
try
{
const string yes = gettext("YES");
const string no = gettext("NO");
const cat_inode * al_inode = dynamic_cast(already_here);
const cat_directory * al_directory = dynamic_cast(already_here);
const cat_file * al_file = dynamic_cast(already_here);
const cat_mirage * al_mirage = dynamic_cast(already_here);
const cat_inode * do_inode = dynamic_cast(dolly);
const cat_directory * do_directory = dynamic_cast(dolly);
const cat_file * do_file = dynamic_cast(dolly);
const cat_mirage * do_mirage = dynamic_cast(dolly);
dialog.printf(gettext("Entry information:\t\"in place\"\t\"to be added\""));
dialog.printf(gettext("Is inode :\t %S \t\t %S"), al_inode == nullptr ? &no : &yes , do_inode == nullptr ? &no : &yes);
dialog.printf(gettext("Is directory :\t %S \t\t %S"), al_directory == nullptr ? &no : &yes , do_directory == nullptr ? &no : &yes);
dialog.printf(gettext("Is plain file :\t %S \t\t %S"), al_file == nullptr ? &no : &yes , do_file == nullptr ? &no : &yes);
dialog.printf(gettext("Is hard linked :\t %S \t\t %S"), al_mirage == nullptr ? &no : &yes , do_mirage == nullptr ? &no : &yes);
dialog.printf(gettext("Entry type :\t %s \t %s"),
cat_entree_signature2string(already_here->signature()),
cat_entree_signature2string(dolly->signature()));
if(al_inode != nullptr && do_inode != nullptr)
{
const string me = gettext("me");
const string notme = "";
bool in_place_data_recent = al_inode->get_last_modif() >= do_inode->get_last_modif();
bool in_place_ea_recent = al_inode->get_last_change() >= do_inode->get_last_change();
bool al_ea_saved = al_inode->ea_get_saved_status() == ea_saved_status::full;
bool do_ea_saved = do_inode->ea_get_saved_status() == ea_saved_status::full;
bool al_fsa_saved = al_inode->fsa_get_saved_status() == fsa_saved_status::full;
bool do_fsa_saved = do_inode->fsa_get_saved_status() == fsa_saved_status::full;
dialog.printf(gettext("Data more recent :\t %S \t\t %S"), in_place_data_recent ? &me : ¬me , in_place_data_recent ? ¬me : &me);
if(al_file != nullptr && do_file != nullptr)
{
infinint al_size = al_file->get_size();
infinint do_size = do_file->get_size();
bool al_dirty = al_file->is_dirty();
bool do_dirty = do_file->is_dirty();
bool al_sparse = al_file->get_sparse_file_detection_read();
bool do_sparse = do_file->get_sparse_file_detection_read();
dialog.printf(gettext("Data size :\t %i \t\t %i"), &al_size, &do_size);
dialog.printf(gettext("Sparse file :\t %S \t\t %S"), al_sparse ? &yes : &no, do_sparse ? &yes : &no);
dialog.printf(gettext("Dirty file :\t %S \t\t %S"), al_dirty ? &yes : &no, do_dirty ? &yes : &no);
}
dialog.printf(gettext("Data full saved :\t %S \t\t %S"),al_inode->get_saved_status() == saved_status::saved ? &yes:&no , do_inode->get_saved_status() == saved_status::saved ? &yes:&no);
dialog.printf(gettext("EA full saved :\t %S \t\t %S"),al_ea_saved ? &yes:&no , do_ea_saved ? &yes:&no);
if(al_ea_saved || do_ea_saved)
dialog.printf(gettext("EA more recent :\t %S \t\t %S"),in_place_ea_recent ? &me : ¬me , in_place_data_recent ? ¬me : &me);
dialog.printf(gettext("FSA full saved :\t %S \t\t %S"), al_fsa_saved ? &yes:&no , do_fsa_saved ? &yes:&no);
if(al_fsa_saved || do_fsa_saved)
{
string al_fam = al_fsa_saved ? fsa_scope_to_string(al_fsa_saved, al_inode->fsa_get_families()) : "-";
string do_fam = do_fsa_saved ? fsa_scope_to_string(do_fsa_saved, do_inode->fsa_get_families()) : "-";
dialog.printf(gettext("FSA familly :\t %S \t\t %S"), &al_fam, &do_fam);
}
if(al_ea_saved && do_ea_saved)
{
const ea_attributs *al_ea = al_inode->get_ea();
const ea_attributs *do_ea = do_inode->get_ea();
infinint al_tmp = al_ea->size();
infinint do_tmp = do_ea->size();
dialog.printf(gettext("EA number :\t %i \t\t %i"), &al_tmp, &do_tmp);
al_tmp = al_ea->space_used();
do_tmp = do_ea->space_used();
dialog.printf(gettext("EA size :\t %i \t\t %i"), &al_tmp, &do_tmp);
}
}
}
catch(...)
{
NLS_SWAP_OUT;
throw;
}
NLS_SWAP_OUT;
}
} // end of namespace
dar-2.7.15/src/libdar/cat_detruit.hpp 0000644 0001750 0001750 00000005723 14636066467 014372 0000000 0000000 /*********************************************************************/
// dar - disk archive - a backup/restoration program
// Copyright (C) 2002-2024 Denis Corbin
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// to contact the author, see the AUTHOR file
/*********************************************************************/
/// \file cat_detruit.hpp
/// \brief used to record information in a catalogue about a deleted file (differential backup context)
/// \ingroup Private
#ifndef CAT_DETRUIT_HPP
#define CAT_DETRUIT_HPP
#include "../my_config.h"
extern "C"
{
} // end extern "C"
#include "cat_nomme.hpp"
#include "datetime.hpp"
#include "archive_version.hpp"
namespace libdar
{
/// \addtogroup Private
/// @{
/// the deleted file entry
class cat_detruit : public cat_nomme
{
public :
cat_detruit(const std::string & name, unsigned char firm, const datetime & date) : cat_nomme(name, saved_status::saved) , del_date(date) { signe = firm; };
cat_detruit(const smart_pointer & pdesc, const archive_version & reading_ver, bool small);
cat_detruit(const cat_nomme & ref): cat_nomme(ref), del_date(0) { signe = ref.signature(); };
cat_detruit(const cat_detruit & ref) = default;
cat_detruit(cat_detruit && ref) noexcept = default;
cat_detruit & operator = (const cat_detruit & ref) = default;
cat_detruit & operator = (cat_detruit && ref) = default;
~cat_detruit() = default;
virtual bool operator == (const cat_entree & ref) const override;
unsigned char get_signature() const { return signe; };
void set_signature(unsigned char x) { signe = x; };
const datetime & get_date() const { return del_date; };
void set_date(const datetime & ref) { del_date = ref; };
/// inherited from cat_entree
virtual unsigned char signature() const override { return 'x'; };
/// inherited from cat_entree
virtual std::string get_description() const override { return "deleted file"; };
/// inherited from cat_entree
virtual cat_entree *clone() const override { return new (std::nothrow) cat_detruit(*this); };
protected:
virtual void inherited_dump(const pile_descriptor & pdesc, bool small) const override;
private :
unsigned char signe;
datetime del_date;
};
/// @}
} // end of namespace
#endif
dar-2.7.15/src/libdar/erreurs_ext.cpp 0000644 0001750 0001750 00000004014 14636066467 014415 0000000 0000000 /*********************************************************************/
// dar - disk archive - a backup/restoration program
// Copyright (C) 2002-2024 Denis Corbin
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// to contact the author, see the AUTHOR file
/*********************************************************************/
#include "../my_config.h"
#include "erreurs_ext.hpp"
using namespace std;
namespace libdar
{
Ethread_cancel_with_attr::Ethread_cancel_with_attr(bool now,
U_64 x_flag,
const infinint & attr) : Ethread_cancel(now, x_flag)
{
x_attr = new (nothrow) infinint(attr);
if(x_attr == nullptr)
throw Ememory("Ethread_cancel_with_attr::Ethread_cancel_with_attr");
}
Ethread_cancel_with_attr & Ethread_cancel_with_attr::operator = (Ethread_cancel_with_attr && ref) noexcept
{
Ethread_cancel::operator = (move(ref));
swap(x_attr, ref.x_attr);
return *this;
}
void Ethread_cancel_with_attr::detruit()
{
try
{
if(x_attr != nullptr)
{
delete x_attr;
x_attr = nullptr;
}
}
catch(...)
{
// do nothing
}
}
void Ethread_cancel_with_attr::copy_from(const Ethread_cancel_with_attr & ref)
{
x_attr = new (nothrow) infinint(*ref.x_attr);
if(x_attr == nullptr)
throw Ememory("Ethread_cancel_with_attr::Ethread_cancel_with_attr");
}
} // end of namespace
dar-2.7.15/src/libdar/cat_device.hpp 0000644 0001750 0001750 00000005732 14636066467 014151 0000000 0000000 /*********************************************************************/
// dar - disk archive - a backup/restoration program
// Copyright (C) 2002-2024 Denis Corbin
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// to contact the author, see the AUTHOR file
/*********************************************************************/
/// \file cat_device.hpp
/// \brief parent class for all special devices inodes
/// \ingroup Private
#ifndef CAT_DEVICE_HPP
#define CAT_DEVICE_HPP
#include "../my_config.h"
extern "C"
{
} // end extern "C"
#include "cat_inode.hpp"
#include "integers.hpp"
namespace libdar
{
/// \addtogroup Private
/// @{
/// the special cat_device root class
class cat_device : public cat_inode
{
public :
cat_device(const infinint & uid, const infinint & gid, U_16 perm,
const datetime & last_access,
const datetime & last_modif,
const datetime &last_change,
const std::string & name,
U_16 major,
U_16 minor,
const infinint & fs_device);
cat_device(const std::shared_ptr & dialog,
const smart_pointer & pdesc,
const archive_version & reading_ver,
saved_status saved,
bool small);
cat_device(const cat_device & ref) = default;
cat_device(cat_device && ref) noexcept = default;
cat_device & operator = (const cat_device & ref) = default;
cat_device & operator = (cat_device && ref) = default;
~cat_device() = default;
virtual bool operator == (const cat_entree & ref) const override;
int get_major() const { if(get_saved_status() != saved_status::saved) throw SRC_BUG; else return xmajor; };
int get_minor() const { if(get_saved_status() != saved_status::saved) throw SRC_BUG; else return xminor; };
void set_major(int x) { xmajor = x; };
void set_minor(int x) { xminor = x; };
// using method is_more_recent_than() from cat_inode class
// using method has_changed_since() from cat_inode class
// signature is left pure abstract
protected :
virtual void sub_compare(const cat_inode & other, bool isolated_mode) const override;
virtual void inherited_dump(const pile_descriptor & pdesc, bool small) const override;
private :
U_16 xmajor, xminor;
};
/// @}
} // end of namespace
#endif
dar-2.7.15/src/libdar/slice_layout.cpp 0000644 0001750 0001750 00000006511 14636066467 014546 0000000 0000000 /*********************************************************************/
// dar - disk archive - a backup/restoration program
// Copyright (C) 2002-2024 Denis Corbin
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// to contact the author, see the AUTHOR file
/*********************************************************************/
#include "../my_config.h"
#include "slice_layout.hpp"
using namespace std;
namespace libdar
{
void slice_layout::read(generic_file & f)
{
char tmp;
first_size.read(f);
other_size.read(f);
first_slice_header.read(f);
other_slice_header.read(f);
if(f.read(&tmp , 1) == 1)
{
switch(tmp)
{
case OLDER_THAN_V8:
older_sar_than_v8 = true;
break;
case V8:
older_sar_than_v8 = false;
break;
default:
throw SRC_BUG;
}
}
else
throw Erange("slice_layout::read", gettext("Missing data while reading slice_layout object"));
}
void slice_layout::write(generic_file & f) const
{
char tmp = older_sar_than_v8 ? OLDER_THAN_V8 : V8;
first_size.dump(f);
other_size.dump(f);
first_slice_header.dump(f);
other_slice_header.dump(f);
f.write(&tmp, 1);
}
void slice_layout::clear()
{
first_size = 0;
other_size = 0;
first_slice_header = 0;
other_slice_header = 0;
older_sar_than_v8 = false;
}
void slice_layout::which_slice(const infinint & offset,
infinint & slice_num,
infinint & slice_offset) const
{
// considering particular case of a non-sliced archive
if(first_size.is_zero() || other_size.is_zero())
{
slice_num = 1;
if(offset < first_slice_header)
slice_offset = first_slice_header;
else
slice_offset = offset - first_slice_header;
return;
}
// sanity checks
if(first_size < first_slice_header)
throw SRC_BUG;
if(other_size < other_slice_header)
throw SRC_BUG;
if(first_slice_header.is_zero())
throw SRC_BUG;
if(other_slice_header.is_zero())
throw SRC_BUG;
// end of sanity checks
infinint byte_in_first_file = first_size - first_slice_header;
infinint byte_per_file = other_size - other_slice_header;
if(!older_sar_than_v8)
{
--byte_in_first_file;
--byte_per_file;
// this is due to the trailing flag (one byte length)
}
if(offset < byte_in_first_file)
{
slice_num = 1;
slice_offset = offset + first_slice_header;
}
else
{
euclide(offset - byte_in_first_file, byte_per_file, slice_num, slice_offset);
slice_num += 2;
// "+2" because file number starts to 1 and first file is already counted
slice_offset += other_slice_header;
}
}
} // end of namespace
dar-2.7.15/src/libdar/candidates.cpp 0000644 0001750 0001750 00000006611 14636066467 014152 0000000 0000000 /*********************************************************************/
// dar - disk archive - a backup/restoration program
// Copyright (C) 2002-2024 Denis Corbin
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// to contact the author, see the AUTHOR file
/*********************************************************************/
#include "../my_config.h"
extern "C"
{
} // end extern "C"
#include "candidates.hpp"
using namespace std;
namespace libdar
{
void candidates::add(archive_num val, db_etat st)
{
// considering the new entry to add
switch(st)
{
case db_etat::et_saved:
clear();
break;
case db_etat::et_removed:
case db_etat::et_absent:
if(ewr)
return; // stop here complete ignoring the new entry
clear();
break;
case db_etat::et_patch:
case db_etat::et_present:
case db_etat::et_inode:
break;
case db_etat::et_patch_unusable:
clear();
break;
default:
throw SRC_BUG;
}
// considering the current stack status
if(status.size() > 0)
{
if(st == db_etat::et_present)
return; // not useful to add et_present when something is already in
switch(status.back())
{
case db_etat::et_saved:
case db_etat::et_patch:
break;
case db_etat::et_present:
if(status.size() > 1) // et_present only allowed in status if it is the first entry
throw SRC_BUG;
else
clear();
break;
case db_etat::et_inode:
num.pop_back(); // removing the top of the stack
status.pop_back(); // removing the top of the stack
break;
case db_etat::et_removed:
case db_etat::et_absent:
clear();
break;
case db_etat::et_patch_unusable:
return; // stop here
default:
throw SRC_BUG;
}
}
// now adding the new entry
num.push_back(val);
status.push_back(st);
}
db_lookup candidates::get_status() const
{
// considering the bottom of the stack
if(status.size() > 0)
{
switch(status.front())
{
case db_etat::et_saved:
return db_lookup::found_present;
case db_etat::et_patch:
case db_etat::et_inode:
case db_etat::et_present:
case db_etat::et_patch_unusable:
return db_lookup::not_restorable;
case db_etat::et_removed:
case db_etat::et_absent:
return db_lookup::found_removed;
default:
throw SRC_BUG;
}
}
else
return db_lookup::not_found;
}
void candidates::set_the_set(set & archive) const
{
deque::const_iterator it = num.begin();
deque::const_iterator et = status.begin();
archive.clear();
while(it != num.end() && et != status.end())
{
archive.insert(*it);
++it;
++et;
}
if(it != num.end() || et != status.end())
throw SRC_BUG;
}
} // end of namespace
dar-2.7.15/src/libdar/fichier_libcurl.hpp 0000644 0001750 0001750 00000022315 14640016434 015164 0000000 0000000 /*********************************************************************/
// dar - disk archive - a backup/restoration program
// Copyright (C) 2002-2024 Denis Corbin
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// to contact the author, see the AUTHOR file
/*********************************************************************/
/// \file fichier_libcurl.hpp
/// \brief class fichier_libcurl definition. This is a full implementation/inherited class of class fichier_global
/// this type of object are generated by entrepot_libcurl.
/// \ingroup Private
#ifndef FICHIER_LIBCURL_HPP
#define FICHIER_LIBCURL_HPP
#include "../my_config.h"
extern "C"
{
#if LIBCURL_AVAILABLE
#if HAVE_CURL_CURL_H
#include
#endif
#endif
} // end extern "C"
#include
#ifdef LIBTHREADAR_AVAILABLE
#include
#endif
#include "integers.hpp"
#include "user_interaction.hpp"
#include "fichier_global.hpp"
#include "mycurl_protocol.hpp"
#include "mycurl_easyhandle_node.hpp"
namespace libdar
{
/// \addtogroup Private
/// @{
#if defined ( LIBCURL_AVAILABLE ) && defined ( LIBTHREADAR_AVAILABLE )
/// libcurl remote files
class fichier_libcurl : public fichier_global, protected libthreadar::thread
{
public:
/// constructor
fichier_libcurl(const std::shared_ptr & dialog, //< for user interaction requested by fichier_global
const std::string & chemin, //< full path of the file to open
mycurl_protocol proto, //< to workaround some libcurl strange behavior for some protocols
const std::shared_ptr & handle, //< the easy handle wrapper object
gf_mode m, //< open mode
U_I waiting, //< retry timeout in case of network error
bool force_permission, //< whether file permission should be modified
U_I permission, //< file permission to enforce if force_permission is set
bool erase); //< whether to erase the file before writing to it
/// no copy constructor available
/// \note because we inherit from libthreadar::thread we has no copy constructor
fichier_libcurl(const fichier_libcurl & ref) = delete;
/// no move constructor
fichier_libcurl(fichier_libcurl && ref) = delete;
/// no assignment operator
///\note because we inherit from libthreadar::thread that has not copy constructor
fichier_libcurl & operator = (const fichier_libcurl & ref) = delete;
/// no move operator
fichier_libcurl & operator = (fichier_libcurl && ref) = delete;
/// destructor
~fichier_libcurl() noexcept { kill(); join(); detruit(); };
/// change the permission of the file
virtual void change_permission(U_I perm) override;
/// set the ownership of the file
virtual void change_ownership(const std::string & user, const std::string & group) override
{ throw Efeature(gettext("user/group ownership not supported for this repository")); }; // not supported
/// return the size of the file
virtual infinint get_size() const override;
/// set posix_fadvise for the whole file
virtual void fadvise(advise adv) const override {}; // not supported and ignored
// inherited from generic_file
virtual bool skippable(skippability direction, const infinint & amount) override;
virtual bool skip(const infinint & pos) override;
virtual bool skip_to_eof() override;
virtual bool skip_relative(S_I x) override;
virtual bool truncatable(const infinint & pos) const override { return pos == get_position(); };
virtual infinint get_position() const override { return current_offset; };
protected:
// inherited from generic_file grand-parent class
virtual void inherited_read_ahead(const infinint & amount) override;
virtual void inherited_truncate(const infinint & pos) override;
virtual void inherited_sync_write() override;
virtual void inherited_flush_read() override;
virtual void inherited_terminate() override;
// inherited from fichier_global parent class
virtual U_I fichier_global_inherited_write(const char *a, U_I size) override;
virtual bool fichier_global_inherited_read(char *a, U_I size, U_I & read, std::string & message) override;
// inherited from thread
virtual void inherited_run() override;
private:
static const U_I tampon_size = CURL_MAX_WRITE_SIZE;
//////////////////////////////
//
// implementation internals
//
//////////////////////////////
// the object has two modes:
// - meta data mode (skip, get_position() and other non read/write operations)
// - data mode (read or write operations)
//
// in metadata mode each method is a simple code execution (no subthread, no callback)
//
// in data mode, a subthread is used to interact with libcurl. It sends or receives
// data through the interthread pipe. A callback is occasionally run by libcurl in this
// subthread.
// in read mode, the subthread is run only if the interthread is empty. the subthread may
// survive the inherited_read call and may suspend on writing data to interthread being full
// - "subthread_net_offset" is updated by the callback and read by the subthread when
// libcurl has returned it keeps trace of the amount of data sent to interthread.
// - "network_block" is set by the main thread to define the amount of data to be fetched. It
// it used to setup libcurl and is read by the subthread for control/validation purposes
bool end_data_mode; ///< true if subthread has been requested to end
bool sub_is_dying; ///< is set by subthread when about to end
bool sync_write_asked; ///< ask subthread to use 'synchronize' tell all data has been written
bool weof; ///< whether write EOF has been signaled to libcurl
std::shared_ptr ehandle; ///< easy handle (wrapped in C++ object) that we modify when necessary
bool metadatamode; ///< wether we are acting on metadata rather than file's data
infinint current_offset; ///< current offset we are reading / writing at
bool has_maxpos; ///< true if maxpos is set
infinint maxpos; ///< in read mode this is the filesize, in write mode this the offset where to append data (not ovewriting)
bool append_write; ///< whether we should append to data (and not replace) when uploading
U_I meta_inbuf; ///< amount of byte available in "meta_tampon"
U_I wait_delay; ///< time in second to wait before retrying in case of network error
infinint network_block; ///< maximum amount of data read at once from the network (only read by subthread)
infinint subthread_net_offset; ///< updated by sub thread in network block mode to give amount of bytes pushed to interthread
infinint subthread_cur_offset; ///< subthread copy of current_offset
libthreadar::fast_tampon interthread; ///< data channel for reading or writing with subthread
libthreadar::barrier synchronize; ///< used to be sure subthread has been launched // also used for sync_write
mycurl_protocol x_proto; ///< used to workaround some libcurl strange behavoir for some protocols
void set_range(const infinint & begin, const infinint & range_size); ///< set range in easyhandle
void unset_range(); ///< unset range in easyhandle
void switch_to_metadata(bool mode);///< set to true to get or set file's metadata, false to read/write file's data
void detruit(); ///< get ready for object destruction
void run_thread(); ///< run subthread with the previously defined parameters
void stop_thread(); ///< ask subthread to stop and wait for its end
void relaunch_thread(const infinint & block_size); ///< re-run the subthread if not running
void initialize_subthread(); ///< subthread routine to init itself
void finalize_subthread(); ///< subthread routine to end itself
void set_subthread(U_I & needed_bytes); ///< set parameters and run subthtread if necessary
bool still_data_to_write(); /// return true when in write mode and there is data pending to writing in interthread
static size_t write_data_callback(char *buffer, size_t size, size_t nmemb, void *userp);
static size_t read_data_callback(char *bufptr, size_t size, size_t nitems, void *userp);
static size_t write_meta_callback(char *buffer, size_t size, size_t nmemb, void *userp);
static size_t read_meta_callback(char *bufptr, size_t size, size_t nitems, void *userp);
};
#endif
/// @}
} // end of namespace
#endif
dar-2.7.15/src/libdar/scrambler.hpp 0000644 0001750 0001750 00000006553 14636066467 014037 0000000 0000000 /*********************************************************************/
// dar - disk archive - a backup/restoration program
// Copyright (C) 2002-2024 Denis Corbin
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// to contact the author, see the AUTHOR file
/*********************************************************************/
/// \file scrambler.hpp
/// \brief contains the definition of the scrambler class, a very weak encryption scheme
/// \ingroup Private
#ifndef SCRAMBLER_HPP
#define SCRAMBLER_HPP
#include "../my_config.h"
#include
#include "infinint.hpp"
#include "generic_file.hpp"
#include "erreurs.hpp"
#include "secu_string.hpp"
namespace libdar
{
/// \addtogroup Private
/// @{
/// \brief scrambler is a very weak encryption scheme
class scrambler : public generic_file
{
public:
scrambler(const secu_string & pass, generic_file & hidden_side);
scrambler(const scrambler & ref) = delete;
scrambler(scrambler && ref) noexcept = delete;
scrambler & operator = (const scrambler & ref) = delete;
scrambler & operator = (scrambler && ref) noexcept = delete;
~scrambler() { if(buffer != nullptr) delete [] buffer; };
virtual bool skippable(skippability direction, const infinint & amount) override { if(ref == nullptr) throw SRC_BUG; return ref->skippable(direction, amount); };
virtual bool skip(const infinint & pos) override { if(ref == nullptr) throw SRC_BUG; return ref->skip(pos); };
virtual bool skip_to_eof() override { if(ref == nullptr) throw SRC_BUG; return ref->skip_to_eof(); };
virtual bool skip_relative(S_I x) override { if(ref == nullptr) throw SRC_BUG; return ref->skip_relative(x); };
virtual bool truncatable(const infinint & pos) const override { if(ref == nullptr) throw SRC_BUG; return ref->truncatable(pos); };
virtual infinint get_position() const override { if(ref == nullptr) throw SRC_BUG; return ref->get_position(); };
protected:
virtual void inherited_read_ahead(const infinint & amount) override { if(ref == nullptr) throw SRC_BUG; ref->read_ahead(amount); };
virtual U_I inherited_read(char *a, U_I size) override;
virtual void inherited_write(const char *a, U_I size) override;
virtual void inherited_truncate(const infinint & pos) override { if(ref == nullptr) throw SRC_BUG; ref->truncate(pos); };
virtual void inherited_sync_write() override {}; // nothing to do
virtual void inherited_flush_read() override {}; // nothing to do
virtual void inherited_terminate() override {}; // nothing to do
private:
secu_string key;
U_I len;
generic_file *ref;
unsigned char *buffer;
U_I buf_size;
};
/// @}
} // end of namespace
#endif
dar-2.7.15/src/libdar/contextual.hpp 0000644 0001750 0001750 00000006502 14636066467 014245 0000000 0000000 /*********************************************************************/
// dar - disk archive - a backup/restoration program
// Copyright (C) 2002-2024 Denis Corbin
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// to contact the author, see the AUTHOR file
/*********************************************************************/
/// \file contextual.hpp
/// \brief class contextual adds the information of phases in the generic_file
/// \ingroup Private
#ifndef CONTEXTUAL_HPP
#define CONTEXTUAL_HPP
#include "../my_config.h"
extern "C"
{
#if HAVE_UNISTD_H
#include
#endif
} // end extern "C"
#include "erreurs.hpp"
#include "label.hpp"
#include
namespace libdar
{
#define CONTEXT_INIT "init"
#define CONTEXT_OP "operation"
#define CONTEXT_LAST_SLICE "last_slice"
/// \addtogroup Private
/// @{
/// the contextual class adds the information of phases in the generic_file
/// several phases are defined like for example
/// - INIT phase
/// - OPERATIONAL phase
/// - LAST SLICE phase
/// .
/// these are used to help the command launched between slices to
/// decide the action to do depending on the context when reading an archive
/// (first slice / last slice read, ...)
/// the context must also be transfered to dar_slave through the pair of tuyau objects
///
/// this class also support some additional informations common to all 'level1' layer of
/// archive, such as:
/// - the data_name information
///
class contextual
{
public :
contextual() { status = ""; };
contextual(const contextual & ref) = default;
contextual(contextual && ref) noexcept = default;
contextual & operator = (const contextual & ref) = default;
contextual & operator = (contextual && ref) noexcept = default;
virtual ~contextual() noexcept(false) {};
/// defines the new contextual value
/// \note inherited class may redefine this call but
/// but must call the parent method to set the value
/// contextual:set_info_status()
virtual void set_info_status(const std::string & s) { status = s; };
/// get the current contextual value
virtual std::string get_info_status() const { return status; };
/// returns whether the archive is a old archive (format < 8)
virtual bool is_an_old_start_end_archive() const = 0;
/// obtain the data_name of the archive (label associated with the archive's data)
/// \note label are conserved with dar_xform and archive isolation, but are
/// not with archive merging or archive creation (full or differential backup)
virtual const label & get_data_name() const = 0;
private:
std::string status;
};
/// @}
} // end of namespace
#endif
dar-2.7.15/src/libdar/cat_tube.cpp 0000644 0001750 0001750 00000002556 14636066467 013645 0000000 0000000 /*********************************************************************/
// dar - disk archive - a backup/restoration program
// Copyright (C) 2002-2024 Denis Corbin
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// to contact the author, see the AUTHOR file
/*********************************************************************/
#include "../my_config.h"
extern "C"
{
} // end extern "C"
#include "cat_tube.hpp"
using namespace std;
namespace libdar
{
bool cat_tube::operator == (const cat_entree & ref) const
{
const cat_tube *ref_tube = dynamic_cast(&ref);
if(ref_tube == nullptr)
return false;
else
return cat_inode::operator == (ref);
}
} // end of namespace
dar-2.7.15/src/libdar/parallel_tronconneuse.hpp 0000644 0001750 0001750 00000060144 14636067146 016452 0000000 0000000 /*********************************************************************/
// dar - disk archive - a backup/restoration program
// Copyright (C) 2002-2024 Denis Corbin
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// to contact the author, see the AUTHOR file
/*********************************************************************/
/// \file parallel_tronconneuse.hpp
/// \brief defines a block structured file.
/// \ingroup Private
/// Several classes are defined here:
/// - class parallel_tronconneuse, which has similar interface and behavior as class tronconneuse
/// - class read_below, is used internally by parallel_tronconneuse in read-only mode to workers from data of the underlay
/// - class write_below, is used internally by parallel_tronconneuse in write-only mode to write down the data produced by the workers
/// - class crypto_workers, that transform data between parallel_tronconneuse and the read_below class or the write_below class
/// depending on the context. Several objects of this class executes in parallel the crypto_module routine, but there is
/// only one read_below or write_below thread, the class parallel_tronconneuse stays executed by the main/original/calling thread
/// .
#ifndef PARALLEL_TRONCONNEUSE_HPP
#define PARALLEL_TRONCONNEUSE_HPP
#include "../my_config.h"
#include
#include "infinint.hpp"
#include "archive_version.hpp"
#include "crypto_segment.hpp"
#include "heap.hpp"
#include "crypto_module.hpp"
#include "proto_tronco.hpp"
#include
namespace libdar
{
/// \addtogroup Private
/// @{
// those class are used by the parallel_tronconneuse class to wrap the different
// type of threads. They are defined just after the parallel_tronconneuse definition
class read_below;
class write_below;
class crypto_worker;
/// status flags used between parallel_tronconneuse and its sub-threads
enum class tronco_flags { normal = 0, stop = 1, eof = 2, die = 3, data_error = 4, exception_below = 5, exception_worker = 6, exception_error = 7 };
/////////////////////////////////////////////////////
//
// the parallel_tronconneuse class that orchestrate all that
//
//
/// this is a partial implementation of the generic_file interface to cypher/decypher data block by block.
/// This class is a pure virtual one, as several calls have to be defined by inherited classes
/// - encrypted_block_size_for
/// - clear_block_allocated_size_for
/// - encrypt_data
/// - decrypt_data
/// .
/// parallel_tronconneuse is either read_only or write_only, read_write is not allowed.
/// The openning mode is defined by encrypted_side's mode.
/// In write_only no skip() is allowed, writing is sequential from the beginning of the file to the end
/// (like writing to a pipe).
/// In read_only all skip() functions are available.
class parallel_tronconneuse : public proto_tronco
{
public:
/// This is the constructor
/// \param[in] workers is the number of worker threads
/// \param[in] block_size is the size of block encryption (the size of clear data encrypted toghether).
/// \param[in] encrypted_side where encrypted data are read from or written to.
/// \param[in] reading_ver version of the archive format
/// \param[in] ptr pointer to an crypto_module object that will be passed to the parallel_tronconneuse
/// \note that encrypted_side is not owned and destroyed by tronconneuse, it must exist during all the life of the
/// tronconneuse object, and is not destroyed by the tronconneuse's destructor
parallel_tronconneuse(U_I workers,
U_32 block_size,
generic_file & encrypted_side,
const archive_version & reading_ver,
std::unique_ptr & ptr);
/// copy constructor
parallel_tronconneuse(const parallel_tronconneuse & ref) = delete;
/// move constructor
parallel_tronconneuse(parallel_tronconneuse && ref) = default;
/// assignment operator
parallel_tronconneuse & operator = (const parallel_tronconneuse & ref) = delete;
/// move operator
parallel_tronconneuse & operator = (parallel_tronconneuse && ref) noexcept = default;
/// destructor
~parallel_tronconneuse() noexcept;
/// inherited from generic_file
virtual bool skippable(skippability direction, const infinint & amount) override;
/// inherited from generic_file
virtual bool skip(const infinint & pos) override;
/// inherited from generic_file
virtual bool skip_to_eof() override;
/// inherited from generic_file
virtual bool skip_relative(S_I x) override;
/// inherited from generic_file
virtual bool truncatable(const infinint & pos) const override { return false; };
/// inherited from generic_file
virtual infinint get_position() const override { if(is_terminated()) throw SRC_BUG; return current_position; };
/// in write_only mode indicate that end of file is reached
/// this call must be called in write mode to purge the
/// internal cache before deleting the object (else some data may be lost)
/// no further write call is allowed
/// \note this call cannot be used from the destructor, because it relies on pure virtual methods
virtual void write_end_of_file() override { if(is_terminated()) throw SRC_BUG; sync_write(); };
/// this method to modify the initial shift. This overrides the constructor "no_initial_shift" of the constructor
virtual void set_initial_shift(const infinint & x) override;
/// let the caller give a callback function that given a generic_file with cyphered data, is able
/// to return the offset of the first clear byte located *after* all the cyphered data, this
/// callback function is used (if defined by the following method), when reaching End of File.
virtual void set_callback_trailing_clear_data(trailing_clear_data_callback call_back) override;
/// returns the block size given to constructor
virtual U_32 get_clear_block_size() const override { return clear_block_size; };
private:
// inherited from generic_file
/// this protected inherited method is now private for inherited classes of tronconneuse
virtual void inherited_read_ahead(const infinint & amount) override;
/// this protected inherited method is now private for inherited classes of tronconneuse
virtual U_I inherited_read(char *a, U_I size) override;
/// inherited from generic_file
/// this protected inherited method is now private for inherited classes of tronconneuse
virtual void inherited_write(const char *a, U_I size) override;
/// this prorected inherited method is now private for inherited classed of tronconneuse
/// \note no skippability in write mode, so no truncate possibility neither, this call
/// will always throw a bug exception
virtual void inherited_truncate(const infinint & pos) override { throw SRC_BUG; };
/// this protected inherited method is now private for inherited classes of tronconneuse
virtual void inherited_sync_write() override;
/// this protected inherited method is now private for inherited classes of tronconneuse
virtual void inherited_flush_read() override;
/// this protected inherited method is now private for inherited classes of tronconneuse
virtual void inherited_terminate() override;
const archive_version & get_reading_version() const { return reading_ver; };
// internal data structure
enum class thread_status { running, suspended, dead };
// the fields
U_I num_workers; ///< number of worker threads
U_32 clear_block_size; ///< size of a clear block
infinint current_position; ///< current position for the upper layer perspective (modified by skip*, inherited_read/write, find_offset_in_lus_data)
infinint initial_shift; ///< the offset in the "encrypted" below layer at which starts the encrypted data
archive_version reading_ver; ///< archive format we follow
std::unique_ptr crypto; ///< the crypto module use to cipher / uncipher block of data
infinint (*mycallback)(generic_file & below, const archive_version & reading_ver);
generic_file* encrypted;
// fields used to represent possible status of subthreads and communication channel (the pipe)
U_I ignore_stop_acks; ///< how much stop ack still to be read (aborted stop order context)
thread_status t_status; ///< wehther child thread are waiting us on the barrier
// the following stores data from the ratelier_gather to be provided for read() operation
// the lus_data/lus_flags is what is extracted from the ratelier_gather, both constitute
// the feedback channel from sub-threads to provide order acks and normal data
std::deque > lus_data;
std::deque lus_flags;
bool lus_eof;
bool check_bytes_to_skip; ///< whether to check for bytes to skip
// the following stores data going to ratelier_scatter for the write() operation
std::unique_ptr tempo_write;
infinint block_num;
// the datastructures shared among threads
std::shared_ptr > scatter;
std::shared_ptr > gather;
std::shared_ptr waiter;
std::shared_ptr > tas;
// the child threads
std::deque > travailleur;
std::unique_ptr crypto_reader;
std::unique_ptr crypto_writer;
/// send and order to subthreads and gather acks from them
/// \param[in] order is the order to send to the subthreads
/// \param[in] for_offset is not zero is the offset we want to skip to
/// (it is only taken into account when order is stop)
/// \note with order stop and non zero for_offset, if the
/// data at for_offset is found while purging the
/// ratelier_gather, the purge is stopped, false is returned and
/// the ignore_stop field is set to true, meaning that a stop order
/// has not been purged from the pipe and should be ignored when its
/// acknolegements will be met. In any other case true is returned,
/// the subthreaded got the order and the ratelier has been purged.
bool send_read_order(tronco_flags order, const infinint & for_offset = 0);
/// send order in write mode
void send_write_order(tronco_flags order);
/// wake up threads in read mode when necessary
void go_read();
/// fill lus_data/lus_flags from ratelier_gather if these are empty
void read_refill();
/// purge the ratelier from the next order which is provided as returned value
/// \param[in] pos if pos is not zero, the normal data located at
/// pos offset is also looked for. If it is found before any order
/// the call returns tronco_flags::normal and the order is not purged
/// but the ignore_stop_acks fields is set to true for further
/// reading to skip over this order acknolegments.
tronco_flags purge_ratelier_from_next_order(infinint pos = 0);
/// removing the ignore_stop_acks pending on the pipe
/// \param[in] pos if pos is not zero and normal data is found at
/// pos offset before all stop acks could get read, the call stops
/// and return false. Else true is returned meaning all stop acks
/// has been read and removed from the pope
/// \note this method acts the same pas purge_ratelier_from_next_order but fetch
/// from ratelier up to data offset met of the pending ack to be all read
/// but it then stops, it does not look for a real order after
/// the pending stop acks of an aborted stop order
bool purge_unack_stop_order(const infinint & pos = 0);
/// flush lus_data/lus_flags up to requested pos offset to be found or all data has been removed
/// \param[in] pos the data offset we look for
/// \return true if the offset has been found and is
/// ready for next inherited_read() call, false else
/// and lus_data/lus_flags have been empties of
/// the first non-order blocks found (data blocks)
/// \note current_position is set upon success else
/// it is unchanged but will not match what may still
/// remain in the pipe
bool find_offset_in_lus_data(const infinint & pos);
/// reset the interthread datastructure and launch the threads
void run_threads();
/// end threads taking into account the fact they may be suspended on the barrier
void stop_threads();
/// call by join_threads() below just code simplification around exception handling
void join_workers_only();
/// wait for threads to finish and eventually rethrow their exceptions in current thread
void join_threads();
static U_I get_ratelier_size(U_I num_worker) { return num_worker + num_worker/2; };
static U_I get_heap_size(U_I num_worker);
};
/////////////////////////////////////////////////////
//
// read_below subthread used by parallel_tronconneuse
// to dispatch chunk of encrypted data to the workers
//
class read_below: public libthreadar::thread
{
public:
read_below(const std::shared_ptr > & to_workers, ///< where to send chunk of crypted data
const std::shared_ptr & waiter, ///< barrier used for synchronization with workers and the thread that called us
U_I num_workers, ///< how much workers have to be informed when special condition occurs
U_I clear_block_size, ///< clear block size used
generic_file* encrypted_side, ///< the encrypted file we fetch data from and slice in chunks for the workers
const std::shared_ptr > xtas, ///< heap of pre-allocated memory for the chunks
infinint init_shift): ///< the offset at which the encrypted data is expected to start
workers(to_workers),
waiting(waiter),
num_w(num_workers),
clear_buf_size(clear_block_size),
encrypted(encrypted_side),
tas(xtas),
initial_shift(init_shift),
reof(false),
trailing_clear_data(nullptr)
{ flag = tronco_flags::normal; };
~read_below() { if(ptr) tas->put(move(ptr)); kill(); join(); };
/// let the caller give a callback function that given a generic_file with mixed cyphered and clear data, is able
/// to return the offset of the first clear byte located *after* all the cyphered data, this
/// callback function is used (if defined by the following method), when reaching End of File.
void set_callback_trailing_clear_data(trailing_clear_data_callback call_back) { trailing_clear_data = call_back; };
// *** //
// *** the method above should not be used anymore once the thread is running *** //
// *** //
/// set the initial shift must be called right after set_flag(stop) to take effect
void set_initial_shift(const infinint & x) { initial_shift = x; };
/// available for the parent thread to skip at another positon (read mode)
/// \param[in] pos is the offset (from the upper layer / clear data point
/// of view) at which we should seek
/// \note changes asked by this call do not take effect until set_flag(stop)
/// is invoked
void set_pos(const infinint & pos) { skip_to = pos; };
/// method for the parent thread to send a control order
/// \note the parent thread must cleanup the gather object, it should
/// expect to receive N block with the flag given to set_flag (N being
/// the number of workers. Then this parent thread by a call the the
/// waiter.Wait() barrier method will
/// release all the worker and this below thread that will feed the
/// pipe with new data taken at the requested offset provided by
/// mean of the above set_pos() method.
/// \note example: ask to stop before skipping
void set_flag(tronco_flags val) { flag = val; };
/// method available for the parent thread to know the clear offset of the new flow
/// \note after set_pos()+set_flag() the new flow may start
/// a bit before the position requested by set_pos() due to
/// block of encryption boundaries. So the caller should ignore
/// some first bytes of data received
const infinint & get_clear_flow_start() const { return clear_flow_start; };
/// method available for the parent thread to know the amount of bytes to skip in the new flow
/// \note this is the difference between the argument provided
/// to set_pos() and the value returned by get_clear_flow_start()
/// in other words this is the amount of bytes to skip in the
/// new flow, in order to
const infinint & get_pos_in_flow() const { return pos_in_flow; };
protected:
virtual void inherited_run() override;
private:
std::shared_ptr > workers; ///< object used to scatter data to workers
std::shared_ptr waiting; ///< barrier used to synchronize with worker and parent thread
U_I num_w; ///< number of worker thread we are feeding through the ratelier_scatter
U_I clear_buf_size; ///< amount of clear data per encrypted chunk
generic_file* encrypted; ///< the encrypted data
archive_version version; ///< archive version format
std::shared_ptr > tas; ///< where to fetch from blocks of data
infinint initial_shift; ///< initial shift
bool reof; ///< whether we reached eof while reading
trailing_clear_data_callback trailing_clear_data; ///< callback function that gives the amount of clear data found at the end of the given file
std::unique_ptr ptr; ///< current segment we are setting up
infinint index_num; ///< current crypto block index
// initialized by inherited_run() / get_ready_for_new_offset()
infinint crypt_offset; ///< position to skip to in 'below' to start reading crypted data
U_I encrypted_buf_size; ///< size of the encrypted chunk of data
// fields accessible by both the caller and the read_below thread
infinint skip_to; ///< modification to this field is only done by the parent thread at a time it is not read by this thread
tronco_flags flag; ///< modification to this type is atomic so we do not use mutex
infinint clear_flow_start; ///< modification of this field is only done by this thread a at time the parent thread does not read it
infinint pos_in_flow; ///< modification of this field is only done by this thread a at time the parent thread does not read it
void work();
infinint get_ready_for_new_offset();
void send_flag_to_workers(tronco_flags theflag);
// same function as the tronconneuse::position_clear2crypt
void position_clear2crypt(const infinint & pos,
infinint & file_buf_start,
infinint & clear_buf_start,
infinint & pos_in_buf,
infinint & block_num);
};
/////////////////////////////////////////////////////
//
// write_below subthread used by parallel_tronconneuse
// to gather and write down encrypted data work from workers
//
class write_below: public libthreadar::thread
{
public:
write_below(const std::shared_ptr > & from_workers,
const std::shared_ptr & waiter,
U_I num_workers,
generic_file* encrypted_side,
const std::shared_ptr > xtas):
workers(from_workers),
waiting(waiter),
num_w(num_workers),
cur_num_w(0),
encrypted(encrypted_side),
tas(xtas),
error(false),
error_block(0)
{ if(encrypted == nullptr) throw SRC_BUG; };
~write_below() { kill(); join(); };
bool exception_pending() const { return error; };
const infinint & get_error_block() const { return error_block; };
protected:
virtual void inherited_run() override;
private:
std::shared_ptr > workers;
std::shared_ptr waiting;
U_I num_w;
U_I cur_num_w;
generic_file* encrypted; ///< the encrypted data
std::shared_ptr > tas;
bool error;
infinint error_block; // last crypto block before error
std::deque >ones;
std::deque flags;
void work();
};
/////////////////////////////////////////////////////
//
// the crypto_worker threads performing ciphering/deciphering
// of many data blocks in parallel
//
class crypto_worker: public libthreadar::thread
{
public:
crypto_worker(std::shared_ptr > & read_side,
std::shared_ptr > & write_side,
std::shared_ptr waiter,
std::unique_ptr && ptr,
bool encrypt):
reader(read_side),
writer(write_side),
waiting(waiter),
crypto(move(ptr)),
do_encrypt(encrypt),
abort(status::fine)
{ if(!reader || !writer || !waiting || !crypto) throw SRC_BUG; };
virtual ~crypto_worker() { kill(); join(); };
protected:
virtual void inherited_run() override;
private:
enum class status { fine, inform, sent };
std::shared_ptr > & reader;
std::shared_ptr > & writer;
std::shared_ptr waiting;
std::unique_ptr crypto;
bool do_encrypt; // if false do decrypt
std::unique_ptr ptr;
unsigned int slot;
status abort;
void work();
};
/// @}
} // end of namespace
#endif
dar-2.7.15/src/libdar/wrapperlib.hpp 0000644 0001750 0001750 00000016213 14636066467 014226 0000000 0000000 /*********************************************************************/
// dar - disk archive - a backup/restoration program
// Copyright (C) 2002-2024 Denis Corbin
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// to contact the author, see the AUTHOR file
/*********************************************************************/
/// \file wrapperlib.hpp
/// \brief libz and libbz2 wrapper to have identical interface to these libraries.
/// \ingroup Private
///
/// libz and libbz2 library differ in the way they return values
/// in certain circumpstances. This module defines the wrapperlib class
/// that make their use homogeneous.
#ifndef WRAPPERLIB_HPP
#define WRAPPERLIB_HPP
#include "../my_config.h"
extern "C"
{
#if HAVE_ZLIB_H && LIBZ_AVAILABLE
#include
#endif
#if HAVE_BZLIB_H && LIBBZ2_AVAILABLE
#include
#endif
#if HAVE_LZMA_H && LIBLZMA_AVAILABLE
#include
#endif
} // end extern "C"
#include "integers.hpp"
namespace libdar
{
/// \addtogroup Private
/// @{
const int WR_OK = 0; // operation successful
const int WR_MEM_ERROR = 1; // lack of memory
const int WR_VERSION_ERROR = 2; // incompatible version of the compression library with the one expected by libdar
const int WR_STREAM_ERROR = 3; // not a valid compression level, incoherent data provided to the compression library
const int WR_DATA_ERROR = 4; // data has been corrupted
const int WR_NO_FLUSH = 5; // parameter to let the compression library decide at which time to output data (from zlib Z_NO_FLUSH, no other way is done in libdar)
const int WR_BUF_ERROR = 6; // no possible work to perform for the request action without additional provided data/or storage space to the compression library
const int WR_STREAM_END = 7; // end of compressed data met
const int WR_FINISH = 8; // parameter requiring the compression library to cleanly stop the running operation
enum wrapperlib_mode { zlib_mode, bzlib_mode, xz_mode };
/// this class encapsulates calls to libz or libbz2
/// this is mainly an adaptation of libbz2 specificities to
/// have libb2 acting exactly as libz does.
class wrapperlib
{
public:
wrapperlib(wrapperlib_mode mode);
wrapperlib(const wrapperlib & ref) = delete;
wrapperlib(wrapperlib && ref) noexcept = delete;
wrapperlib & operator = (const wrapperlib & ref) = delete;
wrapperlib & operator = (wrapperlib && ref) noexcept = delete;
~wrapperlib();
void set_next_in(const char *x) { return (this->*x_set_next_in)(x); };
void set_avail_in(U_I x) { return (this->*x_set_avail_in)(x); };
U_I get_avail_in() const { return (this->*x_get_avail_in)(); };
U_64 get_total_in() const { return (this->*x_get_total_in)(); };
void set_next_out(char *x) { return (this->*x_set_next_out)(x); };
char *get_next_out() const { return (this->*x_get_next_out)(); };
void set_avail_out(U_I x) { return (this->*x_set_avail_out)(x); };
U_I get_avail_out() const { return (this->*x_get_avail_out)(); };
U_64 get_total_out() const { return (this->*x_get_total_out)(); };
S_I compressInit(U_I compression_level) { level = compression_level; return (this->*x_compressInit)(compression_level); };
S_I decompressInit() { return (this->*x_decompressInit)(); };
S_I compressEnd() { return (this->*x_compressEnd)(); };
S_I decompressEnd() { return (this->*x_decompressEnd)(); };
S_I compress(S_I flag) { return (this->*x_compress)(flag); };
S_I decompress(S_I flag) { return (this->*x_decompress)(flag);};
S_I compressReset();
S_I decompressReset();
private:
#if LIBZ_AVAILABLE
z_stream *z_ptr;
#endif
#if LIBBZ2_AVAILABLE
bz_stream *bz_ptr;
#endif
#if LIBLZMA_AVAILABLE
lzma_stream *lzma_ptr;
#endif
S_I level;
void (wrapperlib::*x_set_next_in)(const char *x);
void (wrapperlib::*x_set_avail_in)(U_I x);
U_I (wrapperlib::*x_get_avail_in)() const;
U_64 (wrapperlib::*x_get_total_in)() const;
void (wrapperlib::*x_set_next_out)(char *x);
char *(wrapperlib::*x_get_next_out)() const;
void (wrapperlib::*x_set_avail_out)(U_I x);
U_I (wrapperlib::*x_get_avail_out)() const;
U_64 (wrapperlib::*x_get_total_out)() const;
S_I (wrapperlib::*x_compressInit)(U_I compression_level);
S_I (wrapperlib::*x_decompressInit)();
S_I (wrapperlib::*x_compressEnd)();
S_I (wrapperlib::*x_decompressEnd)();
S_I (wrapperlib::*x_compress)(S_I flag);
S_I (wrapperlib::*x_decompress)(S_I flag);
// set of routines for zlib
#if LIBZ_AVAILABLE
S_I z_compressInit(U_I compression_level);
S_I z_decompressInit();
S_I z_compressEnd();
S_I z_decompressEnd();
S_I z_compress(S_I flag);
S_I z_decompress(S_I flag);
void z_set_next_in(const char *x);
void z_set_avail_in(U_I x);
U_I z_get_avail_in() const;
U_64 z_get_total_in() const;
void z_set_next_out(char *x);
char *z_get_next_out() const;
void z_set_avail_out(U_I x);
U_I z_get_avail_out() const;
U_64 z_get_total_out() const;
#endif
// set of routines for bzlib
#if LIBBZ2_AVAILABLE
S_I bz_compressInit(U_I compression_level);
S_I bz_decompressInit();
S_I bz_compressEnd();
S_I bz_decompressEnd();
S_I bz_compress(S_I flag);
S_I bz_decompress(S_I flag);
void bz_set_next_in(const char *x);
void bz_set_avail_in(U_I x);
U_I bz_get_avail_in() const;
U_64 bz_get_total_in() const;
void bz_set_next_out(char *x);
char *bz_get_next_out() const;
void bz_set_avail_out(U_I x);
U_I bz_get_avail_out() const;
U_64 bz_get_total_out() const;
#endif
// set of routines for liblzma
#if LIBLZMA_AVAILABLE
S_I lzma_compressInit(U_I compression_level);
S_I lzma_decompressInit();
S_I lzma_end();
S_I lzma_encode(S_I flag);
void lzma_set_next_in(const char *x);
void lzma_set_avail_in(U_I x);
U_I lzma_get_avail_in() const;
U_64 lzma_get_total_in() const;
void lzma_set_next_out(char *x);
char *lzma_get_next_out() const;
void lzma_set_avail_out(U_I x);
U_I lzma_get_avail_out() const;
U_64 lzma_get_total_out() const;
#endif
};
/// @}
} // end of namespace
#endif
dar-2.7.15/src/libdar/mycurl_protocol.hpp 0000644 0001750 0001750 00000003620 14636066467 015311 0000000 0000000 /*********************************************************************/
// dar - disk archive - a backup/restoration program
// Copyright (C) 2002-2024 Denis Corbin
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// to contact the author, see the AUTHOR file
/*********************************************************************/
/// \file mycurl_protocol.hpp
/// \brief datastructure defining the network protocols available for entrepot_libcurl class
/// \ingroup API
#ifndef MYCURL_PROTOCOL_HPP
#define MYCURL_PROTOCOL_HPP
#include "../my_config.h"
extern "C"
{
} // end extern "C"
namespace libdar
{
/// \addtogroup API
/// @{
/// libcurl protocols supported by libdar
/// \note dar needs to list a directory content to find
/// the last slice available in a directory, which
/// feature is not always available with http and https protocols
/// and never available with scp protocol
/// Thus dar only supports ftp and sftp
enum mycurl_protocol
{
proto_ftp, ///< FTP file transfer protocol
proto_sftp ///< SFTP Secure FTP (over ssh)
};
/// extract mycurl_protocol from a given URL
extern mycurl_protocol string_to_mycurl_protocol(const std::string & arg);
/// @}
} // end of namespace
#endif
dar-2.7.15/src/libdar/macro_tools.hpp 0000644 0001750 0001750 00000044275 14636067146 014404 0000000 0000000 /*********************************************************************/
// dar - disk archive - a backup/restoration program
// Copyright (C) 2002-2024 Denis Corbin
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// to contact the author, see the AUTHOR file
/*********************************************************************/
/// \file macro_tools.hpp
/// \brief macroscopic tools for libdar internals
/// \ingroup Private
#ifndef MACRO_TOOLS_HPP
#define MACRO_TOOLS_HPP
#include "../my_config.h"
extern "C"
{
#if HAVE_LIMITS_H
#include
#endif
}
#include
#include
#include "catalogue.hpp"
#include "compression.hpp"
#include "infinint.hpp"
#include "header_version.hpp"
#include "generic_file.hpp"
#include "crypto.hpp"
#include "pile.hpp"
#include "entrepot.hpp"
#include "range.hpp"
#include "slice_layout.hpp"
#include "tuyau.hpp"
#include "trivial_sar.hpp"
#include "proto_compressor.hpp"
#define BUFFER_SIZE 102400
#ifdef SSIZE_MAX
#if SSIZE_MAX < BUFFER_SIZE
#undef BUFFER_SIZE
#define BUFFER_SIZE SSIZE_MAX
#endif
#endif
namespace libdar
{
/// \addtogroup Private
/// @{
constexpr U_I GLOBAL_ELASTIC_BUFFER_SIZE = 51200;
extern const archive_version macro_tools_supported_version;
extern const std::string LIBDAR_STACK_LABEL_UNCOMPRESSED;
extern const std::string LIBDAR_STACK_LABEL_CLEAR;
extern const std::string LIBDAR_STACK_LABEL_UNCYPHERED;
extern const std::string LIBDAR_STACK_LABEL_LEVEL1;
/// create an container to write an archive to a pipe
extern trivial_sar *macro_tools_open_archive_tuyau(const std::shared_ptr & dialog,
S_I fd,
gf_mode mode,
const label & internal_name,
const label & data_name,
bool slice_header_format_07,
const std::string & execute);
/// setup the given pile object to contain a stack of generic_files suitable to read an archive
/// \note the stack has the following contents depending on given options
///
/// +-top LIBDAR_STACK_LABEL_
/// +-------------------------------------------------------+---------------------+
/// | compressor |v v v |
/// +-------------------------------------------------------+---------------------+
/// | [ escape ] |v v v |
/// +-------------------------------------------------------+v---v---v------------+
/// | [ cache ] | (parallel_)tronconneuse | scrambler |v v v |
/// | [ tronc ] |LEVEL 1 |
/// | trivial_sar | zapette | sar |v v v |
/// +-------------------------------------------------------+---------------------+
/// +-bottom
///
/// \note escape is present unless tape mark have been disabled at archive creation time
/// \note tronc is not present in sequential read mode
/// \note cache layer is present only in absence of encryption and when no escape layer is above
/// \note _UNCOMPRESSED label is associated to the top of the stack
/// \note _CLEAR is associated to the generic_thread below compressor else escape else
/// the cache or crypto_sym or scrambler which then has two Labels (_CLEAR and _UNCYPHERED)
extern void macro_tools_open_archive(const std::shared_ptr & dialog, ///< for user interaction
const std::shared_ptr & where, ///< slices location
const std::string &basename, ///< slice basename
const infinint & min_digits, ///< minimum digits for the slice number
const std::string &extension, ///< slice extensions
crypto_algo crypto, ///< encryption algorithm
const secu_string &pass, ///< pass key for crypto/scrambling
U_32 crypto_size, ///< crypto block size
pile & stack, ///< the stack of generic_file resulting of the archive openning
header_version &ver, ///< header read from raw data
const std::string &input_pipe, ///< named pipe for input when basename is "-" (dar_slave)
const std::string &output_pipe, ///< named pipe for output when basename is "-" (dar_slave)
const std::string & execute, ///< command to execute between slices
infinint & second_terminateur_offset, ///< where to start looking for the second terminateur (set to zero if there is only one terminateur).
bool lax, ///< whether we skip&warn the usual verifications
bool has_external_cat, ///< true if the catalogue will not be read from the current archive (flag used in lax mode only)
bool sequential_read, ///< whether to use the escape sequence (if present) to get archive contents and proceed to sequential reading
bool info_details, ///< be or not verbose about the archive openning
std::list & gnupg_signed, ///< list of existing signature found for that archive (valid or not)
slice_layout & sl, ///< slicing layout of the archive (read from sar header if present)
U_I multi_threaded_crypto, ///< number of worker thread to run for cryptography (1 -> tronconneuse object, more -> parallel_tronconneuse object)
U_I multi_threaded_compress, ///< number of worker threads to compress/decompress (need compression_block_size > 0)
bool header_only ///< if true, stop the process before openning the encryption layer
);
// all allocated objects (ret1, ret2, scram), must be deleted when no more needed by the caller of this routine
/// uses terminator to skip to the position where to find the catalogue and read it, taking care of having this catalogue pointing to the real data (context of isolated catalogue --- cata_stack --- used to rescue an internal archive --- data_stack)
extern catalogue *macro_tools_get_derivated_catalogue_from(const std::shared_ptr & dialog,
pile & data_stack, // where to get the files and EA from
pile & cata_stack, // where to get the catalogue from
const header_version & ver, // version format as defined in the header of the archive to read
bool info_details, // verbose display (throught user_interaction)
infinint &cat_size, // return size of archive in file (not in memory !)
const infinint & second_terminateur_offset, // location of the second terminateur (zero if none exist)
std::list & signatories, // returns the list of signatories (empty if archive is was not signed)
bool lax_mode); // whether to do relaxed checkings
/// uses terminator to skip to the position where to find the catalogue and read it
extern catalogue *macro_tools_get_catalogue_from(const std::shared_ptr & dialog,
pile & stack, // raw data access object
const header_version & ver, // version format as defined in the header of the archive to read
bool info_details, // verbose display (throught user_interaction)
infinint &cat_size, // return size of archive in file (not in memory !)
const infinint & second_terminateur_offset,
std::list & signatories, // returns the list of signatories (empty if archive is was not signed)
bool lax_mode);
/// read the catalogue from cata_stack assuming the cata_stack is positionned at the beginning of the area containing archive's dumped data
extern catalogue *macro_tools_read_catalogue(const std::shared_ptr & dialog,
const header_version & ver,
const pile_descriptor & cata_pdesc,
const infinint & cat_size,
std::list & signatories,
bool lax_mode,
const label & lax_layer1_data_name,
bool only_detruits);
extern catalogue *macro_tools_lax_search_catalogue(const std::shared_ptr & dialog,
pile & stack,
const archive_version & edition,
compression compr_algo,
bool info_details,
bool even_partial_catalogues,
const label & layer1_data_name);
// return the offset of the beginning of the catalogue.
extern infinint macro_tools_get_terminator_start(generic_file & f, const archive_version & reading_ver);
/// build layers for a new archive
/// \param[in] dialog for user interaction
/// \param[out] layers the resulting stack of generic_file layers ready for use
/// \param[out] ver the archive "header/trailer" to be dropped at beginning and end of archive
/// \param[out] slicing slicing layout of the created archive (resulting from sar layers if present according to the provided first/file_size provided below)
/// \param[in] ref_slicing if not nullptr the pointed to slicing_layout will be stored in the header/trailer version of the archive
/// \param[in] sauv_path_t where to create the archive
/// \param[in] filename archive base name
/// \param[in] extension archive extension
/// \param[in] allow_over whether to allow slice overwriting
/// \param[in] warn_over whether to warn before overwriting
/// \param[in] info_details whether to display detailed information
/// \param[in] pause how many slices to wait before pausing (0 to never wait)
/// \param[in] algo compression algorithm
/// \param[in] compression_level compression level
/// \param[in] compression_block_size if set to zero use streaming compression else use block compression of the given size
/// \param[in] file_size size of the slices
/// \param[in] first_file_size size of the first slice
/// \param[in] execute command to execute after each slice creation
/// \param[in] crypto cipher algorithm to use
/// \param[in] pass password/passphrase to use for encryption
/// \param[in] crypto_size size of crypto blocks
/// \param[in] gnupg_recipients list of email recipients'public keys to encrypt a randomly chosen key with
/// \param[in] gnupg_signatories list of email which associated signature has to be used to sign the archive
/// \param[in] empty dry-run execution (null_file at bottom of the stack)
/// \param[in] slice_permission permission to set the slices to
/// \param[in] add_marks_for_sequential_reading whether to add an escape layer in the stack
/// \param[in] user_comment user comment to add into the slice header/trailer
/// \param[in] hash algorithm to use for slices hashing
/// \param[in] slice_min_digits minimum number of digits slice number must have
/// \param[in] internal_name common label to all slices
/// \param[in] data_name to use in slice header
/// \param[in] iteration_count used for key derivation when passphrase is human provided
/// \param[in] kdf_hash hash algorithm used for the key derivation function
/// \param[in] multi_threaded_crypto number of worker threads to handle cryptography stuff
/// \param[in] multi_threaded_compress number of worker threads to handle compression (block mode only)
///
/// \note the stack has the following contents depending on given options
///
/// +-top LIBDAR_STACK_LABEL_
/// +---------------------------------------------------------+---------------------+
/// | compressor | |
/// +---------------------------------------------------------+---------------------+
/// | [ escape ] | |
/// +-- - - - - - - - - - - - - - - - - - - - - - - - - - - - +---------------------+
/// | cache | (paralle_)tronconneuse | scrambler | |
/// | [ cache ] |_CACHE_PIPE |
/// | trivial_sar | null_file | sar | |
/// +---------------------------------------------------------+---------------------+
/// +-bottom
///
/// \note the bottom cache layer is only present when trivial_sar is used to write on a pipe.
/// trivial_sar used to write a non sliced archive does not use a cache layer above it
/// \note the top cache is only used in place of crypto_sym or scrambler when no encryption
/// is required and the cache layer labelled _CACHE_PIPE is absent.
/// \note escape layer is present by default unless tape marks have been disabled
/// \note the generic_thread are inserted in the stack if multi-threading is possible and allowed
///
extern void macro_tools_create_layers(const std::shared_ptr & dialog,
pile & layers,
header_version & ver,
slice_layout & slicing,
const slice_layout *ref_slicing,
const std::shared_ptr & sauv_path_t,
const std::string & filename,
const std::string & extension,
bool allow_over,
bool warn_over,
bool info_details,
const infinint & pause,
compression algo,
U_I compression_level,
U_I compression_block_size,
const infinint & file_size,
const infinint & first_file_size,
const std::string & execute,
crypto_algo crypto,
const secu_string & pass,
U_32 crypto_size,
const std::vector & gnupg_recipients,
const std::vector & gnupg_signatories,
bool empty,
const std::string & slice_permission,
bool add_marks_for_sequential_reading,
const std::string & user_comment,
hash_algo hash,
const infinint & slice_min_digits,
const label & internal_name,
const label & data_name,
const infinint & iteration_count,
hash_algo kdf_hash,
U_I multi_threaded_crypto,
U_I multi_threaded_compress);
/// dumps the catalogue and close all the archive layers to terminate the archive
/// \param[in] dialog for user interaction
/// \param[in] layers the archive layers to close
/// \param[in] ver the archive "header" to be dropped at end of archive
/// \param[in] cat the catalogue to dump in the layer before closing the archive
/// \param[in] info_details whether to display detailed information
/// \param[in] crypto cipher algorithm used in "layers"
/// \param[in] gnupg_recipients used sign the catalog, use an empty vector if there is no signatories (no nedd to sign the hash of the catalogue)
/// \param[in] gnupg_signatories used to sign the catalog, use an empty vector to disable signning
/// \param[in] algo compression algorithm used
/// \param[in] empty dry-run execution (null_file at bottom of the stack)
extern void macro_tools_close_layers(const std::shared_ptr & dialog,
pile & layers,
const header_version & ver,
const catalogue & cat,
bool info_details,
crypto_algo crypto,
compression algo,
const std::vector & gnupg_recipients,
const std::vector & gnupg_signatories,
bool empty);
/// gives the location of data EA and FSA (when they are saved) of the object given in argument
/// \param[in] obj a pointer to the object which data & EFSA is to be located
/// \param[in] sl slice layout of the archive
/// \return a set of slices which will be required to restore that particular file (over the slice(s)
/// containing the catalogue of course).
extern range macro_tools_get_slices(const cat_nomme *obj, slice_layout sl);
/// open a pair of tuyau objects encapsulating two named pipes.
/// \param[in,out] dialog for user interaction
/// \param[in] input path to the input named pipe
/// \param[in] output path to the output named pipe
/// \param[out] in resulting tuyau object for input
/// \param[out] out resulting tuyau object for output
/// \note in and out parameters must be released by the caller thanks to the "delete" operator
extern void macro_tools_open_pipes(const std::shared_ptr & dialog,
const std::string &input,
const std::string & output,
tuyau *&in,
tuyau *&out);
/// return a proto_compressor object realizing the desired (de)compression level/aglo on top of "base" in streaming mode
/// \param[in] algo the compression algorithm to use
/// \param[in,out] base the layer to read from or write to compressed data
/// \param[in] compression_level the compression level to use (when compressing data)
/// \param[in] num_workers for the few algorithm that allow multi-thread compression (lz4 actually)
extern proto_compressor* macro_tools_build_streaming_compressor(compression algo,
generic_file & base,
U_I compression_level,
U_I num_workers);
/// return a proto_compressor object realizing the desired (de)compression level/algo on to of "base" in block mode
/// \param[in] algo the compression algorithm to use
/// \param[in,out] base the layer to read from or write to compressed data
/// \param[in] compression_level the compression level to use (when compressing data)
/// \param[in] num_workers for the few algorithm that allow multi-thread compression (lz4 actually)
/// \param[in] block_size size of the data block
extern proto_compressor* macro_tools_build_block_compressor(compression algo,
generic_file & base,
U_I compression_level,
U_I num_workers,
U_I block_size);
/// @}
} // end of namespace
#endif
dar-2.7.15/src/libdar/user_interaction_blind.hpp 0000644 0001750 0001750 00000005114 14636066467 016602 0000000 0000000 /*********************************************************************/
// dar - disk archive - a backup/restoration program
// Copyright (C) 2002-2024 Denis Corbin
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// to contact the author, see the AUTHOR file
/*********************************************************************/
/// \file user_interaction_blind.hpp
/// \brief defines the interaction between libdar and a non communcant "blind" user
/// \note yes blind people do communicate, no offense to them, this class just
/// "blindly" answer and do never show messages to a particular user
/// \ingroup API
#ifndef USER_INTERACTION_BLIND_HPP
#define USER_INTERACTION_BLIND_HPP
#include "../my_config.h"
#include
#include "user_interaction.hpp"
#include "secu_string.hpp"
namespace libdar
{
/// \addtogroup API
/// @{
/// full implementation class for user_interaction, which shows nothing and assumes answer "no" to any question
class user_interaction_blind : public user_interaction
{
public:
user_interaction_blind() {};
user_interaction_blind(const user_interaction_blind & ref) = default;
user_interaction_blind(user_interaction_blind && ref) noexcept = default;
user_interaction_blind & operator = (const user_interaction_blind & ref) = default;
user_interaction_blind & operator = (user_interaction_blind && ref) noexcept = default;
~user_interaction_blind() = default;
protected:
virtual void inherited_message(const std::string & message) override { }; // do nothing
virtual bool inherited_pause(const std::string & message) override { return false; };
virtual std::string inherited_get_string(const std::string & message, bool echo) override { return "user_interaction_blind, is blindly answering no"; };
virtual secu_string inherited_get_secu_string(const std::string & message, bool echo) override { return secu_string(); };
};
/// @}
} // end of namespace
#endif
dar-2.7.15/src/libdar/archive5.cpp 0000644 0001750 0001750 00000005640 14636067146 013555 0000000 0000000 /*********************************************************************/
// dar - disk archive - a backup/restoration program
// Copyright (C) 2002-2024 Denis Corbin
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// to contact the author, see the AUTHOR file
/*********************************************************************/
#include "../my_config.h"
extern "C"
{
#if HAVE_UNISTD_H
#include
#endif
} // extern "C"
#include "archive5.hpp"
#include "erreurs.hpp"
#include "shell_interaction_emulator.hpp"
#define ARCHIVE_NOT_EXPLOITABLE "Archive of reference given is not exploitable"
using namespace std;
using libdar::Erange;
using libdar::Ebug;
namespace libdar5
{
void archive::op_listing(user_interaction & dialog,
const archive_options_listing & options)
{
libdar::shell_interaction_emulator emul(&dialog);
emul.archive_show_contents(*this, options);
}
bool archive::get_children_of(user_interaction & dialog,
const std::string & dir)
{
if(!dialog.get_use_listing())
throw Erange("archive::get_childen_of", gettext("listing() method must be given"));
return libdar::archive::get_children_of(listing_callback,
&dialog,
dir);
}
void archive::listing_callback(const string & the_path,
const libdar::list_entry & entry,
void *context)
{
user_interaction *dialog = (user_interaction *)(context);
const std::string & flag =
entry.get_data_flag()
+ entry.get_delta_flag()
+ entry.get_ea_flag()
+ entry.get_fsa_flag()
+ entry.get_compression_ratio_flag()
+ entry.get_sparse_flag();
const std::string & perm = entry.get_perm();
const std::string & uid = entry.get_uid(true);
const std::string & gid = entry.get_gid(true);
const std::string & size = entry.get_file_size(true); //<<<<< listing sizes in bytes
const std::string & date = entry.get_last_modif();
const std::string & filename = entry.get_name();
bool is_dir = entry.is_dir();
bool has_children = !entry.is_empty_dir();
if(dialog == nullptr)
throw SRC_BUG;
if(dialog->get_use_listing())
dialog->listing(flag,
perm,
uid,
gid,
size,
date,
filename,
is_dir,
has_children);
else
throw SRC_BUG;
}
} // end of namespace
dar-2.7.15/src/libdar/filesystem_diff.cpp 0000644 0001750 0001750 00000014250 14636066467 015225 0000000 0000000 /*********************************************************************/
// dar - disk archive - a backup/restoration program
// Copyright (C) 2002-2024 Denis Corbin
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// to contact the author, see the AUTHOR file
/*********************************************************************/
#include "../my_config.h"
extern "C"
{
#if HAVE_STRING_H
#include
#endif
#if HAVE_STRINGS_H
#include
#endif
#if STDC_HEADERS
# include
#else
# if !HAVE_STRCHR
# define strchr index
# define strrchr rindex
# endif
char *strchr (), *strrchr ();
# if !HAVE_MEMCPY
# define memcpy(d, s, n) bcopy ((s), (d), (n))
# define memmove(d, s, n) bcopy ((s), (d), (n))
# endif
#endif
#if HAVE_ERRNO_H
#include
#endif
#if HAVE_TIME_H
#include
#endif
#if HAVE_FCNTL_H
#include
#endif
#if HAVE_SYS_TYPES_H
#include
#endif
#if HAVE_SYS_SOCKET_H
#include
#endif
#if HAVE_SYS_UN_H
#include
#endif
#if HAVE_UNISTD_H
#include
#endif
#if STDC_HEADERS
#include
#endif
#ifdef LIBDAR_NODUMP_FEATURE
#if HAVE_SYS_IOCTL_H
#include
#endif
#if LIBDAR_NODUMP_FEATURE == NODUMP_LINUX
#include
#else
#if LIBDAR_NODUMP_FEATURE == NODUMP_EXT2FS
#include
#else
#error "unknown location of ext2_fs.h include file"
#endif
#endif
#endif
#if MAJOR_IN_MKDEV
#include
#if !defined(makedev) && defined(mkdev)
#define makedev(a,b) mkdev((a),(b))
#endif
#else
#if MAJOR_IN_SYSMACROS
#include
#endif
#endif
} // end extern "C"
#include