xfsdump-3.1.6+nmu1/0000755000000000000000000000000012643557274010770 5ustar xfsdump-3.1.6+nmu1/VERSION0000644000000000000000000000016312620476160012025 0ustar # # This file is used by configure to get version information # PKG_MAJOR=3 PKG_MINOR=1 PKG_REVISION=6 PKG_BUILD=1 xfsdump-3.1.6+nmu1/configure0000755000000000000000000154224612607344150012700 0ustar #! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for xfsdump 3.1.5. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" SHELL=${CONFIG_SHELL-/bin/sh} test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='xfsdump' PACKAGE_TARNAME='xfsdump' PACKAGE_VERSION='3.1.5' PACKAGE_STRING='xfsdump 3.1.5' PACKAGE_BUGREPORT='' PACKAGE_URL='' ac_unique_file="common/main.c" ac_default_prefix=/usr # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='LTLIBOBJS LIBOBJS have_zipped_manpages libattr libhdl libcurses enable_curses libpthread libuuid libdirsuffix rpmbuild RPMBUILD rpm_version rpm RPM xgettext XGETTEXT msgmerge MSGMERGE msgfmt MSGFMT sort SORT echo ECHO sed awk makedepend zip ZIP tar TAR make MAKE cc pkg_platform pkg_distribution pkg_group pkg_user malloc_lib opt_build debug_build pkg_release pkg_version pkg_name LOCALIZED_FILES root_libdir root_sbindir enable_lib64 enable_gettext enable_shared CPP OTOOL64 OTOOL LIPO NMEDIT DSYMUTIL MANIFEST_TOOL AWK RANLIB STRIP ac_ct_AR AR DLLTOOL OBJDUMP LN_S NM ac_ct_DUMPBIN DUMPBIN LD FGREP EGREP GREP SED OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC host_os host_vendor host_cpu host build_os build_vendor build_cpu build LIBTOOL target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_shared enable_static with_pic enable_fast_install with_gnu_ld with_sysroot enable_libtool_lock enable_gettext enable_lib64 ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures xfsdump 3.1.5 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/xfsdump] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of xfsdump 3.1.5:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-shared[=PKGS] build shared libraries [default=yes] --enable-static[=PKGS] build static libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) --enable-shared=yes/no Enable use of shared libraries default=yes --enable-gettext=yes/no Enable alternate language support default=yes --enable-lib64=yes/no Enable lib64 support default=yes Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use both] --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-sysroot=DIR Search for dependent libraries within DIR (or the compiler's sysroot if not specified). Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF xfsdump configure 3.1.5 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by xfsdump $as_me 3.1.5, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_aux_dir= for ac_dir in . "$srcdir"/.; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in . \"$srcdir\"/." "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. ac_config_headers="$ac_config_headers include/config.h" case `pwd` in *\ * | *\ *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 $as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; esac macro_version='2.4.2' macro_revision='1.3337' ltmain="$ac_aux_dir/ltmain.sh" # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac # Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\(["`$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 $as_echo_n "checking how to print strings... " >&6; } # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "" } case "$ECHO" in printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 $as_echo "printf" >&6; } ;; print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 $as_echo "print -r" >&6; } ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 $as_echo "cat" >&6; } ;; esac ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 $as_echo_n "checking for a sed that does not truncate output... " >&6; } if ${ac_cv_path_SED+:} false; then : $as_echo_n "(cached) " >&6 else ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for ac_i in 1 2 3 4 5 6 7; do ac_script="$ac_script$as_nl$ac_script" done echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed { ac_script=; unset ac_script;} if test -z "$SED"; then ac_path_SED_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_SED" || continue # Check for GNU ac_path_SED and select it if it is found. # Check for GNU $ac_path_SED case `"$ac_path_SED" --version 2>&1` in *GNU*) ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo '' >> "conftest.nl" "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_SED_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_SED="$ac_path_SED" ac_path_SED_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_SED_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_SED"; then as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 fi else ac_cv_path_SED=$SED fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 $as_echo "$ac_cv_path_SED" >&6; } SED="$ac_cv_path_SED" rm -f conftest.sed test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 $as_echo_n "checking for fgrep... " >&6; } if ${ac_cv_path_FGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 then ac_cv_path_FGREP="$GREP -F" else if test -z "$FGREP"; then ac_path_FGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in fgrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_FGREP" || continue # Check for GNU ac_path_FGREP and select it if it is found. # Check for GNU $ac_path_FGREP case `"$ac_path_FGREP" --version 2>&1` in *GNU*) ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'FGREP' >> "conftest.nl" "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_FGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_FGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_FGREP"; then as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_FGREP=$FGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 $as_echo "$ac_cv_path_FGREP" >&6; } FGREP="$ac_cv_path_FGREP" test -z "$GREP" && GREP=grep # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if ${lt_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 $as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } if ${lt_cv_path_NM+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/$lt_tmp_nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS="$lt_save_ifs" done : ${lt_cv_path_NM=no} fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 $as_echo "$lt_cv_path_NM" >&6; } if test "$lt_cv_path_NM" != "no"; then NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else if test -n "$ac_tool_prefix"; then for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DUMPBIN"; then ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DUMPBIN=$ac_cv_prog_DUMPBIN if test -n "$DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 $as_echo "$DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$DUMPBIN" && break done fi if test -z "$DUMPBIN"; then ac_ct_DUMPBIN=$DUMPBIN for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DUMPBIN"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN if test -n "$ac_ct_DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 $as_echo "$ac_ct_DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_DUMPBIN" && break done if test "x$ac_ct_DUMPBIN" = x; then DUMPBIN=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DUMPBIN=$ac_ct_DUMPBIN fi fi case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols" ;; *) DUMPBIN=: ;; esac fi if test "$DUMPBIN" != ":"; then NM="$DUMPBIN" fi fi test -z "$NM" && NM=nm { $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 $as_echo_n "checking the name lister ($NM) interface... " >&6; } if ${lt_cv_nm_interface+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 $as_echo "$lt_cv_nm_interface" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi # find the maximum length of command line arguments { $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 $as_echo_n "checking the maximum length of command line arguments... " >&6; } if ${lt_cv_sys_max_cmd_len+:} false; then : $as_echo_n "(cached) " >&6 else i=0 teststring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8 ; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac fi if test -n $lt_cv_sys_max_cmd_len ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 $as_echo "$lt_cv_sys_max_cmd_len" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } fi max_cmd_len=$lt_cv_sys_max_cmd_len : ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 $as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ = c,a/b,b/c, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 $as_echo "$xsi_shell" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 $as_echo_n "checking whether the shell understands \"+=\"... " >&6; } lt_shell_append=no ( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ >/dev/null 2>&1 \ && lt_shell_append=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 $as_echo "$lt_shell_append" >&6; } if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 $as_echo_n "checking how to convert $build file names to $host format... " >&6; } if ${lt_cv_to_host_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac fi to_host_file_cmd=$lt_cv_to_host_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 $as_echo "$lt_cv_to_host_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 $as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } if ${lt_cv_to_tool_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else #assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac fi to_tool_file_cmd=$lt_cv_to_tool_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 $as_echo "$lt_cv_to_tool_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 $as_echo_n "checking for $LD option to reload object files... " >&6; } if ${lt_cv_ld_reload_flag+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_reload_flag='-r' fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 $as_echo "$lt_cv_ld_reload_flag" >&6; } reload_flag=$lt_cv_ld_reload_flag case $reload_flag in "" | " "*) ;; *) reload_flag=" $reload_flag" ;; esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in cygwin* | mingw* | pw32* | cegcc*) if test "$GCC" != yes; then reload_cmds=false fi ;; darwin*) if test "$GCC" = yes; then reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi ;; esac if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OBJDUMP"; then ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 $as_echo "$OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OBJDUMP"; then ac_ct_OBJDUMP=$OBJDUMP # Extract the first word of "objdump", so it can be a program name with args. set dummy objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OBJDUMP"; then ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OBJDUMP="objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 $as_echo "$ac_ct_OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OBJDUMP" = x; then OBJDUMP="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OBJDUMP=$ac_ct_OBJDUMP fi else OBJDUMP="$ac_cv_prog_OBJDUMP" fi test -z "$OBJDUMP" && OBJDUMP=objdump { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 $as_echo_n "checking how to recognize dependent libraries... " >&6; } if ${lt_cv_deplibs_check_method+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # `unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # which responds to the $file_magic_cmd with a given extended regex. # If you have `file' or equivalent on your system and you're not sure # whether `pass_all' will *always* work, you probably want this one. case $host_os in aix[4-9]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[45]*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[3-9]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 $as_echo "$lt_cv_deplibs_check_method" >&6; } file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. set dummy ${ac_tool_prefix}dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DLLTOOL"; then ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DLLTOOL=$ac_cv_prog_DLLTOOL if test -n "$DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 $as_echo "$DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DLLTOOL"; then ac_ct_DLLTOOL=$DLLTOOL # Extract the first word of "dlltool", so it can be a program name with args. set dummy dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DLLTOOL"; then ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DLLTOOL="dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL if test -n "$ac_ct_DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 $as_echo "$ac_ct_DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DLLTOOL" = x; then DLLTOOL="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DLLTOOL=$ac_ct_DLLTOOL fi else DLLTOOL="$ac_cv_prog_DLLTOOL" fi test -z "$DLLTOOL" && DLLTOOL=dlltool { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 $as_echo_n "checking how to associate runtime and link libraries... " >&6; } if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh # decide which to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd="$ECHO" ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 $as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO if test -n "$ac_tool_prefix"; then for ac_prog in ar do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AR" && break done fi if test -z "$AR"; then ac_ct_AR=$AR for ac_prog in ar do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_AR" && break done if test "x$ac_ct_AR" = x; then AR="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi fi : ${AR=ar} : ${AR_FLAGS=cru} { $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 $as_echo_n "checking for archiver @FILE support... " >&6; } if ${lt_cv_ar_at_file+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ar_at_file=no cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -eq 0; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -ne 0; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 $as_echo "$lt_cv_ar_at_file" >&6; } if test "x$lt_cv_ar_at_file" = xno; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi test -z "$STRIP" && STRIP=: if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi test -z "$RANLIB" && RANLIB=: # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Check for command to grab the raw symbol name followed by C symbol from nm. { $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 $as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } if ${lt_cv_sys_global_symbol_pipe+:} false; then : $as_echo_n "(cached) " >&6 else # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[BCDT]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[ABCDGISTW]' ;; hpux*) if test "$host_cpu" = ia64; then symcode='[ABCDEGRST]' fi ;; irix* | nonstopux*) symcode='[BCDEGRST]' ;; osf*) symcode='[BCDEGQRST]' ;; solaris*) symcode='[BDRT]' ;; sco3.2v5*) symcode='[DT]' ;; sysv4.2uw2*) symcode='[DT]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[ABDT]' ;; sysv4) symcode='[DFNSTU]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[ABCDGIRSTW]' ;; esac # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK '"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ " {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ " s[1]~/^[@?]/{print s[1], s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Now try to grab the symbols. nlist=conftest.nm if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&5 fi else echo "cannot find nm_test_var in $nlist" >&5 fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 fi else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done fi if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 $as_echo "failed" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then nm_file_list_spec='@' fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 $as_echo_n "checking for sysroot... " >&6; } # Check whether --with-sysroot was given. if test "${with_sysroot+set}" = set; then : withval=$with_sysroot; else with_sysroot=no fi lt_sysroot= case ${with_sysroot} in #( yes) if test "$GCC" = yes; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${with_sysroot}" >&5 $as_echo "${with_sysroot}" >&6; } as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 $as_echo "${lt_sysroot:-no}" >&6; } # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then : enableval=$enable_libtool_lock; fi test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `/usr/bin/file conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 $as_echo_n "checking whether the C compiler needs -belf... " >&6; } if ${lt_cv_cc_needs_belf+:} false; then : $as_echo_n "(cached) " >&6 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_cc_needs_belf=yes else lt_cv_cc_needs_belf=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 $as_echo "$lt_cv_cc_needs_belf" >&6; } if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; *-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD="${LD-ld}_sol2" fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks="$enable_libtool_lock" if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. set dummy ${ac_tool_prefix}mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$MANIFEST_TOOL"; then ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL if test -n "$MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 $as_echo "$MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_MANIFEST_TOOL"; then ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL # Extract the first word of "mt", so it can be a program name with args. set dummy mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_MANIFEST_TOOL"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL if test -n "$ac_ct_MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 $as_echo "$ac_ct_MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_MANIFEST_TOOL" = x; then MANIFEST_TOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL fi else MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" fi test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 $as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } if ${lt_cv_path_mainfest_tool+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&5 if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 $as_echo "$lt_cv_path_mainfest_tool" >&6; } if test "x$lt_cv_path_mainfest_tool" != xyes; then MANIFEST_TOOL=: fi case $host_os in rhapsody* | darwin*) if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DSYMUTIL"; then ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DSYMUTIL=$ac_cv_prog_DSYMUTIL if test -n "$DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 $as_echo "$DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DSYMUTIL"; then ac_ct_DSYMUTIL=$DSYMUTIL # Extract the first word of "dsymutil", so it can be a program name with args. set dummy dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DSYMUTIL"; then ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL if test -n "$ac_ct_DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 $as_echo "$ac_ct_DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DSYMUTIL" = x; then DSYMUTIL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DSYMUTIL=$ac_ct_DSYMUTIL fi else DSYMUTIL="$ac_cv_prog_DSYMUTIL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. set dummy ${ac_tool_prefix}nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NMEDIT"; then ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi NMEDIT=$ac_cv_prog_NMEDIT if test -n "$NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 $as_echo "$NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_NMEDIT"; then ac_ct_NMEDIT=$NMEDIT # Extract the first word of "nmedit", so it can be a program name with args. set dummy nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_NMEDIT"; then ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_NMEDIT="nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT if test -n "$ac_ct_NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 $as_echo "$ac_ct_NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_NMEDIT" = x; then NMEDIT=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac NMEDIT=$ac_ct_NMEDIT fi else NMEDIT="$ac_cv_prog_NMEDIT" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. set dummy ${ac_tool_prefix}lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$LIPO"; then ac_cv_prog_LIPO="$LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_LIPO="${ac_tool_prefix}lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi LIPO=$ac_cv_prog_LIPO if test -n "$LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 $as_echo "$LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_LIPO"; then ac_ct_LIPO=$LIPO # Extract the first word of "lipo", so it can be a program name with args. set dummy lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_LIPO"; then ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_LIPO="lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO if test -n "$ac_ct_LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 $as_echo "$ac_ct_LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_LIPO" = x; then LIPO=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac LIPO=$ac_ct_LIPO fi else LIPO="$ac_cv_prog_LIPO" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. set dummy ${ac_tool_prefix}otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL"; then ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL="${ac_tool_prefix}otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL=$ac_cv_prog_OTOOL if test -n "$OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 $as_echo "$OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL"; then ac_ct_OTOOL=$OTOOL # Extract the first word of "otool", so it can be a program name with args. set dummy otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL"; then ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL="otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL if test -n "$ac_ct_OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 $as_echo "$ac_ct_OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL" = x; then OTOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL=$ac_ct_OTOOL fi else OTOOL="$ac_cv_prog_OTOOL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. set dummy ${ac_tool_prefix}otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL64"; then ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL64=$ac_cv_prog_OTOOL64 if test -n "$OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 $as_echo "$OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL64"; then ac_ct_OTOOL64=$OTOOL64 # Extract the first word of "otool64", so it can be a program name with args. set dummy otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL64"; then ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL64="otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 if test -n "$ac_ct_OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 $as_echo "$ac_ct_OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL64" = x; then OTOOL64=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL64=$ac_ct_OTOOL64 fi else OTOOL64="$ac_cv_prog_OTOOL64" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 $as_echo_n "checking for -single_module linker flag... " >&6; } if ${lt_cv_apple_cc_single_mod+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_apple_cc_single_mod=no if test -z "${LT_MULTI_MODULE}"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&5 $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&5 # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test $_lt_result -eq 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&5 fi rm -rf libconftest.dylib* rm -f conftest.* fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 $as_echo "$lt_cv_apple_cc_single_mod" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 $as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } if ${lt_cv_ld_exported_symbols_list+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_ld_exported_symbols_list=yes else lt_cv_ld_exported_symbols_list=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 $as_echo "$lt_cv_ld_exported_symbols_list" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 $as_echo_n "checking for -force_load linker flag... " >&6; } if ${lt_cv_ld_force_load+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 echo "$AR cru libconftest.a conftest.o" >&5 $AR cru libconftest.a conftest.o 2>&5 echo "$RANLIB libconftest.a" >&5 $RANLIB libconftest.a 2>&5 cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&5 elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then lt_cv_ld_force_load=yes else cat conftest.err >&5 fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 $as_echo "$lt_cv_ld_force_load" >&6; } case $host_os in rhapsody* | darwin1.[012]) _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[91]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; 10.[012]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; then _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in dlfcn.h do : ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default " if test "x$ac_cv_header_dlfcn_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_DLFCN_H 1 _ACEOF fi done # Set options enable_dlopen=no enable_win32_dll=no # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then : enableval=$enable_shared; p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac else enable_shared=yes fi # Check whether --enable-static was given. if test "${enable_static+set}" = set; then : enableval=$enable_static; p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac else enable_static=yes fi # Check whether --with-pic was given. if test "${with_pic+set}" = set; then : withval=$with_pic; lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for lt_pkg in $withval; do IFS="$lt_save_ifs" if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS="$lt_save_ifs" ;; esac else pic_mode=default fi test -z "$pic_mode" && pic_mode=default # Check whether --enable-fast-install was given. if test "${enable_fast_install+set}" = set; then : enableval=$enable_fast_install; p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac else enable_fast_install=yes fi # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ltmain" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' test -z "$LN_S" && LN_S="ln -s" if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 $as_echo_n "checking for objdir... " >&6; } if ${lt_cv_objdir+:} false; then : $as_echo_n "(cached) " >&6 else rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 $as_echo "$lt_cv_objdir" >&6; } objdir=$lt_cv_objdir cat >>confdefs.h <<_ACEOF #define LT_OBJDIR "$lt_cv_objdir/" _ACEOF case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld="$lt_cv_prog_gnu_ld" old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 $as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/${ac_tool_prefix}file; then lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 $as_echo_n "checking for file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/file; then lt_cv_path_MAGIC_CMD="$ac_dir/file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else MAGIC_CMD=: fi fi fi ;; esac # Use C for the default configuration in the libtool script lt_save_CC="$CC" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o objext=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then lt_prog_compiler_no_builtin_flag= if test "$GCC" = yes; then case $cc_basename in nvcc*) lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; *) lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 $as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 $as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl= lt_prog_compiler_pic= lt_prog_compiler_static= if test "$GCC" = yes; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. lt_prog_compiler_static= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) lt_prog_compiler_pic='-fPIC' ;; esac ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic=-Kconform_pic fi ;; *) lt_prog_compiler_pic='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 lt_prog_compiler_wl='-Xlinker ' if test -n "$lt_prog_compiler_pic"; then lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; # Lahey Fortran 8.1. lf95*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='--shared' lt_prog_compiler_static='--static' ;; nagfor*) # NAG Fortran compiler lt_prog_compiler_wl='-Wl,-Wl,,' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; ccc*) lt_prog_compiler_wl='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-qpic' lt_prog_compiler_static='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='' ;; *Sun\ F* | *Sun*Fortran*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Wl,' ;; *Intel*\ [CF]*Compiler*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; *Portland\ Group*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; esac ;; esac ;; newsos6) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static='-non_shared' ;; rdos*) lt_prog_compiler_static='-non_shared' ;; solaris*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) lt_prog_compiler_wl='-Qoption ld ';; *) lt_prog_compiler_wl='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl='-Qoption ld ' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; unicos*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_can_build_shared=no ;; uts4*) lt_prog_compiler_pic='-pic' lt_prog_compiler_static='-Bstatic' ;; *) lt_prog_compiler_can_build_shared=no ;; esac fi case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; *) lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if ${lt_cv_prog_compiler_pic+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic=$lt_prog_compiler_pic fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 $as_echo "$lt_cv_prog_compiler_pic" >&6; } lt_prog_compiler_pic=$lt_cv_prog_compiler_pic # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } if ${lt_cv_prog_compiler_pic_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic -DPIC" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 $as_echo "$lt_cv_prog_compiler_pic_works" >&6; } if test x"$lt_cv_prog_compiler_pic_works" = xyes; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; esac else lt_prog_compiler_pic= lt_prog_compiler_can_build_shared=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if ${lt_cv_prog_compiler_static_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works=yes fi else lt_cv_prog_compiler_static_works=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 $as_echo "$lt_cv_prog_compiler_static_works" >&6; } if test x"$lt_cv_prog_compiler_static_works" = xyes; then : else lt_prog_compiler_static= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } hard_links="nottested" if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test "$hard_links" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } runpath_var= allow_undefined_flag= always_export_symbols=no archive_cmds= archive_expsym_cmds= compiler_needs_object=no enable_shared_with_static_runtimes=no export_dynamic_flag_spec= export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' hardcode_automatic=no hardcode_direct=no hardcode_direct_absolute=no hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_minus_L=no hardcode_shlibpath_var=unsupported inherit_rpath=no link_all_deplibs=unknown module_cmds= module_expsym_cmds= old_archive_from_new_cmds= old_archive_from_expsyms_cmds= thread_safe_flag_spec= whole_archive_flag_spec= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; linux* | k*bsd*-gnu | gnu*) link_all_deplibs=no ;; esac ld_shlibs=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test "$with_gnu_ld" = yes; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; *\ \(GNU\ Binutils\)\ [3-9]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test "$lt_use_gnu_ld_interface" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' export_dynamic_flag_spec='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec= fi supports_anon_versioning=no case `$LD -v 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' export_dynamic_flag_spec='${wl}--export-all-symbols' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs=no fi ;; haiku*) archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' link_all_deplibs=yes ;; interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test "$host_os" = linux-dietlibc; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test "$tmp_diet" = no then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 whole_archive_flag_spec= tmp_sharedflag='--shared' ;; xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi case $cc_basename in xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else ld_shlibs=no fi ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = no; then runpath_var= hardcode_libdir_flag_spec= export_dynamic_flag_spec= whole_archive_flag_spec= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix[4-9]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global # defined symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds='' hardcode_direct=yes hardcode_direct_absolute=yes hardcode_libdir_separator=':' link_all_deplibs=yes file_list_spec='${wl}-f,' if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi link_all_deplibs=no else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi export_dynamic_flag_spec='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an # empty executable. if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_="/usr/lib:/lib" fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_="/usr/lib:/lib" fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag=' ${wl}-bernotok' allow_undefined_flag=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec='$convenience' fi archive_cmds_need_lc=yes # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; bsdi[45]*) export_dynamic_flag_spec=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported always_export_symbols=yes file_list_spec='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, )='true' enable_shared_with_static_runtimes=yes exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib old_postinstall_cmds='chmod 644 $oldlib' postlink_cmds='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_from_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' enable_shared_with_static_runtimes=yes ;; esac ;; darwin* | rhapsody*) archive_cmds_need_lc=no hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported if test "$lt_cv_ld_force_load" = "yes"; then whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec='' fi link_all_deplibs=yes allow_undefined_flag="$_lt_dar_allow_undefined" case $cc_basename in ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=func_echo_all archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" else ld_shlibs=no fi ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9*) if test "$GCC" = yes; then archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes export_dynamic_flag_spec='${wl}-E' ;; hpux10*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 $as_echo_n "checking if $CC understands -b... " >&6; } if ${lt_cv_prog_compiler__b+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler__b=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -b" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler__b=yes fi else lt_cv_prog_compiler__b=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 $as_echo "$lt_cv_prog_compiler__b" >&6; } if test x"$lt_cv_prog_compiler__b" = xyes; then archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi ;; esac fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_direct=no hardcode_shlibpath_var=no ;; *) hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 $as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } if ${lt_cv_irix_exported_symbol+:} false; then : $as_echo_n "(cached) " >&6 else save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int foo (void) { return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_irix_exported_symbol=yes else lt_cv_irix_exported_symbol=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 $as_echo "$lt_cv_irix_exported_symbol" >&6; } if test "$lt_cv_irix_exported_symbol" = yes; then archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' fi else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: inherit_rpath=yes link_all_deplibs=yes ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; *nto* | *qnx*) ;; openbsd*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes hardcode_shlibpath_var=no hardcode_direct_absolute=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' else case $host_os in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-R$libdir' ;; *) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi archive_cmds_need_lc='no' hardcode_libdir_separator=: ;; solaris*) no_undefined_flag=' -z defs' if test "$GCC" = yes; then wlarc='${wl}' archive_cmds='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='${wl}' archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test "$GCC" = yes; then whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else whole_archive_flag_spec='-z allextract$convenience -z defaultextract' fi ;; esac link_all_deplibs=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) case $host_vendor in sni) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds='$CC -r -o $output$reload_objs' hardcode_direct=no ;; motorola) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag='${wl}-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag='${wl}-z,text' allow_undefined_flag='${wl}-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='${wl}-R,$libdir' hardcode_libdir_separator=':' link_all_deplibs=yes export_dynamic_flag_spec='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac if test x$host_vendor = xsni; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) export_dynamic_flag_spec='${wl}-Blargedynsym' ;; esac fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 $as_echo "$ld_shlibs" >&6; } test "$ld_shlibs" = no && can_build_shared=no with_gnu_ld=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc" in x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } if ${lt_cv_archive_cmds_need_lc+:} false; then : $as_echo_n "(cached) " >&6 else $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl pic_flag=$lt_prog_compiler_pic compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then lt_cv_archive_cmds_need_lc=no else lt_cv_archive_cmds_need_lc=yes fi allow_undefined_flag=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 $as_echo "$lt_cv_archive_cmds_need_lc" >&6; } archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } if test "$GCC" = yes; then case $host_os in darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;; *) lt_sed_strip_eq="s,=/,/,g" ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path/$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" else test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo="/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[lt_foo]++; } if (lt_freq[lt_foo] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's,/\([A-Za-z]:\),\1,g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[4-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' library_names_spec='${libname}.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec="$LIB" if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=yes sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[3-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH if ${lt_cv_shlibpath_overrides_runpath+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir fi shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || test -n "$runpath_var" || test "X$hardcode_automatic" = "Xyes" ; then # We can hardcode non-existent directories. if test "$hardcode_direct" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && test "$hardcode_minus_L" != no; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 $as_echo "$hardcode_action" >&6; } if test "$hardcode_action" = relink || test "$inherit_rpath" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes fi ;; *) ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" if test "x$ac_cv_func_shl_load" = xyes; then : lt_cv_dlopen="shl_load" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if ${ac_cv_lib_dld_shl_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_shl_load=yes else ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes; then : lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" else ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = xyes; then : lt_cv_dlopen="dlopen" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 $as_echo_n "checking for dlopen in -lsvld... " >&6; } if ${ac_cv_lib_svld_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_svld_dlopen=yes else ac_cv_lib_svld_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 $as_echo "$ac_cv_lib_svld_dlopen" >&6; } if test "x$ac_cv_lib_svld_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 $as_echo_n "checking for dld_link in -ldld... " >&6; } if ${ac_cv_lib_dld_dld_link+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dld_link (); int main () { return dld_link (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_dld_link=yes else ac_cv_lib_dld_dld_link=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 $as_echo "$ac_cv_lib_dld_dld_link" >&6; } if test "x$ac_cv_lib_dld_dld_link" = xyes; then : lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" fi fi fi fi fi fi ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 $as_echo_n "checking whether a program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 $as_echo "$lt_cv_dlopen_self" >&6; } if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self_static+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 $as_echo "$lt_cv_dlopen_self_static" >&6; } fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi striplib= old_striplib= { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 $as_echo_n "checking whether stripping libraries is possible... " >&6; } if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac fi # Report which library types will actually be built { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 $as_echo_n "checking if libtool supports shared libraries... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 $as_echo "$can_build_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 $as_echo_n "checking whether to build shared libraries... " >&6; } test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[4-9]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 $as_echo "$enable_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 $as_echo_n "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 $as_echo "$enable_static" >&6; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$lt_save_CC" ac_config_commands="$ac_config_commands libtool" # Only expand once: # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then : enableval=$enable_shared; else enable_shared=yes fi # Check whether --enable-gettext was given. if test "${enable_gettext+set}" = set; then : enableval=$enable_gettext; else enable_gettext=yes fi # Check whether --enable-lib64 was given. if test "${enable_lib64+set}" = set; then : enableval=$enable_lib64; else enable_lib64=yes fi # # If the user specified a libdir ending in lib64 do not append another # 64 to the library names. # base_libdir=`basename "$libdir"` case $base_libdir in lib64) enable_lib64=no esac # # Some important tools should be installed into the root partitions. # # Check whether exec_prefix=/usr: and install them to /sbin in that # case. If the user choses a different prefix assume he just wants # a local install for testing and not a system install. # case $exec_prefix:$prefix in NONE:NONE | NONE:/usr | /usr:*) root_sbindir='/sbin' root_libdir="/${base_libdir}" ;; *) root_sbindir="${sbindir}" root_libdir="${libdir}" ;; esac # Find localized files LOCALIZED_FILES="" for lfile in `find ${srcdir} -name '*.c' -type f || exit 1`; do LOCALIZED_FILES="$LOCALIZED_FILES \$(TOPDIR)/$lfile" done pkg_name="xfsdump" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu . ./VERSION pkg_version=${PKG_MAJOR}.${PKG_MINOR}.${PKG_REVISION} pkg_release=$PKG_BUILD test -z "$BUILD_VERSION" || pkg_release="$BUILD_VERSION" DEBUG=${DEBUG:-'-DDEBUG'} debug_build="$DEBUG" OPTIMIZER=${OPTIMIZER:-'-g -O2'} opt_build="$OPTIMIZER" MALLOCLIB=${MALLOCLIB:-''} malloc_lib="$MALLOCLIB" pkg_user=`id -u -n` test -z "$INSTALL_USER" || pkg_user="$INSTALL_USER" pkg_group=`id -g -n` test -z "$INSTALL_GROUP" || pkg_group="$INSTALL_GROUP" pkg_distribution=`uname -s` test -z "$DISTRIBUTION" || pkg_distribution="$DISTRIBUTION" pkg_platform=`uname -s | tr 'A-Z' 'a-z' | sed -e 's/irix64/irix/'` test -z "$PLATFORM" || pkg_platform="$PLATFORM" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cc="$CC" if test -z ""$cc""; then echo echo FATAL ERROR: cc does not seem to be installed. echo xfsdump cannot be built without a working C compiler installation. exit 1 fi if test -z "$MAKE"; then # Extract the first word of "gmake", so it can be a program name with args. set dummy gmake; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_MAKE+:} false; then : $as_echo_n "(cached) " >&6 else case $MAKE in [\\/]* | ?:[\\/]*) ac_cv_path_MAKE="$MAKE" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_dummy="/usr/bin:/usr/local/bin:/usr/freeware/bin" for as_dir in $as_dummy do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_MAKE="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi MAKE=$ac_cv_path_MAKE if test -n "$MAKE"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAKE" >&5 $as_echo "$MAKE" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$MAKE"; then # Extract the first word of "make", so it can be a program name with args. set dummy make; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_MAKE+:} false; then : $as_echo_n "(cached) " >&6 else case $MAKE in [\\/]* | ?:[\\/]*) ac_cv_path_MAKE="$MAKE" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /usr/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_MAKE="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi MAKE=$ac_cv_path_MAKE if test -n "$MAKE"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAKE" >&5 $as_echo "$MAKE" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi make=$MAKE if test -z ""$make""; then echo echo FATAL ERROR: make does not seem to be installed. echo xfsdump cannot be built without a working GNU make installation. exit 1 fi if test -z "$TAR"; then # Extract the first word of "tar", so it can be a program name with args. set dummy tar; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_TAR+:} false; then : $as_echo_n "(cached) " >&6 else case $TAR in [\\/]* | ?:[\\/]*) ac_cv_path_TAR="$TAR" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_dummy="/usr/freeware/bin:/bin:/usr/local/bin:/usr/bin" for as_dir in $as_dummy do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_TAR="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi TAR=$ac_cv_path_TAR if test -n "$TAR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $TAR" >&5 $as_echo "$TAR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi tar=$TAR if test -z "$ZIP"; then # Extract the first word of "gzip", so it can be a program name with args. set dummy gzip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ZIP+:} false; then : $as_echo_n "(cached) " >&6 else case $ZIP in [\\/]* | ?:[\\/]*) ac_cv_path_ZIP="$ZIP" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_dummy="/bin:/usr/bin:/usr/local/bin:/usr/freeware/bin" for as_dir in $as_dummy do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ZIP="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ZIP=$ac_cv_path_ZIP if test -n "$ZIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ZIP" >&5 $as_echo "$ZIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi zip=$ZIP { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether gcc -MM is supported" >&5 $as_echo_n "checking whether gcc -MM is supported... " >&6; } if ${ac_cv_gcc_nodeps+:} false; then : $as_echo_n "(cached) " >&6 else cat > conftest.c < int main() { exit(0); } EOF ac_cv_gcc_nodeps=no if ${CC} -MM conftest.c >/dev/null 2>&1; then ac_cv_gcc_nodeps=yes fi rm -f conftest.c a.out fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_gcc_nodeps" >&5 $as_echo "$ac_cv_gcc_nodeps" >&6; } makedepend="$cc -MM" if test $ac_cv_gcc_nodeps = no; then makedepend=/bin/true fi if test -z "$AWK"; then # Extract the first word of "awk", so it can be a program name with args. set dummy awk; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_AWK+:} false; then : $as_echo_n "(cached) " >&6 else case $AWK in [\\/]* | ?:[\\/]*) ac_cv_path_AWK="$AWK" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_dummy="/bin:/usr/bin" for as_dir in $as_dummy do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_AWK="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi AWK=$ac_cv_path_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi awk=$AWK if test -z "$SED"; then # Extract the first word of "sed", so it can be a program name with args. set dummy sed; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_SED+:} false; then : $as_echo_n "(cached) " >&6 else case $SED in [\\/]* | ?:[\\/]*) ac_cv_path_SED="$SED" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_dummy="/bin:/usr/bin" for as_dir in $as_dummy do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_SED="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi SED=$ac_cv_path_SED if test -n "$SED"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SED" >&5 $as_echo "$SED" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi sed=$SED if test -z "$ECHO"; then # Extract the first word of "echo", so it can be a program name with args. set dummy echo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ECHO+:} false; then : $as_echo_n "(cached) " >&6 else case $ECHO in [\\/]* | ?:[\\/]*) ac_cv_path_ECHO="$ECHO" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_dummy="/bin:/usr/bin" for as_dir in $as_dummy do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ECHO="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ECHO=$ac_cv_path_ECHO if test -n "$ECHO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ECHO" >&5 $as_echo "$ECHO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi echo=$ECHO if test -z "$SORT"; then # Extract the first word of "sort", so it can be a program name with args. set dummy sort; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_SORT+:} false; then : $as_echo_n "(cached) " >&6 else case $SORT in [\\/]* | ?:[\\/]*) ac_cv_path_SORT="$SORT" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_dummy="/bin:/usr/bin" for as_dir in $as_dummy do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_SORT="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi SORT=$ac_cv_path_SORT if test -n "$SORT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SORT" >&5 $as_echo "$SORT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi sort=$SORT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi if test "$enable_gettext" = yes; then if test -z "$MSGFMT"; then # Extract the first word of "msgfmt", so it can be a program name with args. set dummy msgfmt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_MSGFMT+:} false; then : $as_echo_n "(cached) " >&6 else case $MSGFMT in [\\/]* | ?:[\\/]*) ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_dummy="/usr/bin:/usr/local/bin:/usr/freeware/bin" for as_dir in $as_dummy do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_MSGFMT="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi MSGFMT=$ac_cv_path_MSGFMT if test -n "$MSGFMT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGFMT" >&5 $as_echo "$MSGFMT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi msgfmt=$MSGFMT if test -z ""$msgfmt""; then echo echo FATAL ERROR: msgfmt does not seem to be installed. echo xfsdump cannot be built without a working gettext installation. exit 1 fi if test -z "$MSGMERGE"; then # Extract the first word of "msgmerge", so it can be a program name with args. set dummy msgmerge; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_MSGMERGE+:} false; then : $as_echo_n "(cached) " >&6 else case $MSGMERGE in [\\/]* | ?:[\\/]*) ac_cv_path_MSGMERGE="$MSGMERGE" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_dummy="/usr/bin:/usr/local/bin:/usr/freeware/bin" for as_dir in $as_dummy do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_MSGMERGE="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi MSGMERGE=$ac_cv_path_MSGMERGE if test -n "$MSGMERGE"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGMERGE" >&5 $as_echo "$MSGMERGE" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi msgmerge=$MSGMERGE if test -z ""$msgmerge""; then echo echo FATAL ERROR: msgmerge does not seem to be installed. echo xfsdump cannot be built without a working gettext installation. exit 1 fi if test -z "$XGETTEXT"; then # Extract the first word of "xgettext", so it can be a program name with args. set dummy xgettext; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_XGETTEXT+:} false; then : $as_echo_n "(cached) " >&6 else case $XGETTEXT in [\\/]* | ?:[\\/]*) ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_dummy="/usr/bin:/usr/local/bin:/usr/freeware/bin" for as_dir in $as_dummy do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_XGETTEXT="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi XGETTEXT=$ac_cv_path_XGETTEXT if test -n "$XGETTEXT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XGETTEXT" >&5 $as_echo "$XGETTEXT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi xgettext=$XGETTEXT if test -z ""$xgettext""; then echo echo FATAL ERROR: xgettext does not seem to be installed. echo xfsdump cannot be built without a working gettext installation. exit 1 fi fi if test -z "$RPM"; then # Extract the first word of "rpm", so it can be a program name with args. set dummy rpm; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_RPM+:} false; then : $as_echo_n "(cached) " >&6 else case $RPM in [\\/]* | ?:[\\/]*) ac_cv_path_RPM="$RPM" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_dummy="/bin:/usr/bin:/usr/freeware/bin" for as_dir in $as_dummy do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_RPM="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi RPM=$ac_cv_path_RPM if test -n "$RPM"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RPM" >&5 $as_echo "$RPM" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi rpm=$RPM rpm_version=0 test -n "$RPM" && test -x "$RPM" && rpm_version=`$RPM --version \ | awk '{print $NF}' | awk -F. '{V=1; print $V}'` if test $rpm_version -ge 4; then # Extract the first word of "rpmbuild", so it can be a program name with args. set dummy rpmbuild; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_RPMBUILD+:} false; then : $as_echo_n "(cached) " >&6 else case $RPMBUILD in [\\/]* | ?:[\\/]*) ac_cv_path_RPMBUILD="$RPMBUILD" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_RPMBUILD="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi RPMBUILD=$ac_cv_path_RPMBUILD if test -n "$RPMBUILD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RPMBUILD" >&5 $as_echo "$RPMBUILD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rpmbuild=$RPMBUILD else rpmbuild=$RPM fi enable_lib64="$enable_lib64" libdirsuffix="" searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'` if test "$enable_lib64" = "yes" -a -n "$searchpath"; then save_IFS="${IFS= }"; IFS=":" for searchdir in $searchpath; do if test -d "$searchdir"; then case "$searchdir" in */lib64/ | */lib64 ) libdirsuffix=64 ;; *) searchdir=`cd "$searchdir" && pwd` case "$searchdir" in */lib64 ) libdirsuffix=64 ;; esac ;; esac fi done IFS="$save_IFS" fi for ac_header in uuid.h sys/uuid.h uuid/uuid.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done if test $ac_cv_header_uuid_h = no -a \ $ac_cv_header_sys_uuid_h = no -a \ $ac_cv_header_uuid_uuid_h = no; then echo echo 'FATAL ERROR: could not find a valid UUID header.' echo 'Install the Universally Unique Identifiers development package.' exit 1 fi for ac_func in uuid_compare do : ac_fn_c_check_func "$LINENO" "uuid_compare" "ac_cv_func_uuid_compare" if test "x$ac_cv_func_uuid_compare" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_UUID_COMPARE 1 _ACEOF fi done if test $ac_cv_func_uuid_compare = yes; then libuuid="" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_compare in -luuid" >&5 $as_echo_n "checking for uuid_compare in -luuid... " >&6; } if ${ac_cv_lib_uuid_uuid_compare+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-luuid $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char uuid_compare (); int main () { return uuid_compare (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_uuid_uuid_compare=yes else ac_cv_lib_uuid_uuid_compare=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_uuid_uuid_compare" >&5 $as_echo "$ac_cv_lib_uuid_uuid_compare" >&6; } if test "x$ac_cv_lib_uuid_uuid_compare" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBUUID 1 _ACEOF LIBS="-luuid $LIBS" else echo echo 'FATAL ERROR: could not find a valid UUID library.' echo 'Install the Universally Unique Identifiers library package.' exit 1 fi libuuid="-luuid" fi for ac_header in pthread.h do : ac_fn_c_check_header_mongrel "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default" if test "x$ac_cv_header_pthread_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_PTHREAD_H 1 _ACEOF fi done if test $ac_cv_header_pthread_h = no; then for ac_header in pthread.h do : ac_fn_c_check_header_mongrel "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default" if test "x$ac_cv_header_pthread_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_PTHREAD_H 1 _ACEOF else echo echo 'FATAL ERROR: could not find a valid pthread header.' exit 1 fi done fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthread" >&5 $as_echo_n "checking for pthread_mutex_init in -lpthread... " >&6; } if ${ac_cv_lib_pthread_pthread_mutex_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_mutex_init (); int main () { return pthread_mutex_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pthread_pthread_mutex_init=yes else ac_cv_lib_pthread_pthread_mutex_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_mutex_init" >&5 $as_echo "$ac_cv_lib_pthread_pthread_mutex_init" >&6; } if test "x$ac_cv_lib_pthread_pthread_mutex_init" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBPTHREAD 1 _ACEOF LIBS="-lpthread $LIBS" else echo echo 'FATAL ERROR: could not find a valid pthread library.' exit 1 fi libpthread=-lpthread for ac_header in ncurses.h do : ac_fn_c_check_header_mongrel "$LINENO" "ncurses.h" "ac_cv_header_ncurses_h" "$ac_includes_default" if test "x$ac_cv_header_ncurses_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_NCURSES_H 1 _ACEOF fi done if test "$ac_cv_header_ncurses_h" != yes; then echo echo 'FATAL ERROR: could not find a valid ncurses header.' echo 'Install the ncurses development package.' exit 1 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for initscr in -lncurses" >&5 $as_echo_n "checking for initscr in -lncurses... " >&6; } if ${ac_cv_lib_ncurses_initscr+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lncurses $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char initscr (); int main () { return initscr (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_ncurses_initscr=yes else ac_cv_lib_ncurses_initscr=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ncurses_initscr" >&5 $as_echo "$ac_cv_lib_ncurses_initscr" >&6; } if test "x$ac_cv_lib_ncurses_initscr" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBNCURSES 1 _ACEOF LIBS="-lncurses $LIBS" else echo echo 'FATAL ERROR: could not find a valid ncurses library.' echo 'Install the ncurses library package.' exit 1 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for bad glibc/ncurses header interaction" >&5 $as_echo_n "checking for bad glibc/ncurses header interaction... " >&6; } libcurses="-lncurses" LIBS="$LIBS $libcurses" CFLAGS="$CFLAGS -D_GNU_SOURCE" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { wgetch(stdscr); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : enable_curses=yes; { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } else enable_curses=no; libcurses=""; { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabling curses" >&5 $as_echo "disabling curses" >&6; } fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext for ac_header in xfs/xfs.h do : ac_fn_c_check_header_mongrel "$LINENO" "xfs/xfs.h" "ac_cv_header_xfs_xfs_h" "$ac_includes_default" if test "x$ac_cv_header_xfs_xfs_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_XFS_XFS_H 1 _ACEOF fi done if test "$ac_cv_header_xfs_xfs_h" != "yes"; then echo echo 'FATAL ERROR: cannot find a valid header file.' echo 'Install or upgrade the XFS development package.' echo 'Alternatively, run "make install-dev" from the xfsprogs source.' exit 1 fi for ac_header in xfs/handle.h do : ac_fn_c_check_header_mongrel "$LINENO" "xfs/handle.h" "ac_cv_header_xfs_handle_h" "$ac_includes_default" if test "x$ac_cv_header_xfs_handle_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_XFS_HANDLE_H 1 _ACEOF fi done if test "$ac_cv_header_xfs_handle_h" != "yes"; then echo echo 'FATAL ERROR: cannot find a valid header file.' echo 'Install or upgrade the XFS development package.' echo 'Alternatively, run "make install-dev" from the xfsprogs source.' exit 1 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for open_by_fshandle in -lhandle" >&5 $as_echo_n "checking for open_by_fshandle in -lhandle... " >&6; } if ${ac_cv_lib_handle_open_by_fshandle+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lhandle $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char open_by_fshandle (); int main () { return open_by_fshandle (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_handle_open_by_fshandle=yes else ac_cv_lib_handle_open_by_fshandle=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_handle_open_by_fshandle" >&5 $as_echo "$ac_cv_lib_handle_open_by_fshandle" >&6; } if test "x$ac_cv_lib_handle_open_by_fshandle" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBHANDLE 1 _ACEOF LIBS="-lhandle $LIBS" else echo echo 'FATAL ERROR: could not find a current XFS handle library.' echo 'Install or upgrade the XFS library package.' echo 'Alternatively, run "make install-dev" from the xfsprogs source.' exit 1 fi libhdl="-lhandle" test -f `pwd`/../xfsprogs/libhandle/libhandle.la && \ libhdl="`pwd`/../xfsprogs/libhandle/libhandle.la" test -f ${libexecdir}${libdirsuffix}/libhandle.la && \ libhdl="${libexecdir}${libdirsuffix}/libhandle.la" have_attributes_h=false for ac_header in attr/attributes.h sys/attributes.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF have_attributes_h=true fi done if test "$have_attributes_h" = "false"; then echo echo 'FATAL ERROR: attributes.h does not exist.' echo 'Install the extended attributes (attr) development package.' echo 'Alternatively, run "make install-dev" from the attr source.' exit 1 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking macros in attr/attributes.h" >&5 $as_echo_n "checking macros in attr/attributes.h... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { int x = ATTR_SECURE; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : echo ok else echo echo 'FATAL ERROR: could not find a current attributes header.' echo 'Upgrade the extended attributes (attr) development package.' echo 'Alternatively, run "make install-dev" from the attr source.' exit 1 fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: checking for attr_get in -lattr" >&5 $as_echo_n "checking for attr_get in -lattr... " >&6; } if ${ac_cv_lib_attr_attr_get+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lattr $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char attr_get (); int main () { return attr_get (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_attr_attr_get=yes else ac_cv_lib_attr_attr_get=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_attr_attr_get" >&5 $as_echo "$ac_cv_lib_attr_attr_get" >&6; } if test "x$ac_cv_lib_attr_attr_get" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBATTR 1 _ACEOF LIBS="-lattr $LIBS" else echo echo 'FATAL ERROR: could not find a valid Extended Attributes library.' echo 'Install the extended attributes (attr) development package.' echo 'Alternatively, run "make install-lib" from the attr source.' exit 1 fi libattr="-lattr" test -f ${libexecdir}${libdirsuffix}/libattr.la && \ libattr="${libexecdir}${libdirsuffix}/libattr.la" have_zipped_manpages=false for d in ${prefix}/share/man ${prefix}/man ; do if test -f $d/man1/man.1.gz then have_zipped_manpages=true break fi done ac_config_files="$ac_config_files include/builddefs" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by xfsdump $as_me 3.1.5, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ xfsdump config.status 3.1.5 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`' hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } # Quote evaled strings. for var in SHELL \ ECHO \ PATH_SEPARATOR \ SED \ GREP \ EGREP \ FGREP \ LD \ NM \ LN_S \ lt_SP2NL \ lt_NL2SP \ reload_flag \ OBJDUMP \ deplibs_check_method \ file_magic_cmd \ file_magic_glob \ want_nocaseglob \ DLLTOOL \ sharedlib_from_linklib_cmd \ AR \ AR_FLAGS \ archiver_list_spec \ STRIP \ RANLIB \ CC \ CFLAGS \ compiler \ lt_cv_sys_global_symbol_pipe \ lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ nm_file_list_spec \ lt_prog_compiler_no_builtin_flag \ lt_prog_compiler_pic \ lt_prog_compiler_wl \ lt_prog_compiler_static \ lt_cv_prog_compiler_c_o \ need_locks \ MANIFEST_TOOL \ DSYMUTIL \ NMEDIT \ LIPO \ OTOOL \ OTOOL64 \ shrext_cmds \ export_dynamic_flag_spec \ whole_archive_flag_spec \ compiler_needs_object \ with_gnu_ld \ allow_undefined_flag \ no_undefined_flag \ hardcode_libdir_flag_spec \ hardcode_libdir_separator \ exclude_expsyms \ include_expsyms \ file_list_spec \ variables_saved_for_relink \ libname_spec \ library_names_spec \ soname_spec \ install_override_mode \ finish_eval \ old_striplib \ striplib; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in reload_cmds \ old_postinstall_cmds \ old_postuninstall_cmds \ old_archive_cmds \ extract_expsyms_cmds \ old_archive_from_new_cmds \ old_archive_from_expsyms_cmds \ archive_cmds \ archive_expsym_cmds \ module_cmds \ module_expsym_cmds \ export_symbols_cmds \ prelink_cmds \ postlink_cmds \ postinstall_cmds \ postuninstall_cmds \ finish_cmds \ sys_lib_search_path_spec \ sys_lib_dlsearch_path_spec; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done ac_aux_dir='$ac_aux_dir' xsi_shell='$xsi_shell' lt_shell_append='$lt_shell_append' # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi PACKAGE='$PACKAGE' VERSION='$VERSION' TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile' _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "include/config.h") CONFIG_HEADERS="$CONFIG_HEADERS include/config.h" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "include/builddefs") CONFIG_FILES="$CONFIG_FILES include/builddefs" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "libtool":C) # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi cfgfile="${ofile}T" trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. # # GNU Libtool 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. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool 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 GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, or # obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # The names of the tagged configurations supported by this script. available_tags="" # ### BEGIN LIBTOOL CONFIG # Which release of libtool.m4 was used? macro_version=$macro_version macro_revision=$macro_revision # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # What type of objects to build. pic_mode=$pic_mode # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # An echo program that protects backslashes. ECHO=$lt_ECHO # The PATH separator for the build system. PATH_SEPARATOR=$lt_PATH_SEPARATOR # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # A sed program that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="\$SED -e 1s/^X//" # A grep program that handles long lines. GREP=$lt_GREP # An ERE matcher. EGREP=$lt_EGREP # A literal string matcher. FGREP=$lt_FGREP # A BSD- or MS-compatible name lister. NM=$lt_NM # Whether we need soft or hard links. LN_S=$lt_LN_S # What is the maximum length of a command? max_cmd_len=$max_cmd_len # Object file suffix (normally "o"). objext=$ac_objext # Executable file suffix (normally ""). exeext=$exeext # whether the shell understands "unset". lt_unset=$lt_unset # turn spaces into newlines. SP2NL=$lt_lt_SP2NL # turn newlines into spaces. NL2SP=$lt_lt_NL2SP # convert \$build file names to \$host format. to_host_file_cmd=$lt_cv_to_host_file_cmd # convert \$build files to toolchain format. to_tool_file_cmd=$lt_cv_to_tool_file_cmd # An object symbol dumper. OBJDUMP=$lt_OBJDUMP # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method = "file_magic". file_magic_cmd=$lt_file_magic_cmd # How to find potential files when deplibs_check_method = "file_magic". file_magic_glob=$lt_file_magic_glob # Find potential files using nocaseglob when deplibs_check_method = "file_magic". want_nocaseglob=$lt_want_nocaseglob # DLL creation program. DLLTOOL=$lt_DLLTOOL # Command to associate shared and link libraries. sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd # The archiver. AR=$lt_AR # Flags to create an archive. AR_FLAGS=$lt_AR_FLAGS # How to feed a file listing to the archiver. archiver_list_spec=$lt_archiver_list_spec # A symbol stripping program. STRIP=$lt_STRIP # Commands used to install an old-style archive. RANLIB=$lt_RANLIB old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Whether to use a lock for old archive extraction. lock_old_archive_extraction=$lock_old_archive_extraction # A C compiler. LTCC=$lt_CC # LTCC compiler flags. LTCFLAGS=$lt_CFLAGS # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration. global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair. global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # Transform the output of nm in a C name address pair when lib prefix is needed. global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix # Specify filename containing input files for \$NM. nm_file_list_spec=$lt_nm_file_list_spec # The root where to search for dependent libraries,and in which our libraries should be installed. lt_sysroot=$lt_sysroot # The name of the directory that contains temporary libtool files. objdir=$objdir # Used to examine libraries when file_magic_cmd begins with "file". MAGIC_CMD=$MAGIC_CMD # Must we lock files when doing compilation? need_locks=$lt_need_locks # Manifest tool. MANIFEST_TOOL=$lt_MANIFEST_TOOL # Tool to manipulate archived DWARF debug symbol files on Mac OS X. DSYMUTIL=$lt_DSYMUTIL # Tool to change global to local symbols on Mac OS X. NMEDIT=$lt_NMEDIT # Tool to manipulate fat objects and archives on Mac OS X. LIPO=$lt_LIPO # ldd/readelf like tool for Mach-O binaries on Mac OS X. OTOOL=$lt_OTOOL # ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. OTOOL64=$lt_OTOOL64 # Old archive suffix (normally "a"). libext=$libext # Shared library suffix (normally ".so"). shrext_cmds=$lt_shrext_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Variables whose values should be saved in libtool wrapper scripts and # restored at link time. variables_saved_for_relink=$lt_variables_saved_for_relink # Do we need the "lib" prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Library versioning type. version_type=$version_type # Shared library runtime path variable. runpath_var=$runpath_var # Shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Permission mode override for installation of shared libraries. install_override_mode=$lt_install_override_mode # Command to use after installation of a shared archive. postinstall_cmds=$lt_postinstall_cmds # Command to use after uninstallation of a shared archive. postuninstall_cmds=$lt_postuninstall_cmds # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # As "finish_cmds", except a single script fragment to be evaled but # not shown. finish_eval=$lt_finish_eval # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Compile-time system search path for libraries. sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries. sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # The linker used to build libraries. LD=$lt_LD # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds # A language specific compiler. CC=$lt_compiler # Is the compiler the GNU compiler? with_gcc=$GCC # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds archive_expsym_cmds=$lt_archive_expsym_cmds # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds module_expsym_cmds=$lt_module_expsym_cmds # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \${shlibpath_var} if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms # Symbols that must always be exported. include_expsyms=$lt_include_expsyms # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds # Commands necessary for finishing linking programs. postlink_cmds=$lt_postlink_cmds # Specify filename containing input files. file_list_spec=$lt_file_list_spec # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # ### END LIBTOOL CONFIG _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac ltmain="$ac_aux_dir/ltmain.sh" # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) if test x"$xsi_shell" = xyes; then sed -e '/^func_dirname ()$/,/^} # func_dirname /c\ func_dirname ()\ {\ \ case ${1} in\ \ */*) func_dirname_result="${1%/*}${2}" ;;\ \ * ) func_dirname_result="${3}" ;;\ \ esac\ } # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_basename ()$/,/^} # func_basename /c\ func_basename ()\ {\ \ func_basename_result="${1##*/}"\ } # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\ func_dirname_and_basename ()\ {\ \ case ${1} in\ \ */*) func_dirname_result="${1%/*}${2}" ;;\ \ * ) func_dirname_result="${3}" ;;\ \ esac\ \ func_basename_result="${1##*/}"\ } # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_stripname ()$/,/^} # func_stripname /c\ func_stripname ()\ {\ \ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\ \ # positional parameters, so assign one to ordinary parameter first.\ \ func_stripname_result=${3}\ \ func_stripname_result=${func_stripname_result#"${1}"}\ \ func_stripname_result=${func_stripname_result%"${2}"}\ } # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\ func_split_long_opt ()\ {\ \ func_split_long_opt_name=${1%%=*}\ \ func_split_long_opt_arg=${1#*=}\ } # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\ func_split_short_opt ()\ {\ \ func_split_short_opt_arg=${1#??}\ \ func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\ } # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\ func_lo2o ()\ {\ \ case ${1} in\ \ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\ \ *) func_lo2o_result=${1} ;;\ \ esac\ } # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_xform ()$/,/^} # func_xform /c\ func_xform ()\ {\ func_xform_result=${1%.*}.lo\ } # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_arith ()$/,/^} # func_arith /c\ func_arith ()\ {\ func_arith_result=$(( $* ))\ } # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_len ()$/,/^} # func_len /c\ func_len ()\ {\ func_len_result=${#1}\ } # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$lt_shell_append" = xyes; then sed -e '/^func_append ()$/,/^} # func_append /c\ func_append ()\ {\ eval "${1}+=\\${2}"\ } # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\ func_append_quoted ()\ {\ \ func_quote_for_eval "${2}"\ \ eval "${1}+=\\\\ \\$func_quote_for_eval_result"\ } # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: # Save a `func_append' function call where possible by direct use of '+=' sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: else # Save a `func_append' function call even when '+=' is not available sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$_lt_function_replace_fail" = x":"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5 $as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;} fi mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi xfsdump-3.1.6+nmu1/README0000644000000000000000000000070412607344125011636 0ustar XFS Dump Tools README _____________________ See the file doc/INSTALL for build, installation and post- install configuration steps. Refer to the xfs(5) manual page for general XFS information and references to other XFS manual pages. For more information and details on how to contribute to the XFS project see the web pages at: http://oss.sgi.com/projects/xfs/ For more information on the build process, please refer to the doc/PORTING document. xfsdump-3.1.6+nmu1/release.sh0000755000000000000000000000123212607344125012732 0ustar #!/bin/bash # # Automate generation a new release # . ./VERSION version=${PKG_MAJOR}.${PKG_MINOR}.${PKG_REVISION} date=`date +"%-d %B %Y"` echo "Cleaning up" make realclean echo "Updating CHANGES" sed -e "s/${version}.*/${version} (${date})/" doc/CHANGES > doc/CHANGES.tmp && \ mv doc/CHANGES.tmp doc/CHANGES echo "Commiting CHANGES update to git" git commit -s -a -m "${version} release" echo "Tagging git repository" git tag -s -a -m "${version} release" v${version} echo "Making source tarball" make dist echo "Sign the source tarball" gpg --detach-sign xfsdump-${version}.tar.gz echo "Done. Please remember to push out tags using \"git push --tags\"" xfsdump-3.1.6+nmu1/aclocal.m40000644000000000000000000000214712607344150012617 0ustar # generated automatically by aclocal 1.15 -*- Autoconf -*- # Copyright (C) 1996-2014 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_include([m4/libtool.m4]) m4_include([m4/ltoptions.m4]) m4_include([m4/ltsugar.m4]) m4_include([m4/ltversion.m4]) m4_include([m4/lt~obsolete.m4]) m4_include([m4/manual_format.m4]) m4_include([m4/multilib.m4]) m4_include([m4/package_attrdev.m4]) m4_include([m4/package_globals.m4]) m4_include([m4/package_ncurses.m4]) m4_include([m4/package_pthread.m4]) m4_include([m4/package_utilies.m4]) m4_include([m4/package_uuiddev.m4]) m4_include([m4/package_xfslibs.m4]) xfsdump-3.1.6+nmu1/include/0000755000000000000000000000000012643557274012413 5ustar xfsdump-3.1.6+nmu1/include/swap.h0000644000000000000000000000364012607344125013526 0ustar /* * Copyright (c) 2006 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef SWAP_H #define SWAP_H #include #include #if __BYTE_ORDER == __BIG_ENDIAN #define XFS_NATIVE_HOST 1 #else #undef XFS_NATIVE_HOST #endif #define ARCH_NOCONVERT 1 #ifdef XFS_NATIVE_HOST #define ARCH_CONVERT ARCH_NOCONVERT #else #define ARCH_CONVERT 0 #endif #ifndef HAVE_SWABMACROS #define INT_SWAP16(type,var) ((typeof(type))(__swab16((__u16)(var)))) #define INT_SWAP32(type,var) ((typeof(type))(__swab32((__u32)(var)))) #define INT_SWAP64(type,var) ((typeof(type))(__swab64((__u64)(var)))) #endif #define INT_SWAP(type, var) \ ((sizeof(type) == 8) ? INT_SWAP64(type,var) : \ ((sizeof(type) == 4) ? INT_SWAP32(type,var) : \ ((sizeof(type) == 2) ? INT_SWAP16(type,var) : \ (var)))) #define INT_GET(ref,arch) \ (((arch) == ARCH_NOCONVERT) ? (ref) : INT_SWAP((ref),(ref))) #define INT_SET(ref,arch,valueref) \ (__builtin_constant_p(valueref) ? \ (void)( (ref) = ( ((arch) != ARCH_NOCONVERT) ? \ (INT_SWAP((ref),(valueref))) : (valueref)) ) : \ (void)( ((ref) = (valueref)), \ ( ((arch) != ARCH_NOCONVERT) ? \ (ref) = INT_SWAP((ref),(ref)) : 0 ) )) #define INT_XLATE(buf,p,dir,arch) \ ((dir > 0) ? ((p) = INT_GET((buf),(arch))) : INT_SET((buf),(arch),(p))) #endif /* SWAP_H */ xfsdump-3.1.6+nmu1/include/install-sh0000755000000000000000000001546112607344125014413 0ustar #! /bin/bash # # Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved. # # This script emulates bsd install and also recognises # two environment variables, with the following semantics :- # # $DIST_MANIFEST - if set, the name of the file to append manifest # information in the following format: # File : f mode owner group src target # Directory: d mode owner group target # Symlink : l linkval target # # $DIST_ROOT - if set, prepend to target # # The sematics of all combinations of these two variables # are as follows: # # $DIST_MANIFEST? $DIST_ROOT? | Copy? Append Manifest? # -----------------------------+-------------------------- # not set not set | yes no # not set set | yes no # set not set | no yes # set set | yes yes # _usage() { echo "Usage: $prog [-o owner] [-g group] [-m mode] -d directory" echo "or $prog [-D] [-o owner] [-g group] [-m mode] file directory/file" echo "or $prog [-o owner] [-g group] [-m mode] file [file ...] directory" echo "or $prog -S file target (creates \"target\" symlink)" echo "or $prog -T lt_arg [-o owner] [-g group] [-m mode] libtool.lai directory" echo "" echo "The \$DIST_MANIFEST and \$DIST_ROOT environment variables affect the" echo "behaviour of this command - see comments in the script." echo "The -D flag is only available for the second usage, and causes" echo "the target directory to be created before installing the file." echo "" exit 1 } _chown () { _st=255 if [ $# -eq 3 ] ; then chown $1:$2 $3 _st=$? if [ $_st -ne 0 ] ; then if [ $REAL_UID != '0' ] ; then if [ ! -f $DIST_ROOT/.chown.quiet ] ; then echo '===============================================' echo Ownership of files under ${DIST_ROOT:-/} echo cannot be changed echo '===============================================' if [ -n "$DIST_ROOT" ] ; then touch $DIST_ROOT/.chown.quiet fi fi _st=0 fi fi fi return $_st } _manifest () { echo $* | sed -e 's/\/\//\//g' >>${DIST_MANIFEST:-/dev/null} } prog=`basename $0` HERE=`pwd` dflag=false Dflag=false Sflag=false Tflag=false DIRMODE=755 FILEMODE=644 OWNER=`id -u` GROUP=`id -g` REAL_UID=$OWNER # default is to install and don't append manifest INSTALL=true MANIFEST=: : ${DIST_ROOT:=${DESTDIR}} [ -n "$DIST_MANIFEST" -a -z "$DIST_ROOT" ] && INSTALL=false [ -n "$DIST_MANIFEST" ] && MANIFEST="_manifest" [ $# -eq 0 ] && _usage if $INSTALL then CP=cp; LN=ln; MKDIR=mkdir; CHMOD=chmod; CHOWN=_chown else CP=true; LN=true; MKDIR=true; CHMOD=true; CHOWN=true fi [ -n "$DIST_ROOT" -a $REAL_UID -ne 0 ] && CHOWN=true while getopts "Dcm:d:S:o:g:T:" c $* do case $c in c) ;; g) GROUP=$OPTARG ;; o) OWNER=$OPTARG ;; m) DIRMODE=`expr $OPTARG` FILEMODE=$DIRMODE ;; D) Dflag=true ;; S) symlink=$OPTARG Sflag=true ;; d) dir=$DIST_ROOT/$OPTARG dflag=true ;; T) lt_install=$OPTARG Tflag=true ;; *) _usage ;; esac done shift `expr $OPTIND - 1` status=0 if $dflag then # # first usage # $MKDIR -p $dir status=$? if [ $status -eq 0 ] then $CHMOD $DIRMODE $dir status=$? fi if [ $status -eq 0 ] then $CHOWN $OWNER $GROUP $dir status=$? fi $MANIFEST d $DIRMODE $OWNER $GROUP ${dir#$DIST_ROOT} elif $Sflag then # # fourth usage (symlink) # if [ $# -ne 1 ] then _usage else target=$DIST_ROOT/$1 fi $LN -s -f $symlink $target status=$? $MANIFEST l $symlink ${target#$DIST_ROOT} elif $Tflag then # # -T (install libs built by libtool) # if [ $# -ne 2 ] then _usage else libtool_lai=$1 # source the libtool variables if [ ! -f $libtool_lai ] then echo "$prog: Unable to find libtool library file $libtool_lai" exit 2 fi . ./$libtool_lai target=$DIST_ROOT/$2 fi case $lt_install in so_dot_version) # Loop until we find libfoo.so.x.y.z, then break out. for solib in $library_names do # does it have enough parts? libfoo.so.x.y.z == 5 cnt=`echo "$solib" | sed -e 's/\./ /g' | wc -w` if [ $cnt -eq 5 ] then install_name=$target/$solib $CP $solib $install_name status=$? $MANIFEST f $FILEMODE $OWNER $GROUP $HERE/$solib ${install_name#$DIST_ROOT} break fi done ;; so_*) case $lt_install in so_dot_current) # ln -s libfoo.so.x.y.z to libfoo.so.x from_parts=5 # libfoo.so.x.y.z to_parts=3 # libfoo.so.x ;; so_base) # ln -s libfoo.so.x to libfoo.so from_parts=3 # libfoo.so.x to_parts=2 # libfoo.so ;; *) echo "$prog: -T $lt_install invalid" exit 2 ;; esac # Loop until we find the names, then break out. for solib in $library_names do # does it have enough parts? cnt=`echo "$solib" | sed -e 's/\./ /g' | wc -w` if [ $cnt -eq $from_parts ] then from_name=$solib elif [ $cnt -eq $to_parts ] then to_name=$solib fi if [ -n "$from_name" ] && [ -n "$to_name" ] then install_name=$target/$to_name $LN -s -f $from_name $install_name status=$? $MANIFEST l $from_name ${install_name#$DIST_ROOT} break fi done ;; old_lib) install_name=$target/$old_library $CP $old_library $install_name status=$? $MANIFEST f $FILEMODE $OWNER $GROUP $HERE/$old_library ${install_name#$DIST_ROOT} ;; *) echo "$prog: -T $lt_install invalid" exit 2 ;; esac case $lt_install in old_lib|so_dot_version) if [ $status -eq 0 ] then $CHMOD $FILEMODE $install_name $CHOWN $OWNER $GROUP $install_name fi ;; esac else list="" dir="" if [ $# -eq 2 ] then # # second usage # f=$1 dir=$DIST_ROOT/$2 if $Dflag then mkdir -p `dirname $dir` fi $CP $f $dir status=$? if [ $status -eq 0 ] then if [ -f $dir/$f ] then $CHMOD $FILEMODE $dir/$f status=$? if [ $status -eq 0 ] then $CHOWN $OWNER $GROUP $dir/$f status=$? fi $MANIFEST f $FILEMODE $OWNER $GROUP $HERE/$f ${dir#$DIST_ROOT}/$f else $CHMOD $FILEMODE $dir status=$? if [ $status -eq 0 ] then $CHOWN $OWNER $GROUP $dir status=$? fi $MANIFEST f $FILEMODE $OWNER $GROUP $HERE/$dir ${dir#$DIST_ROOT} fi fi else # # third usage # n=1 while [ $# -gt 0 ] do if [ $# -gt 1 ] then list="$list $1" else dir=$DIST_ROOT/$1 fi shift done # echo DIR=$dir list=\"$list\" for f in $list do $CP $f $dir status=$? if [ $status -eq 0 ] then $CHMOD $FILEMODE $dir/$f status=$? if [ $status -eq 0 ] then $CHOWN $OWNER $GROUP $dir/$f status=$? fi $MANIFEST f $FILEMODE $OWNER $GROUP $HERE/$f ${dir#$DIST_ROOT}/$f fi [ $status -ne 0 ] && break done fi fi exit $status xfsdump-3.1.6+nmu1/include/swab.h0000644000000000000000000001054112607344125013506 0ustar #ifndef SWAB_H #define SWAB_H /* casts are necessary for constants, because we never know how for sure * how U/UL/ULL map to __u16, __u32, __u64. At least not in a portable way. */ #define ___swab16(x) \ ({ \ __u16 __x = (x); \ ((__u16)( \ (((__u16)(__x) & (__u16)0x00ffU) << 8) | \ (((__u16)(__x) & (__u16)0xff00U) >> 8) )); \ }) #define ___swab32(x) \ ({ \ __u32 __x = (x); \ ((__u32)( \ (((__u32)(__x) & (__u32)0x000000ffUL) << 24) | \ (((__u32)(__x) & (__u32)0x0000ff00UL) << 8) | \ (((__u32)(__x) & (__u32)0x00ff0000UL) >> 8) | \ (((__u32)(__x) & (__u32)0xff000000UL) >> 24) )); \ }) #define ___swab64(x) \ ({ \ __u64 __x = (x); \ ((__u64)( \ (__u64)(((__u64)(__x) & (__u64)0x00000000000000ffULL) << 56) | \ (__u64)(((__u64)(__x) & (__u64)0x000000000000ff00ULL) << 40) | \ (__u64)(((__u64)(__x) & (__u64)0x0000000000ff0000ULL) << 24) | \ (__u64)(((__u64)(__x) & (__u64)0x00000000ff000000ULL) << 8) | \ (__u64)(((__u64)(__x) & (__u64)0x000000ff00000000ULL) >> 8) | \ (__u64)(((__u64)(__x) & (__u64)0x0000ff0000000000ULL) >> 24) | \ (__u64)(((__u64)(__x) & (__u64)0x00ff000000000000ULL) >> 40) | \ (__u64)(((__u64)(__x) & (__u64)0xff00000000000000ULL) >> 56) )); \ }) #define ___constant_swab16(x) \ ((__u16)( \ (((__u16)(x) & (__u16)0x00ffU) << 8) | \ (((__u16)(x) & (__u16)0xff00U) >> 8) )) #define ___constant_swab32(x) \ ((__u32)( \ (((__u32)(x) & (__u32)0x000000ffUL) << 24) | \ (((__u32)(x) & (__u32)0x0000ff00UL) << 8) | \ (((__u32)(x) & (__u32)0x00ff0000UL) >> 8) | \ (((__u32)(x) & (__u32)0xff000000UL) >> 24) )) #define ___constant_swab64(x) \ ((__u64)( \ (__u64)(((__u64)(x) & (__u64)0x00000000000000ffULL) << 56) | \ (__u64)(((__u64)(x) & (__u64)0x000000000000ff00ULL) << 40) | \ (__u64)(((__u64)(x) & (__u64)0x0000000000ff0000ULL) << 24) | \ (__u64)(((__u64)(x) & (__u64)0x00000000ff000000ULL) << 8) | \ (__u64)(((__u64)(x) & (__u64)0x000000ff00000000ULL) >> 8) | \ (__u64)(((__u64)(x) & (__u64)0x0000ff0000000000ULL) >> 24) | \ (__u64)(((__u64)(x) & (__u64)0x00ff000000000000ULL) >> 40) | \ (__u64)(((__u64)(x) & (__u64)0xff00000000000000ULL) >> 56) )) /* * provide defaults when no architecture-specific optimization is detected */ #ifndef __arch__swab16 # define __arch__swab16(x) ({ __u16 __tmp = (x) ; ___swab16(__tmp); }) #endif #ifndef __arch__swab32 # define __arch__swab32(x) ({ __u32 __tmp = (x) ; ___swab32(__tmp); }) #endif #ifndef __arch__swab64 # define __arch__swab64(x) ({ __u64 __tmp = (x) ; ___swab64(__tmp); }) #endif #ifndef __arch__swab16p # define __arch__swab16p(x) __arch__swab16(*(x)) #endif #ifndef __arch__swab32p # define __arch__swab32p(x) __arch__swab32(*(x)) #endif #ifndef __arch__swab64p # define __arch__swab64p(x) __arch__swab64(*(x)) #endif #ifndef __arch__swab16s # define __arch__swab16s(x) do { *(x) = __arch__swab16p((x)); } while (0) #endif #ifndef __arch__swab32s # define __arch__swab32s(x) do { *(x) = __arch__swab32p((x)); } while (0) #endif #ifndef __arch__swab64s # define __arch__swab64s(x) do { *(x) = __arch__swab64p((x)); } while (0) #endif /* * Allow constant folding */ # define __swab16(x) \ (__builtin_constant_p((__u16)(x)) ? \ ___swab16((x)) : \ __fswab16((x))) # define __swab32(x) \ (__builtin_constant_p((__u32)(x)) ? \ ___swab32((x)) : \ __fswab32((x))) # define __swab64(x) \ (__builtin_constant_p((__u64)(x)) ? \ ___swab64((x)) : \ __fswab64((x))) static __inline__ __u16 __fswab16(__u16 x) { return (__extension__ __arch__swab16(x)); } static __inline__ __u16 __swab16p(__u16 *x) { return (__extension__ __arch__swab16p(x)); } static __inline__ void __swab16s(__u16 *addr) { (__extension__ ({__arch__swab16s(addr);})); } static __inline__ __u32 __fswab32(__u32 x) { return (__extension__ __arch__swab32(x)); } static __inline__ __u32 __swab32p(__u32 *x) { return (__extension__ __arch__swab32p(x)); } static __inline__ void __swab32s(__u32 *addr) { (__extension__ ({__arch__swab32s(addr);})); } static __inline__ __u64 __fswab64(__u64 x) { # ifdef __SWAB_64_THRU_32__ __u32 h = x >> 32; __u32 l = x & ((1ULL<<32)-1); return (((__u64)__swab32(l)) << 32) | ((__u64)(__swab32(h))); # else return (__extension__ __arch__swab64(x)); # endif } static __inline__ __u64 __swab64p(__u64 *x) { return (__extension__ __arch__swab64p(x)); } static __inline__ void __swab64s(__u64 *addr) { (__extension__ ({__arch__swab64s(addr);})); } #endif /* SWAB_H */ xfsdump-3.1.6+nmu1/include/builddefs.in0000644000000000000000000000476612607344125014706 0ustar # # Copyright (c) 2002-2006 Silicon Graphics, Inc. All Rights Reserved. # # @configure_input@ # ifndef _BUILDDEFS_INCLUDED_ _BUILDDEFS_INCLUDED_ = 1 DEBUG = @debug_build@ OPTIMIZER = @opt_build@ MALLOCLIB = @malloc_lib@ LOADERFLAGS = @LDFLAGS@ CFLAGS = @CFLAGS@ LIBRMT = $(TOPDIR)/librmt/librmt.la LIBXFS = @libxfs@ LIBATTR = @libattr@ LIBPTHREAD = @libpthread@ LIBUUID = @libuuid@ LIBCURSES = @libcurses@ LIBHANDLE = @libhdl@ PKG_NAME = @pkg_name@ PKG_USER = @pkg_user@ PKG_GROUP = @pkg_group@ PKG_RELEASE = @pkg_release@ PKG_VERSION = @pkg_version@ PKG_PLATFORM = @pkg_platform@ PKG_DISTRIBUTION= @pkg_distribution@ prefix = @prefix@ exec_prefix = @exec_prefix@ datarootdir = @datarootdir@ top_builddir = @top_builddir@ PKG_SBIN_DIR = @sbindir@ PKG_ROOT_SBIN_DIR = @root_sbindir@ PKG_ROOT_LIB_DIR= @root_libdir@@libdirsuffix@ PKG_INC_DIR = @includedir@ PKG_MAN_DIR = @mandir@ PKG_DOC_DIR = @datadir@/doc/@pkg_name@ PKG_LOCALE_DIR = @datadir@/locale CC = @cc@ AWK = @awk@ SED = @sed@ TAR = @tar@ ZIP = @zip@ MAKE = @make@ ECHO = @echo@ SORT = @sort@ LN_S = @LN_S@ SHELL = @SHELL@ LIBTOOL = @LIBTOOL@ MAKEDEPEND = @makedepend@ MSGFMT = @msgfmt@ MSGMERGE = @msgmerge@ XGETTEXT = @xgettext@ LOCALIZED_FILES = @LOCALIZED_FILES@ RPM = @rpm@ RPMBUILD = @rpmbuild@ RPM_VERSION = @rpm_version@ ENABLE_CURSES = @enable_curses@ ENABLE_SHARED = @enable_shared@ ENABLE_GETTEXT = @enable_gettext@ HAVE_ZIPPED_MANPAGES = @have_zipped_manpages@ GCCFLAGS = -funsigned-char -fno-strict-aliasing -Wall # -Wbitwise -Wno-transparent-union -Wno-old-initializer -Wno-decl ifeq ($(PKG_PLATFORM),linux) PCFLAGS = -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 $(GCCFLAGS) DEPENDFLAGS = -D__linux__ endif ifeq ($(PKG_PLATFORM),darwin) PCFLAGS = -traditional-cpp $(GCCFLAGS) DEPENDFLAGS = -D__APPLE__ endif ifeq ($(PKG_PLATFORM),irix) PLDLIBS = -ldisk -lgen DEPENDFLAGS = -D__sgi__ endif ifeq ($(PKG_PLATFORM),freebsd) PLDLIBS = -L/usr/local/lib -lintl PCFLAGS = -I/usr/local/include $(GCCFLAGS) DEPENDFLAGS = -D__FreeBSD__ endif GCFLAGS = $(OPTIMIZER) $(DEBUG) \ -DVERSION=\"$(PKG_VERSION)\" -DLOCALEDIR=\"$(PKG_LOCALE_DIR)\" \ -DPACKAGE=\"$(PKG_NAME)\" -I$(TOPDIR)/include ifeq ($(ENABLE_GETTEXT),yes) GCFLAGS += -DENABLE_GETTEXT endif # First, Global, Platform, Local CFLAGS CFLAGS += $(FCFLAGS) $(GCFLAGS) $(PCFLAGS) $(LCFLAGS) include $(TOPDIR)/include/buildmacros endif # # For targets that should always be rebuilt, # define a target that is never up-to-date. # Targets needing this should depend on $(_FORCE) _FORCE = __force_build xfsdump-3.1.6+nmu1/include/Makefile0000644000000000000000000000042112607344125014035 0ustar # # Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = .. include $(TOPDIR)/include/builddefs HFILES = swab.h swap.h LSRCFILES = builddefs.in buildmacros buildrules config.h.in install-sh default install install-dev : include $(BUILDRULES) xfsdump-3.1.6+nmu1/include/buildrules0000644000000000000000000000412012607344125014472 0ustar # # Copyright (c) 1999, 2001-2003 Silicon Graphics, Inc. All Rights Reserved. # ifndef _BUILDRULES_INCLUDED_ _BUILDRULES_INCLUDED_ = 1 include $(TOPDIR)/include/builddefs clean clobber : $(addsuffix -clean,$(SUBDIRS)) @rm -f $(DIRT) .ltdep .dep @rm -fr $(DIRDIRT) %-clean: @echo "Cleaning $*" $(Q)$(MAKE) $(MAKEOPTS) -q -C $* clean || $(MAKE) $(MAKEOPTS) -C $* clean # Never blow away subdirs ifdef SUBDIRS .PRECIOUS: $(SUBDIRS) .PHONY: $(SUBDIRS) $(SUBDIRS): @echo "Building $@" $(Q)$(MAKE) $(MAKEOPTS) -q -C $@ || $(MAKE) $(MAKEOPTS) -C $@ endif # # Standard targets # ifdef LTCOMMAND $(LTCOMMAND) : $(SUBDIRS) $(OBJECTS) $(LTDEPENDENCIES) @echo " [LD] $@" $(Q)$(LTLINK) -o $@ $(LDFLAGS) $(OBJECTS) $(LDLIBS) endif ifdef LTLIBRARY $(LTLIBRARY) : $(SUBDIRS) $(LTOBJECTS) @echo " [LD] $@" $(Q)$(LTLINK) $(LTLDFLAGS) -o $(LTLIBRARY) $(LTOBJECTS) $(LTLIBS) %.lo: %.c @echo " [CC] $@" $(Q)$(LTCOMPILE) -c $< else %.o: %.c @echo " [CC] $@" $(Q)$(CC) $(CFLAGS) -c $< endif ifdef POTHEAD $(POTHEAD): $(XGETTEXTFILES) @echo " [GETTXT] $@" $(Q)$(XGETTEXT) --language=C --keyword=_ --keyword=N_ -o $@ $(XGETTEXTFILES) # Update translations update-po: $(POTHEAD) $(wildcard $(TOPDIR)/po/*.po) catalogs="$(wildcard $(TOPDIR)/po/*.po)"; \ for cat in $$catalogs; do \ lang=`basename $$cat .po`; \ mv $$lang.po $$lang.old.po; \ echo "$$lang:"; \ if $(MSGMERGE) $$lang.old.po $(POTHEAD) -o $$lang.po; then \ rm -f $$lang.old.po; \ else \ echo "msgmerge for $$lang failed!"; \ rm -f $$lang.po; \ mv $$lang.old.po $$lang.po; \ fi; \ done %.mo: %.po @echo " [MSGFMT] $@" $(Q)$(MSGFMT) -c --statistics -o $@ $< endif endif # _BUILDRULES_INCLUDED_ $(_FORCE): # dependency build is automatic, relies on gcc -MM to generate. .PHONY : depend ltdepend MAKEDEP := $(MAKEDEPEND) $(CFLAGS) ltdepend: .ltdep .ltdep: $(CFILES) $(HFILES) @echo " [LTDEP]" $(Q)$(MAKEDEP) $(CFILES) | $(SED) -e 's,^\([^:]*\)\.o,\1.lo,' > .ltdep depend: .dep .dep: $(CFILES) $(HFILES) @echo " [DEP]" $(Q)[ -n "$(CFILES)" ] && $(MAKEDEP) $(CFILES) > .dep xfsdump-3.1.6+nmu1/include/config.h.in0000644000000000000000000000261312620476160014425 0ustar /* * Copyright (c) 2002 Silicon Graphics, Inc. All Rights Reserved. * * @configure_input@ */ #ifndef __CONFIG_H__ #define __CONFIG_H__ /* long and pointer must be either 32 bit or 64 bit */ #undef SIZEOF_LONG #undef SIZEOF_CHAR_P #define BITS_PER_LONG (SIZEOF_LONG * CHAR_BIT) /* Check whether to define umode_t ourselves. */ #ifndef HAVE_UMODE_T typedef unsigned short umode_t; #endif /* Define if you want gettext (I18N) support */ #undef ENABLE_GETTEXT #ifdef ENABLE_GETTEXT # include # define _(x) gettext(x) # define N_(x) x #else # define _(x) (x) # define N_(x) x # define textdomain(d) do { } while (0) # define bindtextdomain(d,dir) do { } while (0) #endif #include #define IRIX_DEV_BITSMAJOR 14 #define IRIX_DEV_BITSMINOR 18 #define IRIX_DEV_MAXMAJ 0x1ff #define IRIX_DEV_MAXMIN 0x3ffff #define IRIX_DEV_MAJOR(dev) ((int)(((unsigned)(dev) >> IRIX_DEV_BITSMINOR) \ & IRIX_DEV_MAXMAJ)) #define IRIX_DEV_MINOR(dev) ((int)((dev) & IRIX_DEV_MAXMIN)) #define IRIX_MKDEV(major,minor) ((xfs_dev_t)(((major) << IRIX_DEV_BITSMINOR) \ | (minor&IRIX_DEV_MAXMIN))) #define IRIX_DEV_TO_KDEVT(dev) makedev(IRIX_DEV_MAJOR(dev),IRIX_DEV_MINOR(dev)) #ifndef min #define min(a,b) (((a)<(b))?(a):(b)) #define max(a,b) (((a)>(b))?(a):(b)) #endif #ifndef NBBY #define NBBY 8 #endif #endif /* __CONFIG_H__ */ xfsdump-3.1.6+nmu1/include/buildmacros0000644000000000000000000001025612607344125014633 0ustar # # Copyright (c) 2002-2003 Silicon Graphics, Inc. All Rights Reserved. # BUILDRULES = $(TOPDIR)/include/buildrules # LCFLAGS, LLDFLAGS, LLDLIBS, LSRCFILES and LDIRT may be specified in # user Makefiles. Note: LSRCFILES is anything other than Makefile, $(CFILES) # $(CXXFILES), or $(HFILES) and is used to construct the manifest list # during the "dist" phase (packaging). LDFLAGS += $(LOADERFLAGS) $(LLDFLAGS) LTLDFLAGS += $(LOADERFLAGS) LDLIBS = $(LLDLIBS) $(PLDLIBS) $(MALLOCLIB) MAKEOPTS = --no-print-directory Q=$(Q) SRCFILES = Makefile $(HFILES) $(CFILES) $(LSRCFILES) $(LFILES) $(YFILES) DEPDIRT = dep dep.bak MANDIRT = *.[1-9].gz PODIRT = *.tmpo *.mo CDIRT = $(OBJECTS) $(LTOBJECTS) $(LTCOMMAND) $(LTLIBRARY) DIRT = $(LDIRT) $(DEPDIRT) $(MANDIRT) $(PODIRT) $(CDIRT) LIBDIRT = .libs DIRDIRT = $(LDIRDIRT) $(LIBDIRT) OBJECTS = $(ASFILES:.s=.o) \ $(LCFILES:.c=.o) \ $(CFILES:.c=.o) \ $(LFILES:.l=.o) \ $(YFILES:%.y=%.tab.o) INSTALL = $(TOPDIR)/install-sh -o $(PKG_USER) -g $(PKG_GROUP) IMAGES_DIR = $(TOPDIR)/all-images DIST_DIR = $(TOPDIR)/dist CCF = $(CC) $(CFLAGS) $(CPPFLAGS) MAKEF = $(MAKE) $(MAKEOPTS) CXXF = $(CXX) $(CXXFLAGS) # For libtool. LIBNAME = $(basename $(LTLIBRARY)) LTOBJECTS = $(OBJECTS:.o=.lo) LTVERSION = $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) LTLINK = $(LIBTOOL) --quiet --tag=CC --mode=link $(CC) LTEXEC = $(LIBTOOL) --quiet --mode=execute LTINSTALL = $(LIBTOOL) --quiet --mode=install $(INSTALL) LTCOMPILE = $(LIBTOOL) --quiet --tag=CC --mode=compile $(CCF) ifeq ($(ENABLE_SHARED),yes) LTLDFLAGS += -rpath $(PKG_ROOT_LIB_DIR) LTLDFLAGS += -version-info $(LTVERSION) endif ifeq ($(ENABLE_SHARED),yes) INSTALL_LTLIB = \ cd $(TOPDIR)/$(LIBNAME)/.libs; \ ../$(INSTALL) -m 755 -d $(PKG_ROOT_LIB_DIR); \ ../$(INSTALL) -m 755 -T so_dot_version $(LIBNAME).lai $(PKG_ROOT_LIB_DIR); \ ../$(INSTALL) -T so_dot_current $(LIBNAME).lai $(PKG_ROOT_LIB_DIR) endif # Libtool thinks the static and shared libs should be in the same dir, so # make the static lib appear in the place we chose as rpath (using the two # symlinks below). # Other things want the shared libs to appear in /usr/lib, else they'll # link with the static libs there. So, another symlink to get the .so into # /usr/lib. ifeq ($(ENABLE_SHARED),yes) INSTALL_LTLIB_DEV = \ cd $(TOPDIR)/$(LIBNAME)/.libs; \ ../$(INSTALL) -m 755 -d $(PKG_LIB_DIR); \ ../$(INSTALL) -m 644 -T old_lib $(LIBNAME).lai $(PKG_LIB_DIR); \ ../$(INSTALL) -m 644 $(LIBNAME).lai $(PKG_LIB_DIR)/$(LIBNAME).la ; \ ../$(INSTALL) -m 755 -d $(PKG_ROOT_LIB_DIR); \ ../$(INSTALL) -T so_base $(LIBNAME).lai $(PKG_ROOT_LIB_DIR); \ if test "x$(PKG_LIB_DIR)" != "x$(PKG_ROOT_LIB_DIR)" ; then \ ../$(INSTALL) -S $(PKG_LIB_DIR)/$(LIBNAME).a $(PKG_ROOT_LIB_DIR)/$(LIBNAME).a; \ ../$(INSTALL) -S $(PKG_LIB_DIR)/$(LIBNAME).la $(PKG_ROOT_LIB_DIR)/$(LIBNAME).la; \ ../$(INSTALL) -S $(PKG_ROOT_LIB_DIR)/$(LIBNAME).so $(PKG_LIB_DIR)/$(LIBNAME).so; \ fi else INSTALL_LTLIB_DEV = $(INSTALL_LTLIB_STATIC) endif INSTALL_LTLIB_STATIC = \ cd $(TOPDIR)/$(LIBNAME)/.libs; \ ../$(INSTALL) -m 755 -d $(PKG_LIB_DIR); \ ../$(INSTALL) -m 644 -T old_lib $(LIBNAME).lai $(PKG_LIB_DIR) INSTALL_MAN = \ @for d in $(MAN_PAGES); do \ first=true; \ for m in `$(AWK) \ '/^\.S[h|H] NAME/ {ok=1; next} ok {print; exit}' $$d \ | $(SED) \ -e 's/^\.Nm //' -e 's/,/ /g' -e 's/\\-.*//' \ -e 's/\\\f[0-9]//g' -e 's/ / /g;q'`; \ do \ [ -z "$$m" -o "$$m" = "\\" ] && continue; \ t=$(MAN_DEST)/$$m.$(MAN_SECTION); \ if $$first; then \ if $(HAVE_ZIPPED_MANPAGES); then \ $(ZIP) -9 -c $$d > $$d.gz; _sfx=.gz; \ fi; \ u=$$m.$(MAN_SECTION)$$_sfx; \ echo $(INSTALL) -m 644 $${d}$$_sfx $${t}$$_sfx;\ $(INSTALL) -m 644 $${d}$$_sfx $${t}$$_sfx; \ else \ echo $(INSTALL) -S $$u $${t}$$_sfx; \ $(INSTALL) -S $$u $${t}$$_sfx; \ fi; \ first=false; \ done; \ done ifeq ($(ENABLE_GETTEXT),yes) INSTALL_LINGUAS = \ @for l in $(LINGUAS) ""; do \ if test -f "$$l.mo" ; then \ ldir=$(PKG_LOCALE_DIR)/$$l/LC_MESSAGES; \ $(INSTALL) -m 755 -d $$ldir; \ $(INSTALL) -m 644 $$l.mo $$ldir/$(PKG_NAME).mo; \ fi; \ done endif MAN_MAKERULE = \ @for f in *.[12345678] ""; do \ if test ! -z "$$f"; then \ $(ZIP) --best -c < $$f > $$f.gz; \ fi; \ done xfsdump-3.1.6+nmu1/config.sub0000755000000000000000000010577512607344145012761 0ustar #! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2014 Free Software Foundation, Inc. timestamp='2014-09-11' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # Please send patches with a ChangeLog entry to config-patches@gnu.org. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright 1992-2014 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | \ kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray | -microblaze*) os= basic_machine=$1 ;; -bluegene*) os=-cnk ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*178) os=-lynxos178 ;; -lynx*5) os=-lynxos5 ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arceb \ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ | avr | avr32 \ | be32 | be64 \ | bfin \ | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ | epiphany \ | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | k1om \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa32r6 | mipsisa32r6el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64r6 | mipsisa64r6el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipsr5900 | mipsr5900el \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nds32 | nds32le | nds32be \ | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ | open8 | or1k | or1knd | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pyramid \ | riscv32 | riscv64 \ | rl78 | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu \ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; c54x) basic_machine=tic54x-unknown ;; c55x) basic_machine=tic55x-unknown ;; c6x) basic_machine=tic6x-unknown ;; m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; strongarm | thumb | xscale) basic_machine=arm-unknown ;; xgate) basic_machine=$basic_machine-unknown os=-none ;; xscaleeb) basic_machine=armeb-unknown ;; xscaleel) basic_machine=armel-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | k1om-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ | microblaze-* | microblazeel-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa32r6-* | mipsisa32r6el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64r6-* | mipsisa64r6el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipsr5900-* | mipsr5900el-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nds32-* | nds32le-* | nds32be-* \ | nios-* | nios2-* | nios2eb-* | nios2el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ | or1k*-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pyramid-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ | tron-* \ | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aros) basic_machine=i386-pc os=-aros ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) basic_machine=powerpc-ibm os=-cnk ;; c54x-*) basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c55x-*) basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c6x-*) basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray os=-unicos ;; cegcc) basic_machine=arm-unknown os=-cegcc ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16 | cr16-*) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dicos) basic_machine=i686-pc os=-dicos ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; microblaze*) basic_machine=microblaze-xilinx ;; mingw64) basic_machine=x86_64-pc os=-mingw64 ;; mingw32) basic_machine=i686-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; moxiebox) basic_machine=moxie-unknown os=-moxiebox ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i686-pc os=-msys ;; mvs) basic_machine=i370-ibm os=-mvs ;; nacl) basic_machine=le32-unknown os=-nacl ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; neo-tandem) basic_machine=neo-tandem ;; nse-tandem) basic_machine=nse-tandem ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos | rdos64) basic_machine=x86_64-pc os=-rdos ;; rdos32) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; strongarm-* | thumb-*) basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tile*) basic_machine=$basic_machine-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; z80-*-coff) basic_machine=z80-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -bitrig* | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -nacl*) ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; c8051-*) os=-elf ;; hexagon-*) os=-elf ;; tic54x-*) os=-coff ;; tic55x-*) os=-coff ;; tic6x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -cnk*|-aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: xfsdump-3.1.6+nmu1/dump/0000755000000000000000000000000012643557274011735 5ustar xfsdump-3.1.6+nmu1/dump/inomap.h0000644000000000000000000001250112620476160013355 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef INOMAP_H #define INOMAP_H /* inomap.[hc] - inode map abstraction * * an inode map describes the inode numbers (inos) in a file system dump. * the map identifies which inos are in-use by the fs, which of those are * directories, and which are dumped. * * the map is represented as a list of map segments. a map segment is * a 64-bit starting ino and two 64-bit bitmaps. the bitmaps describe * the 64 inos beginning with the starting ino. two bits are available * for each ino. */ struct xfs_bstat; /* inomap_build - this function allocates and constructs an in-memory * representation of the bitmap. it prunes from the map inos of files not * changed since the last dump, inos not identified by the subtree list, * and directories not needed to represent a hierarchy containing * changed inodes. it handles hard links; a file linked to multiple * directory entries will not be pruned if at least one of those * directories has an ancestor in the subtree list. * * it returns by reference an array of startpoints in the non-directory * portion of the dump, as well as the count of dir and nondir inos * makred as present and to be dumped. A startpoint identifies a non-dir ino, * and a non-hole accumulated size position within that file. only very large * files will contain a startpoint; in all other cases the startpoints will * fall at file boundaries. returns BOOL_FALSE if error encountered (should * abort the dump; else returns BOOL_TRUE. */ extern bool_t inomap_build( void *fshandlep, int fsfd, struct xfs_bstat *rootstatp, bool_t last, time32_t lasttime, bool_t resume, time32_t resumetime, size_t resumerangecnt, drange_t *resumerangep, char *subtreebuf[], ix_t subtreecnt, bool_t skip_unchanged_dirs, startpt_t startptp[], size_t startptcnt, ix_t *statphasep, ix_t *statpassp, size64_t statcnt, size64_t *statdonep ); extern uint64_t inomap_getsz( void ); /* inomap_skip - tell inomap about inodes to skip in the dump */ extern void inomap_skip( xfs_ino_t ino ); /* inomap_writehdr - updates the write header with inomap-private info * to be communicated to the restore side */ extern void inomap_writehdr( content_inode_hdr_t *scwhdrp ); /* inomap_dump - dumps the map to media - content-abstraction-knowledgable * * returns error from media write op */ extern rv_t inomap_dump( drive_t *drivep ); /* map state values */ #define MAP_INO_UNUSED 0 /* ino not in use by fs */ #define MAP_DIR_NOCHNG 1 /* dir, ino in use by fs, but not dumped */ #define MAP_NDR_NOCHNG 2 /* non-dir, ino in use by fs, but not dumped */ #define MAP_DIR_CHANGE 3 /* dir, changed since last dump */ #define MAP_NDR_CHANGE 4 /* non-dir, changed since last dump */ #define MAP_DIR_SUPPRT 5 /* dir, unchanged but needed for hierarchy */ #define MAP_RESERVED1 6 /* this state currently not used */ #define MAP_RESERVED2 7 /* this state currently not used */ /* the inomap is implemented as a linked list of chunks. each chunk contains * an array of map segments. a map segment contains a start ino and a * bitmap of 64 3-bit state values (see MAP_... in inomap.h). the SEG_macros * index and manipulate the 3-bit state values. */ struct seg { xfs_ino_t base; uint64_t lobits; uint64_t mebits; uint64_t hibits; }; typedef struct seg seg_t; #define INOPERSEG ( sizeof( (( seg_t * )0 )->lobits ) * NBBY ) #define HNKSZ ( 4 * PGSZ ) #define SEGPERHNK ( ( HNKSZ / sizeof( seg_t )) - 1 ) struct hnk { seg_t seg[ SEGPERHNK ]; xfs_ino_t maxino; struct hnk *nextp; /* no longer used, kept for binary compat */ char pad[sizeof( seg_t ) - sizeof( xfs_ino_t ) - sizeof( struct hnk * )]; }; typedef struct hnk hnk_t; /* functions to get state and gen information from the inomap. * requires a pointer to a context block, obtained from * inomap_alloc_context(), and released by inomap_free_context(). */ extern void *inomap_alloc_context( void ); extern void inomap_reset_context( void *contextp ); extern void inomap_free_context( void *contextp ); extern int inomap_get_state( void *contextp, xfs_ino_t ino ); extern int inomap_get_gen( void *contextp, xfs_ino_t ino, gen_t *gen ); /* generators returning the next dir or non-dir ino selected in this dump. * returns INO64MAX when no more inos. * requires a pointer to a context block, obtained from * inomap_alloc_context(), and released by inomap_free_context(). */ extern xfs_ino_t inomap_next_nondir(void *contextp, xfs_ino_t lastino); extern xfs_ino_t inomap_next_dir(void *contextp, xfs_ino_t lastino); #endif /* INOMAP_H */ xfsdump-3.1.6+nmu1/dump/content.c0000644000000000000000000052060412620476160013547 0ustar /* * Copyright (c) 2000-2004 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef linux #include #endif #include #include "config.h" #include "hsmapi.h" #include "exit.h" #include "types.h" #include "path.h" #include "timeutil.h" #include "util.h" #include "lock.h" #include "qlock.h" #include "mlog.h" #include "dlog.h" #include "getopt.h" #include "stream.h" #include "cldmgr.h" #include "global.h" #include "drive.h" #include "media.h" #include "content.h" #include "content_common.h" #include "content_inode.h" #include "fs.h" #include "inomap.h" #include "var.h" #include "inventory.h" #include "getdents.h" #include "arch_xlate.h" /* max "unsigned long long int" */ #define ULONGLONG_MAX 18446744073709551615LLU /* legal range of dump levels */ #define LEVEL_DEFAULT 0 #define LEVEL_MAX 9 /* ordinary files as big or bigger than this many pages will be * preceeded in the dump by enough padding to align the first byte * of that file's data to a page boundary */ #define PGALIGNTHRESH 8 /* structure definitions used locally ****************************************/ /* number of bstats bstat_iter fetches at a time */ #define BSTATBUFLEN 4096 /* if the source file system type can't be determined, assume it is this */ #define FS_DEFAULT "xfs" /* marks consist of a opaque drive layer cookie and a startpoint. * the drive layer requires that it be passed a pointer to a drive_markrec_t. * we tack on content-specific baggage (startpt_t). this works because we * allocate and free mark_t's here. */ struct mark { drive_markrec_t dm; startpt_t startpt; }; typedef struct mark mark_t; /* Media_mfile_begin( ) entry state. */ enum bes { BES_INIT, /* in the beginning */ BES_ENDOK, /* last media file successfully flushed to media */ BES_ENDEOM, /* hit EOM while writing last media file */ BES_INVAL }; /* to assert protocol being followed */ typedef enum bes bes_t; /* per-stream context */ struct context { filehdr_t *cc_filehdrp; /* pre-allocated buffer: heads each dumped file */ extenthdr_t *cc_extenthdrp; /* pre-allocated buffer: heads each dumped file extent */ void *cc_inomap_contextp; /* pre-allocated context to speed inomap iteration */ char *cc_getdentsbufp; size_t cc_getdentsbufsz; /* pre-allocated buffer for getdents() syscall */ char *cc_mdirentbufp; size_t cc_mdirentbufsz; /* pre-allocated buffer for on-media dirent */ char *cc_extattrlistbufp; size_t cc_extattrlistbufsz; /* pre-allocated buffer for retrieving a * list of extended file attributes */ attr_multiop_t *cc_extattrrtrvarrayp; size_t cc_extattrrtrvarraylen; /* pre-allocated array of ops for retrieving the * values for a list of extended file attributes */ char *cc_extattrdumpbufp; size_t cc_extattrdumpbufsz; /* pre-allocated buffer for dumping the names and * values for a list of extended file attributes */ hsm_f_ctxt_t *cc_hsm_f_ctxtp; /* pre-allocated HSM context used for holding HSM state information about a file across subroutine calls. */ char *cc_readlinkbufp; size_t cc_readlinkbufsz; /* pre-allocated buffer for readlink() */ off64_t cc_mfilesz; /* total bytes dumped to media file */ size_t cc_markscommitted; /* number of marks committed in mfile. only useful * info is if greater than zero. */ xfs_ino_t cc_stat_lastino; /* monotonic strm nondir ino dumped */ bool_t cc_completepr; /* set if stream completely dumped. useful for * determining if dump was interrupted */ bool_t cc_Media_useterminatorpr; /* true if stream terminators are expected and * will be used */ char *cc_Media_firstlabel; /* optional command line media label. only used * for first media object in stream, and only if * media object does not already have a label */ bes_t cc_Media_begin_entrystate; /* Media_mfile_begin context entry state */ }; typedef struct context context_t; /* extent group context, used by dump_file() */ #define BMAP_LEN 512 struct extent_group_context { getbmapx_t eg_bmap[ BMAP_LEN ]; getbmapx_t *eg_nextbmapp; /* ptr to the next extent to dump */ getbmapx_t *eg_endbmapp; /* to detect extent exhaustion */ int eg_fd; /* file desc. */ int eg_bmapix; /* debug info only, not used */ int eg_gbmcnt; /* debug, counts getbmapx calls for ino*/ }; typedef struct extent_group_context extent_group_context_t; /* minimum getdents( ) buffer size */ #define GETDENTSBUF_SZ_MIN ( 2 * pgsz ) /* minimum sizes for extended attributes buffers */ #define EXTATTR_LISTBUF_SZ ( XATTR_LIST_MAX ) #define EXTATTR_RTRVARRAY_LEN ( 1 * pgsz ) #define EXTATTR_DUMPBUF_SZ ( 4 * pgsz ) /* for printing ext attr namespace */ #define EXTATTR_NAMESPACE(flag) ( ((flag) & ATTR_ROOT) ? _("root") : \ ( ((flag) & ATTR_SECURE) ? _("secure") : \ _("non-root") ) ) /* for printing file type */ #define FILETYPE(statp) ( ( (statp)->bs_mode & S_IFMT ) == S_IFDIR \ ? _("dir") : _("nondir") ) /* per-drive status descriptor */ struct pds { enum { PDS_NULL, /* per-drive activity not begun */ PDS_INOMAP, /* dumping inomap */ PDS_DIRDUMP, /* dumping dirs */ PDS_NONDIR, /* dumping nondirs */ PDS_INVSYNC, /* waiting for inventory */ PDS_INVDUMP, /* dumping session inventory */ PDS_TERMDUMP /* writing stream terminator */ } pds_phase; size64_t pds_dirdone; /* number of directories done */ }; typedef struct pds pds_t; /* declarations of externally defined global symbols *************************/ extern void usage( void ); extern bool_t preemptchk( int ); extern char *homedir; extern bool_t pipeline; extern bool_t stdoutpiped; extern char *sistr; extern size_t pgsz; /* forward declarations of locally defined static functions ******************/ /* file dumpers */ static rv_t dump_dirs( ix_t strmix, xfs_bstat_t *bstatbufp, size_t bstatbuflen, void *inomap_contextp ); static rv_t dump_dir( ix_t strmix, jdm_fshandle_t *, int, xfs_bstat_t * ); static rv_t dump_file( void *, jdm_fshandle_t *, int, xfs_bstat_t * ); static rv_t dump_file_reg( drive_t *drivep, context_t *contextp, content_inode_hdr_t *scwhdrp, jdm_fshandle_t *, xfs_bstat_t *, bool_t *); static rv_t dump_file_spec( drive_t *drivep, context_t *contextp, jdm_fshandle_t *, xfs_bstat_t * ); static rv_t dump_filehdr( drive_t *drivep, context_t *contextp, xfs_bstat_t *, off64_t, int ); static rv_t dump_extenthdr( drive_t *drivep, context_t *contextp, int32_t, int32_t, off64_t, off64_t ); static rv_t dump_dirent( drive_t *drivep, context_t *contextp, xfs_bstat_t *, xfs_ino_t, gen_t, char *, size_t ); static rv_t init_extent_group_context( jdm_fshandle_t *, xfs_bstat_t *, extent_group_context_t * ); static void cleanup_extent_group_context( extent_group_context_t * ); static rv_t dump_extent_group( drive_t *drivep, context_t *contextp, xfs_bstat_t *, extent_group_context_t *, off64_t, off64_t, bool_t, off64_t *, off64_t *, bool_t * ); static bool_t dump_session_inv( drive_t *drivep, context_t *contextp, media_hdr_t *mwhdrp, content_inode_hdr_t *scwhdrp ); static rv_t write_pad( drive_t *drivep, size_t ); static void mark_callback( void *, drive_markrec_t *, bool_t ); static void inv_cleanup( void ); static void dump_terminator( drive_t *drivep, context_t *contextp, media_hdr_t *mwhdrp ); static rv_t Media_mfile_begin( drive_t *drivep, context_t *contextp, bool_t intr_allowed ); static rv_t Media_mfile_end( drive_t *drivep, context_t *contextp, media_hdr_t *mwhdrp, off64_t *ncommittedp, bool_t hit_eom ); static bool_t Media_prompt_overwrite( drive_t *drivep ); static rv_t Media_erasechk( drive_t *drivep, int dcaps, bool_t intr_allowed, bool_t prevmediapresentpr ); static bool_t Media_prompt_erase( drive_t *drivep ); static char *Media_prompt_label( drive_t *drivep, char *bufp, size_t bufsz ); static void update_cc_Media_useterminatorpr( drive_t *drivep, context_t *contextp ); static void set_mcflag( ix_t thrdix ); static void clr_mcflag( ix_t thrdix ); static bool_t check_complete_flags( void ); static rv_t dump_extattrs( drive_t *drivep, context_t *contextp, jdm_fshandle_t *fshandlep, xfs_bstat_t *statp); static rv_t dump_extattr_list( drive_t *drivep, context_t *contextp, jdm_fshandle_t *fshandlep, xfs_bstat_t *statp, attrlist_t *listp, int flag, bool_t *abortprp ); static char *dump_extattr_buildrecord( xfs_bstat_t *statp, char *dumpbufp, char *dumpbufendp, char *namesrcp, uint32_t valuesz, int flag, char **valuepp ); static rv_t dump_extattrhdr( drive_t *drivep, context_t *contextp, xfs_bstat_t *statp, size_t recsz, size_t valoff, ix_t flags, uint32_t valsz ); static bool_t save_quotas( char *mntpnt, quota_info_t *quotainfo ); static int getxfsqstat( char *fsdev ); /* definition of locally defined global variables ****************************/ bool_t content_media_change_needed; char *media_change_alert_program = NULL; hsm_fs_ctxt_t *hsm_fs_ctxtp = NULL; uint64_t hdr_mfilesz = 0; uint64_t maxdumpfilesize = 0; bool_t allowexcludefiles_pr = BOOL_FALSE; /* definition of locally defined static variables *****************************/ static bool_t sc_preerasepr = BOOL_FALSE; /* pre-erase media */ static inv_idbtoken_t sc_inv_idbtoken = INV_TOKEN_NULL; /* handle to inventory */ static inv_sestoken_t sc_inv_sestoken = INV_TOKEN_NULL; /* handle to inventory session */ static inv_stmtoken_t *sc_inv_stmtokenp = 0; /* array of inventory session stream handles */ static bool_t sc_inv_updatepr = BOOL_TRUE; /* set if ok to update online inventory with stats of this dump */ static ix_t sc_level = LEVEL_DEFAULT; /* dump level requested */ static bool_t sc_incrpr = BOOL_FALSE; static time32_t sc_incrbasetime; static ix_t sc_incrbaselevel; static uuid_t sc_incrbaseid; /* if an incremental dump, the base, level and time of the incremental * base dump. TRICKY: if resuming an incremental dump, this is the * base of the original incremental. */ static bool_t sc_resumepr = BOOL_FALSE; static time32_t sc_resumebasetime = 0; static uuid_t sc_resumebaseid; static size_t sc_resumerangecnt = 0; static drange_t *sc_resumerangep = 0; /* if a resumed dump, the id, time and undumped ino/offset ranges * of the interrupted dump being resumed. */ static jdm_fshandle_t *sc_fshandlep = 0; /* dmi file system handle */ static int sc_fsfd = -1; /* open file descriptor for root directory */ static xfs_bstat_t *sc_rootxfsstatp = 0; /* pointer to loaded bulkstat for root directory */ static startpt_t *sc_startptp = 0; /* an array of stream ino/offset start points */ static time32_t sc_stat_starttime = 0; /* for cacluating elapsed time */ static ix_t sc_stat_inomapphase = 0; static ix_t sc_stat_inomappass = 0; static size64_t sc_stat_inomapcnt; static size64_t sc_stat_inomapdone; static size64_t sc_stat_dircnt = 0; /* total number of directory inodes to be dumped (strm 0) */ static pds_t sc_stat_pds[ STREAM_SIMMAX ]; /* per-drive stream status */ static size64_t sc_stat_nondircnt = 0; /* total number of non-directory inodes to be dumped (all strms) */ static size64_t sc_stat_nondirdone = 0; /* total number of non-directory inodes dumped (all strms) */ static size64_t sc_stat_datasz = 0; /* total size in bytes of non-dirs to be dumped (all strms) */ static size64_t sc_stat_datadone = 0; /* total size in bytes of non-dirs dumped (all strms) */ static size_t sc_thrdsarrivedcnt = 0; /* each thread checks in by bumping this count under lock. * used to decide when its ok to begin waiting for all threads * to arrive at sync pt for session inventory dump. */ static size_t sc_thrdsdonecnt = 0; /* number of threads which are ready to dump the session inventory. * when equal to the number of streams remaining (stream_cnt( )), * can proceed with inventory dumps */ static context_t *sc_contextp; /* an array of per-stream context descriptors */ static bool_t sc_mcflag[ STREAM_SIMMAX ]; /* media change flag */ static bool_t sc_dumpextattrpr = BOOL_TRUE; /* dump extended attributes */ static bool_t sc_dumpasoffline = BOOL_FALSE; /* dump dual-residency HSM files as offline */ static bool_t sc_use_old_direntpr = BOOL_FALSE; /* dump dirents as dirent_v1_t instead of dirent_t * (for compat with dump format 2) */ static bool_t sc_savequotas = BOOL_TRUE; /* save quota information in dump */ static quota_info_t quotas[] = { { "user quota", BOOL_TRUE, CONTENT_QUOTAFILE, "", "-uf", XFS_QUOTA_UDQ_ACCT, 0 }, { "project quota", BOOL_TRUE, CONTENT_PQUOTAFILE, "", "-pf", XFS_QUOTA_PDQ_ACCT, 0 }, { "group quota", BOOL_TRUE, CONTENT_GQUOTAFILE, "", "-gf", XFS_QUOTA_GDQ_ACCT, 0 } }; /* definition of locally defined global functions ****************************/ /* definition of locally defined static functions ****************************/ static bool_t create_inv_session( global_hdr_t *gwhdrtemplatep, uuid_t *fsidp, const char *mntpnt, const char *fsdevice, ix_t subtreecnt, size_t strmix); bool_t content_init( int argc, char *argv[ ], global_hdr_t *gwhdrtemplatep ) { inv_idbtoken_t inv_idbt; inv_session_t *sessp = 0; drive_hdr_t *dwhdrtemplatep; media_hdr_t *mwhdrtemplatep; content_hdr_t *cwhdrtemplatep; content_inode_hdr_t *scwhdrtemplatep; ix_t subtreecnt; char **subtreep; ix_t subtreeix; bool_t resumereqpr = BOOL_FALSE; char *srcname; char mntpnt[ GLOBAL_HDR_STRING_SZ ]; char fsdevice[ GLOBAL_HDR_STRING_SZ ]; char fstype[ CONTENT_HDR_FSTYPE_SZ ]; bool_t skip_unchanged_dirs = BOOL_FALSE; uuid_t fsid; bool_t underfoundpr; ix_t underlevel = ( ix_t )( -1 ); time32_t undertime = 0; uuid_t underid; bool_t underpartialpr = BOOL_FALSE; bool_t underinterruptedpr = BOOL_FALSE; bool_t samefoundpr; time32_t sametime = 0; uuid_t sameid; bool_t samepartialpr = BOOL_FALSE; bool_t sameinterruptedpr = BOOL_FALSE; size_t strmix; int c; int i; int qstat; int rval; bool_t ok; extern char *optarg; extern int optind, opterr, optopt; char *baseuuidstr = NULL; uuid_t baseuuid; bool_t baseuuidvalpr; uint64_t dircnt; uint64_t nondircnt; uint64_t datasz; uint64_t inocnt; uint64_t inomapsz; uint64_t direntsz; uint64_t filesz; uint64_t size_estimate; /* basic sanity checks */ assert( sizeof( mode_t ) == MODE_SZ ); assert( sizeof( timestruct_t ) == TIMESTRUCT_SZ ); assert( sizeof( bstat_t ) == BSTAT_SZ ); assert( sizeof( filehdr_t ) == FILEHDR_SZ ); assert( sizeof( extenthdr_t ) == EXTENTHDR_SZ ); assert( sizeof( direnthdr_t ) == DIRENTHDR_SZ ); assert( sizeof( direnthdr_v1_t ) == DIRENTHDR_SZ ); assert( DIRENTHDR_SZ % DIRENTHDR_ALIGN == 0 ); assert( sizeofmember( content_hdr_t, ch_specific ) >= sizeof( content_inode_hdr_t )); assert( sizeof( extattrhdr_t ) == EXTATTRHDR_SZ ); /* calculate offsets of portions of the write hdr template */ dwhdrtemplatep = ( drive_hdr_t * )gwhdrtemplatep->gh_upper; mwhdrtemplatep = ( media_hdr_t * )dwhdrtemplatep->dh_upper; cwhdrtemplatep = ( content_hdr_t * )mwhdrtemplatep->mh_upper; scwhdrtemplatep = ( content_inode_hdr_t * ) cwhdrtemplatep->ch_specific; if ( gwhdrtemplatep->gh_version < GLOBAL_HDR_VERSION_3 ) { sc_use_old_direntpr = BOOL_TRUE; } /* process command line args */ optind = 1; opterr = 0; subtreecnt = 0; baseuuidvalpr = BOOL_FALSE; while ( ( c = getopt( argc, argv, GETOPT_CMDSTRING )) != EOF ) { switch ( c ) { case GETOPT_LEVEL: if ( ! optarg || optarg[ 0 ] == '-' ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c argument missing\n"), c ); usage( ); return BOOL_FALSE; } sc_level = ( ix_t )atoi( optarg ); if ( sc_level > LEVEL_MAX ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c argument must be " "between 0 and %d\n"), c, LEVEL_MAX ); usage( ); return BOOL_FALSE; } break; case GETOPT_SUBTREE: if ( ! optarg || optarg[ 0 ] == '-' ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c argument missing\n"), c ); usage( ); return BOOL_FALSE; } if ( optarg[ 0 ] == '/' ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c argument (subtree) " "must be a relative pathname\n"), c ); usage( ); return BOOL_FALSE; } subtreecnt++; break; case GETOPT_MAXDUMPFILESIZE: if ( ! optarg || optarg [ 0 ] == '-' ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c argument missing\n"), c ); usage( ); return BOOL_FALSE; } maxdumpfilesize = strtoull(optarg, NULL, 0); if ( maxdumpfilesize == 0 || maxdumpfilesize > ULONGLONG_MAX / 1024 || ( maxdumpfilesize == ULONGLONG_MAX && errno == ERANGE ) ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c argument is not a valid file size\n"), c ); usage( ); return BOOL_FALSE; } maxdumpfilesize *= 1024; break; case GETOPT_NOUNCHANGEDDIRS: skip_unchanged_dirs = BOOL_TRUE; break; case GETOPT_EXCLUDEFILES: allowexcludefiles_pr = BOOL_TRUE; break; case GETOPT_RESUME: resumereqpr = BOOL_TRUE; break; case GETOPT_NOINVUPDATE: sc_inv_updatepr = BOOL_FALSE; break; case GETOPT_ERASE: sc_preerasepr = BOOL_TRUE; break; case GETOPT_ALERTPROG: if ( ! optarg || optarg[ 0 ] == '-' ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c argument missing\n"), c ); usage( ); return BOOL_FALSE; } media_change_alert_program = optarg; break; case GETOPT_NOEXTATTR: sc_dumpextattrpr = BOOL_FALSE; break; case GETOPT_DUMPASOFFLINE: sc_dumpasoffline = BOOL_TRUE; break; case GETOPT_BASED: if ( ! optarg || optarg[ 0 ] == '-' ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c argument missing\n"), c ); usage( ); return BOOL_FALSE; } baseuuidstr = optarg; if ( uuid_parse( baseuuidstr, baseuuid ) < 0 ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c argument not a valid " "dump session id\n"), c ); usage( ); return BOOL_FALSE; } baseuuidvalpr = BOOL_TRUE; } } if ( resumereqpr && baseuuidvalpr ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "may not specify both -%c and -%c\n"), GETOPT_BASED, GETOPT_RESUME ); return BOOL_FALSE; } /* the user may specify stdout as the destination, by a single * dash ('-') with no option letter. This must appear between * all lettered arguments and the source file system pathname. */ if ( optind < argc && ! strcmp( argv[ optind ], "-" )) { optind++; } /* the last argument must be either the mount point or a * device pathname of the file system to be dumped. */ if ( optind >= argc ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "source file system " "not specified\n") ); usage( ); return BOOL_FALSE; } srcname = argv[ optind ]; if ( preemptchk( PREEMPT_FULL )) { return BOOL_FALSE; } /* allocate space for the subtree pointer array and load it */ if ( subtreecnt ) { subtreep = ( char ** )calloc( subtreecnt, sizeof( char * )); assert( subtreep ); optind = 1; opterr = 0; subtreeix = 0; while ( ( c = getopt( argc, argv, GETOPT_CMDSTRING )) != EOF ) { switch ( c ) { case GETOPT_SUBTREE: assert( subtreeix < subtreecnt ); assert( optarg && optarg[ 0 ] != '-' ); subtreep[ subtreeix++ ] = optarg; break; } } assert( subtreeix == subtreecnt ); } else { subtreep = 0; } /* call a magic function to figure out if the last argument is * a mount point or a device pathname, and retrieve the file * system type, full pathname of the character special device * containing the file system, the latest mount point, and the file * system ID (uuid). returns BOOL_FALSE if the last * argument doesn't look like a file system. */ if ( ! fs_info( fstype, sizeof( fstype ), FS_DEFAULT, fsdevice, sizeof( fsdevice ), mntpnt, sizeof( mntpnt ), &fsid, srcname )) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "%s does not identify a file system\n"), srcname ); usage( ); return BOOL_FALSE; } /* verify that the file system is mounted. This must be enhanced * to mount an unmounted file system on a temporary mount point, * if it is not currently mounted. */ if ( ! fs_mounted( fstype, fsdevice, mntpnt, &fsid )) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "%s must be mounted to be dumped\n"), srcname ); return BOOL_FALSE; } /* place the fs info in the write hdr template */ ( void )strncpyterm( cwhdrtemplatep->ch_mntpnt, mntpnt, sizeof( cwhdrtemplatep->ch_mntpnt )); ( void )strncpyterm( cwhdrtemplatep->ch_fsdevice, fsdevice, sizeof( cwhdrtemplatep->ch_fsdevice )); ( void )strncpyterm( cwhdrtemplatep->ch_fstype, fstype, sizeof( cwhdrtemplatep->ch_fstype )); uuid_copy( cwhdrtemplatep->ch_fsid, fsid ); /* write quota information */ if( sc_savequotas ) { sc_savequotas = BOOL_FALSE; for(i = 0; i < (sizeof(quotas) / sizeof(quotas[0])); i++) { quotas[i].savequotas = BOOL_FALSE; qstat = getxfsqstat( fsdevice ); if (qstat > 0 && (qstat & quotas[i].statflag) ) { sprintf( quotas[i].quotapath, "%s/%s", mntpnt, quotas[i].quotafile ); if( save_quotas( mntpnt, "as[i] )) { if( subtreecnt ) { subtreecnt++; subtreep = (char **) realloc( subtreep, subtreecnt * sizeof(char *)); assert( subtreep ); subtreep[ subtreecnt - 1 ] = quotas[i].quotafile; } sc_savequotas = BOOL_TRUE; quotas[i].savequotas = BOOL_TRUE; } else { mlog( MLOG_NORMAL | MLOG_ERROR, _( "failed to save %s information, continuing\n"), quotas[i].desc ); } } } } /* create my /var directory if it doesn't already exist. */ var_create( ); /* get two session descriptors from the inventory: one for the last * dump at this level, and one for the last dump at a lower level. * the former will be used to check if the last dump at this level * was prematurely terminated; if so, for those inos already dumped * then, we will look only for changes since that dump. the latter * will give us a change date for all other inos. */ if ( preemptchk( PREEMPT_FULL )) { return BOOL_FALSE; } /* briefly open the online dump inventory, so it can be used * to calculate incremental and resumed dumps. */ inv_idbt = inv_open( ( inv_predicate_t )INV_BY_UUID, INV_SEARCH_ONLY, ( void * )&fsid ); /* if a based request, look for the indicated session. * if found, and not interrupted, this will be used as an * incremental base. if interrupted, will be used as * resume base. */ if ( baseuuidvalpr ) { ix_t strix; ix_t strcnt; inv_stream_t *bsp; bool_t interruptedpr; underfoundpr = BOOL_FALSE; samefoundpr = BOOL_FALSE; underinterruptedpr = BOOL_FALSE; sameinterruptedpr = BOOL_FALSE; interruptedpr = BOOL_FALSE; ok = inv_get_session_byuuid(&fsid, &baseuuid, &sessp); if ( ! ok ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "could not find specified base dump (%s) " "in inventory\n"), baseuuidstr ); return BOOL_FALSE; } strcnt = ( ix_t )sessp->s_nstreams; for ( strix = 0 ; strix < strcnt ; strix++ ) { bsp = &sessp->s_streams[ strix ]; if ( bsp->st_interrupted ) { interruptedpr = BOOL_TRUE; break; } } if ( interruptedpr ) { sc_level = ( ix_t )sessp->s_level; resumereqpr = BOOL_TRUE; samefoundpr = BOOL_TRUE; sametime = sessp->s_time; uuid_copy (sameid, sessp->s_sesid); samepartialpr = sessp->s_ispartial; sameinterruptedpr = BOOL_TRUE; sc_resumerangecnt = ( size_t )sessp->s_nstreams; sc_resumerangep = ( drange_t * )calloc( sc_resumerangecnt, sizeof( drange_t )); assert( sc_resumerangep ); for ( strmix = 0 ; strmix < sc_resumerangecnt ; strmix++ ) { inv_stream_t *bsp; inv_stream_t *esp; drange_t *p = &sc_resumerangep[ strmix ]; bsp = &sessp->s_streams[ strmix ]; esp = ( strmix < sc_resumerangecnt - 1 ) ? bsp + 1 : 0; if ( bsp->st_interrupted ) { sameinterruptedpr = BOOL_TRUE; p->dr_begin.sp_ino = bsp->st_endino; p->dr_begin.sp_offset = bsp->st_endino_off; if ( esp ) { p->dr_end.sp_ino = esp->st_startino; p->dr_end.sp_offset = esp->st_startino_off; mlog( MLOG_DEBUG, "resume range stream %u " "ino %llu:%lld to " "%llu:%lld\n", strmix, p->dr_begin.sp_ino, p->dr_begin.sp_offset, p->dr_end.sp_ino, p->dr_end.sp_offset ); } else { p->dr_end.sp_flags = STARTPT_FLAGS_END; mlog( MLOG_DEBUG, "resume range stream %u " "ino %llu:%lld to " "end\n", strmix, p->dr_begin.sp_ino, p->dr_begin.sp_offset ); } } else { /* set the range start pt's END flag to * indicate the range was not interrupted. */ p->dr_begin.sp_flags = STARTPT_FLAGS_END; } } } else { if ( sessp->s_level >= LEVEL_MAX ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "cannot select dump session %d as base " "for incremental dump: " "level must be less than %d\n"), sessp->s_level, LEVEL_MAX ); return BOOL_FALSE; } sc_level = ( ix_t )sessp->s_level + 1; undertime = sessp->s_time; underlevel = ( ix_t )sessp->s_level; uuid_copy (underid, sessp->s_sesid); underpartialpr = sessp->s_ispartial; underinterruptedpr = BOOL_FALSE; underfoundpr = BOOL_TRUE; } inv_free_session( &sessp ); sessp = 0; ok = inv_close( inv_idbt ); assert( ok ); inv_idbt = INV_TOKEN_NULL; goto baseuuidbypass; } /* look for the most recent dump at a level less than the level * of this dump. extract the time, level, id, and predicates partial * and interrupted. */ underfoundpr = BOOL_FALSE; if ( sc_level > 0 ) { if ( inv_idbt == INV_TOKEN_NULL ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "cannot calculate incremental dump: " "online inventory not available\n") ); return BOOL_FALSE; } ok = inv_lastsession_level_lessthan(&fsid, inv_idbt, (u_char_t)sc_level, &sessp); if ( ! ok ) { sessp = 0; } if ( sessp ) { ix_t strix; ix_t strcnt; inv_stream_t *bsp; undertime = sessp->s_time; underlevel = ( ix_t )sessp->s_level; uuid_copy (underid, sessp->s_sesid); underpartialpr = sessp->s_ispartial; underinterruptedpr = BOOL_FALSE; strcnt = ( ix_t )sessp->s_nstreams; for ( strix = 0 ; strix < strcnt ; strix++ ) { bsp = &sessp->s_streams[ strix ]; if ( bsp->st_interrupted ) { underinterruptedpr = BOOL_TRUE; break; } } underfoundpr = BOOL_TRUE; inv_free_session( & sessp ); sessp = 0; } } /* look for the most recent dump at a level equal to the level * of this dump. extract the time, level, id, and predicates partial * and interrupted, and for each stream the range of ino/offset * values not dumped. */ if ( inv_idbt != INV_TOKEN_NULL ) { /* REFERENCED */ bool_t ok1; ok = inv_lastsession_level_equalto(&fsid, inv_idbt, (u_char_t)sc_level, &sessp); ok1 = inv_close( inv_idbt ); assert( ok1 ); if ( ! ok ) { sessp = 0; } inv_idbt = INV_TOKEN_NULL; } else { sessp = 0; } samefoundpr = BOOL_FALSE; if ( sessp ) { sametime = sessp->s_time; uuid_copy(sameid, sessp->s_sesid); samepartialpr = sessp->s_ispartial; sameinterruptedpr = BOOL_FALSE; sc_resumerangecnt = ( size_t )sessp->s_nstreams; sc_resumerangep = ( drange_t * )calloc( sc_resumerangecnt, sizeof( drange_t )); assert( sc_resumerangep ); for ( strmix = 0 ; strmix < sc_resumerangecnt ; strmix++ ) { inv_stream_t *bsp; inv_stream_t *esp; drange_t *p = &sc_resumerangep[ strmix ]; bsp = &sessp->s_streams[ strmix ]; esp = ( strmix < sc_resumerangecnt - 1 ) ? bsp + 1 : 0; if ( bsp->st_interrupted ) { sameinterruptedpr = BOOL_TRUE; p->dr_begin.sp_ino = bsp->st_endino; p->dr_begin.sp_offset = bsp->st_endino_off; if ( esp ) { p->dr_end.sp_ino = esp->st_startino; p->dr_end.sp_offset = esp->st_startino_off; mlog( MLOG_DEBUG, "resume range stream %u " "ino %llu:%lld to " "%llu:%lld\n", strmix, p->dr_begin.sp_ino, p->dr_begin.sp_offset, p->dr_end.sp_ino, p->dr_end.sp_offset ); } else { p->dr_end.sp_flags = STARTPT_FLAGS_END; mlog( MLOG_DEBUG, "resume range stream %u " "ino %llu:%lld to " "end\n", strmix, p->dr_begin.sp_ino, p->dr_begin.sp_offset ); } } else { /* set the range start pt's END flag to * indicate the range was not interrupted. */ p->dr_begin.sp_flags = STARTPT_FLAGS_END; } } inv_free_session( & sessp ); sessp = 0; samefoundpr = BOOL_TRUE; } baseuuidbypass: /* now determine the incremental and resume bases, if any. */ if ( samefoundpr && ! sameinterruptedpr ) { free( ( void * )sc_resumerangep ); sc_resumerangep = 0; samefoundpr = BOOL_FALSE; } if ( samefoundpr && ! resumereqpr ) { if ( ! underfoundpr || undertime <= sametime ) { mlog( MLOG_VERBOSE | MLOG_WARNING, _( "most recent level %d dump " "was interrupted, " "but not resuming that dump since " "resume (-R) option not specified\n"), sc_level ); } free( ( void * )sc_resumerangep ); sc_resumerangep = 0; samefoundpr = BOOL_FALSE; } if ( underfoundpr ) { assert( underlevel <= LEVEL_MAX ); assert( undertime ); if ( samefoundpr ) { if ( undertime >= sametime ) { if ( underinterruptedpr ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "most recent base for " "incremental dump was " "interrupted (level %u): " "must resume or redump " "at or below level %d\n"), underlevel, sc_level ); return BOOL_FALSE; } if ( subtreecnt && ! underpartialpr ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "level %u incremental " "subtree dump " "will be based on non-subtree " "level %u dump\n"), sc_level, underlevel ); } if ( ! subtreecnt && underpartialpr ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "level %u incremental " "non-subtree dump " "will be based on subtree " "level %u dump\n"), sc_level, underlevel ); } sc_incrpr = BOOL_TRUE; sc_incrbasetime = undertime; sc_incrbaselevel = underlevel; uuid_copy(sc_incrbaseid, underid); sc_resumepr = BOOL_FALSE; assert( sc_resumerangep ); free( ( void * )sc_resumerangep ); sc_resumerangep = 0; } else { if ( subtreecnt && ! samepartialpr ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "level %u incremental " "subtree dump " "will be based on non-subtree " "level %u resumed dump\n"), sc_level, sc_level ); } if ( ! subtreecnt && samepartialpr ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "level %u incremental " "non-subtree dump " "will be based on subtree " "level %u resumed dump\n"), sc_level, sc_level ); } assert( sametime ); sc_incrpr = BOOL_TRUE; sc_incrbasetime = undertime; sc_incrbaselevel = underlevel; sc_resumepr = BOOL_TRUE; sc_resumebasetime = sametime; uuid_copy(sc_resumebaseid, sameid); assert( sc_resumerangep ); } } else { if ( underinterruptedpr ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "most recent base for " "incremental dump was " "interrupted (level %u): " "must resume or redump " "at or below level %d\n"), underlevel, sc_level ); return BOOL_FALSE; } if ( subtreecnt && ! underpartialpr ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "level %u incremental " "subtree dump " "will be based on non-subtree " "level %u dump\n"), sc_level, underlevel ); } if ( ! subtreecnt && underpartialpr ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "level %u incremental " "non-subtree dump " "will be based on subtree " "level %u dump\n"), sc_level, underlevel ); } sc_incrpr = BOOL_TRUE; sc_incrbasetime = undertime; sc_incrbaselevel = underlevel; uuid_copy(sc_incrbaseid, underid); sc_resumepr = BOOL_FALSE; assert( ! sc_resumerangep ); } } else { if ( samefoundpr ) { assert( sametime ); if ( subtreecnt && ! samepartialpr ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "level %u " "subtree dump " "will be based on non-subtree " "level %u resumed dump\n"), sc_level, sc_level ); } if ( ! subtreecnt && samepartialpr ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "level %u " "non-subtree dump " "will be based on subtree " "level %u resumed dump\n"), sc_level, sc_level ); } sc_incrpr = BOOL_FALSE; sc_resumepr = BOOL_TRUE; sc_resumebasetime = sametime; uuid_copy(sc_resumebaseid, sameid); assert( sc_resumerangep ); } else { sc_incrpr = BOOL_FALSE; sc_resumepr = BOOL_FALSE; assert( ! sc_resumerangep ); if ( sc_level > 0 ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "cannot find earlier dump " "to base level %d increment upon\n"), sc_level ); return BOOL_FALSE; } } } /* don't allow interrupted dumps of a lesser level to be bases */ if ( sc_incrpr && underinterruptedpr ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "most recent base dump (level %d begun %s) " "was interrupted: aborting\n"), sc_incrbaselevel, ctimennl( &sc_incrbasetime )); return BOOL_FALSE; } /* reject if resume (-R) specified, but base was not interrupted */ if ( ! sc_resumepr && resumereqpr ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "resume (-R) option inappropriate: " "no interrupted level %d dump to resume\n"), sc_level ); return BOOL_FALSE; } /* announce the dump characteristics */ if ( sc_incrpr ) { if ( sc_resumepr ) { char restimestr[ 30 ]; char incrtimestr[ 30 ]; strcpy( restimestr, ctimennl( &sc_resumebasetime )); assert( strlen( restimestr ) < sizeof( restimestr )); strcpy( incrtimestr, ctimennl( &sc_incrbasetime )); assert( strlen( incrtimestr ) < sizeof( incrtimestr )); mlog( MLOG_VERBOSE, _( "resuming level %d incremental dump of %s:%s " "begun %s " "(incremental base level %d begun %s)\n"), sc_level, gwhdrtemplatep->gh_hostname, mntpnt, restimestr, sc_incrbaselevel, incrtimestr ); } else { mlog( MLOG_VERBOSE, _( "level %d incremental dump of %s:%s " "based on level %d dump begun %s\n"), sc_level, gwhdrtemplatep->gh_hostname, mntpnt, sc_incrbaselevel, ctimennl( &sc_incrbasetime )); } } else { if ( sc_resumepr ) { mlog( MLOG_VERBOSE, _( "resuming level %d dump of %s:%s begun %s\n"), sc_level, gwhdrtemplatep->gh_hostname, mntpnt, ctimennl( &sc_resumebasetime )); } else { mlog( MLOG_VERBOSE, _( "level %d dump of %s:%s\n"), sc_level, gwhdrtemplatep->gh_hostname, mntpnt ); } } if ( preemptchk( PREEMPT_FULL )) { return BOOL_FALSE; } /* announce the dump time */ mlog( MLOG_VERBOSE, _( "dump date: %s\n"), ctimennl( &gwhdrtemplatep->gh_timestamp )); /* display the session UUID */ { char string_uuid[UUID_STR_LEN + 1]; uuid_unparse( gwhdrtemplatep->gh_dumpid, string_uuid ); mlog( MLOG_VERBOSE, _( "session id: %s\n"), string_uuid ); } /* display the session label */ mlog( MLOG_VERBOSE, _( "session label: \"%s\"\n"), gwhdrtemplatep->gh_dumplabel ); /* get a file descriptor for the file system. any file * contained in the file system will do; use the mntpnt. * needed by bigstat. */ sc_fsfd = open( mntpnt, O_RDONLY ); if ( sc_fsfd < 0 ) { mlog( MLOG_NORMAL, _( "unable to open %s: %s\n"), mntpnt, strerror( errno )); return BOOL_FALSE; } /* figure out the ino for the root directory of the fs * and get its xfs_bstat_t for inomap_build() */ { stat64_t rootstat; rval = fstat64( sc_fsfd, &rootstat ); if ( rval ) { mlog( MLOG_NORMAL, _( "could not stat %s\n"), mntpnt ); return BOOL_FALSE; } sc_rootxfsstatp = ( xfs_bstat_t * )calloc( 1, sizeof( xfs_bstat_t )); assert( sc_rootxfsstatp ); if ( bigstat_one( sc_fsfd, rootstat.st_ino, sc_rootxfsstatp) < 0 ) { mlog( MLOG_ERROR, _("failed to get bulkstat information for root inode\n")); return BOOL_FALSE; } } /* alloc a file system handle, to be used with the jdm_open() * functions. */ sc_fshandlep = jdm_getfshandle( mntpnt ); if ( ! sc_fshandlep ) { mlog( MLOG_NORMAL, _( "unable to construct a file system handle for %s: %s\n"), mntpnt, strerror( errno )); return BOOL_FALSE; } if ( preemptchk( PREEMPT_FULL )) { return BOOL_FALSE; } /* If GETOPT_DUMPASOFFLINE was specified, allocate a filesystem context * for use by the HSM routines. */ if (sc_dumpasoffline) { hsm_fs_ctxtp = HsmInitFsysContext(mntpnt, HSM_API_VERSION_1); } /* set now so statline can be displayed */ sc_stat_starttime = gwhdrtemplatep->gh_timestamp; /* allocate storage for the stream startpoints, and build inomap. * inomap_build() also fills in the start points. storage only needed * until the startpoints are copied into each streams header. will * be freed at the end of this function. */ sc_stat_inomapcnt = ( size64_t )fs_getinocnt( mntpnt ); sc_startptp = ( startpt_t * )calloc( drivecnt, sizeof( startpt_t )); assert( sc_startptp ); ok = inomap_build( sc_fshandlep, sc_fsfd, sc_rootxfsstatp, sc_incrpr, sc_incrbasetime, sc_resumepr, sc_resumebasetime, sc_resumerangecnt, sc_resumerangep, subtreep, subtreecnt, skip_unchanged_dirs, sc_startptp, drivecnt, &sc_stat_inomapphase, &sc_stat_inomappass, sc_stat_inomapcnt, &sc_stat_inomapdone ); free( ( void * )subtreep ); subtreep = 0; if ( ! ok ) { return BOOL_FALSE; } /* ask var to ask inomap to skip files under var if var is in * the fs being dumped */ var_skip( &fsid, inomap_skip ); /* fill in write header template content info. always produce * an inomap for each media file. the dirdump flag will be set * in content_stream_dump() for streams which dump the directories. */ assert( sizeof( cwhdrtemplatep->ch_specific ) >= sizeof( *scwhdrtemplatep )); scwhdrtemplatep->cih_mediafiletype = CIH_MEDIAFILETYPE_DATA; scwhdrtemplatep->cih_level = ( int32_t )sc_level; scwhdrtemplatep->cih_dumpattr = CIH_DUMPATTR_INOMAP; if ( subtreecnt ) { scwhdrtemplatep->cih_dumpattr |= CIH_DUMPATTR_SUBTREE; } if ( sc_inv_updatepr ) { scwhdrtemplatep->cih_dumpattr |= CIH_DUMPATTR_INVENTORY; } scwhdrtemplatep->cih_dumpattr |= CIH_DUMPATTR_FILEHDR_CHECKSUM; scwhdrtemplatep->cih_dumpattr |= CIH_DUMPATTR_EXTENTHDR_CHECKSUM; scwhdrtemplatep->cih_dumpattr |= CIH_DUMPATTR_DIRENTHDR_CHECKSUM; scwhdrtemplatep->cih_dumpattr |= CIH_DUMPATTR_DIRENTHDR_GEN; if ( sc_incrpr ) { scwhdrtemplatep->cih_dumpattr |= CIH_DUMPATTR_INCREMENTAL; scwhdrtemplatep->cih_last_time = sc_incrbasetime; uuid_copy(scwhdrtemplatep->cih_last_id, sc_incrbaseid); if ( skip_unchanged_dirs ) { scwhdrtemplatep->cih_dumpattr |= CIH_DUMPATTR_NOTSELFCONTAINED; } } if ( sc_resumepr ) { scwhdrtemplatep->cih_dumpattr |= CIH_DUMPATTR_RESUME; scwhdrtemplatep->cih_resume_time = sc_resumebasetime; uuid_copy(scwhdrtemplatep->cih_resume_id, sc_resumebaseid); } if ( sc_dumpextattrpr ) { scwhdrtemplatep->cih_dumpattr |= CIH_DUMPATTR_EXTATTR; scwhdrtemplatep->cih_dumpattr |= CIH_DUMPATTR_EXTATTRHDR_CHECKSUM; } scwhdrtemplatep->cih_rootino = sc_rootxfsstatp->bs_ino; inomap_writehdr( scwhdrtemplatep ); /* log the dump size. just a rough approx. */ dircnt = scwhdrtemplatep->cih_inomap_dircnt; nondircnt = scwhdrtemplatep->cih_inomap_nondircnt; datasz = scwhdrtemplatep->cih_inomap_datasz; inocnt = dircnt + nondircnt; inomapsz = inomap_getsz( ); direntsz = inocnt * ( uint64_t )( DIRENTHDR_SZ + 8 ); filesz = inocnt * ( uint64_t )( FILEHDR_SZ + EXTENTHDR_SZ ); hdr_mfilesz = GLOBAL_HDR_SZ + inomapsz + direntsz; size_estimate = hdr_mfilesz + filesz + datasz; mlog( MLOG_VERBOSE, _( "estimated dump size: %llu bytes\n"), size_estimate ); if (drivecnt > 1) { mlog( MLOG_VERBOSE, _( "estimated dump size per stream: %llu bytes\n"), hdr_mfilesz + (filesz + datasz) / drivecnt); } mlog( MLOG_DEBUG, "estimated dump header size: %llu bytes\n", hdr_mfilesz ); mlog( MLOG_DEBUG, "estimated component sizes: global hdr: %llu bytes, " "inomap: %llu bytes, dir entries: %llu bytes, " "file hdrs: %llu bytes, datasz: %llu bytes\n", GLOBAL_HDR_SZ, inomapsz, direntsz, filesz, datasz ); /* extract the progress stat denominators from the write hdr * template. placed there by inomap_writehdr( ) */ sc_stat_dircnt = scwhdrtemplatep->cih_inomap_dircnt; sc_stat_nondircnt = scwhdrtemplatep->cih_inomap_nondircnt; sc_stat_datasz = scwhdrtemplatep->cih_inomap_datasz; /* allocate and populate per-stream context descriptors */ sc_contextp = ( context_t * )calloc( drivecnt, sizeof( context_t )); assert( sc_contextp ); for ( strmix = 0 ; strmix < drivecnt ; strmix++ ) { context_t *contextp = &sc_contextp[ strmix ]; contextp->cc_filehdrp = ( filehdr_t * )calloc( 1, sizeof( filehdr_t )); assert( contextp->cc_filehdrp ); contextp->cc_extenthdrp = ( extenthdr_t * )calloc( 1, sizeof( extenthdr_t )); assert( contextp->cc_extenthdrp ); contextp->cc_getdentsbufsz = sizeof( struct dirent ) + NAME_MAX + 1; if ( contextp->cc_getdentsbufsz < GETDENTSBUF_SZ_MIN ) { contextp->cc_getdentsbufsz = GETDENTSBUF_SZ_MIN; } contextp->cc_getdentsbufp = ( char * ) calloc( 1, contextp->cc_getdentsbufsz ); assert( contextp->cc_getdentsbufp ); contextp->cc_mdirentbufsz = sizeof( direnthdr_t ) + NAME_MAX + 1 + DIRENTHDR_ALIGN; contextp->cc_mdirentbufp = ( char * ) calloc( 1, contextp->cc_mdirentbufsz ); assert( contextp->cc_mdirentbufp ); contextp->cc_extattrlistbufsz = EXTATTR_LISTBUF_SZ; contextp->cc_extattrrtrvarraylen = EXTATTR_RTRVARRAY_LEN; contextp->cc_extattrdumpbufsz = 2 * ATTR_MAX_VALUELEN; if ( contextp->cc_extattrdumpbufsz < EXTATTR_DUMPBUF_SZ ) { contextp->cc_extattrdumpbufsz = EXTATTR_DUMPBUF_SZ; } contextp->cc_extattrlistbufp = ( char * )calloc( 1, contextp->cc_extattrlistbufsz ); assert( contextp->cc_extattrlistbufp ); contextp->cc_extattrrtrvarrayp = ( attr_multiop_t * )calloc( contextp->cc_extattrrtrvarraylen, sizeof( attr_multiop_t )); assert( contextp->cc_extattrrtrvarrayp ); contextp->cc_extattrdumpbufp = ( char * )memalign( sizeof( extattrhdr_t ), contextp->cc_extattrdumpbufsz ); assert( contextp->cc_extattrdumpbufp ); if (hsm_fs_ctxtp) { contextp->cc_hsm_f_ctxtp = HsmAllocateFileContext( hsm_fs_ctxtp); } else { contextp->cc_hsm_f_ctxtp = NULL; } contextp->cc_readlinkbufsz = MAXPATHLEN + SYMLINK_ALIGN; contextp->cc_readlinkbufp = ( char * ) calloc( 1, contextp->cc_readlinkbufsz ); assert( contextp->cc_readlinkbufp ); contextp->cc_inomap_contextp = inomap_alloc_context( ); } /* look for command line media labels. these will be assigned * to each stream as found. this label is only for the media * object currently in the drive. subsequently inserted media * objects must get a label via prompting. */ { context_t *cp = sc_contextp; context_t *ep = sc_contextp + drivecnt; optind = 1; opterr = 0; while ( ( c = getopt( argc, argv, GETOPT_CMDSTRING )) != EOF ) { switch ( c ) { case GETOPT_MEDIALABEL: if ( cp >= ep ) { mlog( MLOG_NORMAL, _( "more -%c arguments " "than number of drives\n"), c ); usage( ); return BOOL_FALSE; } if ( ! optarg || optarg[ 0 ] == '-' ) { mlog( MLOG_NORMAL, _( "-%c argument missing\n"), c ); usage( ); return BOOL_FALSE; } cp->cc_Media_firstlabel = optarg; cp++; break; } } if ( cp > sc_contextp && cp < ep ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "media labels given for only %d out of %d " "drives\n"), cp - sc_contextp, drivecnt ); } } if ( preemptchk( PREEMPT_FULL )) { return BOOL_FALSE; } /* open the dump inventory and a dump inventory write session * if an inventory update is to be done. */ if ( sc_inv_updatepr ) { bool_t result; sigset_t tty_set, orig_set; /* hold tty signals while creating a new inventory session */ sigemptyset( &tty_set ); sigaddset( &tty_set, SIGINT ); sigaddset( &tty_set, SIGQUIT ); sigaddset( &tty_set, SIGHUP ); pthread_sigmask( SIG_BLOCK, &tty_set, &orig_set ); result = create_inv_session( gwhdrtemplatep, &fsid, mntpnt, fsdevice, subtreecnt, strmix ); pthread_sigmask( SIG_SETMASK, &orig_set, NULL ); if ( !result ) { return BOOL_FALSE; } } /* set media change flags to FALSE; */ { ix_t ix; ix_t endix = sizeof( sc_mcflag ) / sizeof( sc_mcflag[ 0 ] ); for ( ix = 0 ; ix < endix ; ix++ ) { sc_mcflag[ ix ] = BOOL_FALSE; } } content_media_change_needed = BOOL_FALSE; /* initialize the per-drive status */ { ix_t driveix; for ( driveix = 0 ; driveix < STREAM_SIMMAX ; driveix++ ) { sc_stat_pds[ driveix ].pds_phase = PDS_NULL; } } return BOOL_TRUE; } #define STATLINESZ 160 size_t content_statline( char **linespp[ ] ) { static char statlinebuf[ STREAM_SIMMAX + 1 ][ STATLINESZ ]; static char *statline[ STREAM_SIMMAX + 1 ]; size_t statlinecnt; size64_t nondirdone; size64_t datadone; double percent; time_t elapsed; time_t now; struct tm *tmp; ix_t i; /* build and supply the line array */ for ( i = 0 ; i < STREAM_SIMMAX + 1 ; i++ ) { statline[ i ] = &statlinebuf[ i ][ 0 ]; } *linespp = statline; statlinecnt = 0; /* if start time not initialized, return no strings */ if ( ! sc_stat_starttime ) { return 0; } /* calculate the elapsed time */ now = time( 0 ); elapsed = now - sc_stat_starttime; /* get local time */ tmp = localtime( &now ); /* if inomap phase indicated, report on that */ if ( sc_stat_inomapphase && sc_stat_inomapcnt ) { if ( sc_stat_inomappass ) { sprintf( statline[ 0 ], "status at %02d:%02d:%02d: " "inomap phase %u pass %u " "%llu/%llu inos scanned, " "%ld seconds elapsed\n", tmp->tm_hour, tmp->tm_min, tmp->tm_sec, (unsigned int)sc_stat_inomapphase, (unsigned int)sc_stat_inomappass, (unsigned long long)sc_stat_inomapdone, (unsigned long long)sc_stat_inomapcnt, elapsed ); assert( strlen( statline[ 0 ] ) < STATLINESZ ); } else { sprintf( statline[ 0 ], "status at %02d:%02d:%02d: " "inomap phase %u " "%llu/%llu inos scanned, " "%ld seconds elapsed\n", tmp->tm_hour, tmp->tm_min, tmp->tm_sec, (unsigned int)sc_stat_inomapphase, (unsigned long long)sc_stat_inomapdone, (unsigned long long)sc_stat_inomapcnt, elapsed ); assert( strlen( statline[ 0 ] ) < STATLINESZ ); } return 1; } /* get the accumulated totals for non-dir inos and data bytes dumped */ lock( ); nondirdone = sc_stat_nondirdone; datadone = sc_stat_datadone; unlock( ); /* non-dir dump phase */ if ( nondirdone || datadone ) { /* calculate percentage of data dumped */ if ( sc_stat_datasz ) { percent = ( double )datadone / ( double )sc_stat_datasz; percent *= 100.0; } else { percent = 100.0; } if ( percent > 100.0 ) { percent = 100.0; } /* format the status line in a local static buffer (non-re-entrant!) */ sprintf( statline[ 0 ], "status at %02d:%02d:%02d: %llu/%llu files dumped, " "%.1lf%%%% data dumped, " "%ld seconds elapsed\n", tmp->tm_hour, tmp->tm_min, tmp->tm_sec, (unsigned long long) nondirdone, (unsigned long long) sc_stat_nondircnt, percent, elapsed ); } else { sprintf( statline[ 0 ], "status at %02d:%02d:%02d: " "%ld seconds elapsed\n", tmp->tm_hour, tmp->tm_min, tmp->tm_sec, elapsed ); } assert( strlen( statline[ 0 ] ) < STATLINESZ ); /* optionally create stat lines for each drive */ statlinecnt = 1; for ( i = 0 ; i < drivecnt ; i++ ) { pds_t *pdsp = &sc_stat_pds[ i ]; if ( pdsp->pds_phase == PDS_NULL || pdsp->pds_phase == PDS_NONDIR ) { continue; } statline[ statlinecnt ][ 0 ] = 0; if ( drivecnt > 1 ) { sprintf( statline[ statlinecnt ], "drive %u: ", (unsigned int)i ); } switch( pdsp->pds_phase ) { case PDS_INOMAP: strcat( statline[ statlinecnt ], "dumping inomap" ); break; case PDS_DIRDUMP: sprintf( &statline[ statlinecnt ] [ strlen( statline[ statlinecnt ] ) ], "%llu/%llu directories dumped", (unsigned long long)pdsp->pds_dirdone, (unsigned long long)sc_stat_dircnt ); break; case PDS_INVSYNC: strcat( statline[ statlinecnt ], "waiting to dump inventory" ); break; case PDS_INVDUMP: strcat( statline[ statlinecnt ], "dumping inventory" ); break; case PDS_TERMDUMP: strcat( statline[ statlinecnt ], "dumping stream terminator" ); break; default: break; } sprintf( &statline[ statlinecnt ] [ strlen( statline[ statlinecnt ] ) ], "\n" ); assert( strlen( statline[ statlinecnt ] ) < STATLINESZ ); statlinecnt++; } return statlinecnt; } static bool_t create_inv_session( global_hdr_t *gwhdrtemplatep, uuid_t *fsidp, const char *mntpnt, const char *fsdevice, ix_t subtreecnt, size_t strmix) { int rval; char *qmntpnt; char *qfsdevice; /* create a cleanup handler to close the inventory on exit. */ rval = atexit( inv_cleanup ); assert( ! rval ); sc_inv_idbtoken = inv_open( ( inv_predicate_t )INV_BY_UUID, INV_SEARCH_N_MOD, ( void * )fsidp ); if ( sc_inv_idbtoken == INV_TOKEN_NULL ) { return BOOL_FALSE; } qmntpnt = ( char * )calloc( 1, strlen( gwhdrtemplatep->gh_hostname ) + 1 + strlen( mntpnt ) + 1 ); assert( qmntpnt ); assert( strlen( gwhdrtemplatep->gh_hostname )); sprintf( qmntpnt, "%s:%s", gwhdrtemplatep->gh_hostname, mntpnt ); qfsdevice = ( char * )calloc( 1, strlen( gwhdrtemplatep->gh_hostname ) + 1 + strlen( fsdevice ) + 1 ); assert( qfsdevice ); sprintf( qfsdevice, "%s:%s", gwhdrtemplatep->gh_hostname, fsdevice ); sc_inv_sestoken = inv_writesession_open( sc_inv_idbtoken, fsidp, &gwhdrtemplatep->gh_dumpid, gwhdrtemplatep->gh_dumplabel, subtreecnt ? BOOL_TRUE : BOOL_FALSE, sc_resumepr, ( u_char_t )sc_level, drivecnt, gwhdrtemplatep->gh_timestamp, qmntpnt, qfsdevice ); if ( sc_inv_sestoken == INV_TOKEN_NULL ) { return BOOL_FALSE; } /* open an inventory stream for each stream */ sc_inv_stmtokenp = ( inv_stmtoken_t * ) calloc( drivecnt, sizeof( inv_stmtoken_t )); assert( sc_inv_stmtokenp ); for ( strmix = 0 ; strmix < drivecnt ; strmix++ ) { drive_t *drivep = drivepp[ strmix ]; char *drvpath; if ( strcmp( drivep->d_pathname, "stdio" )) { drvpath = path_reltoabs( drivep->d_pathname, homedir ); } else { drvpath = drivep->d_pathname; } sc_inv_stmtokenp[ strmix ] = inv_stream_open( sc_inv_sestoken, drvpath ); if ( strcmp( drivep->d_pathname, "stdio" )) { free( ( void * )drvpath ); } if ( sc_inv_stmtokenp[ strmix ] == INV_TOKEN_NULL ) { return BOOL_FALSE; } } return BOOL_TRUE; } static void mark_set( drive_t *drivep, xfs_ino_t ino, off64_t offset, int32_t flags ) { drive_ops_t *dop = drivep->d_opsp; mark_t *markp = ( mark_t * )calloc( 1, sizeof( mark_t )); assert( markp ); if ( flags & STARTPT_FLAGS_NULL ) { mlog( MLOG_DEBUG, "setting media NULL mark\n" ); } else if ( flags & STARTPT_FLAGS_END ) { mlog( MLOG_DEBUG, "setting media END mark\n" ); } else { mlog( MLOG_DEBUG, "setting media mark" " for ino %llu offset %lld\n", ino, offset ); } markp->startpt.sp_ino = ino; markp->startpt.sp_offset = offset; markp->startpt.sp_flags = flags; ( * dop->do_set_mark )( drivep, mark_callback, ( void * )drivep->d_index, ( drive_markrec_t * )markp ); } static void mark_callback( void *p, drive_markrec_t *dmp, bool_t committed ) { /* get context */ ix_t strmix = ( ix_t )p; context_t *contextp = &sc_contextp[ strmix ]; drive_t *drivep = drivepp[ strmix ]; drive_hdr_t *dwhdrp = drivep->d_writehdrp; media_hdr_t *mwhdrp = ( media_hdr_t * )dwhdrp->dh_upper; content_hdr_t *cwhdrp = ( content_hdr_t * )mwhdrp->mh_upper; content_inode_hdr_t *scwhdrp = ( content_inode_hdr_t * ) ( void * ) cwhdrp->ch_specific; /* this is really a mark_t, allocated by mark_set() */ mark_t *markp = ( mark_t * )dmp; if ( committed ) { /* bump the per-mfile mark committed count */ contextp->cc_markscommitted++; /* copy the mark into the write header: this establishes the * starting point should we need to retry the non-dir portion * of the dump */ /* log the mark commit */ if ( markp->startpt.sp_flags & STARTPT_FLAGS_NULL ) { mlog( MLOG_DEBUG, "media NULL mark committed" " in media file %d\n", mwhdrp->mh_dumpfileix ); scwhdrp->cih_startpt.sp_flags |= STARTPT_FLAGS_NULL; } else if ( markp->startpt.sp_flags & STARTPT_FLAGS_END ) { mlog( MLOG_DEBUG, "media END mark committed" " in media file %d\n", mwhdrp->mh_dumpfileix ); if ( scwhdrp->cih_endpt.sp_flags & STARTPT_FLAGS_END ) { scwhdrp->cih_startpt.sp_ino++; scwhdrp->cih_startpt.sp_offset = 0; } else { scwhdrp->cih_startpt = scwhdrp->cih_endpt; } scwhdrp->cih_startpt.sp_flags |= STARTPT_FLAGS_END; } else { mlog( MLOG_DEBUG, "media mark committed" " for ino %llu offset %lld" " in media file %d\n", markp->startpt.sp_ino, markp->startpt.sp_offset, mwhdrp->mh_dumpfileix ); scwhdrp->cih_startpt = markp->startpt; } } else { /* note the mark was not committed */ if ( markp->startpt.sp_flags & STARTPT_FLAGS_NULL ) { mlog( MLOG_DEBUG, "media NULL mark -NOT- committed\n" ); } else if ( markp->startpt.sp_flags & STARTPT_FLAGS_END ) { mlog( MLOG_DEBUG, "media END mark -NOT- committed\n" ); } else { mlog( MLOG_DEBUG, "media mark -NOT- committed" " for ino %llu offset %lld\n", markp->startpt.sp_ino, markp->startpt.sp_offset ); } } /* get rid of this mark (it was allocated by mark_set()) */ free( ( void * )markp ); } /* begin - called by stream process to invoke the dump stream */ int content_stream_dump( ix_t strmix ) { context_t *contextp = &sc_contextp[ strmix ]; drive_t *drivep = drivepp[ strmix ]; drive_hdr_t *dwhdrp = drivep->d_writehdrp; media_hdr_t *mwhdrp = ( media_hdr_t * )dwhdrp->dh_upper; content_hdr_t *cwhdrp = ( content_hdr_t * )mwhdrp->mh_upper; content_inode_hdr_t *scwhdrp = ( content_inode_hdr_t * ) cwhdrp->ch_specific; void *inomap_contextp; bool_t all_nondirs_committed; bool_t empty_mediafile; time_t elapsed; inv_stmtoken_t inv_stmt; xfs_bstat_t *bstatbufp; const size_t bstatbuflen = BSTATBUFLEN; int rval; rv_t rv; /* sanity checks */ assert( RV_OK == 0 ); /* bigstat_iter depends on this */ /* allocate a buffer for use by bstat_iter */ bstatbufp = ( xfs_bstat_t * )calloc( bstatbuflen, sizeof( xfs_bstat_t )); assert( bstatbufp ); /* allocate an inomap context */ inomap_contextp = inomap_alloc_context(); assert( inomap_contextp ); /* determine if stream terminators will be used and are expected. * this will be revised each time a new media file is begun. */ update_cc_Media_useterminatorpr( drivep, contextp ); /* check in */ lock( ); sc_thrdsarrivedcnt++; unlock( ); /* fill in write hdr stream start and end points */ scwhdrp->cih_startpt = sc_startptp[ strmix ]; if ( strmix < drivecnt - 1 ) { scwhdrp->cih_endpt = sc_startptp[ strmix + 1 ]; } else { scwhdrp->cih_endpt.sp_flags = STARTPT_FLAGS_END; } // the first stream dumps the directories if ( strmix == 0 ) { scwhdrp->cih_dumpattr |= CIH_DUMPATTR_DIRDUMP; } /* fill in inomap fields of write hdr */ inomap_writehdr( scwhdrp ); /* used to decide if any non-dirs not yet on media */ all_nondirs_committed = BOOL_FALSE; /* used to guarantee we don't count the same ino more than once * in the progress stats */ contextp->cc_stat_lastino = 0; /* used to detect generation of an empty media file; * contains at most an inomap and dirdump and null file hdr. */ empty_mediafile = BOOL_FALSE; /* get the inventory stream token */ if ( sc_inv_stmtokenp ) { inv_stmt = sc_inv_stmtokenp[ strmix ]; } else { inv_stmt = INV_TOKEN_NULL; } /* loop, dumping media files, until the entire stream is dumped. * each time we hit EOM/EOF, repeat the inomap and directory dump. * dump the non-dirs beginning with the current startpoint. * The current startpoint will be updated each time a media mark * is committed. */ for ( ; ; ) { xfs_ino_t startino; bool_t stop_requested; bool_t hit_eom; bool_t all_dirs_committed; bool_t all_nondirs_sent; off64_t startoffset; off64_t ncommitted; bool_t done; /* used to decide whether or not to go back for more. */ stop_requested = BOOL_FALSE; /* TRUE if hit EOM while dumping */ hit_eom = BOOL_FALSE; /* used to decide if the media file contains all * of the inomap and dirdump. */ all_dirs_committed = BOOL_FALSE; /* used to decide if all non-dirs were sent (not necessarily * committed) */ all_nondirs_sent = BOOL_FALSE; /* always clear the NULL flag from the stream startpoint * before beginning the media file. allows detection * of null file hdr commit. */ scwhdrp->cih_startpt.sp_flags &= ~STARTPT_FLAGS_NULL; /* save the original start points, to be given to * the inventory at the end of each media file. */ startino = scwhdrp->cih_startpt.sp_ino; startoffset = scwhdrp->cih_startpt.sp_offset; /* set the accumulated file size to zero. * this will be monitored by dump_file() to decide * if the current dump file is too long. if so, * it will set a startpoint and spoof an EOF. * this will cause a new dump file to be started, * beginning at the startpoint. */ contextp->cc_mfilesz = 0; /* tell the Media abstraction to position a media object * and begin a new media file. This will dump the media * file header if successful. */ rv = Media_mfile_begin( drivep, contextp, BOOL_TRUE ); if ( rv == RV_INTR ) { return mlog_exit(EXIT_INTERRUPT, rv); } if ( rv == RV_TIMEOUT ) { mlog( MLOG_VERBOSE | MLOG_WARNING, _( "media change timeout will be treated as " "a request to stop using drive: " "can resume later\n") ); mlog_exit_hint(RV_QUIT); return mlog_exit(EXIT_NORMAL, rv); } if ( rv == RV_QUIT ) { mlog( MLOG_VERBOSE | MLOG_WARNING, _( "media change decline will be treated as " "a request to stop using drive: " "can resume later\n") ); mlog_exit_hint(RV_QUIT); return mlog_exit(EXIT_NORMAL, rv); } if ( rv == RV_DRIVE ) { return mlog_exit(EXIT_NORMAL, rv); } if ( rv == RV_ERROR ) { return mlog_exit(EXIT_ERROR, rv); } if ( rv == RV_CORE ) { return mlog_exit(EXIT_FAULT, rv); } assert( rv == RV_OK ); if ( rv != RV_OK ) { return mlog_exit(EXIT_FAULT, rv); } /* sync up here with other streams if reasonable */ mlog( MLOG_VERBOSE, _( "creating dump session media file %u " "(media %u, file %u)\n"), mwhdrp->mh_dumpfileix, mwhdrp->mh_mediaix, mwhdrp->mh_mediafileix ); /* initialize the count of marks committed in the media file. * will be bumped by mark_callback(). */ contextp->cc_markscommitted = 0; /* first dump the inomap */ mlog( MLOG_VERBOSE, _( "dumping ino map\n") ); sc_stat_pds[ strmix ].pds_phase = PDS_INOMAP; rv = inomap_dump( drivep ); if ( rv == RV_INTR ) { stop_requested = BOOL_TRUE; goto decision_more; } if ( rv == RV_EOM ) { hit_eom = BOOL_TRUE; goto decision_more; } if ( rv == RV_DRIVE ) { free( ( void * )bstatbufp ); return mlog_exit(EXIT_NORMAL, rv); } if ( rv == RV_ERROR ) { free( ( void * )bstatbufp ); return mlog_exit(EXIT_ERROR, rv); } if ( rv == RV_CORE ) { free( ( void * )bstatbufp ); return mlog_exit(EXIT_FAULT, rv); } assert( rv == RV_OK ); if ( rv != RV_OK ) { free( ( void * )bstatbufp ); return mlog_exit(EXIT_FAULT, rv); } /* now dump the directories, if this is a stream that dumps * directories. use the bigstat iterator capability to call * my dump_dir function for each directory in the bitmap. */ if ( scwhdrp->cih_dumpattr & CIH_DUMPATTR_DIRDUMP ) { sc_stat_pds[ strmix ].pds_dirdone = 0; rv = dump_dirs( strmix, bstatbufp, bstatbuflen, inomap_contextp ); if ( rv == RV_INTR ) { stop_requested = BOOL_TRUE; goto decision_more; } if ( rv == RV_EOM ) { hit_eom = BOOL_TRUE; goto decision_more; } if ( rv == RV_DRIVE ) { free( ( void * )bstatbufp ); return mlog_exit(EXIT_NORMAL, rv); } if ( rv == RV_ERROR ) { free( ( void * )bstatbufp ); return mlog_exit(EXIT_ERROR, rv); } if ( rv == RV_CORE ) { free( ( void * )bstatbufp ); return mlog_exit(EXIT_FAULT, rv); } assert( rv == RV_OK ); if ( rv != RV_OK ) { free( ( void * )bstatbufp ); return mlog_exit(EXIT_FAULT, rv); } } /* finally, dump the non-directory files beginning with this * stream's startpoint. Note that dump_file will set one or * more media marks; the callback will update the hdr's * startpoint; thus each time a demarcated portion of a * non-directory file is fully committed to media, * the starting point for the next media file will be advanced. */ if ( ! all_nondirs_committed ) { mlog( MLOG_VERBOSE, _( "dumping non-directory files\n") ); sc_stat_pds[ strmix ].pds_phase = PDS_NONDIR; rv = RV_OK; inomap_reset_context(inomap_contextp); rval = bigstat_iter( sc_fshandlep, sc_fsfd, BIGSTAT_ITER_NONDIR, scwhdrp->cih_startpt.sp_ino, ( bstat_cbfp_t )dump_file, ( void * )strmix, inomap_next_nondir, inomap_contextp, ( int * )&rv, pipeline ? (bool_t (*)(int))preemptchk : 0, bstatbufp, bstatbuflen ); if ( rval ) { free( ( void * )bstatbufp ); return mlog_exit(EXIT_FAULT, RV_CORE); } if ( rv == RV_INTR ) { stop_requested = BOOL_TRUE; goto decision_more; } if ( rv == RV_EOM ) { hit_eom = BOOL_TRUE; goto decision_more; } if ( rv == RV_EOF ) { goto decision_more; } if ( rv == RV_DRIVE ) { free( ( void * )bstatbufp ); return mlog_exit(EXIT_NORMAL, rv); } if ( rv == RV_ERROR ) { free( ( void * )bstatbufp ); return mlog_exit(EXIT_ERROR, rv); } if ( rv == RV_CORE ) { free( ( void * )bstatbufp ); return mlog_exit(EXIT_FAULT, rv); } assert( rv == RV_OK || rv == RV_NOMORE ); if ( rv != RV_OK && rv != RV_NOMORE ) { free( ( void * )bstatbufp ); return mlog_exit(EXIT_FAULT, rv); } } /* if we got here, all files were sent without hitting * the end of the current media object, or hitting the * media file size limit. send the special END mark. * this is only send at the end of the last media file in the * dump session. if it actually gets committed to media, * we know the last data written to media all made it. * we won't know if this mark is committed to media until * we attempt to end the write stream. */ all_nondirs_sent = BOOL_TRUE; mark_set( drivep, INO64MAX, OFF64MAX, STARTPT_FLAGS_END ); decision_more: /* write a null file hdr, to let restore recognize * the end of the media file. the flags indicate * whether or not this is intended to be the last * media file in the stream. don't bother if we hit * EOM. */ if ( ! hit_eom ) { rv = dump_filehdr( drivep, contextp, 0, 0, all_nondirs_sent ? ( FILEHDR_FLAGS_NULL | FILEHDR_FLAGS_END ) : FILEHDR_FLAGS_NULL ); if ( rv == RV_DRIVE ) { free( ( void * )bstatbufp ); return mlog_exit(EXIT_NORMAL, rv); } if ( rv == RV_CORE ) { free( ( void * )bstatbufp ); return mlog_exit(EXIT_FAULT, rv); } if ( rv == RV_ERROR ) { free( ( void * )bstatbufp ); return mlog_exit(EXIT_ERROR, rv); } /* send a mark to detect if the null file header made * it. mark callback will adjust start pt before this * call returns if the null file header made it. */ mark_set( drivep, INO64MAX, OFF64MAX, all_nondirs_sent ? STARTPT_FLAGS_NULL | STARTPT_FLAGS_END : STARTPT_FLAGS_NULL ); } /* tell the Media abstraction to end the media file. * this is done before the inventory update, to * see how much was actually committed to media. * will invoke drive end_write, which will flush * all pending marks. */ mlog( MLOG_VERBOSE, _( "ending media file\n") ); ncommitted = 0; rv = Media_mfile_end( drivep, contextp, mwhdrp, &ncommitted, hit_eom ); if ( rv == RV_DRIVE ) { free( ( void * )bstatbufp ); return mlog_exit(EXIT_NORMAL, rv); } if ( rv == RV_CORE ) { free( ( void * )bstatbufp ); return mlog_exit(EXIT_FAULT, rv); } mlog( MLOG_VERBOSE, _( "media file size %lld bytes\n"), ncommitted ); /* if at least one mark committed, we know all of * the inomap and dirdump was committed. */ all_dirs_committed = ( contextp->cc_markscommitted > 0 ); /* at this point we can check the new start point * to determine if all nondirs have been committed. * if this flag was already set, then this is a * inomap and dirdump-only media file. */ if ( scwhdrp->cih_startpt.sp_flags & STARTPT_FLAGS_END ) { if ( all_nondirs_committed ) { empty_mediafile = BOOL_TRUE; } all_nondirs_committed = BOOL_TRUE; } /* we are done if all nondirs have been committed. * it is not necessary for the null file header to have * been committed. */ done = all_nondirs_committed; /* tell the inventory about the media file */ if ( inv_stmt != INV_TOKEN_NULL ) { bool_t ok; if ( ! all_dirs_committed ) { mlog( MLOG_DEBUG, "giving inventory " "partial dirdump media file\n" ); } else if ( done && empty_mediafile ) { mlog( MLOG_DEBUG, "giving inventory " "empty last media file: " "%llu:%lld\n", startino, startoffset ); } else if ( empty_mediafile ) { mlog( MLOG_DEBUG, "giving inventory " "empty media file: " "%llu:%lld\n", startino, startoffset ); } else if ( done ) { mlog( MLOG_DEBUG, "giving inventory " "last media file: " "%llu:%lld\n", startino, startoffset ); } else { mlog( MLOG_DEBUG, "giving inventory " "media file: " "%llu:%lld - %llu:%lld\n", startino, startoffset, scwhdrp->cih_startpt.sp_ino, scwhdrp->cih_startpt.sp_offset ); } /* already thread-safe, don't need to lock */ ok = inv_put_mediafile( inv_stmt, &mwhdrp->mh_mediaid, mwhdrp->mh_medialabel, ( uint )mwhdrp->mh_mediafileix, startino, startoffset, scwhdrp->cih_startpt.sp_ino, scwhdrp->cih_startpt.sp_offset, ncommitted, all_dirs_committed && ! empty_mediafile, BOOL_FALSE ); if ( ! ok ) { mlog( MLOG_NORMAL, _( "inventory media file put failed\n") ); } } if ( done ) { contextp->cc_completepr = BOOL_TRUE; /* so inv_end_stream and main will know */ } /* don't go back for more if done or stop was requested */ if ( done || stop_requested ) { break; } } /* end main dump loop */ /* check in */ lock( ); sc_thrdsdonecnt++; unlock( ); /* dump the session inventory and terminator here, if the drive * supports multiple media files. must wait until all * streams have completed or given up, so all media files * from all streams have been registered. */ if ( drivep->d_capabilities & DRIVE_CAP_FILES ) { if ( stream_cnt( ) > 1 ) { mlog( MLOG_VERBOSE, _( "waiting for synchronized " "session inventory dump\n") ); sc_stat_pds[ strmix ].pds_phase = PDS_INVSYNC; } /* first be sure all threads have begun */ while ( sc_thrdsarrivedcnt < drivecnt ) { sleep( 1 ); } /* now wait for survivors to checkin */ while ( sc_thrdsdonecnt < stream_cnt( )) { sleep( 1 ); } /* proceeed */ sc_stat_pds[ strmix ].pds_phase = PDS_INVDUMP; if ( dump_session_inv( drivep, contextp, mwhdrp, scwhdrp )) { sc_stat_pds[ strmix ].pds_phase = PDS_TERMDUMP; dump_terminator( drivep, contextp, mwhdrp ); } } sc_stat_pds[ strmix ].pds_phase = PDS_NULL; free( ( void * )bstatbufp ); elapsed = time( 0 ) - sc_stat_starttime; mlog( MLOG_TRACE, _( "ending stream: %ld seconds elapsed\n"), elapsed ); return mlog_exit(EXIT_NORMAL, rv); } /* indicates if the dump was complete. * easy to tell: initially contextp->cc_completepr is false for each stream. * only set true if stream complete. if any stream NOT complete, * dump is not complete. */ bool_t content_complete( void ) { time_t elapsed; bool_t completepr; int i; completepr = check_complete_flags( ); elapsed = time( 0 ) - sc_stat_starttime; mlog( MLOG_VERBOSE, _( "dump size (non-dir files) : %llu bytes\n"), sc_stat_datadone ); if ( completepr ) { if( sc_savequotas ) { for(i = 0; i < (sizeof(quotas) / sizeof(quotas[0])); i++) { if( quotas[i].savequotas && unlink( quotas[i].quotapath ) < 0 ) { mlog( MLOG_ERROR, _( "unable to remove %s: %s\n"), quotas[i].quotapath, strerror ( errno )); } } } mlog( MLOG_VERBOSE, _( "dump complete" ": %ld seconds elapsed" "\n"), elapsed ); } else { if ( sc_inv_updatepr ) { mlog( MLOG_VERBOSE | MLOG_NOTE, _( "dump interrupted" ": %ld seconds elapsed" ": may resume later using -%c option" "\n"), elapsed, GETOPT_RESUME ); mlog_exit_hint(RV_INTR); } else { mlog( MLOG_VERBOSE | MLOG_NOTE, _( "dump interrupted" ": %ld seconds elapsed" "\n"), elapsed ); mlog_exit_hint(RV_INTR); } } return completepr; } #define PREAMBLEMAX 3 #define QUERYMAX 1 #define CHOICEMAX 30 #define ACKMAX 3 #define POSTAMBLEMAX 3 #define DLOG_TIMEOUT 300 #define DLOG_TIMEOUT_MEDIA 3600 #define CHOICESTRSZ 10 typedef struct { ix_t thrdix; char choicestr[ CHOICESTRSZ ]; } cttm_t; char * content_mediachange_query( void ) { cttm_t choicetothrdmap[ STREAM_SIMMAX ]; char *querystr[ QUERYMAX ]; size_t querycnt; char *choicestr[ CHOICEMAX ]; size_t choicecnt; size_t maxdrvchoiceix; size_t nochangeix; size_t responseix; ix_t thrdix; querycnt = 0; querystr[ querycnt++ ] = "select a drive to acknowledge media change\n"; choicecnt = 0; maxdrvchoiceix = 0; for ( thrdix = 0 ; thrdix < STREAM_SIMMAX ; thrdix++ ) { if ( sc_mcflag[ thrdix ] ) { choicetothrdmap[ choicecnt ].thrdix = thrdix; sprintf( choicetothrdmap[ choicecnt ].choicestr, "drive %u", (unsigned int)thrdix ); choicestr[ choicecnt ] = choicetothrdmap[ choicecnt ].choicestr; maxdrvchoiceix = choicecnt; choicecnt++; } } nochangeix = choicecnt; choicestr[ choicecnt++ ] = "continue"; assert( choicecnt <= CHOICEMAX ); responseix = dlog_multi_query( querystr, querycnt, choicestr, choicecnt, 0, /* hilitestr */ IXMAX, /* hiliteix */ 0, /* defaultstr */ nochangeix, /* defaultix */ DLOG_TIMEOUT_MEDIA, nochangeix, /* timeout ix */ nochangeix, /* sigint ix */ nochangeix, /* sighup ix */ nochangeix);/* sigquit ix */ if ( responseix <= maxdrvchoiceix ) { clr_mcflag( choicetothrdmap[ responseix ].thrdix ); return "media change acknowledged\n"; } assert( responseix == nochangeix ); return "continuing\n"; } static void update_cc_Media_useterminatorpr( drive_t *drivep, context_t *contextp ) { int dcaps = drivep->d_capabilities; contextp->cc_Media_useterminatorpr = BOOL_TRUE; if ( ! ( dcaps & DRIVE_CAP_FILES )) { contextp->cc_Media_useterminatorpr = BOOL_FALSE; } if ( ! ( dcaps & DRIVE_CAP_OVERWRITE )) { contextp->cc_Media_useterminatorpr = BOOL_FALSE; } if ( ! ( dcaps & DRIVE_CAP_BSF )) { contextp->cc_Media_useterminatorpr = BOOL_FALSE; } if ( ! ( dcaps & DRIVE_CAP_APPEND )) { contextp->cc_Media_useterminatorpr = BOOL_FALSE; } } static rv_t dump_dirs( ix_t strmix, xfs_bstat_t *bstatbufp, size_t bstatbuflen, void *inomap_contextp ) { xfs_ino_t lastino; size_t bulkstatcallcnt; xfs_fsop_bulkreq_t bulkreq; inomap_reset_context(inomap_contextp); /* begin iteration at ino zero */ lastino = 0; for ( bulkstatcallcnt = 0 ; ; bulkstatcallcnt++ ) { xfs_bstat_t *p; xfs_bstat_t *endp; __s32 buflenout; int rval; if ( bulkstatcallcnt == 0 ) { mlog( MLOG_VERBOSE, _( "dumping directories\n") ); } sc_stat_pds[ strmix ].pds_phase = PDS_DIRDUMP; /* check for interruption */ if ( cldmgr_stop_requested( )) { return RV_INTR; } /* get a bunch of bulkstats */ mlog( MLOG_NITTY, "dump_dirs SGI_FS_BULKSTAT %u buf len %u\n", bulkstatcallcnt, bstatbuflen ); bulkreq.lastip = (__u64 *)&lastino; bulkreq.icount = bstatbuflen; bulkreq.ubuffer = bstatbufp; bulkreq.ocount = &buflenout; rval = ioctl(sc_fsfd, XFS_IOC_FSBULKSTAT, &bulkreq); if ( rval ) { mlog( MLOG_NORMAL, _( "SGI_FS_BULKSTAT failed: " "%s (%d)\n"), strerror( errno ), errno ); return RV_ERROR; } mlog( MLOG_NITTY, "dump_dirs SGI_FS_BULKSTAT returns %d entries\n", buflenout ); /* check if done */ if ( buflenout == 0 ) { return RV_OK; } /* step through each node, dumping if * appropriate */ for ( p = bstatbufp, endp = bstatbufp + buflenout ; p < endp ; p++ ) { rv_t rv; if ( p->bs_ino == 0 ) continue; if ( !p->bs_nlink || !p->bs_mode ) { /* inode being modified, get synced data */ mlog( MLOG_NITTY, "ino %llu needs second bulkstat\n", p->bs_ino ); if ( bigstat_one( sc_fsfd, p->bs_ino, p ) < 0 ) { mlog( MLOG_WARNING, _( "failed to get bulkstat information for inode %llu\n"), p->bs_ino ); continue; } if ( !p->bs_nlink || !p->bs_mode || !p->bs_ino ) { mlog( MLOG_TRACE, "failed to get valid bulkstat information for inode %llu\n", p->bs_ino ); continue; } } if ( ( p->bs_mode & S_IFMT ) != S_IFDIR ) { continue; } rv = dump_dir( strmix, sc_fshandlep, sc_fsfd, p ); if ( rv != RV_OK ) { return rv; } } lastino = inomap_next_dir(inomap_contextp, lastino); if (lastino == INO64MAX) { mlog( MLOG_DEBUG, "bulkstat seeked to EOS\n" ); return 0; } mlog( MLOG_DEBUG, "bulkstat seeked to %llu\n", lastino ); lastino = (lastino > 0) ? lastino - 1 : 0; } /* NOTREACHED */ } static rv_t dump_dir( ix_t strmix, jdm_fshandle_t *fshandlep, int fsfd, xfs_bstat_t *statp ) { context_t *contextp = &sc_contextp[ strmix ]; drive_t *drivep = drivepp[ strmix ]; void *inomap_contextp = contextp->cc_inomap_contextp; int state; int fd; struct dirent *gdp = ( struct dirent *)contextp->cc_getdentsbufp; size_t gdsz = contextp->cc_getdentsbufsz; int gdcnt; gen_t gen; rv_t rv; /* no way this can be non-dir, but check anyway */ assert( ( statp->bs_mode & S_IFMT ) == S_IFDIR ); if ( ( statp->bs_mode & S_IFMT ) != S_IFDIR ) { return RV_OK; } /* skip if no links */ if ( statp->bs_nlink < 1 ) { return RV_OK; } /* see what the inomap says about this ino */ state = inomap_get_state( inomap_contextp, statp->bs_ino ); /* skip if not in inomap */ if ( state == MAP_INO_UNUSED || state == MAP_DIR_NOCHNG || state == MAP_NDR_NOCHNG ) { if ( state == MAP_NDR_NOCHNG ) { mlog( MLOG_DEBUG, "inomap inconsistency ino %llu: " "map says is non-dir but is dir: skipping\n", statp->bs_ino ); } return RV_OK; } /* note if map says a non-dir */ if ( state == MAP_NDR_CHANGE ) { mlog( MLOG_DEBUG, "inomap inconsistency ino %llu: " "map says non-dir but is dir: skipping\n", statp->bs_ino ); return RV_OK; } /* bump the stats now. a bit early, but fewer lines of code */ sc_stat_pds[ strmix ].pds_dirdone++; /* if bulkstat ino# occupied more than 32 bits and * linux ino# for getdents is 32 bits then * warn and skip. */ if ( statp->bs_ino > ( xfs_ino_t )INOMAX ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "unable to dump directory: ino %llu too large\n"), statp->bs_ino ); return RV_OK; /* continue anyway */ } mlog( MLOG_TRACE, "dumping directory ino %llu\n", statp->bs_ino ); /* open the directory named by statp */ fd = jdm_open( fshandlep, statp, O_RDONLY ); if ( fd < 0 ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "unable to open directory: ino %llu: %s\n"), statp->bs_ino, strerror( errno ) ); return RV_OK; /* continue anyway */ } /* dump the file header. */ rv = dump_filehdr( drivep, contextp, statp, 0, 0 ); if ( rv != RV_OK ) { close( fd ); return rv; } /* dump dirents - lots of buffering done here, to achieve OS- * independence. if proves to be to much overhead, can streamline. */ for ( gdcnt = 1, rv = RV_OK ; rv == RV_OK ; gdcnt++ ) { struct dirent *p; int nread; register size_t reclen; nread = getdents_wrap( fd, (char *)gdp, gdsz ); /* negative count indicates something very bad happened; * try to gracefully end this dir. */ if ( nread < 0 ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "unable to read dirents (%d) for " "directory ino %llu: %s\n"), gdcnt, statp->bs_ino, strerror( errno )); /* !!! curtis looked at this, and pointed out that * we could take some recovery action here. if the * errno is appropriate, lseek64 to the value of * doff field of the last dirent successfully * obtained, and contiue the loop. */ nread = 0; /* pretend we are done */ } /* no more directory entries: break; */ if ( nread == 0 ) { break; } /* translate and dump each entry: skip "." and ".." * and null entries. */ for ( p = gdp, reclen = ( size_t )p->d_reclen ; nread > 0 ; nread -= ( int )reclen, assert( nread >= 0 ), p = ( struct dirent * )( ( char * )p + reclen ), reclen = ( size_t )p->d_reclen ) { xfs_ino_t ino; register size_t namelen = strlen( p->d_name ); #ifdef DEBUG register size_t nameszmax = ( size_t )reclen - offsetofmember( struct dirent, d_name ); /* getdents(2) guarantees that the string will * be null-terminated, but the record may have * padding after the null-termination. */ assert( namelen < nameszmax ); #endif /* skip "." and ".." */ if ( *( p->d_name + 0 ) == '.' && ( *( p->d_name + 1 ) == 0 || ( *( p->d_name + 1 ) == '.' && *( p->d_name + 2 ) == 0 ))) { continue; } ino = (xfs_ino_t)p->d_ino; if ( ino == 0 ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "encountered 0 ino (%s) in " "directory ino %llu: NOT dumping\n"), p->d_name, statp->bs_ino ); continue; } /* lookup the gen number in the ino-to-gen map. * if it's not there, we have to get it the slow way. */ if ( inomap_get_gen( NULL, p->d_ino, &gen) ) { xfs_bstat_t statbuf; int scrval; scrval = bigstat_one( fsfd, p->d_ino, &statbuf ); if ( scrval ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "could not stat " "dirent %s ino %llu: %s: " "using null generation count " "in directory entry\n"), p->d_name, ( xfs_ino_t )p->d_ino, strerror( errno )); gen = 0; } else { gen = statbuf.bs_gen; } } rv = dump_dirent( drivep, contextp, statp, ino, gen, p->d_name, namelen ); if ( rv != RV_OK ) { break; } } } /* write a null dirent hdr, unless trouble encountered in the loop */ if ( rv == RV_OK ) { rv = dump_dirent( drivep, contextp, statp, 0, 0, 0, 0 ); } if ( rv == RV_OK && sc_dumpextattrpr && ( statp->bs_xflags & XFS_XFLAG_HASATTR )) { rv = dump_extattrs( drivep, contextp, fshandlep, statp); } close( fd ); /* if an error occurred, just return the error */ return rv; } static rv_t dump_extattrs( drive_t *drivep, context_t *contextp, jdm_fshandle_t *fshandlep, xfs_bstat_t *statp) { ix_t pass; int flag; attrlist_cursor_t cursor; rv_t rv; bool_t abort; /* dump a file header specially marked as heading extended attributes */ mlog( MLOG_NITTY, "dumping %s ino %llu extended attributes filehdr\n", FILETYPE(statp), statp->bs_ino ); rv = dump_filehdr( drivep, contextp, statp, 0, FILEHDR_FLAGS_EXTATTR ); if ( rv != RV_OK ) { return rv; } /* loop three times: once for the non-root, once for root, and * again for the secure attributes. */ for ( pass = 0; pass < 3; pass++ ) { bool_t more; if ( pass == 0 ) flag = 0; else if ( pass == 1) flag = ATTR_ROOT; else flag = ATTR_SECURE; mlog( MLOG_NITTY, "dumping %s extended attributes for %s ino %llu\n", EXTATTR_NAMESPACE(flag), FILETYPE(statp), statp->bs_ino ); /* loop dumping the extended attributes from the namespace * selected by the outer loop */ memset( &cursor, 0, sizeof( cursor )); more = BOOL_FALSE; do { attrlist_t *listp; int rval = 0; rval = jdm_attr_list(fshandlep, statp, contextp->cc_extattrlistbufp, ( int )contextp->cc_extattrlistbufsz, flag, &cursor ); if ( rval ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "could not get list of %s attributes for " "%s ino %llu: %s (%d)\n"), EXTATTR_NAMESPACE(flag), FILETYPE(statp), statp->bs_ino, strerror( errno ), errno ); break; } listp = ( attrlist_t * )contextp->cc_extattrlistbufp; more = listp->al_more; abort = BOOL_FALSE; rv = dump_extattr_list( drivep, contextp, fshandlep, statp, listp, flag, &abort ); if ( rv != RV_OK ) { return rv; } } while ( more && !abort ); } /* finally, dump a dummy extattr hdr so restore will know * we're done. */ /*DBG*/mlog( MLOG_NITTY, "dumping NULL extattrhdr\n" ); rv = dump_extattrhdr( drivep, contextp, statp, EXTATTRHDR_SZ, 0, EXTATTRHDR_FLAGS_NULL, 0 ); return rv; } static rv_t dump_extattr_list( drive_t *drivep, context_t *contextp, jdm_fshandle_t *fshandlep, xfs_bstat_t *statp, attrlist_t *listp, int flag, bool_t *abortprp ) { size_t listlen = ( size_t )listp->al_count; ix_t nameix; char *dumpbufp; char *endp; size_t bufsz; int rval = 0; rv_t rv; char *dumpbufendp = contextp->cc_extattrdumpbufp + contextp->cc_extattrdumpbufsz; /* sanity checks */ assert( listp->al_count >= 0 ); /* fill up a retrieve array and build a dump buffer; * can run out of entries in the name list, space in the * retrieve buffer, or space in the dump buffer */ dumpbufp = contextp->cc_extattrdumpbufp; endp = dumpbufp; for ( nameix = 0 ; nameix < listlen ; ) { ix_t rtrvix; size_t rtrvcnt; rtrvix = 0; while (nameix < listlen && rtrvix < EXTATTR_RTRVARRAY_LEN) { attrlist_ent_t *entp; char *valuep; attr_multiop_t *opp; entp = ATTR_ENTRY( listp, nameix ); opp = &contextp->cc_extattrrtrvarrayp[ rtrvix ]; /* Offer the HSM a chance to avoid dumping certain * attributes. */ if (hsm_fs_ctxtp) { int skip_entry; if (!HsmFilterExistingAttribute( contextp->cc_hsm_f_ctxtp, entp->a_name, entp->a_valuelen, flag, &skip_entry)) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "HSM could not filter %s " "attribute %s for %s ino %llu\n"), EXTATTR_NAMESPACE(flag), entp->a_name, FILETYPE(statp), statp->bs_ino); *abortprp = BOOL_TRUE; return RV_OK; } if (skip_entry) { nameix++; continue; } } dumpbufp = dump_extattr_buildrecord( statp, dumpbufp, dumpbufendp, entp->a_name, entp->a_valuelen, flag, &valuep ); if ( dumpbufp > dumpbufendp ) { break; /* won't fit in buffer */ } if (valuep != NULL) { /* if added to dump buffer */ endp = dumpbufp; opp->am_attrname = entp->a_name; opp->am_attrvalue = valuep; opp->am_length = ( int )entp->a_valuelen; opp->am_flags = flag; opp->am_error = 0; opp->am_opcode = ATTR_OP_GET; rtrvix++; } nameix++; } /* Either the retrieve buffer is full, the dump buffer is full, * or we just put the last attribute into the dump buffer. In * any case, fill in the values for any attributes added so far. */ rtrvcnt = rtrvix; if (rtrvcnt > 0) { rval = jdm_attr_multi( fshandlep, statp, (void *)contextp->cc_extattrrtrvarrayp, ( int )rtrvcnt, 0 ); if ( rval ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "could not retrieve %s attributes for " "%s ino %llu: %s (%d)\n"), EXTATTR_NAMESPACE(flag), FILETYPE(statp), statp->bs_ino, strerror( errno ), errno ); *abortprp = BOOL_TRUE; return RV_OK; } for ( rtrvix = 0 ; rtrvix < rtrvcnt ; rtrvix++ ) { attr_multiop_t *opp; opp = &contextp->cc_extattrrtrvarrayp[ rtrvix ]; if ( opp->am_error ) { if ( opp->am_error == ENOATTR && flag & ATTR_SECURE ) { /* Security attributes are supported by * the kernel but jdm_attr_multi() returns * ENOATTR for every 'user' space attribute * during the 'security' pass of the extended * attribute loop (pass==3). Suppress the * following error message with a no-op. The * jdm_attr_multi() problem is fixed in mod * xfs-linux:xfs-kern:167038a (PV 907903). */ continue; } mlog( MLOG_NORMAL | MLOG_WARNING, _( "attr_multi indicates error while " "retrieving %s attribute [%s] for " "%s ino %llu: %s (%d)\n"), EXTATTR_NAMESPACE(flag), opp->am_attrname, FILETYPE(statp), statp->bs_ino, strerror( opp->am_error ), opp->am_error ); } } } /* The values for all attributes in the dump buffer have been * filled in. If the dump buffer isn't full yet, let's wait * and put some more attributes in. */ if (dumpbufp <= dumpbufendp) continue; /* no buffer overflow yet */ assert( endp > contextp->cc_extattrdumpbufp ); bufsz = ( size_t )( endp - contextp->cc_extattrdumpbufp ); rval = write_buf( contextp->cc_extattrdumpbufp, bufsz, ( void * )drivep, ( gwbfp_t )drivep->d_opsp->do_get_write_buf, ( wfp_t )drivep->d_opsp->do_write ); switch ( rval ) { case 0: rv = RV_OK; break; case DRIVE_ERROR_MEDIA: case DRIVE_ERROR_EOM: rv = RV_EOM; break; case DRIVE_ERROR_DEVICE: rv = RV_DRIVE; break; case DRIVE_ERROR_CORE: default: rv = RV_CORE; break; } if ( rv != RV_OK ) { *abortprp = BOOL_FALSE; return rv; } dumpbufp = contextp->cc_extattrdumpbufp; endp = dumpbufp; } /* All existing attributes are in the dump buffer. See if the HSM * needs to add any addtional attributes. */ if (!listp->al_more && hsm_fs_ctxtp) { int hsmcursor = 0; for (;;) { char *hsmnamep; char *hsmvaluep; char *valuep; uint32_t hsmvaluesz; if (!HsmAddNewAttribute(contextp->cc_hsm_f_ctxtp, hsmcursor, flag, &hsmnamep, &hsmvaluep, &hsmvaluesz)) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "HSM could not add new %s attribute " "#%d for %s ino %llu\n"), EXTATTR_NAMESPACE(flag), hsmcursor, FILETYPE(statp), statp->bs_ino); *abortprp = BOOL_TRUE; return RV_OK; } if (hsmnamep == NULL) { break; /* No more attributes to add */ } dumpbufp = dump_extattr_buildrecord( statp, dumpbufp, dumpbufendp, hsmnamep, hsmvaluesz, flag, &valuep ); if ( dumpbufp < dumpbufendp ) { /* if fits in buffer */ endp = dumpbufp; (void)memcpy(valuep, hsmvaluep, hsmvaluesz); hsmcursor++; continue; } assert( endp > contextp->cc_extattrdumpbufp ); bufsz = ( size_t )( endp - contextp->cc_extattrdumpbufp ); rval = write_buf( contextp->cc_extattrdumpbufp, bufsz, ( void * )drivep, ( gwbfp_t )drivep->d_opsp->do_get_write_buf, ( wfp_t )drivep->d_opsp->do_write ); switch ( rval ) { case 0: rv = RV_OK; break; case DRIVE_ERROR_MEDIA: case DRIVE_ERROR_EOM: rv = RV_EOM; break; case DRIVE_ERROR_DEVICE: rv = RV_DRIVE; break; case DRIVE_ERROR_CORE: default: rv = RV_CORE; break; } if ( rv != RV_OK ) { *abortprp = BOOL_FALSE; return rv; } dumpbufp = contextp->cc_extattrdumpbufp; endp = dumpbufp; } } /* If any attributes remain unwritten in the dump buffer, write them * now. */ if (endp > contextp->cc_extattrdumpbufp) { bufsz = ( size_t )( endp - contextp->cc_extattrdumpbufp ); rval = write_buf( contextp->cc_extattrdumpbufp, bufsz, ( void * )drivep, ( gwbfp_t )drivep->d_opsp->do_get_write_buf, ( wfp_t )drivep->d_opsp->do_write ); switch ( rval ) { case 0: rv = RV_OK; break; case DRIVE_ERROR_MEDIA: case DRIVE_ERROR_EOM: rv = RV_EOM; break; case DRIVE_ERROR_DEVICE: rv = RV_DRIVE; break; case DRIVE_ERROR_CORE: default: rv = RV_CORE; break; } if ( rv != RV_OK ) { *abortprp = BOOL_FALSE; return rv; } } *abortprp = BOOL_FALSE; return RV_OK; } static char * dump_extattr_buildrecord( xfs_bstat_t *statp, char *dumpbufp, char *dumpbufendp, char *namesrcp, uint32_t valuesz, int flag, char **valuepp ) { extattrhdr_t *ahdrp = ( extattrhdr_t * )dumpbufp; char *namep = dumpbufp + EXTATTRHDR_SZ; uint32_t namelen = strlen( namesrcp ); uint32_t namesz = namelen + 1; char *valuep = namep + namesz; uint32_t recsz = EXTATTRHDR_SZ + namesz + valuesz; extattrhdr_t tmpah; recsz = ( recsz + ( EXTATTRHDR_ALIGN - 1 )) & ~( EXTATTRHDR_ALIGN - 1 ); if ( dumpbufp + recsz > dumpbufendp ) { *valuepp = 0; return dumpbufp + recsz; } if ( namelen > NAME_MAX ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "%s extended attribute name for %s ino %llu too long: " "%u, max is %u: skipping\n"), EXTATTR_NAMESPACE(flag), FILETYPE(statp), statp->bs_ino, namelen, NAME_MAX ); *valuepp = 0; return dumpbufp; } if ( valuesz > ATTR_MAX_VALUELEN ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "%s extended attribute value for %s ino %llu too long: " "%u, max is %u: skipping\n"), EXTATTR_NAMESPACE(flag), FILETYPE(statp), statp->bs_ino, valuesz, ATTR_MAX_VALUELEN ); *valuepp = 0; return dumpbufp; } /*DBG*/mlog( MLOG_NITTY, "building extattr " "record sz %u " "hdrsz %u " "namesz %u (%s) " "valsz %u\n", recsz, EXTATTRHDR_SZ, namesz, namesrcp, valuesz ); ( void )strcpy( namep, namesrcp ); memset( ( void * )&tmpah, 0, sizeof( tmpah )); tmpah.ah_sz = recsz; assert( EXTATTRHDR_SZ + namesz < UINT16MAX ); tmpah.ah_valoff = ( uint16_t )( EXTATTRHDR_SZ + namesz ); tmpah.ah_flags = ( uint16_t ) (( flag & ATTR_ROOT ) ? EXTATTRHDR_FLAGS_ROOT : (( flag & ATTR_SECURE ) ? EXTATTRHDR_FLAGS_SECURE : 0)); tmpah.ah_valsz = valuesz; tmpah.ah_flags |= EXTATTRHDR_FLAGS_CHECKSUM; tmpah.ah_checksum = calc_checksum( &tmpah, EXTATTRHDR_SZ ); xlate_extattrhdr(ahdrp, &tmpah, -1); *valuepp = valuep; return dumpbufp + recsz; } /* ARGSUSED */ static rv_t dump_extattrhdr( drive_t *drivep, context_t *contextp, xfs_bstat_t *statp, size_t recsz, size_t valoff, ix_t flags, uint32_t valsz ) { extattrhdr_t ahdr; extattrhdr_t tmpahdr; int rval; rv_t rv; memset( ( void * )&ahdr, 0, sizeof( ahdr )); ahdr.ah_sz = recsz; assert( valoff < UINT16MAX ); ahdr.ah_valoff = ( uint16_t )valoff; ahdr.ah_flags = ( uint16_t )flags | EXTATTRHDR_FLAGS_CHECKSUM; ahdr.ah_valsz = valsz; ahdr.ah_checksum = calc_checksum( &ahdr, EXTATTRHDR_SZ ); xlate_extattrhdr(&ahdr, &tmpahdr, 1); rval = write_buf( ( char * )&tmpahdr, EXTATTRHDR_SZ, ( void * )drivep, ( gwbfp_t )drivep->d_opsp->do_get_write_buf, ( wfp_t )drivep->d_opsp->do_write ); switch ( rval ) { case 0: rv = RV_OK; break; case DRIVE_ERROR_MEDIA: case DRIVE_ERROR_EOM: rv = RV_EOM; break; case DRIVE_ERROR_DEVICE: rv = RV_DRIVE; break; case DRIVE_ERROR_CORE: default: rv = RV_CORE; break; } return rv; } /* this function is called by the bigstat iterator for all non-directory * files. it passes the buck to file type-specific dump functions. * return value is RV_EOF if the media file is getting too big, * RV_... if trouble encountered with the media/drive, * 0 if file completely dumped, RV_NOMORE if we've encountered the stream * endpt, RV_INTR if operator interrupted the dump. */ /* ARGSUSED */ static rv_t dump_file( void *arg1, jdm_fshandle_t *fshandlep, int fsfd, xfs_bstat_t *statp ) { ix_t strmix = ( ix_t )arg1; context_t *contextp = &sc_contextp[ strmix ]; drive_t *drivep = drivepp[ strmix ]; drive_hdr_t *dwhdrp = drivep->d_writehdrp; media_hdr_t *mwhdrp = ( media_hdr_t * )dwhdrp->dh_upper; content_hdr_t *cwhdrp = ( content_hdr_t * )mwhdrp->mh_upper; content_inode_hdr_t *scwhdrp = ( content_inode_hdr_t * ) ( void * ) cwhdrp->ch_specific; startpt_t *startptp = &scwhdrp->cih_startpt; startpt_t *endptp = &scwhdrp->cih_endpt; bool_t file_skipped = BOOL_FALSE; int state; rv_t rv; /* skip if no links */ if ( statp->bs_nlink < 1 ) { if ( statp->bs_ino > contextp->cc_stat_lastino ) { contextp->cc_stat_lastino = statp->bs_ino; } mlog( MLOG_DEBUG, "skip as no links for ino %llu\n", statp->bs_ino); return RV_OK; } /* skip if prior to startpoint */ if ( statp->bs_ino < startptp->sp_ino ) { if ( statp->bs_ino > contextp->cc_stat_lastino ) { contextp->cc_stat_lastino = statp->bs_ino; } mlog( MLOG_DEBUG, "skip as ino %llu is prior to starpoint\n", statp->bs_ino); return RV_OK; } /* skip if at or beyond next startpoint. return non-zero to * abort iteration. */ if ( ! ( endptp->sp_flags & STARTPT_FLAGS_END )) { if ( endptp->sp_offset == 0 ) { if ( statp->bs_ino >= endptp->sp_ino ) { if ( statp->bs_ino > contextp->cc_stat_lastino ) { contextp->cc_stat_lastino = statp->bs_ino; } mlog( MLOG_DEBUG, "skip as ino %llu is at/beyond starpoint\n", statp->bs_ino); return RV_NOMORE; } } else { if ( statp->bs_ino > endptp->sp_ino ) { if ( statp->bs_ino > contextp->cc_stat_lastino ) { contextp->cc_stat_lastino = statp->bs_ino; } mlog( MLOG_DEBUG, "skip as ino %llu is at/beyond starpoint\n", statp->bs_ino); return RV_NOMORE; } } } /* see what the inomap says about this ino */ state = inomap_get_state( contextp->cc_inomap_contextp, statp->bs_ino ); /* skip if not in inomap */ if ( state == MAP_INO_UNUSED || state == MAP_DIR_NOCHNG || state == MAP_NDR_NOCHNG ) { if ( state == MAP_DIR_NOCHNG ) { mlog( MLOG_DEBUG, "inomap inconsistency ino %llu: " "MAP_DIR_NOCHNG but is non-dir: skipping\n", statp->bs_ino ); } if ( statp->bs_ino > contextp->cc_stat_lastino ) { contextp->cc_stat_lastino = statp->bs_ino; } mlog( MLOG_DEBUG, "skip as ino %llu is not marked as changed in inomap\n", statp->bs_ino); mlog( MLOG_DEBUG, "ino %llu is in state %d\n", statp->bs_ino, state); return RV_OK; } /* note if map says a dir */ if ( state == MAP_DIR_CHANGE || state == MAP_DIR_SUPPRT ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "inomap inconsistency ino %llu: " "%s but is now non-dir: NOT dumping\n"), statp->bs_ino, state == MAP_DIR_CHANGE ? "map says changed dir" : "map says unchanged dir" ); } /* if GETOPT_DUMPASOFFLINE was specified, initialize the HSM's file * context for use in other routines. If the context can't be * initialized, don't dump the file. */ if (hsm_fs_ctxtp) { if (HsmInitFileContext(contextp->cc_hsm_f_ctxtp, statp)) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "inomap inconsistency ino %llu: " "hsm detected error: NOT dumping\n"), statp->bs_ino); if ( statp->bs_ino > contextp->cc_stat_lastino ) { contextp->cc_stat_lastino = statp->bs_ino; } return RV_OK; } } /* pass on to specific dump function */ switch( statp->bs_mode & S_IFMT ) { case S_IFREG: /* ordinary file */ /* filter out any files that have grown beyond the * max file size since the initial scan. */ if (maxdumpfilesize) { off64_t estimated_size = statp->bs_blocks * ( off64_t )statp->bs_blksize; if (hsm_fs_ctxtp) { HsmEstimateFileSpace(hsm_fs_ctxtp, contextp->cc_hsm_f_ctxtp, statp, &estimated_size, 1); } /* quota files are exempt from max size check */ if (estimated_size > maxdumpfilesize && !is_quota_file(statp->bs_ino)) { mlog( MLOG_DEBUG | MLOG_NOTE, "ino %llu increased beyond maximum size: " "NOT dumping\n", statp->bs_ino); return RV_OK; } } rv = dump_file_reg( drivep, contextp, scwhdrp, fshandlep, statp, &file_skipped ); if ( statp->bs_ino > contextp->cc_stat_lastino ) { lock( ); sc_stat_nondirdone++; unlock( ); contextp->cc_stat_lastino = statp->bs_ino; } break; /* drop out of switch to extattr dump */ case S_IFCHR: case S_IFBLK: case S_IFIFO: #ifdef S_IFNAM case S_IFNAM: #endif case S_IFLNK: case S_IFSOCK: /* only need a filehdr_t; no data */ rv = dump_file_spec( drivep, contextp, fshandlep, statp ); if ( statp->bs_ino > contextp->cc_stat_lastino ) { lock( ); sc_stat_nondirdone++; unlock( ); contextp->cc_stat_lastino = statp->bs_ino; } break; /* drop out of switch to extattr dump */ case S_IFDIR: default: /* don't know how to dump these */ mlog( MLOG_VERBOSE, _( "don't know how to dump ino %llu: mode %08x\n"), statp->bs_ino, statp->bs_mode ); if ( statp->bs_ino > contextp->cc_stat_lastino ) { lock( ); sc_stat_nondirdone++; unlock( ); contextp->cc_stat_lastino = statp->bs_ino; } return RV_OK; /* not yet implemented case S_IFMNT: */ } if ( rv == RV_OK && file_skipped == BOOL_FALSE && sc_dumpextattrpr && ( statp->bs_xflags & XFS_XFLAG_HASATTR )) { rv = dump_extattrs( drivep, contextp, fshandlep, statp); } return rv; } /* a regular file may be broken into several portions if its size * is large. Each portion begins with a filehdr_t and is followed by * several extents. each extent begins with an extenthdr_t. returns RV_OK * if all extents dumped, RV_... on drive errors, or RV_INTR if * operator requested stop. */ static rv_t dump_file_reg( drive_t *drivep, context_t *contextp, content_inode_hdr_t *scwhdrp, jdm_fshandle_t *fshandlep, xfs_bstat_t *statp, bool_t *file_skippedp ) { startpt_t *startptp = &scwhdrp->cih_startpt; startpt_t *endptp = &scwhdrp->cih_endpt; extent_group_context_t extent_group_context; bool_t cmpltflg; off64_t offset; off64_t stopoffset; bool_t sosig; /* stop offset is significant */ off64_t maxextentcnt; rv_t rv; /* determine the offset within the file where the dump should begin. * it must have been aligned to the basic fs block size by the * startpoint calculations done during strategy initialization. */ if ( statp->bs_ino == startptp->sp_ino ) { offset = startptp->sp_offset; assert( ( offset & ( off64_t )( BBSIZE - 1 )) == 0 ); } else { offset = 0; } /* if this is a resumed dump and the resumption begins somewhere * within this file, and that point is greater than offset set * above, and that file hasn't changed since the resumed dump, * modify offset. */ if ( sc_resumepr ) { drange_t *drangep = sc_resumerangep; size_t drangecnt = sc_resumerangecnt; size_t drangeix; for ( drangeix = 0 ; drangeix < drangecnt ; drangeix++ ) { drange_t *rp = &drangep[ drangeix ]; if ( statp->bs_ino == rp->dr_begin.sp_ino ) { register time32_t mtime = statp->bs_mtime.tv_sec; register time32_t ctime = statp->bs_ctime.tv_sec; register time32_t ltime = max( mtime, ctime ); if ( ltime < sc_resumebasetime ) { if ( rp->dr_begin.sp_offset > offset ){ offset =rp->dr_begin.sp_offset; } } break; } } assert( ( offset & ( off64_t )( BBSIZE - 1 )) == 0 ); } /* determine the offset within the file where the dump should end. * only significant if this is an inode spanning a startpoint. */ if ( endptp->sp_flags & STARTPT_FLAGS_END ) { sosig = BOOL_FALSE; stopoffset = 0; } else if ( statp->bs_ino == endptp->sp_ino ) { sosig = BOOL_TRUE; stopoffset = endptp->sp_offset; } else { sosig = BOOL_FALSE; stopoffset = 0; } mlog( MLOG_TRACE, "dumping regular file ino %llu " "offset %lld " "to offset %lld " "(size %lld)\n", statp->bs_ino, offset, sosig ? stopoffset : statp->bs_size, statp->bs_size ); /* calculate the maximum extent group size. files larger than this * will be broken into multiple extent groups, each with its own * filehdr_t. */ maxextentcnt = drivep->d_recmarksep; /* initialize the extent group context. if fails, just return, * pretending the dump succeeded. */ rv = init_extent_group_context( fshandlep, statp, &extent_group_context ); if ( rv != RV_OK ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "could not open regular file ino %llu mode 0x%08x: " "%s: not dumped\n"), statp->bs_ino, statp->bs_mode, strerror( errno )); *file_skippedp = BOOL_TRUE; return RV_OK; } /* loop here, dumping marked groups of extents. each extent group * is preceeded by a filehdr_t. this is required so that the * recovery side can identify the fs file at each marked point * in the stream. it sets by reference offset, bytecnt, and cmpltflg. * it is important to understand that if a fs file is real big, * it will be dumped in parts (extent groups), each beginning with * an identical filehdr_t. */ cmpltflg = BOOL_FALSE; rv = RV_OK; for ( ; ; ) { off64_t bytecnt = 0; off64_t bc; /* see if we are done. */ if ( cmpltflg ) { assert( rv == RV_OK ); break; } /* set a mark - important to do this now, before deciding * the media file is to big or the operator asked to * interrupt the dump. this mark, if committed, indicates * the previous fs file / extent group was completely dumped. */ mark_set( drivep, statp->bs_ino, offset, 0 ); /* spoof EOF if the media file size is getting too big. * note that the most we can go over is d_recmarksep. */ if ( contextp->cc_mfilesz >= drivep->d_recmfilesz ){ rv = RV_EOF; break; } /* check if the operator has requested to interrupt the dump. */ if ( cldmgr_stop_requested( )) { mlog( MLOG_NORMAL, _( "dump interrupted prior to ino %llu offset %lld\n"), statp->bs_ino, offset ); mlog_exit_hint(RV_INTR); rv = RV_INTR; break; } /* dump the file header */ mlog( MLOG_DEBUG, "dumping extent group ino %llu offset %lld\n", statp->bs_ino, offset ); rv = dump_filehdr( drivep, contextp, statp, offset, 0 ); if ( rv != RV_OK ) { break; } bytecnt += sizeof( filehdr_t ); /* dump a group of extents. returns by reference * the offset of the next extent group (to be placed * in the next mark), the total number of bytes written * to media (headers and all), and a flag indicating * all extents have been dumped. */ bc = 0; /* for lint */ rv = dump_extent_group( drivep, contextp, statp, &extent_group_context, maxextentcnt, stopoffset, sosig, &offset, &bc, &cmpltflg ); assert( bc >= 0 ); bytecnt += bc; if ( rv != RV_OK ) { break; } /* update global stat */ lock( ); sc_stat_datadone += ( size64_t )bc; unlock( ); /* dump LAST extent hdr. one of these is placed at the * end of each dumped file. necessary to detect the * end of the file. */ rv = dump_extenthdr( drivep, contextp, EXTENTHDR_TYPE_LAST, 0, 0, 0 ); if ( rv != RV_OK ) { break; } bytecnt += sizeof( extenthdr_t ); /* update the media file size */ contextp->cc_mfilesz += bytecnt; } cleanup_extent_group_context( &extent_group_context ); return rv; } /* dumps character, block, and fifo - special files. no data, just meta-data, * all contained within the filehdr_t. also handles symbolic link files: * appends a variable-length string after the filehdr_t. */ static rv_t dump_file_spec( drive_t *drivep, context_t *contextp, jdm_fshandle_t *fshandlep, xfs_bstat_t *statp ) { int rval; rv_t rv; mlog( MLOG_TRACE, "dumping special file ino %llu mode 0x%04x\n", statp->bs_ino, statp->bs_mode ); /* set a mark - important to do this now, before deciding * the media file is to big. this mark, if committed, * indicates the previous fs file was completely dumped. */ mark_set( drivep, statp->bs_ino, 0, 0 ); /* dump the file header */ rv = dump_filehdr( drivep, contextp, statp, 0, 0 ); if ( rv != RV_OK ) { return rv; } /* update the media file size */ contextp->cc_mfilesz += sizeof( filehdr_t ); /* if a symbolic link, also dump the link pathname. * use an extent header to represent the pathname. the * extent sz will always be a multiple of SYMLINK_ALIGN. * the symlink pathname char string will always be NULL-terminated. */ if ( ( statp->bs_mode & S_IFMT ) == S_IFLNK ) { int nread; size_t extentsz; /* read the link path. if error, dump a zero-length * extent. in any case, nread will contain the number of * bytes to dump, and contextp->cc_direntbufp will contain * the bytes. */ nread = jdm_readlink( fshandlep, statp, contextp->cc_readlinkbufp, contextp->cc_readlinkbufsz ); if ( nread < 0 ) { mlog( MLOG_DEBUG, "could not read symlink ino %llu\n", statp->bs_ino ); nread = 0; } /* null-terminate the string */ assert( ( size_t )nread < contextp->cc_readlinkbufsz ); contextp->cc_readlinkbufp[ nread ] = 0; /* calculate the extent size - be sure to include room * for the null-termination. */ extentsz = ( ( size_t )nread + 1 + ( SYMLINK_ALIGN - 1 )) & ~ ( SYMLINK_ALIGN - 1 ); assert( extentsz <= contextp->cc_readlinkbufsz ); /* dump an extent header */ rv = dump_extenthdr( drivep, contextp, EXTENTHDR_TYPE_DATA, 0, 0, ( off64_t )extentsz ); if ( rv != RV_OK ) { return rv; } /* dump the link path extent */ rval = write_buf( contextp->cc_readlinkbufp, extentsz, ( void * )drivep, ( gwbfp_t )drivep->d_opsp->do_get_write_buf, ( wfp_t )drivep->d_opsp->do_write ); switch ( rval ) { case 0: rv = RV_OK; break; case DRIVE_ERROR_MEDIA: case DRIVE_ERROR_EOM: rv = RV_EOM; break; case DRIVE_ERROR_DEVICE: rv = RV_DRIVE; break; case DRIVE_ERROR_CORE: default: rv = RV_CORE; break; } if ( rv != RV_OK ) { return rv; } } return RV_OK; } /* contrives the initial state of the extent group context such that * dump_extent_group() will fetch some extents from the kernel before it * does anything else. */ static rv_t init_extent_group_context( jdm_fshandle_t *fshandlep, xfs_bstat_t *statp, extent_group_context_t *gcp ) { bool_t isrealtime; int oflags; struct flock fl; isrealtime = ( bool_t )(statp->bs_xflags & XFS_XFLAG_REALTIME ); oflags = O_RDONLY; if ( isrealtime ) { oflags |= O_DIRECT; } ( void )memset( ( void * )gcp, 0, sizeof( *gcp )); gcp->eg_bmap[ 0 ].bmv_offset = 0; gcp->eg_bmap[ 0 ].bmv_length = -1; gcp->eg_bmap[ 0 ].bmv_count = BMAP_LEN; gcp->eg_bmap[ 0 ].bmv_iflags = BMV_IF_NO_DMAPI_READ; gcp->eg_nextbmapp = &gcp->eg_bmap[ 1 ]; gcp->eg_endbmapp = &gcp->eg_bmap[ 1 ]; gcp->eg_bmapix = 0; gcp->eg_gbmcnt = 0; gcp->eg_fd = jdm_open( fshandlep, statp, oflags ); if ( gcp->eg_fd < 0 ) { return RV_ERROR; } /* Check if a mandatory lock is set on the file to try and * avoid blocking indefinitely on the reads later. Note that * someone could still set a mandatory lock and hose xfsdump * after this check but before all reads have completed. * This change just closes the window a bit. */ if ( (statp->bs_mode & S_ISGID) && ( ! (statp->bs_mode&S_IXOTH) ) ) { fl.l_type = F_RDLCK; fl.l_whence = SEEK_SET; fl.l_start = (off_t)0; fl.l_len = 0; if ((fcntl(gcp->eg_fd, F_GETLK, &fl)) < 0 ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "locking check failed ino %llu\n"), statp->bs_ino ); close(gcp->eg_fd); return RV_ERROR; } if (fl.l_type != F_UNLCK) { /* Mandatory lock is set */ close(gcp->eg_fd); errno = EBUSY; return RV_ERROR; } } return RV_OK; } static void cleanup_extent_group_context( extent_group_context_t *gcp ) { ( void )close( gcp->eg_fd ); } static rv_t dump_extent_group( drive_t *drivep, context_t *contextp, xfs_bstat_t *statp, extent_group_context_t *gcp, off64_t maxcnt, off64_t stopoffset, bool_t sosig, off64_t *nextoffsetp, off64_t *bytecntp, bool_t *cmpltflgp ) { struct dioattr da; drive_ops_t *dop = drivep->d_opsp; bool_t isrealtime = ( bool_t )( statp->bs_xflags & XFS_XFLAG_REALTIME ); off64_t nextoffset; off64_t bytecnt; /* accumulates total bytes sent to media */ int rval; rv_t rv; /* * Setup realtime I/O size. */ if ( isrealtime ) { if ( (ioctl(gcp->eg_fd, XFS_IOC_DIOINFO, &da) < 0) ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "dioinfo failed ino %llu\n"), statp->bs_ino ); da.d_miniosz = PGSZ; } } /* dump extents until the recommended extent length is achieved */ nextoffset = *nextoffsetp; bytecnt = 0; assert( ( nextoffset & ( BBSIZE - 1 )) == 0 ); for ( ; ; ) { off64_t offset; off64_t extsz; /* if we've dumped to the stop point return. */ if ( sosig && nextoffset >= stopoffset ) { mlog( MLOG_NITTY, "dumped to stop offset\n" ); *nextoffsetp = nextoffset; *bytecntp = bytecnt; *cmpltflgp = BOOL_TRUE; return RV_OK; } /* if we've dumped the entire file, return */ if ( nextoffset >= statp->bs_size ) { mlog( MLOG_NITTY, "dumped to end of file\n" ); *nextoffsetp = nextoffset; *bytecntp = bytecnt; *cmpltflgp = BOOL_TRUE; return RV_OK; } /* if we've exceeded the desired per-extent group byte count, * call it quits. we'll be called back for more because the * completion flag is set FALSE. */ if ( bytecnt >= maxcnt ) { mlog( MLOG_NITTY, "reached per-extent group byte count\n" ); *nextoffsetp = nextoffset; *bytecntp = bytecnt; *cmpltflgp = BOOL_FALSE; return RV_OK; } /* if we are not looking at a valid bmap entry, * get one. */ if ( gcp->eg_nextbmapp >= gcp->eg_endbmapp ) { int entrycnt; /* entries in new bmap */ assert( gcp->eg_nextbmapp == gcp->eg_endbmapp ); /* get a new extent block */ mlog( MLOG_NITTY, "calling getbmapx for ino %llu\n", statp->bs_ino ); rval = ioctl( gcp->eg_fd, XFS_IOC_GETBMAPX, gcp->eg_bmap ); gcp->eg_gbmcnt++; entrycnt = gcp->eg_bmap[ 0 ].bmv_entries; if ( entrycnt < 0 ) { /* workaround for getbmap bug */ mlog( MLOG_DEBUG | MLOG_WARNING, _( "getbmapx %d ino %lld mode 0x%08x " "offset %lld ix %d " "returns negative entry count\n"), gcp->eg_gbmcnt, statp->bs_ino, statp->bs_mode, nextoffset, gcp->eg_bmapix ); *nextoffsetp = nextoffset; *bytecntp = bytecnt; *cmpltflgp = BOOL_TRUE; return RV_OK; } if ( rval ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "getbmapx %d ino %lld mode 0x%08x " "offset %lld failed: %s\n"), gcp->eg_gbmcnt, statp->bs_ino, statp->bs_mode, nextoffset, strerror( errno )); *nextoffsetp = nextoffset; *bytecntp = bytecnt; *cmpltflgp = BOOL_TRUE; return RV_OK; } /* The F_GETBMAPX call succeeded. Give the HSM a chance * to massage the extents. (It can change the number * of extents remaining, even setting them to zero. */ if (hsm_fs_ctxtp) { if (!HsmModifyExtentMap(contextp->cc_hsm_f_ctxtp, &gcp->eg_bmap[0])) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "hsm detected an extent map " "error in ino %lld, skipping\n"), statp->bs_ino); *nextoffsetp = nextoffset; *bytecntp = bytecnt; *cmpltflgp = BOOL_TRUE; return RV_OK; } entrycnt = gcp->eg_bmap[ 0 ].bmv_entries; } if ( entrycnt <= 0 ) { mlog( MLOG_NITTY, "all extent groups dumped\n" ); *nextoffsetp = nextoffset; *bytecntp = bytecnt; *cmpltflgp = BOOL_TRUE; return RV_OK; } gcp->eg_nextbmapp = &gcp->eg_bmap[ 1 ]; gcp->eg_endbmapp = &gcp->eg_bmap[ entrycnt + 1 ]; mlog( MLOG_NITTY, "getbmapx supplied %d extent entries\n", entrycnt ); } mlog( MLOG_NITTY, "bmap entry %d ix %d block %lld offset %lld length %lld\n", gcp->eg_nextbmapp - &gcp->eg_bmap[ 0 ], gcp->eg_bmapix, gcp->eg_nextbmapp->bmv_block, gcp->eg_nextbmapp->bmv_offset, gcp->eg_nextbmapp->bmv_length ); /* if the next bmap entry represents a hole, go to the next * one in the bmap, and rescan to check above assumptions. * bump nextoffset to after the hole, if beyond current value. */ if ( gcp->eg_nextbmapp->bmv_block == -1 ) { off64_t tmpoffset; /* extract the offset and extent size from this * entry */ offset = gcp->eg_nextbmapp->bmv_offset * ( off64_t )BBSIZE; extsz = gcp->eg_nextbmapp->bmv_length * ( off64_t )BBSIZE; mlog( MLOG_NITTY, "hole extent offset = %lld size = %lld\n", offset, extsz ); /* Encode the hole - dump the extent header * with the right extent type. */ rv = dump_extenthdr( drivep, contextp, EXTENTHDR_TYPE_HOLE, 0, offset, extsz ); if ( rv != RV_OK ) { *nextoffsetp = nextoffset; *bytecntp = bytecnt; *cmpltflgp = BOOL_TRUE; /*moot since rv != OK */ return rv; } bytecnt += sizeof( extenthdr_t ); tmpoffset = ( gcp->eg_nextbmapp->bmv_offset + gcp->eg_nextbmapp->bmv_length ) * ( off64_t )BBSIZE; if ( tmpoffset > nextoffset ) { nextoffset = tmpoffset; } gcp->eg_nextbmapp++; gcp->eg_bmapix++; continue; } /* if the next bmap entry has a zero size, go to the next * one in the bmap, and rescan to check above assumptions. */ if ( gcp->eg_nextbmapp->bmv_length <= 0 ) { off64_t tmpoffset; mlog( MLOG_NITTY, "non-positive extent\n" ); tmpoffset = gcp->eg_nextbmapp->bmv_offset * ( off64_t )BBSIZE; if ( tmpoffset > nextoffset ) { nextoffset = tmpoffset; } gcp->eg_nextbmapp++; gcp->eg_bmapix++; continue; } /* extract the offset and extent size from this * entry */ offset = gcp->eg_nextbmapp->bmv_offset * ( off64_t )BBSIZE; extsz = gcp->eg_nextbmapp->bmv_length * ( off64_t )BBSIZE; mlog( MLOG_NITTY, "extent offset %lld sz %lld; nextoffset %lld\n", offset, extsz, nextoffset ); /* if the new bmap entry begins below the stop offset * but does not contain any data above the current * offset, go to the next one and rescan. */ if ( ! sosig || offset < stopoffset ) { if ( offset + extsz <= nextoffset ) { mlog( MLOG_NITTY, "extent ends before nextoffset\n" ); gcp->eg_nextbmapp++; gcp->eg_bmapix++; continue; } } /* if the new bmap entry begins beyond the end of the file, * we are done. */ if ( offset >= statp->bs_size ) { mlog( MLOG_NITTY, "extent beyond end of file\n" ); *nextoffsetp = nextoffset; *bytecntp = bytecnt; *cmpltflgp = BOOL_TRUE; return RV_OK; } /* if the new bmap entry begins at or above the stop offset, * stop. we are done. */ if ( sosig && offset >= stopoffset ) { mlog( MLOG_NITTY, "extent beyond stop offset\n" ); *nextoffsetp = nextoffset; *bytecntp = bytecnt; *cmpltflgp = BOOL_TRUE; return RV_OK; } /* if the new entry begins below the range of * interest, modify offset to begin at the * beginning of the range of interest, and shorten * extsz accordingly. */ if ( offset < nextoffset ) { extsz -= nextoffset - offset; offset = nextoffset; mlog( MLOG_NITTY, "adjusted bottom of extent to nextoffset: " "offset %lld, sz %lld; nextoffset %lld\n", offset, extsz, nextoffset ); } assert( extsz > 0 ); /* if the resultant extent would put us over maxcnt, * shorten it, and round up to the next BBSIZE (round * upto d_miniosz for realtime). */ if ( extsz > maxcnt - ( bytecnt + sizeof( extenthdr_t ))) { int iosz; if (isrealtime) iosz = da.d_miniosz; else iosz = BBSIZE; extsz = maxcnt - ( bytecnt + sizeof( extenthdr_t )); extsz = ( extsz + ( off64_t )( iosz - 1 )) & ~( off64_t )( iosz - 1 ); mlog( MLOG_NITTY, "adjusted top of extent to honor maxcnt " "(rounded up %d): " "offset %lld, sz %lld; maxcnt %lld\n", iosz, offset, extsz, maxcnt ); } /* if the shortened extent is too small, return; we'll * pick it up next time around. exception: if the file * size is zero, indicate we are done. * !!! I don't believe this rule can ever fire! */ if ( extsz <= 0 ) { mlog( MLOG_NITTY, "adjusted extent size is non-positive: " "%lld (bs_size %lld)\n", extsz, statp->bs_size ); *nextoffsetp = nextoffset; *bytecntp = bytecnt; if ( statp->bs_size == 0 ) { *cmpltflgp = BOOL_TRUE; } else { *cmpltflgp = BOOL_FALSE; } return RV_OK; } /* if the resultant extent extends beyond the end of the * file, shorten the extent to the nearest BBSIZE alignment * at or beyond EOF. (Shorten to d_miniosz for realtime * files). */ if ( extsz > statp->bs_size - offset ) { int iosz; if (isrealtime) iosz = da.d_miniosz; else iosz = BBSIZE; extsz = statp->bs_size - offset; extsz = ( extsz + ( off64_t )( iosz - 1 )) & ~( off64_t )( iosz - 1 ); mlog( MLOG_NITTY, "adjusted top of extent to match file size " "(rounded up %d): " "offset %lld, sz %lld; bs_size %lld\n", iosz, offset, extsz, statp->bs_size ); } /* if the extent extends beyond the stop offset, * shorten it to the stop offset. */ if ( sosig && ( extsz > stopoffset - offset )) { extsz = stopoffset - offset; assert( extsz >= 0 ); assert( ! ( extsz & ( off64_t )( BBSIZE - 1 ))); mlog( MLOG_NITTY, "adjusted top of extent " "to adhere to stop offset: " "offset %lld, sz %lld; bs_size %lld\n", offset, extsz, statp->bs_size ); } /* I/O performance is better if we align the media write * buffer to a page boundary. do this if the extent is * at least a page in length. Also, necessary for real time * files */ if ( isrealtime || extsz >= PGALIGNTHRESH * PGSZ ) { size_t cnt_to_align; cnt_to_align = ( * dop->do_get_align_cnt )( drivep ); if ( ( size_t )cnt_to_align < 2*sizeof( extenthdr_t )) { cnt_to_align += PGSZ; } /* account for the DATA header following the alignment */ cnt_to_align -= sizeof( extenthdr_t ); rv = dump_extenthdr( drivep, contextp, EXTENTHDR_TYPE_ALIGN, 0, 0, ( off64_t ) ( ( size_t )cnt_to_align - sizeof(extenthdr_t))); if ( rv != RV_OK ) { *nextoffsetp = nextoffset; *bytecntp = bytecnt; *cmpltflgp = BOOL_TRUE; return rv; } bytecnt += sizeof( extenthdr_t ); cnt_to_align -= sizeof( extenthdr_t ); rv = write_pad( drivep, cnt_to_align ); if ( rv != RV_OK ) { *nextoffsetp = nextoffset; *bytecntp = bytecnt; *cmpltflgp = BOOL_TRUE; /* moot: rv != OK */ return rv; } bytecnt += ( off64_t )cnt_to_align; } /* adjust the next offset */ assert( ( offset & ( off64_t )( BBSIZE - 1 )) == 0 ); assert( ( extsz & ( off64_t )( BBSIZE - 1 )) == 0 ); nextoffset = offset + extsz; /* dump the extent header */ rv = dump_extenthdr( drivep, contextp, EXTENTHDR_TYPE_DATA, 0, offset, extsz ); if ( rv != RV_OK ) { *nextoffsetp = nextoffset; *bytecntp = bytecnt; *cmpltflgp = BOOL_TRUE; /* moot since rv != OK */ return rv; } bytecnt += sizeof( extenthdr_t ); /* dump the extent. if read fails to return all * asked for, pad out the extent with zeros. necessary * because the extent hdr is already out there! */ while ( extsz ) { off64_t new_off; int nread; size_t reqsz; size_t actualsz; char *bufp; reqsz = extsz > ( off64_t )INTGENMAX ? INTGENMAX : ( size_t )extsz; bufp = ( * dop->do_get_write_buf )( drivep, reqsz, &actualsz ); assert( actualsz <= reqsz ); new_off = lseek64( gcp->eg_fd, offset, SEEK_SET ); if ( new_off == ( off64_t )( -1 )) { mlog( MLOG_NORMAL, _( "can't lseek ino %llu\n"), statp->bs_ino ); nread = 0; } else { nread = read( gcp->eg_fd, bufp, actualsz); } if ( nread < 0 ) { #ifdef HIDDEN struct statvfs64 s; /* Be quiet if this is a swap file - #510197 */ if ( (fstatvfs64(gcp->eg_fd, &s) < 0 ) || ((s.f_flag & ST_LOCAL) != 0) ) mlog( MLOG_NORMAL, _( "can't read ino %llu at offset %d (act=%d req=%d) rt=%d\n"), statp->bs_ino, new_off, actualsz , reqsz, isrealtime ); #endif /* HIDDEN */ nread = 0; } assert( ( size_t )nread <= actualsz ); mlog( MLOG_NITTY, "read ino %llu offset %lld sz %d actual %d\n", statp->bs_ino, offset, actualsz, nread ); /* must return entire buffer supplied by call to * do_get_write_buf; so pad end with zeros. below * we assume the short read implies EOF, so will * then pad out remainder of extent as well. */ if ( ( size_t )nread < actualsz ) { memset( ( void * )( bufp + nread ), 0, actualsz - ( size_t )nread ); } rval = ( * dop->do_write )( drivep, bufp, actualsz ); switch ( rval ) { case 0: rv = RV_OK; break; case DRIVE_ERROR_MEDIA: case DRIVE_ERROR_EOM: rv = RV_EOM; break; case DRIVE_ERROR_DEVICE: rv = RV_DRIVE; break; case DRIVE_ERROR_CORE: default: rv = RV_CORE; break; } if ( rv != RV_OK ) { *nextoffsetp = nextoffset; *bytecntp = bytecnt; *cmpltflgp = BOOL_TRUE; /* moot: rv != OK */ return rv; } bytecnt += ( off64_t )actualsz; extsz -= ( off64_t )actualsz; offset += ( off64_t )actualsz; /* if we got a short read, assume we are at the * end of the file; pad out the remainder of the * extent to match the header. */ if ( ( size_t )nread < actualsz ) { mlog( MLOG_NITTY, "padding remaind %lld bytes of extent\n", extsz ); while ( extsz ) { reqsz = extsz > ( off64_t )INTGENMAX ? INTGENMAX : ( size_t )extsz; rv = write_pad( drivep, ( size_t )reqsz ); if ( rv != RV_OK ) { *nextoffsetp = nextoffset; *bytecntp = bytecnt; *cmpltflgp = BOOL_TRUE; return rv; } bytecnt += ( off64_t )reqsz; extsz -= ( off64_t )reqsz; offset += ( off64_t )reqsz; } } } /* made it! advance to the next extent if the current * extent is completely dumped. * !!! not be necessary, taken care of near the * !!! top of the loop. */ if ( nextoffset >= gcp->eg_nextbmapp->bmv_offset * ( off64_t )BBSIZE + gcp->eg_nextbmapp->bmv_length * ( off64_t )BBSIZE ) { mlog( MLOG_NITTY, "advancing to next extent in bmap\n" ); gcp->eg_nextbmapp++; gcp->eg_bmapix++; } } /* NOTREACHED */ } /* Note: assumes the pad fields in dst have been zeroed. */ static void copy_xfs_bstat(bstat_t *dst, xfs_bstat_t *src) { dst->bs_ino = src->bs_ino; dst->bs_mode = src->bs_mode; dst->bs_nlink = src->bs_nlink; dst->bs_uid = src->bs_uid; dst->bs_gid = src->bs_gid; dst->bs_rdev = src->bs_rdev; dst->bs_blksize = src->bs_blksize; dst->bs_size = src->bs_size; dst->bs_atime.tv_sec = src->bs_atime.tv_sec; dst->bs_atime.tv_nsec = src->bs_atime.tv_nsec; dst->bs_mtime.tv_sec = src->bs_mtime.tv_sec; dst->bs_mtime.tv_nsec = src->bs_mtime.tv_nsec; dst->bs_ctime.tv_sec = src->bs_ctime.tv_sec; dst->bs_ctime.tv_nsec = src->bs_ctime.tv_nsec; dst->bs_blocks = src->bs_blocks; dst->bs_xflags = src->bs_xflags; dst->bs_extsize = src->bs_extsize; dst->bs_extents = src->bs_extents; dst->bs_gen = src->bs_gen; dst->bs_projid_lo = src->bs_projid_lo; dst->bs_forkoff = 0; dst->bs_projid_hi = src->bs_projid_hi; dst->bs_dmevmask = src->bs_dmevmask; dst->bs_dmstate = src->bs_dmstate; } static rv_t dump_filehdr( drive_t *drivep, context_t *contextp, xfs_bstat_t *statp, off64_t offset, int flags ) { drive_ops_t *dop = drivep->d_opsp; register filehdr_t *fhdrp = contextp->cc_filehdrp; filehdr_t tmpfhdrp; int rval; rv_t rv; ( void )memset( ( void * )fhdrp, 0, sizeof( *fhdrp )); if ( statp ) { if (hsm_fs_ctxtp) { HsmModifyInode(contextp->cc_hsm_f_ctxtp, statp); } copy_xfs_bstat(&fhdrp->fh_stat, statp); } fhdrp->fh_offset = offset; fhdrp->fh_flags = flags | FILEHDR_FLAGS_CHECKSUM; fhdrp->fh_checksum = calc_checksum( fhdrp, FILEHDR_SZ ); xlate_filehdr(fhdrp, &tmpfhdrp, 1); rval = write_buf( ( char * )&tmpfhdrp, sizeof( tmpfhdrp ), ( void * )drivep, ( gwbfp_t )dop->do_get_write_buf, ( wfp_t )dop->do_write ); switch ( rval ) { case 0: rv = RV_OK; break; case DRIVE_ERROR_MEDIA: case DRIVE_ERROR_EOM: rv = RV_EOM; break; case DRIVE_ERROR_DEVICE: rv = RV_DRIVE; break; case DRIVE_ERROR_CORE: default: rv = RV_CORE; break; } return rv; } static rv_t dump_extenthdr( drive_t *drivep, context_t *contextp, int32_t type, int32_t flags, off64_t offset, off64_t sz ) { drive_ops_t *dop = drivep->d_opsp; register extenthdr_t *ehdrp = contextp->cc_extenthdrp; extenthdr_t tmpehdrp; int rval; rv_t rv; char typestr[20]; switch( type ) { case EXTENTHDR_TYPE_LAST: strcpy( typestr, "LAST" ); break; case EXTENTHDR_TYPE_ALIGN: strcpy( typestr, "ALIGN" ); break; case EXTENTHDR_TYPE_DATA: strcpy( typestr, "DATA" ); break; case EXTENTHDR_TYPE_HOLE: strcpy( typestr, "HOLE" ); break; default: strcpy( typestr, "UNKNOWN" ); } mlog( MLOG_DEBUG, "dumping extent type = %s offset = %lld size = %lld\n", typestr, offset, sz ); ( void )memset( ( void * )ehdrp, 0, sizeof( *ehdrp )); ehdrp->eh_type = type; ehdrp->eh_flags = flags | EXTENTHDR_FLAGS_CHECKSUM; ehdrp->eh_offset = offset; ehdrp->eh_sz = sz; ehdrp->eh_checksum = calc_checksum( ehdrp, EXTENTHDR_SZ ); xlate_extenthdr(ehdrp, &tmpehdrp, 1); rval = write_buf( ( char * )&tmpehdrp, sizeof( tmpehdrp ), ( void * )drivep, ( gwbfp_t )dop->do_get_write_buf, ( wfp_t )dop->do_write ); switch ( rval ) { case 0: rv = RV_OK; break; case DRIVE_ERROR_MEDIA: case DRIVE_ERROR_EOM: rv = RV_EOM; break; case DRIVE_ERROR_DEVICE: rv = RV_DRIVE; break; case DRIVE_ERROR_CORE: default: rv = RV_CORE; break; } return rv; } static rv_t dump_dirent( drive_t *drivep, context_t *contextp, xfs_bstat_t *statp, xfs_ino_t ino, gen_t gen, char *name, size_t namelen ) { drive_ops_t *dop = drivep->d_opsp; char *outbufp; size_t direntbufsz = contextp->cc_mdirentbufsz; size_t sz; size_t name_offset; int rval; rv_t rv; if ( sc_use_old_direntpr ) { name_offset = offsetofmember( direnthdr_v1_t, dh_name ); } else { name_offset = offsetofmember( direnthdr_t, dh_name ); } sz = name_offset + namelen + 1; sz = ( sz + DIRENTHDR_ALIGN - 1 ) & ~( DIRENTHDR_ALIGN - 1 ); if ( sz > direntbufsz ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "unable to dump " "directory %llu entry %s (%llu): " "name too long\n"), statp->bs_ino, name, ino ); mlog_exit_hint(RV_INCOMPLETE); return RV_OK; } assert( sz <= UINT16MAX ); assert( sz >= DIRENTHDR_SZ ); outbufp = malloc(sz); if ( sc_use_old_direntpr ) { direnthdr_v1_t *dhdrp = ( direnthdr_v1_t * )contextp->cc_mdirentbufp; direnthdr_v1_t *tmpdhdrp = ( direnthdr_v1_t * )outbufp; memset( ( void * )dhdrp, 0, sz ); dhdrp->dh_ino = ino; dhdrp->dh_sz = ( uint16_t )sz; dhdrp->dh_gen = ( uint16_t )( gen & DENTGENMASK ); if ( name ) { strcpy( dhdrp->dh_name, name ); } dhdrp->dh_checksum = calc_checksum( dhdrp, DIRENTHDR_SZ ); xlate_direnthdr_v1( dhdrp, tmpdhdrp, 1 ); if ( name ) { strcpy( tmpdhdrp->dh_name, name ); } } else { direnthdr_t *dhdrp = ( direnthdr_t * )contextp->cc_mdirentbufp; direnthdr_t *tmpdhdrp = ( direnthdr_t * )outbufp; memset( ( void * )dhdrp, 0, sz ); dhdrp->dh_ino = ino; dhdrp->dh_gen = gen; dhdrp->dh_sz = ( uint16_t )sz; if ( name ) { strcpy( dhdrp->dh_name, name ); } dhdrp->dh_checksum = calc_checksum( dhdrp, DIRENTHDR_SZ ); xlate_direnthdr( dhdrp, tmpdhdrp, 1 ); if ( name ) { strcpy( tmpdhdrp->dh_name, name ); } } rval = write_buf( outbufp, sz, ( void * )drivep, ( gwbfp_t )dop->do_get_write_buf, ( wfp_t )dop->do_write ); free(outbufp); switch ( rval ) { case 0: rv = RV_OK; break; case DRIVE_ERROR_MEDIA: case DRIVE_ERROR_EOM: rv = RV_EOM; break; case DRIVE_ERROR_DEVICE: rv = RV_DRIVE; break; case DRIVE_ERROR_CORE: default: rv = RV_CORE; break; } return rv; } static bool_t dump_session_inv( drive_t *drivep, context_t *contextp, media_hdr_t *mwhdrp, content_inode_hdr_t *scwhdrp ) { drive_ops_t *dop = drivep->d_opsp; ix_t strmix = drivep->d_index; inv_stmtoken_t inv_stmt; char *inv_sbufp; size_t inv_sbufsz; off64_t ncommitted; bool_t ok; bool_t done; /* if the inventory session token is null, skip */ if ( sc_inv_sestoken == INV_TOKEN_NULL ) { return BOOL_TRUE; } mlog( MLOG_VERBOSE, _( "dumping session inventory\n") ); /* get a buffer from the inventory manager */ inv_sbufp = 0; inv_sbufsz = 0; ok = inv_get_sessioninfo( sc_inv_sestoken, ( void * )&inv_sbufp, &inv_sbufsz ); if ( ! ok ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "unable to get session inventory to dump\n") ); return BOOL_TRUE; } assert( inv_sbufp ); /* modify the write header to indicate the media file type. */ scwhdrp->cih_mediafiletype = CIH_MEDIAFILETYPE_INVENTORY; /* loop attempting to write a complete media file, * until we are successful or until the media layer * tells us to give up. */ for ( done = BOOL_FALSE ; ! done ; ) { uuid_t mediaid; char medialabel[ GLOBAL_HDR_STRING_SZ ]; bool_t partial; int mediafileix; int rval; rv_t rv; mlog( MLOG_VERBOSE, _( "beginning inventory media file\n") ); partial = BOOL_FALSE; rv = Media_mfile_begin( drivep, contextp, BOOL_FALSE ); switch( rv ) { case RV_OK: break; case RV_TIMEOUT: mlog( MLOG_VERBOSE | MLOG_WARNING, _( "media change timeout: " "session inventory not dumped\n") ); mlog_exit_hint(RV_INV); return BOOL_FALSE; case RV_QUIT: mlog( MLOG_VERBOSE | MLOG_WARNING, _( "media change declined: " "session inventory not dumped\n") ); mlog_exit_hint(RV_INV); return BOOL_FALSE; case RV_DRIVE: case RV_ERROR: case RV_CORE: default: return BOOL_FALSE; } mlog( MLOG_VERBOSE, _( "media file %u (media %u, file %u)\n"), mwhdrp->mh_dumpfileix, mwhdrp->mh_mediaix, mwhdrp->mh_mediafileix ); uuid_copy(mediaid, mwhdrp->mh_mediaid); strcpy( medialabel, mwhdrp->mh_medialabel ); mediafileix = ( int )mwhdrp->mh_mediafileix; rval = write_buf( inv_sbufp, inv_sbufsz, ( void * )drivep, ( gwbfp_t )dop->do_get_write_buf, ( wfp_t )dop->do_write ); switch ( rval ) { case 0: break; case DRIVE_ERROR_MEDIA: case DRIVE_ERROR_EOM: partial = BOOL_TRUE; break; case DRIVE_ERROR_DEVICE: case DRIVE_ERROR_CORE: default: return BOOL_FALSE; } mlog( MLOG_VERBOSE, _( "ending inventory media file\n") ); ncommitted = 0; rv = Media_mfile_end( drivep, contextp, mwhdrp, &ncommitted, partial ); switch( rv ) { case RV_OK: break; case RV_EOM: partial = BOOL_TRUE; break; default: return BOOL_FALSE; } if ( partial ) { mlog( MLOG_VERBOSE, _( "encountered EOM while writing " "inventory media file size %lld bytes\n"), ncommitted ); mlog_exit_hint(RV_INV); } else { mlog( MLOG_VERBOSE, _( "inventory media file size %lld bytes\n"), ncommitted ); } if ( sc_inv_stmtokenp ) { inv_stmt = sc_inv_stmtokenp[ strmix ]; } else { inv_stmt = INV_TOKEN_NULL; } if ( inv_stmt != INV_TOKEN_NULL ) { mlog( MLOG_DEBUG, "giving inventory " "session dump media file\n" ); ok = inv_put_mediafile( inv_stmt, &mediaid, medialabel, ( uint )mediafileix, (xfs_ino_t )0, ( off64_t )0, (xfs_ino_t )0, ( off64_t )0, ncommitted, ! partial, BOOL_TRUE ); if ( ! ok ) { mlog( MLOG_NORMAL, _( "inventory session media file " "put failed\n") ); return BOOL_FALSE; } } done = ! partial; } return BOOL_TRUE; } static void dump_terminator( drive_t *drivep, context_t *contextp, media_hdr_t *mwhdrp ) { off64_t ncommitted; bool_t done; /* if the drive doesn't support use of stream terminators, don't bother */ if ( ! contextp->cc_Media_useterminatorpr ) { return; } mlog( MLOG_VERBOSE, _( "writing stream terminator\n") ); /* modify the write header to indicate a terminator */ MEDIA_TERMINATOR_SET( mwhdrp ); /* loop attempting to write a complete media file header * until we are successful or until the media layer * tells us to give up. */ for ( done = BOOL_FALSE ; ! done ; ) { bool_t partial; rv_t rv; mlog( MLOG_VERBOSE, _( "beginning media stream terminator\n") ); partial = BOOL_FALSE; rv = Media_mfile_begin( drivep, contextp, BOOL_FALSE ); switch( rv ) { case RV_OK: break; case RV_TIMEOUT: mlog( MLOG_VERBOSE | MLOG_WARNING, _( "media change timeout: " "media stream terminator not written\n") ); return; case RV_QUIT: mlog( MLOG_VERBOSE | MLOG_WARNING, _( "media change declined: " "media stream terminator not written\n") ); return; case RV_DRIVE: case RV_ERROR: case RV_CORE: default: return; } mlog( MLOG_VERBOSE, _( "media file %u (media %u, file %u)\n"), mwhdrp->mh_dumpfileix, mwhdrp->mh_mediaix, mwhdrp->mh_mediafileix ); mlog( MLOG_VERBOSE, _( "ending media stream terminator\n") ); ncommitted = 0; rv = Media_mfile_end( drivep, contextp, mwhdrp, &ncommitted, BOOL_FALSE ); switch( rv ) { case RV_OK: break; case RV_EOM: partial = BOOL_TRUE; break; default: return; } if ( partial ) { mlog( MLOG_VERBOSE, _( "encountered EOM while writing " "media stream terminator size %lld bytes\n"), ncommitted ); } else { mlog( MLOG_VERBOSE, _( "media stream terminator size %lld bytes\n"), ncommitted ); } done = ! partial; } } static rv_t write_pad( drive_t *drivep, size_t sz ) { drive_ops_t *dop = drivep->d_opsp; int rval; rv_t rv; rval = write_buf( 0, sz, ( void * )drivep, ( gwbfp_t )dop->do_get_write_buf, ( wfp_t )dop->do_write ); switch ( rval ) { case 0: rv = RV_OK; break; case DRIVE_ERROR_MEDIA: case DRIVE_ERROR_EOM: rv = RV_EOM; break; case DRIVE_ERROR_DEVICE: rv = RV_DRIVE; break; case DRIVE_ERROR_CORE: default: rv = RV_CORE; break; } return rv; } static void inv_cleanup( void ) { /* REFERENCED */ bool_t ok; if ( sc_inv_stmtokenp && sc_contextp ) { size_t strmix; inv_stmtoken_t *inv_stmtp; context_t *contextp; for ( strmix = 0, inv_stmtp = sc_inv_stmtokenp, contextp = sc_contextp ; strmix < drivecnt ; strmix++, inv_stmtp++, contextp++ ) { bool_t interrupted; interrupted = ! contextp->cc_completepr; if ( *inv_stmtp == INV_TOKEN_NULL ) { continue; } mlog( MLOG_DEBUG, "closing inventory stream %d%s\n", strmix, interrupted ? ": interrupted" : "" ); if (interrupted) mlog_exit_hint(RV_INTR); ok = inv_stream_close( *inv_stmtp, interrupted ); assert( ok ); } } if ( sc_inv_sestoken != INV_TOKEN_NULL ) { ok = inv_writesession_close( sc_inv_sestoken ); assert( ok ); } if ( sc_inv_idbtoken != INV_TOKEN_NULL ) { ok = inv_close( sc_inv_idbtoken ); assert( ok ); } } /* This function returns with the proper media positioned at the proper place * in the specified drive, with a write header layed down. The caller can * immediately dump. The caller is expected to call Media_mfile_end when * the media file is complete or EOM is encountered. * * Media_mfile_begin is partitioned into 4 coroutines, between which it * readily jumps back and forth using gotos. So be careful about the scope * of automatic variables. */ static rv_t Media_mfile_begin( drive_t *drivep, context_t *contextp, bool_t intr_allowed ) { drive_ops_t *dop = drivep->d_opsp; int dcaps = drivep->d_capabilities; global_hdr_t *gwhdrp = drivep->d_gwritehdrp; drive_hdr_t *dwhdrp = drivep->d_writehdrp; media_hdr_t *mwhdrp = ( media_hdr_t * )dwhdrp->dh_upper; drive_hdr_t *drhdrp = drivep->d_readhdrp; media_hdr_t *mrhdrp = ( media_hdr_t * )drhdrp->dh_upper; char *cmdlinemedialabel; bool_t virginmediapr; bool_t mediapresentpr; bool_t prevmediapresentpr; bool_t mediawrittentopr; global_hdr_t saved_gwhdr; int rval; bool_t ok; /* sanity checks */ assert( BES_INIT == 0 ); mlog( MLOG_DEBUG | MLOG_MEDIA, "Media op: begin media file\n" ); /* the command line-specified media label is good only for the * first media object written to. after that, the operator will * be prompted for a label. To enforce this, cc_Media_firstlabel * is saved in a temp var and NULLed. */ cmdlinemedialabel = contextp->cc_Media_firstlabel; contextp->cc_Media_firstlabel = 0; /* dispatch based on entry state. invalidate entry state to assert * each Media_mfile_begin is followed by and Media_mfile_end. */ prevmediapresentpr = BOOL_UNKNOWN; { bes_t entrystate; entrystate = contextp->cc_Media_begin_entrystate; contextp->cc_Media_begin_entrystate = BES_INVAL; switch ( entrystate ) { case BES_INIT: mediawrittentopr = BOOL_FALSE; mwhdrp->mh_mediaix = ( uint32_t )( -1 ); mwhdrp->mh_dumpfileix = ( uint32_t )( -1 ); if ( dcaps & DRIVE_CAP_READ ) { mediapresentpr = BOOL_UNKNOWN; virginmediapr = BOOL_UNKNOWN; goto position; } else { mediapresentpr = BOOL_TRUE; virginmediapr = BOOL_TRUE; goto write; } case BES_ENDOK: mediapresentpr = BOOL_TRUE; virginmediapr = BOOL_FALSE; mediawrittentopr = BOOL_TRUE; goto write; case BES_ENDEOM: mediapresentpr = BOOL_TRUE; virginmediapr = BOOL_FALSE; mediawrittentopr = BOOL_TRUE; goto changemedia; default: assert( 0 ); return RV_CORE; } } position: /* loop until we are positioned either at end of recorded data * or at a terminator, as appropriate, of some media object, or hit EOM. * goto write or changemedia to get out of loop (or return on * catastrophic condition). ensure that all but the first media file * of a stream begins on virgin media. that is, dump streams may * be concatenated but not jumbled. a dump stream must be virtually * contiguous. */ for ( ; ; ) { /* check if a stop has been requested */ if ( intr_allowed && cldmgr_stop_requested( )) { return RV_INTR; } /* do a begin_read to see the disposition of the drive/media. */ rval = ( * dop->do_begin_read )( drivep ); /* update cc_Media_useterminatorpr after every begin_read, * since begin_read will cause some unknown drive params * to be resolved. */ update_cc_Media_useterminatorpr( drivep, contextp ); switch( rval ) { case 0: mlog_lock( ); mlog( MLOG_VERBOSE | MLOG_NOLOCK | MLOG_MEDIA, _( "positioned at media file %u: " "dump %u, " "stream %u\n"), mrhdrp->mh_mediafileix, mrhdrp->mh_dumpmediaix, drhdrp->dh_driveix ); mlog( MLOG_TRACE | MLOG_NOLOCK | MLOG_MEDIA, "stream media file %u (%u in object), " "stream media object %d\n", mrhdrp->mh_dumpfileix, mrhdrp->mh_dumpmediafileix, mrhdrp->mh_mediaix ); mlog_unlock( ); /* successfully read media file header. * we know media must be present in drive, and * contains at least one valid xfsdump, hence * is not virgin. */ prevmediapresentpr = mediapresentpr; mediapresentpr = BOOL_TRUE; virginmediapr = BOOL_FALSE; /* do an end_read. the next begin_read will * position in preparation for appending. * if terminator, back up, we'll overwrite it. * also be sure we can append dumps. * if we back over a terminator which is the * first media file on the media object, make the * media object a virgin. * also, check for erase option. */ ( * dop->do_end_read )( drivep ); switch( Media_erasechk( drivep, dcaps, intr_allowed, prevmediapresentpr )) { case RV_OK: goto erasemedia; case RV_INTR: return RV_INTR; default: break; } if ( ( int32_t )mwhdrp->mh_mediaix >= 0 ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_MEDIA,_( "cannot interleave dump streams: " "must supply a blank media object\n") ); goto changemedia; } if ( ! ( dcaps & DRIVE_CAP_APPEND )) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_MEDIA, _( "media contains valid xfsdump " "but does not support append\n") ); goto changemedia; } if ( MEDIA_TERMINATOR_CHK( mrhdrp )) { int status; mlog( MLOG_VERBOSE | MLOG_MEDIA, _( "stream terminator found\n") ); assert( contextp->cc_Media_useterminatorpr ); assert( dcaps & DRIVE_CAP_BSF ); /* redundant */ status = 0; rval = ( * dop->do_bsf )( drivep, 0, &status ); assert( rval == 0 ); if ( status == DRIVE_ERROR_DEVICE ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_MEDIA, _( "encountered media error " "attempting BSF\n") ); goto changemedia; } if ( mrhdrp->mh_mediafileix == 0 ) { virginmediapr = BOOL_TRUE; } goto write; } continue; case DRIVE_ERROR_FOREIGN: prevmediapresentpr = mediapresentpr; mediapresentpr = BOOL_TRUE; mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_MEDIA, _( "media contains non-xfsdump data " "or a corrupt xfsdump media file header " "at beginning of media\n") ); mlog_exit_hint(RV_CORRUPT); switch( Media_erasechk( drivep, dcaps, intr_allowed, prevmediapresentpr )) { case RV_OK: goto erasemedia; case RV_INTR: return RV_INTR; default: break; } if ( dlog_allowed( )) { bool_t ok; ok = Media_prompt_overwrite( drivep ); if ( intr_allowed && cldmgr_stop_requested( )) { return RV_INTR; } if ( ! ok ) { goto changemedia; } } if ( ! ( dcaps & DRIVE_CAP_OVERWRITE )) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_MEDIA, _( "unable to overwrite\n") ); goto changemedia; } else { int status; mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_MEDIA, _( "repositioning to overwrite\n") ); assert( dcaps & DRIVE_CAP_BSF ); status = 0; rval = ( * dop->do_bsf )( drivep, 0, &status ); assert( rval == 0 ); if ( status == DRIVE_ERROR_DEVICE ) { return RV_DRIVE; } virginmediapr = BOOL_TRUE; goto write; } case DRIVE_ERROR_OVERWRITE: prevmediapresentpr = mediapresentpr; mediapresentpr = BOOL_TRUE; mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_MEDIA, _( "media may contain data. " "Overwrite option specified\n") ); if ( dlog_allowed( )) { bool_t ok; ok = Media_prompt_overwrite( drivep ); if ( intr_allowed && cldmgr_stop_requested( )) { return RV_INTR; } if ( ! ok ) { goto changemedia; } } virginmediapr = BOOL_TRUE; /* like a virgin */ goto write; case DRIVE_ERROR_BLANK: prevmediapresentpr = mediapresentpr; mediapresentpr = BOOL_TRUE; virginmediapr = BOOL_TRUE; goto write; case DRIVE_ERROR_MEDIA: prevmediapresentpr = mediapresentpr; mediapresentpr = BOOL_TRUE; goto changemedia; case DRIVE_ERROR_DEVICE: return RV_DRIVE; case DRIVE_ERROR_EOD: mlog( MLOG_VERBOSE | MLOG_MEDIA, _( "at end of data\n") ); prevmediapresentpr = mediapresentpr; mediapresentpr = BOOL_TRUE; virginmediapr = BOOL_FALSE; switch( Media_erasechk( drivep, dcaps, intr_allowed, prevmediapresentpr )) { case RV_OK: goto erasemedia; case RV_INTR: return RV_INTR; default: break; } if ( contextp->cc_Media_useterminatorpr ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_MEDIA,_( "encountered EOD but expecting a media " "stream terminator: " "assuming full media\n") ); goto changemedia; } else { goto write; } case DRIVE_ERROR_EOM: prevmediapresentpr = mediapresentpr; mediapresentpr = BOOL_TRUE; virginmediapr = BOOL_FALSE; mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_MEDIA, _( "encountered EOM: media is full\n") ); switch( Media_erasechk( drivep, dcaps, intr_allowed, prevmediapresentpr )) { case RV_OK: goto erasemedia; case RV_INTR: return RV_INTR; default: break; } goto changemedia; case DRIVE_ERROR_CORRUPTION: case DRIVE_ERROR_VERSION: case DRIVE_ERROR_FORMAT: prevmediapresentpr = mediapresentpr; mediapresentpr = BOOL_TRUE; virginmediapr = BOOL_FALSE; mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_MEDIA, _( "encountered corrupt or foreign data: " "assuming corrupted media\n") ); mlog_exit_hint(RV_CORRUPT); switch( Media_erasechk( drivep, dcaps, intr_allowed, prevmediapresentpr )) { case RV_OK: goto erasemedia; case RV_INTR: return RV_INTR; default: break; } if ( contextp->cc_Media_useterminatorpr ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_MEDIA,_( "encountered corrupt or foreign data " "but expecting a media " "stream terminator: " "assuming corrupted media\n") ); mlog_exit_hint(RV_CORRUPT); goto changemedia; } else if ( ! ( dcaps & DRIVE_CAP_OVERWRITE )) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_MEDIA,_( "encountered corrupt or foreign data: " "unable to overwrite: " "assuming corrupted media\n") ); mlog_exit_hint(RV_CORRUPT); goto changemedia; } else { int status; mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_MEDIA,_( "encountered corrupt or foreign data: " "repositioning to overwrite\n") ); mlog_exit_hint(RV_CORRUPT); assert( dcaps & DRIVE_CAP_BSF ); status = 0; rval = ( * dop->do_bsf )( drivep, 0, &status ); assert( rval == 0 ); if ( status == DRIVE_ERROR_DEVICE ) { return RV_DRIVE; } goto write; } case DRIVE_ERROR_STOP: return RV_INTR; case DRIVE_ERROR_INVAL: return RV_ERROR; case DRIVE_ERROR_EOF: default: mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_MEDIA, _( "unexpected error from do_begin_read: %d\n"), rval ); return RV_CORE; } } /* NOTREACHED */ erasemedia: mlog( MLOG_VERBOSE | MLOG_WARNING | MLOG_MEDIA, _( "erasing media\n") ); rval = ( * dop->do_erase )( drivep ); if ( rval ) { return RV_DRIVE; } prevmediapresentpr = mediapresentpr; mediapresentpr = BOOL_UNKNOWN; virginmediapr = BOOL_UNKNOWN; mediawrittentopr = BOOL_FALSE; goto position; changemedia: /* if the drive does not support media change, quit. */ if ( ! ( dcaps & DRIVE_CAP_REMOVABLE )) { return RV_ERROR; } /* first eject the current media object if capability supported */ assert( mediapresentpr != BOOL_UNKNOWN ); if ( mediapresentpr == BOOL_TRUE ) { if ( dcaps & DRIVE_CAP_EJECT ) { rval = ( * dop->do_eject_media )( drivep ); if ( rval ) { return RV_DRIVE; } } } /* if dialogs not allowed, we are done. */ if ( ! dlog_allowed( )) { return RV_QUIT; /* this return value will cause approp. msg */ } /* If an alert program has been specified , run it */ if (media_change_alert_program != NULL) system(media_change_alert_program); /* if media change prompt declined or times out, * we are done */ if ( drivecnt > 1 && ! stdoutpiped ) { ix_t thrdix = drivep->d_index; assert( sistr ); mlog( MLOG_NORMAL | MLOG_NOTE | MLOG_MEDIA, _( "please change media: " "type %s to confirm media change\n"), sistr ); set_mcflag( thrdix ); while ( sc_mcflag[ thrdix ] ) { sleep( 2 ); if ( cldmgr_stop_requested( )) { clr_mcflag( thrdix ); return RV_INTR; } } ok = BOOL_TRUE; } else { ok = Media_prompt_change( drivep ); } if ( intr_allowed && cldmgr_stop_requested( )) { return RV_INTR; } if ( ! ok ) { return RV_QUIT; } /* we know nothing about the media after a media change */ prevmediapresentpr = mediapresentpr; mediapresentpr = BOOL_UNKNOWN; virginmediapr = BOOL_UNKNOWN; mediawrittentopr = BOOL_FALSE; goto position; write: assert( mediapresentpr == BOOL_TRUE ); assert( virginmediapr != BOOL_UNKNOWN ); if ( intr_allowed && cldmgr_stop_requested( )) { return RV_INTR; } /* bump the media header indices here. NOTE: will rescind these * if the subsequent do_begin_write fails. this will be done by * making a copy of the global write header, and copying it * back on failure. */ saved_gwhdr = *gwhdrp; if ( mediawrittentopr ) { mwhdrp->mh_dumpmediafileix++; } else { mwhdrp->mh_dumpmediafileix = 0; } mwhdrp->mh_dumpfileix++; /* pre-initialized to -1 */ if ( virginmediapr ) { mwhdrp->mh_mediafileix = 0; mwhdrp->mh_dumpmediaix = 0; } else { if ( mwhdrp->mh_dumpmediafileix == 0 ) { mwhdrp->mh_dumpmediaix = mrhdrp->mh_dumpmediaix + 1; } if ( mediawrittentopr ) { mwhdrp->mh_mediafileix++; } else { mwhdrp->mh_mediafileix = mrhdrp->mh_mediafileix; if ( ! MEDIA_TERMINATOR_CHK( mrhdrp )) { mwhdrp->mh_mediafileix++; } } } if ( ! mediawrittentopr ) { mwhdrp->mh_mediaix++; /* pre-initialized to -1 */ } assert( mwhdrp->mh_mediaix != ( uint32_t )( -1 )); assert( mwhdrp->mh_dumpfileix != ( uint32_t )( -1 )); /* do not allow interleaving of media files from different xfsdumps. */ if ( mwhdrp->mh_mediaix != 0 && mwhdrp->mh_dumpmediafileix == 0 && ! virginmediapr ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_MEDIA, _( "cannot interleave dump streams: must supply a blank " "media object\n") ); *gwhdrp = saved_gwhdr; goto changemedia; } /* update the media object previous id and label */ if ( ! mediawrittentopr && mwhdrp->mh_dumpfileix != 0 ) { uuid_copy(mwhdrp->mh_prevmediaid, mwhdrp->mh_mediaid); ( void )strncpyterm( mwhdrp->mh_prevmedialabel, mwhdrp->mh_medialabel, sizeof( mwhdrp->mh_medialabel )); } /* update the media object current id and label */ if ( ! mediawrittentopr ) { if ( mwhdrp->mh_mediafileix == 0 ) { char labelbuf[ GLOBAL_HDR_STRING_SZ ]; uuid_generate( mwhdrp->mh_mediaid ); if ( ! cmdlinemedialabel && ! drivep->d_isnamedpipepr && ! drivep->d_isunnamedpipepr && dlog_allowed( )) { cmdlinemedialabel = Media_prompt_label( drivep, labelbuf, sizeof( labelbuf )); if ( intr_allowed && cldmgr_stop_requested( )) { return RV_INTR; } } if ( cmdlinemedialabel && strlen( cmdlinemedialabel )) { ( void )strncpyterm( mwhdrp->mh_medialabel, cmdlinemedialabel, sizeof( mwhdrp->mh_medialabel )); } else { ( void )memset( ( void * )mwhdrp->mh_medialabel, 0, sizeof( mwhdrp->mh_medialabel )); if ( ! pipeline ) { mlog( MLOG_VERBOSE | MLOG_WARNING | MLOG_MEDIA, _( "no media label specified\n") ); } } } else { assert( ! virginmediapr ); uuid_copy(mwhdrp->mh_mediaid, mrhdrp->mh_mediaid); ( void )strncpyterm( mwhdrp->mh_medialabel, mrhdrp->mh_medialabel, sizeof( mwhdrp->mh_medialabel )); } } mediawrittentopr = BOOL_TRUE; /* write hdr is prepared. place it on media */ if ( intr_allowed && cldmgr_stop_requested( )) { return RV_INTR; } rval = ( * dop->do_begin_write )( drivep ); switch( rval ) { case 0: return RV_OK; case DRIVE_ERROR_EOM: mlog( MLOG_VERBOSE | MLOG_MEDIA, _( "encountered end of media " "while attempting to begin new media file\n") ); *gwhdrp = saved_gwhdr; goto changemedia; case DRIVE_ERROR_MEDIA: *gwhdrp = saved_gwhdr; goto changemedia; case DRIVE_ERROR_DEVICE: return RV_DRIVE; default: return RV_CORE; } } /* ARGSUSED */ static rv_t Media_mfile_end( drive_t *drivep, context_t *contextp, media_hdr_t *mwhdrp, off64_t *ncommittedp, bool_t hit_eom ) { drive_ops_t *dop = drivep->d_opsp; int rval; mlog( MLOG_DEBUG | MLOG_MEDIA, "Media op: end media file\n" ); assert( contextp->cc_Media_begin_entrystate == BES_INVAL ); /* call drive's end_write op to flush the tail of the media file * if has previously hit EOM, this is moot. */ rval = ( dop->do_end_write )( drivep, ncommittedp ); if ( hit_eom ) { assert( ! rval ); contextp->cc_Media_begin_entrystate = BES_ENDEOM; return RV_EOM; } switch( rval ) { case 0: contextp->cc_Media_begin_entrystate = BES_ENDOK; return RV_OK; case DRIVE_ERROR_MEDIA: case DRIVE_ERROR_EOM: mlog( MLOG_VERBOSE | MLOG_MEDIA, _( "encountered end of media " "while ending media file\n") ); mlog_exit_hint(RV_EOM); contextp->cc_Media_begin_entrystate = BES_ENDEOM; return RV_EOM; case DRIVE_ERROR_DEVICE: contextp->cc_Media_begin_entrystate = BES_INVAL; return RV_DRIVE; default: contextp->cc_Media_begin_entrystate = BES_INVAL; return RV_CORE; } } static bool_t Media_prompt_overwrite( drive_t *drivep ) { fold_t fold; char question[ 100 ]; char *preamblestr[ PREAMBLEMAX ]; size_t preamblecnt; char *querystr[ QUERYMAX ]; size_t querycnt; char *choicestr[ CHOICEMAX ]; size_t choicecnt; char *ackstr[ ACKMAX ]; size_t ackcnt; char *postamblestr[ POSTAMBLEMAX ]; size_t postamblecnt; ix_t doix; ix_t dontix; ix_t responseix; ix_t sigintix; retry: preamblecnt = 0; fold_init( fold, "media overwrite dialog", '=' ); preamblestr[ preamblecnt++ ] = "\n"; preamblestr[ preamblecnt++ ] = fold; preamblestr[ preamblecnt++ ] = "\n\n"; assert( preamblecnt <= PREAMBLEMAX ); dlog_begin( preamblestr, preamblecnt ); /* query: ask if overwrite ok */ sprintf( question, "overwrite data on media in " "drive %u?\n", (unsigned int)drivep->d_index ); querycnt = 0; querystr[ querycnt++ ] = question; assert( querycnt <= QUERYMAX ); choicecnt = 0; dontix = choicecnt; choicestr[ choicecnt++ ] = "don't overwrite"; doix = choicecnt; choicestr[ choicecnt++ ] = "overwrite"; assert( choicecnt <= CHOICEMAX ); sigintix = IXMAX - 1; responseix = dlog_multi_query( querystr, querycnt, choicestr, choicecnt, 0, /* hilitestr */ IXMAX, /* hiliteix */ 0, /* defaultstr */ doix, /* defaultix */ DLOG_TIMEOUT_MEDIA, dontix, /* timeout ix */ sigintix, /* sigint ix */ dontix, /* sighup ix */ dontix ); /* sigquit ix */ ackcnt = 0; if ( responseix == doix ) { ackstr[ ackcnt++ ] = "media will be overwritten\n"; } else if ( responseix == dontix ) { ackstr[ ackcnt++ ] = "media will NOT be overwritten\n"; } else { ackstr[ ackcnt++ ] = "keyboard interrupt\n"; } assert( ackcnt <= ACKMAX ); dlog_multi_ack( ackstr, ackcnt ); postamblecnt = 0; fold_init( fold, "end dialog", '-' ); postamblestr[ postamblecnt++ ] = "\n"; postamblestr[ postamblecnt++ ] = fold; postamblestr[ postamblecnt++ ] = "\n\n"; assert( postamblecnt <= POSTAMBLEMAX ); dlog_end( postamblestr, postamblecnt ); if ( responseix == sigintix ) { if ( cldmgr_stop_requested( )) { return BOOL_FALSE; } sleep( 1 ); /* to allow main thread to begin dialog */ mlog( MLOG_NORMAL | MLOG_BARE, "" ); /* to block until main thread dialog complete */ sleep( 1 ); /* to allow main thread to request children die */ if ( cldmgr_stop_requested( )) { return BOOL_FALSE; } mlog( MLOG_DEBUG, "retrying media overwrite dialog\n" ); goto retry; } return responseix == doix; } static rv_t Media_erasechk( drive_t *drivep, int dcaps, bool_t intr_allowed, bool_t prevmediapresentpr ) { if ( prevmediapresentpr == BOOL_TRUE ) { return RV_NOTOK; } if ( sc_preerasepr ) { if ( dcaps & DRIVE_CAP_ERASE ) { if ( dlog_allowed( )) { bool_t ok; ok = Media_prompt_erase( drivep ); if ( intr_allowed && cldmgr_stop_requested( )) { return RV_INTR; } if ( ok ) { return RV_OK; } else { return RV_NOTOK; } } else { return RV_OK; } } else { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_MEDIA, _( "drive does not support media erase: " "ignoring -%c option\n"), GETOPT_ERASE ); return RV_NOTOK; } } else { return RV_NOTOK; } } static bool_t Media_prompt_erase( drive_t *drivep ) { fold_t fold; char question[ 100 ]; char *preamblestr[ PREAMBLEMAX ]; size_t preamblecnt; char *querystr[ QUERYMAX ]; size_t querycnt; char *choicestr[ CHOICEMAX ]; size_t choicecnt; char *ackstr[ ACKMAX ]; size_t ackcnt; char *postamblestr[ POSTAMBLEMAX ]; size_t postamblecnt; ix_t doix; ix_t dontix; ix_t responseix; ix_t sigintix; retry: preamblecnt = 0; fold_init( fold, "media erase dialog", '=' ); preamblestr[ preamblecnt++ ] = "\n"; preamblestr[ preamblecnt++ ] = fold; preamblestr[ preamblecnt++ ] = "\n\n"; assert( preamblecnt <= PREAMBLEMAX ); dlog_begin( preamblestr, preamblecnt ); /* query: ask if overwrite ok */ sprintf( question, "pre-erase (-%c) option specified " "and non-blank media encountered:\n" "please confirm media erase " "drive %u\n", GETOPT_ERASE, (unsigned int)drivep->d_index ); querycnt = 0; querystr[ querycnt++ ] = question; assert( querycnt <= QUERYMAX ); choicecnt = 0; dontix = choicecnt; choicestr[ choicecnt++ ] = "don't erase"; doix = choicecnt; choicestr[ choicecnt++ ] = "erase"; assert( choicecnt <= CHOICEMAX ); sigintix = IXMAX - 1; responseix = dlog_multi_query( querystr, querycnt, choicestr, choicecnt, 0, /* hilitestr */ IXMAX, /* hiliteix */ 0, /* defaultstr */ doix, /* defaultix */ DLOG_TIMEOUT_MEDIA, dontix, /* timeout ix */ sigintix, /* sigint ix */ dontix, /* sighup ix */ dontix ); /* sigquit ix */ ackcnt = 0; if ( responseix == doix ) { ackstr[ ackcnt++ ] = "media will be erased\n"; } else if ( responseix == dontix ) { ackstr[ ackcnt++ ] = "media will NOT be erased\n"; } else { ackstr[ ackcnt++ ] = "keyboard interrupt\n"; } assert( ackcnt <= ACKMAX ); dlog_multi_ack( ackstr, ackcnt ); postamblecnt = 0; fold_init( fold, "end dialog", '-' ); postamblestr[ postamblecnt++ ] = "\n"; postamblestr[ postamblecnt++ ] = fold; postamblestr[ postamblecnt++ ] = "\n\n"; assert( postamblecnt <= POSTAMBLEMAX ); dlog_end( postamblestr, postamblecnt ); if ( responseix == sigintix ) { if ( cldmgr_stop_requested( )) { return BOOL_FALSE; } sleep( 1 ); /* to allow main thread to begin dialog */ mlog( MLOG_NORMAL | MLOG_BARE, "" ); /* to block until main thread dialog complete */ sleep( 1 ); /* to allow main thread to request children die */ if ( cldmgr_stop_requested( )) { return BOOL_FALSE; } mlog( MLOG_DEBUG, "retrying media erase dialog\n" ); goto retry; } return responseix == doix; } static void Media_prompt_label_cb( void *uctxp, dlog_pcbp_t pcb, void *pctxp ) { drive_t *drivep = ( drive_t * )uctxp; /* query: ask for a label */ ( * pcb )( pctxp, "please enter label for media in " "drive %u", drivep->d_index ); } static char * Media_prompt_label( drive_t *drivep, char *bufp, size_t bufsz ) { fold_t fold; char *preamblestr[ PREAMBLEMAX ]; size_t preamblecnt; char *ackstr[ ACKMAX ]; size_t ackcnt; char *postamblestr[ POSTAMBLEMAX ]; size_t postamblecnt; const ix_t timeoutix = 1; const ix_t abortix = 2; const ix_t sigintix = 3; const ix_t okix = 4; ix_t responseix; retry: preamblecnt = 0; fold_init( fold, "media label dialog", '=' ); preamblestr[ preamblecnt++ ] = "\n"; preamblestr[ preamblecnt++ ] = fold; preamblestr[ preamblecnt++ ] = "\n\n"; assert( preamblecnt <= PREAMBLEMAX ); dlog_begin( preamblestr, preamblecnt ); responseix = dlog_string_query( Media_prompt_label_cb, ( void * )drivep, bufp, bufsz, DLOG_TIMEOUT, timeoutix,/* timeout ix */ sigintix, /* sigint ix */ abortix, /* sighup ix */ abortix, /* sigquit ix */ okix ); /* ok ix */ ackcnt = 0; if ( responseix == okix ) { ackstr[ ackcnt++ ] = "media label entered: \""; ackstr[ ackcnt++ ] = bufp; ackstr[ ackcnt++ ] = "\"\n"; } else if ( responseix == timeoutix ) { ackstr[ ackcnt++ ] = "timeout: media label left blank\n"; } else if ( responseix == sigintix ) { ackstr[ ackcnt++ ] = "keyboard interrupt\n"; } else { ackstr[ ackcnt++ ] = "abort\n"; } assert( ackcnt <= ACKMAX ); dlog_string_ack( ackstr, ackcnt ); postamblecnt = 0; fold_init( fold, "end dialog", '-' ); postamblestr[ postamblecnt++ ] = "\n"; postamblestr[ postamblecnt++ ] = fold; postamblestr[ postamblecnt++ ] = "\n\n"; assert( postamblecnt <= POSTAMBLEMAX ); dlog_end( postamblestr, postamblecnt ); if ( responseix == sigintix ) { if ( cldmgr_stop_requested( )) { return 0; } sleep( 1 ); /* to allow main thread to begin dialog */ mlog( MLOG_NORMAL | MLOG_BARE, "" ); /* to block until main thread dialog complete */ sleep( 1 ); /* to allow main thread to request children die */ if ( cldmgr_stop_requested( )) { return 0; } mlog( MLOG_DEBUG, "retrying media label dialog\n" ); goto retry; } if ( responseix == okix ) { return bufp; } else { return 0; } } static void set_mcflag( ix_t thrdix ) { lock( ); sc_mcflag[ thrdix ] = BOOL_TRUE; content_media_change_needed = BOOL_TRUE; unlock( ); } static void clr_mcflag( ix_t thrdix ) { lock( ); sc_mcflag[ thrdix ] = BOOL_FALSE; for ( thrdix = 0 ; thrdix < drivecnt ; thrdix++ ) { if ( sc_mcflag[ thrdix ] ) { unlock( ); return; } } content_media_change_needed = BOOL_FALSE; unlock( ); } static bool_t check_complete_flags( void ) { ix_t strmix; bool_t completepr = BOOL_TRUE; for ( strmix = 0 ; strmix < drivecnt ; strmix++ ) { context_t *contextp = &sc_contextp[ strmix ]; if ( ! contextp->cc_completepr ) { completepr = BOOL_FALSE; break; } } return completepr; } extern bool_t is_quota_file(ino_t ino) { int i; for(i = 0; i < (sizeof(quotas) / sizeof(quotas[0])); i++) { if (quotas[i].savequotas && ino == quotas[i].quotaino) return BOOL_TRUE; } return BOOL_FALSE; } #define REPQUOTA "xfs_quota" static bool_t save_quotas( char *mntpnt, quota_info_t *quotainfo ) { int sts = 0; char buf[1024] = ""; int fd; char tmp; struct stat statb; mlog( MLOG_VERBOSE, _( "saving %s information for: %s\n"), quotainfo->desc, mntpnt ); if( unlink( quotainfo->quotapath ) == 0 ) { mlog( MLOG_WARNING, _("overwriting: %s\n"), quotainfo->quotapath); } else { if( errno != ENOENT ) { mlog( MLOG_ERROR, _( "unable to remove %s: %s\n"), quotainfo->quotapath, strerror( errno )); return BOOL_FALSE; } } sprintf( buf, "%s -x -c 'dump %s %s' %s 2> /dev/null", REPQUOTA, quotainfo->repquotaargs, quotainfo->quotapath, mntpnt ); mlog( MLOG_NITTY, "saving quotas: %s\n", buf ); sts = system( buf ); if( sts != 0 ) { mlog( MLOG_ERROR, _( "%s failed with exit status: %d\n"), REPQUOTA, sts == -1 ? -1 : WEXITSTATUS(sts)); return BOOL_FALSE; } if((fd = open( quotainfo->quotapath, O_RDONLY|O_DSYNC)) < 0) { mlog( MLOG_ERROR, _( "open failed %s: %s\n"), quotainfo->quotapath, strerror( errno )); return BOOL_FALSE; } if(fstat(fd, &statb) < 0) { mlog( MLOG_ERROR, _( "stat failed %s: %s\n"), quotainfo->quotapath, strerror( errno )); close(fd); return BOOL_FALSE; } quotainfo->quotaino = statb.st_ino; /* open and read dump file to ensure it is in the dump */ read(fd, &tmp, 1); close(fd); return BOOL_TRUE; } static int getxfsqstat(char *fsname) { fs_quota_stat_t qstat; /* * See if quotas is on. If not, nada. */ memset(&qstat, 0, sizeof(fs_quota_stat_t)); if (quotactl(QCMD(Q_XGETQSTAT, 0), fsname, 0, (caddr_t)&qstat) < 0) { return (-1); } return ((int)qstat.qs_flags); } xfsdump-3.1.6+nmu1/dump/var.c0000644000000000000000000000710212620476160012656 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include "config.h" #include "types.h" #include "fs.h" #include "openutil.h" #include "mlog.h" #include "global.h" #include "inventory.h" static void var_skip_recurse( char *, void ( * )( xfs_ino_t )); static int var_create_component( char * ); void var_create( void ) { char path[PATH_MAX]; char *p; p = strcpy( path, XFSDUMP_DIRPATH ); mlog( MLOG_DEBUG, "creating directory %s\n", path ); do { p++; if ( *p == '/' ) { *p = '\0'; if ( ! var_create_component( path ) ) return; *p = '/'; } } while ( *p ); ( void ) var_create_component( path ); } static int var_create_component( char *path ) { int rval = mkdir( path, 0755 ); if ( rval && errno != EEXIST ) { mlog( MLOG_NORMAL, _("unable to create %s: %s\n"), path, strerror( errno )); return 0; } if ( rval == 0 ) { rval = chown( path, 0, 0 ); if ( rval ) { mlog( MLOG_NORMAL, _("unable to chown %s: %s\n"), path, strerror( errno )); } } return 1; } void var_skip( uuid_t *dumped_fsidp, void ( *cb )( xfs_ino_t ino )) { uuid_t fsid; int rval; /* see if the fs uuid's match */ rval = fs_getid( XFSDUMP_DIRPATH, &fsid ); if ( rval ) { #ifdef HIDDEN /* NOTE: this will happen for non-XFS file systems */ /* and is expected, so no msg */ mlog( MLOG_NORMAL, _( "unable to determine uuid of fs containing %s: " "%s\n"), XFSDUMP_DIRPATH, strerror( errno )); #endif return; } if ( uuid_compare( *dumped_fsidp, fsid ) != 0) { return; } /* traverse the xfsdump directory, getting inode numbers of it * and all of its children, and reporting those to the callback. */ var_skip_recurse( XFSDUMP_DIRPATH, cb ); } static void var_skip_recurse( char *base, void ( *cb )( xfs_ino_t ino )) { struct stat64 statbuf; DIR *dirp; struct dirent *direntp; int rval; rval = lstat64( base, &statbuf ); if ( rval ) { mlog( MLOG_NORMAL, _( "unable to get status of %s: %s\n"), base, strerror( errno )); return; } mlog( MLOG_DEBUG, "excluding %s from dump\n", base ); ( * cb )( statbuf.st_ino ); if ( ( statbuf.st_mode & S_IFMT ) != S_IFDIR ) { return; } dirp = opendir( base ); if ( ! dirp ) { mlog( MLOG_NORMAL, _( "unable to open directory %s\n"), base ); return; } while ( ( direntp = readdir( dirp )) != NULL ) { char *path; /* skip "." and ".." */ if ( *( direntp->d_name + 0 ) == '.' && ( *( direntp->d_name + 1 ) == 0 || ( *( direntp->d_name + 1 ) == '.' && *( direntp->d_name + 2 ) == 0 ))) { continue; } path = open_pathalloc( base, direntp->d_name, 0 ); var_skip_recurse( path, cb ); free( ( void * )path ); } closedir( dirp ); } xfsdump-3.1.6+nmu1/dump/Makefile0000644000000000000000000000334512643556443013377 0ustar # # Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = .. include $(TOPDIR)/include/builddefs COMMINCL = \ arch_xlate.h \ cldmgr.h \ content.h \ content_common.h \ content_inode.h \ dlog.h \ drive.h \ exit.h \ fs.h \ getdents.h \ global.h \ hsmapi.h \ lock.h \ media.h \ mlog.h \ openutil.h \ path.h \ qlock.h \ ring.h \ stream.h \ timeutil.h \ ts_mtio.h \ types.h \ util.h \ rec_hdr.h INVINCL = \ inventory.h \ inv_priv.h INVCOMMON = \ inv_api.c \ inv_core.c \ inv_files.c \ inv_fstab.c \ inv_idx.c \ inv_mgr.c \ inv_stobj.c COMMON = \ arch_xlate.c \ cldmgr.c \ content_common.c \ dlog.c \ drive.c \ drive_scsitape.c \ drive_simple.c \ drive_minrmt.c \ fs.c \ getdents.c \ global.c \ hsmapi.c \ lock.c \ main.c \ mlog.c \ openutil.c \ qlock.c \ path.c \ ring.c \ stream.c \ timeutil.c \ util.c LOCALS = \ content.c \ inomap.c \ var.c LOCALINCL = \ getopt.h \ inomap.h \ var.h LTCOMMAND = xfsdump CFILES = $(LOCALS) LCFILES = $(COMMON) $(INVCOMMON) HFILES = $(LOCALINCL) LHFILES = $(COMMINCL) $(INVINCL) LINKS = $(COMMINCL) $(COMMON) $(INVINCL) $(INVCOMMON) LDIRT = $(LINKS) LLDLIBS = $(LIBUUID) $(LIBHANDLE) $(LIBATTR) $(LIBRMT) $(LIBPTHREAD) LTDEPENDENCIES = $(LIBRMT) LCFLAGS = -DDUMP default: depend $(LTCOMMAND) include $(BUILDRULES) install: default $(INSTALL) -m 755 -d $(PKG_ROOT_SBIN_DIR) $(LTINSTALL) -m 755 $(LTCOMMAND) $(PKG_ROOT_SBIN_DIR) $(INSTALL) -m 755 -d $(PKG_SBIN_DIR) install-dev: .dep: $(COMMINCL) $(COMMON) $(INVINCL) $(INVCOMMON) $(COMMINCL) $(COMMON): @echo " [LN] $@" $(Q)$(RM) $@; $(LN_S) ../common/$@ $@ $(INVINCL) $(INVCOMMON): @echo " [LN] $@" $(Q)$(RM) $@; $(LN_S) ../inventory/$@ $@ -include .dep xfsdump-3.1.6+nmu1/dump/getopt.h0000644000000000000000000000757712607344125013415 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GETOPT_H #define GETOPT_H /* getopt.h common getopt command string * * several modules parse the command line looking for arguments specific to * that module. Unfortunately, each of the getopt(3) calls needs the * complete command string, to know how to parse. This file's purpose is * to contain that command string. It also abstracts the option letters, * facilitating easy changes. */ #define GETOPT_CMDSTRING "ab:c:d:ef:hl:mop:qs:t:v:z:AB:CDEFG:H:I:JKL:M:NO:PRSTUVWY:" #define GETOPT_DUMPASOFFLINE 'a' /* dump DMF dualstate files as offline */ #define GETOPT_BLOCKSIZE 'b' /* blocksize for rmt */ #define GETOPT_ALERTPROG 'c' /* Media Change Alert prog(content.c) */ #define GETOPT_FILESZ 'd' /* Media file size to use in Mb */ #define GETOPT_EXCLUDEFILES 'e' /* allow files to be excluded */ #define GETOPT_DUMPDEST 'f' /* dump dest. file (drive.c) */ /* 'g' */ #define GETOPT_HELP 'h' /* display version and usage */ /* 'i' */ /* 'j' */ /* 'k' */ #define GETOPT_LEVEL 'l' /* dump level (content_inode.c) */ #define GETOPT_MINRMT 'm' /* use minimal rmt protocol */ /* 'n' */ #define GETOPT_OVERWRITE 'o' /* overwrite data on tape */ #define GETOPT_PROGRESS 'p' /* interval between progress reports */ #define GETOPT_QIC 'q' /* option to tell dump it's a QIC tape */ /* 'r' */ #define GETOPT_SUBTREE 's' /* subtree dump (content_inode.c) */ #define GETOPT_DUMPTIME 't' /* use mtime of file as dump time */ /* 'u' */ #define GETOPT_VERBOSITY 'v' /* verbosity level (0 to 4 ) */ /* 'w' */ /* 'x' used in irix for xvm snapshot */ /* 'y' */ #define GETOPT_MAXDUMPFILESIZE 'z' /* prune files over specified size */ #define GETOPT_NOEXTATTR 'A' /* do not dump ext. file attributes */ #define GETOPT_BASED 'B' /* specify session to base increment */ #define GETOPT_RECCHKSUM 'C' /* use record checksums */ #define GETOPT_NOUNCHANGEDDIRS 'D' /* skip unchanged directories */ #define GETOPT_ERASE 'E' /* pre-erase media */ #define GETOPT_FORCE 'F' /* don't prompt (getopt.c) */ #define GETOPT_MINSTACKSZ 'G' /* minimum stack size (bytes) */ #define GETOPT_MAXSTACKSZ 'H' /* maximum stack size (bytes) */ #define GETOPT_INVPRINT 'I' /* just display the inventory */ #define GETOPT_NOINVUPDATE 'J' /* do not update the dump inventory */ #define GETOPT_FMT2COMPAT 'K' /* use dump format 2 for compat with old restore */ #define GETOPT_DUMPLABEL 'L' /* dump session label (global.c) */ #define GETOPT_MEDIALABEL 'M' /* media object label (media.c) */ #define GETOPT_TIMESTAMP 'N' /* show timestamps in log msgs */ #define GETOPT_OPTFILE 'O' /* specifycmd line options file */ #define GETOPT_RINGPIN 'P' /* pin down I/O buffer ring */ /* 'Q' */ #define GETOPT_RESUME 'R' /* resume intr dump (content_inode.c) */ #define GETOPT_SINGLEMFILE 'S' /* obsolete - now the default */ #define GETOPT_NOTIMEOUTS 'T' /* don't timeout dialogs */ #define GETOPT_UNLOAD 'U' /* unload media when change needed */ #define GETOPT_SHOWLOGSS 'V' /* show subsystem of log messages */ #define GETOPT_SHOWLOGLEVEL 'W' /* show level of log messages */ /* 'X' */ #define GETOPT_RINGLEN 'Y' /* specify I/O buffer ring length */ /* 'Z' used on irix for miniroot */ #endif /* GETOPT_H */ xfsdump-3.1.6+nmu1/dump/var.h0000644000000000000000000000166012607344125012666 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef VAR_H #define VAR_H /* var.[ch] - abstraction dealing with /var/[lib/]xfsdump/ */ extern void var_create( void ); extern void var_skip( uuid_t *dumped_fsidp, void ( *cb )( xfs_ino_t ino )); #endif /* VAR_H */ xfsdump-3.1.6+nmu1/dump/inomap.c0000644000000000000000000012242212620476160013354 0ustar /* * Copyright (c) 2000-2002 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "types.h" #include "util.h" #include "mlog.h" #include "global.h" #include "drive.h" #include "media.h" #include "content.h" #include "content_inode.h" #include "hsmapi.h" #include "inomap.h" #include "arch_xlate.h" #include "exit.h" #include /* structure definitions used locally ****************************************/ #define BSTATBUFLEN pgsz /* length (in bstat_t's) of buf passed to bigstat_iter */ #define GETDENTBUFSZ pgsz /* size (in bytes) of buf passed to diriter (when not recursive) */ /* declarations of externally defined global symbols *************************/ extern bool_t preemptchk( int ); extern size_t pgsz; extern hsm_fs_ctxt_t *hsm_fs_ctxtp; extern uint64_t maxdumpfilesize; extern bool_t allowexcludefiles_pr; /* forward declarations of locally defined static functions ******************/ /* inomap construction callbacks */ static int cb_context( bool_t last, time32_t, bool_t, time32_t, size_t, drange_t *, startpt_t *, size_t, int, bool_t, bool_t *); static void cb_context_free( void ); static int cb_count_inogrp( void *, int, xfs_inogrp_t *); static int cb_add_inogrp( void *, int, xfs_inogrp_t * ); static int cb_add( void *, jdm_fshandle_t *, int, xfs_bstat_t * ); static bool_t cb_inoinresumerange( xfs_ino_t ); static bool_t cb_inoresumed( xfs_ino_t ); static void cb_accuminit_sz( void ); static void cb_spinit( void ); static int cb_startpt( void *, jdm_fshandle_t *, int, xfs_bstat_t * ); static int supprt_prune( void *, jdm_fshandle_t *, int, xfs_bstat_t *, char * ); static off64_t quantity2offset( jdm_fshandle_t *, xfs_bstat_t *, off64_t ); static off64_t estimate_dump_space( xfs_bstat_t * ); /* inomap primitives */ static int inomap_init( int igrpcnt ); static void inomap_add( void *, xfs_ino_t ino, gen_t gen, int ); static int inomap_set_state( void *, xfs_ino_t ino, int ); static void inomap_set_gen(void *, xfs_ino_t, gen_t ); /* subtree abstraction */ static int subtree_descend_cb( void *, jdm_fshandle_t *, int fsfd, xfs_bstat_t *, char * ); static int subtreelist_parse_cb( void *, jdm_fshandle_t *, int fsfd, xfs_bstat_t *, char * ); static int subtreelist_parse( jdm_fshandle_t *, int, xfs_bstat_t *, char *[], ix_t ); /* definition of locally defined global variables ****************************/ /* definition of locally defined static variables *****************************/ static ix_t *inomap_statphasep; static ix_t *inomap_statpassp; static size64_t *inomap_statdonep; static uint64_t inomap_exclude_filesize = 0; static uint64_t inomap_exclude_skipattr = 0; /* definition of locally defined global functions ****************************/ /* inomap_build - build an in-core image of the inode map for the * specified file system. identify startpoints in the non-dir inodes, * such that the total dump media required is divided into startptcnt segments. */ /* ARGSUSED */ bool_t inomap_build( jdm_fshandle_t *fshandlep, int fsfd, xfs_bstat_t *rootstatp, bool_t last, time32_t lasttime, bool_t resume, time32_t resumetime, size_t resumerangecnt, drange_t *resumerangep, char *subtreebuf[], ix_t subtreecnt, bool_t skip_unchanged_dirs, startpt_t *startptp, size_t startptcnt, ix_t *statphasep, ix_t *statpassp, size64_t statcnt, size64_t *statdonep ) { xfs_bstat_t *bstatbufp; size_t bstatbuflen; bool_t pruneneeded = BOOL_FALSE; int igrpcnt = 0; int stat; int rval; /* do a sync so that bulkstat will pick up inode changes * that are currently in the inode cache. this is necessary * for incremental dumps in order to have the dump time * accurately reflect what inodes were included in this dump. * (PV 881455) */ sync(); /* copy stat ptrs */ inomap_statphasep = statphasep; inomap_statpassp = statpassp; inomap_statdonep = statdonep; /* allocate a bulkstat buf */ bstatbuflen = BSTATBUFLEN; bstatbufp = ( xfs_bstat_t * )memalign( pgsz, bstatbuflen * sizeof( xfs_bstat_t )); assert( bstatbufp ); /* count the number of inode groups, which will serve as a * starting point for the size of the inomap. */ rval = inogrp_iter( fsfd, cb_count_inogrp, (void *)&igrpcnt, &stat ); if ( rval || stat ) { free( ( void * )bstatbufp ); return BOOL_FALSE; } /* initialize the callback context */ rval = cb_context( last, lasttime, resume, resumetime, resumerangecnt, resumerangep, startptp, startptcnt, igrpcnt, skip_unchanged_dirs, &pruneneeded ); if ( rval ) { free( ( void * )bstatbufp ); return BOOL_FALSE; } /* the inode map requires that inodes are added in increasing * ino order. in the case of a subtree dump, inodes would be * added in whatever order they were discovered when walking the * subtrees. so pre-populate the inomap with all the inode groups * in this filesystem. each inode will be marked unused until its * correct state is set in cb_add. */ rval = inogrp_iter( fsfd, cb_add_inogrp, NULL, &stat ); if ( rval || stat ) { cb_context_free(); free( ( void * )bstatbufp ); return BOOL_FALSE; } /* construct the ino map, based on the last dump time, resumed * dump info, and subtree list. place all unchanged directories * in the "needed for children" state (MAP_DIR_SUPPRT). these will be * dumped even though they have not changed. a later pass will move * some of these to "not dumped", such that only those necessary * to represent the minimal tree containing only changes will remain. * for subtree dumps, recurse over the specified subtrees calling * the inomap constructor (cb_add). otherwise, if dumping the entire * filesystem, use the bigstat iterator to add inos to the inomap. * set a flag if any ino not put in a dump state. This will be used * to decide if any pruning can be done. */ mlog( MLOG_VERBOSE | MLOG_INOMAP, _( "ino map phase 1: " "constructing initial dump list\n") ); *inomap_statdonep = 0; *inomap_statphasep = 1; stat = 0; cb_accuminit_sz( ); if ( subtreecnt ) { rval = subtreelist_parse( fshandlep, fsfd, rootstatp, subtreebuf, subtreecnt ); } else { rval = bigstat_iter( fshandlep, fsfd, BIGSTAT_ITER_ALL, ( xfs_ino_t )0, cb_add, NULL, NULL, NULL, &stat, preemptchk, bstatbufp, bstatbuflen ); } *inomap_statphasep = 0; if ( rval || preemptchk( PREEMPT_FULL )) { cb_context_free(); free( ( void * )bstatbufp ); return BOOL_FALSE; } if ( inomap_exclude_filesize > 0 ) { mlog( MLOG_NOTE | MLOG_VERBOSE, _( "pruned %llu files: maximum size exceeded\n"), inomap_exclude_filesize ); } if ( inomap_exclude_skipattr > 0 ) { mlog( MLOG_NOTE | MLOG_VERBOSE, _( "pruned %llu files: skip attribute set\n"), inomap_exclude_skipattr ); } /* prune directories unchanged since the last dump and containing * no children needing dumping. */ if ( pruneneeded ) { bool_t rootdump = BOOL_FALSE; mlog( MLOG_VERBOSE | MLOG_INOMAP, _( "ino map phase 2: " "pruning unneeded subtrees\n") ); *inomap_statdonep = 0; *inomap_statpassp = 0; *inomap_statphasep = 2; (void) supprt_prune( &rootdump, fshandlep, fsfd, rootstatp, NULL ); *inomap_statphasep = 0; if ( preemptchk( PREEMPT_FULL )) { cb_context_free(); free( ( void * )bstatbufp ); return BOOL_FALSE; } } else { mlog( MLOG_VERBOSE | MLOG_INOMAP, _( "ino map phase 2: " "skipping (no pruning necessary)\n") ); } /* initialize the callback context for startpoint calculation */ cb_spinit( ); /* identify dump stream startpoints */ if ( startptcnt > 1 ) { mlog( MLOG_VERBOSE | MLOG_INOMAP, _( "ino map phase 3: " "identifying stream starting points\n") ); } else { mlog( MLOG_VERBOSE | MLOG_INOMAP, _( "ino map phase 3: " "skipping (only one dump stream)\n") ); } stat = 0; *inomap_statdonep = 0; *inomap_statphasep = 3; rval = bigstat_iter( fshandlep, fsfd, BIGSTAT_ITER_NONDIR, ( xfs_ino_t )0, cb_startpt, NULL, inomap_next_nondir, inomap_alloc_context(), &stat, preemptchk, bstatbufp, bstatbuflen ); *inomap_statphasep = 0; if ( rval ) { cb_context_free(); free( ( void * )bstatbufp ); return BOOL_FALSE; } if ( startptcnt > 1 ) { ix_t startptix; for ( startptix = 0 ; startptix < startptcnt ; startptix++ ) { startpt_t *p; startpt_t *ep; p = &startptp[ startptix ]; if ( startptix == startptcnt - 1 ) { ep = 0; } else { ep = &startptp[ startptix + 1 ]; } assert( ! p->sp_flags ); mlog( MLOG_VERBOSE | MLOG_INOMAP, _("stream %u: ino %llu offset %lld to "), startptix, p->sp_ino, p->sp_offset ); if ( ! ep ) { mlog( MLOG_VERBOSE | MLOG_BARE | MLOG_INOMAP, _("end\n") ); } else { mlog( MLOG_VERBOSE | MLOG_BARE | MLOG_INOMAP, _("ino %llu offset %lld\n"), ep->sp_ino, ep->sp_offset ); } } } cb_context_free(); free( ( void * )bstatbufp ); mlog( MLOG_VERBOSE | MLOG_INOMAP, _( "ino map construction complete\n") ); return BOOL_TRUE; } void inomap_skip( xfs_ino_t ino ) { int oldstate; oldstate = inomap_get_state( NULL, ino ); if ( oldstate == MAP_NDR_CHANGE) { inomap_set_state( NULL, ino, MAP_NDR_NOCHNG ); } if ( oldstate == MAP_DIR_CHANGE || oldstate == MAP_DIR_SUPPRT ) { inomap_set_state( NULL, ino, MAP_DIR_NOCHNG ); } } /* definition of locally defined static functions ****************************/ /* callback context and operators - inomap_build makes extensive use * of iterators. below are the callbacks given to these iterators. */ static bool_t cb_last; /* set by cb_context() */ static time32_t cb_lasttime; /* set by cb_context() */ static bool_t cb_resume; /* set by cb_context() */ static time32_t cb_resumetime; /* set by cb_context() */ static size_t cb_resumerangecnt;/* set by cb_context() */ static drange_t *cb_resumerangep;/* set by cb_context() */ static void *cb_inomap_contextp;/* set by cb_context() */ static startpt_t *cb_startptp; /* set by cb_context() */ static size_t cb_startptcnt; /* set by cb_context() */ static size_t cb_startptix; /* set by cb_spinit(), incr. by cb_startpt */ static off64_t cb_datasz; /* set by cb_context() */ static off64_t cb_hdrsz; /* set by cb_context() */ static off64_t cb_accum; /* set by cb_context(), cb_spinit() */ static off64_t cb_incr; /* set by cb_spinit(), used by cb_startpt() */ static off64_t cb_target; /* set by cb_spinit(), used by cb_startpt() */ static off64_t cb_dircnt; /* number of dirs CHANGED or PRUNE */ static off64_t cb_nondircnt; /* number of non-dirs CHANGED */ static bool_t *cb_pruneneededp; /* set by cb_context() */ static bool_t cb_skip_unchanged_dirs; /* set by cb_context() */ /* cb_context - initializes the call back context for the add and prune * phases of inomap_build(). */ static int cb_context( bool_t last, time32_t lasttime, bool_t resume, time32_t resumetime, size_t resumerangecnt, drange_t *resumerangep, startpt_t *startptp, size_t startptcnt, int igrpcnt, bool_t skip_unchanged_dirs, bool_t *pruneneededp ) { cb_last = last; cb_lasttime = lasttime; cb_resume = resume; cb_resumetime = resumetime; cb_resumerangecnt = resumerangecnt; cb_resumerangep = resumerangep; cb_startptp = startptp; cb_startptcnt = startptcnt; cb_accum = 0; cb_dircnt = 0; cb_nondircnt = 0; cb_pruneneededp = pruneneededp; cb_skip_unchanged_dirs = skip_unchanged_dirs; if (inomap_init( igrpcnt )) return -1; cb_inomap_contextp = inomap_alloc_context(); if (!cb_inomap_contextp) return -1; return 0; } static void cb_context_free( void ) { inomap_free_context( cb_inomap_contextp ); } static int cb_count_inogrp( void *arg1, int fsfd, xfs_inogrp_t *inogrp ) { int *count = (int *)arg1; (*count)++; return 0; } /* cb_add - called for all inodes in the file system. checks * mod and create times to decide if should be dumped. sets all * unmodified directories to be dumped for supprt. notes if any * files or directories have not been modified. */ /* ARGSUSED */ static int cb_add( void *arg1, jdm_fshandle_t *fshandlep, int fsfd, xfs_bstat_t *statp ) { register time32_t mtime = statp->bs_mtime.tv_sec; register time32_t ctime = statp->bs_ctime.tv_sec; register time32_t ltime = max( mtime, ctime ); register mode_t mode = statp->bs_mode & S_IFMT; xfs_off_t estimated_size = 0; xfs_ino_t ino = statp->bs_ino; bool_t changed; bool_t resumed; ( *inomap_statdonep )++; /* skip if no links */ if ( statp->bs_nlink == 0 ) { return 0; } /* if no portion of this ino is in the resume range, * then only dump it if it has changed since the interrupted * dump. * * otherwise, if some or all of this ino is in the resume range, * and has changed since the base dump upon which the original * increment was based, dump it if it has changed since that * original base dump. */ if ( cb_resume && ! cb_inoinresumerange( ino )) { if ( ltime >= cb_resumetime ) { changed = BOOL_TRUE; } else { changed = BOOL_FALSE; } } else if ( cb_last ) { if ( ltime >= cb_lasttime ) { changed = BOOL_TRUE; } else { changed = BOOL_FALSE; } } else { changed = BOOL_TRUE; } /* this is redundant: make sure any ino partially dumped * is completed. */ if ( cb_resume && cb_inoresumed( ino )) { resumed = BOOL_TRUE; } else { resumed = BOOL_FALSE; } if ( changed ) { if ( mode == S_IFDIR ) { inomap_add( cb_inomap_contextp, ino, (gen_t)statp->bs_gen, MAP_DIR_CHANGE ); cb_dircnt++; } else { estimated_size = estimate_dump_space( statp ); /* skip if size is greater than prune size. quota * files are exempt from the check. */ if ( maxdumpfilesize > 0 && estimated_size > maxdumpfilesize && !is_quota_file(statp->bs_ino) ) { mlog( MLOG_DEBUG | MLOG_EXCLFILES, "pruned ino %llu, owner %u, estimated size %llu: maximum size exceeded\n", statp->bs_ino, statp->bs_uid, estimated_size ); inomap_add( cb_inomap_contextp, ino, (gen_t)statp->bs_gen, MAP_NDR_NOCHNG ); inomap_exclude_filesize++; return 0; } if (allowexcludefiles_pr && statp->bs_xflags & XFS_XFLAG_NODUMP) { mlog( MLOG_DEBUG | MLOG_EXCLFILES, "pruned ino %llu, owner %u, estimated size %llu: skip flag set\n", statp->bs_ino, statp->bs_uid, estimated_size ); inomap_add( cb_inomap_contextp, ino, (gen_t)statp->bs_gen, MAP_NDR_NOCHNG ); inomap_exclude_skipattr++; return 0; } inomap_add( cb_inomap_contextp, ino, (gen_t)statp->bs_gen, MAP_NDR_CHANGE ); cb_nondircnt++; cb_datasz += estimated_size; cb_hdrsz += ( EXTENTHDR_SZ * (statp->bs_extents + 1) ); } } else if ( resumed ) { assert( mode != S_IFDIR ); assert( changed ); } else { if ( mode == S_IFDIR ) { if ( cb_skip_unchanged_dirs ) { inomap_add( cb_inomap_contextp, ino, (gen_t)statp->bs_gen, MAP_DIR_NOCHNG ); } else { *cb_pruneneededp = BOOL_TRUE; inomap_add( cb_inomap_contextp, ino, (gen_t)statp->bs_gen, MAP_DIR_SUPPRT ); cb_dircnt++; } } else { inomap_add( cb_inomap_contextp, ino, (gen_t)statp->bs_gen, MAP_NDR_NOCHNG ); } } return 0; } static bool_t cb_inoinresumerange( xfs_ino_t ino ) { register size_t streamix; for ( streamix = 0 ; streamix < cb_resumerangecnt ; streamix++ ) { register drange_t *rp = &cb_resumerangep[ streamix ]; if ( ! ( rp->dr_begin.sp_flags & STARTPT_FLAGS_END ) && ino >= rp->dr_begin.sp_ino && ( ( rp->dr_end.sp_flags & STARTPT_FLAGS_END ) || ino < rp->dr_end.sp_ino || ( ino == rp->dr_end.sp_ino && rp->dr_end.sp_offset != 0 ))) { return BOOL_TRUE; } } return BOOL_FALSE; } static bool_t cb_inoresumed( xfs_ino_t ino ) { size_t streamix; for ( streamix = 0 ; streamix < cb_resumerangecnt ; streamix++ ) { drange_t *rp = &cb_resumerangep[ streamix ]; if ( ! ( rp->dr_begin.sp_flags & STARTPT_FLAGS_END ) && ino == rp->dr_begin.sp_ino && rp->dr_begin.sp_offset != 0 ) { return BOOL_TRUE; } } return BOOL_FALSE; } /* supprt_prune - does supprt directory entry pruning. * recurses downward looking for modified inodes, & clears supprt * (-> nochng) on the way back up after examining all descendents. */ /* ARGSUSED */ static bool_t /* false, used as diriter callback */ supprt_prune( void *arg1, /* ancestors marked as changed? */ jdm_fshandle_t *fshandlep, int fsfd, xfs_bstat_t *statp, char *name ) { static bool_t cbrval = BOOL_FALSE; int state; if ( ( statp->bs_mode & S_IFMT ) == S_IFDIR ) { bool_t changed_below = BOOL_FALSE; state = inomap_get_state( cb_inomap_contextp, statp->bs_ino ); if ( state != MAP_DIR_CHANGE && state != MAP_DIR_NOCHNG && state != MAP_DIR_SUPPRT) { /* * if file is now a dir then it has * certainly changed. */ state = MAP_DIR_CHANGE; inomap_set_state( cb_inomap_contextp, statp->bs_ino, state ); } ( void )diriter( fshandlep, fsfd, statp, supprt_prune, (void *)&changed_below, &cbrval, NULL, 0 ); if ( state == MAP_DIR_SUPPRT ) { if ( changed_below == BOOL_FALSE ) { inomap_set_state( cb_inomap_contextp, statp->bs_ino, MAP_DIR_NOCHNG ); cb_dircnt--; /* dump size just changed! */ } else { /* Directory entries back up the hierarchy */ /* to be dumped - as either MAP_DIR_SUPPRT */ /* or as MAP_DIR_CHANGE in inode state map */ *( bool_t * )arg1 = BOOL_TRUE; } } else if ( state == MAP_DIR_CHANGE ) { /* Directory entries back up the hierarchy must get */ /* dumped - as either MAP_DIR_SUPPRT/MAP_DIR_CHANGE */ *( bool_t * )arg1 = BOOL_TRUE; } return cbrval; } if ( *(bool_t *)arg1 == BOOL_TRUE ) { /* shortcut, sibling changed */ return cbrval; } state = inomap_get_state( cb_inomap_contextp, statp->bs_ino ); if ( state != MAP_NDR_CHANGE && state != MAP_NDR_NOCHNG ) { /* * if dir is now a file then it has * certainly changed. */ state = MAP_NDR_CHANGE; inomap_set_state( cb_inomap_contextp, statp->bs_ino, state ); } if ( state == MAP_NDR_CHANGE ) { /* Directory entries back up the hierarchy must get */ /* dumped - as either MAP_DIR_SUPPRT/MAP_DIR_CHANGE */ *( bool_t * )arg1 = BOOL_TRUE; } return cbrval; } static void cb_accuminit_sz( void ) { cb_datasz = 0; cb_hdrsz = 0; } /* cb_spinit - initializes context for the startpoint calculation phase of * inomap_build. cb_startptix is the index of the next startpoint to * record. cb_incr is the dump space distance between each startpoint. * cb_target is the target accum value for the next startpoint. * cb_accum accumulates the dump space. */ static void cb_spinit( void ) { cb_startptix = 0; cb_incr = (cb_datasz + cb_hdrsz) / ( off64_t )cb_startptcnt; cb_target = 0; /* so first ino will push us over the edge */ cb_accum = 0; } /* cb_startpt - called for each non-directory inode. accumulates the * require dump space, and notes startpoints. encodes a heuristic for * selecting startpoints. decides for each file whether to include it * in the current stream, start a new stream beginning with that file, * or split the file between the old and new streams. in the case of * a split decision, always split at a BBSIZE boundary. */ #define TOO_SHY 1000000 /* max accept. accum short of target */ #define TOO_BOLD 1000000 /* max accept. accum beyond target */ typedef enum { HOLD, /* don't change */ BUMP, /* set a new start point and put this file after it */ SPLIT, /* set a new start point and split this file across it */ YELL /* impossible condition; complain */ } action_t; /* ARGSUSED */ static int cb_startpt( void *arg1, jdm_fshandle_t *fshandlep, int fsfd, xfs_bstat_t *statp ) { register int state; off64_t estimate; off64_t old_accum = cb_accum; off64_t qty; /* amount of a SPLIT file to skip */ action_t action; ( *inomap_statdonep )++; /* skip if no links */ if ( statp->bs_nlink == 0 ) { return 0; } /* skip if not in inomap or not a non-dir */ state = inomap_get_state( cb_inomap_contextp, statp->bs_ino ); if ( state != MAP_NDR_CHANGE ) { return 0; } assert( cb_startptix < cb_startptcnt ); estimate = estimate_dump_space( statp ); cb_accum += estimate + ( EXTENTHDR_SZ * (statp->bs_extents + 1) ); /* loop until no new start points found. loop is necessary * to handle the pathological case of a huge file so big it * spans several streams. */ action = ( action_t )HOLD; /* irrelevant, but demanded by lint */ do { /* decide what to do: hold, bump, or split. there are * 8 valid cases to consider: * 1) accum prior to this file is way too short of the * target, and accum incl. this file is also shy: HOLD; * 2) accum prior to this file is way too short of the * target, and accum incl. this file is close to but * still short of target: HOLD; * 3) accum prior to this file is way too short of the * target, and accum incl. this file is a little beyond * the target: HOLD; * 4) accum prior to this file is way too short of the * target, and accum incl. this file is way beyond * the target: SPLIT; * 5) accum prior to this file is close to target, and * accum incl. this file is still short of target: HOLD; * 6) accum prior to this file is close to target, and * accum incl. this file is a little beyond the target, * and excluding this file would be less short of target * than including it would be beyond the target: BUMP; * 7) accum prior to this file is close to target, and * accum incl. this file is a little beyond the target, * and including this file would be less beyond target * than excluding it would be short of target: HOLD; * 8) accum prior to this file is close to target, and * accum incl. this file is would be way beyond the * target: HOLD. */ if ( cb_target - old_accum >= TOO_SHY ) { if ( cb_target - cb_accum >= TOO_SHY ) { action = ( action_t )HOLD; } else if ( cb_accum <= cb_target ) { action = ( action_t )HOLD; } else if ( cb_accum - cb_target < TOO_BOLD ) { action = ( action_t )HOLD; } else { action = ( action_t )SPLIT; } } else { if ( cb_target - cb_accum >= TOO_SHY ) { action = ( action_t )YELL; } else if ( cb_accum < cb_target ) { action = ( action_t )HOLD; } else if ( cb_accum - cb_target < TOO_BOLD ) { if ( cb_accum - cb_target >= cb_target - old_accum ) { action = ( action_t )BUMP; } else { action = ( action_t )HOLD; } } else { action = ( action_t )BUMP; } } /* perform the action selected above */ switch ( action ) { case ( action_t )HOLD: break; case ( action_t )BUMP: cb_startptp->sp_ino = statp->bs_ino; cb_startptp->sp_offset = 0; cb_startptix++; cb_startptp++; cb_target += cb_incr; if ( cb_startptix == cb_startptcnt ) { return 1; /* done; abort the iteration */ } break; case ( action_t )SPLIT: cb_startptp->sp_ino = statp->bs_ino; qty = ( cb_target - old_accum ) & ~( off64_t )( BBSIZE - 1 ); cb_startptp->sp_offset = quantity2offset( fshandlep, statp, qty ); cb_startptix++; cb_startptp++; cb_target += cb_incr; if ( cb_startptix == cb_startptcnt ) { return 1; /* done; abort the iteration */ } break; default: assert( 0 ); return 1; } } while ( action == ( action_t )BUMP || action == ( action_t )SPLIT ); return 0; } /* map context and operators */ /* define structure for ino to gen mapping. */ struct i2gseg { uint64_t s_valid; gen_t s_gen[ INOPERSEG ]; }; typedef struct i2gseg i2gseg_t; typedef struct seg_addr { int hnkoff; int segoff; int inooff; } seg_addr_t; static struct inomap { hnk_t *hnkmap; int hnkmaplen; i2gseg_t *i2gmap; seg_addr_t lastseg; } inomap; static inline void SEG_SET_BITS( seg_t *segp, xfs_ino_t ino, int state ) { register xfs_ino_t relino; register uint64_t mask; register uint64_t clrmask; relino = ino - segp->base; mask = ( uint64_t )1 << relino; clrmask = ~mask; switch( state ) { case 0: segp->lobits &= clrmask; segp->mebits &= clrmask; segp->hibits &= clrmask; break; case 1: segp->lobits |= mask; segp->mebits &= clrmask; segp->hibits &= clrmask; break; case 2: segp->lobits &= clrmask; segp->mebits |= mask; segp->hibits &= clrmask; break; case 3: segp->lobits |= mask; segp->mebits |= mask; segp->hibits &= clrmask; break; case 4: segp->lobits &= clrmask; segp->mebits &= clrmask; segp->hibits |= mask; break; case 5: segp->lobits |= mask; segp->mebits &= clrmask; segp->hibits |= mask; break; case 6: segp->lobits &= clrmask; segp->mebits |= mask; segp->hibits |= mask; break; case 7: segp->lobits |= mask; segp->mebits |= mask; segp->hibits |= mask; break; } } static inline int SEG_GET_BITS( seg_t *segp, xfs_ino_t ino ) { int state; register xfs_ino_t relino; register uint64_t mask; relino = ino - segp->base; mask = ( uint64_t )1 << relino; if ( segp->lobits & mask ) { state = 1; } else { state = 0; } if ( segp->mebits & mask ) { state |= 2; } if ( segp->hibits & mask ) { state |= 4; } return state; } /* context for inomap construction - initialized by map_init */ static int inomap_init( int igrpcnt ) { assert( sizeof( hnk_t ) == HNKSZ ); /* lastseg must be initialized with -1 offsets since * no segments have been added yet */ inomap.lastseg.hnkoff = -1; inomap.lastseg.segoff = -1; inomap.hnkmaplen = (igrpcnt + SEGPERHNK - 1) / SEGPERHNK; inomap.hnkmap = (hnk_t *)malloc(inomap.hnkmaplen * HNKSZ); inomap.i2gmap = (i2gseg_t *) calloc( inomap.hnkmaplen * SEGPERHNK, sizeof(i2gseg_t) ); if (!inomap.hnkmap || !inomap.i2gmap) return -1; return 0; } uint64_t inomap_getsz( void ) { return (inomap.lastseg.hnkoff + 1) * HNKSZ; } static inline bool_t inomap_validaddr( seg_addr_t *addrp ) { int maxseg; if ( addrp->hnkoff < 0 || addrp->hnkoff > inomap.lastseg.hnkoff ) return BOOL_FALSE; maxseg = ( addrp->hnkoff == inomap.lastseg.hnkoff ) ? inomap.lastseg.segoff : SEGPERHNK - 1; if ( addrp->segoff < 0 || addrp->segoff > maxseg ) return BOOL_FALSE; return BOOL_TRUE; } static inline hnk_t * inomap_addr2hnk( seg_addr_t *addrp ) { return &inomap.hnkmap[addrp->hnkoff]; } static inline seg_t * inomap_addr2seg( seg_addr_t *addrp ) { hnk_t *hunkp = inomap_addr2hnk( addrp ); return &hunkp->seg[addrp->segoff]; } static inline int inomap_addr2segix( seg_addr_t *addrp ) { return ( addrp->hnkoff * SEGPERHNK ) + addrp->segoff; } static inline int inomap_lastseg( int hnkoff ) { if ( hnkoff == inomap.lastseg.hnkoff ) return inomap.lastseg.segoff; else return SEGPERHNK - 1; } /* called for every inode group in the filesystem in increasing inode * order. adds a new segment to the inomap and ino-to-gen map. */ static int cb_add_inogrp( void *arg1, int fsfd, xfs_inogrp_t *inogrp ) { hnk_t *hunk; seg_t *segp; seg_addr_t *lastsegp = &inomap.lastseg; /* if out of segments on the current hnk or this is the first segment */ lastsegp->segoff++; if (lastsegp->segoff == SEGPERHNK || lastsegp->segoff == 0) { lastsegp->hnkoff++; lastsegp->segoff = 0; if (lastsegp->hnkoff == inomap.hnkmaplen) { int numsegs; inomap.hnkmaplen++; inomap.hnkmap = (hnk_t *) realloc(inomap.hnkmap, inomap.hnkmaplen * HNKSZ); numsegs = inomap.hnkmaplen * SEGPERHNK; if (numsegs < 0) return -1; inomap.i2gmap = (i2gseg_t *) realloc(inomap.i2gmap, numsegs * sizeof(i2gseg_t)); if (!inomap.hnkmap || !inomap.i2gmap) return -1; /* zero the new portion of the i2gmap */ memset(&inomap.i2gmap[numsegs - SEGPERHNK], 0, SEGPERHNK * sizeof(i2gseg_t)); } memset(inomap_addr2hnk( lastsegp ), 0, HNKSZ); } hunk = inomap_addr2hnk( lastsegp ); hunk->maxino = inogrp->xi_startino + INOPERSEG - 1; segp = inomap_addr2seg( lastsegp ); segp->base = inogrp->xi_startino; return 0; } /* called for every ino to be added to the map. */ static void inomap_add( void *contextp, xfs_ino_t ino, gen_t gen, int state ) { inomap_set_state( contextp, ino, state ); inomap_set_gen( contextp, ino, gen ); } void * inomap_alloc_context( void ) { void *addr = calloc( 1, sizeof(seg_addr_t) ); if (!addr) { mlog( MLOG_NORMAL | MLOG_ERROR, _("failed to allocate inomap context: %s\n"), strerror(errno) ); } return addr; } void inomap_reset_context( void *p ) { memset( p, 0, sizeof(seg_addr_t) ); } void inomap_free_context( void *p ) { free( p ); } /* use binary search to find the hunk containing the given inode. * use the supplied addr as the starting point for the search. */ static bool_t inomap_find_hnk( seg_addr_t *addrp, xfs_ino_t ino ) { hnk_t *hunkp; int lower; int upper; lower = 0; upper = inomap.lastseg.hnkoff; while ( upper >= lower ) { hunkp = inomap_addr2hnk( addrp ); if ( hunkp->seg[0].base > ino ) { upper = addrp->hnkoff - 1; } else if ( hunkp->maxino < ino ) { lower = addrp->hnkoff + 1; } else { return BOOL_TRUE; } addrp->hnkoff = lower + ((upper - lower) / 2); addrp->segoff = 0; } return BOOL_FALSE; } /* use binary search to find the hunk containing the given * inode, and then binary search the hunk to find the correct * segment, if any. use the supplied addr as the starting * point for the search. */ static bool_t inomap_find_seg( seg_addr_t *addrp, xfs_ino_t ino ) { seg_t *segp; int lower; int upper; if ( !inomap_validaddr( addrp ) ) { inomap_reset_context( addrp ); } if ( !inomap_find_hnk( addrp, ino ) ) return BOOL_FALSE; /* find the correct segment */ lower = 0; upper = inomap_lastseg(addrp->hnkoff); while ( upper >= lower ) { segp = inomap_addr2seg( addrp ); if ( segp->base > ino ) { upper = addrp->segoff - 1; } else if ( segp->base + INOPERSEG <= ino ) { lower = addrp->segoff + 1; } else { return BOOL_TRUE; } addrp->segoff = lower + ((upper - lower) / 2); } return BOOL_FALSE; } static xfs_ino_t inomap_iter( void *contextp, int statemask ) { xfs_ino_t ino, endino; seg_t *segp; seg_addr_t *addrp = (seg_addr_t *)contextp; for ( ; addrp->hnkoff <= inomap.lastseg.hnkoff; addrp->hnkoff++, addrp->segoff = 0, addrp->inooff = 0 ) { for ( ; addrp->segoff <= inomap_lastseg(addrp->hnkoff); addrp->segoff++, addrp->inooff = 0 ) { segp = inomap_addr2seg( addrp ); ino = segp->base + addrp->inooff; endino = segp->base + INOPERSEG; for ( ; ino < endino ; ino++, addrp->inooff++ ) { int st; st = SEG_GET_BITS( segp, ino ); if ( statemask & ( 1 << st )) { addrp->inooff++; /* for next call */ return ino; } } } } return INO64MAX; } xfs_ino_t inomap_next_nondir(void *contextp, xfs_ino_t lastino) { int state = 1 << MAP_NDR_CHANGE; xfs_ino_t nextino; do { nextino = inomap_iter(contextp, state); } while (nextino <= lastino); return nextino; } xfs_ino_t inomap_next_dir(void *contextp, xfs_ino_t lastino) { int state = (1 << MAP_DIR_CHANGE) | (1 << MAP_DIR_SUPPRT); xfs_ino_t nextino; do { nextino = inomap_iter(contextp, state); } while (nextino <= lastino); return nextino; } static int inomap_set_state( void *contextp, xfs_ino_t ino, int state ) { int oldstate; seg_addr_t *addrp; seg_addr_t addr; seg_t *segp; addrp = contextp ? (seg_addr_t *)contextp : &addr; if ( !inomap_find_seg( addrp, ino ) ) return MAP_INO_UNUSED; segp = inomap_addr2seg( addrp ); oldstate = SEG_GET_BITS( segp, ino ); SEG_SET_BITS( segp, ino, state ); return oldstate; } int inomap_get_state( void *contextp, xfs_ino_t ino ) { seg_addr_t *addrp; seg_addr_t addr; seg_t *segp; addrp = contextp ? (seg_addr_t *)contextp : &addr; if ( !inomap_find_seg( addrp, ino ) ) return MAP_INO_UNUSED; segp = inomap_addr2seg( addrp ); return SEG_GET_BITS( segp, ino ); } static void inomap_set_gen(void *contextp, xfs_ino_t ino, gen_t gen) { seg_addr_t *addrp; seg_addr_t addr; seg_t *segp; i2gseg_t *i2gsegp; xfs_ino_t relino; addrp = contextp ? (seg_addr_t *)contextp : &addr; if ( !inomap_find_seg( addrp, ino ) ) return; segp = inomap_addr2seg( addrp ); i2gsegp = &inomap.i2gmap[inomap_addr2segix( addrp )]; relino = ino - segp->base; i2gsegp->s_valid |= (uint64_t)1 << relino; i2gsegp->s_gen[relino] = gen; } int inomap_get_gen( void *contextp, xfs_ino_t ino, gen_t *gen ) { seg_addr_t *addrp; seg_addr_t addr; seg_t *segp; i2gseg_t *i2gsegp; xfs_ino_t relino; addrp = contextp ? (seg_addr_t *)contextp : &addr; if ( !inomap_find_seg( addrp, ino ) ) return 1; segp = inomap_addr2seg( addrp ); i2gsegp = &inomap.i2gmap[inomap_addr2segix( addrp )]; relino = ino - segp->base; if ( ! (i2gsegp->s_valid & ((uint64_t)1 << relino)) ) return 1; *gen = i2gsegp->s_gen[relino]; return 0; } void inomap_writehdr( content_inode_hdr_t *scwhdrp ) { /* update the inomap info in the content header */ scwhdrp->cih_inomap_hnkcnt = inomap.lastseg.hnkoff + 1; scwhdrp->cih_inomap_segcnt = inomap_addr2segix( &inomap.lastseg ) + 1; scwhdrp->cih_inomap_dircnt = ( uint64_t )cb_dircnt; scwhdrp->cih_inomap_nondircnt = ( uint64_t )cb_nondircnt; scwhdrp->cih_inomap_firstino = inomap.hnkmap[0].seg[ 0 ].base; scwhdrp->cih_inomap_lastino = inomap.hnkmap[inomap.lastseg.hnkoff].maxino; scwhdrp->cih_inomap_datasz = ( uint64_t )cb_datasz; } rv_t inomap_dump( drive_t *drivep ) { seg_addr_t addr; hnk_t *hnkp; hnk_t tmphnkp; /* use write_buf to dump the hunks */ for ( addr.hnkoff = 0 ; addr.hnkoff <= inomap.lastseg.hnkoff ; addr.hnkoff++ ) { int rval; rv_t rv; drive_ops_t *dop = drivep->d_opsp; hnkp = inomap_addr2hnk( &addr ); xlate_hnk(hnkp, &tmphnkp, 1); rval = write_buf( ( char * )&tmphnkp, sizeof( tmphnkp ), ( void * )drivep, ( gwbfp_t )dop->do_get_write_buf, ( wfp_t )dop->do_write ); switch ( rval ) { case 0: rv = RV_OK; break; case DRIVE_ERROR_MEDIA: case DRIVE_ERROR_EOM: rv = RV_EOM; break; case DRIVE_ERROR_EOF: rv = RV_EOF; break; case DRIVE_ERROR_DEVICE: rv = RV_DRIVE; break; case DRIVE_ERROR_CORE: default: rv = RV_CORE; break; } if ( rv != RV_OK ) { return rv; } } return RV_OK; } static int subtreelist_parse( jdm_fshandle_t *fshandlep, int fsfd, xfs_bstat_t *rootstatp, char *subtreebuf[], ix_t subtreecnt ) { ix_t subtreeix; /* add the root ino to the dump */ cb_add( NULL, fshandlep, fsfd, rootstatp ); /* do a recursive descent for each subtree specified */ for ( subtreeix = 0 ; subtreeix < subtreecnt ; subtreeix++ ) { int cbrval = 0; char *currentpath = subtreebuf[ subtreeix ]; assert( *currentpath != '/' ); ( void )diriter( fshandlep, fsfd, rootstatp, subtreelist_parse_cb, ( void * )currentpath, &cbrval, NULL, 0 ); if ( cbrval != 1 ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_INOMAP, "%s: %s\n", cbrval == 0 ? _("subtree not present") : _("invalid subtree specified"), currentpath ); return -1; } } return 0; } static int subtreelist_parse_cb( void *arg1, jdm_fshandle_t *fshandlep, int fsfd, xfs_bstat_t *statp, char *name ) { int cbrval = 0; /* arg1 is used to carry the tail of the subtree path */ char *subpath = ( char * )arg1; /* temporarily terminate the subpath at the next slash */ char *nextslash = strchr( subpath, '/' ); if ( nextslash ) { *nextslash = 0; } /* if the first element of the subpath doesn't match this * directory entry, try the next entry. */ if ( strcmp( subpath, name )) { if ( nextslash ) { *nextslash = '/'; } return 0; } /* it matches, so add ino to list and continue down the path */ cb_add( NULL, fshandlep, fsfd, statp ); if ( nextslash ) { /* if we're not at the end of the path, yet the current * path element is not a directory, complain and abort the * iteration in a way which terminates the application */ if ( ( statp->bs_mode & S_IFMT ) != S_IFDIR ) { *nextslash = '/'; return 2; } /* repair the subpath */ *nextslash = '/'; /* peel the first element of the subpath and recurse */ ( void )diriter( fshandlep, fsfd, statp, subtreelist_parse_cb, ( void * )( nextslash + 1 ), &cbrval, NULL, 0 ); return cbrval; } else { /* we've reached the specified subpath, so if we're * at a directory, recurse down and add all children * to the inomap. */ if ( ( statp->bs_mode & S_IFMT ) != S_IFDIR ) { return 1; } ( void )diriter( fshandlep, fsfd, statp, subtree_descend_cb, NULL, &cbrval, 0, 0 ); return 1; } } static int subtree_descend_cb( void *arg1, jdm_fshandle_t *fshandlep, int fsfd, xfs_bstat_t *statp, char *name ) { int cbrval = 0; cb_add( NULL, fshandlep, fsfd, statp ); if ( ( statp->bs_mode & S_IFMT ) == S_IFDIR ) { ( void )diriter( fshandlep, fsfd, statp, subtree_descend_cb, NULL, &cbrval, NULL, 0 ); } return cbrval; } /* uses the extent map to figure the first offset in the file * with qty real (non-hole) bytes behind it */ #define BMAP_LEN 512 static off64_t quantity2offset( jdm_fshandle_t *fshandlep, xfs_bstat_t *statp, off64_t qty ) { int fd; getbmapx_t bmap[ BMAP_LEN ]; off64_t offset; off64_t offset_next; off64_t qty_accum; /* If GETOPT_DUMPASOFFLINE was specified and the HSM provided an * estimate, then use it. */ if (hsm_fs_ctxtp) { if (HsmEstimateFileOffset(hsm_fs_ctxtp, statp, qty, &offset)) return offset; } offset = 0; offset_next = 0; qty_accum = 0; bmap[ 0 ].bmv_offset = 0; bmap[ 0 ].bmv_length = -1; bmap[ 0 ].bmv_count = BMAP_LEN; bmap[ 0 ].bmv_iflags = BMV_IF_NO_DMAPI_READ; bmap[ 0 ].bmv_entries = -1; fd = jdm_open( fshandlep, statp, O_RDONLY ); if ( fd < 0 ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_INOMAP, _( "could not open ino %llu to read extent map: %s\n"), statp->bs_ino, strerror( errno )); return 0; } for ( ; ; ) { int eix; int rval; rval = ioctl( fd, XFS_IOC_GETBMAPX, bmap ); if ( rval ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_INOMAP, _( "could not read extent map for ino %llu: %s\n"), statp->bs_ino, strerror( errno )); ( void )close( fd ); return 0; } if ( bmap[ 0 ].bmv_entries <= 0 ) { assert( bmap[ 0 ].bmv_entries == 0 ); ( void )close( fd ); return offset_next; } for ( eix = 1 ; eix <= bmap[ 0 ].bmv_entries ; eix++ ) { getbmapx_t *bmapp = &bmap[ eix ]; off64_t qty_new; if ( bmapp->bmv_block == -1 ) { continue; /* hole */ } offset = bmapp->bmv_offset * BBSIZE; qty_new = qty_accum + bmapp->bmv_length * BBSIZE; if ( qty_new >= qty ) { ( void )close( fd ); return offset + ( qty - qty_accum ); } offset_next = offset + bmapp->bmv_length * BBSIZE; qty_accum = qty_new; } } /* NOTREACHED */ } static off64_t estimate_dump_space( xfs_bstat_t *statp ) { switch ( statp->bs_mode & S_IFMT ) { case S_IFREG: /* very rough: must improve this. If GETOPT_DUMPASOFFLINE was * specified and the HSM provided an estimate, then use it. */ if (hsm_fs_ctxtp) { off64_t bytes; int accurate; /* if -z or multiple streams are being used, * we need an accurate estimate. otherwise a * quick estimate will do. */ accurate = maxdumpfilesize || drivecnt > 1; if (HsmEstimateFileSpace(hsm_fs_ctxtp, NULL, statp, &bytes, accurate)) return bytes; } return statp->bs_blocks * ( off64_t )statp->bs_blksize; case S_IFIFO: case S_IFCHR: case S_IFDIR: #ifdef S_IFNAM case S_IFNAM: #endif case S_IFBLK: case S_IFSOCK: case S_IFLNK: /* not yet case S_IFUUID: */ return 0; default: mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_INOMAP, _( "unknown inode type: ino=%llu, mode=0x%04x 0%06o\n"), statp->bs_ino, statp->bs_mode, statp->bs_mode ); return 0; } } xfsdump-3.1.6+nmu1/ltmain.sh0000644000000000000000000105203012607344146012601 0ustar # libtool (GNU libtool) 2.4.2 # Written by Gordon Matzigkeit , 1996 # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, # 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool 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. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool 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 GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, # or obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Usage: $progname [OPTION]... [MODE-ARG]... # # Provide generalized library-building support services. # # --config show all configuration variables # --debug enable verbose shell tracing # -n, --dry-run display commands without modifying any files # --features display basic configuration information and exit # --mode=MODE use operation mode MODE # --preserve-dup-deps don't remove duplicate dependency libraries # --quiet, --silent don't print informational messages # --no-quiet, --no-silent # print informational messages (default) # --no-warn don't display warning messages # --tag=TAG use configuration variables from tag TAG # -v, --verbose print more informational messages than default # --no-verbose don't print the extra informational messages # --version print version information # -h, --help, --help-all print short, long, or detailed help message # # MODE must be one of the following: # # clean remove files from the build directory # compile compile a source file into a libtool object # execute automatically set library path, then run a program # finish complete the installation of libtool libraries # install install libraries or executables # link create a library or an executable # uninstall remove libraries from an installed directory # # MODE-ARGS vary depending on the MODE. When passed as first option, # `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that. # Try `$progname --help --mode=MODE' for a more detailed description of MODE. # # When reporting a bug, please describe a test case to reproduce it and # include the following information: # # host-triplet: $host # shell: $SHELL # compiler: $LTCC # compiler flags: $LTCFLAGS # linker: $LD (gnu? $with_gnu_ld) # $progname: (GNU libtool) 2.4.2 Debian-2.4.2-1.11 # automake: $automake_version # autoconf: $autoconf_version # # Report bugs to . # GNU libtool home page: . # General help using GNU software: . PROGRAM=libtool PACKAGE=libtool VERSION="2.4.2 Debian-2.4.2-1.11" TIMESTAMP="" package_revision=1.3337 # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } # NLS nuisances: We save the old values to restore during execute mode. lt_user_locale= lt_safe_locale= for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${$lt_var+set}\" = set; then save_$lt_var=\$$lt_var $lt_var=C export $lt_var lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" fi" done LC_ALL=C LANGUAGE=C export LANGUAGE LC_ALL $lt_unset CDPATH # Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh # is ksh but when the shell is invoked as "sh" and the current value of # the _XPG environment variable is not equal to 1 (one), the special # positional parameter $0, within a function call, is the name of the # function. progpath="$0" : ${CP="cp -f"} test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'} : ${MAKE="make"} : ${MKDIR="mkdir"} : ${MV="mv -f"} : ${RM="rm -f"} : ${SHELL="${CONFIG_SHELL-/bin/sh}"} : ${Xsed="$SED -e 1s/^X//"} # Global variables: EXIT_SUCCESS=0 EXIT_FAILURE=1 EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. exit_status=$EXIT_SUCCESS # Make sure IFS has a sensible default lt_nl=' ' IFS=" $lt_nl" dirname="s,/[^/]*$,," basename="s,^.*/,," # func_dirname file append nondir_replacement # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. func_dirname () { func_dirname_result=`$ECHO "${1}" | $SED "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi } # func_dirname may be replaced by extended shell implementation # func_basename file func_basename () { func_basename_result=`$ECHO "${1}" | $SED "$basename"` } # func_basename may be replaced by extended shell implementation # func_dirname_and_basename file append nondir_replacement # perform func_basename and func_dirname in a single function # call: # dirname: Compute the dirname of FILE. If nonempty, # add APPEND to the result, otherwise set result # to NONDIR_REPLACEMENT. # value returned in "$func_dirname_result" # basename: Compute filename of FILE. # value retuned in "$func_basename_result" # Implementation must be kept synchronized with func_dirname # and func_basename. For efficiency, we do not delegate to # those functions but instead duplicate the functionality here. func_dirname_and_basename () { # Extract subdirectory from the argument. func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi func_basename_result=`$ECHO "${1}" | $SED -e "$basename"` } # func_dirname_and_basename may be replaced by extended shell implementation # func_stripname prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # func_strip_suffix prefix name func_stripname () { case ${2} in .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; esac } # func_stripname may be replaced by extended shell implementation # These SED scripts presuppose an absolute path with a trailing slash. pathcar='s,^/\([^/]*\).*$,\1,' pathcdr='s,^/[^/]*,,' removedotparts=':dotsl s@/\./@/@g t dotsl s,/\.$,/,' collapseslashes='s@/\{1,\}@/@g' finalslash='s,/*$,/,' # func_normal_abspath PATH # Remove doubled-up and trailing slashes, "." path components, # and cancel out any ".." path components in PATH after making # it an absolute path. # value returned in "$func_normal_abspath_result" func_normal_abspath () { # Start from root dir and reassemble the path. func_normal_abspath_result= func_normal_abspath_tpath=$1 func_normal_abspath_altnamespace= case $func_normal_abspath_tpath in "") # Empty path, that just means $cwd. func_stripname '' '/' "`pwd`" func_normal_abspath_result=$func_stripname_result return ;; # The next three entries are used to spot a run of precisely # two leading slashes without using negated character classes; # we take advantage of case's first-match behaviour. ///*) # Unusual form of absolute path, do nothing. ;; //*) # Not necessarily an ordinary path; POSIX reserves leading '//' # and for example Cygwin uses it to access remote file shares # over CIFS/SMB, so we conserve a leading double slash if found. func_normal_abspath_altnamespace=/ ;; /*) # Absolute path, do nothing. ;; *) # Relative path, prepend $cwd. func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath ;; esac # Cancel out all the simple stuff to save iterations. We also want # the path to end with a slash for ease of parsing, so make sure # there is one (and only one) here. func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"` while :; do # Processed it all yet? if test "$func_normal_abspath_tpath" = / ; then # If we ascended to the root using ".." the result may be empty now. if test -z "$func_normal_abspath_result" ; then func_normal_abspath_result=/ fi break fi func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$pathcar"` func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$pathcdr"` # Figure out what to do with it case $func_normal_abspath_tcomponent in "") # Trailing empty path component, ignore it. ;; ..) # Parent dir; strip last assembled component from result. func_dirname "$func_normal_abspath_result" func_normal_abspath_result=$func_dirname_result ;; *) # Actual path component, append it. func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent ;; esac done # Restore leading double-slash if one was found on entry. func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result } # func_relative_path SRCDIR DSTDIR # generates a relative path from SRCDIR to DSTDIR, with a trailing # slash if non-empty, suitable for immediately appending a filename # without needing to append a separator. # value returned in "$func_relative_path_result" func_relative_path () { func_relative_path_result= func_normal_abspath "$1" func_relative_path_tlibdir=$func_normal_abspath_result func_normal_abspath "$2" func_relative_path_tbindir=$func_normal_abspath_result # Ascend the tree starting from libdir while :; do # check if we have found a prefix of bindir case $func_relative_path_tbindir in $func_relative_path_tlibdir) # found an exact match func_relative_path_tcancelled= break ;; $func_relative_path_tlibdir*) # found a matching prefix func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" func_relative_path_tcancelled=$func_stripname_result if test -z "$func_relative_path_result"; then func_relative_path_result=. fi break ;; *) func_dirname $func_relative_path_tlibdir func_relative_path_tlibdir=${func_dirname_result} if test "x$func_relative_path_tlibdir" = x ; then # Have to descend all the way to the root! func_relative_path_result=../$func_relative_path_result func_relative_path_tcancelled=$func_relative_path_tbindir break fi func_relative_path_result=../$func_relative_path_result ;; esac done # Now calculate path; take care to avoid doubling-up slashes. func_stripname '' '/' "$func_relative_path_result" func_relative_path_result=$func_stripname_result func_stripname '/' '/' "$func_relative_path_tcancelled" if test "x$func_stripname_result" != x ; then func_relative_path_result=${func_relative_path_result}/${func_stripname_result} fi # Normalisation. If bindir is libdir, return empty string, # else relative path ending with a slash; either way, target # file name can be directly appended. if test ! -z "$func_relative_path_result"; then func_stripname './' '' "$func_relative_path_result/" func_relative_path_result=$func_stripname_result fi } # The name of this program: func_dirname_and_basename "$progpath" progname=$func_basename_result # Make sure we have an absolute path for reexecution: case $progpath in [\\/]*|[A-Za-z]:\\*) ;; *[\\/]*) progdir=$func_dirname_result progdir=`cd "$progdir" && pwd` progpath="$progdir/$progname" ;; *) save_IFS="$IFS" IFS=${PATH_SEPARATOR-:} for progdir in $PATH; do IFS="$save_IFS" test -x "$progdir/$progname" && break done IFS="$save_IFS" test -n "$progdir" || progdir=`pwd` progpath="$progdir/$progname" ;; esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed="${SED}"' -e 1s/^X//' sed_quote_subst='s/\([`"$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution that turns a string into a regex matching for the # string literally. sed_make_literal_regex='s,[].[^$\\*\/],\\&,g' # Sed substitution that converts a w32 file name or path # which contains forward slashes, into one that contains # (escaped) backslashes. A very naive implementation. lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' # Re-`\' parameter expansions in output of double_quote_subst that were # `\'-ed in input to the same. If an odd number of `\' preceded a '$' # in input to double_quote_subst, that '$' was protected from expansion. # Since each input `\' is now two `\'s, look for any number of runs of # four `\'s followed by two `\'s and then a '$'. `\' that '$'. bs='\\' bs2='\\\\' bs4='\\\\\\\\' dollar='\$' sed_double_backslash="\ s/$bs4/&\\ /g s/^$bs2$dollar/$bs&/ s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g s/\n//g" # Standard options: opt_dry_run=false opt_help=false opt_quiet=false opt_verbose=false opt_warning=: # func_echo arg... # Echo program name prefixed message, along with the current mode # name if it has been set yet. func_echo () { $ECHO "$progname: ${opt_mode+$opt_mode: }$*" } # func_verbose arg... # Echo program name prefixed message in verbose mode only. func_verbose () { $opt_verbose && func_echo ${1+"$@"} # A bug in bash halts the script if the last line of a function # fails when set -e is in force, so we need another command to # work around that: : } # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } # func_error arg... # Echo program name prefixed message to standard error. func_error () { $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 } # func_warning arg... # Echo program name prefixed warning message to standard error. func_warning () { $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 # bash bug again: : } # func_fatal_error arg... # Echo program name prefixed message to standard error, and exit. func_fatal_error () { func_error ${1+"$@"} exit $EXIT_FAILURE } # func_fatal_help arg... # Echo program name prefixed message to standard error, followed by # a help hint, and exit. func_fatal_help () { func_error ${1+"$@"} func_fatal_error "$help" } help="Try \`$progname --help' for more information." ## default # func_grep expression filename # Check whether EXPRESSION matches any line of FILENAME, without output. func_grep () { $GREP "$1" "$2" >/dev/null 2>&1 } # func_mkdir_p directory-path # Make sure the entire path to DIRECTORY-PATH is available. func_mkdir_p () { my_directory_path="$1" my_dir_list= if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then # Protect directory names starting with `-' case $my_directory_path in -*) my_directory_path="./$my_directory_path" ;; esac # While some portion of DIR does not yet exist... while test ! -d "$my_directory_path"; do # ...make a list in topmost first order. Use a colon delimited # list incase some portion of path contains whitespace. my_dir_list="$my_directory_path:$my_dir_list" # If the last portion added has no slash in it, the list is done case $my_directory_path in */*) ;; *) break ;; esac # ...otherwise throw away the child directory and loop my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"` done my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'` save_mkdir_p_IFS="$IFS"; IFS=':' for my_dir in $my_dir_list; do IFS="$save_mkdir_p_IFS" # mkdir can fail with a `File exist' error if two processes # try to create one of the directories concurrently. Don't # stop in that case! $MKDIR "$my_dir" 2>/dev/null || : done IFS="$save_mkdir_p_IFS" # Bail out if we (or some other process) failed to create a directory. test -d "$my_directory_path" || \ func_fatal_error "Failed to create \`$1'" fi } # func_mktempdir [string] # Make a temporary directory that won't clash with other running # libtool processes, and avoids race conditions if possible. If # given, STRING is the basename for that directory. func_mktempdir () { my_template="${TMPDIR-/tmp}/${1-$progname}" if test "$opt_dry_run" = ":"; then # Return a directory name, but don't create it in dry-run mode my_tmpdir="${my_template}-$$" else # If mktemp works, use that first and foremost my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` if test ! -d "$my_tmpdir"; then # Failing that, at least try and use $RANDOM to avoid a race my_tmpdir="${my_template}-${RANDOM-0}$$" save_mktempdir_umask=`umask` umask 0077 $MKDIR "$my_tmpdir" umask $save_mktempdir_umask fi # If we're not in dry-run mode, bomb out on failure test -d "$my_tmpdir" || \ func_fatal_error "cannot create temporary directory \`$my_tmpdir'" fi $ECHO "$my_tmpdir" } # func_quote_for_eval arg # Aesthetically quote ARG to be evaled later. # This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT # is double-quoted, suitable for a subsequent eval, whereas # FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters # which are still active within double quotes backslashified. func_quote_for_eval () { case $1 in *[\\\`\"\$]*) func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;; *) func_quote_for_eval_unquoted_result="$1" ;; esac case $func_quote_for_eval_unquoted_result in # Double-quote args containing shell metacharacters to delay # word splitting, command substitution and and variable # expansion for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" ;; *) func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" esac } # func_quote_for_expand arg # Aesthetically quote ARG to be evaled later; same as above, # but do not quote variable references. func_quote_for_expand () { case $1 in *[\\\`\"]*) my_arg=`$ECHO "$1" | $SED \ -e "$double_quote_subst" -e "$sed_double_backslash"` ;; *) my_arg="$1" ;; esac case $my_arg in # Double-quote args containing shell metacharacters to delay # word splitting and command substitution for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") my_arg="\"$my_arg\"" ;; esac func_quote_for_expand_result="$my_arg" } # func_show_eval cmd [fail_exp] # Unless opt_silent is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. func_show_eval () { my_cmd="$1" my_fail_exp="${2-:}" ${opt_silent-false} || { func_quote_for_expand "$my_cmd" eval "func_echo $func_quote_for_expand_result" } if ${opt_dry_run-false}; then :; else eval "$my_cmd" my_status=$? if test "$my_status" -eq 0; then :; else eval "(exit $my_status); $my_fail_exp" fi fi } # func_show_eval_locale cmd [fail_exp] # Unless opt_silent is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. Use the saved locale for evaluation. func_show_eval_locale () { my_cmd="$1" my_fail_exp="${2-:}" ${opt_silent-false} || { func_quote_for_expand "$my_cmd" eval "func_echo $func_quote_for_expand_result" } if ${opt_dry_run-false}; then :; else eval "$lt_user_locale $my_cmd" my_status=$? eval "$lt_safe_locale" if test "$my_status" -eq 0; then :; else eval "(exit $my_status); $my_fail_exp" fi fi } # func_tr_sh # Turn $1 into a string suitable for a shell variable name. # Result is stored in $func_tr_sh_result. All characters # not in the set a-zA-Z0-9_ are replaced with '_'. Further, # if $1 begins with a digit, a '_' is prepended as well. func_tr_sh () { case $1 in [0-9]* | *[!a-zA-Z0-9_]*) func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'` ;; * ) func_tr_sh_result=$1 ;; esac } # func_version # Echo version message to standard output and exit. func_version () { $opt_debug $SED -n '/(C)/!b go :more /\./!{ N s/\n# / / b more } :go /^# '$PROGRAM' (GNU /,/# warranty; / { s/^# // s/^# *$// s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ p }' < "$progpath" exit $? } # func_usage # Echo short help message to standard output and exit. func_usage () { $opt_debug $SED -n '/^# Usage:/,/^# *.*--help/ { s/^# // s/^# *$// s/\$progname/'$progname'/ p }' < "$progpath" echo $ECHO "run \`$progname --help | more' for full usage" exit $? } # func_help [NOEXIT] # Echo long help message to standard output and exit, # unless 'noexit' is passed as argument. func_help () { $opt_debug $SED -n '/^# Usage:/,/# Report bugs to/ { :print s/^# // s/^# *$// s*\$progname*'$progname'* s*\$host*'"$host"'* s*\$SHELL*'"$SHELL"'* s*\$LTCC*'"$LTCC"'* s*\$LTCFLAGS*'"$LTCFLAGS"'* s*\$LD*'"$LD"'* s/\$with_gnu_ld/'"$with_gnu_ld"'/ s/\$automake_version/'"`(${AUTOMAKE-automake} --version) 2>/dev/null |$SED 1q`"'/ s/\$autoconf_version/'"`(${AUTOCONF-autoconf} --version) 2>/dev/null |$SED 1q`"'/ p d } /^# .* home page:/b print /^# General help using/b print ' < "$progpath" ret=$? if test -z "$1"; then exit $ret fi } # func_missing_arg argname # Echo program name prefixed message to standard error and set global # exit_cmd. func_missing_arg () { $opt_debug func_error "missing argument for $1." exit_cmd=exit } # func_split_short_opt shortopt # Set func_split_short_opt_name and func_split_short_opt_arg shell # variables after splitting SHORTOPT after the 2nd character. func_split_short_opt () { my_sed_short_opt='1s/^\(..\).*$/\1/;q' my_sed_short_rest='1s/^..\(.*\)$/\1/;q' func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"` func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"` } # func_split_short_opt may be replaced by extended shell implementation # func_split_long_opt longopt # Set func_split_long_opt_name and func_split_long_opt_arg shell # variables after splitting LONGOPT at the `=' sign. func_split_long_opt () { my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q' my_sed_long_arg='1s/^--[^=]*=//' func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"` func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"` } # func_split_long_opt may be replaced by extended shell implementation exit_cmd=: magic="%%%MAGIC variable%%%" magic_exe="%%%MAGIC EXE variable%%%" # Global variables. nonopt= preserve_args= lo2o="s/\\.lo\$/.${objext}/" o2lo="s/\\.${objext}\$/.lo/" extracted_archives= extracted_serial=0 # If this variable is set in any of the actions, the command in it # will be execed at the end. This prevents here-documents from being # left over by shells. exec_cmd= # func_append var value # Append VALUE to the end of shell variable VAR. func_append () { eval "${1}=\$${1}\${2}" } # func_append may be replaced by extended shell implementation # func_append_quoted var value # Quote VALUE and append to the end of shell variable VAR, separated # by a space. func_append_quoted () { func_quote_for_eval "${2}" eval "${1}=\$${1}\\ \$func_quote_for_eval_result" } # func_append_quoted may be replaced by extended shell implementation # func_arith arithmetic-term... func_arith () { func_arith_result=`expr "${@}"` } # func_arith may be replaced by extended shell implementation # func_len string # STRING may not start with a hyphen. func_len () { func_len_result=`expr "${1}" : ".*" 2>/dev/null || echo $max_cmd_len` } # func_len may be replaced by extended shell implementation # func_lo2o object func_lo2o () { func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"` } # func_lo2o may be replaced by extended shell implementation # func_xform libobj-or-source func_xform () { func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'` } # func_xform may be replaced by extended shell implementation # func_fatal_configuration arg... # Echo program name prefixed message to standard error, followed by # a configuration failure hint, and exit. func_fatal_configuration () { func_error ${1+"$@"} func_error "See the $PACKAGE documentation for more information." func_fatal_error "Fatal configuration error." } # func_config # Display the configuration for all the tags in this script. func_config () { re_begincf='^# ### BEGIN LIBTOOL' re_endcf='^# ### END LIBTOOL' # Default configuration. $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" # Now print the configurations for the tags. for tagname in $taglist; do $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" done exit $? } # func_features # Display the features supported by this script. func_features () { echo "host: $host" if test "$build_libtool_libs" = yes; then echo "enable shared libraries" else echo "disable shared libraries" fi if test "$build_old_libs" = yes; then echo "enable static libraries" else echo "disable static libraries" fi exit $? } # func_enable_tag tagname # Verify that TAGNAME is valid, and either flag an error and exit, or # enable the TAGNAME tag. We also add TAGNAME to the global $taglist # variable here. func_enable_tag () { # Global variable: tagname="$1" re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" sed_extractcf="/$re_begincf/,/$re_endcf/p" # Validate tagname. case $tagname in *[!-_A-Za-z0-9,/]*) func_fatal_error "invalid tag name: $tagname" ;; esac # Don't test for the "default" C tag, as we know it's # there but not specially marked. case $tagname in CC) ;; *) if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then taglist="$taglist $tagname" # Evaluate the configuration. Be careful to quote the path # and the sed script, to avoid splitting on whitespace, but # also don't use non-portable quotes within backquotes within # quotes we have to do it in 2 steps: extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` eval "$extractedcf" else func_error "ignoring unknown tag $tagname" fi ;; esac } # func_check_version_match # Ensure that we are using m4 macros, and libtool script from the same # release of libtool. func_check_version_match () { if test "$package_revision" != "$macro_revision"; then if test "$VERSION" != "$macro_version"; then if test -z "$macro_version"; then cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from an older release. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from $PACKAGE $macro_version. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF fi else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, $progname: but the definition of this LT_INIT comes from revision $macro_revision. $progname: You should recreate aclocal.m4 with macros from revision $package_revision $progname: of $PACKAGE $VERSION and run autoconf again. _LT_EOF fi exit $EXIT_MISMATCH fi } # Shorthand for --mode=foo, only valid as the first argument case $1 in clean|clea|cle|cl) shift; set dummy --mode clean ${1+"$@"}; shift ;; compile|compil|compi|comp|com|co|c) shift; set dummy --mode compile ${1+"$@"}; shift ;; execute|execut|execu|exec|exe|ex|e) shift; set dummy --mode execute ${1+"$@"}; shift ;; finish|finis|fini|fin|fi|f) shift; set dummy --mode finish ${1+"$@"}; shift ;; install|instal|insta|inst|ins|in|i) shift; set dummy --mode install ${1+"$@"}; shift ;; link|lin|li|l) shift; set dummy --mode link ${1+"$@"}; shift ;; uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) shift; set dummy --mode uninstall ${1+"$@"}; shift ;; esac # Option defaults: opt_debug=: opt_dry_run=false opt_config=false opt_preserve_dup_deps=false opt_features=false opt_finish=false opt_help=false opt_help_all=false opt_silent=: opt_warning=: opt_verbose=: opt_silent=false opt_verbose=false # Parse options once, thoroughly. This comes as soon as possible in the # script to make things like `--version' happen as quickly as we can. { # this just eases exit handling while test $# -gt 0; do opt="$1" shift case $opt in --debug|-x) opt_debug='set -x' func_echo "enabling shell trace mode" $opt_debug ;; --dry-run|--dryrun|-n) opt_dry_run=: ;; --config) opt_config=: func_config ;; --dlopen|-dlopen) optarg="$1" opt_dlopen="${opt_dlopen+$opt_dlopen }$optarg" shift ;; --preserve-dup-deps) opt_preserve_dup_deps=: ;; --features) opt_features=: func_features ;; --finish) opt_finish=: set dummy --mode finish ${1+"$@"}; shift ;; --help) opt_help=: ;; --help-all) opt_help_all=: opt_help=': help-all' ;; --mode) test $# = 0 && func_missing_arg $opt && break optarg="$1" opt_mode="$optarg" case $optarg in # Valid mode arguments: clean|compile|execute|finish|install|link|relink|uninstall) ;; # Catch anything else as an error *) func_error "invalid argument for $opt" exit_cmd=exit break ;; esac shift ;; --no-silent|--no-quiet) opt_silent=false func_append preserve_args " $opt" ;; --no-warning|--no-warn) opt_warning=false func_append preserve_args " $opt" ;; --no-verbose) opt_verbose=false func_append preserve_args " $opt" ;; --silent|--quiet) opt_silent=: func_append preserve_args " $opt" opt_verbose=false ;; --verbose|-v) opt_verbose=: func_append preserve_args " $opt" opt_silent=false ;; --tag) test $# = 0 && func_missing_arg $opt && break optarg="$1" opt_tag="$optarg" func_append preserve_args " $opt $optarg" func_enable_tag "$optarg" shift ;; -\?|-h) func_usage ;; --help) func_help ;; --version) func_version ;; # Separate optargs to long options: --*=*) func_split_long_opt "$opt" set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"} shift ;; # Separate non-argument short options: -\?*|-h*|-n*|-v*) func_split_short_opt "$opt" set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"} shift ;; --) break ;; -*) func_fatal_help "unrecognized option \`$opt'" ;; *) set dummy "$opt" ${1+"$@"}; shift; break ;; esac done # Validate options: # save first non-option argument if test "$#" -gt 0; then nonopt="$opt" shift fi # preserve --debug test "$opt_debug" = : || func_append preserve_args " --debug" case $host in *cygwin* | *mingw* | *pw32* | *cegcc*) # don't eliminate duplications in $postdeps and $predeps opt_duplicate_compiler_generated_deps=: ;; *) opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps ;; esac $opt_help || { # Sanity checks first: func_check_version_match if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then func_fatal_configuration "not configured to build any kind of library" fi # Darwin sucks eval std_shrext=\"$shrext_cmds\" # Only execute mode is allowed to have -dlopen flags. if test -n "$opt_dlopen" && test "$opt_mode" != execute; then func_error "unrecognized option \`-dlopen'" $ECHO "$help" 1>&2 exit $EXIT_FAILURE fi # Change the help message to a mode-specific one. generic_help="$help" help="Try \`$progname --help --mode=$opt_mode' for more information." } # Bail if the options were screwed $exit_cmd $EXIT_FAILURE } ## ----------- ## ## Main. ## ## ----------- ## # func_lalib_p file # True iff FILE is a libtool `.la' library or `.lo' object file. # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_lalib_p () { test -f "$1" && $SED -e 4q "$1" 2>/dev/null \ | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 } # func_lalib_unsafe_p file # True iff FILE is a libtool `.la' library or `.lo' object file. # This function implements the same check as func_lalib_p without # resorting to external programs. To this end, it redirects stdin and # closes it afterwards, without saving the original file descriptor. # As a safety measure, use it only where a negative result would be # fatal anyway. Works if `file' does not exist. func_lalib_unsafe_p () { lalib_p=no if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then for lalib_p_l in 1 2 3 4 do read lalib_p_line case "$lalib_p_line" in \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; esac done exec 0<&5 5<&- fi test "$lalib_p" = yes } # func_ltwrapper_script_p file # True iff FILE is a libtool wrapper script # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_script_p () { func_lalib_p "$1" } # func_ltwrapper_executable_p file # True iff FILE is a libtool wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_executable_p () { func_ltwrapper_exec_suffix= case $1 in *.exe) ;; *) func_ltwrapper_exec_suffix=.exe ;; esac $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 } # func_ltwrapper_scriptname file # Assumes file is an ltwrapper_executable # uses $file to determine the appropriate filename for a # temporary ltwrapper_script. func_ltwrapper_scriptname () { func_dirname_and_basename "$1" "" "." func_stripname '' '.exe' "$func_basename_result" func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" } # func_ltwrapper_p file # True iff FILE is a libtool wrapper script or wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_p () { func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" } # func_execute_cmds commands fail_cmd # Execute tilde-delimited COMMANDS. # If FAIL_CMD is given, eval that upon failure. # FAIL_CMD may read-access the current command in variable CMD! func_execute_cmds () { $opt_debug save_ifs=$IFS; IFS='~' for cmd in $1; do IFS=$save_ifs eval cmd=\"$cmd\" func_show_eval "$cmd" "${2-:}" done IFS=$save_ifs } # func_source file # Source FILE, adding directory component if necessary. # Note that it is not necessary on cygwin/mingw to append a dot to # FILE even if both FILE and FILE.exe exist: automatic-append-.exe # behavior happens only for exec(3), not for open(2)! Also, sourcing # `FILE.' does not work on cygwin managed mounts. func_source () { $opt_debug case $1 in */* | *\\*) . "$1" ;; *) . "./$1" ;; esac } # func_resolve_sysroot PATH # Replace a leading = in PATH with a sysroot. Store the result into # func_resolve_sysroot_result func_resolve_sysroot () { func_resolve_sysroot_result=$1 case $func_resolve_sysroot_result in =*) func_stripname '=' '' "$func_resolve_sysroot_result" func_resolve_sysroot_result=$lt_sysroot$func_stripname_result ;; esac } # func_replace_sysroot PATH # If PATH begins with the sysroot, replace it with = and # store the result into func_replace_sysroot_result. func_replace_sysroot () { case "$lt_sysroot:$1" in ?*:"$lt_sysroot"*) func_stripname "$lt_sysroot" '' "$1" func_replace_sysroot_result="=$func_stripname_result" ;; *) # Including no sysroot. func_replace_sysroot_result=$1 ;; esac } # func_infer_tag arg # Infer tagged configuration to use if any are available and # if one wasn't chosen via the "--tag" command line option. # Only attempt this if the compiler in the base compile # command doesn't match the default compiler. # arg is usually of the form 'gcc ...' func_infer_tag () { $opt_debug if test -n "$available_tags" && test -z "$tagname"; then CC_quoted= for arg in $CC; do func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case $@ in # Blanks in the command may have been stripped by the calling shell, # but not from the CC environment variable when configure was run. " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; # Blanks at the start of $base_compile will cause this to fail # if we don't check for them as well. *) for z in $available_tags; do if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then # Evaluate the configuration. eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" CC_quoted= for arg in $CC; do # Double-quote args containing other shell metacharacters. func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case "$@ " in " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) # The compiler in the base compile command matches # the one in the tagged configuration. # Assume this is the tagged configuration we want. tagname=$z break ;; esac fi done # If $tagname still isn't set, then no tagged configuration # was found and let the user know that the "--tag" command # line option must be used. if test -z "$tagname"; then func_echo "unable to infer tagged configuration" func_fatal_error "specify a tag with \`--tag'" # else # func_verbose "using $tagname tagged configuration" fi ;; esac fi } # func_write_libtool_object output_name pic_name nonpic_name # Create a libtool object file (analogous to a ".la" file), # but don't create it if we're doing a dry run. func_write_libtool_object () { write_libobj=${1} if test "$build_libtool_libs" = yes; then write_lobj=\'${2}\' else write_lobj=none fi if test "$build_old_libs" = yes; then write_oldobj=\'${3}\' else write_oldobj=none fi $opt_dry_run || { cat >${write_libobj}T </dev/null` if test "$?" -eq 0 && test -n "${func_convert_core_file_wine_to_w32_tmp}"; then func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | $SED -e "$lt_sed_naive_backslashify"` else func_convert_core_file_wine_to_w32_result= fi fi } # end: func_convert_core_file_wine_to_w32 # func_convert_core_path_wine_to_w32 ARG # Helper function used by path conversion functions when $build is *nix, and # $host is mingw, cygwin, or some other w32 environment. Relies on a correctly # configured wine environment available, with the winepath program in $build's # $PATH. Assumes ARG has no leading or trailing path separator characters. # # ARG is path to be converted from $build format to win32. # Result is available in $func_convert_core_path_wine_to_w32_result. # Unconvertible file (directory) names in ARG are skipped; if no directory names # are convertible, then the result may be empty. func_convert_core_path_wine_to_w32 () { $opt_debug # unfortunately, winepath doesn't convert paths, only file names func_convert_core_path_wine_to_w32_result="" if test -n "$1"; then oldIFS=$IFS IFS=: for func_convert_core_path_wine_to_w32_f in $1; do IFS=$oldIFS func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" if test -n "$func_convert_core_file_wine_to_w32_result" ; then if test -z "$func_convert_core_path_wine_to_w32_result"; then func_convert_core_path_wine_to_w32_result="$func_convert_core_file_wine_to_w32_result" else func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" fi fi done IFS=$oldIFS fi } # end: func_convert_core_path_wine_to_w32 # func_cygpath ARGS... # Wrapper around calling the cygpath program via LT_CYGPATH. This is used when # when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) # $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or # (2), returns the Cygwin file name or path in func_cygpath_result (input # file name or path is assumed to be in w32 format, as previously converted # from $build's *nix or MSYS format). In case (3), returns the w32 file name # or path in func_cygpath_result (input file name or path is assumed to be in # Cygwin format). Returns an empty string on error. # # ARGS are passed to cygpath, with the last one being the file name or path to # be converted. # # Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH # environment variable; do not put it in $PATH. func_cygpath () { $opt_debug if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` if test "$?" -ne 0; then # on failure, ensure result is empty func_cygpath_result= fi else func_cygpath_result= func_error "LT_CYGPATH is empty or specifies non-existent file: \`$LT_CYGPATH'" fi } #end: func_cygpath # func_convert_core_msys_to_w32 ARG # Convert file name or path ARG from MSYS format to w32 format. Return # result in func_convert_core_msys_to_w32_result. func_convert_core_msys_to_w32 () { $opt_debug # awkward: cmd appends spaces to result func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"` } #end: func_convert_core_msys_to_w32 # func_convert_file_check ARG1 ARG2 # Verify that ARG1 (a file name in $build format) was converted to $host # format in ARG2. Otherwise, emit an error message, but continue (resetting # func_to_host_file_result to ARG1). func_convert_file_check () { $opt_debug if test -z "$2" && test -n "$1" ; then func_error "Could not determine host file name corresponding to" func_error " \`$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback: func_to_host_file_result="$1" fi } # end func_convert_file_check # func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH # Verify that FROM_PATH (a path in $build format) was converted to $host # format in TO_PATH. Otherwise, emit an error message, but continue, resetting # func_to_host_file_result to a simplistic fallback value (see below). func_convert_path_check () { $opt_debug if test -z "$4" && test -n "$3"; then func_error "Could not determine the host path corresponding to" func_error " \`$3'" func_error "Continuing, but uninstalled executables may not work." # Fallback. This is a deliberately simplistic "conversion" and # should not be "improved". See libtool.info. if test "x$1" != "x$2"; then lt_replace_pathsep_chars="s|$1|$2|g" func_to_host_path_result=`echo "$3" | $SED -e "$lt_replace_pathsep_chars"` else func_to_host_path_result="$3" fi fi } # end func_convert_path_check # func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG # Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT # and appending REPL if ORIG matches BACKPAT. func_convert_path_front_back_pathsep () { $opt_debug case $4 in $1 ) func_to_host_path_result="$3$func_to_host_path_result" ;; esac case $4 in $2 ) func_append func_to_host_path_result "$3" ;; esac } # end func_convert_path_front_back_pathsep ################################################## # $build to $host FILE NAME CONVERSION FUNCTIONS # ################################################## # invoked via `$to_host_file_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # Result will be available in $func_to_host_file_result. # func_to_host_file ARG # Converts the file name ARG from $build format to $host format. Return result # in func_to_host_file_result. func_to_host_file () { $opt_debug $to_host_file_cmd "$1" } # end func_to_host_file # func_to_tool_file ARG LAZY # converts the file name ARG from $build format to toolchain format. Return # result in func_to_tool_file_result. If the conversion in use is listed # in (the comma separated) LAZY, no conversion takes place. func_to_tool_file () { $opt_debug case ,$2, in *,"$to_tool_file_cmd",*) func_to_tool_file_result=$1 ;; *) $to_tool_file_cmd "$1" func_to_tool_file_result=$func_to_host_file_result ;; esac } # end func_to_tool_file # func_convert_file_noop ARG # Copy ARG to func_to_host_file_result. func_convert_file_noop () { func_to_host_file_result="$1" } # end func_convert_file_noop # func_convert_file_msys_to_w32 ARG # Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_file_result. func_convert_file_msys_to_w32 () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_to_host_file_result="$func_convert_core_msys_to_w32_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_w32 # func_convert_file_cygwin_to_w32 ARG # Convert file name ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_file_cygwin_to_w32 () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then # because $build is cygwin, we call "the" cygpath in $PATH; no need to use # LT_CYGPATH in this case. func_to_host_file_result=`cygpath -m "$1"` fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_cygwin_to_w32 # func_convert_file_nix_to_w32 ARG # Convert file name ARG from *nix to w32 format. Requires a wine environment # and a working winepath. Returns result in func_to_host_file_result. func_convert_file_nix_to_w32 () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_file_wine_to_w32 "$1" func_to_host_file_result="$func_convert_core_file_wine_to_w32_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_w32 # func_convert_file_msys_to_cygwin ARG # Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_file_msys_to_cygwin () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_cygpath -u "$func_convert_core_msys_to_w32_result" func_to_host_file_result="$func_cygpath_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_cygwin # func_convert_file_nix_to_cygwin ARG # Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed # in a wine environment, working winepath, and LT_CYGPATH set. Returns result # in func_to_host_file_result. func_convert_file_nix_to_cygwin () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. func_convert_core_file_wine_to_w32 "$1" func_cygpath -u "$func_convert_core_file_wine_to_w32_result" func_to_host_file_result="$func_cygpath_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_cygwin ############################################# # $build to $host PATH CONVERSION FUNCTIONS # ############################################# # invoked via `$to_host_path_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # The result will be available in $func_to_host_path_result. # # Path separators are also converted from $build format to $host format. If # ARG begins or ends with a path separator character, it is preserved (but # converted to $host format) on output. # # All path conversion functions are named using the following convention: # file name conversion function : func_convert_file_X_to_Y () # path conversion function : func_convert_path_X_to_Y () # where, for any given $build/$host combination the 'X_to_Y' value is the # same. If conversion functions are added for new $build/$host combinations, # the two new functions must follow this pattern, or func_init_to_host_path_cmd # will break. # func_init_to_host_path_cmd # Ensures that function "pointer" variable $to_host_path_cmd is set to the # appropriate value, based on the value of $to_host_file_cmd. to_host_path_cmd= func_init_to_host_path_cmd () { $opt_debug if test -z "$to_host_path_cmd"; then func_stripname 'func_convert_file_' '' "$to_host_file_cmd" to_host_path_cmd="func_convert_path_${func_stripname_result}" fi } # func_to_host_path ARG # Converts the path ARG from $build format to $host format. Return result # in func_to_host_path_result. func_to_host_path () { $opt_debug func_init_to_host_path_cmd $to_host_path_cmd "$1" } # end func_to_host_path # func_convert_path_noop ARG # Copy ARG to func_to_host_path_result. func_convert_path_noop () { func_to_host_path_result="$1" } # end func_convert_path_noop # func_convert_path_msys_to_w32 ARG # Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_path_result. func_convert_path_msys_to_w32 () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # Remove leading and trailing path separator characters from ARG. MSYS # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; # and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result="$func_convert_core_msys_to_w32_result" func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_msys_to_w32 # func_convert_path_cygwin_to_w32 ARG # Convert path ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_path_cygwin_to_w32 () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_cygwin_to_w32 # func_convert_path_nix_to_w32 ARG # Convert path ARG from *nix to w32 format. Requires a wine environment and # a working winepath. Returns result in func_to_host_file_result. func_convert_path_nix_to_w32 () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result="$func_convert_core_path_wine_to_w32_result" func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_nix_to_w32 # func_convert_path_msys_to_cygwin ARG # Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_path_msys_to_cygwin () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_msys_to_w32_result" func_to_host_path_result="$func_cygpath_result" func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_msys_to_cygwin # func_convert_path_nix_to_cygwin ARG # Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a # a wine environment, working winepath, and LT_CYGPATH set. Returns result in # func_to_host_file_result. func_convert_path_nix_to_cygwin () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # Remove leading and trailing path separator characters from # ARG. msys behavior is inconsistent here, cygpath turns them # into '.;' and ';.', and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" func_to_host_path_result="$func_cygpath_result" func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_nix_to_cygwin # func_mode_compile arg... func_mode_compile () { $opt_debug # Get the compilation command and the source file. base_compile= srcfile="$nonopt" # always keep a non-empty value in "srcfile" suppress_opt=yes suppress_output= arg_mode=normal libobj= later= pie_flag= for arg do case $arg_mode in arg ) # do not "continue". Instead, add this to base_compile lastarg="$arg" arg_mode=normal ;; target ) libobj="$arg" arg_mode=normal continue ;; normal ) # Accept any command-line options. case $arg in -o) test -n "$libobj" && \ func_fatal_error "you cannot specify \`-o' more than once" arg_mode=target continue ;; -pie | -fpie | -fPIE) func_append pie_flag " $arg" continue ;; -shared | -static | -prefer-pic | -prefer-non-pic) func_append later " $arg" continue ;; -no-suppress) suppress_opt=no continue ;; -Xcompiler) arg_mode=arg # the next one goes into the "base_compile" arg list continue # The current "srcfile" will either be retained or ;; # replaced later. I would guess that would be a bug. -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result lastarg= save_ifs="$IFS"; IFS=',' for arg in $args; do IFS="$save_ifs" func_append_quoted lastarg "$arg" done IFS="$save_ifs" func_stripname ' ' '' "$lastarg" lastarg=$func_stripname_result # Add the arguments to base_compile. func_append base_compile " $lastarg" continue ;; *) # Accept the current argument as the source file. # The previous "srcfile" becomes the current argument. # lastarg="$srcfile" srcfile="$arg" ;; esac # case $arg ;; esac # case $arg_mode # Aesthetically quote the previous argument. func_append_quoted base_compile "$lastarg" done # for arg case $arg_mode in arg) func_fatal_error "you must specify an argument for -Xcompile" ;; target) func_fatal_error "you must specify a target with \`-o'" ;; *) # Get the name of the library object. test -z "$libobj" && { func_basename "$srcfile" libobj="$func_basename_result" } ;; esac # Recognize several different file suffixes. # If the user specifies -o file.o, it is replaced with file.lo case $libobj in *.[cCFSifmso] | \ *.ada | *.adb | *.ads | *.asm | \ *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) func_xform "$libobj" libobj=$func_xform_result ;; esac case $libobj in *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; *) func_fatal_error "cannot determine name of library object from \`$libobj'" ;; esac func_infer_tag $base_compile for arg in $later; do case $arg in -shared) test "$build_libtool_libs" != yes && \ func_fatal_configuration "can not build a shared library" build_old_libs=no continue ;; -static) build_libtool_libs=no build_old_libs=yes continue ;; -prefer-pic) pic_mode=yes continue ;; -prefer-non-pic) pic_mode=no continue ;; esac done func_quote_for_eval "$libobj" test "X$libobj" != "X$func_quote_for_eval_result" \ && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ && func_warning "libobj name \`$libobj' may not contain shell special characters." func_dirname_and_basename "$obj" "/" "" objname="$func_basename_result" xdir="$func_dirname_result" lobj=${xdir}$objdir/$objname test -z "$base_compile" && \ func_fatal_help "you must specify a compilation command" # Delete any leftover library objects. if test "$build_old_libs" = yes; then removelist="$obj $lobj $libobj ${libobj}T" else removelist="$lobj $libobj ${libobj}T" fi # On Cygwin there's no "real" PIC flag so we must build both object types case $host_os in cygwin* | mingw* | pw32* | os2* | cegcc*) pic_mode=default ;; esac if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c if test "$compiler_c_o" = no; then output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext} lockfile="$output_obj.lock" else output_obj= need_locks=no lockfile= fi # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file if test "$need_locks" = yes; then until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done elif test "$need_locks" = warn; then if test -f "$lockfile"; then $ECHO "\ *** ERROR, $lockfile exists and contains: `cat $lockfile 2>/dev/null` This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi func_append removelist " $output_obj" $ECHO "$srcfile" > "$lockfile" fi $opt_dry_run || $RM $removelist func_append removelist " $lockfile" trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 srcfile=$func_to_tool_file_result func_quote_for_eval "$srcfile" qsrcfile=$func_quote_for_eval_result # Only build a PIC object if we are building libtool libraries. if test "$build_libtool_libs" = yes; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile if test "$pic_mode" != no; then command="$base_compile $qsrcfile $pic_flag" else # Don't build PIC code command="$base_compile $qsrcfile" fi func_mkdir_p "$xdir$objdir" if test -z "$output_obj"; then # Place PIC objects in $objdir func_append command " -o $lobj" fi func_show_eval_locale "$command" \ 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' if test "$need_locks" = warn && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed, then go on to compile the next one if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then func_show_eval '$MV "$output_obj" "$lobj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi # Allow error messages only from the first compilation. if test "$suppress_opt" = yes; then suppress_output=' >/dev/null 2>&1' fi fi # Only build a position-dependent object if we build old libraries. if test "$build_old_libs" = yes; then if test "$pic_mode" != yes; then # Don't build PIC code command="$base_compile $qsrcfile$pie_flag" else command="$base_compile $qsrcfile $pic_flag" fi if test "$compiler_c_o" = yes; then func_append command " -o $obj" fi # Suppress compiler output if we already did a PIC compilation. func_append command "$suppress_output" func_show_eval_locale "$command" \ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' if test "$need_locks" = warn && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then func_show_eval '$MV "$output_obj" "$obj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi fi $opt_dry_run || { func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" # Unlock the critical section if it was locked if test "$need_locks" != no; then removelist=$lockfile $RM "$lockfile" fi } exit $EXIT_SUCCESS } $opt_help || { test "$opt_mode" = compile && func_mode_compile ${1+"$@"} } func_mode_help () { # We need to display help for each of the modes. case $opt_mode in "") # Generic help is extracted from the usage comments # at the start of this file. func_help ;; clean) $ECHO \ "Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; compile) $ECHO \ "Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE Compile a source file into a libtool library object. This mode accepts the following additional options: -o OUTPUT-FILE set the output file name to OUTPUT-FILE -no-suppress do not suppress compiler output for multiple passes -prefer-pic try to build PIC objects only -prefer-non-pic try to build non-PIC objects only -shared do not build a \`.o' file suitable for static linking -static only build a \`.o' file suitable for static linking -Wc,FLAG pass FLAG directly to the compiler COMPILE-COMMAND is a command to be used in creating a \`standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from SOURCEFILE, then substituting the C source code suffix \`.c' with the library object suffix, \`.lo'." ;; execute) $ECHO \ "Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... Automatically set library path, then run a program. This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path This mode sets the library path environment variable according to \`-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated into their corresponding uninstalled binary, and any of their required library directories are added to the library path. Then, COMMAND is executed, with ARGS as arguments." ;; finish) $ECHO \ "Usage: $progname [OPTION]... --mode=finish [LIBDIR]... Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use the \`--dry-run' option if you just want to see what would be executed." ;; install) $ECHO \ "Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be either the \`install' or \`cp' program. The following components of INSTALL-COMMAND are treated specially: -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." ;; link) $ECHO \ "Usage: $progname [OPTION]... --mode=link LINK-COMMAND... Link object files or libraries together to form another library, or to create an executable program. LINK-COMMAND is a command using the C compiler that you would use to create a program from several object files. The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible -bindir BINDIR specify path to binaries directory (for systems where libraries must be found in the PATH setting at runtime) -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE try to export only the symbols listed in SYMFILE -export-symbols-regex REGEX try to export only the symbols matching REGEX -LLIBDIR search LIBDIR for required installed libraries -lNAME OUTPUT-FILE requires the installed library libNAME -module build a library that can dlopened -no-fast-install disable the fast-install mode -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects -objectlist FILE Use a list of object files found in FILE to specify objects -precious-files-regex REGEX don't remove output files matching REGEX -release RELEASE specify package release information -rpath LIBDIR the created library will eventually be installed in LIBDIR -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries -shared only do dynamic linking of libtool libraries -shrext SUFFIX override the standard shared library file extension -static do not do any dynamic linking of uninstalled libtool libraries -static-libtool-libs do not do any dynamic linking of libtool libraries -version-info CURRENT[:REVISION[:AGE]] specify library version info [each variable defaults to 0] -weak LIBNAME declare that the target provides the LIBNAME interface -Wc,FLAG -Xcompiler FLAG pass linker-specific FLAG directly to the compiler -Wl,FLAG -Xlinker FLAG pass linker-specific FLAG directly to the linker -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) All other options (arguments beginning with \`-') are ignored. Every other argument is treated as a filename. Files ending in \`.la' are treated as uninstalled libtool libraries, other files are standard or library object files. If the OUTPUT-FILE ends in \`.la', then a libtool library is created, only library objects (\`.lo' files) may be specified, and \`-rpath' is required, except when creating a convenience library. If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created using \`ar' and \`ranlib', or on Windows using \`lib'. If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file is created, otherwise an executable program is created." ;; uninstall) $ECHO \ "Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; *) func_fatal_help "invalid operation mode \`$opt_mode'" ;; esac echo $ECHO "Try \`$progname --help' for more information about other modes." } # Now that we've collected a possible --mode arg, show help if necessary if $opt_help; then if test "$opt_help" = :; then func_mode_help else { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do func_mode_help done } | sed -n '1p; 2,$s/^Usage:/ or: /p' { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do echo func_mode_help done } | sed '1d /^When reporting/,/^Report/{ H d } $x /information about other modes/d /more detailed .*MODE/d s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' fi exit $? fi # func_mode_execute arg... func_mode_execute () { $opt_debug # The first argument is the command name. cmd="$nonopt" test -z "$cmd" && \ func_fatal_help "you must specify a COMMAND" # Handle -dlopen flags immediately. for file in $opt_dlopen; do test -f "$file" \ || func_fatal_help "\`$file' is not a file" dir= case $file in *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "\`$lib' is not a valid libtool archive" # Read the libtool library. dlname= library_names= func_source "$file" # Skip this library if it cannot be dlopened. if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && \ func_warning "\`$file' was not linked with \`-export-dynamic'" continue fi func_dirname "$file" "" "." dir="$func_dirname_result" if test -f "$dir/$objdir/$dlname"; then func_append dir "/$objdir" else if test ! -f "$dir/$dlname"; then func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" fi fi ;; *.lo) # Just add the directory containing the .lo file. func_dirname "$file" "" "." dir="$func_dirname_result" ;; *) func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` test -n "$absdir" && dir="$absdir" # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then eval "$shlibpath_var=\"\$dir\"" else eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" fi done # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. libtool_execute_magic="$magic" # Check if any of the arguments is a wrapper script. args= for file do case $file in -* | *.la | *.lo ) ;; *) # Do a test to see if this is really a libtool program. if func_ltwrapper_script_p "$file"; then func_source "$file" # Transform arg to wrapped name. file="$progdir/$program" elif func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" func_source "$func_ltwrapper_scriptname_result" # Transform arg to wrapped name. file="$progdir/$program" fi ;; esac # Quote arguments (to preserve shell metacharacters). func_append_quoted args "$file" done if test "X$opt_dry_run" = Xfalse; then if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" fi # Restore saved environment variables for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${save_$lt_var+set}\" = set; then $lt_var=\$save_$lt_var; export $lt_var else $lt_unset $lt_var fi" done # Now prepare to actually exec the command. exec_cmd="\$cmd$args" else # Display what would be done. if test -n "$shlibpath_var"; then eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" echo "export $shlibpath_var" fi $ECHO "$cmd$args" exit $EXIT_SUCCESS fi } test "$opt_mode" = execute && func_mode_execute ${1+"$@"} # func_mode_finish arg... func_mode_finish () { $opt_debug libs= libdirs= admincmds= for opt in "$nonopt" ${1+"$@"} do if test -d "$opt"; then func_append libdirs " $opt" elif test -f "$opt"; then if func_lalib_unsafe_p "$opt"; then func_append libs " $opt" else func_warning "\`$opt' is not a valid libtool archive" fi else func_fatal_error "invalid argument \`$opt'" fi done if test -n "$libs"; then if test -n "$lt_sysroot"; then sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" else sysroot_cmd= fi # Remove sysroot references if $opt_dry_run; then for lib in $libs; do echo "removing references to $lt_sysroot and \`=' prefixes from $lib" done else tmpdir=`func_mktempdir` for lib in $libs; do sed -e "${sysroot_cmd} s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ > $tmpdir/tmp-la mv -f $tmpdir/tmp-la $lib done ${RM}r "$tmpdir" fi fi if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. func_execute_cmds "$finish_cmds" 'admincmds="$admincmds '"$cmd"'"' fi if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" $opt_dry_run || eval "$cmds" || func_append admincmds " $cmds" fi done fi # Exit here if they wanted silent mode. $opt_silent && exit $EXIT_SUCCESS if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then echo "----------------------------------------------------------------------" echo "Libraries have been installed in:" for libdir in $libdirs; do $ECHO " $libdir" done echo echo "If you ever happen to want to link against installed libraries" echo "in a given directory, LIBDIR, you must either use libtool, and" echo "specify the full pathname of the library, or use the \`-LLIBDIR'" echo "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then echo " - add LIBDIR to the \`$shlibpath_var' environment variable" echo " during execution" fi if test -n "$runpath_var"; then echo " - add LIBDIR to the \`$runpath_var' environment variable" echo " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" $ECHO " - use the \`$flag' linker flag" fi if test -n "$admincmds"; then $ECHO " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" fi echo echo "See any operating system documentation about shared libraries for" case $host in solaris2.[6789]|solaris2.1[0-9]) echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" echo "pages." ;; *) echo "more information, such as the ld(1) and ld.so(8) manual pages." ;; esac echo "----------------------------------------------------------------------" fi exit $EXIT_SUCCESS } test "$opt_mode" = finish && func_mode_finish ${1+"$@"} # func_mode_install arg... func_mode_install () { $opt_debug # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || # Allow the use of GNU shtool's install command. case $nonopt in *shtool*) :;; *) false;; esac; then # Aesthetically quote it. func_quote_for_eval "$nonopt" install_prog="$func_quote_for_eval_result " arg=$1 shift else install_prog= arg=$nonopt fi # The real first argument should be the name of the installation program. # Aesthetically quote it. func_quote_for_eval "$arg" func_append install_prog "$func_quote_for_eval_result" install_shared_prog=$install_prog case " $install_prog " in *[\\\ /]cp\ *) install_cp=: ;; *) install_cp=false ;; esac # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=no stripme= no_mode=: for arg do arg2= if test -n "$dest"; then func_append files " $dest" dest=$arg continue fi case $arg in -d) isdir=yes ;; -f) if $install_cp; then :; else prev=$arg fi ;; -g | -m | -o) prev=$arg ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then if test "x$prev" = x-m && test -n "$install_override_mode"; then arg2=$install_override_mode no_mode=false fi prev= else dest=$arg continue fi ;; esac # Aesthetically quote the argument. func_quote_for_eval "$arg" func_append install_prog " $func_quote_for_eval_result" if test -n "$arg2"; then func_quote_for_eval "$arg2" fi func_append install_shared_prog " $func_quote_for_eval_result" done test -z "$install_prog" && \ func_fatal_help "you must specify an install program" test -n "$prev" && \ func_fatal_help "the \`$prev' option requires an argument" if test -n "$install_override_mode" && $no_mode; then if $install_cp; then :; else func_quote_for_eval "$install_override_mode" func_append install_shared_prog " -m $func_quote_for_eval_result" fi fi if test -z "$files"; then if test -z "$dest"; then func_fatal_help "no file or destination specified" else func_fatal_help "you must specify a destination" fi fi # Strip any trailing slash from the destination. func_stripname '' '/' "$dest" dest=$func_stripname_result # Check to see that the destination is a directory. test -d "$dest" && isdir=yes if test "$isdir" = yes; then destdir="$dest" destname= else func_dirname_and_basename "$dest" "" "." destdir="$func_dirname_result" destname="$func_basename_result" # Not a directory, so check to see that there is only one file specified. set dummy $files; shift test "$#" -gt 1 && \ func_fatal_help "\`$dest' is not a directory" fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) for file in $files; do case $file in *.lo) ;; *) func_fatal_help "\`$destdir' must be an absolute directory name" ;; esac done ;; esac # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" staticlibs= future_libdirs= current_libdirs= for file in $files; do # Do each installation. case $file in *.$libext) # Do the static libraries later. func_append staticlibs " $file" ;; *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "\`$file' is not a valid libtool archive" library_names= old_library= relink_command= func_source "$file" # Add the libdir to current_libdirs if it is the destination. if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; *) func_append current_libdirs " $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; *) func_append future_libdirs " $libdir" ;; esac fi func_dirname "$file" "/" "" dir="$func_dirname_result" func_append dir "$objdir" if test -n "$relink_command"; then # Determine the prefix the user has applied to our future dir. inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` # Don't allow the user to place us outside of our expected # location b/c this prevents finding dependent libraries that # are installed to the same prefix. # At present, this check doesn't affect windows .dll's that # are installed into $libdir/../bin (currently, that works fine) # but it's something to keep an eye on. test "$inst_prefix_dir" = "$destdir" && \ func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` else relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` fi func_warning "relinking \`$file'" func_show_eval "$relink_command" \ 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' fi # See the names of the shared library. set dummy $library_names; shift if test -n "$1"; then realname="$1" shift srcname="$realname" test -n "$relink_command" && srcname="$realname"T # Install the shared library and build the symlinks. func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ 'exit $?' tstripme="$stripme" case $host_os in cygwin* | mingw* | pw32* | cegcc*) case $realname in *.dll.a) tstripme="" ;; esac ;; esac if test -n "$tstripme" && test -n "$striplib"; then func_show_eval "$striplib $destdir/$realname" 'exit $?' fi if test "$#" -gt 0; then # Delete the old symlinks, and create new ones. # Try `ln -sf' first, because the `ln' binary might depend on # the symlink we replace! Solaris /bin/ln does not understand -f, # so we also need to try rm && ln -s. for linkname do test "$linkname" != "$realname" \ && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" done fi # Do each command in the postinstall commands. lib="$destdir/$realname" func_execute_cmds "$postinstall_cmds" 'exit $?' fi # Install the pseudo-library for information purposes. func_basename "$file" name="$func_basename_result" instname="$dir/$name"i func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' # Maybe install the static library, too. test -n "$old_library" && func_append staticlibs " $dir/$old_library" ;; *.lo) # Install (i.e. copy) a libtool object. # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else func_basename "$file" destfile="$func_basename_result" destfile="$destdir/$destfile" fi # Deduce the name of the destination old-style object file. case $destfile in *.lo) func_lo2o "$destfile" staticdest=$func_lo2o_result ;; *.$objext) staticdest="$destfile" destfile= ;; *) func_fatal_help "cannot copy a libtool object to \`$destfile'" ;; esac # Install the libtool object if requested. test -n "$destfile" && \ func_show_eval "$install_prog $file $destfile" 'exit $?' # Install the old object if enabled. if test "$build_old_libs" = yes; then # Deduce the name of the old-style object file. func_lo2o "$file" staticobj=$func_lo2o_result func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' fi exit $EXIT_SUCCESS ;; *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else func_basename "$file" destfile="$func_basename_result" destfile="$destdir/$destfile" fi # If the file is missing, and there is a .exe on the end, strip it # because it is most likely a libtool script we actually want to # install stripped_ext="" case $file in *.exe) if test ! -f "$file"; then func_stripname '' '.exe' "$file" file=$func_stripname_result stripped_ext=".exe" fi ;; esac # Do a test to see if this is really a libtool program. case $host in *cygwin* | *mingw*) if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" wrapper=$func_ltwrapper_scriptname_result else func_stripname '' '.exe' "$file" wrapper=$func_stripname_result fi ;; *) wrapper=$file ;; esac if func_ltwrapper_script_p "$wrapper"; then notinst_deplibs= relink_command= func_source "$wrapper" # Check the variables that should have been set. test -z "$generated_by_libtool_version" && \ func_fatal_error "invalid libtool wrapper script \`$wrapper'" finalize=yes for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then func_source "$lib" fi libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test if test -n "$libdir" && test ! -f "$libfile"; then func_warning "\`$lib' has not been installed in \`$libdir'" finalize=no fi done relink_command= func_source "$wrapper" outputname= if test "$fast_install" = no && test -n "$relink_command"; then $opt_dry_run || { if test "$finalize" = yes; then tmpdir=`func_mktempdir` func_basename "$file$stripped_ext" file="$func_basename_result" outputname="$tmpdir/$file" # Replace the output file specification. relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` $opt_silent || { func_quote_for_expand "$relink_command" eval "func_echo $func_quote_for_expand_result" } if eval "$relink_command"; then : else func_error "error: relink \`$file' with the above command before installing it" $opt_dry_run || ${RM}r "$tmpdir" continue fi file="$outputname" else func_warning "cannot relink \`$file'" fi } else # Install the binary that we compiled earlier. file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` fi fi # remove .exe since cygwin /usr/bin/install will append another # one anyway case $install_prog,$host in */usr/bin/install*,*cygwin*) case $file:$destfile in *.exe:*.exe) # this is ok ;; *.exe:*) destfile=$destfile.exe ;; *:*.exe) func_stripname '' '.exe' "$destfile" destfile=$func_stripname_result ;; esac ;; esac func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' $opt_dry_run || if test -n "$outputname"; then ${RM}r "$tmpdir" fi ;; esac done for file in $staticlibs; do func_basename "$file" name="$func_basename_result" # Set up the ranlib parameters. oldlib="$destdir/$name" func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result func_show_eval "$install_prog \$file \$oldlib" 'exit $?' if test -n "$stripme" && test -n "$old_striplib"; then func_show_eval "$old_striplib $tool_oldlib" 'exit $?' fi # Do each command in the postinstall commands. func_execute_cmds "$old_postinstall_cmds" 'exit $?' done test -n "$future_libdirs" && \ func_warning "remember to run \`$progname --finish$future_libdirs'" if test -n "$current_libdirs"; then # Maybe just do a dry run. $opt_dry_run && current_libdirs=" -n$current_libdirs" exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' else exit $EXIT_SUCCESS fi } test "$opt_mode" = install && func_mode_install ${1+"$@"} # func_generate_dlsyms outputname originator pic_p # Extract symbols from dlprefiles and create ${outputname}S.o with # a dlpreopen symbol table. func_generate_dlsyms () { $opt_debug my_outputname="$1" my_originator="$2" my_pic_p="${3-no}" my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` my_dlsyms= if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then if test -n "$NM" && test -n "$global_symbol_pipe"; then my_dlsyms="${my_outputname}S.c" else func_error "not configured to extract global symbols from dlpreopened files" fi fi if test -n "$my_dlsyms"; then case $my_dlsyms in "") ;; *.c) # Discover the nlist of each of the dlfiles. nlist="$output_objdir/${my_outputname}.nm" func_show_eval "$RM $nlist ${nlist}S ${nlist}T" # Parse the name list into a source file. func_verbose "creating $output_objdir/$my_dlsyms" $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ /* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ /* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ #ifdef __cplusplus extern \"C\" { #endif #if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) #pragma GCC diagnostic ignored \"-Wstrict-prototypes\" #endif /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif /* External symbol declarations for the compiler. */\ " if test "$dlself" = yes; then func_verbose "generating symbol list for \`$output'" $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` for progfile in $progfiles; do func_to_tool_file "$progfile" func_convert_file_msys_to_w32 func_verbose "extracting global C symbols from \`$func_to_tool_file_result'" $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then $opt_dry_run || { eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi if test -n "$export_symbols_regex"; then $opt_dry_run || { eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi # Prepare the list of exported symbols if test -z "$export_symbols"; then export_symbols="$output_objdir/$outputname.exp" $opt_dry_run || { $RM $export_symbols eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' ;; esac } else $opt_dry_run || { eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' ;; esac } fi fi for dlprefile in $dlprefiles; do func_verbose "extracting global C symbols from \`$dlprefile'" func_basename "$dlprefile" name="$func_basename_result" case $host in *cygwin* | *mingw* | *cegcc* ) # if an import library, we need to obtain dlname if func_win32_import_lib_p "$dlprefile"; then func_tr_sh "$dlprefile" eval "curr_lafile=\$libfile_$func_tr_sh_result" dlprefile_dlbasename="" if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then # Use subshell, to avoid clobbering current variable values dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` if test -n "$dlprefile_dlname" ; then func_basename "$dlprefile_dlname" dlprefile_dlbasename="$func_basename_result" else # no lafile. user explicitly requested -dlpreopen . $sharedlib_from_linklib_cmd "$dlprefile" dlprefile_dlbasename=$sharedlib_from_linklib_result fi fi $opt_dry_run || { if test -n "$dlprefile_dlbasename" ; then eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' else func_warning "Could not compute DLL name from $name" eval '$ECHO ": $name " >> "$nlist"' fi func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" } else # not an import lib $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } fi ;; *) $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } ;; esac done $opt_dry_run || { # Make sure we have at least an empty file. test -f "$nlist" || : > "$nlist" if test -n "$exclude_expsyms"; then $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T $MV "$nlist"T "$nlist" fi # Try sorting and uniquifying the output. if $GREP -v "^: " < "$nlist" | if sort -k 3 /dev/null 2>&1; then sort -k 3 else sort +2 fi | uniq > "$nlist"S; then : else $GREP -v "^: " < "$nlist" > "$nlist"S fi if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' else echo '/* NONE */' >> "$output_objdir/$my_dlsyms" fi echo >> "$output_objdir/$my_dlsyms" "\ /* The mapping between symbol names and symbols. */ typedef struct { const char *name; void *address; } lt_dlsymlist; extern LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[]; LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[] = {\ { \"$my_originator\", (void *) 0 }," case $need_lib_prefix in no) eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; *) eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; esac echo >> "$output_objdir/$my_dlsyms" "\ {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_${my_prefix}_LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " } # !$opt_dry_run pic_flag_for_symtable= case "$compile_command " in *" -static "*) ;; *) case $host in # compiling the symbol table file with pic_flag works around # a FreeBSD bug that causes programs to crash when -lm is # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; *-*-hpux*) pic_flag_for_symtable=" $pic_flag" ;; *) if test "X$my_pic_p" != Xno; then pic_flag_for_symtable=" $pic_flag" fi ;; esac ;; esac symtab_cflags= for arg in $LTCFLAGS; do case $arg in -pie | -fpie | -fPIE) ;; *) func_append symtab_cflags " $arg" ;; esac done # Now compile the dynamic symbol file. func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' # Clean up the generated files. func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' # Transform the symbol file into the correct name. symfileobj="$output_objdir/${my_outputname}S.$objext" case $host in *cygwin* | *mingw* | *cegcc* ) if test -f "$output_objdir/$my_outputname.def"; then compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` else compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` fi ;; *) compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` ;; esac ;; *) func_fatal_error "unknown suffix for \`$my_dlsyms'" ;; esac else # We keep going just in case the user didn't refer to # lt_preloaded_symbols. The linker will fail if global_symbol_pipe # really was required. # Nullify the symbol file. compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` fi } # func_win32_libid arg # return the library type of file 'arg' # # Need a lot of goo to handle *both* DLLs and import libs # Has to be a shell function in order to 'eat' the argument # that is supplied when $file_magic_command is called. # Despite the name, also deal with 64 bit binaries. func_win32_libid () { $opt_debug win32_libid_type="unknown" win32_fileres=`file -L $1 2>/dev/null` case $win32_fileres in *ar\ archive\ import\ library*) # definitely import win32_libid_type="x86 archive import" ;; *ar\ archive*) # could be an import, or static # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then func_to_tool_file "$1" func_convert_file_msys_to_w32 win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | $SED -n -e ' 1,100{ / I /{ s,.*,import, p q } }'` case $win32_nmres in import*) win32_libid_type="x86 archive import";; *) win32_libid_type="x86 archive static";; esac fi ;; *DLL*) win32_libid_type="x86 DLL" ;; *executable*) # but shell scripts are "executable" too... case $win32_fileres in *MS\ Windows\ PE\ Intel*) win32_libid_type="x86 DLL" ;; esac ;; esac $ECHO "$win32_libid_type" } # func_cygming_dll_for_implib ARG # # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib () { $opt_debug sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` } # func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs # # The is the core of a fallback implementation of a # platform-specific function to extract the name of the # DLL associated with the specified import library LIBNAME. # # SECTION_NAME is either .idata$6 or .idata$7, depending # on the platform and compiler that created the implib. # # Echos the name of the DLL associated with the # specified import library. func_cygming_dll_for_implib_fallback_core () { $opt_debug match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` $OBJDUMP -s --section "$1" "$2" 2>/dev/null | $SED '/^Contents of section '"$match_literal"':/{ # Place marker at beginning of archive member dllname section s/.*/====MARK====/ p d } # These lines can sometimes be longer than 43 characters, but # are always uninteresting /:[ ]*file format pe[i]\{,1\}-/d /^In archive [^:]*:/d # Ensure marker is printed /^====MARK====/p # Remove all lines with less than 43 characters /^.\{43\}/!d # From remaining lines, remove first 43 characters s/^.\{43\}//' | $SED -n ' # Join marker and all lines until next marker into a single line /^====MARK====/ b para H $ b para b :para x s/\n//g # Remove the marker s/^====MARK====// # Remove trailing dots and whitespace s/[\. \t]*$// # Print /./p' | # we now have a list, one entry per line, of the stringified # contents of the appropriate section of all members of the # archive which possess that section. Heuristic: eliminate # all those which have a first or second character that is # a '.' (that is, objdump's representation of an unprintable # character.) This should work for all archives with less than # 0x302f exports -- but will fail for DLLs whose name actually # begins with a literal '.' or a single character followed by # a '.'. # # Of those that remain, print the first one. $SED -e '/^\./d;/^.\./d;q' } # func_cygming_gnu_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is a GNU/binutils-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_gnu_implib_p () { $opt_debug func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` test -n "$func_cygming_gnu_implib_tmp" } # func_cygming_ms_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is an MS-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_ms_implib_p () { $opt_debug func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` test -n "$func_cygming_ms_implib_tmp" } # func_cygming_dll_for_implib_fallback ARG # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # # This fallback implementation is for use when $DLLTOOL # does not support the --identify-strict option. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib_fallback () { $opt_debug if func_cygming_gnu_implib_p "$1" ; then # binutils import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` elif func_cygming_ms_implib_p "$1" ; then # ms-generated import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` else # unknown sharedlib_from_linklib_result="" fi } # func_extract_an_archive dir oldlib func_extract_an_archive () { $opt_debug f_ex_an_ar_dir="$1"; shift f_ex_an_ar_oldlib="$1" if test "$lock_old_archive_extraction" = yes; then lockfile=$f_ex_an_ar_oldlib.lock until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done fi func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ 'stat=$?; rm -f "$lockfile"; exit $stat' if test "$lock_old_archive_extraction" = yes; then $opt_dry_run || rm -f "$lockfile" fi if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then : else func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" fi } # func_extract_archives gentop oldlib ... func_extract_archives () { $opt_debug my_gentop="$1"; shift my_oldlibs=${1+"$@"} my_oldobjs="" my_xlib="" my_xabs="" my_xdir="" for my_xlib in $my_oldlibs; do # Extract the objects. case $my_xlib in [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; *) my_xabs=`pwd`"/$my_xlib" ;; esac func_basename "$my_xlib" my_xlib="$func_basename_result" my_xlib_u=$my_xlib while :; do case " $extracted_archives " in *" $my_xlib_u "*) func_arith $extracted_serial + 1 extracted_serial=$func_arith_result my_xlib_u=lt$extracted_serial-$my_xlib ;; *) break ;; esac done extracted_archives="$extracted_archives $my_xlib_u" my_xdir="$my_gentop/$my_xlib_u" func_mkdir_p "$my_xdir" case $host in *-darwin*) func_verbose "Extracting $my_xabs" # Do not bother doing anything if just a dry run $opt_dry_run || { darwin_orig_dir=`pwd` cd $my_xdir || exit $? darwin_archive=$my_xabs darwin_curdir=`pwd` darwin_base_archive=`basename "$darwin_archive"` darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` if test -n "$darwin_arches"; then darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` darwin_arch= func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" for darwin_arch in $darwin_arches ; do func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" func_extract_an_archive "`pwd`" "${darwin_base_archive}" cd "$darwin_curdir" $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" done # $darwin_arches ## Okay now we've a bunch of thin objects, gotta fatten them up :) darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` darwin_file= darwin_files= for darwin_file in $darwin_filelist; do darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` $LIPO -create -output "$darwin_file" $darwin_files done # $darwin_filelist $RM -rf unfat-$$ cd "$darwin_orig_dir" else cd $darwin_orig_dir func_extract_an_archive "$my_xdir" "$my_xabs" fi # $darwin_arches } # !$opt_dry_run ;; *) func_extract_an_archive "$my_xdir" "$my_xabs" ;; esac my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` done func_extract_archives_result="$my_oldobjs" } # func_emit_wrapper [arg=no] # # Emit a libtool wrapper script on stdout. # Don't directly open a file because we may want to # incorporate the script contents within a cygwin/mingw # wrapper executable. Must ONLY be called from within # func_mode_link because it depends on a number of variables # set therein. # # ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR # variable will take. If 'yes', then the emitted script # will assume that the directory in which it is stored is # the $objdir directory. This is a cygwin/mingw-specific # behavior. func_emit_wrapper () { func_emit_wrapper_arg1=${1-no} $ECHO "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. # # This wrapper script should never be moved out of the build directory. # If it is, it will not operate correctly. # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='$sed_quote_subst' # Be Bourne compatible if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH relink_command=\"$relink_command\" # This environment variable determines our operation mode. if test \"\$libtool_install_magic\" = \"$magic\"; then # install mode needs the following variables: generated_by_libtool_version='$macro_version' notinst_deplibs='$notinst_deplibs' else # When we are sourced in execute mode, \$file and \$ECHO are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then file=\"\$0\"" qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` $ECHO "\ # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } ECHO=\"$qECHO\" fi # Very basic option parsing. These options are (a) specific to # the libtool wrapper, (b) are identical between the wrapper # /script/ and the wrapper /executable/ which is used only on # windows platforms, and (c) all begin with the string "--lt-" # (application programs are unlikely to have options which match # this pattern). # # There are only two supported options: --lt-debug and # --lt-dump-script. There is, deliberately, no --lt-help. # # The first argument to this parsing function should be the # script's $0 value, followed by "$@". lt_option_debug= func_parse_lt_options () { lt_script_arg0=\$0 shift for lt_opt do case \"\$lt_opt\" in --lt-debug) lt_option_debug=1 ;; --lt-dump-script) lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` cat \"\$lt_dump_D/\$lt_dump_F\" exit 0 ;; --lt-*) \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 exit 1 ;; esac done # Print the debug banner immediately: if test -n \"\$lt_option_debug\"; then echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2 fi } # Used when --lt-debug. Prints its arguments to stdout # (redirection is the responsibility of the caller) func_lt_dump_args () { lt_dump_args_N=1; for lt_arg do \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\" lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` done } # Core function for launching the target application func_exec_program_core () { " case $host in # Backslashes separate directories on plain windows *-*-mingw | *-*-os2* | *-cegcc*) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} " ;; *) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir/\$program\" \${1+\"\$@\"} " ;; esac $ECHO "\ \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 exit 1 } # A function to encapsulate launching the target application # Strips options in the --lt-* namespace from \$@ and # launches target application with the remaining arguments. func_exec_program () { case \" \$* \" in *\\ --lt-*) for lt_wr_arg do case \$lt_wr_arg in --lt-*) ;; *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; esac shift done ;; esac func_exec_program_core \${1+\"\$@\"} } # Parse options func_parse_lt_options \"\$0\" \${1+\"\$@\"} # Find the directory that this script lives in. thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` while test -n \"\$file\"; do destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then case \"\$destdir\" in [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; *) thisdir=\"\$thisdir/\$destdir\" ;; esac fi file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` done # Usually 'no', except on cygwin/mingw when embedded into # the cwrapper. WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then # special case for '.' if test \"\$thisdir\" = \".\"; then thisdir=\`pwd\` fi # remove .libs from thisdir case \"\$thisdir\" in *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; $objdir ) thisdir=. ;; esac fi # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test "$fast_install" = yes; then $ECHO "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" if test ! -d \"\$progdir\"; then $MKDIR \"\$progdir\" else $RM \"\$progdir/\$file\" fi" $ECHO "\ # relink executable if necessary if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else $ECHO \"\$relink_command_output\" >&2 $RM \"\$progdir/\$file\" exit 1 fi fi $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $RM \"\$progdir/\$program\"; $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } $RM \"\$progdir/\$file\" fi" else $ECHO "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi $ECHO "\ if test -f \"\$progdir/\$program\"; then" # fixup the dll searchpath if we need to. # # Fix the DLL searchpath if we need to. Do this before prepending # to shlibpath, because on Windows, both are PATH and uninstalled # libraries must come first. if test -n "$dllsearchpath"; then $ECHO "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi # Export our shlibpath_var if we have one. if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $ECHO "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` export $shlibpath_var " fi $ECHO "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. func_exec_program \${1+\"\$@\"} fi else # The program doesn't exist. \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 fi fi\ " } # func_emit_cwrapperexe_src # emit the source code for a wrapper executable on stdout # Must ONLY be called from within func_mode_link because # it depends on a number of variable set therein. func_emit_cwrapperexe_src () { cat < #include #ifdef _MSC_VER # include # include # include #else # include # include # ifdef __CYGWIN__ # include # endif #endif #include #include #include #include #include #include #include #include /* declarations of non-ANSI functions */ #if defined(__MINGW32__) # ifdef __STRICT_ANSI__ int _putenv (const char *); # endif #elif defined(__CYGWIN__) # ifdef __STRICT_ANSI__ char *realpath (const char *, char *); int putenv (char *); int setenv (const char *, const char *, int); # endif /* #elif defined (other platforms) ... */ #endif /* portability defines, excluding path handling macros */ #if defined(_MSC_VER) # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv # define S_IXUSR _S_IEXEC # ifndef _INTPTR_T_DEFINED # define _INTPTR_T_DEFINED # define intptr_t int # endif #elif defined(__MINGW32__) # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv #elif defined(__CYGWIN__) # define HAVE_SETENV # define FOPEN_WB "wb" /* #elif defined (other platforms) ... */ #endif #if defined(PATH_MAX) # define LT_PATHMAX PATH_MAX #elif defined(MAXPATHLEN) # define LT_PATHMAX MAXPATHLEN #else # define LT_PATHMAX 1024 #endif #ifndef S_IXOTH # define S_IXOTH 0 #endif #ifndef S_IXGRP # define S_IXGRP 0 #endif /* path handling portability macros */ #ifndef DIR_SEPARATOR # define DIR_SEPARATOR '/' # define PATH_SEPARATOR ':' #endif #if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ defined (__OS2__) # define HAVE_DOS_BASED_FILE_SYSTEM # define FOPEN_WB "wb" # ifndef DIR_SEPARATOR_2 # define DIR_SEPARATOR_2 '\\' # endif # ifndef PATH_SEPARATOR_2 # define PATH_SEPARATOR_2 ';' # endif #endif #ifndef DIR_SEPARATOR_2 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) #else /* DIR_SEPARATOR_2 */ # define IS_DIR_SEPARATOR(ch) \ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) #endif /* DIR_SEPARATOR_2 */ #ifndef PATH_SEPARATOR_2 # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) #else /* PATH_SEPARATOR_2 */ # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) #endif /* PATH_SEPARATOR_2 */ #ifndef FOPEN_WB # define FOPEN_WB "w" #endif #ifndef _O_BINARY # define _O_BINARY 0 #endif #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ if (stale) { free ((void *) stale); stale = 0; } \ } while (0) #if defined(LT_DEBUGWRAPPER) static int lt_debug = 1; #else static int lt_debug = 0; #endif const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ void *xmalloc (size_t num); char *xstrdup (const char *string); const char *base_name (const char *name); char *find_executable (const char *wrapper); char *chase_symlinks (const char *pathspec); int make_executable (const char *path); int check_executable (const char *path); char *strendzap (char *str, const char *pat); void lt_debugprintf (const char *file, int line, const char *fmt, ...); void lt_fatal (const char *file, int line, const char *message, ...); static const char *nonnull (const char *s); static const char *nonempty (const char *s); void lt_setenv (const char *name, const char *value); char *lt_extend_str (const char *orig_value, const char *add, int to_end); void lt_update_exe_path (const char *name, const char *value); void lt_update_lib_path (const char *name, const char *value); char **prepare_spawn (char **argv); void lt_dump_script (FILE *f); EOF cat <= 0) && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) return 1; else return 0; } int make_executable (const char *path) { int rval = 0; struct stat st; lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", nonempty (path)); if ((!path) || (!*path)) return 0; if (stat (path, &st) >= 0) { rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); } return rval; } /* Searches for the full path of the wrapper. Returns newly allocated full path name if found, NULL otherwise Does not chase symlinks, even on platforms that support them. */ char * find_executable (const char *wrapper) { int has_slash = 0; const char *p; const char *p_next; /* static buffer for getcwd */ char tmp[LT_PATHMAX + 1]; int tmp_len; char *concat_name; lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", nonempty (wrapper)); if ((wrapper == NULL) || (*wrapper == '\0')) return NULL; /* Absolute path? */ #if defined (HAVE_DOS_BASED_FILE_SYSTEM) if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } else { #endif if (IS_DIR_SEPARATOR (wrapper[0])) { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } #if defined (HAVE_DOS_BASED_FILE_SYSTEM) } #endif for (p = wrapper; *p; p++) if (*p == '/') { has_slash = 1; break; } if (!has_slash) { /* no slashes; search PATH */ const char *path = getenv ("PATH"); if (path != NULL) { for (p = path; *p; p = p_next) { const char *q; size_t p_len; for (q = p; *q; q++) if (IS_PATH_SEPARATOR (*q)) break; p_len = q - p; p_next = (*q == '\0' ? q : q + 1); if (p_len == 0) { /* empty path: current directory */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); } else { concat_name = XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, p, p_len); concat_name[p_len] = '/'; strcpy (concat_name + p_len + 1, wrapper); } if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } } /* not found in PATH; assume curdir */ } /* Relative path | not found in path: prepend cwd */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); return NULL; } char * chase_symlinks (const char *pathspec) { #ifndef S_ISLNK return xstrdup (pathspec); #else char buf[LT_PATHMAX]; struct stat s; char *tmp_pathspec = xstrdup (pathspec); char *p; int has_symlinks = 0; while (strlen (tmp_pathspec) && !has_symlinks) { lt_debugprintf (__FILE__, __LINE__, "checking path component for symlinks: %s\n", tmp_pathspec); if (lstat (tmp_pathspec, &s) == 0) { if (S_ISLNK (s.st_mode) != 0) { has_symlinks = 1; break; } /* search backwards for last DIR_SEPARATOR */ p = tmp_pathspec + strlen (tmp_pathspec) - 1; while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) p--; if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) { /* no more DIR_SEPARATORS left */ break; } *p = '\0'; } else { lt_fatal (__FILE__, __LINE__, "error accessing file \"%s\": %s", tmp_pathspec, nonnull (strerror (errno))); } } XFREE (tmp_pathspec); if (!has_symlinks) { return xstrdup (pathspec); } tmp_pathspec = realpath (pathspec, buf); if (tmp_pathspec == 0) { lt_fatal (__FILE__, __LINE__, "could not follow symlinks for %s", pathspec); } return xstrdup (tmp_pathspec); #endif } char * strendzap (char *str, const char *pat) { size_t len, patlen; assert (str != NULL); assert (pat != NULL); len = strlen (str); patlen = strlen (pat); if (patlen <= len) { str += len - patlen; if (strcmp (str, pat) == 0) *str = '\0'; } return str; } void lt_debugprintf (const char *file, int line, const char *fmt, ...) { va_list args; if (lt_debug) { (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); va_start (args, fmt); (void) vfprintf (stderr, fmt, args); va_end (args); } } static void lt_error_core (int exit_status, const char *file, int line, const char *mode, const char *message, va_list ap) { fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); vfprintf (stderr, message, ap); fprintf (stderr, ".\n"); if (exit_status >= 0) exit (exit_status); } void lt_fatal (const char *file, int line, const char *message, ...) { va_list ap; va_start (ap, message); lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); va_end (ap); } static const char * nonnull (const char *s) { return s ? s : "(null)"; } static const char * nonempty (const char *s) { return (s && !*s) ? "(empty)" : nonnull (s); } void lt_setenv (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_setenv) setting '%s' to '%s'\n", nonnull (name), nonnull (value)); { #ifdef HAVE_SETENV /* always make a copy, for consistency with !HAVE_SETENV */ char *str = xstrdup (value); setenv (name, str, 1); #else int len = strlen (name) + 1 + strlen (value) + 1; char *str = XMALLOC (char, len); sprintf (str, "%s=%s", name, value); if (putenv (str) != EXIT_SUCCESS) { XFREE (str); } #endif } } char * lt_extend_str (const char *orig_value, const char *add, int to_end) { char *new_value; if (orig_value && *orig_value) { int orig_value_len = strlen (orig_value); int add_len = strlen (add); new_value = XMALLOC (char, add_len + orig_value_len + 1); if (to_end) { strcpy (new_value, orig_value); strcpy (new_value + orig_value_len, add); } else { strcpy (new_value, add); strcpy (new_value + add_len, orig_value); } } else { new_value = xstrdup (add); } return new_value; } void lt_update_exe_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); /* some systems can't cope with a ':'-terminated path #' */ int len = strlen (new_value); while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) { new_value[len-1] = '\0'; } lt_setenv (name, new_value); XFREE (new_value); } } void lt_update_lib_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); lt_setenv (name, new_value); XFREE (new_value); } } EOF case $host_os in mingw*) cat <<"EOF" /* Prepares an argument vector before calling spawn(). Note that spawn() does not by itself call the command interpreter (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&v); v.dwPlatformId == VER_PLATFORM_WIN32_NT; }) ? "cmd.exe" : "command.com"). Instead it simply concatenates the arguments, separated by ' ', and calls CreateProcess(). We must quote the arguments since Win32 CreateProcess() interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a special way: - Space and tab are interpreted as delimiters. They are not treated as delimiters if they are surrounded by double quotes: "...". - Unescaped double quotes are removed from the input. Their only effect is that within double quotes, space and tab are treated like normal characters. - Backslashes not followed by double quotes are not special. - But 2*n+1 backslashes followed by a double quote become n backslashes followed by a double quote (n >= 0): \" -> " \\\" -> \" \\\\\" -> \\" */ #define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" #define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" char ** prepare_spawn (char **argv) { size_t argc; char **new_argv; size_t i; /* Count number of arguments. */ for (argc = 0; argv[argc] != NULL; argc++) ; /* Allocate new argument vector. */ new_argv = XMALLOC (char *, argc + 1); /* Put quoted arguments into the new argument vector. */ for (i = 0; i < argc; i++) { const char *string = argv[i]; if (string[0] == '\0') new_argv[i] = xstrdup ("\"\""); else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) { int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); size_t length; unsigned int backslashes; const char *s; char *quoted_string; char *p; length = 0; backslashes = 0; if (quote_around) length++; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') length += backslashes + 1; length++; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) length += backslashes + 1; quoted_string = XMALLOC (char, length + 1); p = quoted_string; backslashes = 0; if (quote_around) *p++ = '"'; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') { unsigned int j; for (j = backslashes + 1; j > 0; j--) *p++ = '\\'; } *p++ = c; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) { unsigned int j; for (j = backslashes; j > 0; j--) *p++ = '\\'; *p++ = '"'; } *p = '\0'; new_argv[i] = quoted_string; } else new_argv[i] = (char *) string; } new_argv[argc] = NULL; return new_argv; } EOF ;; esac cat <<"EOF" void lt_dump_script (FILE* f) { EOF func_emit_wrapper yes | $SED -n -e ' s/^\(.\{79\}\)\(..*\)/\1\ \2/ h s/\([\\"]\)/\\\1/g s/$/\\n/ s/\([^\n]*\).*/ fputs ("\1", f);/p g D' cat <<"EOF" } EOF } # end: func_emit_cwrapperexe_src # func_win32_import_lib_p ARG # True if ARG is an import lib, as indicated by $file_magic_cmd func_win32_import_lib_p () { $opt_debug case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in *import*) : ;; *) false ;; esac } # func_mode_link arg... func_mode_link () { $opt_debug case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out # which system we are compiling for in order to pass an extra # flag for every libtool invocation. # allow_undefined=no # FIXME: Unfortunately, there are problems with the above when trying # to make a dll which has undefined symbols, in which case not # even a static library is built. For now, we need to specify # -no-undefined on the libtool link line when we can be certain # that all symbols are satisfied, otherwise we get a static library. allow_undefined=yes ;; *) allow_undefined=yes ;; esac libtool_args=$nonopt base_compile="$nonopt $@" compile_command=$nonopt finalize_command=$nonopt compile_rpath= finalize_rpath= compile_shlibpath= finalize_shlibpath= convenience= old_convenience= deplibs= old_deplibs= compiler_flags= linker_flags= dllsearchpath= lib_search_path=`pwd` inst_prefix_dir= new_inherited_linker_flags= avoid_version=no bindir= dlfiles= dlprefiles= dlself=no export_dynamic=no export_symbols= export_symbols_regex= generated= libobjs= ltlibs= module=no no_install=no objs= non_pic_objects= precious_files_regex= prefer_static_libs=no preload=no prev= prevarg= release= rpath= xrpath= perm_rpath= temp_rpath= thread_safe=no vinfo= vinfo_number=no weak_libs= single_module="${wl}-single_module" func_infer_tag $base_compile # We need to know -static, to get the right output filenames. for arg do case $arg in -shared) test "$build_libtool_libs" != yes && \ func_fatal_configuration "can not build a shared library" build_old_libs=no break ;; -all-static | -static | -static-libtool-libs) case $arg in -all-static) if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then func_warning "complete static linking is impossible in this configuration" fi if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; -static) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=built ;; -static-libtool-libs) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; esac build_libtool_libs=no build_old_libs=yes break ;; esac done # See if our shared archives depend on static archives. test -n "$old_archive_from_new_cmds" && build_old_libs=yes # Go through the arguments, transforming them on the way. while test "$#" -gt 0; do arg="$1" shift func_quote_for_eval "$arg" qarg=$func_quote_for_eval_unquoted_result func_append libtool_args " $func_quote_for_eval_result" # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) func_append compile_command " @OUTPUT@" func_append finalize_command " @OUTPUT@" ;; esac case $prev in bindir) bindir="$arg" prev= continue ;; dlfiles|dlprefiles) if test "$preload" = no; then # Add the symbol object into the linking commands. func_append compile_command " @SYMFILE@" func_append finalize_command " @SYMFILE@" preload=yes fi case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test "$dlself" = no; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test "$prev" = dlprefiles; then dlself=yes elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test "$prev" = dlfiles; then func_append dlfiles " $arg" else func_append dlprefiles " $arg" fi prev= continue ;; esac ;; expsyms) export_symbols="$arg" test -f "$arg" \ || func_fatal_error "symbol file \`$arg' does not exist" prev= continue ;; expsyms_regex) export_symbols_regex="$arg" prev= continue ;; framework) case $host in *-*-darwin*) case "$deplibs " in *" $qarg.ltframework "*) ;; *) func_append deplibs " $qarg.ltframework" # this is fixed later ;; esac ;; esac prev= continue ;; inst_prefix) inst_prefix_dir="$arg" prev= continue ;; objectlist) if test -f "$arg"; then save_arg=$arg moreargs= for fil in `cat "$save_arg"` do # func_append moreargs " $fil" arg=$fil # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test "$pic_object" = none && test "$non_pic_object" = none; then func_fatal_error "cannot find name of object for \`$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "\`$arg' is not a valid libtool object" fi fi done else func_fatal_error "link input file \`$arg' does not exist" fi arg=$save_arg prev= continue ;; precious_regex) precious_files_regex="$arg" prev= continue ;; release) release="-$arg" prev= continue ;; rpath | xrpath) # We need an absolute path. case $arg in [\\/]* | [A-Za-z]:[\\/]*) ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac if test "$prev" = rpath; then case "$rpath " in *" $arg "*) ;; *) func_append rpath " $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) func_append xrpath " $arg" ;; esac fi prev= continue ;; shrext) shrext_cmds="$arg" prev= continue ;; weak) func_append weak_libs " $arg" prev= continue ;; xcclinker) func_append linker_flags " $qarg" func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xcompiler) func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xlinker) func_append linker_flags " $qarg" func_append compiler_flags " $wl$qarg" prev= func_append compile_command " $wl$qarg" func_append finalize_command " $wl$qarg" continue ;; *) eval "$prev=\"\$arg\"" prev= continue ;; esac fi # test -n "$prev" prevarg="$arg" case $arg in -all-static) if test -n "$link_static_flag"; then # See comment for -static flag below, for more details. func_append compile_command " $link_static_flag" func_append finalize_command " $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. func_fatal_error "\`-allow-undefined' must not be used because it is the default" ;; -avoid-version) avoid_version=yes continue ;; -bindir) prev=bindir continue ;; -dlopen) prev=dlfiles continue ;; -dlpreopen) prev=dlprefiles continue ;; -export-dynamic) export_dynamic=yes continue ;; -export-symbols | -export-symbols-regex) if test -n "$export_symbols" || test -n "$export_symbols_regex"; then func_fatal_error "more than one -exported-symbols argument is not allowed" fi if test "X$arg" = "X-export-symbols"; then prev=expsyms else prev=expsyms_regex fi continue ;; -framework) prev=framework continue ;; -inst-prefix-dir) prev=inst_prefix continue ;; # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* # so, if we see these flags be careful not to treat them like -L -L[A-Z][A-Z]*:*) case $with_gcc/$host in no/*-*-irix* | /*-*-irix*) func_append compile_command " $arg" func_append finalize_command " $arg" ;; esac continue ;; -L*) func_stripname "-L" '' "$arg" if test -z "$func_stripname_result"; then if test "$#" -gt 0; then func_fatal_error "require no space between \`-L' and \`$1'" else func_fatal_error "need path for \`-L' option" fi fi func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` test -z "$absdir" && \ func_fatal_error "cannot determine absolute directory name of \`$dir'" dir="$absdir" ;; esac case "$deplibs " in *" -L$dir "* | *" $arg "*) # Will only happen for absolute or sysroot arguments ;; *) # Preserve sysroot, but never include relative directories case $dir in [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; *) func_append deplibs " -L$dir" ;; esac func_append lib_search_path " $dir" ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` case :$dllsearchpath: in *":$dir:"*) ;; ::) dllsearchpath=$dir;; *) func_append dllsearchpath ":$dir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac continue ;; -l*) if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) # These systems don't actually have a C or math library (as such) continue ;; *-*-os2*) # These systems don't actually have a C library (as such) test "X$arg" = "X-lc" && continue ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. test "X$arg" = "X-lc" && continue ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework func_append deplibs " System.ltframework" continue ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype test "X$arg" = "X-lc" && continue ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work test "X$arg" = "X-lc" && continue ;; esac elif test "X$arg" = "X-lc_r"; then case $host in *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi func_append deplibs " $arg" continue ;; -module) module=yes continue ;; # Tru64 UNIX uses -model [arg] to determine the layout of C++ # classes, name mangling, and exception handling. # Darwin uses the -arch flag to determine output architecture. -model|-arch|-isysroot|--sysroot) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" prev=xcompiler continue ;; -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case "$new_inherited_linker_flags " in *" $arg "*) ;; * ) func_append new_inherited_linker_flags " $arg" ;; esac continue ;; -multi_module) single_module="${wl}-multi_module" continue ;; -no-fast-install) fast_install=no continue ;; -no-install) case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) # The PATH hackery in wrapper scripts is required on Windows # and Darwin in order for the loader to find any dlls it needs. func_warning "\`-no-install' is ignored for $host" func_warning "assuming \`-no-fast-install' instead" fast_install=no ;; *) no_install=yes ;; esac continue ;; -no-undefined) allow_undefined=no continue ;; -objectlist) prev=objectlist continue ;; -o) prev=output ;; -precious-files-regex) prev=precious_regex continue ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) func_stripname '-R' '' "$arg" dir=$func_stripname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; =*) func_stripname '=' '' "$dir" dir=$lt_sysroot$func_stripname_result ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac continue ;; -shared) # The effects of -shared are defined in a previous loop. continue ;; -shrext) prev=shrext continue ;; -static | -static-libtool-libs) # The effects of -static are defined in a previous loop. # We used to do the same as -all-static on platforms that # didn't have a PIC flag, but the assumption that the effects # would be equivalent was wrong. It would break on at least # Digital Unix and AIX. continue ;; -thread-safe) thread_safe=yes continue ;; -version-info) prev=vinfo continue ;; -version-number) prev=vinfo vinfo_number=yes continue ;; -weak) prev=weak continue ;; -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" func_append arg " $func_quote_for_eval_result" func_append compiler_flags " $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Wl,*) func_stripname '-Wl,' '' "$arg" args=$func_stripname_result arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" func_append arg " $wl$func_quote_for_eval_result" func_append compiler_flags " $wl$func_quote_for_eval_result" func_append linker_flags " $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; -XCClinker) prev=xcclinker continue ;; # -msg_* for osf cc -msg_*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; # Flags to be passed through unchanged, with rationale: # -64, -mips[0-9] enable 64-bit mode for the SGI compiler # -r[0-9][0-9]* specify processor for the SGI compiler # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler # +DA*, +DD* enable 64-bit mode for the HP compiler # -q* compiler args for the IBM compiler # -m*, -t[45]*, -txscale* architecture-specific flags for GCC # -F/path path to uninstalled frameworks, gcc on darwin # -p, -pg, --coverage, -fprofile-* profiling flags for GCC # @file GCC response files # -tp=* Portland pgcc target processor selection # --sysroot=* for sysroot support # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ -O*|-flto*|-fwhopr*|-fuse-linker-plugin) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" func_append compile_command " $arg" func_append finalize_command " $arg" func_append compiler_flags " $arg" continue ;; # Some other compiler flag. -* | +*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; *.$objext) # A standard object. func_append objs " $arg" ;; *.lo) # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test "$pic_object" = none && test "$non_pic_object" = none; then func_fatal_error "cannot find name of object for \`$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "\`$arg' is not a valid libtool object" fi fi ;; *.$libext) # An archive. func_append deplibs " $arg" func_append old_deplibs " $arg" continue ;; *.la) # A libtool-controlled library. func_resolve_sysroot "$arg" if test "$prev" = dlfiles; then # This library was specified with -dlopen. func_append dlfiles " $func_resolve_sysroot_result" prev= elif test "$prev" = dlprefiles; then # The library was specified with -dlpreopen. func_append dlprefiles " $func_resolve_sysroot_result" prev= else func_append deplibs " $func_resolve_sysroot_result" fi continue ;; # Some other compiler argument. *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; esac # arg # Now actually substitute the argument into the commands. if test -n "$arg"; then func_append compile_command " $arg" func_append finalize_command " $arg" fi done # argument parsing loop test -n "$prev" && \ func_fatal_help "the \`$prevarg' option requires an argument" if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" func_append compile_command " $arg" func_append finalize_command " $arg" fi oldlibs= # calculate the name of the file, without its directory func_basename "$output" outputname="$func_basename_result" libobjs_save="$libobjs" if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" func_dirname "$output" "/" "" output_objdir="$func_dirname_result$objdir" func_to_tool_file "$output_objdir/" tool_output_objdir=$func_to_tool_file_result # Create the object directory. func_mkdir_p "$output_objdir" # Determine the type of output case $output in "") func_fatal_help "you must specify an output file" ;; *.$libext) linkmode=oldlib ;; *.lo | *.$objext) linkmode=obj ;; *.la) linkmode=lib ;; *) linkmode=prog ;; # Anything else should be a program. esac specialdeplibs= libs= # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do if $opt_preserve_dup_deps ; then case "$libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append libs " $deplib" done if test "$linkmode" = lib; then libs="$predeps $libs $compiler_lib_search_path $postdeps" # Compute libraries that are listed more than once in $predeps # $postdeps and mark them as special (i.e., whose duplicates are # not to be eliminated). pre_post_deps= if $opt_duplicate_compiler_generated_deps; then for pre_post_dep in $predeps $postdeps; do case "$pre_post_deps " in *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; esac func_append pre_post_deps " $pre_post_dep" done fi pre_post_deps= fi deplibs= newdependency_libs= newlib_search_path= need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries notinst_path= # paths that contain not-installed libtool libraries case $linkmode in lib) passes="conv dlpreopen link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; *) func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" ;; esac done ;; prog) compile_deplibs= finalize_deplibs= alldeplibs=no newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" ;; *) passes="conv" ;; esac for pass in $passes; do # The preopen pass in lib mode reverses $deplibs; put it back here # so that -L comes before libs that need it for instance... if test "$linkmode,$pass" = "lib,link"; then ## FIXME: Find the place where the list is rebuilt in the wrong ## order, and fix it there properly tmp_deplibs= for deplib in $deplibs; do tmp_deplibs="$deplib $tmp_deplibs" done deplibs="$tmp_deplibs" fi if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan"; then libs="$deplibs" deplibs= fi if test "$linkmode" = prog; then case $pass in dlopen) libs="$dlfiles" ;; dlpreopen) libs="$dlprefiles" ;; link) libs="$deplibs %DEPLIBS%" test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" ;; esac fi if test "$linkmode,$pass" = "lib,dlpreopen"; then # Collect and forward deplibs of preopened libtool libs for lib in $dlprefiles; do # Ignore non-libtool-libs dependency_libs= func_resolve_sysroot "$lib" case $lib in *.la) func_source "$func_resolve_sysroot_result" ;; esac # Collect preopened libtool deplibs, except any this library # has declared as weak libs for deplib in $dependency_libs; do func_basename "$deplib" deplib_base=$func_basename_result case " $weak_libs " in *" $deplib_base "*) ;; *) func_append deplibs " $deplib" ;; esac done done libs="$dlprefiles" fi if test "$pass" = dlopen; then # Collect dlpreopened libraries save_deplibs="$deplibs" deplibs= fi for deplib in $libs; do lib= found=no case $deplib in -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append compiler_flags " $deplib" if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -l*) if test "$linkmode" != lib && test "$linkmode" != prog; then func_warning "\`-l' is ignored for archives/objects" continue fi func_stripname '-l' '' "$deplib" name=$func_stripname_result if test "$linkmode" = lib; then searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" else searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" fi for searchdir in $searchdirs; do for search_ext in .la $std_shrext .so .a; do # Search the libtool library lib="$searchdir/lib${name}${search_ext}" if test -f "$lib"; then if test "$search_ext" = ".la"; then found=yes else found=no fi break 2 fi done done if test "$found" != yes; then # deplib doesn't seem to be a libtool library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue else # deplib is a libtool library # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, # We need to do some special things here, and not later. if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $deplib "*) if func_lalib_p "$lib"; then library_names= old_library= func_source "$lib" for l in $old_library $library_names; do ll="$l" done if test "X$ll" = "X$old_library" ; then # only static version available found=no func_dirname "$lib" "" "." ladir="$func_dirname_result" lib=$ladir/$old_library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue fi fi ;; *) ;; esac fi fi ;; # -l *.ltframework) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -L*) case $linkmode in lib) deplibs="$deplib $deplibs" test "$pass" = conv && continue newdependency_libs="$deplib $newdependency_libs" func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; prog) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi if test "$pass" = scan; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; *) func_warning "\`-L' is ignored for archives/objects" ;; esac # linkmode continue ;; # -L -R*) if test "$pass" = link; then func_stripname '-R' '' "$deplib" func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; *.la) func_resolve_sysroot "$deplib" lib=$func_resolve_sysroot_result ;; *.$libext) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi case $linkmode in lib) # Linking convenience modules into shared libraries is allowed, # but linking other static libraries is non-portable. case " $dlpreconveniencelibs " in *" $deplib "*) ;; *) valid_a_lib=no case $deplibs_check_method in match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then valid_a_lib=yes fi ;; pass_all) valid_a_lib=yes ;; esac if test "$valid_a_lib" != yes; then echo $ECHO "*** Warning: Trying to link with static lib archive $deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because the file extensions .$libext of this argument makes me believe" echo "*** that it is just a static archive that I should not use here." else echo $ECHO "*** Warning: Linking the shared library $output against the" $ECHO "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" fi ;; esac continue ;; prog) if test "$pass" != link; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test "$pass" = conv; then deplibs="$deplib $deplibs" elif test "$linkmode" = prog; then if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlopen support or we're linking statically, # we need to preload. func_append newdlprefiles " $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append newdlfiles " $deplib" fi fi continue ;; %DEPLIBS%) alldeplibs=yes continue ;; esac # case $deplib if test "$found" = yes || test -f "$lib"; then : else func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" fi # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$lib" \ || func_fatal_error "\`$lib' is not a valid libtool archive" func_dirname "$lib" "" "." ladir="$func_dirname_result" dlname= dlopen= dlpreopen= libdir= library_names= old_library= inherited_linker_flags= # If the library was installed with an old release of libtool, # it will not redefine variables installed, or shouldnotlink installed=yes shouldnotlink=no avoidtemprpath= # Read the .la file func_source "$lib" # Convert "-framework foo" to "foo.ltframework" if test -n "$inherited_linker_flags"; then tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do case " $new_inherited_linker_flags " in *" $tmp_inherited_linker_flag "*) ;; *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; esac done fi dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan" || { test "$linkmode" != prog && test "$linkmode" != lib; }; then test -n "$dlopen" && func_append dlfiles " $dlopen" test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" fi if test "$pass" = conv; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then func_fatal_error "cannot find name of link library for \`$lib'" fi # It is a libtool convenience library, so add in its objects. func_append convenience " $ladir/$objdir/$old_library" func_append old_convenience " $ladir/$objdir/$old_library" tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done elif test "$linkmode" != prog && test "$linkmode" != lib; then func_fatal_error "\`$lib' is not a convenience library" fi continue fi # $pass = conv # Get the name of the library we link against. linklib= if test -n "$old_library" && { test "$prefer_static_libs" = yes || test "$prefer_static_libs,$installed" = "built,no"; }; then linklib=$old_library else for l in $old_library $library_names; do linklib="$l" done fi if test -z "$linklib"; then func_fatal_error "cannot find name of link library for \`$lib'" fi # This library was specified with -dlopen. if test "$pass" = dlopen; then if test -z "$libdir"; then func_fatal_error "cannot -dlopen a convenience library: \`$lib'" fi if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. We also need to preload any # dependent libraries so libltdl's deplib preloader doesn't # bomb out in the load deplibs phase. func_append dlprefiles " $lib $dependency_libs" else func_append newdlfiles " $lib" fi continue fi # $pass = dlopen # We need an absolute path. case $ladir in [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then func_warning "cannot determine absolute directory name of \`$ladir'" func_warning "passing it literally to the linker, although it might fail" abs_ladir="$ladir" fi ;; esac func_basename "$lib" laname="$func_basename_result" # Find the relevant object directory and library name. if test "X$installed" = Xyes; then if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then func_warning "library \`$lib' was moved." dir="$ladir" absdir="$abs_ladir" libdir="$abs_ladir" else dir="$lt_sysroot$libdir" absdir="$lt_sysroot$libdir" fi test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes else if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then dir="$ladir" absdir="$abs_ladir" # Remove this search path later func_append notinst_path " $abs_ladir" else dir="$ladir/$objdir" absdir="$abs_ladir/$objdir" # Remove this search path later func_append notinst_path " $abs_ladir" fi fi # $installed = yes func_stripname 'lib' '.la' "$laname" name=$func_stripname_result # This library was specified with -dlpreopen. if test "$pass" = dlpreopen; then if test -z "$libdir" && test "$linkmode" = prog; then func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" fi case "$host" in # special handling for platforms with PE-DLLs. *cygwin* | *mingw* | *cegcc* ) # Linker will automatically link against shared library if both # static and shared are present. Therefore, ensure we extract # symbols from the import library if a shared library is present # (otherwise, the dlopen module name will be incorrect). We do # this by putting the import library name into $newdlprefiles. # We recover the dlopen module name by 'saving' the la file # name in a special purpose variable, and (later) extracting the # dlname from the la file. if test -n "$dlname"; then func_tr_sh "$dir/$linklib" eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" func_append newdlprefiles " $dir/$linklib" else func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" fi ;; * ) # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then func_append newdlprefiles " $dir/$dlname" else func_append newdlprefiles " $dir/$linklib" fi ;; esac fi # $pass = dlpreopen if test -z "$libdir"; then # Link the convenience library if test "$linkmode" = lib; then deplibs="$dir/$old_library $deplibs" elif test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else deplibs="$lib $deplibs" # used for prog,scan pass fi continue fi if test "$linkmode" = prog && test "$pass" != link; then func_append newlib_search_path " $ladir" deplibs="$lib $deplibs" linkalldeplibs=no if test "$link_all_deplibs" != no || test -z "$library_names" || test "$build_libtool_libs" = no; then linkalldeplibs=yes fi tmp_libs= for deplib in $dependency_libs; do case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; esac # Need to link against all dependency_libs? if test "$linkalldeplibs" = yes; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done # for deplib continue fi # $linkmode = prog... if test "$linkmode,$pass" = "prog,link"; then if test -n "$library_names" && { { test "$prefer_static_libs" = no || test "$prefer_static_libs,$installed" = "built,yes"; } || test -z "$old_library"; }; then # We need to hardcode the library path if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then # Make sure the rpath contains only unique directories. case "$temp_rpath:" in *"$absdir:"*) ;; *) func_append temp_rpath "$absdir:" ;; esac fi # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi # $linkmode,$pass = prog,link... if test "$alldeplibs" = yes && { test "$deplibs_check_method" = pass_all || { test "$build_libtool_libs" = yes && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi fi link_static=no # Whether the deplib will be linked statically use_static_libs=$prefer_static_libs if test "$use_static_libs" = built && test "$installed" = yes; then use_static_libs=no fi if test -n "$library_names" && { test "$use_static_libs" = no || test -z "$old_library"; }; then case $host in *cygwin* | *mingw* | *cegcc*) # No point in relinking DLLs because paths are not encoded func_append notinst_deplibs " $lib" need_relink=no ;; *) if test "$installed" = no; then func_append notinst_deplibs " $lib" need_relink=yes fi ;; esac # This is a shared library # Warn about portability, can't link against -module's on some # systems (darwin). Don't bleat about dlopened modules though! dlopenmodule="" for dlpremoduletest in $dlprefiles; do if test "X$dlpremoduletest" = "X$lib"; then dlopenmodule="$dlpremoduletest" break fi done if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then echo if test "$linkmode" = prog; then $ECHO "*** Warning: Linking the executable $output against the loadable module" else $ECHO "*** Warning: Linking the shared library $output against the loadable module" fi $ECHO "*** $linklib is not portable!" fi if test "$linkmode" = lib && test "$hardcode_into_libs" = yes; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi if test -n "$old_archive_from_expsyms_cmds"; then # figure out the soname set dummy $library_names shift realname="$1" shift libname=`eval "\\$ECHO \"$libname_spec\""` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then soname="$dlname" elif test -n "$soname_spec"; then # bleh windows case $host in *cygwin* | mingw* | *cegcc*) func_arith $current - $age major=$func_arith_result versuffix="-$major" ;; esac eval soname=\"$soname_spec\" else soname="$realname" fi # Make a new name for the extract_expsyms_cmds to use soroot="$soname" func_basename "$soroot" soname="$func_basename_result" func_stripname 'lib' '.dll' "$soname" newlib=libimp-$func_stripname_result.a # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else func_verbose "extracting exported symbol list from \`$soname'" func_execute_cmds "$extract_expsyms_cmds" 'exit $?' fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else func_verbose "generating import library for \`$soname'" func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' fi # make sure the library variables are pointing to the new library dir=$output_objdir linklib=$newlib fi # test -n "$old_archive_from_expsyms_cmds" if test "$linkmode" = prog || test "$opt_mode" != relink; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test "$hardcode_direct" = no; then add="$dir/$linklib" case $host in *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; *-*-sysv4*uw2*) add_dir="-L$dir" ;; *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ *-*-unixware7*) add_dir="-L$dir" ;; *-*-darwin* ) # if the lib is a (non-dlopened) module then we can not # link against it, someone is ignoring the earlier warnings if /usr/bin/file -L $add 2> /dev/null | $GREP ": [^:]* bundle" >/dev/null ; then if test "X$dlopenmodule" != "X$lib"; then $ECHO "*** Warning: lib $linklib is a module, not a shared library" if test -z "$old_library" ; then echo echo "*** And there doesn't seem to be a static archive available" echo "*** The link will probably fail, sorry" else add="$dir/$old_library" fi elif test -n "$old_library"; then add="$dir/$old_library" fi fi esac elif test "$hardcode_minus_L" = no; then case $host in *-*-sunos*) add_shlibpath="$dir" ;; esac add_dir="-L$dir" add="-l$name" elif test "$hardcode_shlibpath_var" = no; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; relink) if test "$hardcode_direct" = yes && test "$hardcode_direct_absolute" = no; then add="$dir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$absdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; *) lib_linked=no ;; esac if test "$lib_linked" != yes; then func_fatal_configuration "unsupported hardcode properties" fi if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; *) func_append compile_shlibpath "$add_shlibpath:" ;; esac fi if test "$linkmode" = prog; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" if test "$hardcode_direct" != yes && test "$hardcode_minus_L" != yes && test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac fi fi fi if test "$linkmode" = prog || test "$opt_mode" = relink; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test "$hardcode_direct" = yes && test "$hardcode_direct_absolute" = no; then add="$libdir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$libdir" add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac add="-l$name" elif test "$hardcode_automatic" = yes; then if test -n "$inst_prefix_dir" && test -f "$inst_prefix_dir$libdir/$linklib" ; then add="$inst_prefix_dir$libdir/$linklib" else add="$libdir/$linklib" fi else # We cannot seem to hardcode it, guess we'll fake it. add_dir="-L$libdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" fi if test "$linkmode" = prog; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" fi fi elif test "$linkmode" = prog; then # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. if test "$hardcode_direct" != unsupported; then test -n "$old_library" && linklib="$old_library" compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi elif test "$build_libtool_libs" = yes; then # Not a shared library if test "$deplibs_check_method" != pass_all; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. echo $ECHO "*** Warning: This system can not link to static lib archive $lib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have." if test "$module" = yes; then echo "*** But as you try to build a module library, libtool will still create " echo "*** a static module, that should work as long as the dlopening application" echo "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using \`nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi else deplibs="$dir/$old_library $deplibs" link_static=yes fi fi # link shared/static library? if test "$linkmode" = lib; then if test -n "$dependency_libs" && { test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes || test "$link_static" = yes; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do case $libdir in -R*) func_stripname '-R' '' "$libdir" temp_xrpath=$func_stripname_result case " $xrpath " in *" $temp_xrpath "*) ;; *) func_append xrpath " $temp_xrpath";; esac;; *) func_append temp_deplibs " $libdir";; esac done dependency_libs="$temp_deplibs" fi func_append newlib_search_path " $absdir" # Link against this library test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result";; *) func_resolve_sysroot "$deplib" ;; esac if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $func_resolve_sysroot_result "*) func_append specialdeplibs " $func_resolve_sysroot_result" ;; esac fi func_append tmp_libs " $func_resolve_sysroot_result" done if test "$link_all_deplibs" != no; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do path= case $deplib in -L*) path="$deplib" ;; *.la) func_resolve_sysroot "$deplib" deplib=$func_resolve_sysroot_result func_dirname "$deplib" "" "." dir=$func_dirname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then func_warning "cannot determine absolute directory name of \`$dir'" absdir="$dir" fi ;; esac if $GREP "^installed=no" $deplib > /dev/null; then case $host in *-*-darwin*) depdepl= eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` if test -n "$deplibrary_names" ; then for tmp in $deplibrary_names ; do depdepl=$tmp done if test -f "$absdir/$objdir/$depdepl" ; then depdepl="$absdir/$objdir/$depdepl" darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` if test -z "$darwin_install_name"; then darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` fi func_append compiler_flags " ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" func_append linker_flags " -dylib_file ${darwin_install_name}:${depdepl}" path= fi fi ;; *) path="-L$absdir/$objdir" ;; esac else eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "\`$deplib' is not a valid libtool archive" test "$absdir" != "$libdir" && \ func_warning "\`$deplib' seems to be moved" path="-L$absdir" fi ;; esac case " $deplibs " in *" $path "*) ;; *) deplibs="$path $deplibs" ;; esac done fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs if test "$pass" = link; then if test "$linkmode" = "prog"; then compile_deplibs="$new_inherited_linker_flags $compile_deplibs" finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" else compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` fi fi dependency_libs="$newdependency_libs" if test "$pass" = dlpreopen; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test "$pass" != dlopen; then if test "$pass" != conv; then # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do case "$lib_search_path " in *" $dir "*) ;; *) func_append lib_search_path " $dir" ;; esac done newlib_search_path= fi if test "$linkmode,$pass" != "prog,link"; then vars="deplibs" else vars="compile_deplibs finalize_deplibs" fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order eval tmp_libs=\"\$$var\" new_libs= for deplib in $tmp_libs; do # FIXME: Pedantically, this is the right thing to do, so # that some nasty dependency loop isn't accidentally # broken: #new_libs="$deplib $new_libs" # Pragmatically, this seems to cause very few problems in # practice: case $deplib in -L*) new_libs="$deplib $new_libs" ;; -R*) ;; *) # And here is the reason: when a library appears more # than once as an explicit dependence of a library, or # is implicitly linked in more than once by the # compiler, it is considered special, and multiple # occurrences thereof are not removed. Compare this # with having the same library being listed as a # dependency of multiple other libraries: in this case, # we know (pedantically, we assume) the library does not # need to be listed more than once, so we keep only the # last copy. This is not always right, but it is rare # enough that we require users that really mean to play # such unportable linking tricks to link the library # using -Wl,-lname, so that libtool does not consider it # for duplicate removal. case " $specialdeplibs " in *" $deplib "*) new_libs="$deplib $new_libs" ;; *) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$deplib $new_libs" ;; esac ;; esac ;; esac done tmp_libs= for deplib in $new_libs; do case $deplib in -L*) case " $tmp_libs " in *" $deplib "*) ;; *) func_append tmp_libs " $deplib" ;; esac ;; *) func_append tmp_libs " $deplib" ;; esac done eval $var=\"$tmp_libs\" done # for var fi # Last step: remove runtime libs from dependency_libs # (they stay in deplibs) tmp_libs= for i in $dependency_libs ; do case " $predeps $postdeps $compiler_lib_search_path " in *" $i "*) i="" ;; esac if test -n "$i" ; then func_append tmp_libs " $i" fi done dependency_libs=$tmp_libs done # for pass if test "$linkmode" = prog; then dlfiles="$newdlfiles" fi if test "$linkmode" = prog || test "$linkmode" = lib; then dlprefiles="$newdlprefiles" fi case $linkmode in oldlib) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then func_warning "\`-dlopen' is ignored for archives" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "\`-l' and \`-L' are ignored for archives" ;; esac test -n "$rpath" && \ func_warning "\`-rpath' is ignored for archives" test -n "$xrpath" && \ func_warning "\`-R' is ignored for archives" test -n "$vinfo" && \ func_warning "\`-version-info/-version-number' is ignored for archives" test -n "$release" && \ func_warning "\`-release' is ignored for archives" test -n "$export_symbols$export_symbols_regex" && \ func_warning "\`-export-symbols' is ignored for archives" # Now set the variables for building old libraries. build_libtool_libs=no oldlibs="$output" func_append objs "$old_deplibs" ;; lib) # Make sure we only generate libraries of the form `libNAME.la'. case $outputname in lib*) func_stripname 'lib' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" ;; *) test "$module" = no && \ func_fatal_help "libtool library \`$output' must begin with \`lib'" if test "$need_lib_prefix" != no; then # Add the "lib" prefix for modules if required func_stripname '' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" else func_stripname '' '.la' "$outputname" libname=$func_stripname_result fi ;; esac if test -n "$objs"; then if test "$deplibs_check_method" != pass_all; then func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" else echo $ECHO "*** Warning: Linking the shared library $output against the non-libtool" $ECHO "*** objects $objs is not portable!" func_append libobjs " $objs" fi fi test "$dlself" != no && \ func_warning "\`-dlopen self' is ignored for libtool libraries" set dummy $rpath shift test "$#" -gt 1 && \ func_warning "ignoring multiple \`-rpath's for a libtool library" install_libdir="$1" oldlibs= if test -z "$rpath"; then if test "$build_libtool_libs" = yes; then # Building a libtool convenience library. # Some compilers have problems with a `.al' extension so # convenience libraries should have the same extension an # archive normally would. oldlibs="$output_objdir/$libname.$libext $oldlibs" build_libtool_libs=convenience build_old_libs=yes fi test -n "$vinfo" && \ func_warning "\`-version-info/-version-number' is ignored for convenience libraries" test -n "$release" && \ func_warning "\`-release' is ignored for convenience libraries" else # Parse the version information argument. save_ifs="$IFS"; IFS=':' set dummy $vinfo 0 0 0 shift IFS="$save_ifs" test -n "$7" && \ func_fatal_help "too many parameters to \`-version-info'" # convert absolute version numbers to libtool ages # this retains compatibility with .la files and attempts # to make the code below a bit more comprehensible case $vinfo_number in yes) number_major="$1" number_minor="$2" number_revision="$3" # # There are really only two kinds -- those that # use the current revision as the major version # and those that subtract age and use age as # a minor version. But, then there is irix # which has an extra 1 added just for fun # case $version_type in # correct linux to gnu/linux during the next big refactor darwin|linux|osf|windows|none) func_arith $number_major + $number_minor current=$func_arith_result age="$number_minor" revision="$number_revision" ;; freebsd-aout|freebsd-elf|qnx|sunos) current="$number_major" revision="$number_minor" age="0" ;; irix|nonstopux) func_arith $number_major + $number_minor current=$func_arith_result age="$number_minor" revision="$number_minor" lt_irix_increment=no ;; *) func_fatal_configuration "$modename: unknown library version type \`$version_type'" ;; esac ;; no) current="$1" revision="$2" age="$3" ;; esac # Check that each of the things are valid numbers. case $current in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "CURRENT \`$current' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac case $revision in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "REVISION \`$revision' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac case $age in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "AGE \`$age' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac if test "$age" -gt "$current"; then func_error "AGE \`$age' is greater than the current interface number \`$current'" func_fatal_error "\`$vinfo' is not valid version information" fi # Calculate the version variables. major= versuffix= verstring= case $version_type in none) ;; darwin) # Like Linux, but with the current version available in # verstring for coding it into the library header func_arith $current - $age major=.$func_arith_result versuffix="$major.$age.$revision" # Darwin ld doesn't like 0 for these options... func_arith $current + 1 minor_current=$func_arith_result xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; freebsd-aout) major=".$current" versuffix=".$current.$revision"; ;; freebsd-elf) major=".$current" versuffix=".$current" ;; irix | nonstopux) if test "X$lt_irix_increment" = "Xno"; then func_arith $current - $age else func_arith $current - $age + 1 fi major=$func_arith_result case $version_type in nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac verstring="$verstring_prefix$major.$revision" # Add in all the interfaces that we are compatible with. loop=$revision while test "$loop" -ne 0; do func_arith $revision - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring="$verstring_prefix$major.$iface:$verstring" done # Before this point, $major must not contain `.'. major=.$major versuffix="$major.$revision" ;; linux) # correct to gnu/linux during the next big refactor func_arith $current - $age major=.$func_arith_result versuffix="$major.$age.$revision" ;; osf) func_arith $current - $age major=.$func_arith_result versuffix=".$current.$age.$revision" verstring="$current.$age.$revision" # Add in all the interfaces that we are compatible with. loop=$age while test "$loop" -ne 0; do func_arith $current - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring="$verstring:${iface}.0" done # Make executables depend on our current version. func_append verstring ":${current}.0" ;; qnx) major=".$current" versuffix=".$current" ;; sunos) major=".$current" versuffix=".$current.$revision" ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 filesystems. func_arith $current - $age major=$func_arith_result versuffix="-$major" ;; *) func_fatal_configuration "unknown library version type \`$version_type'" ;; esac # Clear the version info if we defaulted, and they specified a release. if test -z "$vinfo" && test -n "$release"; then major= case $version_type in darwin) # we can't check for "0.0" in archive_cmds due to quoting # problems, so we reset it completely verstring= ;; *) verstring="0.0" ;; esac if test "$need_version" = no; then versuffix= else versuffix=".0.0" fi fi # Remove version info from name if versioning should be avoided if test "$avoid_version" = yes && test "$need_version" = no; then major= versuffix= verstring="" fi # Check to see if the archive will have undefined symbols. if test "$allow_undefined" = yes; then if test "$allow_undefined_flag" = unsupported; then func_warning "undefined symbols not allowed in $host shared libraries" build_libtool_libs=no build_old_libs=yes fi else # Don't allow undefined symbols. allow_undefined_flag="$no_undefined_flag" fi fi func_generate_dlsyms "$libname" "$libname" "yes" func_append libobjs " $symfileobj" test "X$libobjs" = "X " && libobjs= if test "$opt_mode" != relink; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. removelist= tempremovelist=`$ECHO "$output_objdir/*"` for p in $tempremovelist; do case $p in *.$objext | *.gcno) ;; $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) if test "X$precious_files_regex" != "X"; then if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 then continue fi fi func_append removelist " $p" ;; *) ;; esac done test -n "$removelist" && \ func_show_eval "${RM}r \$removelist" fi # Now set the variables for building old libraries. if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then func_append oldlibs " $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP` fi # Eliminate all temporary directories. #for path in $notinst_path; do # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` #done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. temp_xrpath= for libdir in $xrpath; do func_replace_sysroot "$libdir" func_append temp_xrpath " -R$func_replace_sysroot_result" case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened old_dlfiles="$dlfiles" dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in *" $lib "*) ;; *) func_append dlfiles " $lib" ;; esac done # Make sure dlprefiles contains only unique files old_dlprefiles="$dlprefiles" dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in *" $lib "*) ;; *) func_append dlprefiles " $lib" ;; esac done if test "$build_libtool_libs" = yes; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework func_append deplibs " System.ltframework" ;; *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work ;; *) # Add libc to deplibs on all other systems if necessary. if test "$build_libtool_need_lc" = "yes"; then func_append deplibs " -lc" fi ;; esac fi # Transform deplibs into only deplibs that can be linked in shared. name_save=$name libname_save=$libname release_save=$release versuffix_save=$versuffix major_save=$major # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? release="" versuffix="" major="" newdeplibs= droppeddeps=no case $deplibs_check_method in pass_all) # Don't check for shared/static. Everything works. # This might be a little naive. We might want to check # whether the library exists or not. But this is on # osf3 & osf4 and I'm not really sure... Just # implementing what was already the behavior. newdeplibs=$deplibs ;; test_compile) # This code stresses the "libraries are programs" paradigm to its # limits. Maybe even breaks it. We compile a program, linking it # against the deplibs as a proxy for the library. Then we can check # whether they linked in statically or dynamically with ldd. $opt_dry_run || $RM conftest.c cat > conftest.c </dev/null` $nocaseglob else potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` fi for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null | $GREP " -> " >/dev/null; then continue fi # The statement above tries to avoid entering an # endless loop below, in case of cyclic links. # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? potlib="$potent_lib" while test -h "$potlib" 2>/dev/null; do potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; *) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | $SED -e 10q | $EGREP "$file_magic_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for file magic test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a file magic. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` for a_deplib in $deplibs; do case $a_deplib in -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $a_deplib "*) func_append newdeplibs " $a_deplib" a_deplib="" ;; esac fi if test -n "$a_deplib" ; then libname=`eval "\\$ECHO \"$libname_spec\""` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do potlib="$potent_lib" # see symlink-check above in file_magic test if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ $EGREP "$match_pattern_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a regex pattern. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; none | unknown | *) newdeplibs="" tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then for i in $predeps $postdeps ; do # can't use Xsed below, because $i might contain '/' tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"` done fi case $tmp_deplibs in *[!\ \ ]*) echo if test "X$deplibs_check_method" = "Xnone"; then echo "*** Warning: inter-library dependencies are not supported in this platform." else echo "*** Warning: inter-library dependencies are not known to be supported." fi echo "*** All declared inter-library dependencies are being dropped." droppeddeps=yes ;; esac ;; esac versuffix=$versuffix_save major=$major_save release=$release_save libname=$libname_save name=$name_save case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library with the System framework newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac if test "$droppeddeps" = yes; then if test "$module" = yes; then echo echo "*** Warning: libtool could not satisfy all declared inter-library" $ECHO "*** dependencies of module $libname. Therefore, libtool will create" echo "*** a static module, that should work as long as the dlopening" echo "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using \`nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi else echo "*** The inter-library dependencies that have been dropped here will be" echo "*** automatically added whenever a program is linked with this library" echo "*** or is declared to -dlopen it." if test "$allow_undefined" = no; then echo echo "*** Since this library must not contain undefined symbols," echo "*** because either the platform does not support them or" echo "*** it was explicitly requested with -no-undefined," echo "*** libtool will only create a static version of it." if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi fi fi # Done checking deplibs! deplibs=$newdeplibs fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" case $host in *-*-darwin*) newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done deplibs="$new_libs" # All the library-specific variables (install_libdir is set above). library_names= old_library= dlname= # Test again, we may have decided not to build it any more if test "$build_libtool_libs" = yes; then # Remove ${wl} instances when linking with ld. # FIXME: should test the right _cmds variable. case $archive_cmds in *\$LD\ *) wl= ;; esac if test "$hardcode_into_libs" = yes; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath="$finalize_rpath" test "$opt_mode" != relink && rpath="$compile_rpath$rpath" for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then func_replace_sysroot "$libdir" libdir=$func_replace_sysroot_result if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append dep_rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" fi test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi shlibpath="$finalize_shlibpath" test "$opt_mode" != relink && shlibpath="$compile_shlibpath$shlibpath" if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi # Get the real and link names of the library. eval shared_ext=\"$shrext_cmds\" eval library_names=\"$library_names_spec\" set dummy $library_names shift realname="$1" shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else soname="$realname" fi if test -z "$dlname"; then dlname=$soname fi lib="$output_objdir/$realname" linknames= for link do func_append linknames " $link" done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` test "X$libobjs" = "X " && libobjs= delfiles= if test -n "$export_symbols" && test -n "$include_expsyms"; then $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" export_symbols="$output_objdir/$libname.uexp" func_append delfiles " $export_symbols" fi orig_export_symbols= case $host_os in cygwin* | mingw* | cegcc*) if test -n "$export_symbols" && test -z "$export_symbols_regex"; then # exporting using user supplied symfile if test "x`$SED 1q $export_symbols`" != xEXPORTS; then # and it's NOT already a .def file. Must figure out # which of the given symbols are data symbols and tag # them as such. So, trigger use of export_symbols_cmds. # export_symbols gets reassigned inside the "prepare # the list of exported symbols" if statement, so the # include_expsyms logic still works. orig_export_symbols="$export_symbols" export_symbols= always_export_symbols=yes fi fi ;; esac # Prepare the list of exported symbols if test -z "$export_symbols"; then if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then func_verbose "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $opt_dry_run || $RM $export_symbols cmds=$export_symbols_cmds save_ifs="$IFS"; IFS='~' for cmd1 in $cmds; do IFS="$save_ifs" # Take the normal branch if the nm_file_list_spec branch # doesn't work or if tool conversion is not needed. case $nm_file_list_spec~$to_tool_file_cmd in *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) try_normal_branch=yes eval cmd=\"$cmd1\" func_len " $cmd" len=$func_len_result ;; *) try_normal_branch=no ;; esac if test "$try_normal_branch" = yes \ && { test "$len" -lt "$max_cmd_len" \ || test "$max_cmd_len" -le -1; } then func_show_eval "$cmd" 'exit $?' skipped_export=false elif test -n "$nm_file_list_spec"; then func_basename "$output" output_la=$func_basename_result save_libobjs=$libobjs save_output=$output output=${output_objdir}/${output_la}.nm func_to_tool_file "$output" libobjs=$nm_file_list_spec$func_to_tool_file_result func_append delfiles " $output" func_verbose "creating $NM input file list: $output" for obj in $save_libobjs; do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > "$output" eval cmd=\"$cmd1\" func_show_eval "$cmd" 'exit $?' output=$save_output libobjs=$save_libobjs skipped_export=false else # The command line is too long to execute in one step. func_verbose "using reloadable object file for export list..." skipped_export=: # Break out early, otherwise skipped_export may be # set to false by a later but shorter cmd. break fi done IFS="$save_ifs" if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi tmp_deplibs= for test_deplib in $deplibs; do case " $convenience " in *" $test_deplib "*) ;; *) func_append tmp_deplibs " $test_deplib" ;; esac done deplibs="$tmp_deplibs" if test -n "$convenience"; then if test -n "$whole_archive_flag_spec" && test "$compiler_needs_object" = yes && test -z "$libobjs"; then # extract the archives, so we have objects to list. # TODO: could optimize this to just extract one archive. whole_archive_flag_spec= fi if test -n "$whole_archive_flag_spec"; then save_libobjs=$libobjs eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= else gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $convenience func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi fi if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" func_append linker_flags " $flag" fi # Make a backup of the uninstalled library when relinking if test "$opt_mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? fi # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then eval test_cmds=\"$module_expsym_cmds\" cmds=$module_expsym_cmds else eval test_cmds=\"$module_cmds\" cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval test_cmds=\"$archive_expsym_cmds\" cmds=$archive_expsym_cmds else eval test_cmds=\"$archive_cmds\" cmds=$archive_cmds fi fi if test "X$skipped_export" != "X:" && func_len " $test_cmds" && len=$func_len_result && test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else # The command line is too long to link in one step, link piecewise # or, if using GNU ld and skipped_export is not :, use a linker # script. # Save the value of $output and $libobjs because we want to # use them later. If we have whole_archive_flag_spec, we # want to use save_libobjs as it was before # whole_archive_flag_spec was expanded, because we can't # assume the linker understands whole_archive_flag_spec. # This may have to be revisited, in case too many # convenience libraries get linked in and end up exceeding # the spec. if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then save_libobjs=$libobjs fi save_output=$output func_basename "$output" output_la=$func_basename_result # Clear the reloadable object creation command queue and # initialize k to one. test_cmds= concat_cmds= objlist= last_robj= k=1 if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then output=${output_objdir}/${output_la}.lnkscript func_verbose "creating GNU ld script: $output" echo 'INPUT (' > $output for obj in $save_libobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done echo ')' >> $output func_append delfiles " $output" func_to_tool_file "$output" output=$func_to_tool_file_result elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then output=${output_objdir}/${output_la}.lnk func_verbose "creating linker input file list: $output" : > $output set x $save_libobjs shift firstobj= if test "$compiler_needs_object" = yes; then firstobj="$1 " shift fi for obj do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done func_append delfiles " $output" func_to_tool_file "$output" output=$firstobj\"$file_list_spec$func_to_tool_file_result\" else if test -n "$save_libobjs"; then func_verbose "creating reloadable object files..." output=$output_objdir/$output_la-${k}.$objext eval test_cmds=\"$reload_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 # Loop over the list of objects to be linked. for obj in $save_libobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result if test "X$objlist" = X || test "$len" -lt "$max_cmd_len"; then func_append objlist " $obj" else # The command $test_cmds is almost too long, add a # command to the queue. if test "$k" -eq 1 ; then # The first file doesn't have a previous command to add. reload_objs=$objlist eval concat_cmds=\"$reload_cmds\" else # All subsequent reloadable object files will link in # the last one created. reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" fi last_robj=$output_objdir/$output_la-${k}.$objext func_arith $k + 1 k=$func_arith_result output=$output_objdir/$output_la-${k}.$objext objlist=" $obj" func_len " $last_robj" func_arith $len0 + $func_len_result len=$func_arith_result fi done # Handle the remaining objects by creating one last # reloadable object file. All subsequent reloadable object # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ reload_objs="$objlist $last_robj" eval concat_cmds=\"\${concat_cmds}$reload_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" fi func_append delfiles " $output" else output= fi if ${skipped_export-false}; then func_verbose "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $opt_dry_run || $RM $export_symbols libobjs=$output # Append the command to create the export file. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi fi test -n "$save_libobjs" && func_verbose "creating a temporary reloadable object file: $output" # Loop through the commands generated above and execute them. save_ifs="$IFS"; IFS='~' for cmd in $concat_cmds; do IFS="$save_ifs" $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$opt_mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS="$save_ifs" if test -n "$export_symbols_regex" && ${skipped_export-false}; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi if ${skipped_export-false}; then if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi fi libobjs=$output # Restore the value of output. output=$save_output if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= fi # Expand the library linking commands again to reset the # value of $libobjs for piecewise linking. # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then cmds=$module_expsym_cmds else cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then cmds=$archive_expsym_cmds else cmds=$archive_cmds fi fi fi if test -n "$delfiles"; then # Append the command to remove temporary files to $cmds. eval cmds=\"\$cmds~\$RM $delfiles\" fi # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$opt_mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS="$save_ifs" # Restore the uninstalled library and exit if test "$opt_mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? if test -n "$convenience"; then if test -z "$whole_archive_flag_spec"; then func_show_eval '${RM}r "$gentop"' fi fi exit $EXIT_SUCCESS fi # Create links to the real library. for linkname in $linknames; do if test "$realname" != "$linkname"; then func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' fi done # If -module or -export-dynamic was specified, set the dlname. if test "$module" = yes || test "$export_dynamic" = yes; then # On all known operating systems, these are identical. dlname="$soname" fi fi ;; obj) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then func_warning "\`-dlopen' is ignored for objects" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "\`-l' and \`-L' are ignored for objects" ;; esac test -n "$rpath" && \ func_warning "\`-rpath' is ignored for objects" test -n "$xrpath" && \ func_warning "\`-R' is ignored for objects" test -n "$vinfo" && \ func_warning "\`-version-info' is ignored for objects" test -n "$release" && \ func_warning "\`-release' is ignored for objects" case $output in *.lo) test -n "$objs$old_deplibs" && \ func_fatal_error "cannot build library object \`$output' from non-libtool objects" libobj=$output func_lo2o "$libobj" obj=$func_lo2o_result ;; *) libobj= obj="$output" ;; esac # Delete the old objects. $opt_dry_run || $RM $obj $libobj # Objects from convenience libraries. This assumes # single-version convenience libraries. Whenever we create # different ones for PIC/non-PIC, this we'll have to duplicate # the extraction. reload_conv_objs= gentop= # reload_cmds runs $LD directly, so let us get rid of # -Wl from whole_archive_flag_spec and hope we can get by with # turning comma into space.. wl= if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` else gentop="$output_objdir/${obj}x" func_append generated " $gentop" func_extract_archives $gentop $convenience reload_conv_objs="$reload_objs $func_extract_archives_result" fi fi # If we're not building shared, we need to use non_pic_objs test "$build_libtool_libs" != yes && libobjs="$non_pic_objects" # Create the old-style object. reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test output="$obj" func_execute_cmds "$reload_cmds" 'exit $?' # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS fi if test "$build_libtool_libs" != yes; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi # Create an invalid libtool object if no PIC, so that we don't # accidentally link it into a program. # $show "echo timestamp > $libobj" # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? exit $EXIT_SUCCESS fi if test -n "$pic_flag" || test "$pic_mode" != default; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output="$libobj" func_execute_cmds "$reload_cmds" 'exit $?' fi if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS ;; prog) case $host in *cygwin*) func_stripname '' '.exe' "$output" output=$func_stripname_result.exe;; esac test -n "$vinfo" && \ func_warning "\`-version-info' is ignored for programs" test -n "$release" && \ func_warning "\`-release' is ignored for programs" test "$preload" = yes \ && test "$dlopen_support" = unknown \ && test "$dlopen_self" = unknown \ && test "$dlopen_self_static" = unknown && \ func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac case $host in *-*-darwin*) # Don't allow lazy linking, it breaks C++ global constructors # But is supposedly fixed on 10.4 or later (yay!). if test "$tagname" = CXX ; then case ${MACOSX_DEPLOYMENT_TARGET-10.0} in 10.[0123]) func_append compile_command " ${wl}-bind_at_load" func_append finalize_command " ${wl}-bind_at_load" ;; esac fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $compile_deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $compile_deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done compile_deplibs="$new_libs" func_append compile_command " $compile_deplibs" func_append finalize_command " $finalize_deplibs" if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. for libdir in $rpath $xrpath; do # This is the magic to use -rpath. case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done fi # Now hardcode the library paths rpath= hardcode_libdirs= for libdir in $compile_rpath $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; ::) dllsearchpath=$libdir;; *) func_append dllsearchpath ":$libdir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi compile_rpath="$rpath" rpath= hardcode_libdirs= for libdir in $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) func_append finalize_perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi finalize_rpath="$rpath" if test -n "$libobjs" && test "$build_old_libs" = yes; then # Transform all the library objects into standard objects. compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` fi func_generate_dlsyms "$outputname" "@PROGRAM@" "no" # template prelinking step if test -n "$prelink_cmds"; then func_execute_cmds "$prelink_cmds" 'exit $?' fi wrappers_required=yes case $host in *cegcc* | *mingw32ce*) # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. wrappers_required=no ;; *cygwin* | *mingw* ) if test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; *) if test "$need_relink" = no || test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; esac if test "$wrappers_required" = no; then # Replace the output file specification. compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` link_command="$compile_command$compile_rpath" # We have no uninstalled library dependencies, so finalize right now. exit_status=0 func_show_eval "$link_command" 'exit_status=$?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Delete the generated files. if test -f "$output_objdir/${outputname}S.${objext}"; then func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' fi exit $exit_status fi if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" fi if test -n "$finalize_shlibpath"; then finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" fi compile_var= finalize_var= if test -n "$runpath_var"; then if test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi if test -n "$finalize_perm_rpath"; then # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do func_append rpath "$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test "$no_install" = yes; then # We don't need to create a wrapper script. link_command="$compile_var$compile_command$compile_rpath" # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $opt_dry_run || $RM $output # Link the executable and exit func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi exit $EXIT_SUCCESS fi if test "$hardcode_action" = relink; then # Fast installation is not supported link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" func_warning "this platform does not like uninstalled shared libraries" func_warning "\`$output' will be relinked during installation" else if test "$fast_install" != no; then link_command="$finalize_var$compile_command$finalize_rpath" if test "$fast_install" = yes; then relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` else # fast_install is set to needless relink_command= fi else link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" fi fi # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output_objdir/$outputname" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Now create the wrapper script. func_verbose "creating $output" # Quote the relink command for shipping. if test -n "$relink_command"; then # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done relink_command="(cd `pwd`; $relink_command)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` fi # Only actually do things if not in dry run mode. $opt_dry_run || { # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) func_stripname '' '.exe' "$output" output=$func_stripname_result ;; esac # test for cygwin because mv fails w/o .exe extensions case $host in *cygwin*) exeext=.exe func_stripname '' '.exe' "$outputname" outputname=$func_stripname_result ;; *) exeext= ;; esac case $host in *cygwin* | *mingw* ) func_dirname_and_basename "$output" "" "." output_name=$func_basename_result output_path=$func_dirname_result cwrappersource="$output_path/$objdir/lt-$output_name.c" cwrapper="$output_path/$output_name.exe" $RM $cwrappersource $cwrapper trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 func_emit_cwrapperexe_src > $cwrappersource # The wrapper executable is built using the $host compiler, # because it contains $host paths and files. If cross- # compiling, it, like the target executable, must be # executed on the $host or under an emulation environment. $opt_dry_run || { $LTCC $LTCFLAGS -o $cwrapper $cwrappersource $STRIP $cwrapper } # Now, create the wrapper script for func_source use: func_ltwrapper_scriptname $cwrapper $RM $func_ltwrapper_scriptname_result trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 $opt_dry_run || { # note: this script will not be executed, so do not chmod. if test "x$build" = "x$host" ; then $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result else func_emit_wrapper no > $func_ltwrapper_scriptname_result fi } ;; * ) $RM $output trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 func_emit_wrapper no > $output chmod +x $output ;; esac } exit $EXIT_SUCCESS ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do if test "$build_libtool_libs" = convenience; then oldobjs="$libobjs_save $symfileobj" addlibs="$convenience" build_libtool_libs=no else if test "$build_libtool_libs" = module; then oldobjs="$libobjs_save" build_libtool_libs=no else oldobjs="$old_deplibs $non_pic_objects" if test "$preload" = yes && test -f "$symfileobj"; then func_append oldobjs " $symfileobj" fi fi addlibs="$old_convenience" fi if test -n "$addlibs"; then gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $addlibs func_append oldobjs " $func_extract_archives_result" fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then cmds=$old_archive_from_new_cmds else # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append oldobjs " $func_extract_archives_result" fi # POSIX demands no paths to be encoded in archives. We have # to avoid creating archives with duplicate basenames if we # might have to extract them afterwards, e.g., when creating a # static archive out of a convenience library, or when linking # the entirety of a libtool archive into another (currently # not supported by libtool). if (for obj in $oldobjs do func_basename "$obj" $ECHO "$func_basename_result" done | sort | sort -uc >/dev/null 2>&1); then : else echo "copying selected object files to avoid basename conflicts..." gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_mkdir_p "$gentop" save_oldobjs=$oldobjs oldobjs= counter=1 for obj in $save_oldobjs do func_basename "$obj" objbase="$func_basename_result" case " $oldobjs " in " ") oldobjs=$obj ;; *[\ /]"$objbase "*) while :; do # Make sure we don't pick an alternate name that also # overlaps. newobj=lt$counter-$objbase func_arith $counter + 1 counter=$func_arith_result case " $oldobjs " in *[\ /]"$newobj "*) ;; *) if test ! -f "$gentop/$newobj"; then break; fi ;; esac done func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" func_append oldobjs " $gentop/$newobj" ;; *) func_append oldobjs " $obj" ;; esac done fi func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result eval cmds=\"$old_archive_cmds\" func_len " $cmds" len=$func_len_result if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then cmds=$old_archive_cmds elif test -n "$archiver_list_spec"; then func_verbose "using command file archive linking..." for obj in $oldobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > $output_objdir/$libname.libcmd func_to_tool_file "$output_objdir/$libname.libcmd" oldobjs=" $archiver_list_spec$func_to_tool_file_result" cmds=$old_archive_cmds else # the command line is too long to link in one step, link in parts func_verbose "using piecewise archive linking..." save_RANLIB=$RANLIB RANLIB=: objlist= concat_cmds= save_oldobjs=$oldobjs oldobjs= # Is there a better way of finding the last object in the list? for obj in $save_oldobjs do last_oldobj=$obj done eval test_cmds=\"$old_archive_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 for obj in $save_oldobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result func_append objlist " $obj" if test "$len" -lt "$max_cmd_len"; then : else # the above command should be used before it gets too long oldobjs=$objlist if test "$obj" = "$last_oldobj" ; then RANLIB=$save_RANLIB fi test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" objlist= len=$len0 fi done RANLIB=$save_RANLIB oldobjs=$objlist if test "X$oldobjs" = "X" ; then eval cmds=\"\$concat_cmds\" else eval cmds=\"\$concat_cmds~\$old_archive_cmds\" fi fi fi func_execute_cmds "$cmds" 'exit $?' done test -n "$generated" && \ func_show_eval "${RM}r$generated" # Now create the libtool archive. case $output in *.la) old_library= test "$build_old_libs" = yes && old_library="$libname.$libext" func_verbose "creating $output" # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done # Quote the link command for shipping. relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` if test "$hardcode_automatic" = yes ; then relink_command= fi # Only create the output if not a dry run. $opt_dry_run || { for installed in no yes; do if test "$installed" = yes; then if test -z "$install_libdir"; then break fi output="$output_objdir/$outputname"i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) func_basename "$deplib" name="$func_basename_result" func_resolve_sysroot "$deplib" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` test -z "$libdir" && \ func_fatal_error "\`$deplib' is not a valid libtool archive" func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" ;; -L*) func_stripname -L '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -L$func_replace_sysroot_result" ;; -R*) func_stripname -R '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -R$func_replace_sysroot_result" ;; *) func_append newdependency_libs " $deplib" ;; esac done dependency_libs="$newdependency_libs" newdlfiles= for lib in $dlfiles; do case $lib in *.la) func_basename "$lib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "\`$lib' is not a valid libtool archive" func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" ;; *) func_append newdlfiles " $lib" ;; esac done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in *.la) # Only pass preopened files to the pseudo-archive (for # eventual linking with the app. that links it) if we # didn't already link the preopened objects directly into # the library: func_basename "$lib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "\`$lib' is not a valid libtool archive" func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" ;; esac done dlprefiles="$newdlprefiles" else newdlfiles= for lib in $dlfiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlfiles " $abs" done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlprefiles " $abs" done dlprefiles="$newdlprefiles" fi $RM $output # place dlname in correct position for cygwin # In fact, it would be nice if we could use this code for all target # systems that can't hard-code library paths into their executables # and that have no shared library path variable independent of PATH, # but it turns out we can't easily determine that from inspecting # libtool variables, so we have to hard-code the OSs to which it # applies here; at the moment, that means platforms that use the PE # object format with DLL files. See the long comment at the top of # tests/bindir.at for full details. tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) # If a -bindir argument was supplied, place the dll there. if test "x$bindir" != x ; then func_relative_path "$install_libdir" "$bindir" tdlname=$func_relative_path_result$dlname else # Otherwise fall back on heuristic. tdlname=../bin/$dlname fi ;; esac $ECHO > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='$tdlname' # Names of this library. library_names='$library_names' # The name of the static archive. old_library='$old_library' # Linker flags that can not go in dependency_libs. inherited_linker_flags='$new_inherited_linker_flags' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Names of additional weak libraries provided by this library weak_library_names='$weak_libs' # Version information for $libname. current=$current age=$age revision=$revision # Is this an already installed library? installed=$installed # Should we warn about portability when linking against -modules? shouldnotlink=$module # Files to dlopen/dlpreopen dlopen='$dlfiles' dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" if test "$installed" = no && test "$need_relink" = yes; then $ECHO >> $output "\ relink_command=\"$relink_command\"" fi done } # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' ;; esac exit $EXIT_SUCCESS } { test "$opt_mode" = link || test "$opt_mode" = relink; } && func_mode_link ${1+"$@"} # func_mode_uninstall arg... func_mode_uninstall () { $opt_debug RM="$nonopt" files= rmforce= exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" for arg do case $arg in -f) func_append RM " $arg"; rmforce=yes ;; -*) func_append RM " $arg" ;; *) func_append files " $arg" ;; esac done test -z "$RM" && \ func_fatal_help "you must specify an RM program" rmdirs= for file in $files; do func_dirname "$file" "" "." dir="$func_dirname_result" if test "X$dir" = X.; then odir="$objdir" else odir="$dir/$objdir" fi func_basename "$file" name="$func_basename_result" test "$opt_mode" = uninstall && odir="$dir" # Remember odir for removal later, being careful to avoid duplicates if test "$opt_mode" = clean; then case " $rmdirs " in *" $odir "*) ;; *) func_append rmdirs " $odir" ;; esac fi # Don't error if the file doesn't exist and rm -f was used. if { test -L "$file"; } >/dev/null 2>&1 || { test -h "$file"; } >/dev/null 2>&1 || test -f "$file"; then : elif test -d "$file"; then exit_status=1 continue elif test "$rmforce" = yes; then continue fi rmfiles="$file" case $name in *.la) # Possibly a libtool archive, so verify it. if func_lalib_p "$file"; then func_source $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do func_append rmfiles " $odir/$n" done test -n "$old_library" && func_append rmfiles " $odir/$old_library" case "$opt_mode" in clean) case " $library_names " in *" $dlname "*) ;; *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; esac test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" ;; uninstall) if test -n "$library_names"; then # Do each command in the postuninstall commands. func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' fi # FIXME: should reinstall the best remaining shared library. ;; esac fi ;; *.lo) # Possibly a libtool object, so verify it. if func_lalib_p "$file"; then # Read the .lo file func_source $dir/$name # Add PIC object to the list of files to remove. if test -n "$pic_object" && test "$pic_object" != none; then func_append rmfiles " $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. if test -n "$non_pic_object" && test "$non_pic_object" != none; then func_append rmfiles " $dir/$non_pic_object" fi fi ;; *) if test "$opt_mode" = clean ; then noexename=$name case $file in *.exe) func_stripname '' '.exe' "$file" file=$func_stripname_result func_stripname '' '.exe' "$name" noexename=$func_stripname_result # $file with .exe has already been added to rmfiles, # add $file without .exe func_append rmfiles " $file" ;; esac # Do a test to see if this is a libtool program. if func_ltwrapper_p "$file"; then if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" relink_command= func_source $func_ltwrapper_scriptname_result func_append rmfiles " $func_ltwrapper_scriptname_result" else relink_command= func_source $dir/$noexename fi # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles func_append rmfiles " $odir/$name $odir/${name}S.${objext}" if test "$fast_install" = yes && test -n "$relink_command"; then func_append rmfiles " $odir/lt-$name" fi if test "X$noexename" != "X$name" ; then func_append rmfiles " $odir/lt-${noexename}.c" fi fi fi ;; esac func_show_eval "$RM $rmfiles" 'exit_status=1' done # Try to remove the ${objdir}s in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then func_show_eval "rmdir $dir >/dev/null 2>&1" fi done exit $exit_status } { test "$opt_mode" = uninstall || test "$opt_mode" = clean; } && func_mode_uninstall ${1+"$@"} test -z "$opt_mode" && { help="$generic_help" func_fatal_help "you must specify a MODE" } test -z "$exec_cmd" && \ func_fatal_help "invalid operation mode \`$opt_mode'" if test -n "$exec_cmd"; then eval exec "$exec_cmd" exit $EXIT_FAILURE fi exit $exit_status # The TAGs below are defined such that we never get into a situation # in which we disable both kinds of libraries. Given conflicting # choices, we go for a static library, that is the most portable, # since we can't tell whether shared libraries were disabled because # the user asked for that or because the platform doesn't support # them. This is particularly important on AIX, because we don't # support having both static and shared libraries enabled at the same # time on that platform, so we default to a shared-only configuration. # If a disable-shared tag is given, we'll fallback to a static-only # configuration. But we'll never go from static-only to shared-only. # ### BEGIN LIBTOOL TAG CONFIG: disable-shared build_libtool_libs=no build_old_libs=yes # ### END LIBTOOL TAG CONFIG: disable-shared # ### BEGIN LIBTOOL TAG CONFIG: disable-static build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` # ### END LIBTOOL TAG CONFIG: disable-static # Local Variables: # mode:shell-script # sh-indentation:2 # End: # vi:sw=2 xfsdump-3.1.6+nmu1/doc/0000755000000000000000000000000012643557274011535 5ustar xfsdump-3.1.6+nmu1/doc/global_hdr.gif0000644000000000000000000000402712607344125014311 0ustar GIF87a¥ž€ÿÿÿ,¥žþŒ©Ëí£œ´Ú‹³Þ¼û†âøftV&@¢lû*iYžñq;ù´/«ñãô<ÃàŠ6b3œd&nRJUÓ;â^Í@q*“%½Þ®6ŒBäÆe³mÚLu— $ÓîËÓÔ| Ó Ø%H¦dxx'HUxUV¶5wHXGÉøˆXsæ8 ¸¦é(©#æ)™uš¹Ã…yÄú¤øzgä:šf»eš ‹ÛÚ·ØKøõéZl%öÊ;wìÙÙ™ˆhÙ8M\Í;ù§¢C i©ªÆÙ–ȦE;éG5¦Þ—ÔÌS÷sFß²Ïß½×/ @"þ <ˆ0¡Â… :|1¢Ä‰+Z¼ˆ1£Æþ;zü2¤È‘$Kš<‰2¥Ê•,Îz 3¦Ì™4kÚ¼ s¢Á–ß$îäiÏ'Ð?÷ âQ¤Ê”^`7t)QôðA%)UDÑyÜXf ±õ8ž_A„-wÕdÙgO­µø¶C[gquÚµÀu¬×»TËíjY· UuFÒ† Œ…©Y¾Š…0nœX(dÇ’'GŽˆhf ›su쌷!h°-‡®Ï smƲq'Íáèe±ç\v$hÝ>È}ÀôZ«“Vë^Èk‘ìI™ÎP¿éýž˜þáúG `îgœ€.p1XzÕ«Ù1Z~ÖˆÍmÁ`ç‹nѼg`wÞà†FS¿`8Õ€ö½Ã`ó‘x܆‹™X ‹¸„¸2¾Øáw4~˜ þH‚„zX‘EUð°Æ x ÎÇV|NèÝ“´å(¥zTViß•XBùÐW祆‘>RGÐEb.wš\a:ÉÌ%¯½ùÆsöxzáǦ†«)¢a‹?bggYg Ç¥o<ú)Š4Ð$Š(™ZrY#rµÜã<|6úTž. ©RðèoxÂ¥¡=ÞöÜ©Ù![¦¤Þ#G¬(®QÕ’HŠ+en‰æBƒ~¦)–¿ºÈk¯ »þ²Èj¤l±VFél§ÍE«ŸlÔVËÛµCB«íŒÓvKè±xY)JÍöUJºð½êì¹àzëë»áº$/¼âÖÛê·òº»o°Uòû.Àà Ü-ÁÚ|-ÂÔ*-Ãíú+¥ÃÅJÌ«²8]ŒqÆoLñ– ñ“ÿ2߇ƒËºº«º*ûuçaÁB•×—fÎÌZW0c…³Î1û ÒÈíLôHBûüÌÊ,s[›Ë?Ó×sÌy™ëï­ù$ 5»—¼ßÑ&s}Ÿ×]ƒmš×_"––ÍY2]ܳ8®}ÛÆëö¨-·IM‚h5È7)éÄ)ŽÚ'M†¨Ñý æ6 bŠ­¾IMÅá‡VþÝ*Gu,9Ü~¾””áójžmw@ŽiꔈÞ(ºµÅÅú3órÚÕR#[%©Ê´VzUa´žsÝ¡÷«uÅd½Á{<üdb‡`íïuü9I¿¼îÝE“CWýrSº„‚jWt²Þâ ÒT¤¿.q†äJ êÆå´§­dó»ŸÑ¢VA ]0~Jr ‚z÷‘îaï}+!÷H¨‚…)Q!~®@@5qÈ í:âaV $ß̳* –É~|ШW.űNTÚÿ¤ã Êý&Ä™þîòÁŸÓ}®ILŶ<Å-щ_ŒÔèv"{5Qµ“y('+y|0†¦cc½nȾʇsÌb!Õôø5@ŽMÌ#$ô I=?žîC¤õ©=HzO’#¤ä }R¾Ljr“t,ÑéÀß ”%a$üˆˆ —%$%Ïx™B_nЖfÖˆ)2cÊ ˜-Tæ™ùGdRšƒ¤f!­yHl&š‹tf½éSö’›¡tÜÀÀ ,r–g0ÕùKm>Rž‘¤ç$íYI|^RŸ«äg+ýùJ€ÆR—[ƒç0 *<ƒ¡©h-þ:K‡æÒŽÀ“è8-úNŒ6S¡ËÔh4!zKv“£Ïi9éöI’~S¥ádg²\ÚG–¦Ó¤ë”i;ašwn”¦ñi1múR Æ”§¥è(»È¤~B4VÈiÍCZn0u PÕ‘):9TŸJ5©­jâjPŸºAƒ#µe±º¦ø¡"]j=®¦4Á5§8M+QêÕ„Õõfsµ«VŸ¢FU† lšrxؼ¶gÒJìÁd§vì Ę¡SåQ§pbkÕèš4*‰ˆ½—q.†Ã+_§’Üåf–*ù.=LÛÍèXQîµ> ,ê"•9G-5¶ò¬¢>ý»Å W±‚Äœ(ûÜY±Ö©FâWkÚŠþµšÛHñ¢Ó®>ö¨wíhw³yÞm–·¤ég{ëùÞ{Æ7ŸóÝg}•ÊÜ]®w¥ûmi_ùÚß™Þ÷Ÿk~ à›þ÷? jƒ³zà„>˜® à^\`ªŽ÷œ.à…-Üa—ÆÃnh†Ÿºá‚}ØÃ!êˆAôŠMadêÜ»Gó¾#{Ý(]xƒ?¾hz­È ¯ó~½üùôëÛ¿?¿þýüþûûÿ`€H`ˆ`‚ .È`ƒ>a„NHa…^ˆa†nÈa‡~bˆ"ŽHb‰&žˆbŠ*®Èb‹0cŒ2ÎHc6ÞˆcŽ:îÈc>þdBI¤‹Ø=(~I:³$hF6d”ç5YÑ“ PI–ói¹ÕtVBé —ë‰É…˜d~É’gN‰ž™hj¦”à¹ù¦kÎ)§wtÖyež Þ Äž|zhw…rwh‚ÊA¢Ò9¤:,Êè~*(iyvVJè¥ fŠ¥œ^*_¥îuj ¢Žzƒ©fõê «²ZPœ¶â¹)­Äê¯-ùš„—º’ê)‚À¾0þë°qýYl¤Â*KÁ±I;Z›ÏBûÝ­®Z›+¶µ6Hí3ᮬ·N>✴A²Ñ¡‰=rK’Ã{G·¡nhlßjMT•åkA¾„unÀþÂ%g†w¤¬×ÚÖ^§lÈî1û ¯L¥´­ÅÙb¡1[/¦p½2”«\ªR­)¼,áÏr0ïæäÀŒWåvf|ƒsp/ÏœUó×êT´­†3nýèö.ûP_Á°kÒ÷(ÑœÍK·Ö×OÓ oA<¯#Oº™éƒÎÍdg,r-csæñ[*%õLlÿ{Ür£pÚ—y6wÛ½¶):™–—Þ—Õ¼pà°¶\UF5¥þYHÄBõÄq­€[39M®\tù䂽·Ð)/Ø?¨ÜgÀ†½K挙Í7·ÙBÄSçñÒLw•¬QùíåÞØî•u3S‹M¦XÕÊŸm·ede²ëëÒâwì%ùöXôiBGuï+™Ýýèx‡ìxÝÉ#Ÿ:?Ë×-ºÎwí9Âôv>õ­}Ôôs5ïÚ•ÌPÁ³‹6âö¿»yNp´ë ‡ò¡o‚—ƒó@³=˜1zŠsŸEˆe¯‹-{ D] èA\}Nk«yÓ®÷½ö0Œa-œ“ä(§…¾‰áqt˜›^Xއ2sÚQ}ò›XÇ‚hC¤)‡(PÓÍþaš–DÞ™ªYjšÖÈBX °QGŒ| c—ªÂê‘+jøâbÌ6šÏ‰îÑâ‡àX&7†e»’cˆð¸@jAjÜ¡üH¢fÐvl”º ¸Âm¼á£F*DžH‘ÄÀ`ÏbTÀƒýp†| fHg5F -¢¼MRJI@0A“*âä5¼²Š«M02º«ß÷æ¨6ÃÍï/XÛåøŽyºò- Q˜Äa#­dK`ÂÃpÊ,H¦qÀšr™üšæoŒ‰¿»ø%~æc3aˆ-E>g}<«fñÄÌ_æÌ)´K;Áé=»T0}ødO3W9,ëÄO)¸C¤ w>Kާ‚ž¡ávþü}6|Ïh:wUú2hç* 3âYÎú-™)|(T@Ò”ŠÆL5—<×ç»ÓñS‚½d"0—Uϸ³} §MºÅ)Ñ¥Ýà`JJŽ*¦¦ó¼ió|ú˜¤šÒ1ïj?—É`¨†¨ïSn²˜C…’Š»xáUùy“ëqï“bÝWTÜ€=äè/–OD)W¹yÆJŽGkš+3ëºBBH°V…å6˨׽š³_;ëEµÅ,6Éò®Žía«c;CR¶°º¬¢2‹±Í:u@žåAié¨YÑÞeýk!U»ÚvR lcÛY=õµ·­¦ÀU۩ݶ©òí½$þË[Ø·ºEÕ97»\DweÈM­r›+Ûà:r¸¸ýÏtið]…ZŠ»hÍmk›\Õ†÷dØÅjzEK¤øÊw¾ô­¯}ï‹ßüê×Gä-/ÅÚ߃C°ÉÕ¡xÁïÕ‚ aÃŽÀ®pHMô` Wx½¨¢°†ÌaðyøÃ×ÕU†ILÔ©¥(61tGÜbF©x?0Ž14 |b¯hÆo¬±ŽEÄcL±øÇ r˜|Ld yBHN2pLÏgBùSޤ”«ÌŸ%OxÈXVR—ûÈå/kWÌD3™uf949Í/ѲŒ×Ìf&Å;fžsí¼Æ:ã9<{N‚žûìþ0@Ÿ ΂®D¡AèC?WÑ1H4£QûèI9:Ò‡¥´¤iié¢fúÒ˜ÞôK=žIÚÍqÎ1¥IÝgS ÕŠ5–Y}jWÿÖ V5”i jµâº½¹F”¬¼ë^{µÓÀ6iÍÕ`[¨Nö²]…ìQ)ûÙWŠö›¦Mm<4›OØÎv‰ý¤n{;ÏW6’¸Ç Ÿm'Ý(²u‰ÎÍnDƒ;CðŽ7§Ë}¡p½ Lë²·iÕýdÆ \f{MXc%êïPY;»„KÎ)»*ÜÕÖûÕ ×'9:¶T.çgè\ 3Šï„# à4ŽÆ…ÙÁ}—4'#­êÄ«ìnËïx‘kS:Äþ¶‘Sä"ù˜‰ÓȆ§KD›ù~÷òRW|·ïkŠøäušÇsç<HÌéÚô¬»²ƒxBWWuXùüWŒÕ*Mô¥Ÿ ,‹>tåZ;vI»’æ~g»ßzé´Õ»˜¯>H¿Ï™ïu|ª OIÃï‰Wü£`Ç{òX@¼ä“LùF1þògÎ|™çÍùŃÞ6¡¹çãUz»{~ô©ïµ‚iV÷Ö*wv•}ëŸwšýê~÷¼ï½ïüà øÄ×owýûJw1ÙÀK¾bÅkûùÑ—yooý€oëúÓÏþöµ_ìg¹úãçþ§Í ~L w€Ÿ"ÉÍï|¯þ(þxuv÷ËŸþöÃßýç¥Ø}ç€%v~Þå^¶88{â÷~ù7€êå€ý§€ËG€ô§i¤Å€Ü6ùfxø}%~#H¸€ ¨‚!YxH•Ó.!‡,dFXrƒ×èÕ3ÛU€µA\÷—ƒÚÆzÈVg"0µ7Y_ÄoÃFpS`H8r‹¤R37s9ÅY•Uƒac[eöp fT x³Ô"ã( ²SeˆJZן q5”…¦ƒË0T@؃¶ð6Àð†ÏSoˆ5¨zf‡E¹¤: 3ˆ#6ø ‡rtMMóO¸qª4G3Uäte³OA4RˆþBÓAù„Y\HL&tJØ8ß´Ý>PÇ9(ä‰$cÚãI+‚·„Bµã8ya‹kóŠìÛCs-—:}sA|v¾Qq,¢˜kpMMµ9kx~«¨M˜@ÏèrýƒLz>¨(>k5‘a:%=Ø.2øQ:'SRÁ‰r¸N¢ƒÍ¸‹›c€T„¬XOÏ£ÃØ‰þbf݈Œņ>¥k±Ct¨,wt@CéÀ‰IP눅¿UITõØx1RUõ§ŽD‡ÿxT”„¹Åd‘ Šö£6¸äÆ:ŠeŠfØQKñ‰y\M8BÃ<1´’£Iq!@³þCŠ·èNçH‹Uˆ“G™‹ i””“è#e dMßXŒe‘G‡“ŽòH„XiÕolGZWœƒoIxˆQD–o ‰@Ô–\9³Ô7¤‰Én™vpé‡_%ŒÎd铦#((†£©0h—O¡1²XBÆYxÈY\¸98™­Ø“wÒɘ¤™›Ã´TåÈ™ËØ‚¨ÉI¬sBÎYˆê –ïÙÊy–O(—|coiy]ؘøé-5 Ÿæ¹‚ñ‰ .8 "¸š©Ù /è µ H õ )¸ ªšš¡Ø›hb ùy¡¢Ù¡!*ê¡y§¢(:&Þ٢ܩú9J¢ê¢é£ *¡=¡èù¡j£3Ê£?Z£>JY#J¤CÊZEz¤FzžIš{ÅG¥Uj¥WŠ¥Yª¥[Ê¥8R;xfsdump-3.1.6+nmu1/doc/inventory.obj0000644000000000000000000003627612607344125014271 0ustar %TGIF 4.1.16 state(0,37,100.000,0,0,0,16,1,9,1,1,0,0,1,0,1,0,'Courier',0,80640,0,0,0,10,0,0,0,1,0,16,0,0,1,1,1,1,1088,1408,1,0,2880,0). % % @(#)$Header: /home/cattelan/osspush/CVSROOT/xfs-cmds/xfsdump/doc/inventory.obj,v 1.1 2002/03/15 06:01:08 tes Exp $ % %W% % unit("1 pixel/pixel"). color_info(11,65535,0,[ "magenta", 65535, 0, 65535, 65535, 0, 65535, 1, "red", 65535, 0, 0, 65535, 0, 0, 1, "green", 0, 65535, 0, 0, 65535, 0, 1, "blue", 0, 0, 65535, 0, 0, 65535, 1, "yellow", 65535, 65535, 0, 65535, 65535, 0, 1, "pink", 65535, 40606, 44461, 65535, 40606, 44461, 1, "cyan", 0, 65535, 65535, 0, 65535, 65535, 1, "CadetBlue", 12336, 29041, 29812, 12336, 29041, 29812, 1, "white", 65535, 65535, 65535, 65535, 65535, 65535, 1, "black", 0, 0, 0, 0, 0, 0, 1, "DarkSlateGray", 3598, 8995, 8995, 3598, 8995, 8995, 1 ]). script_frac("0.6"). fg_bg_colors('black','white'). page(1,"",1,''). text('black',96,660,3,0,1,288,46,111,12,4,0,0,0,0,2,288,46,0,0,"",0,0,0,0,672,'',[ minilines(288,46,0,0,0,0,0,[ mini_line(135,12,4,0,0,0,[ str_block(0,126,12,4,0,-1,0,0,0,[ str_seg('black','Courier-Bold',1,80640,126,12,4,0,-1,0,0,0,0,0, "session header")]), str_block(0,9,12,3,0,-8,0,0,0,[ str_seg('black','Courier',0,80640,9,12,3,0,-8,0,0,0,0,0, " ")]) ]), mini_line(288,12,3,0,0,0,[ str_block(0,288,12,3,0,-8,0,0,0,[ str_seg('black','Courier',0,80640,288,12,3,0,-8,0,0,0,0,0, "(session offset, stream offset, ")]) ]), mini_line(189,12,3,0,0,0,[ str_block(0,189,12,3,0,-4,0,0,0,[ str_seg('black','Courier',0,80640,189,12,3,0,-4,0,0,0,0,0, "dump-time, level,...)")]) ]) ])]). box('black','',64,64,416,272,0,1,1,0,0,0,0,0,0,'1',0,[ ]). poly('black','',2,[ 64,96,416,96],0,2,1,1,0,0,0,0,0,0,0,'2',0,0, "0","",[ 0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[ ]). text('black',112,68,1,0,1,225,15,5,12,3,0,0,0,0,2,225,15,0,0,"",0,0,0,0,80,'',[ minilines(225,15,0,0,0,0,0,[ mini_line(225,12,3,0,0,0,[ str_block(0,225,12,3,0,-4,0,0,0,[ str_seg('black','Courier',0,80640,225,12,3,0,-4,0,0,0,0,0, "number of items (counter)")]) ]) ])]). poly('black','',2,[ 64,128,416,128],0,2,1,7,0,0,0,0,0,0,0,'2',0,0, "0","",[ 0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[ ]). text('black',96,100,1,0,1,45,15,8,12,3,0,0,0,0,2,45,15,0,0,"",0,0,0,0,112,'',[ minilines(45,15,0,0,0,0,0,[ mini_line(45,12,3,0,0,0,[ str_block(0,45,12,3,0,-8,0,0,0,[ str_seg('black','Courier',0,80640,45,12,3,0,-8,0,0,0,0,0, "uuid ")]) ]) ])]). text('black',160,100,1,0,1,45,15,10,12,3,0,0,0,0,2,45,15,0,0,"",0,0,0,0,112,'',[ minilines(45,15,0,0,0,0,0,[ mini_line(45,12,3,0,0,0,[ str_block(0,45,12,3,0,-2,0,0,0,[ str_seg('black','Courier',0,80640,45,12,3,0,-2,0,0,0,0,0, "mntpt")]) ]) ])]). text('black',240,100,1,0,1,99,15,12,12,3,0,0,0,0,2,99,15,0,0,"",0,0,0,0,112,'',[ minilines(99,15,0,0,0,0,0,[ mini_line(99,12,3,0,0,0,[ str_block(0,99,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,99,12,3,0,-1,0,0,0,0,0, "device path")]) ]) ])]). poly('black','',2,[ 64,160,416,160],0,1,1,17,0,0,0,0,0,0,0,'1',0,0, "0","",[ 0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[ ]). poly('black','',2,[ 64,192,416,192],0,1,1,18,0,0,0,0,0,0,0,'1',0,0, "0","",[ 0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[ ]). poly('black','',2,[ 144,96,144,272],0,2,1,34,0,0,0,0,0,0,0,'2',0,0, "0","",[ 0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[ ]). poly('black','',2,[ 224,96,224,272],0,2,1,35,0,0,0,0,0,0,0,'2',0,0, "0","",[ 0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[ ]). text('black',176,36,1,0,1,45,16,36,12,4,0,0,0,0,2,45,16,0,0,"",0,0,0,0,48,'',[ minilines(45,16,0,0,0,0,0,[ mini_line(45,12,4,0,0,0,[ str_block(0,45,12,4,0,-1,0,0,0,[ str_seg('black','Courier-Bold',1,80640,45,12,4,0,-1,0,0,0,0,0, "fstab")]) ]) ])]). poly('black','',2,[ 64,224,416,224],0,1,1,38,0,0,0,0,0,0,0,'1',0,0, "0","",[ 0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[ ]). poly('black','',2,[ 64,256,416,256],0,1,1,39,0,0,0,0,0,0,0,'1',0,0, "0","",[ 0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[ ]). text('black',32,132,1,0,1,27,15,40,12,3,0,0,0,0,2,27,15,0,0,"",0,0,0,0,144,'',[ minilines(27,15,0,0,0,0,0,[ mini_line(27,12,3,0,0,0,[ str_block(0,27,12,3,0,-3,0,0,0,[ str_seg('black','Courier',0,80640,27,12,3,0,-3,0,0,0,0,0, "fs1")]) ]) ])]). text('black',32,164,1,0,1,27,15,42,12,3,0,0,0,0,2,27,15,0,0,"",0,0,0,0,176,'',[ minilines(27,15,0,0,0,0,0,[ mini_line(27,12,3,0,0,0,[ str_block(0,27,12,3,0,-3,0,0,0,[ str_seg('black','Courier',0,80640,27,12,3,0,-3,0,0,0,0,0, "fs2")]) ]) ])]). text('black',32,196,1,0,1,27,15,44,12,3,0,0,0,0,2,27,15,0,0,"",0,0,0,0,208,'',[ minilines(27,15,0,0,0,0,0,[ mini_line(27,12,3,0,0,0,[ str_block(0,27,12,3,0,-2,0,0,0,[ str_seg('black','Courier',0,80640,27,12,3,0,-2,0,0,0,0,0, "fs3")]) ]) ])]). text('black',32,228,1,0,1,27,15,48,12,3,0,0,0,0,2,27,15,0,0,"",0,0,0,0,240,'',[ minilines(27,15,0,0,0,0,0,[ mini_line(27,12,3,0,0,0,[ str_block(0,27,12,3,0,-2,0,0,0,[ str_seg('black','Courier',0,80640,27,12,3,0,-2,0,0,0,0,0, "fs4")]) ]) ])]). text('black',240,132,1,0,1,153,15,50,12,3,0,0,0,0,2,153,15,0,0,"",0,0,0,0,144,'',[ minilines(153,15,0,0,0,0,0,[ mini_line(153,12,3,0,0,0,[ str_block(0,153,12,3,0,-2,0,0,0,[ str_seg('black','Courier',0,80640,153,12,3,0,-2,0,0,0,0,0, "/dev/dsk/dks0d2s0")]) ]) ])]). text('black',160,132,1,0,1,36,15,52,12,3,0,0,0,0,2,36,15,0,0,"",0,0,0,0,144,'',[ minilines(36,15,0,0,0,0,0,[ mini_line(36,12,3,0,0,0,[ str_block(0,36,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,36,12,3,0,-1,0,0,0,0,0, "/usr")]) ]) ])]). text('black',80,132,1,0,1,54,15,54,12,3,0,0,0,0,2,54,15,0,0,"",0,0,0,0,144,'',[ minilines(54,15,0,0,0,0,0,[ mini_line(54,12,3,0,0,0,[ str_block(0,54,12,3,0,-2,0,0,0,[ str_seg('black','Courier',0,80640,54,12,3,0,-2,0,0,0,0,0, "0x1234")]) ]) ])]). poly('black','',3,[ 416,144,528,288,368,336],1,1,1,63,0,0,0,0,0,0,0,'1',0,0, "0","",[ 0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[ ]). box('black','',64,336,416,544,0,1,1,69,0,0,0,0,0,'1',0,[ ]). poly('black','',2,[ 64,368,416,368],0,2,1,70,0,0,0,0,0,0,0,'2',0,0, "0","",[ 0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[ ]). poly('black','',2,[ 64,416,416,416],0,2,1,75,0,0,0,0,0,0,0,'2',0,0, "0","",[ 0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[ ]). text('black',112,628,1,0,1,225,15,76,12,3,0,0,0,0,2,225,15,0,0,"",0,0,0,0,640,'',[ minilines(225,15,0,0,0,0,0,[ mini_line(225,12,3,0,0,0,[ str_block(0,225,12,3,0,-4,0,0,0,[ str_seg('black','Courier',0,80640,225,12,3,0,-4,0,0,0,0,0, "number of items (counter)")]) ]) ])]). poly('black','',2,[ 256,368,256,544],0,2,1,77,0,0,0,0,0,0,0,'2',0,0, "0","",[ 0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[ ]). poly('black','',2,[ 160,368,160,544],0,2,1,78,0,0,0,0,0,0,0,'2',0,0, "0","",[ 0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[ ]). text('black',80,372,2,0,1,45,30,81,12,3,0,0,0,0,2,45,30,0,0,"",0,0,0,0,384,'',[ minilines(45,30,0,0,0,0,0,[ mini_line(45,12,3,0,0,0,[ str_block(0,45,12,3,0,-2,0,0,0,[ str_seg('black','Courier',0,80640,45,12,3,0,-2,0,0,0,0,0, "start")]) ]), mini_line(36,12,3,0,0,0,[ str_block(0,36,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,36,12,3,0,-1,0,0,0,0,0, "time")]) ]) ])]). text('black',192,372,2,0,1,36,30,83,12,3,0,0,0,0,2,36,30,0,0,"",0,0,0,0,384,'',[ minilines(36,30,0,0,0,0,0,[ mini_line(27,12,3,0,0,0,[ str_block(0,27,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,27,12,3,0,-1,0,0,0,0,0, "end")]) ]), mini_line(36,12,3,0,0,0,[ str_block(0,36,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,36,12,3,0,-1,0,0,0,0,0, "time")]) ]) ])]). text('black',272,388,1,0,1,99,15,85,12,3,0,0,0,0,2,99,15,0,0,"",0,0,0,0,400,'',[ minilines(99,15,0,0,0,0,0,[ mini_line(99,12,3,0,0,0,[ str_block(0,99,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,99,12,3,0,-1,0,0,0,0,0, "stobj fname")]) ]) ])]). poly('black','',2,[ 64,448,416,448],0,1,1,87,0,0,0,0,0,0,0,'1',0,0, "0","",[ 0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[ ]). poly('black','',2,[ 64,480,416,480],0,1,1,88,0,0,0,0,0,0,0,'1',0,0, "0","",[ 0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[ ]). poly('black','',2,[ 64,512,416,512],0,1,1,89,0,0,0,0,0,0,0,'1',0,0, "0","",[ 0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[ ]). text('black',96,308,1,0,1,81,16,90,12,4,0,0,0,0,2,81,16,0,0,"",0,0,0,0,320,'',[ minilines(81,16,0,0,0,0,0,[ mini_line(81,12,4,0,0,0,[ str_block(0,81,12,4,0,-1,0,0,0,[ str_seg('black','Courier-Bold',1,80640,81,12,4,0,-1,0,0,0,0,0, "Inv Index")]) ]) ])]). box('black','',64,624,416,1344,0,1,1,94,0,0,0,0,0,'1',0,[ ]). poly('black','',3,[ 416,464,512,528,336,624],1,1,1,97,0,0,0,0,0,0,0,'1',0,0, "0","",[ 0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[ ]). text('black',176,580,1,0,1,90,16,99,12,4,0,0,0,0,2,90,16,0,0,"",0,0,0,0,592,'',[ minilines(90,16,0,0,0,0,0,[ mini_line(90,12,4,0,0,0,[ str_block(0,90,12,4,0,-1,0,0,0,[ str_seg('black','Courier-Bold',1,80640,90,12,4,0,-1,0,0,0,0,0, "Stobj File")]) ]) ])]). poly('black','',2,[ 64,656,416,656],0,2,1,101,0,0,0,0,0,0,0,'2',0,0, "0","",[ 0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[ ]). poly('black','',2,[ 64,784,416,784],0,2,1,102,0,0,0,0,0,0,0,'2',0,0, "0","",[ 0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[ ]). text('black',96,900,1,0,1,234,15,106,12,3,0,0,0,0,2,234,15,0,0,"",0,0,0,0,912,'',[ minilines(234,15,0,0,0,0,0,[ mini_line(234,12,3,0,0,0,[ str_block(0,234,12,3,0,-4,0,0,0,[ str_seg('black','Courier',0,80640,234,12,3,0,-4,0,0,0,0,0, "...space for 5 sessions...")]) ]) ])]). poly('black','',2,[ 64,720,416,720],0,1,1,108,0,0,0,0,0,0,0,'1',0,0, "0","",[ 0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[ ]). poly('black','',2,[ 64,880,416,880],0,1,1,109,0,0,0,0,0,0,0,'1',0,0, "0","",[ 0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[ ]). text('black',96,804,3,0,1,306,46,119,12,4,0,0,0,0,2,306,46,0,0,"",0,0,0,0,816,'',[ minilines(306,46,0,0,0,0,0,[ mini_line(63,12,4,0,0,0,[ str_block(0,63,12,4,0,0,0,0,0,[ str_seg('black','Courier-Bold',1,80640,63,12,4,0,0,0,0,0,0,0, "session")]) ]), mini_line(234,12,3,0,0,0,[ str_block(0,234,12,3,0,-8,0,0,0,[ str_seg('black','Courier',0,80640,234,12,3,0,-8,0,0,0,0,0, "(session-id, fsid, label, ")]) ]), mini_line(306,12,3,0,0,0,[ str_block(0,306,12,3,0,-4,0,0,0,[ str_seg('black','Courier',0,80640,306,12,3,0,-4,0,0,0,0,0, "mountpt, devpath, num streams,...)")]) ]) ])]). text('black',112,740,1,0,1,225,15,122,12,3,0,0,0,0,2,225,15,0,0,"",0,0,0,0,752,'',[ minilines(225,15,0,0,0,0,0,[ mini_line(225,12,3,0,0,0,[ str_block(0,225,12,3,0,-4,0,0,0,[ str_seg('black','Courier',0,80640,225,12,3,0,-4,0,0,0,0,0, "...space for 5 headers...")]) ]) ])]). poly('black','',2,[ 64,944,416,944],0,2,1,124,0,0,0,0,0,0,0,'2',0,0, "0","",[ 0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[ ]). text('black',96,948,5,0,1,234,76,132,12,4,0,0,0,0,2,234,76,0,0,"",0,0,0,0,960,'',[ minilines(234,76,0,0,0,0,0,[ mini_line(54,12,4,0,0,0,[ str_block(0,54,12,4,0,0,0,0,0,[ str_seg('black','Courier-Bold',1,80640,54,12,4,0,0,0,0,0,0,0, "stream")]) ]), mini_line(180,12,3,0,0,0,[ str_block(0,180,12,3,0,-4,0,0,0,[ str_seg('black','Courier',0,80640,180,12,3,0,-4,0,0,0,0,0, "(startino#, endino#,")]) ]), mini_line(207,12,3,0,0,0,[ str_block(0,207,12,3,0,-8,0,0,0,[ str_seg('black','Courier',0,80640,207,12,3,0,-8,0,0,0,0,0, "firstmediafile offset, ")]) ]), mini_line(189,12,3,0,0,0,[ str_block(0,189,12,3,0,-4,0,0,0,[ str_seg('black','Courier',0,80640,189,12,3,0,-4,0,0,0,0,0, "lastmediafile offset,")]) ]), mini_line(234,12,3,0,0,0,[ str_block(0,234,12,3,0,-4,0,0,0,[ str_seg('black','Courier',0,80640,234,12,3,0,-4,0,0,0,0,0, "number of media files,...)")]) ]) ])]). poly('black','',2,[ 64,1040,240,1040],0,2,1,135,0,0,0,0,0,0,0,'2',0,0, "0","",[ 0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[ ]). poly('black','',2,[ 240,1040,416,1040],0,1,1,136,0,0,0,0,0,0,0,'1',0,0, "0","",[ 0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[ ]). box('black','',240,1040,416,1136,0,1,1,137,0,0,0,0,0,'1',0,[ ]). text('black',256,1044,5,0,1,162,76,138,12,4,0,0,0,0,2,162,76,0,0,"",0,0,0,0,1056,'',[ minilines(162,76,0,0,0,0,0,[ mini_line(90,12,4,0,0,0,[ str_block(0,90,12,4,0,-1,0,0,0,[ str_seg('black','Courier-Bold',1,80640,90,12,4,0,-1,0,0,0,0,0, "media file")]) ]), mini_line(99,12,3,0,0,0,[ str_block(0,99,12,3,0,-4,0,0,0,[ str_seg('black','Courier',0,80640,99,12,3,0,-4,0,0,0,0,0, "(id, label,")]) ]), mini_line(162,12,3,0,0,0,[ str_block(0,162,12,3,0,-4,0,0,0,[ str_seg('black','Courier',0,80640,162,12,3,0,-4,0,0,0,0,0, "startino#,endino#,")]) ]), mini_line(162,12,3,0,0,0,[ str_block(0,162,12,3,0,-4,0,0,0,[ str_seg('black','Courier',0,80640,162,12,3,0,-4,0,0,0,0,0, "link to next file,")]) ]), mini_line(81,12,3,0,0,0,[ str_block(0,81,12,3,0,-4,0,0,0,[ str_seg('black','Courier',0,80640,81,12,3,0,-4,0,0,0,0,0, "size,...)")]) ]) ])]). poly('black','',2,[ 64,1200,416,1200],0,2,1,145,0,0,0,0,0,0,0,'2',0,0, "0","",[ 0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[ ]). text('black',96,1220,4,0,1,270,61,147,12,4,0,0,0,0,2,270,61,0,0,"",0,0,0,0,1232,'',[ minilines(270,61,0,0,0,0,0,[ mini_line(54,12,4,0,0,0,[ str_block(0,54,12,4,0,0,0,0,0,[ str_seg('black','Courier-Bold',1,80640,54,12,4,0,0,0,0,0,0,0, "stream")]) ]), mini_line(180,12,3,0,0,0,[ str_block(0,180,12,3,0,-4,0,0,0,[ str_seg('black','Courier',0,80640,180,12,3,0,-4,0,0,0,0,0, "(startino#, endino#,")]) ]), mini_line(270,12,3,0,0,0,[ str_block(0,270,12,3,0,-4,0,0,0,[ str_seg('black','Courier',0,80640,270,12,3,0,-4,0,0,0,0,0, "firstmediafile, lastmediafile,")]) ]), mini_line(234,12,3,0,0,0,[ str_block(0,234,12,3,0,-4,0,0,0,[ str_seg('black','Courier',0,80640,234,12,3,0,-4,0,0,0,0,0, "number of media files,...)")]) ]) ])]). poly('black','',2,[ 64,1296,416,1296],0,2,1,148,0,0,0,0,0,0,0,'2',0,0, "0","",[ 0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[ ]). poly('black','',2,[ 240,1136,240,1200],0,1,1,149,0,0,0,0,0,0,0,'1',0,0, "0","",[ 0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[ ]). text('black',256,1156,2,0,1,126,31,150,12,3,0,0,0,0,2,126,31,0,0,"",0,0,0,0,1168,'',[ minilines(126,31,0,0,0,0,0,[ mini_line(126,12,3,0,0,0,[ str_block(0,126,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,126,12,3,0,-1,0,0,0,0,0, "arbitrary # of")]) ]), mini_line(99,12,4,0,0,0,[ str_block(0,90,12,4,0,-1,0,0,0,[ str_seg('black','Courier-Bold',1,80640,90,12,4,0,-1,0,0,0,0,0, "media file")]), str_block(0,9,12,3,0,-2,0,0,0,[ str_seg('black','Courier',0,80640,9,12,3,0,-2,0,0,0,0,0, "s")]) ]) ])]). poly('black','',3,[ 112,688,32,752,64,800],1,1,1,157,0,0,0,0,0,0,0,'1',0,0, "0","",[ 0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[ ]). poly('black','',3,[ 304,688,496,864,416,960],1,1,1,160,0,0,0,0,0,0,0,'1',0,0, "0","",[ 0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[ ]). poly('black','',3,[ 288,992,480,1024,416,1056],1,1,1,166,0,0,0,0,0,0,0,'1',0,0, "0","",[ 0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[ ]). poly('black','',3,[ 288,1008,480,1088,416,1152],1,1,1,167,0,0,0,0,0,0,0,'1',0,0, "0","",[ 0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[ ]). text('black',112,1316,1,0,1,261,15,172,12,3,0,0,0,0,2,261,15,0,0,"",0,0,0,0,1328,'',[ minilines(261,15,0,0,0,0,0,[ mini_line(261,12,3,0,0,0,[ str_block(0,261,12,3,0,-4,0,0,0,[ str_seg('black','Courier',0,80640,261,12,3,0,-4,0,0,0,0,0, "...streams and media files...")]) ]) ])]). text('black',112,340,1,0,1,225,15,173,12,3,0,0,0,0,2,225,15,0,0,"",0,0,0,0,352,'',[ minilines(225,15,0,0,0,0,0,[ mini_line(225,12,3,0,0,0,[ str_block(0,225,12,3,0,-4,0,0,0,[ str_seg('black','Courier',0,80640,225,12,3,0,-4,0,0,0,0,0, "number of items (counter)")]) ]) ])]). xfsdump-3.1.6+nmu1/doc/files.obj0000644000000000000000000002257112607344125013327 0ustar %TGIF 4.1.16 state(0,37,100.000,0,0,0,16,1,9,1,1,0,0,1,0,1,0,'Courier',0,80640,0,0,0,10,0,0,1,1,0,16,0,0,1,1,1,1,1088,1408,1,0,2880,0). % % @(#)$Header: /home/cattelan/osspush/CVSROOT/xfs-cmds/xfsdump/doc/files.obj,v 1.1 2001/12/18 01:56:03 tes Exp $ % %W% % unit("1 pixel/pixel"). color_info(11,65535,0,[ "magenta", 65535, 0, 65535, 65535, 0, 65535, 1, "red", 65535, 0, 0, 65535, 0, 0, 1, "green", 0, 65535, 0, 0, 65535, 0, 1, "blue", 0, 0, 65535, 0, 0, 65535, 1, "yellow", 65535, 65535, 0, 65535, 65535, 0, 1, "pink", 65535, 40606, 44461, 65535, 40606, 44461, 1, "cyan", 0, 65535, 65535, 0, 65535, 65535, 1, "CadetBlue", 12336, 29041, 29812, 12336, 29041, 29812, 1, "white", 65535, 65535, 65535, 65535, 65535, 65535, 1, "black", 0, 0, 0, 0, 0, 0, 1, "DarkSlateGray", 3598, 8995, 8995, 3598, 8995, 8995, 1 ]). script_frac("0.6"). fg_bg_colors('black','white'). page(1,"",1,''). box('black','',32,96,992,176,0,1,1,340,0,0,0,0,0,'1',0,[ ]). text('black',48,116,2,0,1,54,30,341,12,3,0,0,0,0,2,54,30,0,0,"",0,0,0,0,128,'',[ minilines(54,30,0,0,0,0,0,[ mini_line(36,12,3,0,0,0,[ str_block(0,36,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,36,12,3,0,-1,0,0,0,0,0, "File")]) ]), mini_line(54,12,3,0,0,0,[ str_block(0,54,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,54,12,3,0,-1,0,0,0,0,0, "Header")]) ]) ])]). box('black','',32,96,112,176,0,1,1,342,0,0,0,0,0,'1',0,[ ]). text('black',128,116,3,0,1,54,45,343,12,3,0,0,0,0,2,54,45,-1,0,"",0,0,0,0,128,'',[ minilines(54,45,-1,0,0,0,0,[ mini_line(27,12,3,0,0,0,[ str_block(0,27,12,3,0,-2,0,0,0,[ str_seg('black','Courier',0,80640,27,12,3,0,-2,0,0,0,0,0, "Ext")]) ]), mini_line(54,12,3,0,0,0,[ str_block(0,54,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,54,12,3,0,-1,0,0,0,0,0, "Header")]) ]), mini_line(45,12,3,-1,0,0,[ str_block(0,45,12,3,-1,-1,0,0,0,[ str_seg('black','Courier',0,80640,45,12,3,-1,-1,0,0,0,0,0, "Align")]) ]) ])]). box('black','',112,96,192,176,0,1,1,344,0,0,0,0,0,'1',0,[ ]). text('black',208,116,3,0,1,54,45,345,12,3,0,0,0,0,2,54,45,0,0,"",0,0,0,0,128,'',[ minilines(54,45,0,0,0,0,0,[ mini_line(27,12,3,0,0,0,[ str_block(0,27,12,3,0,-2,0,0,0,[ str_seg('black','Courier',0,80640,27,12,3,0,-2,0,0,0,0,0, "Ext")]) ]), mini_line(54,12,3,0,0,0,[ str_block(0,54,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,54,12,3,0,-1,0,0,0,0,0, "Header")]) ]), mini_line(36,12,3,0,0,0,[ str_block(0,36,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,36,12,3,0,-1,0,0,0,0,0, "Data")]) ]) ])]). box('black','',192,96,272,176,0,1,1,346,0,0,0,0,0,'1',0,[ ]). text('black',448,132,1,0,1,36,15,347,12,3,0,0,0,0,2,36,15,0,0,"",0,0,0,0,144,'',[ minilines(36,15,0,0,0,0,0,[ mini_line(36,12,3,0,0,0,[ str_block(0,36,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,36,12,3,0,-1,0,0,0,0,0, "Data")]) ]) ])]). box('black','',432,96,512,176,0,1,1,348,0,0,0,0,0,'1',0,[ ]). text('black',368,116,3,0,1,54,45,349,12,3,0,0,0,0,2,54,45,0,0,"",0,0,0,0,128,'',[ minilines(54,45,0,0,0,0,0,[ mini_line(27,12,3,0,0,0,[ str_block(0,27,12,3,0,-2,0,0,0,[ str_seg('black','Courier',0,80640,27,12,3,0,-2,0,0,0,0,0, "Ext")]) ]), mini_line(54,12,3,0,0,0,[ str_block(0,54,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,54,12,3,0,-1,0,0,0,0,0, "Header")]) ]), mini_line(36,12,3,0,0,0,[ str_block(0,36,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,36,12,3,0,-1,0,0,0,0,0, "Data")]) ]) ])]). box('black','',352,96,432,176,0,1,1,350,0,0,0,0,0,'1',0,[ ]). text('black',288,132,1,0,1,36,15,351,12,3,0,0,0,0,2,36,15,0,0,"",0,0,0,0,144,'',[ minilines(36,15,0,0,0,0,0,[ mini_line(36,12,3,0,0,0,[ str_block(0,36,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,36,12,3,0,-1,0,0,0,0,0, "Data")]) ]) ])]). box('black','',272,96,352,176,0,1,1,352,0,0,0,0,0,'1',0,[ ]). text('black',528,116,3,0,1,54,45,353,12,3,0,0,0,0,2,54,45,0,0,"",0,0,0,0,128,'',[ minilines(54,45,0,0,0,0,0,[ mini_line(27,12,3,0,0,0,[ str_block(0,27,12,3,0,-2,0,0,0,[ str_seg('black','Courier',0,80640,27,12,3,0,-2,0,0,0,0,0, "Ext")]) ]), mini_line(54,12,3,0,0,0,[ str_block(0,54,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,54,12,3,0,-1,0,0,0,0,0, "Header")]) ]), mini_line(36,12,3,0,0,0,[ str_block(0,36,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,36,12,3,0,-1,0,0,0,0,0, "Hole")]) ]) ])]). box('black','',512,96,592,176,0,1,1,354,0,0,0,0,0,'1',0,[ ]). text('black',608,132,1,0,1,27,15,355,12,3,0,0,0,0,2,27,15,0,0,"",0,0,0,0,144,'',[ minilines(27,15,0,0,0,0,0,[ mini_line(27,12,3,0,0,0,[ str_block(0,27,12,3,0,-4,0,0,0,[ str_seg('black','Courier',0,80640,27,12,3,0,-4,0,0,0,0,0, "...")]) ]) ])]). text('black',656,116,3,0,1,54,45,356,12,3,0,0,0,0,2,54,45,0,0,"",0,0,0,0,128,'',[ minilines(54,45,0,0,0,0,0,[ mini_line(27,12,3,0,0,0,[ str_block(0,27,12,3,0,-2,0,0,0,[ str_seg('black','Courier',0,80640,27,12,3,0,-2,0,0,0,0,0, "Ext")]) ]), mini_line(54,12,3,0,0,0,[ str_block(0,54,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,54,12,3,0,-1,0,0,0,0,0, "Header")]) ]), mini_line(36,12,3,0,0,0,[ str_block(0,36,12,3,0,-2,0,0,0,[ str_seg('black','Courier',0,80640,36,12,3,0,-2,0,0,0,0,0, "Last")]) ]) ])]). box('black','',640,96,720,176,0,1,1,357,0,0,0,0,0,'1',0,[ ]). box('black','',32,96,720,176,0,2,1,358,0,0,0,0,0,'2',0,[ ]). text('black',48,68,1,0,1,342,15,359,12,3,0,0,0,0,2,342,15,0,0,"",0,0,0,0,80,'',[ minilines(342,15,0,0,0,0,0,[ mini_line(342,12,3,0,0,0,[ str_block(0,342,12,3,0,-2,0,0,0,[ str_seg('black','Courier',0,80640,342,12,3,0,-2,0,0,0,0,0, "Regular File (S_IFREG) with attributes")]) ]) ])]). box('black','',720,96,816,176,0,1,1,360,0,0,0,0,0,'1',0,[ ]). text('black',736,116,2,0,1,81,30,361,12,3,0,0,0,0,2,81,30,0,0,"",0,0,0,0,128,'',[ minilines(81,30,0,0,0,0,0,[ mini_line(81,12,3,0,0,0,[ str_block(0,81,12,3,0,-4,0,0,0,[ str_seg('black','Courier',0,80640,81,12,3,0,-4,0,0,0,0,0, "Ext.Attr.")]) ]), mini_line(54,12,3,0,0,0,[ str_block(0,54,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,54,12,3,0,-1,0,0,0,0,0, "Header")]) ]) ])]). text('black',832,132,1,0,1,45,15,362,12,3,0,0,0,0,2,45,15,-1,0,"",0,0,0,0,144,'',[ minilines(45,15,-1,0,0,0,0,[ mini_line(45,12,3,-1,0,0,[ str_block(0,45,12,3,-1,-4,0,0,0,[ str_seg('black','Courier',0,80640,45,12,3,-1,-4,0,0,0,0,0, "Attr.")]) ]) ])]). box('black','',816,96,880,176,0,1,1,363,0,0,0,0,0,'1',0,[ ]). text('black',896,132,1,0,1,45,15,364,12,3,0,0,0,0,2,45,15,-1,0,"",0,0,0,0,144,'',[ minilines(45,15,-1,0,0,0,0,[ mini_line(45,12,3,-1,0,0,[ str_block(0,45,12,3,-1,-4,0,0,0,[ str_seg('black','Courier',0,80640,45,12,3,-1,-4,0,0,0,0,0, "Attr.")]) ]) ])]). box('black','',880,96,944,176,0,1,1,365,0,0,0,0,0,'1',0,[ ]). box('black','',720,96,944,176,0,2,1,366,0,0,0,0,0,'2',0,[ ]). text('black',960,132,1,0,1,27,15,367,12,3,0,0,0,0,2,27,15,0,0,"",0,0,0,0,144,'',[ minilines(27,15,0,0,0,0,0,[ mini_line(27,12,3,0,0,0,[ str_block(0,27,12,3,0,-4,0,0,0,[ str_seg('black','Courier',0,80640,27,12,3,0,-4,0,0,0,0,0, "...")]) ]) ])]). text('black',48,196,1,0,1,198,15,368,12,3,0,0,0,0,2,198,15,0,0,"",0,0,0,0,208,'',[ minilines(198,15,0,0,0,0,0,[ mini_line(198,12,3,0,0,0,[ str_block(0,198,12,3,0,-4,0,0,0,[ str_seg('black','Courier',0,80640,198,12,3,0,-4,0,0,0,0,0, "Symlink File (S_IFLNK)")]) ]) ])]). text('black',48,372,2,0,1,54,30,369,12,3,0,0,0,0,2,54,30,0,0,"",0,0,0,0,384,'',[ minilines(54,30,0,0,0,0,0,[ mini_line(36,12,3,0,0,0,[ str_block(0,36,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,36,12,3,0,-1,0,0,0,0,0, "File")]) ]), mini_line(54,12,3,0,0,0,[ str_block(0,54,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,54,12,3,0,-1,0,0,0,0,0, "Header")]) ]) ])]). box('black','',32,224,112,304,0,1,1,370,0,0,0,0,0,'1',0,[ ]). text('black',128,244,3,0,1,54,45,371,12,3,0,0,0,0,2,54,45,0,0,"",0,0,0,0,256,'',[ minilines(54,45,0,0,0,0,0,[ mini_line(27,12,3,0,0,0,[ str_block(0,27,12,3,0,-2,0,0,0,[ str_seg('black','Courier',0,80640,27,12,3,0,-2,0,0,0,0,0, "Ext")]) ]), mini_line(54,12,3,0,0,0,[ str_block(0,54,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,54,12,3,0,-1,0,0,0,0,0, "Header")]) ]), mini_line(36,12,3,0,0,0,[ str_block(0,36,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,36,12,3,0,-1,0,0,0,0,0, "Data")]) ]) ])]). box('black','',112,224,192,304,0,1,1,372,0,0,0,0,0,'1',0,[ ]). text('black',208,244,3,0,1,54,45,373,12,3,0,0,0,0,2,54,45,0,0,"",0,0,0,0,256,'',[ minilines(54,45,0,0,0,0,0,[ mini_line(36,12,3,0,0,0,[ str_block(0,36,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,36,12,3,0,-1,0,0,0,0,0, "Data")]) ]), mini_line(27,12,3,0,0,0,[ str_block(0,27,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,27,12,3,0,-1,0,0,0,0,0, "for")]) ]), mini_line(54,12,3,0,0,0,[ str_block(0,54,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,54,12,3,0,-1,0,0,0,0,0, "string")]) ]) ])]). box('black','',192,224,272,304,0,1,1,374,0,0,0,0,0,'1',0,[ ]). box('black','',32,224,272,304,0,2,1,375,0,0,0,0,0,'2',0,[ ]). box('black','',32,352,112,432,0,2,1,376,0,0,0,0,0,'2',0,[ ]). box('black','',32,352,112,432,0,1,1,377,0,0,0,0,0,'1',0,[ ]). text('black',48,324,1,0,1,486,15,378,12,3,0,0,0,0,2,486,15,0,0,"",0,0,0,0,336,'',[ minilines(486,15,0,0,0,0,0,[ mini_line(486,12,3,0,0,0,[ str_block(0,486,12,3,0,-4,0,0,0,[ str_seg('black','Courier',0,80640,486,12,3,0,-4,0,0,0,0,0, "Other File (S_IFCHAR|S_IFBLK|S_IFIFO|S_IFNAM|S_IFSOCK)")]) ]) ])]). text('black',48,244,2,0,1,54,30,379,12,3,0,0,0,0,2,54,30,0,0,"",0,0,0,0,256,'',[ minilines(54,30,0,0,0,0,0,[ mini_line(36,12,3,0,0,0,[ str_block(0,36,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,36,12,3,0,-1,0,0,0,0,0, "File")]) ]), mini_line(54,12,3,0,0,0,[ str_block(0,54,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,54,12,3,0,-1,0,0,0,0,0, "Header")]) ]) ])]). xfsdump-3.1.6+nmu1/doc/media_files.obj0000644000000000000000000001127112607344125014461 0ustar %TGIF 4.1.16 state(0,37,100.000,0,0,0,16,1,9,1,1,0,0,1,0,1,0,'Courier',0,80640,0,0,0,10,0,0,0,1,0,16,0,0,1,1,1,1,1088,1408,1,0,2880,0). % % @(#)$Header: /home/cattelan/osspush/CVSROOT/xfs-cmds/xfsdump/doc/media_files.obj,v 1.2 2002/03/01 07:45:12 tes Exp $ % %W% % unit("1 pixel/pixel"). color_info(11,65535,0,[ "magenta", 65535, 0, 65535, 65535, 0, 65535, 1, "red", 65535, 0, 0, 65535, 0, 0, 1, "green", 0, 65535, 0, 0, 65535, 0, 1, "blue", 0, 0, 65535, 0, 0, 65535, 1, "yellow", 65535, 65535, 0, 65535, 65535, 0, 1, "pink", 65535, 40606, 44461, 65535, 40606, 44461, 1, "cyan", 0, 65535, 65535, 0, 65535, 65535, 1, "CadetBlue", 12336, 29041, 29812, 12336, 29041, 29812, 1, "white", 65535, 65535, 65535, 65535, 65535, 65535, 1, "black", 0, 0, 0, 0, 0, 0, 1, "DarkSlateGray", 3598, 8995, 8995, 3598, 8995, 8995, 1 ]). script_frac("0.6"). fg_bg_colors('black','white'). page(1,"",1,''). box('black','',64,192,640,256,0,1,1,310,0,0,0,0,0,'1',0,[ ]). text('black',224,212,1,0,1,81,15,311,12,3,0,0,0,0,2,81,15,0,0,"",0,0,0,0,224,'',[ minilines(81,15,0,0,0,0,0,[ mini_line(81,12,3,0,0,0,[ str_block(0,81,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,81,12,3,0,-1,0,0,0,0,0, "Inode Map")]) ]) ])]). box('black','',192,192,320,256,0,1,1,312,0,0,0,0,0,'1',0,[ ]). text('black',336,212,1,0,1,99,15,313,12,3,0,0,0,0,2,99,15,0,0,"",0,0,0,0,224,'',[ minilines(99,15,0,0,0,0,0,[ mini_line(99,12,3,0,0,0,[ str_block(0,99,12,3,0,-2,0,0,0,[ str_seg('black','Courier',0,80640,99,12,3,0,-2,0,0,0,0,0, "Directories")]) ]) ])]). box('black','',320,192,448,256,0,1,1,314,0,0,0,0,0,'1',0,[ ]). text('black',464,212,1,0,1,171,15,315,12,3,0,0,0,0,2,171,15,0,0,"",0,0,0,0,224,'',[ minilines(171,15,0,0,0,0,0,[ mini_line(171,12,3,0,0,0,[ str_block(0,171,12,3,0,-2,0,0,0,[ str_seg('black','Courier',0,80640,171,12,3,0,-2,0,0,0,0,0, "Non-Directory Files")]) ]) ])]). text('black',80,212,2,0,1,54,30,316,12,3,0,0,0,0,2,54,30,0,0,"",0,0,0,0,224,'',[ minilines(54,30,0,0,0,0,0,[ mini_line(54,12,3,0,0,0,[ str_block(0,54,12,3,0,-2,0,0,0,[ str_seg('black','Courier',0,80640,54,12,3,0,-2,0,0,0,0,0, "Global")]) ]), mini_line(54,12,3,0,0,0,[ str_block(0,54,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,54,12,3,0,-1,0,0,0,0,0, "Header")]) ]) ])]). text('black',80,164,1,0,1,108,15,317,12,3,0,0,0,0,2,108,15,-1,0,"",0,0,0,0,176,'',[ minilines(108,15,-1,0,0,0,0,[ mini_line(108,12,3,-1,0,0,[ str_block(0,108,12,3,-1,-1,0,0,0,[ str_seg('black','Courier',0,80640,108,12,3,-1,-1,0,0,0,0,0, "A Media File")]) ]) ])]). box('black','',64,48,448,112,0,1,1,318,0,0,0,0,0,'1',0,[ ]). text('black',208,68,2,0,1,108,30,319,12,3,0,0,0,0,2,108,30,0,0,"",0,0,0,0,80,'',[ minilines(108,30,0,0,0,0,0,[ mini_line(108,12,3,0,0,0,[ str_block(0,108,12,3,0,-3,0,0,0,[ str_seg('black','Courier',0,80640,108,12,3,0,-3,0,0,0,0,0, "Media File 2")]) ]), mini_line(99,12,3,0,0,0,[ str_block(0,99,12,3,0,-4,0,0,0,[ str_seg('black','Courier',0,80640,99,12,3,0,-4,0,0,0,0,0, "512MB (DAT)")]) ]) ])]). box('black','',192,48,320,112,0,1,1,320,0,0,0,0,0,'1',0,[ ]). text('black',320,68,1,0,1,81,15,321,12,3,0,0,0,0,2,81,15,0,0,"",0,0,0,0,80,'',[ minilines(81,15,0,0,0,0,0,[ mini_line(81,12,3,0,0,0,[ str_block(0,81,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,81,12,3,0,-1,0,0,0,0,0, "Inventory")]) ]) ])]). box('black','',320,48,416,112,0,1,1,322,0,0,0,0,0,'1',0,[ ]). text('black',80,68,3,0,1,99,45,324,12,3,0,0,0,0,2,99,45,0,0,"",0,0,0,0,80,'',[ minilines(99,45,0,0,0,0,0,[ mini_line(99,12,3,0,0,0,[ str_block(0,99,12,3,0,-3,0,0,0,[ str_seg('black','Courier',0,80640,99,12,3,0,-3,0,0,0,0,0, "Media File1")]) ]), mini_line(99,12,3,0,0,0,[ str_block(0,99,12,3,0,-4,0,0,0,[ str_seg('black','Courier',0,80640,99,12,3,0,-4,0,0,0,0,0, "512MB (DAT)")]) ]), mini_line(0,12,3,0,0,0,[ str_block(0,0,12,3,0,0,0,0,0,[ str_seg('black','Courier',0,80640,0,12,3,0,0,0,0,0,0,0, "")]) ]) ])]). text('black',464,68,1,0,1,90,15,331,12,3,0,0,0,0,2,90,15,0,0,"",0,0,0,0,80,'',[ minilines(90,15,0,0,0,0,0,[ mini_line(90,12,3,0,0,0,[ str_block(0,90,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,90,12,3,0,-1,0,0,0,0,0, "Terminator")]) ]) ])]). poly('black','',2,[ 432,96,496,80],2,1,1,335,0,0,0,0,0,0,0,'1',0,0, "0","",[ 0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[ ]). text('black',80,20,1,0,1,342,15,340,12,3,0,0,0,0,2,342,15,0,0,"",0,0,0,0,32,'',[ minilines(342,15,0,0,0,0,0,[ mini_line(342,12,3,0,0,0,[ str_block(0,342,12,3,0,-4,0,0,0,[ str_seg('black','Courier',0,80640,342,12,3,0,-4,0,0,0,0,0, "Multiple Media Files (large tape dump)")]) ]) ])]). poly('black','',2,[ 64,112,64,192],1,1,1,341,0,0,0,0,0,0,0,'1',0,0, "0","",[ 0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[ ]). poly('black','',2,[ 192,112,640,192],1,1,1,342,0,0,0,0,0,0,0,'1',0,0, "0","",[ 0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[ ]). xfsdump-3.1.6+nmu1/doc/xfsdump_ts.txt0000644000000000000000000000533112607344125014461 0ustar ============================================ Xfsdump/Xfsrestore Troubleshooting Questions ============================================ SGI Support (relevant for IRIX customers only) ---------------------------------------------- * What is the customer support case number? * Is there an associated engineering bug number? * Do you have any existing contacts within SGI? General ------- * Have you run xfsdump or xfsrestore before? * Is this a new problem? And if so, what has changed since xfsdump or xfsrestore last worked correctly? Operating System (OS) --------------------- * What versions of the OS are you using now and when the dump was made ? (IRIX: uname -Ra or Linux: uname -a, cat /etc/issue) * What patches were installed for the OS ? * If Linux, what version of the xfsdump package are you using? (rpm -q xfsdump) * Is there anything in the /var/adm/SYSLOG file for the period that xfsdump or xfsrestore was run? File System (FS) ---------------- * How big is the filesystem being dumped ? (df -kl) * Does the filesystem have quotas enabled ? (mount) * Is the filesystem managed with DMF ? * Does the file system use Security attributes such as ACLs ? * Are extended attributes used in the filesystem ? * Is the filesystem controlled by CXFS, or the host part of a cluster? Tape System ----------- * Is TMF or Openvault used to manage the tapes ? If so, which versions? * What kind of tape drive is used ? * On IRIX, what kind of tape driver is used - tpsc or ts ? (eg. attr -g _drivername /dev/rmt/tps4d6) * Is the drive used in variable or fixed block mode ? (IRIX: look at the path for the tape specification) (Linux: mt -f /dev/st0 status; and report the blocksize) * How many tapes were used for the dump ? Dump/restore commands --------------------- * What was the xfsdump/xfsrestore command lines used ? * What was the output from the commands ? * If the FS is not too large, what is the output with the -v5 option ? * How big was the dump ? * What drive strategy was used in the commands? (xfsdump -v3 ... |grep "instantiat") (xfsrestore -v3 ... |grep "instantiat") If you have the -v5 output, then just grep for "instantiat". * If dumping/restoring to/from a remote host, what is the OS version of that host? * If xfsdump/xfsrestore seem to take a really long time, use the -p option to get progress output. * What is the output of 'xfsdump -I' ? Misc ---- * If the problem is related to files not being dumped or restored, and you know the inode numbers from the xfsdump/xfsrestore output, what files are they associated with? (IRIX: xfs_ncheck -i ´Ö®÷ c€ÃÙyÎfY ËçR-ô®fàÕ\ºÿˆb——Ðg–‡'¸ÈØèXÁņ¨6¹Vø˜©¹ùwxi ªøÉIZjjEÊ„¶7z +{SyIfø6¤ëæ9ëû ,N^n~Žž®¾ÎÞîþ/?O_oŸ¯ß‘Öïÿ0 À <ˆ0¡Â… :|ñà9Lû*6™h1#þŠá8jüh#È‘ <~3IR#Ên+“ôJq+BË%Tfz±™ §"x èSMA£vTGRK×ÈhjªÓN"cðJ„õ/§oj%³k­-XÆz´ÕÖK3zÜxÍ:êêÛHeWQ¢jNª†;lûþdÅêÕW¿? n0¸MÔ»%ýnå£Xf㸑æK¸ò`È•çèeöyŒæÑ†9÷Å7 ã©Ww.=Õt늲¾Ü™#jP®å„Vö{±cÒœwÿ•dy‹kŸ¶)Õ*þö"íé§IßÖ=epÛu—Î:1ìñÕõ€'̼÷íȲ3#VŸœ i¤ åYÅŠF%º ¦‚h§xz ¨~ˆú©aé 8¦Z(áª^RZ“«$¢:`G9˜´¢¥JèŠ SDð:$Üxª <5þ,‹ÂÕ  ^åˆ:S²L»´µV¡„°Ž—(3º«¥¦˜á‡ Ê¥–µnä¸gÉ8¢‰_­…ntén¦n²Š±x®—Ú¬M”+˜²˜]Ëîlë†ç ‹©5(ð|:—jû†Ñ/„Í\ì±M\«qñuzžÄ»'òÉs¼œ}›'lO·¬,ÅÒòkg «Èý”GÝÈÆ4†e¹Œ_Ì!øë°Îˆ³eÍW-N>¿7rÊ5c ´ÔHk«´P¿’YÀˆét Ží¼sÂàžG›¼ÒÁj3¼2¶a ‘–†5Λ!Y—“XGÇKô¸ìÞ¢‹'yKÒþî·e$ŽÊ¶u4ù]¾=¼¼è7µúBç¢ Ìé™Ãáù%òÝjëDj~)é´ª®7¿¸/¬çîSì.û­¾3¼Q¶ëN«Ð'qñÄ8ïó`¿ôH}òÖ_!ýÔë³ýNÝß¾‘´ïšýíç»”>ªåÿ:¾Åï;9‘¤ößþúïÿOýüÿÀ p€YßõÚ×;^wšè=ZI;à›$¨”ø¡ƒ[ZÆë`Â)Ì]'*‰äŽ2'ua‡(&±lÆ;ŵð]2ôU2Цj%hcW« ©µkáŠ\{a©s,„A,A¢w.’ÃóH.>msÚþ EóÀ¢ цقÏÖþ¥œT-‘@M,YŽ34Ômík»Ðš'vÅe-LD¢ø^ =F£ä˜ë[Ò¸àö¢&Æ\“Z»Šv®5šñy4[ÚöãE¡Ù¡Œw$#ÈÔÖžª¹®@LËËæøŸ¬qrA ëäSÆ6"Þ0’Êke# 3µ7RÍ•• c(•gGÞà±l¼ôšÓ ’Xêч5dѼÆM®òq¬|d/á3E¼EÌŒ dÒóË¡ñ§7¨|‘ÜŽ©ËÆÁ‰m%-I<[6Ñ™&-/ƒÆ.2™¾°æf2Ú¸ÑíT*[™Êaž3 ÕÎ+ªC`R±a¢ÜþׯÐîܳ>æ4$4CJ~L6wó×#zNtžÑp$=s¯Åóƒ2jËCÝu!:þ†W¸ê‡zõÅ´ E¸Ôé*~JApAeáÞÈ÷Ò ²³G'ààÅaAùiÏ©6ˆê§JUXµRY-Ó;±±ÕXi/¤Öëﺺ‰*&‰uf=µÑÖÚ©/œ™Ò WǪȲÚU¬sÍ+5âŠ>¼ÊR¯lÝ+–V¸V䶯ƒý«a7'XV"å±ruŸ£´XÅZö²¡" g? ÚÐÚÏ¡`¥l`BÂj¶y‘}êd3ËZÔº6€e_kÏ*ÓÚV¶³mæh(Ù³ê6HKõê.¿þ Û页MNLëÛRÁᦛ¾U)K‘»ZåÞö‡™˜>ýZÙØn¶¹rj&g£›\:iѸ”klm¸Ý]–׈ÑÌ.zÇK²î6R­_=­}/($GìÔº‰{ïã»H8I·‚Np:Ó‹TÞÊq™ÿ•ª„?…&[¿6¨†¯zá ?¸Â æpA),Þ7v þð]C¬Ì'º˜¯&æbf,\cñÆ$~qUÉHCVÇÜⱊï›@¦¹Ç4N²’…a`¹Ã©[°¾–«_ca¹œ¢í²—¿ f… ÊVþÕ– “`DùÊ ›/Ölæ6»YpþÜ™ûº;÷w·L>, TÇþÒv±ÄG🧧0wF¸ÏnŠÅv ^ÿZMGÊåŸ\àAûxÒgâÜèȉÓà™ÑPzÒž›­:gQÎ%Øv<¡è sZLW’UÝ »gø ¹ÔOq•wš·“zIZ2¦#‡kYkwÊÆ"…ª•Êê1;w×’^±Vúl¥èyaÂv™íí4gyØ|v2³Æ=ë&[›ó%·®lf[xáš©]îuKQß^5³[ð¾ysgÛ›ò÷ìðýnsߊÛý†ö¿í¬t [á¼Qõ]oXOà´ øÁã<ª0‹|ä$9÷Fuqz?üGžIùÀ3þ:p¼ª·xÂùåòþŽÃ<æIs÷W[ʤ9§ù΃®ÕiaW⣦øÉyÅdzÙðyéŽmLM«ÉúÞÒo)ŸHç›ëêÍ]é)Æ¢3«æ¯Ëÿ¨P²Ž}ÑNŸ»¸¹f–`7êuÞÙAýÆ™¯ýèûÎsI_­õ‰ó½ëÁ2ûâÉnèO7žéáeüÖýîs)WÝx“<Ý-ïxÌS¾ÚeǹÛþóÍïý飷{§ÁæuÔk¾ï«½ç•]zسþöSϽîõ¥ök~öð“=›nûÏßlG¹óo|«ÓÑÐÏüñUÿùŠ[_ú gÝ•Kþð‹ŸW~ôÁüß™ûèÇ>Ƹü^þõç>¿Á§ÿûªÆ?ÞóWÿÂíïpîç}…×z7ç{Üf&‚'|é÷hì€Ç€ XìwÝ÷q_W€©‡m§qû§qÍ'seÂ% È|ý'yoÇ{›f uH|È\ñ6~3Hƒ5x(¦`iÉ£ƒ¸ƒ=h>>„U„CHgDh„8‚GyJÈ„÷Ö„OÈ‚P(…!7…UØrVˆ…¦—…[(\è…§÷…ah€bH†ÚW†g¨rh¨†2˜„kæ†qxMm(‡í‡uˆ‡üð[yȇÜB‡}è?ˆÏ’ƒƒ‡{hˆ‰x6…¨ˆgˆˆ‰À‰“ÈL”h‰yt‰™ÈGš8þ‰wȉƒøˆŸ˜‡ž(Š|HŠ¥ˆ‡¡ˆŠ‡¨ŠÄƈ«H"¯è$ñ¤‡§HW°Øj²e¦“_¸˜‹ºø<(u9mGòâ tô.­ˆŠ¶è fãR$äSÝB¾‹ð Ïx‹¡&ŒªŒkÈŒäsÄ8¤Õæx/uapWå¨C‡YQG5Ža¨Œé(UCêÈSë2ŒdÉã¸ÏAŒ’Èe1uSm43’©xíèƒ)‘\Hé…‰‘Y¨‘Y…é‘XØ‘!)…#I’M’'Y’©’”f’-i„) “Lø’3©ƒ5b“bø39‰2É“D¸“fƒCI”EþÉô“ÕGŽI9€Ï”Z¸”OI}N)•Þƒ”Ȇò¥þǃªò~((Rµq'ö|Qi•`cwhFU–ãPl““Žä-ÅGßH2-x)hrù7ZyF£ Zñ72/™k`h–ü'Mð”"c³˜árkÏDM D ^Sƒ3㘒Dí=‚¸4I7Kó5aÐõVO%Li#w(LŒaJõ”M°Ö•˃Åšì‘“©w¨ój…£2̈j͛ɔQ‚Gpš9ž©D¼Ùš …vaRà ›ÌÙPšö™Wù¦´M¥APù¤Nü¤NIJQÃD4ãáÉžŽT›þÍÈ|?õ—“£"tySéR*2•ŸÎØ^~C8­ø›î8Ÿ1BR•˜Fu–T¹ƒ®fs º w…Z•¡g+Ú…ni¡ UZ{‰É¡œ'¡š|*¢ ê¡%º{Š¢±¢+Z|-ê¢ð§œ1j†J£â“F©£;Ê£yU= ¤A:”Ü™}Ššc©¢Ý…mGºœ3J$KúŽDŠ{F¥Nz#PŠ'VÚ nŒ,éARRgOq¢#^êa0*b6dªfŠb6:81…l– §8ˆB—~Lº–hú5!ó¦á#…¸DUK=Á§ö¦¥_¤t5¨CJ*¦®“¨mj@¯#þ7*%¦ˆ:‡ÀÙ5‡YdYê§ãù§œ™gOjäÉ©¢z¢—å`wK#Q‘*1]Z©wת‹HóØ.´X“舨<µGºè¦-6ª[šV·*mÇJ…¾U¥Ì*sX:ÊÊ3Éj­¬ §r"­{¦½©sj)Øš¤~)vƒ‡ª¢¶¦KP_aQ¬Ë𫽥xsVÕê`Þ>Ôª¦±èM…iS¿J©cŠ©ìØ¯¹<ÅE–ï™XäZ6³˜7«Gô£©‡Ÿ2Œ{8ú"¹¯•É;þš¯$ª°,Sš¦ö°©•›Þú4êI—¤VVC¸É°âÙ¤Ðêžç¹ŽØjœ•6>ºëšúä›ÐþiªÍùIàš­"õK¥©˜ö¤³'Ë‹³O×Ù4~YM¹à´<«¨4Û°%¨åÚ%‹O8“š½(Gßåœú³æé´“z®ãšŸ”#Ÿ}㓚ô‹pkŒæhG4uK0 . xÔµ(+3‹­×ºŸ„ÙŸä²tºŠ!–ãG0‚“-x´}²­ˆƒÝzyDôC¸žQ¹ñùf˜¯T*® +`Ÿûøš–§k¸ÜÚ¹¾ºî ºiª¹ÎZº^i»Jú¬ïú¤­û†¢Kµ;­À[y”»»“Kºº{»¶©¼ÍëºZë×÷¼ä(¤Õk½%ˆ×«½ÛûYÄKzÉ;½È+¼Úz¼nk¼¹¾æ ¾þ¬»¼ð‰¾ì;¼¯½Ü‡Þëz½Û¾ ¿ä›¿Ü»›2»L+¿¨‚õ;À8¥²k¿c8¾¿{À.Á¦«¾ |¾ñ ½œ¹v¸À¸¿|ÁÜ{©»Á/¸¾üÁ y üÀ)x¥å+Á% Ã*|Â,Œ¬ý[Wï[ÁéûÂüÂ) À.Œ»ÎÛÁ&Ì»-ŒÃ"üÃEÊÃ2|Ä5LÄF,¾AœÄN<ÅøÅJLˆÜËÅ]ü?#,½E¬ÅOܬYlÅLÅfìÃ3 ÄX¬ÃCÌ¿jÌœTMœÆo̼q¬ÇLÆ…[ÅkÜÇžë»RŒÆn,Æg¼Ãw|È€|ÅH,Ç ÆôÛÃsþÉí·Ç„œÈ†œÃ|ÜÈP|ÉcÜÉeüɲۮÎ6È“ É J[§lÇ”l˜þËÊŠ,Åt ¯Ž<ÊŒ|¨ªuËš Ê‚Û ÿËˈüÊYËÁŒËhë ÀlËœ,Oº¼ÈÆìÊ*KÌ Í©œ²«LÍËŒÉç5&ŬͽÌ]ÉìÍžÌÌ!û¦›ŒÎàÜäÅíìÎ’r°_šÍä¼Ín#ÏLÏêL»K¶Ëß,ÌÿzΨœÏÿü±d6Ï¢\ÎtkdÏìÏÇ d92Î]ÏLÑ|Ê<ÐÝ}Ð~lÁ¹¨fÍÑxš?ˆÏ­Ï«Z„-È6,¯—«Ò°+ÄZ6A/=¿Ð`j°`Ñ&MÐM…V9þÒ µÓVÒ?=ÑmJU>½Ò-¹xFÓ Wßê„ý|ÑѼ•L=ÔI-Ò8ËoM °¼¹Q(Õ:Ñ Ø aMÔ'=m™Î­lÍ–ÜsfÕ@ý ×0ÍÒæš-ÖT¢ Z×5ÝÍÅ«¡z}Ö;½~~ÍÐSÝÖ‚}VàØ Ù‘-Ù“MÙ•mÙ—Ù™­Ù›ÍÙíÙŸ Ú¡-Ú£MÚ¥mÚƒ˜‰½×‹=º,ú×NY'˜Úk-Ëhý½}ÍÖŠ­¸³*Hm×JÝÆ_}Õ¿Õzت]ØcÀ5JÛÕ¼Û[Õ¯ÝÕ7¼Ú¢9Ü€-ÎÈÜ„×E=Ý#}ݰ]Z[=×ÒÂþy\ÛKÍÝÄ-×j­Þ¹]ÝúÈÕÞßÛæ ÞøÜÏ]ßô­ßL¬ÜÝýÞéMà|ÝÐh ßÉmà >àÎßè°=Žý¢ÿ½Ü ®;˜âÛØýËŽÈ-à†ÁÛààÁ{ÜÍ}à¬Â8Úß4,ßû}âë­áVá,Ná+^â’l¢ÎÞÞíÖÆ]à)Îߌ+¦mäGŽäI®äKÎäMîäOnÙD~£=(áS®„Unå@IËY^À\¾ [îå&æ½æc~ÛfÞ@eŽæ$¼æê¥æmþãp~AX.çi^çîóæwþrzîæ|Þç~î’yè%8è´&è…®ÕˆîV‡®èÛè‡ÅþènԒŽ$tnéLé™îÑœN˜îéê¡^=›Nê,vê¢nê©>±¬®ê"úØÓªö²#«ÎÎ~šÑ¨ëŒëŽjë×lUÞë¹Ì<“ëÅn‡¿ÔÙª¸ÎŽ[Ï8ê Þ섨’Ãî88…彎é£N1ˆUìÂéØN’‘í¼!îºäí‰{îíNçëVÊþWÛ>ÙNïÈÞBàîî“}òN[Sïtj6ð¾Ó^˜?ú“Ü^Ù¸1DðÃ\IÝ.ŸpåïŽUí´~Ÿþé!Ë«Ã.Ù´å/ç"Ÿä^è$(¿æ¯é®^*ïòYñ1¿Î4_ë6¿&3þó²¾óo¨ó=ßÌ@?/ôø^ô2ô>ŸôC¿ô©KôIóMߌOôQ/õ™BõEoõWŸY/ô&ÏõÖöúèõ@¿õcÿïöþËòkßmïöý÷qÏöæÞ“PŽ÷y¯÷{Ï÷}ï÷F^Ɉnëe“ò†?èƒ÷ŠãZFò\ ¡oÊ×Óà¨YùþÏ’_È;>³T†¤îšùy ÇW—R/—°Díïn òyIT©Ï±ôö]뀗¸.û&íéŽÌ@î¾áJ7h™¸IL‘Y´TK™Â äÚ-̹íÅÔ™Ç/úè ®ÄO´´Ê˜aéµÖi³Ô©ýÄD«íÉMþÝÔývÖ?²7KV¿F^¿ÉíÁ9ûâNRãñÜ •“ßl£Ù éKBKÈ1MÛ×i3¾˜¬¬‹2ÿ5î 2h<ÑT]Õ’}áXžé¶¾Ažnê1ÁÐÊ’q¡JÀœ/T$n>Î!o)ÔU‡PÜ–+ê~ÁáðQ|áýzTõštn'Ý’3Ù—Û‘ó:œúnÿçè¼öŠðüÖÐ0úË _#)+Á&-357/9;=91AGIEIOQGMSMX#W]c¿`ekmoqsµty·h{ƒ…‡o~‰•—™‘›Ÿ­ ¥§©m“«S¯±·¹»Y´½CÃÇÉËaÀÍ)ÑÓÙÛƒ×Ý?þãçé¥áëqîñ÷ùÕûQõý8°F@‚6&T˜ÉàB3!FìÒPbŽŠ1"É(&PGA†9’dI“'Q¦T¹’eK—/aƹqŒL›7qæÔ¹“gOŸ?iÊ :#Å‹F‰&݆T"S¥O¡9…(jÕcTbµºµ—Ö„^g4TlWr` ¢åR6ì%µfÅÁýöU[¹ÜÞþ£Ø‘!¾wâè!Ô×ÀX…Ë \1#Æ~î ËÛ¯a£rúfþƒY³fË—Omws;¦G&6™_e8Š8ב¸PlÒ°1Ó>l4oÕWk,ãè ñâŒÙêöœ&Oæ‹{£þ»9øþ»ê³-±IAZyìÒÌC3çÞ²wÙסÔ–³tßÔ»·OÝ ùDî¿ÛŸ¯>ë}®;Ž°ÓŒ›®¸¬4>ƒÌ !4Œ?Vüç 1<'Ã,6ìP— éÑÃ[ÁPDQ<ÑQôEv^l1ÃÍa ,´L0©s´§C¤påt€”ì¡|p¡±œ"ÓÒ¬Û…•<ë• xL.@ã s̹Û£M1¹ìÒ@ˆ#³·;Ë­±<ÄŒ0N#>“°”¯,QŠ+øäsO‹öld»hú$´Ï@ E3';ð @ ŽC'õ´âOYªǨ$ŽŒ¢ÓO9=TÒGKþäP‹f cÈPQuô :X-UJwHOH\Ørº,¹3´QYKUJÀ;m-¿>PNO5Q`u-ÐÖ 7•ZImâYg[m¶ÖdŸì6WP™…õlµPuÚó\Ô]aá=õ[SÏ ÖÔ?T|³Å"ß_w1\~ç¥óNj¡T6Ì4ð(“Ë1ñ oÎb)n“°ÝZè±a7Vã7gëxb…-fó¥`v]UR¥f¹vFaOX–±’ ÿË™!¡³éY¥±±qMŸ7±3¢Ç¨I!¦«q ävmÎ.ᨭ>kj´¦:ÜZ˜ŒË-±+Røþ.c‘íÖM;“‹Á’a¼»Üöë‰Ææ¨íµð´±èJVîy§D‰,ïvh• ÜǪy”‰B4;!6—ü Bœsœ)§lp$MÓ\ÛÓG]osò.VÐCÏ ’k W'ËÒß_tÐÏË¥· {_7^ôÝo­÷)Ë›B Lï4Öà]…–Xk«4Ññ° ¿k¡B|Íûöž{q©÷ }¸µü†Wƒ®¸3ÜNÆßïµë±<*ö&b %™­qKó_ªÌ'‰æa*J©3`ù~滚i€›Ç› VðœKSåAšgI ÍcÖ*ÃD!pšdBŒ½0…5þ’¡þhèޝ:ÛËa ­Âæü°I;\ÞoöeD"ÎL‡&tá£bD%)vP,b7¦Ø@ñY1Ol™qÈEŠ0‹é™¡!H¶ý„mtãáG9ÚÄh^D#ÕB;Þ—c ùX´ÿý¬Œ<ß3 É ö²XKä‡ÉÈì ÔŠ¤$'©´K¢Í[˜¤LÏ6éŠÖy2+; eÒŽHJARñ:‰QåT†qʃíï•ÎÓâÊÆUK‡TI–:—.ÓbÆ»€©—À̘"U#ˆb“næ$–ÉÌ!Þ"šÃ¹–4§B%¸˜­šØ 5ͲŠnz“‰ ´ÊÇIÎ_ž"Tþà3)©· ÅóŒK1çSžØÎY0k¢(¡’ }ÐÃ#^º£k`0Mˆ¡“]ĈŒE«{Tgßø¦#6=7#»Ù,ƒBÉŽq$ÂèÞ¥€Éó˜+éò¥Òäu’By(4˜GÙ¥Ë3è½î÷Î~žô{Â3*}”—¤— e mX+¤%ÏEÂxŠà ¨îJA¼TËMÃCP{5¦È‹«úÓê¹”ªêª¢RQW”{ø|õ4iöâ¹kz/©õºê»bêJÆe«®ù{Å2BOZ2$Wu_üQy NZòheé–ˆÉ+}È!Ùbê HŶlGYàþ?ÕYÐÉÅŸ¨MípJkÚƒ6mª¯EàÑ;[Û²Ök™ënwÔÛÜŠ¸!MÛpÏV\ãò³)MU®BU+[$=—(£5kS’K]šX7•¥œ®v™°&®€à­®ny[^ó2uŸÐUïzCJ\ö¾¾Û%>é[_ßf7¼·Õouµ1^¡jè¿îõ/~'Y`š¥µ*¿°‚›iÕ'Âp@ \aSøœÖðy/Œá~8¸#ÞŠ)L⟾ÁäUñ|WÜa¿8¾1nð^ilaÒlÆ9Þ®¹†icû֭Üm§…åßpÝqK¢¶ªZ¨Ei±ñ ê¼æDÇ9zÙÌâ¡[é6xÌ­9sæjªvò•pÓ—þuŒ·Z ã¨ýt1‹Ím¢aJzW/;–EÓwKuûÙû74°v=¥Ù+ëõîŠâ­V½_>ý7‡Ù Ÿªâ9‡Í óеҾ^ {Òséø¾xÈGª=-×ÛéèÚ»N%ë{àÕêô¬˯„ؘzš»›gGŸt·^­¹çÆ—ÛïÖ¥ršRŸùÖ±­âë^ºÏë~±G 7J‡Sî8ïu‡V5½’þÎㆲԷ¾õ³šQ©J4>VFδÓ}ï{ép­øò ¿´–}Œ˜`7uu£—ðžÈü}\WIs½°s™#÷³M‹Éÿ² •âîÇBW ðJA–˜fÙTN¸ŠÏ™Tèêø/ýbÉܾ Mœ&P+°‹8¢ü6+zÈî8ÄãÈâmÄnáÊoڔŠ„6d9 %³è­Ý¾nE´ÔÆÄ(C0sà¥ùZåv2ÍZËR‡`NF –P …öžåmž0ð'^rΰ1‡BåîŠjðlÏt„靖ôþ Z"°ôþEÌxä—h‡áp³|ùê/ˆêP¾pðfÏïro°@gò˜ð ML _ç¢Ä¥k{±†± ý„‰Jð‹›nQîMíŽtö¥ªúPò\ç™…¨B‡sëÕn#è ‰þ¢­5êcXP¢<@íÌO~¶&K ²,ÍL"æïÌŽ[ÐÑîQõÀ¡j°Lþ®°ÂîQH²Èƒ‚.úäŽÈØëjŠê²Fpþ4ÏŸN””È©L.ðäúCŠôoý:¨Rþ„I§2ÿnÉ’w`H!Ò2ƒ&’!/pþQÍÉr6²ÌƦßñ"m‘B’$þ Ð$-%‡Î%[Ò%… &P"+’&åqW'¹P'Y‰'‰Ñ&¿(ƒÒ!’(MQ&#)“r–’) Ò)Ÿ*ÇJ*§’*}r%™á#Á,p¼+r5¾,j+=’,Ër&-×ò(µ’-5R-ã.…r(ç’.ÛR‘Ô‘Ëø²/ýò/§L,«/i'“0·2#1YÈ-ë’1“£2¯R€š’23 s3 S/“3ÒŠ4C³'“4í’“J5o’G“5ûƒš‰+‘ìD"‰6‡LD. 7} D6‰7sìBB 8i¬BDR4a³4Ñ‘"“9³!%›3þ6Ÿ:£S2A*&M¼zä:Õ#1Rê`Ë9'äeúo¿ðÑ›¾*šh¤¡0ŠcTðí¼.ãNÈBFë™±<¤ñ8³r©S<çC´»bo qª˜P¯ö hîO:wÊqî0•jOzl+tÎÔ ×l¿mžJ ='>q ¨ŽpÕJæq;;4¯b!5Жh÷Äp©ÊµÐZ`¯ôv±Y"M+ø³5}á ‹óJg,Cï¯üEI/J± n3Û1å¢Á²,ë=çÇ]ð­l¢ÌïâÀû ÄdÄ‘Jw.,ÏsEä1©b 4‰2¥â¦@)FiþRkz¯:?*ÏOÿ”ÛîQPUóMÿÓPçÐæ UQŠQÕQ§SæúTRÕ‚~ÍRS3US'ÕêVÏSÙ é"UT!TÁÓTñò:UU¡Æ^ÎU³z0MVA”cÕVG’sUW•é*ÕWg4ÄLMXg•ç ÍX§nš>TY—• ÍÌYŸ5WNZ!{ÕZù [³U[Yõ›˜Í[Ó´¶M\[ÍÓ\IGõ 0Ýõ]á5^e"ÞL^íõ^ñ5_¡ieÔ•Rѯ\û5_-\öÎT` 6¿Ráöx€•ÇV`¶YYOVûŒ_}ÉUï-8ö¢¡²/BìgAˆ3Èþ¯‡²nôæ< KnF¶×ô”bà‚JüôskpÒ¡ZvbQüê9LðK¬%q6gýM´6¶3j6hIgùÃ56ß0æA4+sÖ^b'h?_0dÕ‡e‘rH‹.bvßÄÖaÿ¨l3´;ÑvlMvmqUmÝ–ÉvZoU0E‹ªönÓ–ZãHÌñ ü6oÑ•gvõË ¶¾ q…FpÙ•W=Vkiðg•ÑM²¦æ9*5(×ó qqoW™ô¨Ptb‘TÄQ¨4e§ µçjƒÍD€/ÎoEíp ÙêBst¥`ÐsÁè\I¯ Gô`kWVzzÒä}Å{bþq·iŸu5±“Š­¶“W…Ew«×q®÷laWµÔt_/JñÐ@ÿ5`<”„ŠwJ×y÷opM»ôUÜó>E«Dà5vVMÄL“1xÍ·çö{Õ:Ž8n½w\­ô1x<ãVnÛ6‚w=Þ÷¿ÞHED–¥|â¾ô…2xê*ÑêÙ–^V†_¹9-½xç§sN>ìÓ‡XM” >aYríùúŽXDÏÙ*Ù¸Á°ç‰Õ·Š½e“ ±Œ y w÷¹3ÓY‰ñÊ^f':WíBlz•™Ͳ¡=ó¡þ]ˆáXöš€/´·Ž½Xq y‰1ù‡£Ê%=:n¹ Yz™˜|ú’­Xo¯˜C%GŠVúS¥YæþyC‡’¡˜ ¯Ùv¡!9|õ%k‚Ú?i9Úâ„~óóbîæ†ý—³TY¤¹•Gù•=cfªéc5 l0¦]¸ª,Ñ:œ‘—»h®±÷k³—Xôm-øÿØZ6Ýš‘ÑL6Ûºc§FzrÝæ­‘íœgzPÕoFgø¢ O›aºíŽySOµœe¡j¯_ׂfpà´Û'rÅúžÃçnÚsóóZDÚ»ÔÁ Fúº®Nsš±xt—N§_[Y¢ÚþwZÙ%ø4wÖXAYy•oI#p¢-’» gC/†?Ó}{¼3ºoº¤_‘³»Mº¢¯O¹”¼ñ7fÅy1Á´¼¸šÑŒï{Z8Àøw7¯ï¾ZÍ{g]·&…b §§¤Å7Eýpt&Ùº‘{zUÔ g*ÙTBv3kÜ!¥U»úbš¬%F¹•dÖö3‡UœcÖà N·n°»¹7ëÂahHû4‹Wô{T{Äú!•<3õ‘Ç&œªõY ovʇUŸ|"›\²ŸœÄËùË_“'»œ³kj6ÑRÌ[Ø|²×üÍéþš±†/ϼ³:Qã<1ó"óÎ={›eTNa&úþPóÐ(jKISÑíOîZ/:ÝËOýÒ5¹NÑ=ýÓA=ÔE}ÔI½ÔMýÔQ=ÕU}ÕY=Ô“Ì4‘¹¹Z}Öi½ÖmýÖq=×u}×y½×}=×'Hº Éÿ4;ùÐ.ø›ÝqU‘÷“é#‹Λ½‘ù7+ýXmfÑ8£½€µÏÙ«õø|®½g»Ñ§¯ìŽmØ3O€ÏÁHÝýƼ> –Ý+P.i\NÝëýÙå‡ú<ûê[LÑnàÃ(à…ü³W›ÕIœD°Ò!~jw®Üy ý(>âݼ²¹±´þÃýßáÝdf}.ß˱ÜM>=¬£(žãïÈáOÜÕ¯ýâÁ/‰nß@Ý59ìæiX’\þãÏeN–-ÞWžÌßéÓÿšç‘Õçó£éƒžž‡þÆ#Þ7/Jçû¸ãËŽéÞçÙY«‹žˆu8ìUY¦¿ž¾[6Ùi~~¡ûë¨ì#Ûß­èÜãÞíç>‘õºåŸýãkX„¾ì¯^ïßvä§Y[#Дžœå›šõ–í‘síÕÚÞ1´¼…î²Mžòw”îùžò@Wþçý§±¸“„ñ»5ßÅ4¢ Ö¡~Ýå^¼+¼š)Ôº ÞïÓ«¹¾žÁ_è‹?Ûµ]Œ´ V5sÉIÚ¥_¼ózÓ#3“(­ûÛo õA9ö >¦.ô>ŒrÒj'¸zóî?Èe!Yš'jiЬ,G¯\Û7Jãž¾oN¢Çž€¾cˆˆ\2oÊËS5#e¢I…Óš:Í/,çJYm­j;kÔ6NNÏëvQÛ5Ò{[.P _—Ãà!àVE¢aßßK¢ŸÖâƒ\œæYç'(”âAO¤â^i˜ÑÊi©%f«*«N¥k-+¢dPSo¨ g0ñþÚh¦ìäå›oí-*Eå®s3©î⳪ҰI_qÙwø\ì5o!2³5öò®_ ©tõôt¶ûê°ø7ÿ?뮽j'j]ªjƒ$y5o Ãv Îñ°ÍÅŒ8ØœEp ®{õ<šsƒÈ`Âz®Db"9rË­”uöiÌWóf7(å`á2d X¯…‡mi‹ÁPA+«,Uú“糘/gZÄIÏ*Ö€Y£­zÇäÑ©_ý#»ÕªYœiüäõæÚ³ãʽH7ÆÝ™u÷2âë×f§¼zÿ¾Zø¯à"ˆ3&W5ËÛ½;RêØÓbÆ…55”r¬âu?Þ¬ÙthäìÈiþmÔeÖ§ sÆRˆé<š?ƒê†U™ÐÒßð¢Mü=ú©hÙ‡cχ‡bØ–2wÌ”+$ö¶ “ƒ¼tãæ~kïv»á'ž§œÌðˇðÁ0ÿ*ž/ùÑæ9Wo ^ub¡÷]IÃHßlõÝÇD~W™ç^:Ý èÒ%,q¡ƒ}wš‚ "Ñ D (ÑG>H!ŠÜi'R$Óé#^‡úà˜$B9¥Lo<ER-:ÅÛ;“W%¸ŒxDŒöɸU’KáÝ‹÷5é¤0TΥ݌Niå\ª… –^Â%fM[™™™æ :¹&›Za œ¹ùfœÅUç…ø-Áç`þyŠh–ã}È%¡‚j¨ÂN@  ‰vY¨•’*:a2B ¥~î`) ^Šá{Ç•hŽ1ž:A¦¨£š:Ã>“c ­ÎI«®3Œ…”Ái+«¦ ¬®b¨é©Ò™²,R¤žÅ±bDë*GÖh­‘¶5«í«YÅ6-˜ÅÂÆÚ·™E*(¸—JZ®¹µ*šî»âÒyn¼òºeï½îª‹oiü*§Ø¨ð¢ëï¿·ÖKp¨o¬®çépœkAìœÂW®jòN<ìÅÒ2,îÆ¹v¥œ Lòɇ–lrʶì²@ü†,æÌ^òJp͈¾¬rjþæ\éÎH>‡sД*i>ÝéþÒ¸z¦ðÏTFçÓP7½€Yk½5×]{ý5Øa‹=6ÙVmõÕU¦×¢O½äÛ2¾“rÜa®M/`hß­ïÞà¨èvß|nð|×½àáRþÝqâ0p·€?Nøä¯E.yåg®9;G7ÞÜç îÖtèn®ùd;—®ÙêáXtëËPêªÏóí?Ðzrì¨åžÇÞ½Óö{Ïk ß.ñ}Ÿ|ÒÌçí¹ómG¿8ôÓcjýå¶cOýöǼ}áIø×Øî+_í½ª“ªhi{Å;½<øæ„‘lduˆþÂñ£ÊеÑáܬZ"G7Úd®U;¿ÁOX‚Î)B‹ô Cþ‚"²àþlC«êܯoø«ËÍ|“! m+9ÞPK…B¼5ÐgÒ :ôCAù )ghß _8¿»}P.üIVIrŸ-#9bѧ<袤-$¡t ˆ%HA#Sác`Úzø¬<ø¤H+1Înz2«a£vü1¢¨Ø&.1ƒéãJº´ˆ1öîsrDɧF5)±Æê^ÛxG¬ òN‚ìB¶Äw2¾ñ|~ücÙfqK2\¢‚öºMýòKøÄä'™É͈>´™­èDÓ‰Q†R¡Uh;úхƯ¡cÚhIER‚Ô‘,éJ[ÊQ”‚Ϥe’èLeº´²ñ´§>ý)Pƒ*Ô¡µ¨F=*Ø<ˆÔ¥2µ©N}*T£*U²áô‘9%©UkZÕ¬’¦\µžMöÕ”zu¬Î kÍzÕ˜ªµ«m+X· Wâ¡•is^]…uW¼Êu¯³Ë+ÒüÊ<À¾O°tþí«a+GXµ%ö°emìãË6ÈþN²,¤ìé,«>Ìf±œ}«Kg¤ÙÆŽ‹]øìÀËÔŸ¥ £oˆ„ÚAyV_,' XBYjr¶ù m2NR×û,íä»ÃZô˜Y ãeé[~(—rÌ}'v­ÎãN—ºµÕÝvË-Hìa˜Òíî7ªû±àb *·!ÊÿÈ[\ôÎKµôÕhï \¶ê—¿ûí/é¾ `Æ xÀ†+ðÐ,¦¦^é´z“Užù˜Ø31#êݬM˽湋Â纰à2¼\÷B—‘ô,1/N¤¨(2¶«KÿV\¡Í8Â#Žâþ”’msS¦´þÜ,¼s[ˆ!ýo€ìFÍÓ]‘G¹‘(Cq$.Š Ìa!Y§Fæ "5èC}Æ""UÆ1k 9¬®WŠMÌ Eä+YÌñ‘a˜ÿsä$ç÷ÆDô1œQ%@kCž&²rHX²žI¥Ï¾¬le\^GõäFðe11‰cé~F³ÌL]{z‹96·-] ÙyD=j¯¹‘¦Öò ŒäÊzÖ®uÐÔ\ç'=b,Ù3ñTÊg[öU¸Ëòq'í»k —jNî–¬”¼lgÛsDÑN¶£KÝjmsøz¦ß¶Á}¶e*›‹£Ôå5Q¼Î÷ÐG0 `Š$l›`kÒDY§þŽRìn`¿.·9V5̲Mm aÑÚê¢K† æ;ùö³³ÁÅÂÛìÏ §!‰Êkéu§Â¦°ÇýG‘:D6VÉß0( ‘Çyɤ"ù÷lÍí9#¥×E´ÇpXC˜C¨Òó&Ђr æ\ˆ°âËû/s®?V¼yçFhò‹¿Šç»^! U^‹?¹áWÔ&«gÞ«?‡Ð §:ϯñùbjѧºÎŽ©<ßANí8Æíe>É7%Ý|Êy ÚΣÎÞ>ÿñèš +º!Òœü(ûùÞÆ×ñ¯Å;õY]óžLçåç±rãZi¤/=¾B/nÔ·LõÝÕ¯þ~®Î¯“9=«ìN/4¶èõÙ/y0„çúqÇ÷—½q³Š¦Ïƒ÷Þ'–®kó}âSN>2¼Ý·Ž°MŸÛT|çYî™^”':–þûOÇGuc"¼Èå¤;„W”ñ»§uù¤Æ…àr¹«2o¾PÁáÙў±¨Ý”eòh^šÖÉÃëÜÐÿ¡Ñ ‚ÎMÓï ˆÏI^À…ßý-àÛíߊžÓù^ÙIœÑ­´½\ü–ït`‚ ™þ•Q²pÊ¡1–ÈÙu=Ý™Y| n=†éèõ¹“|!y©RßÕ-¾]ž|©Gå5aây‘¡!ò’mÜtÝÞþv’øõ» Პ½ _¢¡Þ¸ ¦¡¾aj¡RKÖ!›¨á â¡éÑ!Ρþᾡ r !"ÍÜ!"J"."Ü4¢#ÚF¢ÎÏT]"&f¢&n"':•Ru"(†¢(Ž")N$R¢ã"*ÊÍ)®¢¢+*Æb*N"-"N+ÞâðÌ¢.²N.ö¢«Ñ0bØ ##ò¢1& Ÿ%£ÈØ"3¶`1>#."£4v!5V#“ü"6ž”3n#i£7b,†£Žcæ€á)ý÷ÙÞñèaòec9b¾£ÝA£r£%1Ö·=O<ÞczyZs—ŒäíNAå$°ßþà![ehß.^÷ Ñ‹¡£‚Ec8‘/ÄùõŸùÑß±„Sù)dÂ…äÔÍ#:‹ûUÛ9uc/ÍÇ Q Îc„øà 5`¡   žäÖñŸC±$UØœ÷= 6íßåA¤Ù}ÊÝÊÖ—õÜ4i >Z$¹a Æe‡‹ð’ÛeMÞ ×¡]àÒÖ5NRç ¤œy$¢_ç àR¤œ¾äYzUBm!E6TbMYN¤*Y&$bá:ú|±]ö-¤àuãA‘Ý@¦â±]^žì#Õø$fö¤9næ¥gNeg†&!#iîŠižfð¥¦j®äh¶æ•€&lj+œlÎf}i¦m¦kææo-#oã­ýæ7Ö¦p¶äù”"r&§r.'sš¢;xfsdump-3.1.6+nmu1/doc/files.gif0000644000000000000000000001446712607344125013327 0ustar GIF87aÂo€ÿÿÿ,ÂoþŒ©Ëí£œ´Ú‹³Þ¼û†âH–扦êʶî ÇòL×öçúÎ÷þ ‡Ä¢ñˆL*—̦ó ¦0€bjõdÛN·AÝuÃѲùŒN«×,Öôý¸ßˆ¸Á~‰¿ñ‰ùaNX'xØ'wµÀg·vØÆ&9IYiy2V⨡Á)ñµE¡Wwwú—:* §ˆøÊ ‰Yk{‹› åùG°gEæû{EWx\šú;ŒZŽ<9Ttaw^ Ä Ö«Ÿàq}' žRvÍÉå‰ZÖ­££]ž!œÎÂfGÏ]ý2çê£çTŽ?¿þÐFþÍôÇñß~H`øX‚3(h`ƒ>!b™Hz^ˆa†nÈa‡~bˆ"ŽHb‰&žˆbŠ*®Èb‹.¾cŒ2ÎHc6ÞˆcŽ:îÈc>þdBId‘F‰d’J.Éd“N> e”RNIe•V^‰e–Z&Ya—^~ f˜bŽIf™fž‰fšj®Éf›n¾ gœrÎIgvÞ‰gžzîÉgŸ~þY' €Jh¡†Šh¢Š.Êh£Ž> i¤’Nª§–&xi ò°© &Ø©¡¦0ê ÷©`¡¨™î²ê¥Þ𪠱ê³Ë¬DØ:®™èZ¯U´ê„¯€Û„°.‹þ˜„Èr:IJ8Û¦ÒjJ¬„Õ.­MØf `³BœJ*¸Hpk굪NË*ºÃjJ®¬Þ!®©ñranínRï¸ù–Ëî-÷’ļ›|ë¾ôª¬ÁEÜû¯+,è· ?ü-ÄïR‹p±; ª¿ÿ@ñ® sœ±µ%c»1¼ŸökËÈÓÀ;±Ë È Æ6§{³«+×êqÅ0/rÀ) }ò¹9',Í^(ÝÓ³óÐ KíƒÓXÝ Õ^tÜòÇUG]´½Z3¶¾eóËs×> öÑŸ}°Û&˽Ö­óÚPm÷Ýc{ ÷ÂëÀ0×µôý–mãÌxÞtÝ8Ò1 þÞåøêý5߃ç`9À‘¿ý¸ØIމå”ã­ê=tÎØçs»Žrà$°^]Ï*ÿœ´êd‡n6ïUmÞíè,îõê‹;;äÈ//yò¤’~‰ék.{ñ ;ß;ö¿ Ÿ6ñ˜O½ÑÖ <¬å»[ý÷MC¯’õЇ߫yO?/E^É¢ S…°‘/»þ‡­ß?ûÍU;‹_ªd‡ü ð&AaÆ\ü¦¾÷åÎ(ÆIÜåZ'‘uap¬^³E»—mð,(œç2Ø4 bf…Éz`ÜG¸ãÁ&:ŒÉ6 ƒ\‡~8„Ž'tAíÕ&‡á)¡Å°áÃ"òor´"¯‚¬‡!1>P Åþs¼³Ãt´&‚1„ßË<£ f@…GÙLËòm¡MˆÕH# ƒÈ¼Ã¸QŒp<–>æˆÀÝQ$j e´>Hw““¢v\hÆ«Un[Ñ`(ÖÒH;z’\"ßqˆJžñW¥¡$]ðGAOö1!‰Ì (É6/zŒY "É£I˜¬ñ‹ŸáoÃ@^’3µt¤/WÙËîÑ& „d.e9Êà¥r‚MüäR\qBUÄMÉ4gÙ<:æšÐô]oœèLlp„àL¦ÃÈHnª&35<&à–YHtó¯’gZ(Åj‡›ŒãÛ’dfâ–m h>¹gÅ‚ä' Ô§cþø9œgîs¢²ü9'ø å;k9à ëç‡'²Ç’¥„HËaĆ4‰ôég6¸R*ŽÔ¥ã4`;Åb‚ã¤6L &9:>êȃŽÊÜ3Ów;o ©DSêìØW T5žç«A9x=ÆÎ©¹‚*%¤š¹£rõ¢¢kRwIVj¯t0Ĩ*³úR¸ÊõuZUž$»ÇÖ´Ê*£tk_çºU´žõ—ʲ]S§ZÝ]-V»ab[×pAÖ¯uclSÏÆ2Q¯Vå«"ÒÑ)Ë>ò‡[èhQ*‹É6ZÕ¦øŸÐª6¥½Bí+å€Ò¦v³ƒŸXµ*Ñ&4ž{ípþÚ:ã–ˆáì&p• ]¶¹]%çmkÆÉãwWÑ,mvkëÌQsž©{+PÞSù 76âÊ_SpŠÞõ"£½Ý)&#ßùè÷ŸÏŪZµ+Ÿæà7ÀóE!€ý+Îóø¾ìɯIHX·”Á(u°X_ÛR8¾ˆw“+ñ*&¼åýí !:Gð0%-í|ZŠQŒÇ@B˜„/öMDÃKþîÏ>>YÇt›Icâåt„{EržêÅ´žhŠcœãû‘4È6^Zˆ,ãmdX8UÞïCQÁâëNã,Iþއuœ 2‹G:g.ˆg?ëb.Ô ’édœi#Q|Ö¤ç‘sž]²þçãF. ™­›ïü–0345®…0‹ SÁ¶ÏxÆ' A\ÓåR:Ñsî´—ãbçM?EÑt®nC¦‰0·Ø$~…ª‹a^÷xͤCgÌ_û”¹€¾Î‘›ì?¡êÙ×Åu4M ŒÝۺǞö¯]ËJdG7׳Öu³óòìËzÙØ¹6±Y_g“c؈f²KÙy~Ýnîd¬8OXzÕÍ]LˆmCQsõ›¬uE‹­ckÇ›¹c ÷¶çí΄#Eà!&8}ðÁ(\ßu¤ö½Úåzûâðþ3½ ÎgvO\ãîäLJjb*¯æÉü¸„W>äB—âp‘wÌ­œmþc×¼ã3Û2¾wcš™¿±.AMÏ­kó.«8߸¦ma®ô¢ãÆçÿòÒ¿ln_œä/L;CùîK‡'Óá0™™`Ö’}í1»€…Út8k˜£mÆÛ•|r™ïœ¢Â]îÜÇ^wèÜÝáB×»ÔõžlþíjÉOÐw-Ãzò#G-à›CCÆwçíé’g’ù³o>ñÛÁ2âQÞu£C¹Ý¨¯ßg_èªF ¶JÞé„AŸuÊ:¾WLo=7æ@¼HÙ^W%=œ¹s– âÝ“þ¼uØ®‡è3Bø”jd³wýí™õ°Ùwn°Š?íÝ!³à~YË}ÝŸ¿ûß–a§FÈÄþ–?ïKÝ>üí_5ÙcÚýjë-§Þ¼~ê‡}¨}èwßõ}ï—ñG~ƒ“Î2•W¸€—U,˜5œ%(8€Š÷u™&]óbK´Gx…—{«%v$(‚-xhºƒ+ŠeW«3=)§‚î42ÏvJÚ6ƒ/‡fºÄ~„öƒÞwW‚r¹¢G˜~ÿvØ.äy–?&y¶k>&ƒ4×V ÷xJÔ…)øW>8!x1+&´æ1nx' IøpK(ATåAìtŒfQ%h†g(¸µcVöC'i—´z‘±o@æ‚-dz…˜lh‡nØE6†³ÁJßÄwJ؇ö6„èT‰ôþA†Öƒ/Èkë$Qá7e‘ÇtŠ8} Hƒ x,YXTš6‰§‡cmx‰pgJTh„7ø^w‹®¨‡[ø•ô'èr¥hq¶(?³Ãˆx€a‡JeFý&qÔEÏTt”HŠŸ8‡~mž€'ŒZÈŒEØ_–iw³Œ†(~Î( óC‡€XƒhuòXŒÚˆ‰‡ç‡Ùø/÷ô†Æ(aôxk‹¥Šëè[Ï(D;u…%×`–4¹Å{ɇy‰î1Œ½W‘G õ…£·aƃõEë±|¾øiíÃ@Ó„ˆ€"I€qC«ˆ0YXýçˆn‰|HŽüè„<©‹2„¦æ*éþxœSƒ 9”©ƒ’¿¸’Àè’19#YF¹‡„“”íÈTÍ(•³•8“»…WѕՒBÙ•e9•iù”mi‘ãb•¹ˆL¸“•A¹–xé•5)–Eyï4~­˜Žƒ©µ”þ‰4ÅÞƒ˜¨”lÙ˜v‰–z©–{ù’7ɘ9 x—‰Ù@é™?)™í'*qÙh4˜)D˜_‰š‡©™¢ù™ŠYš‰•¬¨š…É[a ˜®É•”éUI›Hi›%Ô”³Ç—» ™¯Ù™ )Äœ¯˜Zyœµ9ÂYÐé›o œ8Ù›o(ºIài≡™`³É`ÉŽ Èšsižþ“ùžyŸOµVdé–˜u–òÉœ£i™¼©žÉi|è™™Ýé˜ß韭  ÿ™Ê ŸÍ —Ïi>ÃYY”B¡j¡Š¡ª¡Ê¡ê¡ú'|¢#J¢%j¢'Š¢)ª¢+Ê¢-êJ[£1*£3J£5j£7Š£9ª£;Ê£=ê£? ¤A*¤CJ¤Ej¤GФIª¤KʤMê¤O ¥Q*¥SJ¥Uj¥WŠ¥Yª¥[Ê¥]ê¥_ ¦a*¦cJ¦ej¦gЦiª¦kʦmê¦o §q*§sJ§uj§wЧyª§{ʧ}ê§Qò€à–x¸˜‰ú§‡Ê#eg‰Š¨SÆÄu¤¨Ûp…>´vR(SN‰þ¨™Ú"Œ¶¨ã¨r¦˜\œ:cx4\fšŠª,"o)xŒ´`,ÕFôå9A† vŽ‘tŠY6h§šª½j"Òx ëo¨—tÀÔjD†fBœem÷¨¾ ­$"üäoë4Íw¬žöƒÄxŽj4TÑ*®#R¬9&rˆG0¯†H/:JVuÑ+…ãJ¯ÒZ§q®ÜHÈ„H¸Éq¨ÁiõJ°%R‡g&ùºwlq? ©9@À£V°+"—SøCБ…»·{j–^wø± ø‘]ÒSºåe¦i±-‹› Š>.+³öŠWŲ3‹³ÄWœQ…²9ë³? ´Aþ+´CK´Ek´G‹´I«´KË´Më´O µQ+µSKµUkµW‹µY«µ[˵]ëµ_ ¶a»X.J¶*¶gre«¶“‚¶mËyסcé¶sÛf0« ‹I·y»³†™ t™·z»špk– ¸/K•\p³„ë¦{››ꊋ¶Œ{™ó™•{¶’{¸ ꜖۶˜Û“vë·œ+¶ž{ˆüY¹¢ûµ¤ëtŽ[ ¨›ºKž{庣 »¬«“³ûº†û¹x‹»\«º ›ÛÙ»]û»²iº:¼U[¼@Ø·›¼X»¼ÿ»ƒû¼Z½çy¼ðT½Ð[»ÍÛºÛ«¼Ý ºÎ ¾SëŠÑwíù½þå+µé*@óJ„#(«¥K’ Kœì{µR$ék]áê“Øè¿kˆ¿V«¿³:¯„zšÔöDìJ”µX’¼Ç]Lµ‹¸„© jÈZ‚$»wFWbܾ¡Ä|ÛÈ«iw|™ô¬JÂÀ Â!íŽ-Žì©â¼ˆCMÔýˆìÉÅÔ›ÓH½ÂlÊ,ÆKvÆf8•’7Õ[ÕŸœÎ Àf-†¬6ŠûUÐ.<ÖdýÓ\ˆ‰æç¯q—n¥÷®FöÑq}£eÕðÈ‹é6ɰ,Ër(Ø{ý¶~=®€­‰Ð¦¯uÔNœG^×ÖÕÇØÑêØ:Ĺ,„j½m•¨×NÆ×™M¯›M‹òë{d© }|èëhWÑ¶Ø¦í«¨}×ã»»eÛ½ŠÛIýÒáÉz½}Ûs¼/¿MÜJªÜGyÜ Ó×Ë­%Í-ÐËÉÓÒ­©Ô}Ð5-¼Ø©Ú Êܸުà­Ôþ$ÝÝäý§æÁè=Þê¨ìmØ;mÓðݧòm×Ö]ßö½§øÝ†ºßü§þ]…•yºާNÉ‘àn§ ~Ô z+ÑíàNáA,áÍBáÎ$ŽŠ¾Æ~ËkKâl+â ^â)þ('Îâ-îâ/ã1.ã3Nã5nã7Žã9®ã;Îã=îã?äA.äCNäEnäGŽäI®äKÎäMîäOåQ.åSNåUnåWN¼fh_͹îÇÉái«°‹ÚÚ¯]mVÑð5íqJXM©´†_®ª^tæ£'nk>ç°xæiŽ…3U«m>©™wØ´ÍS^ÎÆ -Ïmh¿b&ªuûXþÌÖûsy¨IŽÐ»ŒšŽÍF¸ªUªÿÈÛŽPkx÷´àEn öƒ±ž÷ÊǨÖGêûê°Ù`–MöXëi­®’=ëï(M¾~«»Ž‡­0„ȨöV®¥®Pðûä”A}mÌÈÕë ¤ÏÈ>ŽxØÉÎJhê”éh-P¨¬aíL'êw]ìÂå$é@¦íù|o‚tåÐÎsz¦ÈÙzٹĭ[Á¯mªX7jTˆ¾"[´z¶zH Ûîd˜sÓÊî³øîƒž¬¬¼¬±÷ßBNïùˆm1ŒÃØZFf«ÿŠst§pÖôªÖËièWüË(ÿášAéû&}(ˆj•.õÑxíØN‰ÅzégŸë߾ʔWóŠ'„ÌÌô¦åŸg[³½dFý‘ Y{?fì$øÀ[ «u_²fNaälRíëÓåÍZ¼f Oˆ”ø~z"%j`fø»–IY=²I†á{ŸÆ àŽœ‚ŒúÓkœÏ ô-û¯_^¢,ÁÆ6º5¼ÿ5¾oûÁ/üÃOüÅoüÇüɯüËÏüÍïüÏýÑ/ýÓOýÕoý×!*Šý½«ýÛ?»>éÞO¸þàþâï§äŸõæÏ¦è¯þ¢Ëþío¹ïÿŠ+ÿóÿ·õoÿt‹ÿùï¶ûÏÿ‘KÈ1u¹ýa&V{qÖ›wÿÁPÉÒ<ÑT]ÙÖ}áX–§y­í\ßùÞÿAáX4‡8$F¹t>¡Qé”Zµ^±ÙESËÕ~Áañ˜\6ŸÑ[ Ø›v¿áqùœ^϶¯xûžß÷ÿéôªE § ')+-/1Ã$£63=?ACEG×¾:ISUWY[Q`]gikmo©dL&xo~q…‡‰‹gP}•‚šQt¥§©«aMŸ™a¢­½¿ÁÃ/±Ö|‚ÏKºÅÛÝßáãþÈšÍ×µã÷ùûýOõ©ico[9ìþ%T¸¡‹yéÐ1S†PbC‹1f–AAƒ)(j9’ä¿yëmùXªdK—/1&SWn‚‰CÒ„¹“gOw9õ9”hÑIB} 5º”iÓ:Jy@u:•jU€b¤ZÕº•«‘¬9¾v;–,·€ž-»–m[°já˜é®…°nñæÕ[¯n¶Gùö<˜å¿4yÕ´Y#q¹úî–Ôvk¬y¯.X!öpçÏß_}¸3þçËøì‡¾;ÃN»Ï]ÆÙ@x%¹wi゙=¼æ/Þ·—?_Uüöéç×?N½×þû püÐÐÀ…!PlÐÁ4„æ¿)¬ðOÀР9„BCÀ: QDA>LkÄQ´£ÄVLÑÅAš0 a¬ÑÆ h ¢Åyì1;¬rôQÈ!%’È#‘ìaG–LÒÉ›¤+È'©¬’/#­ÌRK&§LªË-Á$2ÊÆ ÓÌýÊÜ Í3ÙloM޾lSNßd"Î9ñì°Îßòì3Ë=ôSP'eîÎA °P MÔQú… ÒG)kR.­TÓª2½rÓOEìT PI/åPÔŠJMõÁSuRÕÕ'ŠUÖYi­ÕÖ[qmôÕ]õÊÕ×_ –U^‰-ÖØcÿ);xfsdump-3.1.6+nmu1/doc/directories.obj0000644000000000000000000001224612607344125014537 0ustar %TGIF 4.1.16 state(0,37,100.000,0,0,0,16,1,9,1,1,0,0,1,0,1,0,'Courier',0,80640,0,0,0,10,0,0,1,1,0,16,0,0,1,1,1,1,1088,1408,1,0,2880,0). % % @(#)$Header: /home/cattelan/osspush/CVSROOT/xfs-cmds/xfsdump/doc/directories.obj,v 1.1 2001/12/18 01:56:03 tes Exp $ % %W% % unit("1 pixel/pixel"). color_info(11,65535,0,[ "magenta", 65535, 0, 65535, 65535, 0, 65535, 1, "red", 65535, 0, 0, 65535, 0, 0, 1, "green", 0, 65535, 0, 0, 65535, 0, 1, "blue", 0, 0, 65535, 0, 0, 65535, 1, "yellow", 65535, 65535, 0, 65535, 65535, 0, 1, "pink", 65535, 40606, 44461, 65535, 40606, 44461, 1, "cyan", 0, 65535, 65535, 0, 65535, 65535, 1, "CadetBlue", 12336, 29041, 29812, 12336, 29041, 29812, 1, "white", 65535, 65535, 65535, 65535, 65535, 65535, 1, "black", 0, 0, 0, 0, 0, 0, 1, "DarkSlateGray", 3598, 8995, 8995, 3598, 8995, 8995, 1 ]). script_frac("0.6"). fg_bg_colors('black','white'). page(1,"",1,''). box('black','',32,112,768,176,0,1,1,318,0,0,0,0,0,'1',0,[ ]). text('black',48,132,2,0,1,54,30,319,12,3,0,0,0,0,2,54,30,0,0,"",0,0,0,0,144,'',[ minilines(54,30,0,0,0,0,0,[ mini_line(36,12,3,0,0,0,[ str_block(0,36,12,3,0,-8,0,0,0,[ str_seg('black','Courier',0,80640,36,12,3,0,-8,0,0,0,0,0, "Dir ")]) ]), mini_line(54,12,3,0,0,0,[ str_block(0,54,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,54,12,3,0,-1,0,0,0,0,0, "Header")]) ]) ])]). box('black','',32,112,112,176,0,1,1,320,0,0,0,0,0,'1',0,[ ]). box('black','',192,112,272,176,0,1,1,321,0,0,0,0,0,'1',0,[ ]). text('black',208,132,2,0,1,54,30,322,12,3,0,0,0,0,2,54,30,0,0,"",0,0,0,0,144,'',[ minilines(54,30,0,0,0,0,0,[ mini_line(54,12,3,0,0,0,[ str_block(0,54,12,3,0,-2,0,0,0,[ str_seg('black','Courier',0,80640,54,12,3,0,-2,0,0,0,0,0, "dirent")]) ]), mini_line(54,12,3,0,0,0,[ str_block(0,54,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,54,12,3,0,-1,0,0,0,0,0, "header")]) ]) ])]). text('black',128,132,2,0,1,54,30,323,12,3,0,0,0,0,2,54,30,0,0,"",0,0,0,0,144,'',[ minilines(54,30,0,0,0,0,0,[ mini_line(54,12,3,0,0,0,[ str_block(0,54,12,3,0,-2,0,0,0,[ str_seg('black','Courier',0,80640,54,12,3,0,-2,0,0,0,0,0, "dirent")]) ]), mini_line(54,12,3,0,0,0,[ str_block(0,54,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,54,12,3,0,-1,0,0,0,0,0, "header")]) ]) ])]). box('black','',112,112,192,176,0,1,1,324,0,0,0,0,0,'1',0,[ ]). text('black',288,132,2,0,1,54,30,325,12,3,0,0,0,0,2,54,30,0,0,"",0,0,0,0,144,'',[ minilines(54,30,0,0,0,0,0,[ mini_line(54,12,3,0,0,0,[ str_block(0,54,12,3,0,-2,0,0,0,[ str_seg('black','Courier',0,80640,54,12,3,0,-2,0,0,0,0,0, "dirent")]) ]), mini_line(54,12,3,0,0,0,[ str_block(0,54,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,54,12,3,0,-1,0,0,0,0,0, "header")]) ]) ])]). box('black','',272,112,352,176,0,1,1,326,0,0,0,0,0,'1',0,[ ]). text('black',368,132,1,0,1,36,15,327,12,3,0,0,0,0,2,36,15,0,0,"",0,0,0,0,144,'',[ minilines(36,15,0,0,0,0,0,[ mini_line(36,12,3,0,0,0,[ str_block(0,36,12,3,0,-4,0,0,0,[ str_seg('black','Courier',0,80640,36,12,3,0,-4,0,0,0,0,0, "....")]) ]) ])]). text('black',448,116,3,0,1,54,45,328,12,3,0,0,0,0,2,54,45,0,0,"",0,0,0,0,128,'',[ minilines(54,45,0,0,0,0,0,[ mini_line(36,12,3,0,0,0,[ str_block(0,36,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,36,12,3,0,-1,0,0,0,0,0, "NULL")]) ]), mini_line(54,12,3,0,0,0,[ str_block(0,54,12,3,0,-2,0,0,0,[ str_seg('black','Courier',0,80640,54,12,3,0,-2,0,0,0,0,0, "dirent")]) ]), mini_line(54,12,3,0,0,0,[ str_block(0,54,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,54,12,3,0,-1,0,0,0,0,0, "header")]) ]) ])]). box('black','',432,112,512,176,0,1,1,329,0,0,0,0,0,'1',0,[ ]). box('black','',32,112,512,176,0,2,1,330,0,0,0,0,0,'2',0,[ ]). box('black','',512,112,608,176,0,1,1,331,0,0,0,0,0,'1',0,[ ]). text('black',528,132,2,0,1,81,30,332,12,3,0,0,0,0,2,81,30,0,0,"",0,0,0,0,144,'',[ minilines(81,30,0,0,0,0,0,[ mini_line(81,12,3,0,0,0,[ str_block(0,81,12,3,0,-4,0,0,0,[ str_seg('black','Courier',0,80640,81,12,3,0,-4,0,0,0,0,0, "Ext.Attr.")]) ]), mini_line(54,12,3,0,0,0,[ str_block(0,54,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,54,12,3,0,-1,0,0,0,0,0, "Header")]) ]) ])]). text('black',624,132,1,0,1,45,15,333,12,3,0,0,0,0,2,45,15,-1,0,"",0,0,0,0,144,'',[ minilines(45,15,-1,0,0,0,0,[ mini_line(45,12,3,-1,0,0,[ str_block(0,45,12,3,-1,-4,0,0,0,[ str_seg('black','Courier',0,80640,45,12,3,-1,-4,0,0,0,0,0, "Attr.")]) ]) ])]). box('black','',608,112,672,176,0,1,1,334,0,0,0,0,0,'1',0,[ ]). text('black',688,132,1,0,1,45,15,335,12,3,0,0,0,0,2,45,15,-1,0,"",0,0,0,0,144,'',[ minilines(45,15,-1,0,0,0,0,[ mini_line(45,12,3,-1,0,0,[ str_block(0,45,12,3,-1,-4,0,0,0,[ str_seg('black','Courier',0,80640,45,12,3,-1,-4,0,0,0,0,0, "Attr.")]) ]) ])]). box('black','',672,112,736,176,0,1,1,336,0,0,0,0,0,'1',0,[ ]). text('black',48,84,1,0,1,225,15,337,12,3,0,0,0,0,2,225,15,0,0,"",0,0,0,0,96,'',[ minilines(225,15,0,0,0,0,0,[ mini_line(225,12,3,0,0,0,[ str_block(0,225,12,3,0,-2,0,0,0,[ str_seg('black','Courier',0,80640,225,12,3,0,-2,0,0,0,0,0, "Directory with attributes")]) ]) ])]). box('black','',512,112,736,176,0,2,1,338,0,0,0,0,0,'2',0,[ ]). text('black',736,132,1,0,1,27,15,339,12,3,0,0,0,0,2,27,15,0,0,"",0,0,0,0,144,'',[ minilines(27,15,0,0,0,0,0,[ mini_line(27,12,3,0,0,0,[ str_block(0,27,12,3,0,-4,0,0,0,[ str_seg('black','Courier',0,80640,27,12,3,0,-4,0,0,0,0,0, "...")]) ]) ])]). xfsdump-3.1.6+nmu1/doc/split_algorithm.gif0000644000000000000000000001513212607344125015414 0ustar GIF87aö1€ÿÿÿ,ö1þŒ©Ëí£œ´Ú‹³Þ¼û†âH–扦êʶî ÇòL×öçúÎ÷þ ‡Ä¢ñÀ”È¦ó ’˜.ªôŠÍjŸ€®7áµv ã÷LF‡ÑÛ¶û YÍq€‰7ÛÉõ¸ÿè1· 6wH×Ç'ÈØèøH˜ö•¨H¹¦ö˜©¹©¹·X  ÊYjzúC¥ê©Çj‰+;û2©7††»ËvçK,<œ3J|Œœlc¬Üìü,¢ =M]m}­½ÍÝíý .>N^n~Žž®¾¾ÎÌþŸúç_L/…o¿?¡Ÿ?Ï/ Q:1(0!%?‘4T(ð¡ÃÀ’TLÓA"Äþ}K\ÜÐ f!ïl¼u)¥Ê•,[º|©¦Ì™.ò(©') $3žÜùè2›;t†²iKR«^&Ú²ª(QkèØš”4 L¤!ÂèÔg§…8Œ.©Äµ©PFyIÖìF¹5¢ê ÛbÔ§OÚŠ|ûêhØ‘PÉÊêõ#Ï‚Iùæ©à·à…_kÀ;Ã.czÅ^Ѽa[»|wªÂ±ðZÃZ§6Ù{Tq¸|ICiH‰lËPËa­”MVÖÃgC©*)¹à¾yÓ0xû–Ú_º¹²^›ðêÕáNgëèaó¡GtI»<øø _W[f¯îê42~?6óðÚþã¬Xæ”ËlÿåW_\¦u•ÈcØ—~ÖqÉ~ ]?9tšu×U4 …»™z›KSâÇbw,‚w! RõZ‡ÂHà{»Ð¨aŠþß"+n÷ÝrE–†âeÌø‡UÝÖŽQJyV ú¨â{ Y$n½ÜˆXq²·ä†åÙhH”ñuxýœ!â!ewÆ| Ù¤’:d›™F¥‡†He-ªuYRÖx^ŽŒz÷'›kj‰ãG#zt(“}DS§ž~:“—ŒŠ9„yX]•u¤ jèXxV©dz\ j­¶‚š 0—ºöÙ‹n¢)€}Çç¢ÁT¸þ'¦®"úœ2‰ë³ùšç=Ѻì ’‡L¶×j›éMÎ~{(Û&š+¹ËšK-¬Ö2ä”·ÊJû+1ò®po·áJ£Ÿoäûnç6Û/¼ŸpgÆ+ ƒûÓõ۪žþbï¾w5üïÅ Ý rÈȪ*²Èc|°º—©rËÓÊèrÌsÉLsj5ß\Ä8ï܈Î<ÿì1ÐB{ãóÐF ôÑJÏëðÒæ=EÒNs5€RO­MÕÑ\56Z+Ìu×Ö|½UØbSCöÄ)ŸM5Ël¿}§ÙpÏÍÝv£’öÝz£÷Þ~[ýwà‚ô-xáŽx¹'®7ád2ž.ÌkCþ.Œã‡/N¹½n7¹æ’û×¹çrsú0–?zéÇn®ºÓ§÷×zì=¼.;â´×^øí¸®ûî~÷î{ãÁ_/ÊÄ |kÇCºñË÷Ü|É?ÿ`ôŠSÿùäÒc}ö˜sï=穃þ÷äVrúµâ¦~ûî¿?Þô.Ë/Ê7ñŸ#Ò¯Bs?þI²»¿gôÏ@êU1@±+/3аDdŠbmRÅ+ˆ¯8ó?MHpj¬–é%š¦€~¬œ¼H8°‘Q§„+´Ø´S­)&sZ`²È“áÀI:vvåw`pLõã·H4ºbH G¬úgîÕžÀJRhùaþ„(!H}§9Ûàö8äŠ@ˆM…òàb´Å+e‰^Â" ·¨Â¨¡ bã‹TÓÔD5=kŽ}1)Ó ¢¥7YÔ FGñEêIxãž,u (bÉH°Ycõˆ4ÄN‡‹Gdšùˆ¨F.ñ‘²Ê#­´ÉARMBº¢mRÚ°l|ô¤ó0„& éq—³ƒÌ•ò%Öæ‡ YØk:)G… ¨ƒËd¢¸–…Bdîcušái*G~éÓð"£)Èq‘€š´`8#—HržÆDÛÕ©Å p“ï„'Å0tOÖÓžóÄç:vÊ:"¬Ûðæº Íë¹Ë–_ÌXBþjÆi*¡Û'":Ñ™=t› §@5ZQ…V £Ÿ„ˆE-ÚÑtÞ¤ì'(¥¹5~’ ~4M•zjŠÓœÊdŸ2íi>} >u~CªP‹ª®£"õ[J]j´šúS§¶#‰R-‹ 9ZÕ—–O¤Y•ÇV!ÚUv^µ¥aTÖ²öò«XU«ÎU·‚®ÿ”kçèjWŽä•{xÝk<úê×w6°S%ìñà:XÃZ†ŠèJÚØZf²‘M)cÛZÙ…N–«™e^ÛÙ‹~”²¡­ÂXK{Ï¢6v‰]m7Zëڂƶt°U¦No{MÜêv·¼ÅUíNJ®ŽÔ–håpÍþ:à2µ`oMnqÍIÕx>Ó¡!í bÅÓ2†ÎÝè•]¶ZH¬aQn!ÇëXÒB¹å}®z øÇzô²èm™ ‚IL³TA‰tÅ N±@Ù‰›ã{¤¸^2ºh-FœÈK)xJ#U^*Y) *bÇ•ù+güñZøµ¹„°£LIaÓrx•,’%׋Éóš&›1e°‚sUb¶)Å7ô¬/¯òÆJ:Æ ”ñ‡‰{9ªaS”;6åªü{Æ"zXÈë4f&ã‰$w&¹ 9Ô(y f|EùÂR¶$W†å'†©†°"@ãF´.3“‰´,s~©ª`òp>Ä4pp™«þd‡ˆ‚Šqs[:Üã:kÕÌoneXœ†Y¢L4é¶üTFÒ½íÅôÆ:]Ýk—» F4gÓŠJûR×Ô¨>õˆ×ºêJ»š¬pVuÄ8ý2×ÕÇ¥–u«ýêéÞÚ»¤o°µ9ìPÓz³©Vy—]Ò1·îÙεì¨mÜE‡Û–±6kqlØM»·4e¹ÏîsÏV뾫®Û½:cÃ;Äï.Õ¼y:ÚYß[ÛêÕ÷¾Q'oèþ›ÒÌÆìÀépEœàÑ^ø› îð·Y:â•£øï,¾·‰c\ß8Þx$f¨t.¾hf%ä“‘€ ö€p7zýçh*(ekò'E¡¡%­äg¸fû%'Ã7‚e×xüÆ)Úw¬âH¤–Þ—gq"L|&~Es0Ww·„æ dädióyÇtzMèir±d}²Ò_0Usô“x-gƒÈGl'‚_(nH¶zzÈ„"ô{¥Çyi(ˆžGˆÊă˜‡Ý5}xø‡Ž˜~¤×ˆ½&:”‰–h:˜—þˆ+#}˜ÈjOõv5(@h3{Øl¯eŠì5Š^•ƒ~Š|è…¬·†Ùp†ƒ×Š¶æ„¶hy y½ŒÁ(ŒäFquØ…NgŒ²ˆŒŒ'x¸xƒÍ˜3ÐøtÒ˜TÔøgÖ(jؘÚXm¹È¢µvcÇŒ çvÉH‹VgŽ€ˆŽãˆ†t—Žj¸Ž†HŽY÷ŽßèŠÏhO“’¸,Õ&õáž8Šˆ©b¨¸xòØŽqWóÞ(låÈŽÎH‘ i‘ôX‘¦çމéuxYç'’V’u’ü@’)¹‚,‰’.ù’ “ yŒL÷ y‘‰l9y÷È“2©y?ˆÉvþ)zi”3IRC©”mÓ”…õ”é°’QI|TɉVyS‰•‡v1Œ_ –—wXGQšHKrh‡¡•hùŠÛ§xÑØm*å–i©’Ù¶”sY“} åUI“ʨ—lyŠÉ$Y³¨A ³–…y–Š©4È|}ùB‚Éoˆ_¨¢Ø…b-ÙGf…Õ7JŽI“˜yásaø—R¤1d¹4š'ó˜öÀ~>¤…&a'„:h€ªƒW)™“YšùÕB„ò©'-ø?/¸kô4–s‘ì×C’†š“æ—É .¸J¯¹‹‡DMÚ7)ѹ@‹¢„}Øaîq%d´%R¹X¶å&Hþë¹™y„Y¸B Éˆ¿ fœ¼4ž )qðÙ•E¡BØW™qȘÉ—±I—z—wiœùIfÙyš— ÊÕi’† —™ ˜uÙ  š¡!9™v)¢þ OÚù ä¹¢Ï£¢{äô¢$z¢ä3£o£ßD7¢ÙS7º š™¢;  êä£ ¤áa©¤Kz™ÍٓŘ”8ˆ”|äaù]˸{-J^&ŽYª  ]*—#Š“Z7rÅêHŠ…—£( ¡y‡¦xŽ[¹¦ ¦tj¦ª¦[ÙE?Ú”ÿUÒñsDɧǷú ?˜q*$1Lig¨©oêc8I>‡¨pxþc˜eD‰0ø@E:Aš.V§™§DfVYq¦ù§›1G›Ê ¡5ŠV®Š,‰z¥g¤‚\JX¬z« ¸«…諼zb ¸WÀÚ"%$„°:z”Ьy¥¬×ÇfIØNG­Ü'œÚÚŸN¥¬^Ê©pÚ¦i*© ®n”xZª‹¹§XÙ§Fú§øÉŠêºœ\Y®Qù®НòJ…ôº®zšŸ´j£üº¥aŠ¥cŠ®ájwñS¥`9¬Gw“‘OúƒB ÷º:ùi檱þ©ë±¥²°8²YS²ªx²²•²&…oÕ­|Š:D,ìTJÁ÷§ZÏÙ°Mú°K¥Ä¸ƒ1þT³Åꨤ¹—?¦=¦Dþ °s“-/k„D;§bJ±¦:±e1C°9ê¡ûƒ%!× e k_ZcMëSUÓ›µöh‹x´a5n+sk{‡»²Ïd¶ w·vª1»·.»­µ˜³Gû·éZ¸úTµ‡[¯ýj±H ¯–¥óÚ¸0J¨›¸;¥;¤WË”[”©¸”¡ r뱦믨K¯ª«®¬‹§®K§dIºmI£*±wª‘ K¬™{¹|˱½»¹Ÿ«¹Nú»£[¦œ ²³+º«¼›»…Ú¼Ÿ½—8½›X½¸w½7¼{+»Èë¸úê•;+¾ÃH¼Ì •±Fp9e³þà+›!jKœ$µí:˜™¾^ڽɡº¸{¿оÄ¿‹?Ï«µöÀÙŠ=\°û+c L½g3´‡™?çÀw1´äj]œ¹I¼à§»d›¿?µv›Eó' ­yGÿ*²ŠBlRL3û^Ç Ž1Â-¦œ,Œ¸Ç &Ð'ë+X_FœÓIÃx‰]i1ƒ¼ÉÀøbKDÄáœ+ …”r›7|Â×iD¨À€qe†Ôb§Ê¸ $gËwš>˜°[\.<„OšòÅq‘«B,¿€k*8…™Y‚L¹a­ôY'™)tKI·® }ÛÛTŒš¦I™úëÆZ )½Ùþ¿4«ÈÅ î‰Çr‚ÁøKÈ™ Ê_âÇ,•œ DŒž•¢©{t¤Ì®<Ì¿ˆL}™|… üh¡lË´¼ÀeI˜M_¦¬–îÛ˰ÜÀ²ì5Â\¿rYÁ—¿¯|Àbü[B*Àm¹Ìñ748ÌÄümN;Â`èËÎ&ÍLžÕìzá ÍÅÜ£æüÍÒEγÐξ{· ¼NyÍÝ<ÎÆœZÈ Àö‹Ïc“Ëÿ Ð-ÐMÐmÐÐ ­Ð ÍÐ mÏl«Í›»FÛÐMÇt·»»“[»Ø:ÑóL°s¹Í«ÑÙ;Ò&¼(Íïì’,Í’.’0}’À¬Òm¸Â Ò]ë³Æë¹TþËӸ뽔{¼8ýÓýÑEíÑAÝÑÕ[Ò5m¾NýÔPý½R½ÒTzV] 2]’4mÕ\Ñ'í“GÕRÊÑ8Z¹6 Öº(Ö)ÝÓ–‹ÔZU¼c½MÕ[×l}×f×K½×Ý×|ý×C­×5íÕ«»IMÔr=ÆJ=Ø@ØxmÔŒí§7íÓŠ½Ë’m×*M×ÝÖœ=Õž=Ù ]Ç¢Ù¤-ئÚ§}×…xi-ј;”íÖ–Ö°=µ© œ Û»ÍÛ½íÛ¿ ÜÁ-ÜÃMÜÅmÜÇÜɭܾ}Û¥}¾ÿûÐV Ø#i¢ëØþ£ÕËkÓj-£7<Ù­AÞÝÜ[3ßÍ6þÌÄ¢8Ú@C†dz~¼]Ë»-*5l-*ßL‘&¡ÛÖßýÍœðߨ|Cà(èÞ@‚«YVà²íÜuQÆè}^èþÛð€èÞç|.éwÞ³—}æ÷)¡t¾“Ÿ½¡þæBÞè—®ÏÑýéBÛËÍê­îê¯ë±îê–®ÚEÛϤþÕ9$ë»Îë°~·ÐqÖ®¸´ƒ“~>Äî $ì‰~¸Èn«Ã¾ì”>×Ñ΢Ê^ëÌ~®Öèìٌ놊³¨Ê¡ãÂ>®hý¨& ^"Ìí ~gµé@â®XÀ.å=[ìå››Lf%ï:Hß‚ZNý¾Î_·\˜,tëWûž £JÉNã‹ÁÉùaì!¨î /¬lüìå®!²úžÒº„Õ‰«/ÑžÖQ~äúÞñlã‡ÊðCå¿nÏLI7ò£ŽÅ&ðaUìVþ~Ä 4óU óQ+_û¶ízkí•.íGÝ´«ôJn¯Ó[ôv*§öõ(ßí­}îšþôWv'è¯ çlšõµî oëïôLoö^;öm¾õìÎößþõeá³Á½Ž÷yoÜ¿îÚ¨ê~Û€¿ã‚ߨ„¯è†oèˆOö…oÒ¬Ýõ‡=øk ê÷kCò5¿ì¡3ß AŸ—ŸÞ;]…Ïózïù5o÷ÜŠú¨¯" ßӹþ °Ÿ§áºÂeúجø¥þûZ¯ß¢ü£OªÅ¯ëð^À ˆücfQ¤ùóæòmÑoÓ?ðI¾ø#KüIŸéð\Ö­¶þ^¿ýæ¾XãúioþGôü·îZ¢ùã‘ñÖ ·Ù‡¿úª¾ôë?ÿÓùÍÒþOñ1u¹\”“V{qÖ›wÿÁPÉÒÄ S]ÙÖ}áXži7­ñ\ßùÞÿˆ[X4‘I%i¸t>¡QétÕ¤F¬Wí–Ûe½p˜\6‹Ï‹qxv¿¡m6< §ßñ>{w¯íçaþüèG©£#%/  '13E*ã4=?A 8ŸFCMOQ{JSY[]UV_egi)koqsCbu{}Qy…‡'ƒ‰‘ñŒ‰–“{›¢Ÿ©w•/«³ƒ¦¥±µ¿y¸ÄÃÁÍuÈU½ÏÙcÒËáÞþÛçë®ãéñYäÑóûq÷sô7 &¥aC}!F´&‘bE[1f| ‘cǃ2>vi"ä ‘ Kº[w’`J“÷X"tùbæÃ˜k¶È ë&N{ovö””'L¡ýˆžHz”i½;K›F5*•j6¨U±z¹š•ë•­]Áv ;V×W²g‹˜õ -D¶Þ¶»òL\¹NìnÈ‹â.²½þZÜ7íO7ƒ o3œqâq‹ë:Ö˜eÉÚ,¼¼9Ræ“@‡=štiÓ§Q§V½šukׯa‡¦›vmÛ·qçÖ}º,KB_=óËÑï$Äq 9Ò8å4žÛð}ñHþt½?S7bÝ©Nì̵žZå»D0Í«ÓUZ>âùðÌÔ“ÜDZ”ìÒbxoŸ Z}!ü!௾äŽ/5ÞSl¼¢v¹A@ëH´B4á*BÃâpˆ #ìN÷;.¾‚™PB# Büx19½Ðذ 7t ÇOH¬8½dË¿ÞI‘EësqEÿã°†ß.ì°¿jÔQÊ©ôÑDÀèñ šÉCtÑC —œQË*½ÒÁ LPÄ ~äRN2ŒdÉ2ÉS Õ̰J߬‘E+çĤMÍœCÁÏ$³üϲ<ÏÔóÈ5d|r¿%½ÐË,LVÐþÓÏNQÍ‘2Jû¼ÔR2…nº=uÊT¯LT ^î’Â{í/MM³£5=[cŒ´Å( ydX'½+vÍcÄUH]·Ø‹Ù1£ÏXS«½UÜA‹s=i¥ÖÇm—ý]va£RÅ ÌáfÜÃîýÇ¢E±ØÒ^éð­`Xæ—` V–Quë÷s¹8¸Ë„#^xâ¸Ö»Ý¸akÞ7ãk¡8ÛŽþØ•™à˜d!–w˜Í ¾ÉÊÚÍçŸÚçM….Ú裑v3o—n2§¡Î9ê©O¦Új>N¼ú,îpÖ:\ö˜§ËèZl}Á®úlPâäzíSSÚÎúíÎÈÆsîPâ¾{¬¼õW'ðÁ"ÜpYO\bÅ—¯ñÇQ”òy%Ÿ\«ºç°¼r¬Ô\ê§6÷Ü+Ì/=ìÎË6]õoWoÝõ×);xfsdump-3.1.6+nmu1/doc/Makefile0000644000000000000000000000120012607344125013153 0ustar # # Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = .. include $(TOPDIR)/include/builddefs README = README.xfsdump LSRCFILES = INSTALL CHANGES COPYING $(README) \ xfsdump.html xfsdump_ts.txt \ *.obj *.gif LDIRT = *.gz default: CHANGES.gz include $(BUILDRULES) CHANGES.gz: @echo " [ZIP] $@" $(Q)$(ZIP) --best -c < CHANGES > $@ install: default $(INSTALL) -m 755 -d $(PKG_DOC_DIR) $(INSTALL) -m 644 CHANGES.gz $(README) $(PKG_DOC_DIR) ifeq ($(PKG_DISTRIBUTION), debian) $(INSTALL) -S CHANGES.gz $(PKG_DOC_DIR)/changelog.gz else $(INSTALL) -m 644 COPYING $(PKG_DOC_DIR) endif install-dev: xfsdump-3.1.6+nmu1/doc/CHANGES0000644000000000000000000006332512620476160012526 0ustar xfsdump-3.1.6 (14 Oct 2015) - fix build issues against xfsprogs 4.2.0 headers - clean up worst of libhandle API abuse - remove all unnecessary build dependencies on xfsprogs headers xfsdump-3.1.5 (14 Oct 2015) - __psint_t no longer available (Nathan Scott) - restore: fix 2GB directory dump limitation (Rich Johnston) - restore: fix uuid check for incremental restore (Rich Johnston) - dump: fix crash adding inode groups (Rich Johnston) xfsdump-3.1.4 (18 July 2014) - fix partial region segfault and debug code (Eric Sandeen) - dump wholly sparse files correctly (Eric Sandeen) - restore capabilities correctly - memory leak fixes (Boris Ranto) - sys_getdents modernisation (Kyle McMartin) - Error message fixes (Iustin Pop) - Updated polish translation (Jakub Bogusz) - debian package build updates (Nathan Scott) xfsdump-3.1.3 (8 May 2013) - Fix a segfault in xfsrestore when a path name is too long, thanks to Nigel Tamplin. - Fix a backward compatibility problem. Dumps created with version 3.1.2 where extended attributes are in use failed to restore with v3.1.0 due to file header checksum errors. Thanks to Fugazzi for reporting. - Refactored release scripts to conform to using git archive. - Changed the build process so that 'make deb' uses the same process of creating a source tree as the release script. xfsdump-3.1.2 (13 December 2012) - Update release script to create a source tarball. xfsdump-3.1.1 (31 October 2012) - Save and restore 32 bit project ids correctly. - German translation, thanks to Chris Leick. - A few fixups to the German translation, thanks to Stefan Ring. - An initial Polish translation, thanks to Jakub Bogusz. - Various build system cleanups, thanks to Mike Frysinger, and Jan Engelhardt. xfsdump-3.1.0 (22 March 2012) - Fix metadata restore on split files. - Add a -D option to skip a recursive scan of the filesystem when dumping. - Fix a 1 byte overflow with empty lists, thanks to Mike Frysinger. - Enable multi-stream support on Linux using pthreads. - Fix handling of Ctrl-D in prompts. - Obsolete SGI_XFSDUMP_SKIP_FILE extended attribute for excluding files from dump. - Fix restoration of extended attributes on the root directory. - Use the full 32-bit inode generation number instead of 12-bit generation number. Bump the dump format version to 3. - Do not create parent directories for orphaned files during list-only (-t option) restore. xfsdump-3.0.6 (14 October 2011) - Unconditionally add checksums to various dump headers in xfsdump. - Verify dump header checksums if present in xfsrestore. - Convert to using the POSIX signal API. - Remove restriction of 8 options in dialogs. - Various refactoring and internal cleanups to xfsdump and xfsrestore. - Build system fixes, thanks to Ted Ts'o. xfsdump-3.0.5 (30 March 2011) - Release tags will now be digitally signed - Quota files will now be dumped, regardless of the maxsize setting - The new "-s sessid" flag allows inventory sessions to be pruned by their session ID. - Fixed a bug in handling long dump filenames, and dropped (undocumented) support for encoding certain parameters within the dump filename - NODECHK is now off by default, meaning xfsrestore will now support 16 times more directory entries (4 billion) - nrh_t is now 64 bits wide, allowing xfsrestore to support dumps with up to 4 billion directory entries - nix_t is no longer useful, and has been eliminated - Memory use in xfsrestore is better managed now. Segments of nodes are now power-of-2 sized, and allocated nodes are no longer needlessly zeroed and linked into the free list. - Pathname resolution in xfsrestore has a number of performance improvements - Better checking has been implemented for compatibility when resuming a cumulative restore - Build system output has been cleaned up considerably - Dead "namreg" code has been removed - Build dependencies are now determined automatically - Other miscellaneous build system improvements, as well bug fixes thanks to Mike Frysinger and Arkadiusz MiÅ›kiewicz. xfsdump-3.0.4 (13 January 2010) - Improve xfsinvutil man page and argument processing. - Fix timestamp handling on 64-bit architectures in xfsinvutil. - Various build system improvements. xfsdump-3.0.2 (9 May 2009) - Update the Debian packaging and resolve xfsprogs dependencies. xfsdump-3.0.1 (5 May 2009) - Update the Makepkgs script to generate proper source tarballs. - Small specfile improvements, thanks to Jan Engelhardt. - Fix parallel builds, thanks to Mike Frysinger. - Various autoconf/libtool fixes, thanks to Andreas Gruenbacher. xfsdump-3.0.0 (4 February 2009) - Bump major package version number to signify changed dependencies and moved binaries (xfs_fsr and estimate have moved into xfsprogs). - xfsdump should no longer make use of internal XFS headers and libraries, in particular no use of libxfs is permitted in this package anymore (such detailed on-disk format knowledge is the realm of xfsprogs). - Fix xfsdump/xfsrestore to work on systems with 64k page size. xfsdump-2.2.49 (17 Feb 2008) - Fix up error handling in _rmt_open in librmt. Warnings reported by Michal Marek xfsdump-2.2.48 (07 Feb 2008) - Prune dump sessions with 0 media files even when using -m. xfsdump-2.2.47 (01 Feb 2008) - Correctly detect whether a tape device is in variable or fixed block mode when using the TS tape driver. xfsdump-2.2.46 (24 Aug 2007) - Specify mode on all open(2) calls that use O_CREAT. xfsdump-2.2.45 (24 May 2007) - Change fsr's temp directory mode to 0700 to deny full access. - Update fsr's usage text. xfsdump-2.2.44 (01 February 2007) - Fix use of getopt's optopt variable. Thanks to Kouta Ooizumi. - Initialize xfsdump's logging facility earlier. Thanks to Kouta Ooizumi. - Log a message for each quota file restored, not just the first. - When using -z, check a file's size against the max dump file size just before dumping the file, rather than only during the initial scan, to account for changes during the dump. - A sync needs to be issued before the first inode scan to avoid potentially skipping modified files in an incremental dump. xfsdump-2.2.43 (02 October 2006) - Change the inode scans to seek to the next inode of interest, rather than always doing a full scan. Useful for dumps that contain only a subset of the inodes in a filesystem (incrementals, subtree dumps, etc.). - Produce a more accurate dump size estimate when it is worthwhile to do so (when using multiple dump streams or when skipping files based on size). xfsdump-2.2.42 (08 August 2006) - Rework code to remove the DMAPI build and run-time dependency. xfsdump-2.2.41 (14 July 2006) - Fix issues with makedepend on libtool libraries. - Fix issues with symbolic link handling in Makefiles. xfsdump-2.2.40 (05 July 2006) - Update translation Makefile to work better with the Ubuntu translation system. Thanks to feedback from Martin Pitt. - Fix annoying "ignores datarootdir" warning from configure. - Fix issues with makedepend build infrastructure. xfsdump-2.2.39 (21 June 2006) - Fix for parallel compiles, thanks to Robin H. Johnson. xfsdump-2.2.38 (06 June 2006) - Performance improvements for dumping subtrees. xfsdump-2.2.37 (24 May 2006) - Fix xfs_fsr memory and file descriptor leaks. - Fix xfs_fsr handling some of the extended inode flags and fields (like project IDs, extsize, realtime, etc). - Fix Debian packaging for libc-dev build dependency. - Fix up auto lib64 install detection for x86_64 platforms. - Use -O2 optimisation by default now like everywhere else. - Default to using a single media file for each strategy. Multiple media files can be enabled on tape strategies by using the -d option. - Fix a bug in restoring multiple links to files with the immutable bit set. - Fix a regression that caused xfsrestore to fail when restoring files that were changing during the dump. - Remove some overhead in restoring files that were dumped in multiple extent groups (> 16 MiB). - Add simple interface to HSM-specific code in xfsrestore, similar to that already in xfsdump. - Fix fsr mishandling directories given as arguments. - Fix build dependency on recent xfsprogs header files. xfsdump-2.2.36 (15 February 2006) - Debian packaging updates (debmake out, debhelper in). - Minor man page fixups with respect to hyphenation. xfsdump-2.2.35 (07 February 2006) - Merge some minor changes in from IRIX. xfsdump-2.2.34 (31 January 2006) - Updated the spec file to correctly set package user/group. - Optimizations to increase the performance of xfsdump and xfsrestore, especially on filesystems with millions of inodes. Many small changes were made to minimize the number of system calls required per inode. - Significant changes to xfsdump: o Cache the gen number of each inode during the initial inode scan so that a bulkstat single does not need to be done for each inode when dumping directories. o No longer retrieve the DMF attribute when estimating the dump size of a file. Use information from the bulkstat instead. o Retrieve DMF attribute by handle instead of doing open/attr_getf/close. o In determining where to split multi-stream dumps, take into consideration the number of files and not just the file size. This allows filesystems with large amounts of inodes but relatively little data (DMF filesystem) to be split correctly. - Significant changes to xfsrestore: o Buffer writes to the namreg file to eliminate 2 very small write system calls per directory entry. o Buffer writes to dirattr file to eliminate a small write system call per directory. o Speedup the check to see if a particular window of the tree file is mapped. This allows xfsrestore to use more, smaller windows which is beneficial if we can't fit them all in memory and have to start unmapping them. This also makes the -w option obsolete so that option now has no effect. o Change the hash function to give a better distribution among the hash buckets. o Do not make an unnecessary unlink call if the file being restored does not already exist. xfsdump-2.2.33 (16 December 2005) - Add option to allow dump time to be overridden. Useful if doing incremental dumps of snapshots. Thanks to David Brown. xfsdump-2.2.32 (29 November 2005) - Dump and restore project ids and project quotas. - Remove xfsdq(8) and xfsrq(8); use xfs_quota(8) to dump and restore quotas now. - Fix the setting of extended inode flags during restore. Some flags must be set before writing file data, and others must be set after writing file data and extended attributes. xfsdump-2.2.31 (10 November 2005) - Sync up build system (m4 macros, etc) with other projects - Update SGI copyright/licence notices xfsdump-2.2.30 (27 July 2005) - Fix some problems in the xfsrq(8) script, thanks to Kim Hansen. xfsdump-2.2.29 (23 June 2005) - Change xfsrestore to retry a write that fails with ENOSPC after issuing a fdatasync call. If it still fails, issue a sync call and retry once more. xfsdump-2.2.28 (03 June 2005) - removal of unnecessary stat64_to_xfsbstat function xfsdump-2.2.27 (08 March 2005) - Fix compilation with gcc4, from Andreas Jochens. xfsdump-2.2.26 (09 February 2005) - Fix xfsrestore so that it can restore to non-XFS filesystems again. xfsdump-2.2.25 (13 October 2004) - Bump the version to deal with the mixup in 2.2.23-lbs (that fix was missing from the 2.2.23/2.2.24 versions). xfsdump-2.2.23-lbs (04 October 2004) - Fix a problem dumping DMF filesystems when files change from dual-state to offline during the dump. xfsdump-2.2.24 (29 Sep 2004) - Update m4 macros, incorporating some portability changes. xfsdump-2.2.23 (21 Jul 2004) - Fix up xfs_fsr and xfsdump to prevent possible crashes on 64 bit machines such as Alphas, when using a 64 bit count passed to bulkstat when only 32 bits of it have been set by bulkstat. Suggestion came from Jan-Jaap van der Heijden. See http://oss.sgi.com/bugzilla/show_bug.cgi?id=346 for details. xfsdump-2.2.22 (19 Jul 2004) - Add support for new DMF attribute format. - Fix bug in HSM code where a DMF attribute could be generated for both the root and secure extended attribute namespaces. xfsdump-2.2.21 (15 Apr 2004) - Always allocate a filesystem handle on restore instead of doing so only when restoring DMAPI events, as the filesystem handle is also needed if restoring extended attrs. - Remove path_to_fshandle calls in tree.c. These existed to ensure that we always had a fshandle before calling open_by_handle. These calls are extraneous since we now allocate a fshandle during context_init. - Change open_by_fshandle calls to open_by_handle since we are passing a file handle, not a fshandle. xfsdump-2.2.20 (31 March 2004) - fix up "xfs_invutil -i" which was getting segmentation faults on presumably long session labels. See http://oss.sgi.com/bugzilla/show_bug.cgi?id=320. Become paranoid and convert all sprintf's to snprintf's. xfsdump-2.2.19 (23 March 2004) - rearrange fsr algorithm to not copy data unless extent count has been improved. Suggested by Chris Wedgwood and Utz Lehmann xfsdump-2.2.18 (25 February 2004) - add support for the security extended attributes namespace xfsdump-2.2.17 (13 February 2004) - modify calls to libhandle subroutines to account for changes to the libhandle library. xfsdump-2.2.16 (05 December 2003) - fix xfsrestore to restore new XFS inode flags: immutable, append, sync, noatime and nodump. The inode flags have also been added to the _mk_fillconfig_ea() routine in common.dump, called by QA test 063 to test inode flags and xattrs. - fix xfsdump to honor the new nodump xflag, "XFS_XFLAG_NODUMP", (in conjunction with -e). The original method to skip files, -e plus extended attribute "SGI_XFSDUMP_SKIP_FILE", is still supported. Admins may choose which method to use. The xfsdump man page has been updated to document these changes. - update man pages with a more detailed description of the inventory media file that gets written to the end of each dump. - remove 'miniroot' reference from xfsdump man page. xfsdump-2.2.15 (18 December 2003) - a mod was added in 2.2.13 to fix the way xfsdump handles multiple dump sessions to a single tape. The mod fixed problems that the TS tape driver was hitting but actually broke multiple backup functionality using the ST tape driver. Both problems (ST and TS) are fixed in 2.2.15. xfsdump-2.2.14 (18 October 2003) - update Debian packaging to require latest dmapi packages. xfsdump-2.2.13 (21 July 2003) - fix ST/TS tape driver compatibility issues in drive_scsitape. - fix multiple backups to a single tape (TS AND ST). xfsdump-2.2.12 (29 May 2003) - fix up an invutil Makefile botch which was effectively disabling the optional ncurses support (interactive mode). xfsdump-2.2.11 (26 April 2003) - rework configure.in to make use of shared macros. - fix up #include lines to allow compilation of sources with installed headers rather than local headers. - update Debian packaging. - fix up a botch in the RPM packaging from 2.2.8. xfsdump-2.2.10 (14 April 2003) - fix configure tests that used AC_PATH_PROG incorrectly. - switch from using mktemp to using mkstemp for xfs_copy log. - use a FHS compliant name for the xfs_copy log file. xfsdump-2.2.9 (27 March 2003) - add -f option to xfsdq(8) to specify an output file instead of using the standard output stream. This file is created by xfsdq and xfsdq will fail to run if it exists already. The file is also created with a more appropriate mode than whatever the umask happened to be when xfsdump(8) was run. xfsdump-2.2.8 (27 March 2003) - cleanups to the build process, in particular the automatic rpm package generation Makefile and spec file template. - Makepkgs script can now propagate failures back from make. xfsdump-2.2.7 (13 March 2003) - add initial support for TS tape driver. (19 February 2003) - fix xfsdump -I option to set correct fsid. xfsdump-2.2.6 (19 December 2002) - add initial internationalisation support. xfsdump-2.2.5 (19 December 2002) - fix build fallout from macro changes in XFS headers. - add a configure check so that we don't attempt to build against old versions of the headers. xfsdump-2.2.4 (08 November 2002) - configure now looks for, and xfsinvutil uses, the ncurses header and library rather than the curses version - this resolves an issue in those distributions that don't make the compatibility library available. xfsdump-2.2.3 (31 October 2002) - minor update to Debian packaging dependencies. - inventory related bugfix. xfsdump-2.2.2 (03 October 2002) - Remove fork/setuid from fsr. Just chown temp. file to owner. This gets fsr working again with the restricted RESVSP ioctl. Chris Wedgwood xfsdump-2.2.1 (24 September 2002) - minor troff-version-specific fixups for xfsrestore(8). xfsdump-2.2.0 (03 September 2002) - force use of version 1 XFS geometry ioctl everywhere in xfsdump package, so that these tools can still work on older kernels (they don't need the additional information in the new ioctl). - added new config.h.in and configure changes to implement this. - do some additional cleanup after autoconf has run. xfsdump-2.1.5 (14 August 2002) - minor build fix when using relatively old versions of glibc which don't provide the SYS_getdents64 symbol. xfsdump-2.1.4 (01 August 2002) - xfsinvutil -m option added (merge from IRIX). - add missing GPL/copyright headers to several xfsinvutil files. - correct several uses of uuid_compare in xfsinvutil. xfsdump-2.1.3 (30 July 2002) - small xfsinvutil fixups to preserve compatibility with old -n option. - fixed all new xfsinvutil warnings on 64bit platforms xfsdump-2.1.2 (29 July 2002) - xfsinvutil interactive mode - merge of a dump/restore fix from IRIX - test if a child exited with error and if a child did, set the exit_code to EXIT_ERROR. xfsdump-2.1.1 (04 July 2002) - build infrastructure updates so that configure options can be used to specify paths rather than semi-hard-coded path names controlled by the ROOT/ROOT_PREFIX environment variables; eg. now allows /lib64 and /lib32 xfsdump-2.1.0 (14 June 2002) - new fsinfo system call used, mostly changing version to differentiate this. xfsdump-2.0.4 (14 June 2002) - fix xfsrestore/xfsdump version output to report both their version and the respective dump format version. They will report their version from cmd/xfsdump/VERSION. - changed the messages printed out for the xfsrestore interactive mode to emphasize the restore is interactive. xfsdump-2.0.3 (08 May 2002) - fix xfsdump so that it does not cause segmentation fault when media specific object id (OPT_MOBJID) is specified with -I option. - fix similar code for filesystem id (OPT_FSID) option. xfsdump-2.0.2 (08 May 2002) - in xfsdump, check for ERANGE as well as E2BIG for testing of the existence of the SGI_XFSDUMP_SKIP_FILE extended attribute. This only affects dumping using the -e option. This was motivated by an XFS kernel change from returning E2BIG into returning ERANGE. - fix "xfsdump -v silent" to really be silent xfsdump-2.0.1 (13 April 2002) - minor build system updates xfsdump-2.0.0 (07 February 2002) - rework all code dealing with extended attributes to use the new system calls (requires attr-2.0.0 or greater) - also, the attrctl-by-handle ioctl is history, replaced by libhandle routines - more like what we have in IRIX (requires xfsprogs-2.0.0 or greater) - effectively no-op change (cleanup) - switch over to using XFS_IOC_FSGEOMETRY instead of XFS_IOC_GETFSUUID ioctl, so we can deprecate that "special" UUID ioctl in the kernel. - add -q description to xfsdump/xfsrestore man pages and usage text. - change failed bulkstat WARNING to a TRACE message to that it doesn't bother people. - avoid a possible assertion failure for cumulative restores with -B option. xfsdump-1.1.14 (16 January 2002) - fix xfsrestore so that cumulative restores (with -r) will successfully delete removed directories whose files have also been removed. Previously, the files weren't removed until later, which meant that early directory removal failed. SGI bug#844219. xfsdump-1.1.13 (11 January 2002) - fix xfsdump so that if an inode# is reused in the time between building the inode map and pruning the inode map (in phase 3 when some dirs are marked as not changed), that it no longer aborts with an assertion failure. SGI bug#846374. xfsdump-1.1.12 (14 December 2001) - add new -B option to xfsrestore to correctly assign ownership and permissions of the dump root directory to the destination directory xfsdump-1.1.11 (13 December 2001) - port back IRIX changes primarily to xfsrestore for improving performance when one has over a million files - some extra mlogs (messages) for dump estimates, dir tree diagnostics, type of dump format being used - various fixes for restore with multiple threads and extended attributes (note: multiple threads not implemented on Linux yet) xfsdump-1.1.10 (10 December 2001) - fix xfsdump to endian convert all of the record header fields properly just prior to writing the header out (in particular first_mark_offset). This caused do_next_mark() assertion failures at some sites. xfsdump-1.1.9 (28 November 2001) - fix xfsrestore so that it doesn't delete hardlinks on alternate cumulative restores xfsdump-1.1.8 (14 November 2001) - allow xfsdump to exclude files based on whether they have a certain extended attribute set - don't include /var/lib/xfsdump in the dump xfsdump-1.1.7 (18 October 2001) - xfsrestore -t will no longer fail if the current working directory is not xfs - xfsrestore will no longer issue (harmless) warnings related to space pre-allocation if it is writing to a non-xfs filesystem xfsdump-1.1.6 (03 October 2001) - get rid of useless stkchk abstraction (will no longer get stack info messages with -v proc=debug) - FHS compliance for inventory directory (/var/lib/xfsdump), and existing installations will continue to work as is. - A future xfsdump release will have an updated xfsinvutil to allow the old directory to be migrated to the new manually, without corrupting the inventory (its one or the other only though, not both, and this is enforced by the tools) xfsdump-1.1.5 (28 September 2001) - changes for ia64 (e.g. time32_t, getdents, librmt mtget changes) - fix dump/restore to be able to use drive_scsitape with devfs xfsdump-1.1.4 (18 September 2001) - fix librmt to allow a remote path without "/dev" in its name - this allows xfsdump/xfsrestore to remote file - fix librmt for remote uname to use env variable RSH - add some diagnostics to xfsdump xfsdump-1.1.3 (27 July 2001) - fixes for (hopefully) the last few nits in libtool usage xfsdump-1.1.2 (24 July 2001) - merge in phase 3 changes from review and further testing - merge in code to specify maximum file size for xfsdump (-z) - merge in code to specify media file size for xfsdump (-d) - merge in code to request single media file for xfsdump (-S) - merge a couple of minor bug fixes from IRIX xfsdump-1.1.1 (23 July 2001) - look for libtool archives in /usr/lib, not /lib xfsdump-1.1.0 (18 July 2001) - rework package to use libtool - merge fsr bug fixes from IRIX - merge xfsdump phase 3 performance fixup from IRIX - enable use of (shared) libhandle.so and libattr.so - re-enable use of libdm.so for DMAPI support - remove some more unused "common" files - man page updates for xfsdump and xfsrestore - moved certain binaries from /usr/sbin into /sbin to be available for recovery when only root is mounted xfsdump-1.0.12 (13 July 2001) - Fix mistake introduced in 1.0.10 whereby xfsdump/xfsrestore to remote tape drives will cause rmt debug messages to be written to the remote machine in: /server.XXX (where XXX = pid). These files will no longer be created via xfsdump/xfsrestore. The fix is in librmt - it should have only written out warning messages and not debug messages. If the debug environment variable is turned on for librmt then the debug file will go to /tmp/librmt_debug.XXX. xfsdump-1.0.11 (12 July 2001) - correctly restore block and character device major numbers xfsdump-1.0.10 (05 July 2001) - produce librmt warning messages from xfsdump/xfsrestore without needing to set an environment variable xfsdump-1.0.9 (15 May 2001) - correctly [xfs]restore the suid and guid mode bits xfsdump-1.0.8 (12 May 2001) - added build dependency for Debian on latest devel package xfsdump-1.0.7 (07 May 2001) - fix warnings, remove last -Wall filter - configure script default man path now /usr/share/man - support realtime files in dump/restore - cleanup arch-specific code, esp. the byteswab routines - as a result, move to -O1 as default for extern inlines - fix bug dumping to remote tape device with given user xfsdump-1.0.6 (01 May 2001) - remove spurious warnings when dumping quota information xfsdump-1.0.5 (09 April 2001) - fix use of an uninitialised variable in dump - fix a number of compiler warnings xfsdump-1.0.4 (03 April 2001) - added xfsdump support for dumping quota information xfsdump-1.0.3 (28 March 2001) - minor rpm spec file changes - added xfsdq and xfsrq for dumping quota information xfsdump-1.0.2 (10 January 2001) - support extended attributes in xfsdump and xfsrestore xfsdump-1.0.1 (30 January 2001) - minor rpm and deb packaging work xfsdump-1.0.0 (15 January 2001) - dump, restore, fsr and co. abstracted from xfs-cmds package - completed Debian packaging - late beta code xfsdump-3.1.6+nmu1/doc/split_algorithm.obj0000644000000000000000000003163512607344125015427 0ustar %TGIF 4.1.16 state(0,37,100.000,0,0,0,16,0,9,1,1,0,0,3,0,1,0,'Courier-Bold',1,80640,0,0,0,10,0,0,1,1,0,16,0,0,1,1,1,1,1088,1408,1,0,2880,0). % % @(#)$Header: /home/cattelan/osspush/CVSROOT/xfs-cmds/xfsdump/doc/split_algorithm.obj,v 1.1 2001/12/18 01:56:03 tes Exp $ % %W% % unit("1 pixel/pixel"). color_info(11,65535,0,[ "magenta", 65535, 0, 65535, 65535, 0, 65535, 1, "red", 65535, 0, 0, 65535, 0, 0, 1, "green", 0, 65535, 0, 0, 65535, 0, 1, "blue", 0, 0, 65535, 0, 0, 65535, 1, "yellow", 65535, 65535, 0, 65535, 65535, 0, 1, "pink", 65535, 40606, 44461, 65535, 40606, 44461, 1, "cyan", 0, 65535, 65535, 0, 65535, 65535, 1, "CadetBlue", 12336, 29041, 29812, 12336, 29041, 29812, 1, "white", 65535, 65535, 65535, 65535, 65535, 65535, 1, "black", 0, 0, 0, 0, 0, 0, 1, "DarkSlateGray", 3598, 8995, 8995, 3598, 8995, 8995, 1 ]). script_frac("0.6"). fg_bg_colors('black','white'). page(1,"",1,''). box('black','',128,48,208,80,0,1,1,0,0,0,0,0,0,'1',0,[ ]). text('black',144,52,1,0,1,45,15,1,12,3,0,0,0,0,2,45,15,0,0,"",0,0,0,0,64,'',[ minilines(45,15,0,0,0,0,0,[ mini_line(45,12,3,0,0,0,[ str_block(0,45,12,3,0,0,0,0,0,[ str_seg('black','Courier',0,80640,45,12,3,0,0,0,0,0,0,0, "accum")]) ]) ])]). box('black','',212,48,269,80,0,1,1,4,0,0,0,0,0,'1',0,[ ]). text('black',221,51,1,0,1,36,15,5,12,3,0,0,0,0,2,36,15,0,0,"",0,0,0,0,63,'',[ minilines(36,15,0,0,0,0,0,[ mini_line(36,12,3,0,0,0,[ str_block(0,36,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,36,12,3,0,-1,0,0,0,0,0, "file")]) ]) ])]). poly('black','',2,[ 383,40,383,832],0,1,1,11,0,0,0,0,0,0,0,'1',0,0, "0","",[ 0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[ ]). poly('black','',2,[ 293,65,383,65],3,1,1,12,0,0,0,0,0,0,0,'1',0,0, "0","",[ 0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[ ]). text('black',341,45,1,0,1,27,15,13,12,3,0,0,0,0,2,27,15,0,0,"",0,0,0,0,57,'',[ minilines(27,15,0,0,0,0,0,[ mini_line(27,12,3,0,0,0,[ str_block(0,27,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,27,12,3,0,-1,0,0,0,0,0, "shy")]) ]) ])]). text('black',355,19,1,0,1,54,15,16,12,3,0,0,0,0,2,54,15,0,0,"",0,0,0,0,31,'',[ minilines(54,15,0,0,0,0,0,[ mini_line(54,12,3,0,0,0,[ str_block(0,54,12,3,0,-2,0,0,0,[ str_seg('black','Courier',0,80640,54,12,3,0,-2,0,0,0,0,0, "target")]) ]) ])]). poly('black','',2,[ 294,43,294,832],0,1,1,19,0,0,2,0,0,0,0,'1',0,0, "0","",[ 0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[ ]). text('black',575,54,1,2,1,36,16,20,12,4,0,0,0,0,2,36,16,0,0,"",0,0,0,0,66,'',[ minilines(36,16,0,0,2,0,0,[ mini_line(36,12,4,0,0,0,[ str_block(0,36,12,4,0,-1,0,0,0,[ str_seg('black','Courier-Bold',1,80640,36,12,4,0,-1,0,0,0,0,0, "HOLD")]) ]) ])]). poly('black','',2,[ 470,41,470,834],0,1,1,23,0,0,2,0,0,0,0,'1',0,0, "0","",[ 0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[ ]). box('black','',130,130,210,162,0,1,1,24,0,0,0,0,0,'1',0,[ ]). text('black',146,134,1,0,1,45,15,25,12,3,0,0,0,0,2,45,15,0,0,"",0,0,0,0,146,'',[ minilines(45,15,0,0,0,0,0,[ mini_line(45,12,3,0,0,0,[ str_block(0,45,12,3,0,0,0,0,0,[ str_seg('black','Courier',0,80640,45,12,3,0,0,0,0,0,0,0, "accum")]) ]) ])]). box('black','',214,130,345,162,0,1,1,26,0,0,0,0,0,'1',0,[ ]). text('black',223,133,1,0,1,36,15,27,12,3,0,0,0,0,2,36,15,0,0,"",0,0,0,0,145,'',[ minilines(36,15,0,0,0,0,0,[ mini_line(36,12,3,0,0,0,[ str_block(0,36,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,36,12,3,0,-1,0,0,0,0,0, "file")]) ]) ])]). box('black','',130,199,210,231,0,1,1,31,0,0,0,0,0,'1',0,[ ]). text('black',146,203,1,0,1,45,15,32,12,3,0,0,0,0,2,45,15,0,0,"",0,0,0,0,215,'',[ minilines(45,15,0,0,0,0,0,[ mini_line(45,12,3,0,0,0,[ str_block(0,45,12,3,0,0,0,0,0,[ str_seg('black','Courier',0,80640,45,12,3,0,0,0,0,0,0,0, "accum")]) ]) ])]). box('black','',214,199,407,231,0,1,1,33,0,0,0,0,0,'1',0,[ ]). text('black',223,202,1,0,1,36,15,34,12,3,0,0,0,0,2,36,15,0,0,"",0,0,0,0,214,'',[ minilines(36,15,0,0,0,0,0,[ mini_line(36,12,3,0,0,0,[ str_block(0,36,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,36,12,3,0,-1,0,0,0,0,0, "file")]) ]) ])]). poly('black','',2,[ 384,66,470,66],3,1,1,36,0,0,0,0,0,0,0,'1',0,0, "0","",[ 0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[ ]). text('black',411,44,1,0,1,36,15,39,12,3,0,0,0,0,2,36,15,0,0,"",0,0,0,0,56,'',[ minilines(36,15,0,0,0,0,0,[ mini_line(36,12,3,0,0,0,[ str_block(0,36,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,36,12,3,0,-1,0,0,0,0,0, "bold")]) ]) ])]). text('black',575,135,1,2,1,36,16,41,12,4,0,0,0,0,2,36,16,0,0,"",0,0,0,0,147,'',[ minilines(36,16,0,0,2,0,0,[ mini_line(36,12,4,0,0,0,[ str_block(0,36,12,4,0,-1,0,0,0,[ str_seg('black','Courier-Bold',1,80640,36,12,4,0,-1,0,0,0,0,0, "HOLD")]) ]) ])]). text('black',575,204,1,2,1,36,16,42,12,4,0,0,0,0,2,36,16,0,0,"",0,0,0,0,216,'',[ minilines(36,16,0,0,2,0,0,[ mini_line(36,12,4,0,0,0,[ str_block(0,36,12,4,0,-1,0,0,0,[ str_seg('black','Courier-Bold',1,80640,36,12,4,0,-1,0,0,0,0,0, "HOLD")]) ]) ])]). box('black','',131,286,211,318,0,1,1,43,0,0,0,0,0,'1',0,[ ]). text('black',147,290,1,0,1,45,15,44,12,3,0,0,0,0,2,45,15,0,0,"",0,0,0,0,302,'',[ minilines(45,15,0,0,0,0,0,[ mini_line(45,12,3,0,0,0,[ str_block(0,45,12,3,0,0,0,0,0,[ str_seg('black','Courier',0,80640,45,12,3,0,0,0,0,0,0,0, "accum")]) ]) ])]). box('black','',215,286,498,318,0,1,1,45,0,0,0,0,0,'1',0,[ ]). text('black',224,289,1,0,1,36,15,46,12,3,0,0,0,0,2,36,15,0,0,"",0,0,0,0,301,'',[ minilines(36,15,0,0,0,0,0,[ mini_line(36,12,3,0,0,0,[ str_block(0,36,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,36,12,3,0,-1,0,0,0,0,0, "file")]) ]) ])]). text('black',575,291,1,2,1,45,16,49,12,4,0,0,0,0,2,45,16,0,0,"",0,0,0,0,303,'',[ minilines(45,16,0,0,2,0,0,[ mini_line(45,12,4,0,0,0,[ str_block(0,45,12,4,0,-1,0,0,0,[ str_seg('black','Courier-Bold',1,80640,45,12,4,0,-1,0,0,0,0,0, "SPLIT")]) ]) ])]). box('black','',130,378,330,410,0,1,1,52,0,0,0,0,0,'1',0,[ ]). text('black',146,382,1,0,1,45,15,53,12,3,0,0,0,0,2,45,15,0,0,"",0,0,0,0,394,'',[ minilines(45,15,0,0,0,0,0,[ mini_line(45,12,3,0,0,0,[ str_block(0,45,12,3,0,0,0,0,0,[ str_seg('black','Courier',0,80640,45,12,3,0,0,0,0,0,0,0, "accum")]) ]) ])]). box('black','',332,412,461,444,0,1,1,54,0,0,0,0,0,'1',0,[ ]). text('black',346,420,1,0,1,36,15,55,12,3,0,0,0,0,2,36,15,0,0,"",0,0,0,0,432,'',[ minilines(36,15,0,0,0,0,0,[ mini_line(36,12,3,0,0,0,[ str_block(0,36,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,36,12,3,0,-1,0,0,0,0,0, "file")]) ]) ])]). text('black',575,383,1,2,1,36,16,58,12,4,0,0,0,0,2,36,16,0,0,"",0,0,0,0,395,'',[ minilines(36,16,0,0,2,0,0,[ mini_line(36,12,4,0,0,0,[ str_block(0,36,12,4,0,-1,0,0,0,[ str_seg('black','Courier-Bold',1,80640,36,12,4,0,-1,0,0,0,0,0, "BUMP")]) ]) ])]). poly('black','',2,[ 334,459,382,459],3,1,1,73,0,0,0,0,0,0,0,'1',0,0, "0","",[ 0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[ ]). poly('black','',2,[ 383,458,460,458],3,1,1,77,0,0,0,0,0,0,0,'1',0,0, "0","",[ 0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[ ]). text('black',351,460,1,0,1,9,15,78,12,3,0,0,0,0,2,9,15,0,0,"",0,0,0,0,472,'',[ minilines(9,15,0,0,0,0,0,[ mini_line(9,12,3,0,0,0,[ str_block(0,9,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,9,12,3,0,-1,0,0,0,0,0, "X")]) ]) ])]). text('black',413,460,1,0,1,9,15,80,12,3,0,0,0,0,2,9,15,0,0,"",0,0,0,0,472,'',[ minilines(9,15,0,0,0,0,0,[ mini_line(9,12,3,0,0,0,[ str_block(0,9,12,3,0,-2,0,0,0,[ str_seg('black','Courier',0,80640,9,12,3,0,-2,0,0,0,0,0, "Y")]) ]) ])]). text('black',495,420,1,0,1,27,15,82,12,3,0,0,0,0,2,27,15,0,0,"",0,0,0,0,432,'',[ minilines(27,15,0,0,0,0,0,[ mini_line(27,12,3,0,0,0,[ str_block(0,27,12,3,0,-2,0,0,0,[ str_seg('black','Courier',0,80640,27,12,3,0,-2,0,0,0,0,0, "X xfsdump Internals

xfsdump Internals


Table Of Contents


Linux Caveats

These notes are written for xfsdump and xfsrestore in IRIX. Therefore, it refers to some features that aren't supported in Linux. For example, the references to multiple streams/threads/drives do not pertain to xfsdump/xfsrestore in Linux. Also, the DMF support in xfsdump is not yet useful for Linux.

What's in a dump

Xfsdump is used to dump out an XFS filesystem to a file, tape or stdout. The dump includes all the filesystem objects of:
  • directories (S_IFDIR)
  • regular files (S_IFREG)
  • sockets (S_IFSOCK)
  • symlinks (S_IFLNK)
  • character special files (S_IFCHR)
  • block special files (S_IFBLK)
  • named pipes (S_FIFO)
  • XENIX named pipes (S_IFNAM)
but not mount point types (S_IFMNT). It also does not dump files from /var/xfsdump which is where the xfsdump inventory is located. Other data which is stored:
  • file attributes (stored in stat data) of owner, group, permissions, and date stamps
  • any extended attributes associated with these file objects
  • extent information is stored allowing holes to be reconstructed on restoral
  • actual file data of the extents

Dump Format

The dump format is the layout of the data for storage in a dump. This is mostly done at an abstraction above the media dump format (tape or data file). The tape format, for example, will have extra header records. The tape format will be done in multiple media files, whereas the data file format will use 1 media file.

Media Files

Media files are probably used to provide a way of recovering more data in xfsrestore(1) should there be some media error. They provide a self-contained unit for restoration. If the dump media is a disk file (drive_simple.c) then I believe that only one media-file is used. Whereas on tape media, multiple media files are used depending upon the size of the media file. The size of the media file is set depending on the drive type (in IRIX): QIC: 50Mb; DAT: 512Mb; Exabyte: 2Gb; DLT: 4Gb; others: 256Mb. This value (media file size) is now able to be changed by the "-d" option. . Also, on tape, the dump is finished by an inventory media file followed by a terminating null media file.

A global header is placed at the start of each media file.


global_hdr_t (4K bytes)
magic# = "xFSdump0"
version#
checksum
time of dump
ip address
dump id
hostname
dump label
pad to 1K bytes
drive_hdr_t (3K bytes)
    drive count
    drive index
    strategy id = on-file, on-tape, on-rmt-tape
    pad to 512 bytes

    specific (512 bytes)
        tape:
	    rec_hdr
	    magic# - tape magic = 0x13579bdf02468acell
	    version#
	    block size
	    record size
	    drive capabilities
	    record's byte offset in media file
	    byte offset of rirst mark set
	    size (bytes) of record containing user data
	    checksum (if -C used)
	    ischecksum (= 1 if -C used)
	    dump uuid
	    pad to 512 bytes

    upper: (2K bytes)
	media_hdr_t
	media-label
	previous media-label
	media-id
	previous media-id
	5 media indexes - (indices of object/file within stream/media-object)
	strategy id = on-file, on-tape, on-rmt-tape
	strategy specific data:
	  field to denote if media file is a terminator (old fmt)
	upper: (to 2K) 

Note that the strategy id is checked on restore so that the dump strategy and the strategy used by restore are the same with the exception that drive_scsitape matches with drive_minrmt. This strategy check has caused problems with customers in the past. In particular, if one sends xfsdump's stdout to a tape (i.e. xfsdump -L test -M test - / >/dev/tape) then one can not restore this tape using xfsrestore by specifying the tape with the -f option. There was also a problem for a time where if one used a drive with the TS tape driver, xfsdump wouldn't recognise this driver and would select the drive_simple strategy.


Inode Map

Directories

Non-directory files


Regular files, as can be seen from above, have a list of extents followed by the file's extended attributes. If the file is large and/or the dump is to multiple streams, then the file can be dumped in multiple records or extent groups. (See Splitting a Regular File).

Format on Tape

At the beginning of each tape record is a header. However, for the first record of a media file, the record header is buried inside the global header at byte offset 1536 (1K + 512), as is shown in the global header diagram. Reproduced again:
rec_hdr
magic# - tape magic = 0x13579bdf02468acell
version#
block-size
record-size
drive capabilities
record's byte offset in media file
byte offset of rirst mark set
size (bytes) of record containing user data
checksum (if -C used)
ischecksum (= 1 if -C used)
dump uuid
pad to 512 bytes

I can not see where the block-size ("tape_blksz") is ever used ! The record-size ("tape_recsz") is used as the byte count to do the actual write and read system calls.

There is another layer of s/ware for the actual data on the tape. Although, one may write out an inode-map or directory entries, one doesn't just give these record buffers straight to the write system call to write out. Instead, these data objects are written to buffers (akin to <stdio>). Another thread reads from these buffers (unless its running single-threaded) and writes them to tape. Specifically, inside a loop, one calls do_get_write_buf, copies over the data one wants stored and then calls do_write_buf, until the entire data buffer has been copied over.


Run Time Structure

This section reviews the run time structure and failure handling in dump/restore (see IRIX PV 784355). The diagram below gives a schematic of the runtime structure of a dump/restore session to multiple drives.


1.           main process	main.c
	       /  |   \
	      /   |    \
2.	stream  stream  stream	dump/content.c restore/content.c
       manager  manager manager
	   |      |      |
3.	 drive  drive   drive	common/drive.[hc]
	object  object  object
	   |      |      |
4.	   O      O      O	ring buffers common/ring.[ch]
           |      |      |
5.	 slave  slave   slave	ring_create(... ring_slave_entry ...)
	thread  thread  thread
	   |      |      |
6.	 drive  drive   drive	physical drives
	device  device  device

Each stream is broken into two threads of control: a stream manager; and a drive manager. The drive manager provides an abstraction of the tape device that allows multiple classes of device to be handled (including normal files). The stream manager implements the actual dump or restore functionality. The main process and stream managers interact with the drive managers through a set of device ops (e.g.: do_write, do_set_mark, ... etc).

The process hierachy is shown above. main() first initialises the drive managers with calls to the drive_init functions. In addition to choosing and assigning drive strategies and ops for each drive object, the drive managers intialise a ring buffer and (for devices other than simple UNIX files) sproc off a slave thread that that handles IO to the tape device. This initialisation happens in the drive_manager code and is not directly visible from main().

main() takes direct responsibility for initialising the stream managers, calling the child management facility to perform the sprocs. Each child begins execution in childmain(), runs either content_stream_dump or content_stream_restore and exits with the return code from these functions.

Both the stream manager processes and the drive manager slaves set their signal disposition to ignore HUP, INT, QUIT, PIPE, ALRM, CLD (and for the stream manager TERM as well).

The drive manager slave processes are much simpler, and are initialised with a call to ring_create, and begin execution in ring_slave_func. The ring structure must also be initialised with two ops that are called by the spawned thread: a ring read op, and a write op. The stream manager communicates with the tape manager across this ring structure using Ring_put's and Ring_get's.

The slave thread sits in a loop processing messages that come across the ring buffer. It ignores signals and does not terminate until it receives a RING_OP_DIE message. It then exits 0.

The main process sleeps waiting for any of its children to die (ie. waiting for a SIGCLD). All children that it cares about (stream managers and ring buffer slaves) are registered through the child manager abstraction. When a child dies wait status and other info is stored with its entry in the child manager. main() ignores the deaths of children (and grandchildren) that are not registered through the child manager. The return status of these subprocesses is checked and in the case of an error is used to determine the overall exit code.

We do not expect slave threads to ever die unexpectedly: they ignore most signals and only exit when they receive a RING_OP_DIE at which point they drop out of the message processing loop and always signal success.

Thus the only child processes that can affect the return status of dump or restore are the stream managers, and these processes take their exit status from the values returned by content_stream_dump and content_stream_restore.


xfsdump

Control Flow of xfsdump

Below is a higher level summary of the control flow. Further details are given later.
  • initialize the drive strategy for a tape, file, minimal remote tape
  • create the global header

content_init (xfsdump version)

Do up to 5 phases, which create and prune the inode map, calculate an estimate of the file data size and using that create inode-ranges for multi-stream dumps if pertinent.

  • phase 1: create a subtree list based on the -s subtree spec.
  • phase 2: create the inode map
    The inode map stores the type of the inode: directory or non-directory, and a state value to say whether it has changed or not. The inode map is built by processing each inode (using bulkstat) and in order to work out if it should be marked as changed, by comparing its date stamp with the date of the base or interrupted dump. We also update the size for non-dir regular files (bs_blocks * bs_blksize)
  • phase 3: prune the unneeded subtrees due to the set of unchanged directories or the subtrees specified in -s (phase 1). This works by marking higher level directories as unchanged (MAP_DIR_NOCHNG) in the inode map.
  • phase 4: estimate non-dir (file) size if pruning was done since phase 2. It calculates this by processing each inode (using bulkstat) and looking up the inode map to see if it is a changed non-dir (file). If it is then it uses (bs_blocks * bs_blksize) as in phase 2.
  • phase 5: if we have multiple streams, then it splits up the dump to try to give each stream a set of inodes which has an equal amount of file data. See the section on "Splitting a dump over multiple streams" below.
  • if 1 stream, then we call content_stream_dump and if multi stream, then we create children sprocs which call content_stream_dump.

content_stream_dump

  • write global header
  • loop dumping media files
    • dump the changed/needed directories by processing all inodes from bulkstat
      • dump the filehdr based on the bulkstat structure
      • dump the directory entries (using getdents())
      • dump a null dirent terminator
      • dump extended attributes on directory if it has them
    • dump the changed/needed files by processing all inodes from bulkstat (check the multistream range to see if it should be dumped by this particular stream)
      • dump the filehdr
      • dump the extents (called extent groups - max at 16Mb)
        • align to page boundary by dumping EXTENTHDR_TYPE_ALIGN records
        • dump data as EXTENTHDR_TYPE_DATA records
      • dump a null terminator, EXTENTHDR_TYPE_LAST
    • if not EOM then write null file header
    • end the media file
    • update online inventory
  • if multiple-media dump (i.e. tape dump and not file dump) then
    • dump the session inventory to a media file
    • dump the terminator to a media file

The main function of xfsdump
* drive_init1 - initialize drive manager for each stream
  - go thru cmd options looking for -f device
  - each device requires a drive-manager and hence an sproc 
    (sproc = IRIX lightweight process)
  - if supposed to run single threaded then can only
    support one device

  - ?? each drive but drive-0 can complete file from other stream
  - allocate drive structures for each one -f d1,d2,d3
  - if "-" specified for std out then only one drive allowed

  - for each drive it tries to pick best strategy manager
    - there are 3 strategies 
      1) simple - for dump on file
      2) scsitape - for dump on tape
      3) minrmt - minimal protocol for remote tape (non-SGI)
    - for given drive it is scored by each strategy given
      the drive record which basically has device name,
      and args
    - set drive's strategy to the best one and
      set its strategy's mark separation and media file size
    - instantiate the strategy
      - set flags given the args
      - for drive_scsitape/ds_instantiate
	  - if single-threaded then allocate a buffer of
	    STAPE_MAX_RECSZ page aligned
	  - otherwise, create a ring buffer
      - note if remote tape (has ":" in name)
      - set capabilities of BSF, FSF, etc.

* create global header 
  - store magic#, version, date, hostid, uuid, hostname
  - process args for session-id, dump-label, ...

* if have sprocs, then install signal handlers and hold the
  signals (don't deliver but keep 'em pending)

* content_init

  * inomap_build() - stores stream start-points and builds inode map

  - phase1: parsing subtree selections (specified by -s options) 
    INPUT: 
	- sub directory entries (from -s)
    FLOW:
	- go thru each subtree and 
	  call diriter(callback=subtreelist_parse_cb)
	  - diriter on subtreelist_parse_cb  
	    - open_by_handle() on dir handle
	    - getdents()
	    - go thru each entry
		- bulkstat for given entry inode
		- gets stat buf for callback - use inode# and mode (type)
		- call callback (subtreelist_parse_cb())
	  * subtreelist_parse_cb
	    - ensure arg subpath matches dir.entry subpath
	    - if so then add to subtreelist
	    - recurse thru rest of subpaths (i.e. each dir in path)
    OUTPUT:
	- linked list of inogrp_t = pagesize of inode nums
	- list of inodes corresponding to subtree path names

  - premptchk: progress report, return if got a signal
  
  - phase2: creating inode map (initial dump list)
    INPUT: 
      - bulkstat records on all the inodes in the file system
    FLOW:
      - bigstat_init on cb_add()
	  - loops doing bulkstats (using syssgi() or ioctl())
	    until system call returns non-zero value
	  - each bulkstat returns a buffer of xfs_bstat_t records
	    (buffer of size bulkreq.ocount)
	  - loop thru each xfs_bstat_t record for an inode  
	    calling cb_add()
	  * cb_add
	    - looks at latest mtime|ctime and 
	      if inode is resumed:
		 compares with cb_resumetime for change 
	      if have cb_last:
		 compares with cb_lasttime for change
	    - add inode to map (map_add) and note if has changed or not
	    - call with state of either 
		changed - MAP_DIR_CHANGE, MAP_NDR_CHANGE
		not changed - MAP_DIR_SUPPRT or MAP_NDR_NOCHNG
	    - for changed non-dir REG inode, 
	      data size for its dump is added by bs_blocks * bs_blksize
	    - for non-changed dir, it sets flag for <pruneneeded>
	      => we don't want to process this later !
	  * map_add
	    - segment = <base, 64-low, 64-mid, 64-high>
		      = like 64 * 3-bit values (use 0-5)
		      i.e. for 64 inodes, given start inode number
		#define MAP_INO_UNUSED  0 /* ino not in use by fs - 
                                             Used for lookup failure */
		#define MAP_DIR_NOCHNG  1 /* dir, ino in use by fs, 
                                             but not dumped */
		#define MAP_NDR_NOCHNG  2 /* non-dir, ino in use by fs, 
                                             but not dumped */
		#define MAP_DIR_CHANGE  3 /* dir, changed since last dump */

		#define MAP_NDR_CHANGE  4 /* non-dir, changed since last dump */

		#define MAP_DIR_SUPPRT  5 /* dir, unchanged 
                                             but needed for hierarchy */
		- hunk = 4 pages worth of segments, max inode#, next ptr in list
	    - i.e. map = linked list of 4 pages of segments of 64 inode states
    OUTPUT:
	- inode map = list of all inodes of file system and 
	  for each one there is an associated state variable
	  describing type of inode and whether it has changed
	- the inode numbers are stored in chunks of 64 
	  (with only the base inode number explicitly stored)

  - premptchk: progress report, return if got a signal

  - if <pruneneeded> (i.e. non-changed dirs) OR subtrees specified (-s)
    - phase3:  pruning inode map (pruning unneeded subtrees) 
	INPUT:
	    - subtree list
	    - inode map
	FLOW:
	- bigstat_iter on cb_prune() per inode
	* cb_prune
	  - if have subtrees and subtree list contains inode
	    -> need to traverse every group (inogrp_t) and 
               every page of inode#s
	    - diriter on cb_count_in_subtreelist
	      * cb_count_in_subtreelist:
	      - looks up each inode# (in directory iteration) in subtreelist
	      - if exists then increment counter
	    - if at least one inode in list 
	      - diriter on cb_cond_del
	      * cb_cond_del:
            - TODO

	OUTPUT:
            - TODO

- TODO: phase4 and phase5

- if single-threaded (miniroot or pipeline) then
    * drive_init2
	- for each drive
	    * drive_allochdrs
	    * do_init
    * content_stream_dump
    - return

- else (multithreaded std. case)
    * drive_init2 (see above)
    * drive_init3
	- for each drive
	    * do_sync
    - for each stream create a child manager
	* cldmgr_create
	    * childmain
		* content_stream_dump
		* do_quit

- loop waiting for children to die
* content_complete


Dumping to Tape
* content_stream_dump
  * Media_mfile_begin
    write out global header (includes media header; see below)

  - loop dumping media files
    * inomap_dump()
      - dumps out the linked list of hunks of state maps of inodes

    * dump_dirs()
      - bulkstat through all inodes of file system

      * dump_dir()
        - lookup inode# in inode map
        - if state is UNSUSED or NOCHANGED then skip inode dump
        - jdm_open() = open_by_handle() on directory
        * dump_filehdr()
          - write out 256 padded file header
          - header = <offset, flags, checksum, 128-byte bulk stat structure >
          - bulkstat struct derived from xfs_bstat_t 
            - stnd. stat stuff + extent size, #of extents, DMI stuff
          - if HSM context then 
            - modify bstat struct to make it offline
        - loops calling getdents()
          - does a bulkstat or bulkstat-single of dir inode 
          * dump_dirent()
            - fill in direnthdr_t record
            - <ino, gen & DENTGENMASK, record size, 
                  checksum, variable length name (8-char padded)>
              - gen is from statbuf.bs_gen
            - write out record 
        - dump null direnthdr_t record
        - if dumpextattr flag on and it 
          has extended attributes (check bs_xflags)
          * dump_extattrs 
            * dump_filehdr() with flags of FILEHDR_FLAGS_EXTATTR
              - for root and non-root attributes
                - get attribute list (attr_list_by_handle())
            * dump_extattr_list
              - TODO

    - bigstat iter on dump_file()
      - go thru each inode in file system and apply dump_file 
      * dump_file()
	- if file's inode# is less than the start-point then skip it
	  -> presume other sproc handling dumping of that inode
	- if file's inode# is greater than the end-point then stop the loop
	- look-up inode# in inode map
	- if not in inode-map OR hasn't changed then skip it
	- elsif stat is NOT a non-dir then we have an error
	- if have an hsm context then initialize context 
	- call dump function depending on file type (S_IFREG, S_IFCHR, etc.)

	  * dump_file_reg (for S_IFREG):
	    -> see below

	  * dump_file_spec (for S_IFCHAR|BLK|FIFO|NAM|LNK|SOCK):
	    - dump file header
	    - if file is S_IFLNK (symlink) then
	      - read link by handle into buffer
	      - dump extent header of type, EXTENTHDR_TYPE_DATA
	      - write out link buffer (i.e. symlink string)

	  - if dumpextattr flag on and it 
	    has extended attributes (check bs_xflags)
	    * dump_extattrs (see the same call in the dir case above)

    - set mark

    - if haven't hit EOM (end of media) then
      - write out null file header
      - set mark

    - end media file by do_end_write()

    - if got an inventory stream then
      * inv_put_mediafile
	- create an inventory-media-file struct (invt_mediafile_t)
	  - < media-obj-id, label, index, start-ino#, start-offset, 
		 end-ino#, end-offset, size = #recs in media file, flag >
	* stobj_put_mediafile

  - end of loop of media file dumping
  - lock and increment the thread done count

  - if dump supports multiple media files (tapes do but dump-files don't) then
    - if multi-threaded then 
      - wait for all threads to have finished dumping
        (loops sleeping for 1 second each iter)
    * dump_session_inv
      * inv_get_sessioninfo
        (get inventory session data buffer)
        * stobj_get_sessinfo
        * stobj_pack_sessinfo
      * Media_mfile_begin
      - write out inventory buffer
      * Media_mfile_end
      * inv_put_mediafile (as described above)
    * dump_terminator
      * Media_mfile_begin
      * Media_mfile_end

* dump_file_reg (for S_IFREG):
  - if this is the start inode, then set the start offset
  - fixup offset for resumed dump
  * init_extent_group_context 
    - init context - reset getbmapx struct fields with offset=0, len=-1
    - open file by handle 
    - ensure Mandatory lock not set
  - loop dumping extent group
    - dump file header
    * dump_extent_group() [content.c]
      - set up realtime I/O size
      - loop over all extents
	- dump extent
	  - stop if we reach stop-offset
	  - stop if offset is past file size i.e. reached end
	  - stop if exceeded per-extent size

	  - if next-bmap is at or past end-bmap then get a bmap
	    - fcntl( gcp->eg_fd, F_GETBMAPX, gcp->eg_bmap[] )
	    - if have an hsm context then
	      - call HsmModifyExtentMap()
	    - next-bmap = eg_bmap[1]
	    - end-bmap = eg_bmap[eg_bmap[0].bmv_entries+1]

	  - if bmap entry is a hole (bmv_block == -1) then
	    - if dumping ext.attributes then
	      - dump extent header with bmap's offset, 
		extent-size and type EXTENTHDR_TYPE_HOLE

	    - move onto next bmap
	      - if bmap's (offset + len)*512 > next-offset then 
		update next-offset to this
	      - inc ptr

	  - if bmap entry has zero length then
	    - move onto next bmap

	  - get extsz and offset from bmap's bmv_offset*512 and bmv_length*512

	  - about 8 different conditions to test for
	    - cause function to return OR
	    - cause extent size to change OR...

	  - if realtime or extent at least a PAGE worth then
	    - align write buffer to a page boundary
	    - dump extent header of type, EXTENTHDR_TYPE_ALIGN

	  - dump extent header of type, EXTENTHDR_TYPE_DATA
	  - loop thru extent data to write extsz worth of bytes
	    - ask for a write buffer of extsz but get back actualsz
	    - lseek to offset
	    - read data of actualsz from file into buffer
	    - write out buffer
	    - if at end of file and have left over space in the extent then
	      - pad out the rest of the extent 
	    - if next offset is at or past next-bmap's offset+len then
	      - move onto next bmap
    - dump null extent header of type, EXTENTHDR_TYPE_LAST
    - update bytecount and media file size
  - close the file


Splitting a Regular File

If a regular file is greater than 16Mb (maxextentcnt = drivep->d_recmarksep = recommended max. separation between marks), then it is broken up into multiple extent groups each with their own filehdr_t's. A regular file can also be split, if we are dumping to multiple streams and the file would span the stream boundary.

Splitting a dump over multiple streams (Phase 5)

If one is dumping to multiple streams, then xfsdump calculates an estimate of the dump size and divides by the number of streams to determine how much data we should allocate for a stream. The inodes are processed in order from bulkstat in the function cb_startpt. Thus we start allocating inodes to the first stream until we reach the allocated amount and then need to decide how to proceed on to the next stream. At this point we have 3 actions:
Hold
Include this file in the current stream.
Bump
Start a new stream beginning with this file.
Split
Split this file across 2 streams in different extent groups.


xfsrestore

Control Flow of xfsrestore

content_init (xfsrestore version)

Initialize the mmap files of:

  • "$dstdir/xfsrestorehousekeepingdir/state"
  • "$dstdir/xfsrestorehousekeepingdir/dirattr"
  • "$dstdir/xfsrestorehousekeepingdir/dirextattr"
  • "$dstdir/xfsrestorehousekeepingdir/namreg"
  • "$dstdir/xfsrestorehousekeepingdir/inomap"
  • "$dstdir/xfsrestorehousekeepingdir/tree"
content_stream_restore
  • one stream does while others wait:
    • validates command line dump spec against the online inventory
    • incorporates the online inventory into the persistent inventory
  • one stream does while others wait:
    • if which session to restore is still unknown then
      • search media files of dump to match command args or ask the user to select the media file
      • add found media file to persistent inventory
  • one stream does while others wait:
    • search for directory dump
    • calls dirattr_init if necessary
    • calls namreg_init if necessary
    • initialize the directory tree (tree_init)
    • read the dirents into the tree (applydirdump)
  • one stream does while others wait:
    • do tree post processing (treepost)
      • create the directories (mkdir)
      • cumulative restore file system fixups
  • all threads can process each media file of their dumps for restoring the non-directory files
    • loop over each media file
      • read in file header
      • call applynondirdump for file hdr
        • restore extended attributes for file (if it is last extent group of file)
        • restore file
          • loop thru all hardlink paths from tree for inode (tree_cb_links) and call restore_file_cb
            • if a hard link then link(path1, path2)
            • else restore the non-dir object:
              • S_IFREG -> restore_reg - restore regular file
                • if realtime set O_DIRECT
                • truncate file to bs_size
                • set the bs_xflags for extended attributes
                • set DMAPI fields if necessary
                • loop processing the extent headers
                  • if type LAST then exit loop
                  • if type ALIGN then eat up the padding
                  • if type HOLE then ignore
                  • if type DATA then copy the data into the file for the extent; seeking to extent start if necessary
                • register the extent group in the partial registry
                • set timestamps using utime(2)
                • set permissions using fchmod(2)
                • set owner/group using fchown(2)
              • S_IFLNK -> restore_symlink
              • else -> restore_spec
          • if no hardlinks references for inode in tree then restore file into orphanage directory
        • update stats
        • loop
          • get mark
          • read file header
          • if corrupt then go to next mark
          • else exit loop
  • one stream does while others wait:
    • finalize
      • restore directory attributes
      • remove orphanage directory
      • remove persistent inode map

content_init in a bit more detail(xfsrestore version)
  • create house-keeping-directory for persistent mmap file data structures. For cumulative and interrupted restores, we need to keep restore session data between invocations of xfsrestore.
  • mmap the "state" file and create if not already existing. Initially just mmap the header. (More details below)
  • if continuing interrupted session then
    • initialize and mmap the directory attribute data and dirextattr file (dirattr_init)
    • initialize name registry data (namreg_init)
    • initialize and mmap the inode map (inomap_sync_pers)
    • initialize and mmap the dirent tree (tree_sync)

    • finalize -> restore directory attributes, delete inode map
  • mmap the state file for the header and the subtree selections
  • update the state header with the command line predicates
  • update the subtree selections via the -s option
  • create extended attribute buffers for each stream
  • mmap the state file for the persistent inventory descriptors

  • initialize and mmap the directory attribute data and dirextattr file (dirattr_init)
  • initialize name registry data (namreg_init)
  • initialize and mmap the inode map (inomap_sync_pers)
  • initialize and mmap the dirent tree (tree_sync)

Persistent Inventory and State File

The persistent inventory is found inside the "state" file. The state file is an mmap'ed file called $dstdir/xfsrestorehousekeepingdir/state. The state file (struct pers from content.c) contains a header of:
  • command line arguments from 1st session,
  • partial registry data structure for use with multiple streams and extended attributes,
  • various session state such as dumpid, dump label, number of inodes restored so far, etc.

Followed by pages for the subtree selections and then the persistent inventory.
So the 3 main sections look like:
"state" mmap file
---------------------
| State Header      |
| (number of pages  |
|  to hold pers_t)  |
| pers_t:           |
| accum. state      |
|   - cmd opts      |
|   - etc...        |
| session state     |
|   - dumpid        |
|   - accum.time    |
|   - ino count     |
|   - etc...        |
|   - stream head   |
---------------------
| Subtree           |
| Selections        |
| (stpgcnt * pgsz)  |
---------------------
| Persistent        |
| Inventory         |
| Descriptors       |
| (descpgcnt * pgsz)|
|                   |
---------------------
Persistent Inventory Tree
e.g. drive1         drive2        drive3
|-------------|  |---------|   |---------|
| stream1     |->| stream2 |-->| stream3 |
|(pers_strm_t)|  |         |   |         |
|-------------|  |---------|   |---------|
		    ||
		    \/
                 e.g. tape21        tape22         tape23
		 |------------|   |---------|   |---------|
		 |  obj1      |-->|  obj2   |-->|  obj3   |
		 |(pers_obj_t)|   |         |   |         |
		 |------------|   |---------|   |---------|
				    ||
				    \/
				 |-------------|   |---------|   |---------|
				 | file1       |-->|  file2  |-->|  file3  |
				 |(pers_file_t)|   |         |   |         |
				 |-------------|   |---------|   |---------|
[TODO: persistent inventory needs investigation]

Restore's directory entry tree

As can be seen in the directory dump format above, part of the dump consists of directories and their associated directory entries. The other part consists of the files which are just identified by their inode# which is sourced from bulkstat during the dump. When restoring a dump, the first step is reconstructing the tree of directory nodes. This tree can then be used to associate the file with it's directory and so restored to the correct location in the directory structure.

The tree is an mmap'ed file called $dstdir/xfsrestorehousekeepingdir/tree. Different sections of it will be mmap'ed separately. It is of the following format:

--------------------
|  Tree Header     | <--- ptr to root of tree, hash size,...
|  (pgsz = 16K)    |
--------------------
|  Hash Table      | <--- inode# ==map==> tree node
--------------------
|  Node Header     | <--- describes allocation of nodes
|  (pgsz = 16K)    |
--------------------
|  Node Segment#1  | <--- typically 1 million tree nodes
--------------------
|  ...             |
|                  |
--------------------
|  Node Segment#N  |
--------------------

The tree header is described by restore/tree.c/treePersStorage, and it has such things as pointers to the root of the tree and the size of the hash table.

        ino64_t p_rootino - ino of root
        nh_t p_rooth - handle of root node
        nh_t p_orphh - handle to orphanage node
        size64_t p_hashsz - size of hash array
        size_t p_hashmask - hash mask (private to hash abstraction)
        bool_t p_ownerpr - whether to restore directory owner/group attributes
        bool_t p_fullpr - whether restoring a full level 0 non-resumed dump
        bool_t p_ignoreorphpr - set if positive subtree or interactive
        bool_t p_restoredmpr - restore DMI event settings

The hash table maps the inode number to the tree node. It is a chained hash table with the "next" link stored in the tree node in the n_hashh field of struct node in restore/tree.c. The size of the hash table is based on the number of directories and non-directories (which will approximate the number of directory entries - won't include extra hard links). The size of the table is capped below at 1 page and capped above at virtual-memory-limit/4/8 (i.e. vmsz/32) or the range of 2^32 whichever is the smaller.

The node header is described by restore/node.c/node_hdr_t and it contains fields to help in the allocation of nodes.

        size_t nh_nodesz -  internal node size
        ix_t nh_nodehkix -
        size_t nh_nodesperseg - num nodes per segment
        size_t nh_segsz - size in bytes of segment
        size_t nh_winmapmax - maximum number of windows
                              based on using up to vmsz/4
        size_t nh_nodealignsz - node alignment
        nix_t nh_freenix - pointer to singly linked freelist
        off64_t nh_firstsegoff - offset to 1st segment
        off64_t nh_virgsegreloff - (see diagram)
                 offset (relative to beginning of first segment) into
                 backing store of segment containing one or
                 more virgin nodes. relative to beginning of segmented
                 portion of backing store. bumped only when all of the
                 nodes in the segment have been placed on the free list.
                 when bumped, nh_virginrelnix is simultaneously set back
                 to zero.
        nix_t nh_virgrelnix - (see diagram)
                 relative node index within the segment identified by
                 nh_virgsegreloff of the next node not yet placed on the
                 free list. never reaches nh_nodesperseg: instead set
                 to zero and bump nh_virgsegreloff by one segment.

All the directory entries are stored in a node segment. Each segment holds around 1 million nodes (NODESPERSEGMIN). The value is greater because the size in bytes must be a multiple of the node size and the page size. However, the code handling the number of nodes was changed recently due to problems at a site. The number of nodes is now based on the value of dircnt+nondircnt in an attempt to fit most of the entries into 1 segment. As the value of dircnt+nondircnt is an approximation to the number of directory entries, we cap below at 1 million entries as was done previously.

Each segment is mmap'ed separately. In fact, the actual allocation of nodes is handled by a few abstractions. There is a node abstraction and a window abstraction. At the node abstraction when one wants to allocate a node using node_alloc(), one first checks the free-list of nodes. If the free list is empty then a new window is mapped and a chunk of 8192 nodes are put on the free list by linking each node using the first 8 bytes (ignoring node fields).


  SEGMENT (default was about 1 million nodes)
|----------|
| |------| |
| |      | |
| | 8192 | |
| | nodes| |   nodes already used in tree
| | used | | 
| |      | | 
| |------| |
|          |
| |------| |     
| |   --------| <-----nh_freenix (ptr to node-freelist)
| |node1 | |  |
| |------| |  | node-freelist (linked list of free nodes) 
| |   ----<---| 
| |node2 | |
| |------| |
............
|----------|


Window Abstraction
The window abstraction manages the mapping and unmapping of the segments (of nodes) of the dirent tree. In the node allocation, mentioned above, if our node-freelist is empty we call win_map() to map in a chunk of 8192 nodes for the node-freelist.

Consider the win_map(offset, return_memptr) function:

One is asking for an offset within a segment.
It looks up its bag for the segment (given the offset), and 
if it's already mapped then 
    if the window has a refcnt of zero, then remove it from the win-freelist
    it uses that address within the mmap region and
    increments refcnt.
else if it's not in the bag then
    if win-freelist is not empty then
        munmap the oldest mapped segment
	remove head of win-freelist
        remove the old window from the bag 
    else /* empty free-list */
        allocate a new window
    endif
    mmap the segment
    increment refcnt
    insert window into bag of mapped segments
endif

The window abstraction maintains an LRU win-freelist not to be confused with the node-freelist. The win-freelist consists of windows (stored in a bag) which are doubly linked ordered by the time they were used. Whereas the node-freelist, is used to get a new node in the node allocation.

Note that the windows are stored in 2 lists. They are doubly linked in the LRU win-freelist and are also stored in a bag. A bag is just a doubly linked searchable list where the elements are allocated using calloc(). It uses the bag as a container of mmaped windows which can be searched using the bag key of window-offset.


BAG:  |--------|     |--------|     |--------|     |--------|     |-------|
      | win A  |<--->| win B  |<--->| win C  |<--->| win D  |<--->| win E |
      | ref=2  |     | ref=1  |     | ref=0  |     | ref=0  |     | ref=0 |
      | offset |     | offset |     | offset |     | offset |     | offset|
      |--------|     |--------|     |--------|     |--------|     |-------|
                                      ^                               ^
                                      |                               |
                                      |                               |
                     |----------------|       |-----------------------|
LRU             |----|---|               |----|---|
win-freelist:   | oldest |               | 2nd    |
                | winptr |<------------->| oldest |<----....
                |        |               | winptr |
                |--------|               |--------|

Call Chain
Below are some call chain scenarios of how the allocation of dirent tree nodes are done at different stages.

1st time we allocate a dirent node:

applydirdump()
  Go thru each directory entry (dirent)
    tree_addent()
      if new entry then
         Node_alloc()
           node_alloc()
             win_map()
               mmap 1st segment/window
               insert win into bag
	       refcnt++
             make node-freelist of 8192 nodes (linked list)
             remove list node from freelist
             win_unmap()
               refcnt--
               put win on win-freelist (as refcnt==0)
             return node

2nd time we call tree_addent():

      if new entry then
         Node_alloc()
           node_alloc()
             get node off node-freelist (8190 nodes left now)
             return node
 
8193th time when we have used up 8192 nodes and node-freelist is emtpy:

      if new entry then
         Node_alloc()
           node_alloc()
             there is no node left on node-freelist
             win_map at the address after the old node-freelist
               find this segment in bag
                 refcnt==0, so remove from LRU win-freelist
                 refcnt++
                 return addr
             make a node-freelist of 8192 nodes from where left off last time
             win_unmap 
               refcnt--
               put on LRU win-freelist as refcnt==0
             get node off node-freelist (8191 nodes left now)
             return node
             
When whole segment used up and thus all remaining node-freelist 
nodes are gone then
(i.e. in old scheme would have used up all 1 million nodes
 from first segment):

      if new entry then
         Node_alloc()
           node_alloc()
             if no node-freelist then
               win_map()
                 new segment not already mapped
                 LRU win-freelist is not empty (we have 1st segment)
                 remove head from LRU win-freelist
                 remove win from bag
                 munmap its segment
                 mmap the new segment
                 add to bag
                 refcnt++
               make a new node-freelist of 8192 nodes
               win_unmap()
                 refcnt--
                 put on LRU win-freelist as refcnt==0
               get node off node-freelist (8191 nodes left now)
               return node

Pseudo-code of snippets of directory tree creation functions (from notes) gives one an idea of the flow of control for processing dirents and adding to the tree and other auxiliary structures:

content_stream_restore()
  ...
  Get next media file
  dirattr_init() - initialize directory attribute structure
  namereg_init() - initialize name registry structure
  tree_init() - initialize dirent tree
  applydirdump() - process the directory dump and create tree - see below
  treepost() - tree post processing where mkdirs happen
  ...

applydirdump()
  ...
  inomap_restore_pers() - read ino map 
  read directories and their entries
    loop 'til null hdr
       dirh = tree_begindir(fhdr, dah) - process dir filehdr
       loop 'til null entry
         rv = read_dirent()
         tree_addent(dirh, dhdrp->dh_ino, dh_gen, dh_name, namelen)
       endloop
       tree_enddir(dirh)
    endloop
  ...

tree_beginddir(fhdrp - fileheader, dahp - dirattrhandle)
  ...
  ino = fhdrp->fh_stat.bs_ino
  hardh = link_hardh(ino, gen) - lookup inode in tree
  if (hardh == NH_NULL) then
    new directory - 1st time seen
    dah = dirattr_add(fhdrp) - add dir header to dirattr structure
    hardh = Node_alloc(ino, gen,....,NF_ISDIR|NF_NEWORPH)
    link_in(hardh) - link into tree 
    adopt(p_orphh, hardh, NRH_NULL) - put dir in orphanage directory
  else
    ...
  endif

tree_addent(parent, inode, size, name, namelen)
  hardh = link_hardh(ino, gen)
  if (hardh == NH_NULL) then
    new entry - 1st time seen
    nrh = namreg_add(name, namelen)
    hardh = Node_alloc(ino, gen, NRH_NULL, DAH_NULL, NF_REFED)
    link_in(hardh)
    adopt(parent, hardh, nrh)
  else
    ...
  endif


Cumulative Restore

A cumulative restore seems a bit different than one might expect. It tries to restore the state of the filesystem at the time of the incremental dump. As the man page states: "This can involve adding, deleting, renaming, linking, and unlinking files and directories." From a coding point of view, this means we need to know what the dirent tree was like previously compared with what the dirent tree is like now. We need this so we can see what was added and deleted. So this means that the dirent tree, which is stored as an mmap'ed file in restoredir/xfsrestorehousekeepingdir/tree should not be deleted between cumulative restores (as we need to keep using it).

So on the first level 0 restore, the dirent tree is created. When the directories are restored and the files are restored, the corresponding tree nodes are marked as NF_REAL. On the next level cumulative restore, when it is processing the dirents, it looks them up in the tree (created on previous restore). If the entry alreadys exists then it marks it as NF_REFED.

In case a dirent has gone away between times of incremental dumps, xfsrestore does an extra pass in the tree preprocessing which traverses the tree looking for non-referenced (not NF_REFED) nodes so that if they exist in the FS (i.e. are NF_REAL) then they can be deleted (so that the FS resembles what it was at the time of the incremental dump). Note there are more conditionals to the code than just that - but that is the basic plan. It is elaborated further below.

Cumulative Restore Tree Postprocessing

After the dirent tree is created or updated from the directory dump cumulative restoral, it does a 4 step postprocessing (treepost):

Steps of Tree Postprocessing
FunctionWhat it does
1. noref_elim_recurse
  • remove deleted dirs
  • rename moved dirs to orphanage
  • remove extra deleted hard links
  • rename moved non-dirs to orphanage
2. mkdirs_recurse
  • mkdirs on (dir & !real & ref & sel)
3. rename_dirs
  • rename moved dirs from orphanage to destination
4. proc_hardlinks
  • rename moved non-dirs from orphanage to destination
  • remove deleted non-dirs (real & !ref & sel)
  • create a link on rename error (don't understand this one)

Step 1 was changed so that files which are deleted and not moved are deleted early on, otherwise, it can stop a parent directory from being deleted. The new step is:

FunctionWhat it does
1. noref_elim_recurse
  • remove deleted dirs
  • rename moved dirs to orphanage
  • remove extra deleted hard links
  • rename moved non-dirs to orphanage
  • remove deleted non-dirs which aren't part of a rename

One will notice that renames are not performed directly. Instead entries are renamed to the orphanage, directories are created, then entries are moved from the orphanage to the intended destination. This would be done as renames may not succeed until directories are created. And the directories are not created first as we may be able to create the entry by just moving an existing one. The step of "removing deleted non-dirs" in proc_hardlinks should not happen now since it is done earlier.


Partial Registry

The partial registry is a data structure used in xfsrestore for ensuring that files which have been split into multiple extent groups, do not restore the extended attributes until the entire file has been restored. The reason for this is apparently so that DMAPI attributes aren't restored until we have the complete file. Each extent group dumped has the identical copy of the extended attributes (EAs) for that file, thus without this data-structure we could apply the first EAs we come across.

The data structure is of the form:

Array of M entries:
-------------------
0: inode#
   Array for each drive
     drive1:  
     ...
     driveN:  
-------------------
1: inode#
   Array for each drive
-------------------
2: inode#
   Array for each drive
-------------------
...
-------------------
M-1: inode#
     Array for each drive
-------------------

Where N = number of drives (streams); M = 2 * N - 1
There can only be 2*N-1 entries for the partial registry because each stream can contribute an entry for its current inode and one for a previous inode which is split - except for the 1st inode which cannot have a previous split.
      stream 1        stream 2         stream 3      ...  stream N
  |---------------|----------------|-------------------|------------|
  |            ------   -----   ------   -----      -------  -----  |
  |            C  | P     C        | P     C           |  P    C    |
  |---------------|----------------|-------------------|------------|

       current       prev.+curr.        prev.+curr.      prev.+curr.

Where C = current; P = previous
So if an extent group is processed which doesn't cover the whole file, then the extent range for this file is updated with the partial registry. If the file doesn't exist in the array then a new entry is added. If the file does exist in the array then the extent group for the given drive is updated. It is worth remembering that one drive (stream) can have multiple extent groups (if it is >16Mb) in which case the extent group is just extended (they are split up in order).

A bug was discovered in this area of code, for DMF offline files which have an associated file size but no data blocks allocated and thus no extents. The Offline files were wrongly added to the partial registry because on restore they did not complete the size of the file (because they are offline!). These types of files which do not restore data are now special cased.


Drive Strategies

The I/O which happens when reading and writing the dump can be to a tape, file, stdout or to a tape remotely via rsh(1) (or $RSH) and rmt(1) (or $RMT). There are 3 pieces of code called strategies which handle the dump I/O:
  • drive_scsitape
  • drive_minrmt
  • drive_simple
There is an associated data structure - below is one for drive_scsitape:
    drive_strategy_t drive_strategy_scsitape = {
	    DRIVE_STRATEGY_SCSITAPE,        /* ds_id */
	    "scsi tape (drive_scsitape)",   /* ds_description */
	    ds_match,                       /* ds_match */
	    ds_instantiate,                 /* ds_instantiate */
	    0x1000000ll,                    /* ds_recmarksep  16 MB */
	    0x10000000ll,                   /* ds_recmfilesz 256 MB */
    };
The choice of the strategy to use is done by a scoring scheme which is probably not warranted IMHO. (A direct cmd option would be simpler and less confusing.) The scoring function is called ds_match.
strategyIRIX scoringLinux scoring
drive_scsitape score badly with -10 if:
  • stdio pathname
  • if colon (':') in pathname (assumes remote) and
    • open on pathname fails
    • MTIOCGET ioctl fails
  • or not colon and drivername is not "tpsc" or "ts_"
else if syscalls complete ok then we score 10.
score like IRIX but instead of checking drivername associated with path (not available on Linux), score -10 if the following:
  • stat fails
  • it is not a character device
  • its real path does not contain "/nst", "/st" nor "/mt".
drive_minrmt
  • score badly with -10 if stdio pathname
  • score 10 if have all of the following:
    • colon is in the pathname (assumes remote from this)
    • blocksize set with -b option
    • minrmt chosen with -m option
  • otherwise score badly with -10
score like IRIX but do not require a colon in the pathname; i.e. one can use this strategy on Linux without requiring a remote pathname
drive_simple
  • score badly with -1 if
    • stat fails on local pathname
    • pathname is a local directory
  • otherwise score with 1
identical to IRIX

Each strategy is organised like a "class" with functions/methods in the data structure:

        do_init,                
        do_sync,                
        do_begin_read,          
        do_read,                
        do_return_read_buf,     
        do_get_mark,            
        do_seek_mark,           
        do_next_mark,           
        do_end_read,            
        do_begin_write,         
        do_set_mark,            
        do_get_write_buf,       
        do_write,               
        do_get_align_cnt,       
        do_end_write,           
        do_fsf,                 
        do_bsf,                 
        do_rewind,              
        do_erase,               
        do_eject_media,         
        do_get_device_class,    
        do_display_metrics,     
        do_quit,                

Drive Scsitape

This strategy is the main one used for dumps to tape and dumps to a remote tape. This strategy on IRIX can be used for remote dumps to another IRIX machine. On Linux, this strategy is used for remote dumps to Linux or IRIX machines. Remote dumping uses the librmt library, see below.

If xfsdump/xfsrestore is running single-threaded (-Z option) or is running on Linux (which is not multi-threaded) then records are read/written straight to the tape. If it is running multi-threaded then a circular buffer is used as an intermediary between the client and slave threads.

Initially drive_init1() calls ds_instantiate() which if dump/restore is running multi-threaded, creates the ring buffer with ring_create which initialises the state to RING_STAT_INIT and sets up the slave thread with ring_slave_entry.

ds_instantiate()
  ring_create(...,ring_read, ring_write,...)
    - allocate and init buffers
    - set rm_stat = RING_STAT_INIT
    start up slave thread with ring_slave_entry
The slave spends its time in a loop getting items from the active queue, doing the read or write operation and placing the result back on the ready queue.
slave
======
ring_slave_entry()
  loop
    ring_slave_get() - get from active queue
    case rm_op
      RING_OP_READ -> ringp->r_readfunc
      RING_OP_WRITE -> ringp->r_writefunc
      ..
    endcase
    ring_slave_put() - puts on ready queue
  endloop

Reading
Prior to reading, one needs to call do_begin_read(), which calls prepare_drive(). prepare_drive() opens the tape drive if necessary and gets its status. It then works out the tape record size to use (set_best_blk_and_rec_sz) using current max blksize (mtinfo.maxblksz from ioctl(fd,MTIOCGETBLKINFO,minfo)) on the scsi tape device in IRIX.

On IRIX (from set_best_blk_and_rec_sz):

  • local tape -> tape_recsz = min(STAPE_MAX_RECSZ = 2 Mb, mtinfo.maxblksz)
    which typically would mean 2 Mb.
  • remote tape -> tape_recsz = STAPE_MIN_MAX_BLKSZ = 240 Kb

On Linux:

  • local tape ->
    • tape_recsz = STAPE_MAX_LINUX_RECSZ = 1 Mb
    • or if -b cmdlineblksize specified then
      tape_recsz = min(STAPE_MAX_RECSZ = 2 Mb, cmdlineblksize)
      which typically would mean cmdlineblksize.
  • remote tape -> tape_recsz = STAPE_MIN_MAX_BLKSZ = 240 Kb

If we have a fixed size device, then it tries to read initially at minimum(2Mb, current max blksize) but if it reads in a smaller number of bytes than this, then it will try again for STAPE_MIN_MAX_BLKSZ = 240 Kb data.

prepare_drive()
  open drive (repeat & timeout if EBUSY)
  get tape status (repeat 'til timeout or online)
  set up tape rec size to try
  loop trying to read a record using straight Read()
      if variable blksize then
	 ok = nread>0 & !EOD & !EOT & !FileMark
      else fixed blksize then
	 ok = nread==tape_recsz & !EOD & !EOT & !FileMark
      endif
      if ok then 
	validate_media_file_hdr()
      else
        could be an error or try again with newsize
        (complicated logic in this code!)
      endif
  endloop

For each do_read call in the multi-threaded case, we have two sides to the story: the client which is coming from code in content.c and the slave which is a simple thread just satisfying I/O requests. From the point of view of the ring buffer, these are the steps which happen for reading:

  1. client removes msg from ready queue
  2. client wants to read, so sets op field to READ (RING_OP_READ) and puts on active queue
  3. slave removes msg from active queue, invokes client read function, sets status field: OK/ERROR, puts msg on ready queue
  4. client removes this msg from ready queue

The client read code looks like the following:

client
======
do_read()
  getrec()
    singlethreaded -> read_record() -> Read()
    else -> 
      loop 'til contextp->dc_recp is set to a buffer
	Ring_get() -> ring.c/ring_get()
	  remove msg from ready queue
	      block on ready queue - qsemP( ringp->r_ready_qsemh )
	      msgp = &ringp->r_msgp[ ringp->r_ready_out_ix ];
	      cyclic_inc(ringp->r_ready_out_ix)
        case rm_stat: 
	  RING_STAT_INIT, RING_STAT_NOPACK, RING_STAT_IGNORE
            put read msg on active queue
		contextp->dc_msgp->rm_op = RING_OP_READ
		Ring_put(contextp->dc_ringp,contextp->dc_msgp);
          RING_STAT_OK
            contextp->dc_recp = contextp->dc_msgp->rm_bufp
          ...
        endcase
      endloop 

Librmt

Librmt is a standard library on IRIX which provides a set of remote I/O functions:
  • rmtopen
  • rmtclose
  • rmtioctl
  • rmtread
  • rmtwrite
On linux, a librmt library is provided as part of the xfsdump distribution. The remote functions are used to dump/restore to remote tape drives on remote machines. It does this by using rsh or ssh to run rmt(1) on the remote machine. The main caveat, however, comes into play for the rmtioctl function. Unfortunately, the values for mt operations and status codes are different on different machines. For example, the offline command op on IRIX is 6 and on Linux it is 7. On Linux, 6 is rewind and on IRIX 7 is a no-op. So for the Linux xfsdump, the rmtiocl function has been rewritten to check what the remote OS is (e.g. rsh host uname) and do appropriate mappings of codes. As well as the different mt op codes, the mtget structures differ for IRIX and Linux and for Linux 32 bit and Linux 64 bit. The size of the mtget structure is used to determine which structure it is and the value of mt_type is used to determine if endian conversion needs to be done.

Drive Minrmt

The minrmt strategy was written based (copied) on the scsitape strategy. It has been simplified so that the state of the tape driver is not needed (i.e. status of EOT, BOT, EOD, FMK,... are not used) and the current blk size of the tape driver is not used. Instead error handling is based on the return codes from reading and writing and the blksize must be give as a parameter. It was designed for talking to remote NON-IRIX hosts where the status codes can vary. However, as was mentioned in the discussion of librmt on Linux, the mt operations vary on foreign hosts as well as the status codes. So this is only a limited solution.

Drive Simple

The simple strategy was designed for dumping to files or stdout. It is simpler in that it does NOT have to worry about:
  • the ring buffer
  • talking to the scsitape driver with various operations and status
  • multiple media files


Online Inventory

xfsdump keeps a record of previous xfsdump executions in the online inventory stored in /var/xfsdump/inventory or for Linux, /var/lib/xfsdump/inventory. This inventory is used to determine which previous dump a incremental dump should be based on. That is, when doing a level > 0 dump for a filesystem, xfsdump will refer to the online inventory to work out when the last dump for that filesystem was performed in order to work out which files will be included in the current dump. I believe the online inventory is also used by xfsrestore in order to determine which tapes will be needed to completely restore a dump.

xfsinvutil is a utility originally designed to remove unwanted information from the online inventory. Recently it has been beefed up to allow interactive browsing of the inventory and the ability to merge/import one inventory into another. (See Bug 818332.)

The inventory consists of three types of files:

Inventory files
Filename Description
fstab There is one fstab file which contains the list of filesystems that are referenced in the inventory.
*.InvIndex There is one InvIndex file per filesystem which contain pointers to the StObj files sorted temporaly.
*.StObj There may be many StObj files per filesystem. Each file contains information about, up to five, individual xfsdump executions. The information relates to what tapes were used, which inodes are stored in which media files, etc.

The files are constructed like so:

fstab

fstab structure
Quantity Data structure
1
typedef struct invt_counter {
    INVT_COUNTER_FIELDS
        __uint32_t    ic_vernum;/* on disk version number for posterity */\
        u_int         ic_curnum;/* number of sessions/invindices recorded \
                                   so far */                              \
        u_int         ic_maxnum;/* maximum number of sessions/inv_indices \
                                   that we can record on this stobj */

    char              ic_padding[0x20 - INVT_COUNTER_FIELDS_SIZE];
} invt_counter_t;
1 per filesystem
typedef struct invt_fstab {
    uuid_t  ft_uuid;
    char    ft_mountpt[INV_STRLEN];
    char    ft_devpath[INV_STRLEN];
    char    ft_padding[16];
} invt_fstab_t;

InvIndex

InvIndex structure
Quantity Data structure
1
typedef struct invt_counter {
    INVT_COUNTER_FIELDS
        __uint32_t    ic_vernum;/* on disk version number for posterity */\
        u_int         ic_curnum;/* number of sessions/invindices recorded \
                                   so far */                              \
        u_int         ic_maxnum;/* maximum number of sessions/inv_indices \
                                   that we can record on this stobj */
    char              ic_padding[0x20 - INVT_COUNTER_FIELDS_SIZE];
} invt_counter_t;
1 per StObj file
typedef struct invt_entry {
    invt_timeperiod_t ie_timeperiod;
    char              ie_filename[INV_STRLEN];
    char              ie_padding[16];
} invt_entry_t;

StObj

StObj structure
Quantity Data structure
1
typedef struct invt_sescounter {
    INVT_COUNTER_FIELDS
        __uint32_t    ic_vernum;/* on disk version number for posterity */\
        u_int         ic_curnum;/* number of sessions/invindices recorded \
                                   so far */                              \
        u_int         ic_maxnum;/* maximum number of sessions/inv_indices \
                                   that we can record on this stobj */
    off64_t  ic_eof;   /* current end of the file, where the next
                          media file or stream will be written to */
    char     ic_padding[0x20 - ( INVT_COUNTER_FIELDS_SIZE + sizeof( off64_t) )];
} invt_sescounter_t;
fixed space for
INVT_STOBJ_MAXSESSIONS (ie. 5)
typedef struct invt_seshdr {
    off64_t    sh_sess_off;    /* offset to rest of the sessioninfo */
    off64_t    sh_streams_off; /* offset to start of the set of
                                  stream hdrs */
    time_t     sh_time;        /* time of the dump */
    __uint32_t sh_flag;        /* for misc flags */
    u_char     sh_level;       /* dump level */
    u_char     sh_pruned;      /* pruned by invutil flag */
    char       sh_padding[22];
} invt_seshdr_t;
fixed space for
INVT_STOBJ_MAXSESSIONS (ie. 5)
typedef struct invt_session {
    uuid_t   s_sesid;	/* this session's id: 16 bytes*/
    uuid_t   s_fsid;	/* file system id */
    char     s_label[INV_STRLEN];  /* session label */
    char     s_mountpt[INV_STRLEN];/* path to the mount point */
    char     s_devpath[INV_STRLEN];/* path to the device */
    u_int    s_cur_nstreams;/* number of streams created under
                               this session so far */
    u_int    s_max_nstreams;/* number of media streams in 
                               the session */
    char     s_padding[16];
} invt_session_t;
any number
typedef struct invt_stream {
    /* duplicate info from mediafiles for speed */
    invt_breakpt_t  st_startino;   /* the starting pt */
    invt_breakpt_t  st_endino;     /* where we actually ended up. this
                                      means we've written upto but not
                                      including this breakpoint. */
    off64_t         st_firstmfile;  /*offsets to the start and end of*/
    off64_t         st_lastmfile;	  /* .. linked list of mediafiles */
    char            st_cmdarg[INV_STRLEN]; /* drive path */
    u_int           st_nmediafiles; /* number of mediafiles */
    bool_t          st_interrupted;	/* was this stream interrupted ? */
    char            st_padding[16];
} invt_stream_t;
typedef struct invt_mediafile {
    uuid_t           mf_moid;	    /* media object id */
    char             mf_label[INV_STRLEN];	/* media file label */
    invt_breakpt_t   mf_startino; /* file that we started out with */
    invt_breakpt_t   mf_endino;	  /* the dump file we ended this 
                                     media file with */
    off64_t          mf_nextmf;   /* links to other mfiles */
    off64_t          mf_prevmf;
    u_int            mf_mfileidx; /* index within the media object */
    u_char           mf_flag;     /* Currently MFILE_GOOD, INVDUMP */
    off64_t          mf_size;     /* size of the media file */
    char             mf_padding[15];
} invt_mediafile_t;

The data structures above converted to a block diagram look something like this:

The source code for accessing the inventory is contained in the inventory directory. The source code for xsfinvutil is contained in the invutil directory. xfsinvutil only uses some header files from the inventory directory for data structure definitions -- it uses its own code to access and modify the inventory.


Questions and Answers

How is -a and -z handled by xfsdump ?
If -a is NOT used then it looks like nothing special happens for files which have dmf state attached to them. So if the file uses too many blocks compared to our maxsize param (-z) then it will not get dumped. No inode nor data. The only evidence will be its entry in the inode map (which is dumped) which says its the state of a no-change-non-dir and the directory entry in the directories dump. The latter will mean that an ls in xfsrestore will show the file but it can not be restored.

If -a is used and the file has some DMF state then we do some magic. However, the magic really only seems to occur for dual-state files (or possibly also unmigrating files).

A file is marked as dual-state/unmigrating by looking at the DMF attribute, dmfattrp->state[1]. i.e = DMF_ST_DUALSTATE or DMF_ST_UNMIGRATING If this is the case, then we set, dmf_f_ctxtp->candidate = 1. If we have such a changed dual-state file then we mark it as changed in the inode-map so it can be dumped. If it is a dual state file, then its apparent size will be zero, so it will go onto the dumping stage.

When we go to dump the extents of the dual-state file, we do something different. We store the extents as only 1 extent which is a hole. I.e. this is the "NOT dumping data" bit.

When we go to dump the file-hdr of the dual-state file, we set, statp->bs_dmevmask |= (1< When we go to dump the extended-attributes of the dual-state file, we skip dumping the DMF attribute ones ! However, at the end of dumping the attributes, we then go and add a new DMF attribute for it:

        dmfattrp->state[1] = DMF_ST_OFFLINE;
        *valuepp = (char *)dmfattrp;
        *namepp = DMF_ATTR_NAME;
        *valueszp = DMF_ATTR_LEN;

Summary:
  • dual state files (and unmigrating files) dumped with -a, cause magic to happen:
    • if file has changed then it will _always_ be marked to be dumped out (irrespective of file size/blocks)
    • its extent data will be dumped as 1 extent with a hole
    • its DMF attributes won't be dumped but a replacement DMF attribute will be dumped in its place
    • the stat buf's bs_devmask will be or'ed with DM_EVENT_READ
  • for all other cases, if the file has changed and its blocks cause it to exceed the maxsize param (-z) then the file will be marked as NOT-CHANGED in the inode map and so will NOT be dumped at all

How does it compute estimated dump size ?
A dump consists of media files (only 1 in the case of a dump to a file, and usually many when dumped to a tape (depending on device type)). A media file consists of:
  • global header
  • inode map (inode# + state(e.g.dump or not?) )
  • directories
  • non-directory files

A directory consists of a header, directory-entry-headers for its entries and extended-attribute header and attributes.

A non-directory file consists of a file header, extent-headers (for each extent), file data and extended-attribute header and attributes. Some types of files don't have extent headers or data.

The xfsdump code says:

        size_estimate = GLOBAL_HDR_SZ
                        +
                        inomap_getsz( )
                        +
                        inocnt * ( u_int64_t )( FILEHDR_SZ + EXTENTHDR_SZ )
                        +
                        inocnt * ( u_int64_t )( DIRENTHDR_SZ + 8 )
                        +
                        datasz;
So this accounts for the:
  • global header
  • inode map
  • all the files
  • all the direntory entries ( "+8" presumably to account for average file name length range, where 8 chars already included in header; as this structure is padded to the next 8 byte boundary, it accounts for names with lengths between 8-15 chars)
  • data

What estimate doesn't seem to account for (that I can think of):

  • no extended attributes
  • assumes that a file will only have one extent
  • no tape block headers (for tape media)

"Datasz" is calculated by adding up for every regular inode file, its (number of data blocks) * (block size). However, if "-a" is used, then instead of doing this, if the file is dualstate/offline then the file's data won't be dumped and it adds zero for it.

Is the "dump size (non-dir files) : 910617928 bytes" the actual number of bytes it wrote to that tape ?
It is the number of bytes it wrote to the dump for the non-directory files' extents (not including file header nor extent header terminator). (I don't think this includes the tape block headers for a tape dump either.) It includes for each file:
  • any hole hdrs
  • alignment hdrs
  • alignment padding
  • extent headers for data
  • actual _data_ of extents
From code:
    bytecnt += sizeof( filehdr_t );
    dump_extent_group(...,&bc,...);
	bytecnt = 0;
	bytecnt += sizeof( extenthdr_t );  /* extent header for hole */
	bytecnt += sizeof( extenthdr_t );  /* ext. alignment header */
	bytecnt += ( off64_t )cnt_to_align /* alignment padding */
	bytecnt += sizeof( extenthdr_t );  /* extent header for data */
	bytecnt += ( off64_t )actualsz;    /* actual extent data in file */  
	bytecnt += ( off64_t )reqsz; /* write padding to make up extent size */
    sc_stat_datadone += ( size64_t )bc;
It doesn't include the initial file header:
    rv = dump_filehdr( ... );
    bytecnt += sizeof( filehdr_t );
nor the extent hdr terminator:
    rv = dump_extenthdr( ..., EXTENTHDR_TYPE_LAST,...);
    bytecnt += sizeof( extenthdr_t );
    contextp->cc_mfilesz += bytecnt;
It only adds this data size into the media file size.


Outstanding Questions

  • How is the inode map on the tape used by xfsrestore ?
  • Is the final inventory media file on the media ever used/restored ?
  • How are tape marks used and written ?
  • What is the difference between a record and a block ?
    • I don't think there is a difference.
  • Where are tape_recsz and tape_blksz used ?
    • Tape_recsz is used for the read/write byte cnt but I don't think tape_blksz is used.
  • What is the persistent inventory used for ?
xfsdump-3.1.6+nmu1/doc/inode_map.obj0000644000000000000000000002041312607344125014151 0ustar %TGIF 4.1.16 state(0,37,100.000,0,0,0,16,1,9,1,1,0,0,1,0,1,0,'Courier',0,80640,0,0,0,10,0,0,0,1,0,16,0,0,1,1,1,1,1088,1408,1,0,2880,0). % % @(#)$Header: /home/cattelan/osspush/CVSROOT/xfs-cmds/xfsdump/doc/inode_map.obj,v 1.2 2002/03/01 07:45:12 tes Exp $ % %W% % unit("1 pixel/pixel"). color_info(11,65535,0,[ "magenta", 65535, 0, 65535, 65535, 0, 65535, 1, "red", 65535, 0, 0, 65535, 0, 0, 1, "green", 0, 65535, 0, 0, 65535, 0, 1, "blue", 0, 0, 65535, 0, 0, 65535, 1, "yellow", 65535, 65535, 0, 65535, 65535, 0, 1, "pink", 65535, 40606, 44461, 65535, 40606, 44461, 1, "cyan", 0, 65535, 65535, 0, 65535, 65535, 1, "CadetBlue", 12336, 29041, 29812, 12336, 29041, 29812, 1, "white", 65535, 65535, 65535, 65535, 65535, 65535, 1, "black", 0, 0, 0, 0, 0, 0, 1, "DarkSlateGray", 3598, 8995, 8995, 3598, 8995, 8995, 1 ]). script_frac("0.6"). fg_bg_colors('black','white'). page(1,"",1,''). box('black','',112,48,432,640,0,1,1,0,0,0,0,0,0,'1',0,[ ]). text('black',224,292,1,0,1,90,15,1,12,3,0,0,0,0,2,90,15,0,0,"",0,0,0,0,304,'',[ minilines(90,15,0,0,0,0,0,[ mini_line(90,12,3,0,0,0,[ str_block(0,90,12,3,0,-2,0,0,0,[ str_seg('black','Courier',0,80640,90,12,3,0,-2,0,0,0,0,0, "max_inode#")]) ]) ])]). text('black',160,84,3,0,1,234,45,3,12,3,0,0,0,0,2,234,45,0,0,"",0,0,0,0,96,'',[ minilines(234,45,0,0,0,0,0,[ mini_line(99,12,3,0,0,0,[ str_block(0,99,12,3,0,-2,0,0,0,[ str_seg('black','Courier',0,80640,99,12,3,0,-2,0,0,0,0,0, "base inode#")]) ]), mini_line(117,12,3,0,0,0,[ str_block(0,117,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,117,12,3,0,-1,0,0,0,0,0, "3 X 64 bitmap")]) ]), mini_line(234,12,3,0,0,0,[ str_block(0,234,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,234,12,3,0,-1,0,0,0,0,0, "= 64 inodes of 3-bit state")]) ]) ])]). box('black','',144,80,400,128,0,1,1,6,0,0,0,0,0,'1',0,[ ]). text('black',160,148,3,0,1,234,45,13,12,3,0,0,0,0,2,234,45,0,0,"",0,0,0,0,160,'',[ minilines(234,45,0,0,0,0,0,[ mini_line(99,12,3,0,0,0,[ str_block(0,99,12,3,0,-2,0,0,0,[ str_seg('black','Courier',0,80640,99,12,3,0,-2,0,0,0,0,0, "base inode#")]) ]), mini_line(117,12,3,0,0,0,[ str_block(0,117,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,117,12,3,0,-1,0,0,0,0,0, "3 X 64 bitmap")]) ]), mini_line(234,12,3,0,0,0,[ str_block(0,234,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,234,12,3,0,-1,0,0,0,0,0, "= 64 inodes of 3-bit state")]) ]) ])]). box('black','',144,144,400,192,0,1,1,14,0,0,0,0,0,'1',0,[ ]). text('black',240,196,1,0,1,27,15,16,12,3,0,0,0,0,2,27,15,0,0,"",0,0,0,0,208,'',[ minilines(27,15,0,0,0,0,0,[ mini_line(27,12,3,0,0,0,[ str_block(0,27,12,3,0,-4,0,0,0,[ str_seg('black','Courier',0,80640,27,12,3,0,-4,0,0,0,0,0, "...")]) ]) ])]). text('black',160,228,3,0,1,234,45,19,12,3,0,0,0,0,2,234,45,0,0,"",0,0,0,0,240,'',[ minilines(234,45,0,0,0,0,0,[ mini_line(99,12,3,0,0,0,[ str_block(0,99,12,3,0,-2,0,0,0,[ str_seg('black','Courier',0,80640,99,12,3,0,-2,0,0,0,0,0, "base inode#")]) ]), mini_line(117,12,3,0,0,0,[ str_block(0,117,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,117,12,3,0,-1,0,0,0,0,0, "3 X 64 bitmap")]) ]), mini_line(234,12,3,0,0,0,[ str_block(0,234,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,234,12,3,0,-1,0,0,0,0,0, "= 64 inodes of 3-bit state")]) ]) ])]). box('black','',144,224,400,272,0,1,1,20,0,0,0,0,0,'1',0,[ ]). box('black','',128,64,416,320,0,1,1,21,0,0,0,0,0,'1',0,[ ]). text('black',448,100,1,0,1,81,15,45,12,3,0,0,0,0,2,81,15,0,0,"",0,0,0,0,112,'',[ minilines(81,15,0,0,0,0,0,[ mini_line(81,12,3,0,0,0,[ str_block(0,81,12,3,0,-2,0,0,0,[ str_seg('black','Courier',0,80640,81,12,3,0,-2,0,0,0,0,0, "segment 0")]) ]) ])]). text('black',448,164,1,0,1,81,15,47,12,3,0,0,0,0,2,81,15,0,0,"",0,0,0,0,176,'',[ minilines(81,15,0,0,0,0,0,[ mini_line(81,12,3,0,0,0,[ str_block(0,81,12,3,0,-3,0,0,0,[ str_seg('black','Courier',0,80640,81,12,3,0,-3,0,0,0,0,0, "segment 1")]) ]) ])]). text('black',448,228,2,0,1,171,30,48,12,3,0,0,0,0,2,171,30,0,0,"",0,0,0,0,240,'',[ minilines(171,30,0,0,0,0,0,[ mini_line(81,12,3,0,0,0,[ str_block(0,81,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,81,12,3,0,-1,0,0,0,0,0, "segment N")]) ]), mini_line(171,12,3,0,0,0,[ str_block(0,171,12,3,0,-4,0,0,0,[ str_seg('black','Courier',0,80640,171,12,3,0,-4,0,0,0,0,0, "(N = 4 pages worth)")]) ]) ])]). text('black',224,564,1,0,1,90,15,54,12,3,0,0,0,0,2,90,15,0,0,"",0,0,0,0,576,'',[ minilines(90,15,0,0,0,0,0,[ mini_line(90,12,3,0,0,0,[ str_block(0,90,12,3,0,-2,0,0,0,[ str_seg('black','Courier',0,80640,90,12,3,0,-2,0,0,0,0,0, "max_inode#")]) ]) ])]). text('black',160,356,3,0,1,234,45,55,12,3,0,0,0,0,2,234,45,0,0,"",0,0,0,0,368,'',[ minilines(234,45,0,0,0,0,0,[ mini_line(99,12,3,0,0,0,[ str_block(0,99,12,3,0,-2,0,0,0,[ str_seg('black','Courier',0,80640,99,12,3,0,-2,0,0,0,0,0, "base inode#")]) ]), mini_line(117,12,3,0,0,0,[ str_block(0,117,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,117,12,3,0,-1,0,0,0,0,0, "3 X 64 bitmap")]) ]), mini_line(234,12,3,0,0,0,[ str_block(0,234,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,234,12,3,0,-1,0,0,0,0,0, "= 64 inodes of 3-bit state")]) ]) ])]). box('black','',144,352,400,400,0,1,1,56,0,0,0,0,0,'1',0,[ ]). text('black',160,420,3,0,1,234,45,57,12,3,0,0,0,0,2,234,45,0,0,"",0,0,0,0,432,'',[ minilines(234,45,0,0,0,0,0,[ mini_line(99,12,3,0,0,0,[ str_block(0,99,12,3,0,-2,0,0,0,[ str_seg('black','Courier',0,80640,99,12,3,0,-2,0,0,0,0,0, "base inode#")]) ]), mini_line(117,12,3,0,0,0,[ str_block(0,117,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,117,12,3,0,-1,0,0,0,0,0, "3 X 64 bitmap")]) ]), mini_line(234,12,3,0,0,0,[ str_block(0,234,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,234,12,3,0,-1,0,0,0,0,0, "= 64 inodes of 3-bit state")]) ]) ])]). box('black','',144,416,400,464,0,1,1,58,0,0,0,0,0,'1',0,[ ]). text('black',240,468,1,0,1,27,15,59,12,3,0,0,0,0,2,27,15,0,0,"",0,0,0,0,480,'',[ minilines(27,15,0,0,0,0,0,[ mini_line(27,12,3,0,0,0,[ str_block(0,27,12,3,0,-4,0,0,0,[ str_seg('black','Courier',0,80640,27,12,3,0,-4,0,0,0,0,0, "...")]) ]) ])]). text('black',160,500,3,0,1,234,45,60,12,3,0,0,0,0,2,234,45,0,0,"",0,0,0,0,512,'',[ minilines(234,45,0,0,0,0,0,[ mini_line(99,12,3,0,0,0,[ str_block(0,99,12,3,0,-2,0,0,0,[ str_seg('black','Courier',0,80640,99,12,3,0,-2,0,0,0,0,0, "base inode#")]) ]), mini_line(117,12,3,0,0,0,[ str_block(0,117,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,117,12,3,0,-1,0,0,0,0,0, "3 X 64 bitmap")]) ]), mini_line(234,12,3,0,0,0,[ str_block(0,234,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,234,12,3,0,-1,0,0,0,0,0, "= 64 inodes of 3-bit state")]) ]) ])]). box('black','',144,496,400,544,0,1,1,61,0,0,0,0,0,'1',0,[ ]). box('black','',128,336,416,592,0,1,1,62,0,0,0,0,0,'1',0,[ ]). text('black',256,612,1,0,1,27,15,63,12,3,0,0,0,0,2,27,15,0,0,"",0,0,0,0,624,'',[ minilines(27,15,0,0,0,0,0,[ mini_line(27,12,3,0,0,0,[ str_block(0,27,12,3,0,-4,0,0,0,[ str_seg('black','Courier',0,80640,27,12,3,0,-4,0,0,0,0,0, "...")]) ]) ])]). box('black','',496,336,656,480,0,1,1,64,0,0,0,0,0,'1',0,[ ]). text('black',512,340,8,0,1,126,120,65,12,3,0,0,0,0,2,126,120,0,0,"",0,0,0,0,352,'',[ minilines(126,120,0,0,0,0,0,[ mini_line(108,12,3,0,0,0,[ str_block(0,108,12,3,0,-4,0,0,0,[ str_seg('black','Courier',0,80640,108,12,3,0,-4,0,0,0,0,0, "3-bit state:")]) ]), mini_line(72,12,3,0,0,0,[ str_block(0,72,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,72,12,3,0,-1,0,0,0,0,0, "= one of")]) ]), mini_line(126,12,3,0,0,0,[ str_block(0,126,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,126,12,3,0,-1,0,0,0,0,0, "MAP_INO_UNUSED")]) ]), mini_line(126,12,3,0,0,0,[ str_block(0,126,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,126,12,3,0,-1,0,0,0,0,0, "MAP_DIR_NOCHNG")]) ]), mini_line(126,12,3,0,0,0,[ str_block(0,126,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,126,12,3,0,-1,0,0,0,0,0, "MAP_NDR_NOCHNG")]) ]), mini_line(126,12,3,0,0,0,[ str_block(0,126,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,126,12,3,0,-1,0,0,0,0,0, "MAP_DIR_CHANGE")]) ]), mini_line(126,12,3,0,0,0,[ str_block(0,126,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,126,12,3,0,-1,0,0,0,0,0, "MAP_NDR_CHANGE")]) ]), mini_line(126,12,3,0,0,0,[ str_block(0,126,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,126,12,3,0,-1,0,0,0,0,0, "MAP_DIR_SUPPRT")]) ]) ])]). poly('black','',2,[ 400,400,496,336],1,1,1,68,0,0,0,0,0,0,0,'1',0,0, "0","",[ 0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[ ]). box('black','',288,384,400,400,0,1,1,69,0,0,0,0,0,'1',0,[ ]). xfsdump-3.1.6+nmu1/doc/inode_map.gif0000644000000000000000000002143712607344125014153 0ustar GIF87a!Q€ÿÿÿ,!Qþ„©Ëí£œ´Ú‹³Þ<‡†âH–扦êʶî Ç+ ×öçúÎ÷þ ‡Ä¢ñx"—̦ó µ)£ÔªÕ7½j·Ü®7ë ‹µà±ùŒN«Êê¶Ç~Ëçtf¼ŽÏîú¾ÿÂ88&Hxˆ(g˜ÈµØyõ(Y9Di™© „¹éYÓù):ÚJzš„ªº cÊÊêú*«;KZk›Ëˆ«»ÉÛ ì÷,9L|¬ˆ üØÑìü -=MýÌb¬ŒÈœÍݵÝ=û >îxMþ*~®Ž”¾>Úîe.ÿN_¿Ÿ_¹ÏÿïÂÀ]÷,è`?„ ’èðĈ 'RÌcñ"ÀþŒçpìˆï#È6"Gº+iò Ê”äV² ãò%·˜2·Ð¬yì&Î*«ùü 4¨Ð  M`Ûi§h‰£HëôlêQéC¨§žRucõꧬZÑpíšé+X1bÇF*k– Ú‡LKé0ÐumÚIRGPj[÷Å"xƒÉË3oˆ»géøp9ÃŒ räÁp×TÞÃ÷2fÍAàfy ù°ÆÄŠŸqYÉÕƒ[ïA˜µkÑg¯žLñté¤Sžm{iè5Ã_Ó–ýY6p¾ˆ+ßmÓ¹ñÞ´PÖ¼€úêéÈ‹gï>ZúqèVt²}*w·Ë×Nî5îˆæÉ1›;ëçÇþ÷¯fíwQ}ö]"3™}özómfˆu9¨hòev]r}-“àtQ—J.Ì…¢Q–×ቃ¨",¶XHŠ0:ñâŒ_Èhã5æ]‰Âñ¨#Ž3p¦‘µÂdžõì¤^BúÆ[B)\„ ýW“Š(iêµBe|X†fe@MiI&èñSc™eªg¥…›e˜†uÖ9afOT¼ÂŽö€ç¼öfË›YëôÃ@çL„žÛ†@ߪq²Ü×(ÇÑ/}tRÖ„9*ì`’óŒ¥0=ÁÅïƒ ìÚúxH£‘ƒ9ÜáÓ$Ä#BwGŠŸÅ(F1‰JüáþÖªh6éaчWÜât2D0z&â£ÍH1òPh$CÍÈÆ6¢È‡hŒ£‘HG8¾ñŽ1ÊãíÈGÓìÑ‹€ d ù9D’ƒÜ¢"i„G~M’D ÙÈJÎq€¤¤&§ÃJöDФ,¥)Oé.~²yLlå*צÊWZ1“² e;hH·ÉR—ãå*}9I*Ö—®\"uÓ8K¡‹ÙæÓ.V7ùE.hœô`.CÇLÐ ŠšZ¼e'±‰¸=lt7P Q(ÃÖdóŸÙk Æ,ìb¯×@|QvDöŒà%‘AÚY {*õŸ ®Øbú…ŸMí¿LþWYV^”f¯m_Ûõ8€®J«½Ýem‘ÙÛXÇ_˲Þß'…–õM D’dc{\Ûpt´yíw7]ÑÊ·™½SOw>„%¦&Kgƒ:™5…Öµ®<åiÙÕBTƒ·Í‰a¥Ôæžïd µi¥ ¤Sí–°ô•°¾"\`å¾Hu=„}×åaiæ¨Äräå‰UÄâ6ƸEÀä*ó¶j5­âTkz˜1ŒÜ+Ú†¼Ê¤\õ÷ ÈõpÈóÅdŠaI7A2-|Ä\nÿä`>ù€?ÚËä©Ùtæt†ÚðÀø›°ènØ\~=!… —ågbs¢Sq˜hTÏz­tÑSžeþLþ/„Æ·_)õ–ˆç)Ó£n½9\°@ ýÜïM0LÉ{žƒì®ò&*ÎK«žCÌèx9ú£ÀÅÍ‹ÝÚå*Ov¥°súø{’h.Vï©5ê±z®¨nò»V-è·ZÓUNõu dŽRmϵžri—´ù“Õ¿öXQê^NÓ:Ë66YÓ,Ε©ðÖî¯ ¥ fÍ’ÙTm2 wæãÅÛÉL>6çì-·8A¨ì·¿ÿJmS•–ÜòY­Zï‚óéà%¸Â#éð}6øá_ŒxI-Nq¨M\‰³Î8•åzLŒ{Ü®w§ÈG>â’K<á(¯¸Ê/þò–§œå<¹Ì¡ÌðþÇüæ`³ùô:Îs#[ç4×[Žž%Ÿïè=!ÒeÂô+=èüù£NuY×ëY7vb¡Ãõ®Ïr—S{Î]Dz›]è—ÖãÎ×.p«îVöõ½çNw­“ýíy·ºÝ«ö®þÇ|ï{±ÿÎq¼~ì‰.ü⇎v·ýñUg;ÑÏNy.Oþî\¸ç?újÄ=¬£¿¼ßí øÒ_]õ3Â7çëýõݸ>õú–1ëm_û´×žÃ ”Z\nOcâJ™zŽ©¨å#ïkTÆÌÎ}ì·Z|Áw 5ЧØvÇð¾3¤ç97Ë}R;$»bŽX¥z)À~<ÏïƒIo‡mþª”·Í>)¹k&ü='ØN,ÿ6QYÂGh%\ÄÂWBf]ÛÑ~Å €Úò^_–+xZeF'Éd€Æ=ØB ‘]ˆ€ûÑ]%ThÕ€"b¸kU‘Å3¯(=c8·i–%+ÏŒ.%Òk‡¥]£¼…Z~F]›¶«èÄj£}ШZóè:J&`Dl,ø‹QƒeT²[1Øh¾Å- …ô¨ö¸Ò¶~©h\&hk¦¦cCml i—H‡&y3Wðø[ÉÅph‡yt&jVƒÅÆh; y$·Ž}–iFfeØXAS] V+ Eþ6'5?2iÞç郤Øs‘¸cdèmú5çä_œ…aÖˆ*؇Ä8á×WŒ\ç¡~¡Å: õfÇØRYÄ‹ëàXáŒk¥yîçŠ ™á%D XÂ0|xÉ*›Ø {6vƒ‡5ׇù–“tG˜zÈmS‹¾sH:ÖU‰H—‹ùz€©Mu6™wsd •™ô˜ŠQk´M÷™—•d•G[§hÇâe‡#Œ’R~ëWnÊbѨ–íHV·é’›sš€ái§æ›wŽ †Ž§EŽÿ¤|€ö“‡&6Y“ש™´×˜…ÉR{“kiʹ)KVi6xi[Åu“ˆU^ˆœþèå‚Hj$ ZÛH®lmçS¯ÖO.Éž˜9ˆœ©b$¹@ò©kyQ—x7ÒEücòø–Ž—HÉ–m IélÆmnéxŽj£Öf[ˆ&ˆr¡—05ÞF•àf[(:çVŒÝŒíV~Ænd –YXwÿ©TÙ‰rÅ9@ŠT‰™4üzGФIZDz ƒGuNZ¤ ˆPÚ¤ŠgxTjX*sZ vVÚw\*{^šw` ™RšydŠšbê˜j*ufJyhjœlºvp¤rjvtšxªpz:|*Uv #~*›n*g„ºx‚ªˆÚx›§% ˆ­y†Œé¨ê£&g¨W þ¨Áw©_š©„Ǩ”zxaÉTÊ€Ô—d´©r—ª0E|œ ¤¥ŸÚ…®º ŠJ¶Z$·¸›ÿU•é§}Š#–à‰°Z¥«ê Ö¢¨ø”×â-ºÙ)ÆŠ3ĺšÏ¥€U÷#ø( ¸šVÐÚ#J¸ŸÞ9‹ÂÊèsªyzš®&_£dÊ…Ö£ªÀ­HQ¯­”Ú?Ë*ŽîÒJ÷Z˜`æ§¢S1áÖY»y ¯ê­ °z"ª~ù°š*« ºžçÚ­{ °±“*©ëбêT;²$Úž›u›t*û¤¦.{‡0[¦&{², u4ëq8«ˆ:›q<Ë@þ»o2[¬6;²BkH«®j¢L{²˜©±öê³§´ ¡ JеY«µÔ0µyú´}´¨_›|{'¶c¶eëFd‹¶i{¶kjë¶oÛ¶q»šsK·w™²w‹Gv«·¬©IQ‹©pÛ·Í(¸ƒë·=j¸xû·…¸µë¸K]Û_K¹‘K´7G§Î:„¸ ³ãrœ›¸$ËçºU«˜F[$Ëwº’[pdjj­{¹[ú¹Ù}æå´[º~(²D(ï:šÓÕª]+º£ µ=Âk ׋Ã;»O²n ¥<¶d´ØfxnlF–¼‰_]Ù6»²¹ë"²(ûÕ Hx‚Dø%xÆþÞ»™½›«›GŸ)Y¾F4^/Y7ìÛ¨î»Lš¼Æå¡d&6øjÜ»¿Íû£rÊ{}¹¯óÛ'ö£‘„¿|¨ºˆ›žÓ¡Ó©¯)Ĕ.ÑR¼ÆÛ¿‘ŠcÓ»a3Ê85ÊŸbY°žUSô´¾FZ¹1,Ã>¡mܹФ£Z©¦•PñÁÏÛr5Æ 7|9üsÉöš·jÄKgX¼žˆ±ÄºÃΫ7&&˜j1S{ˉºTNÂQ!E¸Ì› DìGåÅ_œ aÜ€gL«ãTiªÝ‹'_£“ë~­r›cÆÂfè«Ù‹›Áª­x5År<DZ¦“Í鄃6±Žð~á(¢}³h ÄþÁ‡iT•jÈà›?(é¿HvŸ^‘Qåå”@8žD<dÆtÀ$™  ˆìÉ×èŸÔ˜Ê)t¢’ln:ú8þ¡”qU®4Ëk¼ä«Žù‚ò ?K¹%+ÈgÜ[ÅܰÆÌÇô±—c 8MÉJÊÆÎ·Á?˜jAxCè¯ÒGºGé–ƒs–iæ=•Sffüüè›)ó¢8´nXȰæ×Ââ‚õU·gÅ‚ôËoÅûl¯ýü6§±NÿlÅLھNj»Z<Ð ¿ =Ǿ+»Á|§ÓÂÊ8÷Ð+™Ñ}<„X£¿3¸Ž_wµ¸ùf–9‰g)‘*³¢“1“» WÜÎL+‰+J‰¥C]‹ÕÑ¥þ)my¾¢¶Í¡+ÌÙSMؽ ˜žB7È®ù±µÜÈU¼M´EÈ쀪.÷Ą˚:~6¾P ©ß7bՋǃ…‹uÜÓ¬ ’k-ÕÓDÕ¬Ëì÷¿¥ žÜeæyW_©Ëްó¿NgC°,²ðnMÆ(¨QÞÜÌÜxÍ×´²Ç^MÁãìwíØ Z×Õƒ:­¸¡zŇK›å¢°íü_§½Ì0 Ñ©™zEÔ™ŸýÕÿÊŽ«¸lþ ÜSבYÖì̽[£½“Ú«žók/NèÙÔlu¡]Î⃭gèÛ¶k×B‰¡èkÕ í|Ï©*̨=Žé•ÝÍíÜþlǺiPÒÑ5†œÛÞ’ œ™ß øW¼*Ó!èÇ(m• •Ü÷_G²Âј—¢H‘âà ¶zé#UJ ÑÔ'B3LÃ%r2ES™®,5ÐffÞ3w:£Üàþà–ðá‰mÁèù>Å31\•6ê]Ñ–½LN‡qˆÍB¶2•!Ͷ‘¼7âB&}£äDg%¤›.}S3ÙÒ6ýÒ­àKpvc=Œ®xf9⚬ ¬Æ¸HÛc%¼A튡«ãŽw“šQöÙFYå"›Ä¦ÉÃ@ݪ× ÚÌÙ:MÒ(œÌ”]Ù`­båx»Ÿ%Ï\NѬÎÖ«¡>.f±R¼‰‘I^þeƒ=ÁW|s¢u.¿ÕÆÙx.„›žÔÚ<‘á$ž²…×G”D Þ“EÁi¾#о”¼é=é½§[µm× ©×C“cÛwmªŠæŽâêÌ䚀£îêTž­ÝêªÖåê¼~ú%H£šm–Ïèë€~ݺVŸ” êï™Ùñ‰çÓ-:‚uÌÍé–öÉá*ƒ‰âŸÉçOìÐ½ÅØÔ~ÊÙ"ëÃ.„èøîáMãuI àN“õë—>t%IšTö ˜Ó9Ñ PóŽê™ŽìÂ-Ÿzæê_-Ñ”Îð ,æÌ ¯Õ¦ì ÿkÓë¨>Ô§žê*Îã¢m•—ÓÞ{Âè|Á…Ë:úm4_Ï­þ™#t°ôœÎÿËš‹Œ®f…æÕß…®Î7ŠC9šóª“ñ™Iâ-Þaˆ ò³NÌmÑø· $äºQô–Üš[£$áeoöPâ[>l©V“üÜõƒêöþUl¿rpÎòG#ä!•$KþèS‰°éüÒ7ÏäðÌísÿxЮóÍ)ò}ϯÏvòOæý÷鈨]O3)~ÈìØMŽ›Ž\n f÷…«öŸšÿÌ«ýhóÂɪîT/žîä¥Ï·ðŽúµ¾Ø·.(®ÿ¡‰jî»×¾Å–¸ÆïÓ"iaÓŽ‚¾/øy½ë"®*¿‰3 Â^gáÙñ¤Ò¿/QÁŸÈ’ÛþÖý<Šªµýö^êUÜ»LùÖÝçš¼¶ŠäìœåÓ,ÃÔz¯_ˆ°¼J1ì`³ýƒM{qÖ›wÿÁPÉr«4Ô\-•}áX¾¤t¾ñ\ßù>â\¾OPX4²jâ‘Ùt>¡%%j.°YdV[ %1Sï˜\6OÄŽ´w}vÏÀ4 —^·ßñyýžß÷ÿ ÷€ß~wâZ#%%Û +'5O2;7?A«¢ )ÁG%Ê»±žD†Ò žŒÖ ^»Šbº€ø5ñ©&#yÊJ²ˆI—˜R^¤É+—̘·švÜÇ4I¾•9Wzãè´'±J‰ôéïM²{ cÎ{‰¶Í›l·Á¤¨ÓhPsQs*À»Ó•³YPÁ  cX3u £ vî%vh 'îööZ6mñZÎÙzÔ#·z-/“=…ÙóglQ —A ¹ìËZ^¡¦°T/­ª)pÙn{4ÕÓy5í:¼õ¢é–+Waj7«>wŽ/þk©jkæÕÞ ûìöØrg< tãg†’‡R=:×îYÝžG®èñòÀÕG1Ÿ}Q;[ê†=ùì¢!4ÓH#5kêÇ;‹òSm³‹”ùãÌ@]~S ?üfË ŸSöš¥C-dcBÉJQ #£ÐE*Ò›q…ýb,ÏFJp¬qÇYѺþbaŠÃߪÑ–\¸c%%ÔKJ)_±3áºRË1z<'8eÎËl&Ï*kO²jŽÛ¨A¦Ò Ëë¶Œó‰.#åÉSP¡Ð&3Ó!øPijÏ63dEH?åLôŠCõTñ;Áƒì•Ž“EB›‹ô»ŒD€G#áp„½$þmíM÷ˆôI©4s¤”OJ 5³>­ŠÕJÜu¢gt.P8£ó±TèKÕÉ€£M"°`ºuÈk{ë*&uÝðT µôÙH³ôuØ#ŠmËñ´u©7úŒ22Ùd Ó/½ÅöZNã…õ®ÀªZŠ}«\F¶oë½X s7ÝÒ„;@ Nè\…[)׈g;¼ª£<]Q†a…2\Sq«’_ÝÚêmÖÛ<êuIÁ`¦µ©Ý$kà€Õ¼Òát™Û¸¡MwF`Q•—à¡ç9¥yÚ*3ãž9NÎa¬¶Eºê«…vÔ꟔fhM^j¢WU¸ç­e$Úh¯øïF·þCñtbˆjš¿”ãø²²³;Øê®+D› ¹çiT— ÑÐñ}Íã÷µÆ¿'9ËGðÌ)æ¼óÏ1'Çsÿ*]mÓýþÔ SG­É™’ÍÙÓ<„<Ú°oGrr»]íÙ=ßœmN,NO1™»Мtͯ -kÔ©ÏØúÏç<ÒLãjìF„˜ÖîùÖ¼ôêÑ/:íéõÓ¾¹ñè¾ôûjãK8hç}îTø·›1k ÿô¯œù®N8Ëš(’â¼ä½gAÓ¦Æw¿Þç|¢†ÿ°(H(ï:>âÇHö§5+(%vdKL(Ðl‡Iÿ álöœ`$þ‚Oç ~¡‚âBÎ ö'ž5/~w Ó`ˆÃNä+ùŠÒ’ú‚BÀpfÊ2à_¢H ѤIX±¢CˆÀ‚Q8Q+bÇÖÔ½!!‰aÔ"©0†=¨°+,“ ŸR3kåo‚j4ž‰ØGÕýÄ5o„â!Ä8Ûï‰,œ"íJ“B J¯t¡#T¸HíMåR Íæç·á±0gÝÜV—¾Ë¹ñv“ºäÒ£ÉʬlT`ã!ƒå‹8ÂÎŽºû£iHHU’ƒ•:™%ðXµ)r ±ƒ•ÌZ(¯gKi˜ƒ_§?šÅ­˜Æ¤æ¸ˆx æñ]ßÛ«øHJS|ëþ¤—†)ƒ$öN†¢¢"”ZØ8!ÒŠ†ó‹$kÓEf1‘ìhc\çÂ’,ž éfC‘öÐkBÔ¡ ¥(ê$ ®‹Ö³r…ðèGAR‘Ž”¤%5%E™Ê¾ •+uiêàùRýµT¦+µ¦Fk:S”æT¦75Bè:Ož¦$*ñvzÔ‹ú´(J5_RTšâ4ª:fU‡ÉTbu’1äêFµê ÆS¨_ëTjÖ®^U­EkSÛ:&¨ÆutaíÁX³jWºL¯AÚ+ïnöWêõUxUeY¿eÏŠµ•°—l»¼:,ÅÊU­ÅaÓ‡ØÇö­m3égAZvv³¥²lþi/KZÔÊé´«•§j]«¥ÖÆV†°¥íŽf{[bÙV·.Êmo‘È[àFè·Ãõfd›Xá&w ËenjŠûܤbVºãˆnué™CìnéºÛ%`J½k¡î†—}Á$¯zÆ{ÞëQW½›H¯zßÛ^c±U¾Ák}¡ë\üjW¢õï`Ô¢ûAF ,Lä–7ÁÇ­fƒ)Q`ïvº6j`iá¿Sà Í.ƒ;üàû†X¬&ñ +ŒÔ‰‹½èCð‰9¼á ×0ƒ6h±iM ã3øÆ…µ“S_¬ãSB‹'Ò"A篃Fq0úèq¢‚¬ãbž+|á{ÏšgÇî.«;ò‡þc<ŸMÊœèrò˜çòdÖzùËêã¯(—ãH_–ÜÊmà—Ó(ÃxÊôÊ:él/AIJÝ󉧌e:¶SÌwD˜ýò\ÓC“˜•'ëËM>P."®„ûL–yËæ6»³¨’ufE=êòÆWÕo^o«w(ãhÂúµ)¦µ¬‡|ë´ÚZ×.u¯KÌk`“úÕº«læÊ¦šÖÝ4$%9…H_ÍŒËö°WVulÚVóï˜ kÛÍn?³±> É&~ùFÝ\æk¸[-Ñ->­‘OCgµ'hË€W¹×Æö¯•ýÝ}îQѸ̛¹KyBÓM:Äã¡? .•³oZÔš1Žýþýï\Ó—™åžð ™pXYùÛ$ax‡û ¾oiÑ›™?ö0ÎfüßÎŽ6â Ô?^5²ÓT2­âî~ãºäÞ=¹Šž_šcûè3Jºaš>ᨋ ™›zƒ¯®ñ0üÖY×z±qÝlx{£°È“‘ys®KgéÃκ´åXÛ`…”vñ`¬QLô¯g{Ä+ê¶cçŽw_ÜÕü;ÇG}u¸w®Š<×g“ܲ-ïNy%Ò],P¶äÜ!™ïa7³·yÁÀDsŽi¼Ÿ–íW7\b./<£%%+ùx}¿Š/8&c©4 ÚWž,(Èc72…guxÝOB=›3ët$½XþËØ;¸ùÖùà./m©ÐÜ׺Vü1«Þ0ÞsùB‹ZHê>ñ%1õôn;°ßÎþ@Gpjmò=ÝÌ©³j—ß‹®r{h¿¼ÙîÉeòi0ò…DªÎ‘š(Ù ’ v.Í;TA¡Þ¯×Pã2P¾6éÆ.ñ:jÀDpI°CëÛìøöξhúdiÑÄ § ±D>MðœÏÎ>î|ñhx …QʆyrÑþtÐ"oÍž‘Òj‘KeZ1œ­ÿ–qxš1Q@Ö eÔÁÒ$o‘ɶìÌ0q‘]êïœÎ·+ÃP±‹¹nâ éŠ kΟ! ‘û´Î =0N!rãÊP"Ò!­í'òF,2¹0þ:Ò¸>Cr¸FÒûþJ2 Sr W² [ò _2crg²kòo2]Ãy²'}ò','Kk7’Æ`(‹²ÆŽ2))M’)Â)U*­« ©²*÷ð*©Ã*µÒ+¸²+¡ñ+ÁòBÄr,Ý«,Ír¤²·Ö2-ËQÊÜòÚò¶æ2.OììR-Ñ2/=¬ù2¦*ò//¬!s05°0ç+0“í–r1së1#Ó&3U ³2-S11“³r39³1=S„4ó¨& 2ò2£ª4è«&sµZó/_s(Có3Qs6Û§3m3{p37¬6y³7Gó7w 4…“ª|³8ð8‘3ð‚s9‹a/Ó!Çv3:ýŠ8©³:•ó:cÐ:µs;!(Á3<Ås<}R ;xfsdump-3.1.6+nmu1/doc/directories.gif0000644000000000000000000000460512607344125014532 0ustar GIF87aâ_€ÿÿÿ,â_þŒ©Ëí£œ´Ú‹³Þ¼û†âH–扦êʶî ÇòL×öçúÎ÷þ ‡Ä¢±8j’S÷ 8•ÔªõŠÍþœÜèÁ ×Àb1Æl~xÓ ¶ö Ëçè;t·•?èN>ñG'8HXh¸±ö5…°¸¨H6•ÔåhÐÅÈÔ˜ÉÆõXI9i'Eé`éY*z*êy™È¹ú ªàú8zh{‹›k”È(+Uù,¬ ì;ü‹Y¬ÜØì øtzÜ» ¹ü{9<½}¨.>N>ÂKM\-|NfœþÝT|ŽžÝ­¦þ ÍŒŸÍ]ÏŸ¬œÀ úÉ÷Ϩ€ÖÜyk˜AÀy ùILÕ¢Dþ„ ÿ•‰e œÁ‘$K¢ØÎ¡Et)#Ê“p­%=áiDÈÑ™¿=ñLúü ´͈•q‹fÓÞ«‘dMºoÒ‡J±9šú«G©A»zýJ$­h©BB5ËìØ›÷¤–å*íÅH¬d}z[ªéš¦uÏ’• 6°àÁ„U>Œ8±âÅô;~ 9r¸²’+[¾Œ9³æÍœ;{þ :´èѤK›>:µêÕ¬[»~ ;¶ìÙ´kÛ¾;·îݼ{ûþ <¸ðáÄ‹?Ž<¹òåÌ›;»0ºôéÔ«[¿Ž=»öíÜ»{ÿ>¼øñäË›?>½úõìÛ»Oâ½üùôëÛ¿?¿þýüþûûÿ`urˆ$A‚[ÄQË- ºð ròpáB1 ƒ†UGöLj7˜¨G‡ z8ŠHˆh΄V¸H3Ø(Ž1èø‚Œ†ðÈŒ"TxªX"’Zø(TˆºHäŒJ.9eFJx%†N&%“Jd¹˜*ˆ™™(—^¦ rW”K˜yâ–[t § u¾¸bžINpTE ygrúàån‚¨çšS%)ýøYSŒ-ÚC¡úe£Ej*%ŸrÕ˜–Ò±(LBâ1*¥âÁi«†AA2Z U…¯öH)†t¶Šèž¾*+0³â3,·Yþà©a¤šë¦‰Rùl[é줭0m¥Ê{ìAÙ:û+´¦.E-U.]Û­„ÍB±ë·†k%¯$Ú×BlRöæ¤É>cºˆÈ{„¿K\¶ðjË/ _KpÁ «Ê¢8 ¯¤a»ƒ ¬»®F<Ùº9ÜÈ jÜkÆ»:ñ )׊ƒÈ¤¸ŒðÉ“œi‰+ãyà¶`ð×,nµ, 3Æ#sÙ/¬cœáÔŽL‚C§HsTyËÔÍñý|¢Å!ã[ª‚MééPï¬Ù8‘=®ÌÒ–É'8ö¾ý5[W·5Ogkƒæ«pÚ,çÈp˜‚_ªnÙ|®¸É0ÑÕ‰6ï þ¢å!yɬµ;zv„ê½¶Ú‡‡º³×=mƒ&WŠÄ ½{-µæ*õâ»÷\¥»åªÌÎ3ëÇ^ùäõê.çn?3u3 aÕçÝú.‰š÷þqÍX¥•‰ñ¦ºÎû]¹[ÍÔí§Ÿ}ÈI7žP;Ù)xò½,:T§‡ÿ½úOU,Þ§» üøËO·xé¯iüû¨²&´R$c;WõÒÀ:¢DJyƒ;3؇õYÃtt[`Ñ7@ð#š³øèn΄”àór@ ²ð]ósáJæV.ö -6¤_úZ¼oJÉ\ûB‡¹qP{? ÊÐGÀ N"†rƒ¢þ¥˜bމQ´Ë·â<'Î̇ÝÛŸJøÂq™q‡Th®PFê‘g¤b?÷‘ ê’Q;œÖø(“M¨ Tå _G£TksÍ##Ÿ©9¿YÑ\ù³‹5'÷=lF.ouü%ÏØFG_vÏ‹ª+ç0ÁW·«xshi2ç6™˜ÎëÉ“œ±Ã^¡p¹Kïe4ˆd ,áúª+©¾í±~9+gƒ‡¹`¦›ý,,Xé©Ñ”³¦%FhSëØÎÖ¥µµëQ‰¹ÊÜÂnX”)ÏÑÙ÷´q=Lyþú[ª(s·ðèí º\hR–·,S¢n¥Ë\®8WÓZ¦§ÛÜê>,º9&ò¨wÊïª7+áýê`µDÒeù.k[ŸVê1ªôâ·¾VI&e= Xÿƒç}o€û;`äø­c¬¬õæyL±TŽ÷å «%®éá¯7‘§:ãrÞ/º—»G‘p1,býÎÏÃf‡„·¨=¯%Â)†ñm É—xw†uðå>܈ok˜­˜fcL:cÞÇ}e’uËçŠÑ!÷µÉ…™ GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. ---------------------------------------------------------------------- xfsdump-3.1.6+nmu1/doc/INSTALL0000644000000000000000000000275012607344125012557 0ustar This document describes how to configure and build the open source XFS commands and utilites ("xfsdump") from source, and how to install and run them. 0. If you have the binary rpm, simply install it and skip to step 2 (below). The rpm command to do this is: # rpm -Uvh xfsdump The Debian command to do this is: # dpkg -i xfsdump or, if you have apt configured (don't need the binary package): # apt-get install xfsdump 1. Configure, build and install the package The xfsdump package uses autoconf/configure and expects a GNU build environment (your platform must at least have both autoconf and gmake). You will also need to have installed either the e2fsprogs-devel package (on an RPM based system) or the uuid-dev package (on a Debian system) as some of the commands make use of the UUID library provided by these. To build the package and install it manually, use the following steps: # make # su root # make install [and optionally, for the development libraries and headers] # make install-dev Note that there are so many "install" variants out there that we wrote our own script (see "install-sh" in the top level directory). If you wish to turn off debugging asserts in the command build and turn on the optimizer then set the shell environment variables: OPTIMIZER=-O1 DEBUG=-DNDEBUG before running make or Makepkgs. 2. How to Contribute See the README file in this directory for details about how to contribute to the XFS project. xfsdump-3.1.6+nmu1/doc/global_hdr.obj0000644000000000000000000000670412607344125014322 0ustar %TGIF 4.1.16 state(0,37,100.000,0,0,0,16,1,9,1,1,0,0,1,0,1,0,'Courier',0,80640,0,0,0,10,0,0,0,1,0,16,0,0,1,1,1,1,1088,1408,1,0,2880,0). % % @(#)$Header: /home/cattelan/osspush/CVSROOT/xfs-cmds/xfsdump/doc/global_hdr.obj,v 1.1 2001/12/18 01:56:03 tes Exp $ % %W% % unit("1 pixel/pixel"). color_info(11,65535,0,[ "magenta", 65535, 0, 65535, 65535, 0, 65535, 1, "red", 65535, 0, 0, 65535, 0, 0, 1, "green", 0, 65535, 0, 0, 65535, 0, 1, "blue", 0, 0, 65535, 0, 0, 65535, 1, "yellow", 65535, 65535, 0, 65535, 65535, 0, 1, "pink", 65535, 40606, 44461, 65535, 40606, 44461, 1, "cyan", 0, 65535, 65535, 0, 65535, 65535, 1, "CadetBlue", 12336, 29041, 29812, 12336, 29041, 29812, 1, "white", 65535, 65535, 65535, 65535, 65535, 65535, 1, "black", 0, 0, 0, 0, 0, 0, 1, "DarkSlateGray", 3598, 8995, 8995, 3598, 8995, 8995, 1 ]). script_frac("0.6"). fg_bg_colors('black','white'). page(1,"",1,''). box('black','',64,32,176,128,0,1,1,0,0,0,0,0,0,'1',0,[ ]). box('black','',64,224,176,416,0,1,1,2,0,0,0,0,0,'1',0,[ ]). box('black','',64,128,176,176,0,1,1,5,0,0,0,0,0,'1',0,[ ]). box('black','',64,176,176,224,0,1,1,8,0,0,0,0,0,'1',0,[ ]). text('black',80,36,5,0,1,72,76,9,12,4,0,0,0,0,2,72,76,0,0,"",0,0,0,0,48,'',[ minilines(72,76,0,0,0,0,0,[ mini_line(18,12,4,0,0,0,[ str_block(0,18,12,4,0,0,0,0,0,[ str_seg('black','Courier-Bold',1,80640,18,12,4,0,0,0,0,0,0,0, "1K")]) ]), mini_line(45,12,3,0,0,0,[ str_block(0,45,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,45,12,3,0,-1,0,0,0,0,0, "magic")]) ]), mini_line(63,12,3,0,0,0,[ str_block(0,63,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,63,12,3,0,-1,0,0,0,0,0, "version")]) ]), mini_line(72,12,3,0,0,0,[ str_block(0,72,12,3,0,0,0,0,0,[ str_seg('black','Courier',0,80640,72,12,3,0,0,0,0,0,0,0, "checksum")]) ]), mini_line(27,12,3,0,0,0,[ str_block(0,27,12,3,0,-4,0,0,0,[ str_seg('black','Courier',0,80640,27,12,3,0,-4,0,0,0,0,0, "...")]) ]) ])]). text('black',80,132,2,0,1,81,31,12,12,4,0,0,0,0,2,81,31,0,0,"",0,0,0,0,144,'',[ minilines(81,31,0,0,0,0,0,[ mini_line(27,12,4,0,0,0,[ str_block(0,27,12,4,0,-2,0,0,0,[ str_seg('black','Courier-Bold',1,80640,27,12,4,0,-2,0,0,0,0,0, "512")]) ]), mini_line(81,12,3,0,0,0,[ str_block(0,81,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,81,12,3,0,-1,0,0,0,0,0, "drive_hdr")]) ]) ])]). text('black',80,180,2,0,1,63,31,14,12,4,0,0,0,0,2,63,31,0,0,"",0,0,0,0,192,'',[ minilines(63,31,0,0,0,0,0,[ mini_line(27,12,4,0,0,0,[ str_block(0,27,12,4,0,-2,0,0,0,[ str_seg('black','Courier-Bold',1,80640,27,12,4,0,-2,0,0,0,0,0, "512")]) ]), mini_line(63,12,3,0,0,0,[ str_block(0,63,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,63,12,3,0,-1,0,0,0,0,0, "rec_hdr")]) ]) ])]). text('black',80,308,2,0,1,81,31,16,12,4,0,0,0,0,2,81,31,0,0,"",0,0,0,0,320,'',[ minilines(81,31,0,0,0,0,0,[ mini_line(18,12,4,0,0,0,[ str_block(0,18,12,4,0,0,0,0,0,[ str_seg('black','Courier-Bold',1,80640,18,12,4,0,0,0,0,0,0,0, "2K")]) ]), mini_line(81,12,3,0,0,0,[ str_block(0,81,12,3,0,-1,0,0,0,[ str_seg('black','Courier',0,80640,81,12,3,0,-1,0,0,0,0,0, "media_hdr")]) ]) ])]). text('black',64,4,1,0,1,162,16,21,12,3,0,0,0,0,2,162,16,0,0,"",0,0,0,0,16,'',[ minilines(162,16,0,0,0,0,0,[ mini_line(162,12,4,0,0,0,[ str_block(0,135,12,3,0,-3,0,0,0,[ str_seg('black','Courier',0,80640,135,12,3,0,-3,0,0,0,0,0, "Global Header (")]), str_block(0,18,12,4,0,0,0,0,0,[ str_seg('black','Courier-Bold',1,80640,18,12,4,0,0,0,0,0,0,0, "4K")]), str_block(0,9,12,3,0,-4,0,0,0,[ str_seg('black','Courier',0,80640,9,12,3,0,-4,0,0,0,0,0, ")")]) ]) ])]). xfsdump-3.1.6+nmu1/.gitcensus0000644000000000000000000000616712620476225012776 0ustar .gitignore Makefile README VERSION common/Makefile common/arch_xlate.c common/arch_xlate.h common/cldmgr.c common/cldmgr.h common/cleanup.c common/cleanup.h common/content.h common/content_common.c common/content_common.h common/content_inode.h common/dlog.c common/dlog.h common/drive.c common/drive.h common/drive_minrmt.c common/drive_scsitape.c common/drive_simple.c common/exit.h common/fs.c common/fs.h common/getdents.c common/getdents.h common/global.c common/global.h common/hsmapi.c common/hsmapi.h common/inventory.c common/inventory.h common/lock.c common/lock.h common/main.c common/media.c common/media.h common/media_rmvtape.h common/mlog.c common/mlog.h common/openutil.c common/openutil.h common/path.c common/path.h common/qlock.c common/qlock.h common/rec_hdr.h common/ring.c common/ring.h common/stream.c common/stream.h common/timeutil.c common/timeutil.h common/ts_mtio.h common/types.h common/util.c common/util.h configure.ac debian/Makefile debian/changelog debian/compat debian/control debian/copyright debian/rules debian/shlibs.local debian/watch doc/CHANGES doc/COPYING doc/INSTALL doc/Makefile doc/README.xfsdump doc/directories.gif doc/directories.obj doc/files.gif doc/files.obj doc/global_hdr.gif doc/global_hdr.obj doc/inode_map.gif doc/inode_map.obj doc/inventory.gif doc/inventory.obj doc/media_files.gif doc/media_files.obj doc/split_algorithm.gif doc/split_algorithm.obj doc/xfsdump.html doc/xfsdump_ts.txt dump/Makefile dump/content.c dump/getopt.h dump/inomap.c dump/inomap.h dump/var.c dump/var.h include/Makefile include/builddefs.in include/buildmacros include/buildrules include/config.h.in include/install-sh include/swab.h include/swap.h inventory/Makefile inventory/getopt.h inventory/inv_api.c inventory/inv_core.c inventory/inv_files.c inventory/inv_fstab.c inventory/inv_idx.c inventory/inv_mgr.c inventory/inv_oref.c inventory/inv_oref.h inventory/inv_priv.h inventory/inv_stobj.c inventory/inventory.h inventory/testmain.c invutil/Makefile invutil/cmenu.c invutil/cmenu.h invutil/fstab.c invutil/fstab.h invutil/getopt.h invutil/invidx.c invutil/invidx.h invutil/invutil.c invutil/invutil.h invutil/list.c invutil/list.h invutil/menu.c invutil/screen.c invutil/stobj.c invutil/stobj.h librmt/Makefile librmt/isrmt.c librmt/rmtabort.c librmt/rmtaccess.c librmt/rmtclose.c librmt/rmtcommand.c librmt/rmtcreat.c librmt/rmtdev.c librmt/rmtfstat.c librmt/rmtioctl.c librmt/rmtisatty.c librmt/rmtlib.h librmt/rmtlseek.c librmt/rmtmsg.c librmt/rmtopen.c librmt/rmtread.c librmt/rmtstatus.c librmt/rmtwrite.c m4/Makefile m4/manual_format.m4 m4/multilib.m4 m4/package_attrdev.m4 m4/package_globals.m4 m4/package_ncurses.m4 m4/package_pthread.m4 m4/package_utilies.m4 m4/package_uuiddev.m4 m4/package_xfslibs.m4 man/Makefile man/man8/Makefile man/man8/xfsdump.8 man/man8/xfsinvutil.8 man/man8/xfsrestore.8 po/Makefile po/de.po po/pl.po release.sh restore/Makefile restore/bag.c restore/bag.h restore/content.c restore/dirattr.c restore/dirattr.h restore/getopt.h restore/inomap.c restore/inomap.h restore/mmap.c restore/mmap.h restore/namreg.c restore/namreg.h restore/node.c restore/node.h restore/tree.c restore/tree.h restore/win.c restore/win.h xfsdump-3.1.6+nmu1/man/0000755000000000000000000000000012620476226011533 5ustar xfsdump-3.1.6+nmu1/man/man8/0000755000000000000000000000000012620476226012376 5ustar xfsdump-3.1.6+nmu1/man/man8/xfsdump.80000644000000000000000000006437012607344125014164 0ustar .TH xfsdump 8 .SH NAME xfsdump \- \&XFS filesystem incremental dump utility .SH SYNOPSIS .nf \f3xfsdump\f1 \-h \f3xfsdump\f1 [ options ] \-f \f2dest\f1 [ \-f \f2dest\f1 ... ] \f2filesystem\f1 \f3xfsdump\f1 [ options ] \- \f2filesystem\f1 \f3xfsdump\f1 \-I [ subopt=value ... ] .fi .\" .\" Macro EX: bold constant width example .de EX \" start bold constant width .in +.5i .ie t .ft CB .el .ft B .ie t .sp .5v .el .sp .ta \\w' 'u*8 .nf .. .de EE \" end bold constant width .fi .ie t .sp .5v .el .sp .ft R .in .. .SH DESCRIPTION .I xfsdump backs up files and their attributes in a filesystem. The files are dumped to storage media, a regular file, or standard output. Options allow the operator to have all files dumped, just files that have changed since a previous dump, or just files contained in a list of pathnames. .P The .IR xfsrestore (8) utility re-populates a filesystem with the contents of the dump. .P Each invocation of .I xfsdump dumps just one filesystem. That invocation is termed a dump session. The dump session splits the filesystem into one or more dump streams, one per destination. The split is done in filesystem inode number (ino) order, at boundaries selected to equalize the size of each stream. Furthermore, the breakpoints between streams may be in the middle of very large files (at extent boundaries) if necessary to achieve reasonable stream size equalization. Each dump stream can span several media objects, and a single media object can contain several dump streams. The typical media object is a tape cartridge. The media object records the dump stream as one or more media files. A media file is a self-contained partial dump, intended to minimize the impact of media dropouts on the entire dump stream at the expense of increasing the time required to complete the dump. By default only one media file is written unless a media file size is specified using the .B \-d option. Other techniques, such as making a second copy of the dump image, provide more protection against media failures than multiple media files will. .P .I xfsdump maintains an online dump inventory in \f2/var/lib/xfsdump/inventory\f1. The .B \-I option displays the inventory contents hierarchically. The levels of the hierarchy are: filesystem, dump session, stream, and media file. .P The options to .I xfsdump are: .TP 5 .B \-a Specifies that files for which the Data Migration Facility (DMF) has complete offline copies (dual-state files) be treated as if they were offline (OFL). This means that the file data will not be dumped by xfsdump, resulting in a smaller dump file. If the file is later restored the file data is still accessible through DMF. If both '\-a option' and '\-z option' are specified, the '\-a option' takes precedence (see '\-z option' below). .TP 5 \f3\-b\f1 \f2blocksize\f1 Specifies the blocksize, in bytes, to be used for the dump. The same blocksize must be specified to restore the tape. If the \f3\-m\f1 option is not used, then \f3\-b\f1 does not need to be specified. Instead, a default blocksize of 1Mb will be used. .TP 5 \f3\-c\f1 \f2progname\f1 Use the specified program to alert the operator when a media change is required. The alert program is typically a script to send a mail or flash a window to draw the operator's attention. .TP 5 \f3\-d\f1 \f2filesize\f1 Specifies the size, in megabytes, of dump media files. If not specified, xfsdump will dump data to tape using a single media file per media object. The specified media file size may need to be adjusted if, for example, xfsdump cannot fit a media file onto a single tape. .TP 5 \f3\-e\f1 Allow files to be excluded from the dump. This will cause xfsdump to skip files which have the "no dump" file attribute set. See the "Excluding individual files" section below for details on setting this file attribute. .TP 5 \f3\-f\f1 \f2dest\f1 [ \f3\-f\f1 \f2dest\f1 ... ] Specifies a dump destination. A dump destination can be the pathname of a device (such as a tape drive), a regular file or a remote tape drive (see \f2rmt\f1(8)). This option must be omitted if the standard output option (a lone .B \- preceding the source filesystem specification) is specified. .TP 5 \f3\-l\f1 \f2level\f1 Specifies a dump level of 0 to 9. The dump level determines the base dump to which this dump is relative. The base dump is the most recent dump at a lesser level. A level 0 dump is absolute \- all files are dumped. A dump level where 1 <= \f2level\f1 <= 9 is referred to as an incremental dump. Only files that have been changed since the base dump are dumped. Subtree dumps (see the .B \-s option below) cannot be used as the base for incremental dumps. .TP 5 .B \-m Use the minimal tape protocol for non-scsi tape destinations or remote tape destinations which are not scsi Linux tape drives nor IRIX tape drives. This option cannot be used without specifying a blocksize to be used (see .B \-b option above). .TP 5 .B \-o Overwrite the tape. With this option, .I xfsdump does not read the tape first to check the contents. This option may be used if .I xfsdump is unable to determine the block size of a tape . .TP 5 \f3\-p\f1 \f2interval\f1 Causes progress reports to be printed at the specified interval. .I interval is given in seconds. The progress report indicates how many files have been dumped, the total number of files to dump, the percentage of data dumped, and the elapsed time. .TP 5 \f3\-q\f1 Destination tape drive is a QIC tape. QIC tapes only use a 512 byte blocksize, for which \f2xfsdump\f1 must make special allowances. .TP 5 \f3\-s\f1 \f2pathname\f1 [ \f3\-s\f1 \f2pathname\f1 ... ] Restricts the dump to files contained in the specified pathnames (subtrees). A \f2pathname\f1 must be relative to the mount point of the filesystem. For example, if a filesystem is mounted at \f2/d2\f1, the \f2pathname\f1 argument for the directory \f2/d2/users\f1 is ``users''. A \f2pathname\f1 can be a file or a directory; if it is a directory, the entire hierarchy of files and subdirectories rooted at that directory is dumped. Subtree dumps cannot be used as the base for incremental dumps (see the .B \-l option above). .TP 5 \f3\-t\f1 \f2file\f1 Sets the dump time to the modification time of \f2file\f1 rather than using the current time. .I xfsdump uses the dump time to determine what files need to be backed up during an incremental dump. This option should be used when dumping snapshots so that the dump time matches the time the snapshot was taken. Otherwise files modified after a snapshot is taken may be skipped in the next incremental dump. .TP 5 \f3\-v\f1 \f2verbosity\f1 .PD 0 .TP 5 \f3\-v\f1 \f2subsys\f1=\f2verbosity\f1[,\f2subsys\f1=\f2verbosity\f1,...] .PD Specifies the level of detail used for messages displayed during the course of the dump. The \f2verbosity\f1 argument can be passed as either a string or an integer. If passed as a string the following values may be used: \f3silent\f1, \f3verbose\f1, \f3trace\f1, \f3debug\f1, or \f3nitty\f1. If passed as an integer, values from 0\-5 may be used. The values 0\-4 correspond to the strings already listed. The value 5 can be used to produce even more verbose debug output. The first form of this option activates message logging across all dump subsystems. The second form allows the message logging level to be controlled on a per-subsystem basis. The two forms can be combined (see the example below). The argument \f2subsys\f1 can take one of the following values: \f3general\f1, \f3proc\f1, \f3drive\f1, \f3media\f1, \f3inventory\f1, \f3inomap\f1 and \f3excluded_files\f1. For example, to dump the root filesystem with tracing activated for all subsystems: .EX # xfsdump \-v trace \-f /dev/tape / .EE To enable debug-level tracing for drive and media operations: .EX # xfsdump \-v drive=debug,media=debug \-f /dev/tape / .EE To enable tracing for all subsystems, and debug level tracing for drive operations only: .EX # xfsdump \-v trace,drive=debug \-f /dev/tape / .EE To list files that will be excluded from the dump: .EX # xfsdump \-e \-v excluded_files=debug \-f /dev/tape / .EE .TP 5 \f3\-z\f1 \f2size\f1 Specifies the maximum size, in kilobytes, of files to be included in the dump. Files over this size, will be excluded from the dump, except for DMF dual-state files when '\-a option' is specified (see '\-a option' above). When specified, '\-a option' takes precedence over '\-z option'. The size is an estimate based on the number of disk blocks actually used by the file, and so does not include holes. In other words, size refers to the amount of space the file would take in the resulting dump. On an interactive restore, the skipped file is visible with xfsrestore's 'ls' and while you can use the 'add' and 'extract' commands, nothing will be restored. .TP 5 .B \-A Do not dump extended file attributes. When dumping a filesystem managed within a DMF environment this option should not be used. DMF stores file migration status within extended attributes associated with each file. If these attributes are not preserved when the filesystem is restored, files that had been in migrated state will not be recallable by DMF. Note that dumps containing extended file attributes cannot be restored with older versions of \f2xfsrestore\f1(8). .TP 5 \f3\-B\f1 \f2session_id\f1 Specifies the ID of the dump session upon which this dump session is to be based. If this option is specified, the .B \-l (level) and .B \-R (resume) options are not allowed. Instead, .B xfsdump determines if the current dump session should be incremental and/or resumed, by looking at the base session's level and interrupted attributes. If the base session was interrupted, the current dump session is a resumption of that base at the same level. Otherwise, the current dump session is an incremental dump with a level one greater than that of the base session. This option allows incremental and resumed dumps to be based on any previous dump, rather than just the most recent. .TP 5 .B \-D Controls which directories are backed up during an incremental dump. By default unchanged directories are dumped if files or directories beneath them have changed. This results in a self-contained dump -- if a base dump is lost, or you know the file(s) you wish to restore is in an incremental dump, you can restore just that dump without loading the base dump(s) first. However, this method requires a potentially expensive traversal through the filesystem. When .B \-D is specified, unchanged directories are not dumped. This results in a faster dump, but files will end up in the .IR xfsrestore (8) .I orphanage directory unless the base dump(s) is loaded first. .TP 5 .B \-E Pre-erase media. If this option is specified, media is erased prior to use. The operator is prompted for confirmation, unless the .B \-F option is also specified. .TP 5 .B \-F Don't prompt the operator. When .I xfsdump encounters a media object containing non-xfsdump data, .I xfsdump normally asks the operator for permission to overwrite. With this option the overwrite is performed, no questions asked. When .I xfsdump encounters end-of-media during a dump, .I xfsdump normally asks the operator if another media object will be provided. With this option the dump is instead interrupted. .TP 5 .B \-I Displays the \f2xfsdump\f1 inventory (no dump is performed). .I xfsdump records each dump session in an online inventory in \f2/var/lib/xfsdump/inventory\f1. .I xfsdump uses this inventory to determine the base for incremental dumps. It is also useful for manually identifying a dump session to be restored. Suboptions to filter the inventory display are described later. .TP 5 .B \-J Inhibits the normal update of the inventory. This is useful when the media being dumped to will be discarded or overwritten. .TP 5 .B \-K Generate a format 2 dump instead of the current format. This is useful if the dump will be restored on a system with an older .I xfsrestore which does not understand the current dump format. Use of this option is otherwise not recommended. .TP 5 \f3\-L\f1 \f2session_label\f1 Specifies a label for the dump session. It can be any arbitrary string up to 255 characters long. .TP 5 \f3\-M\f1 \f2label\f1 [ \f3\-M\f1 \f2label\f1 ... ] Specifies a label for the first media object (for example, tape cartridge) written on the corresponding destination during the session. It can be any arbitrary string up to 255 characters long. Multiple media object labels can be specified, one for each destination. .TP 5 \f3\-O\f1 \f2options_file\f1 Insert the options contained in \f2options_file\f1 into the beginning of the command line. The options are specified just as they would appear if typed into the command line. In addition, newline characters (\en) can be used as whitespace. The options are placed before all options actually given on the command line, just after the command name. Only one \f3\-O\f1 option can be used. Recursive use is ignored. The source filesystem cannot be specified in \f2options_file\f1. .TP 5 .B \-R Resumes a previously interrupted dump session. If the most recent dump at this dump's level (\f3\-l\f1 option) was interrupted, this dump contains only files not in the interrupted dump and consistent with the incremental level. However, files contained in the interrupted dump that have been subsequently modified are re-dumped. .TP 5 .B \-T Inhibits interactive dialogue timeouts. When the .B \-F option is not specified, .I xfsdump prompts the operator for labels and media changes. Each dialogue normally times out if no response is supplied. This option prevents the timeout. .TP 5 \f3\-Y\f1 \f2length\f1 Specify I/O buffer ring length. .I xfsdump uses a ring of output buffers to achieve maximum throughput when dumping to tape drives. The default ring length is 3. However, this is not currently enabled on Linux yet, making this option benign. .TP 5 .B \- A lone .B \- causes the dump stream to be sent to the standard output, where it can be piped to another utility such as \f2xfsrestore\f1(8) or redirected to a file. This option cannot be used with the .B \-f option. The .B \- must follow all other options and precede the filesystem specification. .P The filesystem, \f2filesystem\f1, can be specified either as a mount point or as a special device file (for example, \f2/dev/dsk/dks0d1s0\f1). The filesystem must be mounted to be dumped. .SH NOTES .SS Dump Interruption A dump can be interrupted at any time and later resumed. To interrupt, type control-C (or the current terminal interrupt character). The operator is prompted to select one of several operations, including dump interruption. After the operator selects dump interruption, the dump continues until a convenient break point is encountered (typically the end of the current file). Very large files are broken into smaller subfiles, so the wait for the end of the current file is brief. .SS Dump Resumption A previously interrupted dump can be resumed by specifying the .B \-R option. If the most recent dump at the specified level was interrupted, the new dump does not include files already dumped, unless they have changed since the interrupted dump. .SS Media Management A single media object can contain many dump streams. Conversely, a single dump stream can span multiple media objects. If a dump stream is sent to a media object already containing one or more dumps, .I xfsdump appends the new dump stream after the last dump stream. Media files are never overwritten. If end-of-media is encountered during the course of a dump, the operator is prompted to insert a new media object into the drive. The dump stream continuation is appended after the last media file on the new media object. .SS Inventory Each dump session updates an inventory database in \f2/var/lib/xfsdump/inventory\f1. .I xfsdump uses the inventory to determine the base of incremental and resumed dumps. .P This database can be displayed by invoking .I xfsdump with the .B \-I option. The display uses tabbed indentation to present the inventory hierarchically. The first level is filesystem. The second level is session. The third level is media stream (currently only one stream is supported). The fourth level lists the media files sequentially composing the stream. .P The following suboptions are available to filter the display. .TP 5 \f3\-I depth=\f1\f2n\f1 (where .I n is 1, 2, or 3) limits the hierarchical depth of the display. When .I n is 1, only the filesystem information from the inventory is displayed. When .I n is 2, only filesystem and session information are displayed. When .I n is 3, only filesystem, session and stream information are displayed. .TP 5 \f3\-I level=\f1\f2n\f1 (where .I n is the dump level) limits the display to dumps of that particular dump level. .P The display may be restricted to media files contained in a specific media object. .TP 5 \f3\-I mobjid=\f1\f2value\f1 (where .I value is a media ID) specifies the media object by its media ID. .TP 5 \f3\-I mobjlabel=\f1\f2value\f1 (where .I value is a media label) specifies the media object by its media label. .P Similarly, the display can be restricted to a specific filesystem. .TP 5 \f3\-I mnt=\f1\f2mount_point\f1 (that is, [hostname:]pathname), identifies the filesystem by mountpoint. Specifying the hostname is optional, but may be useful in a clustered environment where more than one host can be responsible for dumping a filesystem. .TP 5 \f3\-I fsid=\f1\f2filesystem_id\f1 identifies the filesystem by filesystem ID. .TP 5 \f3\-I dev=\f1\f2device_pathname\f1 (that is, [hostname:]device_pathname) identifies the filesystem by device. As with the .B mnt filter, specifying the hostname is optional. .P More than one of these suboptions, separated by commas, may be specified at the same time to limit the display of the inventory to those dumps of interest. However, at most four suboptions can be specified at once: one to constrain the display hierarchy depth, one to constrain the dump level, one to constrain the media object, and one to constrain the filesystem. .P For example, .B \-I depth=1,mobjlabel="tape 1",mnt=host1:/test_mnt would display only the filesystem information (depth=1) for those filesystems that were mounted on \f2host1:/test_mnt\f1 at the time of the dump, and only those filesystems dumped to the media object labeled "tape 1". .P Dump records may be removed (pruned) from the inventory using the .I xfsinvutil program. .P An additional media file is placed at the end of each dump stream. This media file contains the inventory information for the current dump session. Its contents may be merged back into the online inventory database at a later time using .IR xfsrestore (1M). .P The inventory files stored in .I /var/lib/xfsdump are not included in the dump, even if that directory is contained within the filesystem being dumped. Including the inventory in the dump may lead to loss or corruption of data, should an older version be restored overwriting the current version. To backup the .I xfsdump inventory, the contents of .I /var/lib/xfsdump should be copied to another location which may then be safely dumped. Upon restoration, those files may be copied back into .IR /var/lib/xfsdump , overwriting whatever files may be there, or .IR xfsinvutil (1M) may be used to selectively merge parts of the restored inventory back into the current inventory. Prior to version 1.1.8, .I xfsdump would include the .I /var/lib/xfsdump directory in the dump. Care should be taken not to overwrite the .I /var/lib/xfsdump directory when restoring an old dump, by either restoring the filesystem to another location or by copying the current contents of .I /var/lib/xfsdump to a safe place prior to running .IR xfsrestore (1M). .P .SS Labels The operator can specify a label to identify the dump session and a label to identify a media object. The session label is placed in every media file produced in the course of the dump, and is recorded in the inventory. .P The media label is used to identify media objects, and is independent of the session label. Each media file on the media object contains a copy of the media label. An error is returned if the operator specifies a media label that does not match the media label on a media object containing valid media files. Media labels are recorded in the inventory. .SS UUIDs UUIDs (Universally Unique Identifiers) are used in three places: to identify the filesystem being dumped (using the filesystem UUID, see .IR xfs (5) for more details), to identify the dump session, and to identify each media object. The inventory display (\f3\-I\f1) includes all of these. .SS Dump Level Usage The dump level mechanism provides a structured form of incremental dumps. A dump of level \f2level\f1 includes only files that have changed since the most recent dump at a level less than \f2level\f1. For example, the operator can establish a dump schedule that involves a full dump every Friday and a daily incremental dump containing only files that have changed since the previous dump. In this case Friday's dump would be at level 0, Saturday's at level 1, Sunday's at level 2, and so on, up to the Thursday dump at level 6. .P The above schedule results in a very tedious restore procedure to fully reconstruct the Thursday version of the filesystem; \f2xfsrestore\f1 would need to be fed all 7 dumps in sequence. A compromise schedule is to use level 1 on Saturday, Monday, and Wednesday, and level 2 on Sunday, Tuesday, and Thursday. The Monday and Wednesday dumps would take longer, but the worst case restore requires the accumulation of just three dumps, one each at level 0, level 1, and level 2. .SS Quotas If the filesystem being dumped contains user quotas, .I xfsdump will use .IR xfs_quota (8) to store the quotas in a file called .I xfsdump_quotas in the root of the filesystem to be dumped. This file will then be included in the dump. Upon restoration, .I xfs_quota (8) can be used to reactivate the quotas for the filesystem. Note, however, that the .I xfsdump_quotas file will probably require modification to change the filesystem or UIDs if the filesystem has been restored to a different partition or system. Group and project quotas will be handled in a similar fashion and saved in files called .I xfsdump_quotas_group and .I xfsdump_quotas_proj , respectively. .SS Excluding individual files It may be desirable to exclude particular files or directories from the dump. The .B -s option can be used to limit the dump to a specified directory, and the .B -z option can be used to exclude files over a particular size. Additionally, when .I xfsdump is run with the .B -e option, files that are tagged with the "no dump" file attribute will not be included in the dump. The .IR chattr (1) command can be used to set this attribute on individual files or entire subtrees. To tag an individual file for exclusion from the dump: .EX $ chattr +d file .EE To tag all files in a subtree for exclusion from the dump: .EX $ chattr \-R +d directory .EE Note that any new files or directories created in a directory which has the "no dump" attribute set will automatically inherit this attribute. Also note that .I xfsdump does not check directories for the "no dump" attribute. .PP Care should be taken to note which files have been tagged. Under normal operation, .I xfsdump will only report the number of files it will skip. The .B "\-v excluded_files=debug" option, however, will cause .I xfsdump to list the inode numbers of the individual files affected. .SH EXAMPLES To perform a level 0, single stream dump of the root filesystem to a locally mounted tape drive, prompting for session and media labels when required: .EX # xfsdump \-f /dev/tape / .EE To specify session and media labels explicitly: .EX # xfsdump \-L session_1 \-M tape_0 \-f /dev/tape / .EE To perform a dump to a remote tape using the minimal rmt protocol and a set blocksize of 64k: .EX # xfsdump \-m \-b 65536 \-f otherhost:/dev/tape / .EE To perform a level 0, multi-stream dump to two locally mounted tape drives: .EX # xfsdump \-L session_2 \-f /dev/rmt/tps4d6v \-M tape_1 \e \-f /dev/rmt/tps5d6v \-M tape_2 / .EE To perform a level 1 dump relative to the last level 0 dump recorded in the inventory: .EX # xfsdump \-l 1 \-f /dev/tape / .EE To copy the contents of a filesystem to another directory (see \f2xfsrestore\f1(8)): .EX # xfsdump \-J \- / | xfsrestore \-J \- /new .EE .SH FILES .TP 25 /var/lib/xfsdump/inventory dump inventory database .SH SEE ALSO attr(1), rmt(8), xfsrestore(8), xfsinvutil(8), xfs_quota(8), attr_get(2). .SH DIAGNOSTICS The exit code is 0 on normal completion, non-zero if an error occurs or the dump is terminated by the operator. .P For all verbosity levels greater than 0 (\f3silent\f1) the final line of the output shows the exit status of the dump. It is of the form: .EX xfsdump: Dump Status: \f2code\f1 .EE Where \f2code\f1 takes one of the following values: \f3SUCCESS\f1 (normal completion), \f3INTERRUPT\f1 (interrupted), \f3QUIT\f1 (media no longer usable), \f3INCOMPLETE\f1 (dump incomplete), \f3FAULT\f1 (software error), and \f3ERROR\f1 (resource error). Every attempt will be made to keep both the syntax and the semantics of this log message unchanged in future versions of xfsdump. However, it may be necessary to refine or expand the set of exit codes, or their interpretation at some point in the future. .PP The message ``xfsdump: WARNING: unable to open directory: ino N: Invalid argument'' can occur with filesystems which are actively being modified while .I xfsdump is running. This can happen to either directory or regular file inodes \- affected files will not end up in the dump, files below affected directories will be placed in the .I orphanage directory by .IR xfsrestore . .SH BUGS .I xfsdump does not dump unmounted filesystems. .PP The dump frequency field of \f2/etc/fstab\f1 is not supported. .PP .I xfsdump uses the alert program only when a media change is required. .PP .I xfsdump requires root privilege (except for inventory display). .PP .I xfsdump can only dump XFS filesystems. .PP The media format used by \f2xfsdump\f1 can only be understood by \f2xfsrestore\f1. .PP \f2xfsdump\f1 does not know how to manage CD-ROM or other removable disk drives. .PP \f2xfsdump\f1 can become confused when doing incremental or resumed dumps if on the same machine you dump two XFS filesystems and both filesystems have the same filesystem identifier (UUID). Since \f2xfsdump\f1 uses the filesystem identifier to identify filesystems, \f2xfsdump\f1 maintains one combined set of dump inventories for both filesystems instead of two sets of dump inventories. This scenario can happen only if .I dd or some other block-by-block copy program was used to make a copy of an XFS filesystem. See .IR xfs_copy (8) and .IR xfs (5) for more details. xfsdump-3.1.6+nmu1/man/man8/Makefile0000644000000000000000000000060212607344125014031 0ustar # # Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = ../.. include $(TOPDIR)/include/builddefs MAN_SECTION = 8 MAN_PAGES = $(shell echo *.$(MAN_SECTION)) MAN_DEST = $(PKG_MAN_DIR)/man$(MAN_SECTION) LSRCFILES = $(MAN_PAGES) default : $(MAN_PAGES) include $(BUILDRULES) install : default $(INSTALL) -m 755 -d $(MAN_DEST) $(INSTALL_MAN) install-dev: xfsdump-3.1.6+nmu1/man/man8/xfsinvutil.80000644000000000000000000001233712607344125014705 0ustar .TH xfsinvutil 8 .SH NAME xfsinvutil \- \&xfsdump inventory database checking and pruning utility .SH SYNOPSIS .nf \f3xfsinvutil\f1 [\-F|\-i] [\-m \f2media_label\f1] \-M \f2mount_point\f1 \f2mm/dd/yyyy\f1 \f3xfsinvutil\f1 [\-F|\-i] [\-m \f2media_label\f1] \-u \f2UUID\f1 \f2mm/dd/yyyy\f1 \f3xfsinvutil\f1 [\-F] \-s \f2SESSION_ID\f1 \f3xfsinvutil\f1 \-i \f3xfsinvutil\f1 \-C .fi .SH DESCRIPTION .I xfsdump maintains an online dump inventory in \f2/var/lib/xfsdump/inventory\f1. The .B \-I option of xfsdump displays the inventory contents hierarchically. The levels of the hierarchy are: filesystem, dump session, stream, and media file. .P .I xfsinvutil is a utility to check this inventory database for consistency, to remove entries of dump sessions which may no longer be of relevance, and to browse the contents of the inventory. .P The following command line options are available: .TP 5 \f3\-F\f1 Don't prompt the operator. When .I xfsinvutil encounters a matching dump session, .I xfsinvutil will normally ask the operator for permission to delete the entry. With this option the deletion is performed, no questions asked. .TP 5 \f3\-i\f1 Interactive mode. Causes .I xfsinvutil to run in a mode that will allow the operator to browse and modify the contents of the inventory. Please refer to the .B "Interactive Mode" section below for more information. .TP 5 \f3\-M\f1 \f2mount_point mm/dd/yyyy\f1 Prunes dump sessions identified by the given mount point which were created prior to the specified date. Optionally \f3\-m\f1 may be be specified to further limit the matching dump sessions by media label. .I xfsinvutil will prompt the operator prior to pruning a dump session unless the \f3\-F\f1 or \f3\-i\f1 options are given. .TP 5 \f3\-u\f1 \f2UUID mm/dd/yyyy\f1 Like \f3\-M\f1, except the matching filesystem is specified using its universally unique identifier (UUID) instead of its mount point. .TP 5 \f3\-m\f1 \f2media_label\f1 If specified, only sessions with at least one media file whose label matches this value will be eligible for pruning. This restriction is in addition to those imposed by the date and the \f3\-M\f1 or \f3\-u\f1 options. This option allows the pruning of all inventory references to media which may have been overwritten or lost. Note that this option does not apply to sessions with no media files. .TP 5 \f3\-s\f1 \f2SESSION_ID\f1 Prunes the dump session identified by the given session id. .I xfsinvutil will prompt the operator prior to pruning a dump session unless the \f3\-F\f1 option is given. .TP 5 .B \-C With this option, .I xfsinvutil performs consistency checks for all entries in the inventory database. It fixes any problems found. If no consistent entries are found , the corresponding inventory database file is removed. .SS Interactive Mode When run with \f3-i\f1, .I xfsinvutil will present the operator with a hierarchical representation of the .I xfsdump inventory. In this mode, the operator can use the arrow keys (or the .B h .B j .B k .B l keys) to navigate the inventory and also use the following keys and functionality: .TP 5 \f3+\f1 Expand a branch of the tree. .TP 5 \f3-\f1 Collapse a branch of the tree. .TP 5 \f3*\f1 Fully expand a branch of the tree. .TP 5 \f3%\f1 Fully collapse a branch of the tree. .TP 5 \f3h\f1 Move selection to the parent entry. .TP 5 \f3l\f1 Move selection to the child entry. .TP 5 \f3j\f1 Move selection to next entry. .TP 5 \f3k\f1 Move selection to previous entry. .TP 5 \f3d\f1 Mark the current record, and all sub-records, to be deleted. .TP 5 \f3u\f1 Clear the current record and all parent records from being deleted. .TP 5 \f3i\f1 Import another .I xfsdump inventory. .TP 5 \f3?\f1 Show help window. .TP 5 \f3x\f1 Commit any changes made to the inventory, and exit the program. .TP 5 \f3q\f1 Exit the program without committing any changes to the inventory. .P Inventories from other hosts can be imported to create a larger common inventory. It is recommended that the contents of .I /var/lib/xfsdump/inventory on the remote host be copied to a temporary local directory prior to running .IR xfsinvutil . When .I xfsinvutil is run in interactive mode, and the operator hits .BR i , they will be prompted for the path to the inventory to be imported. .I xfsinvutil will then add the contents of the imported inventory to the main window, and all entries will be marked as imported. The operator can then delete any of these entries that are not to be imported. When the operator commits the changes, .I xfsinvutil will import any entries which were not marked as deleted. Deleted entries are not actually deleted from the original imported inventory. .SH NOTES .SS Inventory Each dump session updates an inventory database in \f2/var/lib/xfsdump/inventory\f1. .I xfsdump uses the inventory to determine the base of incremental and resumed dumps. .P This database can be displayed by invoking .I xfsdump with the .B \-I option. The display uses tabbed indentation to present the inventory hierarchically. The first level is filesystem. The second level is session. The third level is media stream (currently only one stream is supported). The fourth level lists the media files sequentially composing the stream. .SH FILES .TP 25 /var/lib/xfsdump/inventory dump inventory database .SH SEE ALSO xfsdump(8), xfsrestore(8). xfsdump-3.1.6+nmu1/man/man8/xfsrestore.80000644000000000000000000006135412607344125014701 0ustar .TH xfsrestore 8 .SH NAME xfsrestore \- \&XFS filesystem incremental restore utility .SH SYNOPSIS .nf \f3xfsrestore\f1 \-h \f3xfsrestore\f1 [ options ] \-f \f2source\f1 [ \-f \f2source\f1 ... ] \f2dest\f1 \f3xfsrestore\f1 [ options ] \- \f2dest\f1 \f3xfsrestore\f1 \-I [ subopt=value ... ] .fi .\" .\" Macro EX: bold constant width example .de EX \" start bold constant width .in +.5i .ie t .ft CB .el .ft B .ie t .sp .5v .el .sp .ta \\w' 'u*8 .nf .. .de EE \" end bold constant width .fi .ie t .sp .5v .el .sp .ft R .in .. .SH DESCRIPTION .I xfsrestore restores filesystems from dumps produced by \f2xfsdump\f1(8). Two modes of operation are available: simple and cumulative. .P The default is simple mode. .I xfsrestore populates the specified destination directory, \f2dest\f1, with the files contained in the dump media. .P The .B \-r option specifies the cumulative mode. Successive invocations of .I xfsrestore are used to apply a chronologically ordered sequence of delta dumps to a base (level 0) dump. The contents of the filesystem at the time each dump was produced is reproduced. This can involve adding, deleting, renaming, linking, and unlinking files and directories. .P A delta dump is defined as either an incremental dump (\f2xfsdump\f1 .B \-l option with level > 0) or a resumed dump (\f2xfsdump\f1 .B \-R option). The deltas must be applied in the order they were produced. Each delta applied must have been produced with the previously applied delta as its base. .P .I xfsrestore keeps state information in the .IR xfsrestorehousekeepingdir , to inform subsequent invocations when used in cumulative mode, or in the event a restore is interrupted. To ensure that the state information can be processed, a compatible version of .I xfsrestore must be used for each subsequent invocation. Additionally, each invocation must run on a system of the same endianness and page size. .P The options to .I xfsrestore are: .TP 5 \f3\-a\f1 \f2housekeeping\f1 Each invocation of \f2xfsrestore\f1 creates a directory called .IR xfsrestorehousekeepingdir . This directory is normally created directly under the \f2dest\f1 directory. The .B \-a option allows the operator to specify an alternate directory, \f2housekeeping\f1, in which .I xfsrestore creates the .I xfsrestorehousekeepingdir directory. When performing a cumulative (\f3\-r\f1 option) restore or resuming (\f3\-R\f1 option) a restore, each successive invocation must specify the same alternate directory. .TP 5 \f3\-b\f1 \f2blocksize\f1 Specifies the blocksize, in bytes, to be used for the restore. For other drives such as DAT or 8 mm , the same blocksize used for the xfsdump operation must be specified to restore the tape. The default block size is 1Mb. .TP 5 \f3\-c\f1 \f2progname\f1 Use the specified program to alert the operator when a media change is required. The alert program is typically a script to send a mail or flash a window to draw the operator's attention. .TP 5 \f3\-e\f1 Prevents .I xfsrestore from overwriting existing files in the \f2dest\f1 directory. .TP 5 \f3\-f\f1 \f2source\f1 [ \f3\-f\f1 \f2source\f1 ... ] Specifies a source of the dump to be restored. This can be the pathname of a device (such as a tape drive), a regular file or a remote tape drive (see \f2rmt\f1(8)). This option must be omitted if the standard input option (a lone .B \- preceding the \f2dest\f1 specification) is specified. .TP 5 .B \-i Selects interactive operation. Once the on-media directory hierarchy has been read, an interactive dialogue is begun. The operator uses a small set of commands to peruse the directory hierarchy, selecting files and subtrees for extraction. The available commands are given below. Initially nothing is selected, except for those subtrees specified with \f3\-s\f1 command line options. .RS .TP 15 \f3ls\f1 [\f2arg\f1] List the entries in the current directory or the specified directory, or the specified non-directory file entry. Both the entry's original inode number and name are displayed. Entries that are directories are appended with a `/'. Entries that have been selected for extraction are prepended with a `*'. .TP \f3cd\f1 [\f2arg\f1] Change the current working directory to the specified argument, or to the filesystem root directory if no argument is specified. .TP \f3pwd\f1 Print the pathname of the current directory, relative to the filesystem root. .TP \f3add\f1 [\f2arg\f1] The current directory or specified file or directory within the current directory is selected for extraction. If a directory is specified, then it and all its descendents are selected. Entries that are selected for extraction are prepended with a `*' when they are listed by .BR ls . .TP \f3delete\f1 [\f2arg\f1] The current directory or specified file or directory within the current directory is deselected for extraction. If a directory is specified, then it and all its descendents are deselected. The most expedient way to extract most of the files from a directory is to select the directory and then deselect those files that are not needed. .TP \f3extract\f1 Ends the interactive dialogue, and causes all selected subtrees to be restored. .TP \f3quit\f1 .I xfsrestore ends the interactive dialogue and immediately exits, even if there are files or subtrees selected for extraction. .TP \f3help\f1 List a summary of the available commands. .RE .TP 5 .B \-m Use the minimal tape protocol. This option cannot be used without specifying a blocksize to be used (see .B \-b option above). .TP 5 \f3\-n\f1 \f2file\f1 Allows .I xfsrestore to restore only files newer than \f2file\f1. The modification time of \f2file\f1 (i.e., as displayed with the \f3ls \-l\f1 command) is compared to the inode modification time of each file on the source media (i.e., as displayed with the \f3ls \-lc\f1 command). A file is restored from media only if its inode modification time is greater than or equal to the modification time of \f2file\f1. .TP 5 \f3\-o\f1 Restore file and directory owner/group even if not root. When run with an effective user id of root, .I xfsrestore restores owner and group of each file and directory. When run with any other effective user id it does not, unless this option is specified. .TP 5 \f3\-p\f1 \f2interval\f1 Causes progress reports to be printed at intervals of \f2interval\f1 seconds. The interval value is approximate, \f2xfsrestore\f1 will delay progress reports to avoid undue processing overhead. .TP 5 \f3\-q\f1 Source tape drive is a QIC tape. QIC tapes only use a 512 byte blocksize, for which \f2xfsrestore\f1 must make special allowances. .TP 5 \f3\-r\f1 Selects the cumulative mode of operation. The .B \-a and .I destination options must be the same for each invocation. .TP 5 \f3\-s\f1 \f2subtree\f1 Specifies a subtree to restore. Any number of .B \-s options are allowed. The restore is constrained to the union of all subtrees specified. Each subtree is specified as a pathname relative to the restore \f2dest\f1. If a directory is specified, the directory and all files beneath that directory are restored. .TP 5 .B \-t Displays the contents of the dump, but does not create or modify any files or directories. It may be desirable to set the verbosity level to \f3silent\f1 when using this option. .TP 5 \f3\-v\f1 \f2verbosity\f1 .\" set inter-paragraph distance to 0 .PD 0 .TP 5 \f3\-v\f1 \f2subsys\f1=\f2verbosity\f1[,\f2subsys\f1=\f2verbosity\f1,...] .PD Specifies the level of detail used for messages displayed during the course of the restore. The \f2verbosity\f1 argument can be passed as either a string or an integer. If passed as a string the following values may be used: \f3silent\f1, \f3verbose\f1, \f3trace\f1, \f3debug\f1, or \f3nitty\f1. If passed as an integer, values from 0\-5 may be used. The values 0\-4 correspond to the strings already listed. The value 5 can be used to produce even more verbose debug output. The first form of this option activates message logging across all restore subsystems. The second form allows the message logging level to be controlled on a per-subsystem basis. The two forms can be combined (see the example below). The argument \f2subsys\f1 can take one of the following values: \f3general\f1, \f3proc\f1, \f3drive\f1, \f3media\f1, \f3inventory\f1, and \f3tree\f1. .ne 2 For example, to restore the root filesystem with tracing activated for all subsystems: .EX # xfsrestore \-v trace \-f /dev/tape / .EE .ne 2 To enable debug-level tracing for drive and media operations: .EX # xfsrestore \-v drive=debug,media=debug \-f /dev/tape / .EE .ne 2 To enable tracing for all subsystems, and debug level tracing for drive operations only: .EX # xfsrestore \-v trace,drive=debug \-f /dev/tape / .EE .TP 5 .B \-A Do not restore extended file attributes. When restoring a filesystem managed within a DMF environment this option should not be used. DMF stores file migration status within extended attributes associated with each file. If these attributes are not preserved when the filesystem is restored, files that had been in migrated state will not be recallable by DMF. Note that dumping of extended file attributes is also optional. .TP 5 .B \-B Change the ownership and permissions of the destination directory to match those of the root directory of the dump. .TP 5 .B \-D Restore DMAPI (Data Management Application Programming Interface) event settings. If the restored filesystem will be managed within the same DMF environment as the original dump it is essential that the \-D option be used. Otherwise it is not usually desirable to restore these settings. .TP 5 .B \-E Prevents .I xfsrestore from overwriting newer versions of files. The inode modification time of the on-media file is compared to the inode modification time of corresponding file in the \f2dest\f1 directory. The file is restored only if the on-media version is newer than the version in the \f2dest\f1 directory. The inode modification time of a file can be displayed with the \f3ls \-lc\f1 command. .TP 5 .B \-F Inhibit interactive operator prompts. This option inhibits .I xfsrestore from prompting the operator for verification of the selected dump as the restore target and from prompting for any media change. .TP 5 .B \-I Causes the \f2xfsdump\f1 inventory to be displayed (no restore is performed). Each time \f2xfsdump\f1 is used, an online inventory in \f2/var/lib/xfsdump/inventory\f1 is updated. This is used to determine the base for incremental dumps. It is also useful for manually identifying a dump session to be restored (see the .B \-L and .B \-S options). Suboptions to filter the inventory display are described later. .TP 5 .B \-J Inhibits inventory update when on-media session inventory encountered during restore. .I xfsrestore opportunistically updates the online inventory when it encounters an on-media session inventory, but only if run with an effective user id of root and only if this option is not given. .TP 5 .B \-K Force .I xfsrestore to use dump format 2 generation numbers. Normally the need for this is determined automatically, but this option is required on the first .I xfsrestore invocation in the rare case that a cumulative restore begins with a format 3 (or newer) dump and will be followed by a format 2 dump. .TP 5 \f3\-L\f1 \f2session_label\f1 Specifies the label of the dump session to be restored. The source media is searched for this label. It is any arbitrary string up to 255 characters long. The label of the desired dump session can be copied from the inventory display produced by the .B \-I option. .TP 5 \f3\-O\f1 \f2options_file\f1 Insert the options contained in \f2options_file\f1 into the beginning of the command line. The options are specified just as they would appear if typed into the command line. In addition, newline characters (\\n) can be used as whitespace. The options are placed before all options actually given on the command line, just after the command name. Only one \f3\-O\f1 option can be used. Recursive use is ignored. The destination directory cannot be specified in \f2options_file\f1. .TP 5 .B \-Q Force completion of an interrupted restore session. This option is required to work around one specific pathological scenario. When restoring a dump session which was interrupted due to an EOM condition and no online session inventory is available, .I xfsrestore cannot know when the restore of that dump session is complete. The operator is forced to interrupt the restore session. In that case, if the operator tries to subsequently apply a resumed dump (using the \f3\-r\f1 option), .I xfsrestore refuses to do so. The operator must tell .I xfsrestore to consider the base restore complete by using this option when applying the resumed dump. .TP 5 .B \-R Resume a previously interrupted restore. .I xfsrestore can be interrupted at any time by pressing the terminal interrupt character (see \f2stty\f1(1)). Use this option to resume the restore. The .B \-a and .I destination options must be the same. .TP 5 \f3\-S\f1 \f2session_id\f1 Specifies the session UUID of the dump session to be restored. The source media is searched for this UUID. The UUID of the desired dump session can be copied from the inventory display produced by the .B \-I option. .TP 5 .B \-T Inhibits interactive dialogue timeouts. .I xfsrestore prompts the operator for media changes. This dialogue normally times out if no response is supplied. This option prevents the timeout. .TP 5 \f3\-X\f1 \f2subtree\f1 Specifies a subtree to exclude. This is the converse of the .B \-s option. Any number of .B \-X options are allowed. Each subtree is specified as a pathname relative to the restore \f2dest\f1. If a directory is specified, the directory and all files beneath that directory are excluded. .TP 5 \f3\-Y\f1 \f2io_ring_length\f1 Specify I/O buffer ring length. .I xfsrestore uses a ring of input buffers to achieve maximum throughput when restoring from tape drives. The default ring length is 3. However, this is not currently enabled on Linux yet, making this option benign. .TP 5 .B \- A lone .B \- causes the standard input to be read as the source of the dump to be restored. Standard input can be a pipe from another utility (such as \f2xfsdump\f1(8)) or a redirected file. This option cannot be used with the .B \-f option. The .B \- must follow all other options, and precede the \f2dest\f1 specification. .P The dumped filesystem is restored into the \f2dest\f1 directory. There is no default; the \f2dest\f1 must be specified. .SH NOTES .SS Cumulative Restoration A base (level 0) dump and an ordered set of delta dumps can be sequentially restored, each on top of the previous, to reproduce the contents of the original filesystem at the time the last delta was produced. The operator invokes .I xfsrestore once for each dump. The .B \-r option must be specified. The \f2dest\f1 directory must be the same for all invocations. Each invocation leaves a directory named .I xfsrestorehousekeeping in the \f2dest\f1 directory (however, see the .B \-a option above). This directory contains the state information that must be communicated between invocations. The operator must remove this directory after the last delta has been applied. .P .I xfsrestore also generates a directory named .I orphanage in the \f2dest\f1 directory. .I xfsrestore removes this directory after completing a simple restore. However, if .I orphanage is not empty, it is not removed. This can happen if files present on the dump media are not referenced by any of the restored directories. The .I orphanage has an entry for each such file. The entry name is the file's original inode number, a ".", and the file's generation count modulo 4096 (only the lower 12 bits of the generation count are used). .P .I xfsrestore does not remove the .I orphanage after cumulative restores. Like the .I xfsrestorehousekeeping directory, the operator must remove it after applying all delta dumps. .SS Media Management A dump consists of one or more media files contained on one or more media objects. A media file contains all or a portion of the filesystem dump. Large filesystems are broken up into multiple media files to minimize the impact of media dropouts, and to accommodate media object boundaries (end-of-media). .P A media object is any storage medium: a tape cartridge, a remote tape device (see \f2rmt\f1(8)), a regular file, or the standard input (currently other removable media drives are not supported). Tape cartridges can contain multiple media files, which are typically separated by (in tape parlance) file marks. If a dump spans multiple media objects, the restore must begin with the media object containing the first media file dumped. The operator is prompted when the next media object is needed. .P Media objects can contain more than one dump. The operator can select the desired dump by specifying the dump label .RB ( \-L option), or by specifying the dump UUID .RB ( \-S option). If neither is specified, \f2xfsrestore\f1 scans the entire media object, prompting the operator as each dump session is encountered. .P The inventory display .RB ( \-I option) is useful for identifying the media objects required. It is also useful for identifying a dump session. The session UUID can be copied from the inventory display to the \f3\-S\f1 option argument to unambiguously identify a dump session to be restored. .P Dumps placed in regular files or the standard output do not span multiple media objects, nor do they contain multiple dumps. .SS Inventory Each dump session updates an inventory database in \f2/var/lib/xfsdump/inventory\f1. This database can be displayed by invoking .I xfsrestore with the .B \-I option. The display uses tabbed indentation to present the inventory hierarchically. The first level is filesystem. The second level is session. The third level is media stream (currently only one stream is supported). The fourth level lists the media files sequentially composing the stream. .P The following suboptions are available to filter the display. .TP 5 \f3\-I depth=\f1\f2n\f1 (where .I n is 1, 2, or 3) limits the hierarchical depth of the display. When .I n is 1, only the filesystem information from the inventory is displayed. When .I n is 2, only filesystem and session information are displayed. When .I n is 3, only filesystem, session and stream information are displayed. .TP 5 \f3\-I level=\f1\f2n\f1 (where .I n is the dump level) limits the display to dumps of that particular dump level. .P The display may be restricted to media files contained in a specific media object. .TP 5 \f3\-I mobjid=\f1\f2value\f1 (where .I value is a media ID) specifies the media object by its media ID. .TP 5 \f3\-I mobjlabel=\f1\f2value\f1 (where .I value is a media label) specifies the media object by its media label. .P Similarly, the display can be restricted to a specific filesystem. .TP 5 \f3\-I mnt=\f1\f2mount_point\f1 (that is, [hostname:]pathname), identifies the filesystem by mountpoint. Specifying the hostname is optional, but may be useful in a clustered environment where more than one host can be responsible for dumping a filesystem. .TP 5 \f3\-I fsid=\f1\f2filesystem_id\f1 identifies the filesystem by filesystem ID. .TP 5 \f3\-I dev=\f1\f2device_pathname\f1 (that is, [hostname:]device_pathname) identifies the filesystem by device. As with the .B mnt filter, specifying the hostname is optional. .P More than one of these suboptions, separated by commas, may be specified at the same time to limit the display of the inventory to those dumps of interest. However, at most four suboptions can be specified at once: one to constrain the display hierarchy depth, one to constrain the dump level, one to constrain the media object, and one to constrain the filesystem. .P For example, .B \-I depth=1,mobjlabel="tape 1",mnt=host1:/test_mnt would display only the filesystem information (depth=1) for those filesystems that were mounted on \f2host1:/test_mnt\f1 at the time of the dump, and only those filesystems dumped to the media object labeled "tape 1". .P Dump records may be removed (pruned) from the inventory using the .I xfsinvutil program. .P An additional media file is placed at the end of each dump stream. This media file contains the inventory information for the current dump session. If the online inventory files in .I /var/lib/xfsdump/inventory are missing information for the current dump session, then the inventory information in the media file is automatically added to the files in .I /var/lib/xfsdump/inventory. If you wish to incorporate the inventory information from the media file without restoring any data, you may do so using the .B \-t option: .EX # xfsrestore \-t \-f /dev/tape .EE This is useful to rebuild the inventory database if it is ever lost or corrupted. The only caveat is that .I xfsrestore needs to read through the entire dump in order to reach the inventory media file. This could become time consuming for dump sessions with large media files. .SS Media Errors \f2xfsdump\f1 is tolerant of media errors, but cannot do error correction. If a media error occurs in the body of a media file, the filesystem file represented at that point is lost. The bad portion of the media is skipped, and the restoration resumes at the next filesystem file after the bad portion of the media. .P If a media error occurs in the beginning of the media file, the entire media file is lost. For this reason, large dumps are broken into a number of reasonably sized media files. The restore resumes with the next media file. .SS Quotas When .I xfsdump dumps a filesystem with user quotas, it creates a file in the root of the dump called .IR xfsdump_quotas . .I xfsrestore can restore this file like any other file included in the dump. This file can be processed by the restore command of .IR xfs_quota (8) to reactivate the quotas. However, the .I xfsdump_quotas file contains information which may first require modification; specifically the filesystem name and the user ids. If you are restoring the quotas for the same users on the same filesystem from which the dump was taken, then no modification will be necessary. However, if you are restoring the dump to a different filesystem, you will need to: .HP - ensure the new filesystem is mounted with the quota option .HP - modify the .I xfsdump_quotas file to contain the new filesystem name .HP - ensure the uids in the .I xfsdump_quotas file are correct .P Once the quota information has been verified, the restore command of .I xfs_quota (8) can be used to apply the quota limits to the filesystem. .P Group and project quotas are handled in a similar fashion and will be restored in files called .IR xfsdump_quotas_group and .IR xfsdump_quotas_proj , respectively. .SH EXAMPLES To restore the root filesystem from a locally mounted tape: .EX # xfsrestore \-f /dev/tape / .EE To restore from a remote tape, specifying the dump session id: .EX # xfsrestore \-L session_1 \-f otherhost:/dev/tape /new .EE To restore the contents a of a dump to another subdirectory: .EX # xfsrestore \-f /dev/tape /newdir .EE To copy the contents of a filesystem to another directory (see \f2xfsdump\f1(8)): .EX # xfsdump \-J \- / | xfsrestore \-J \- /new .EE .SH FILES .TP 25 /var/lib/xfsdump/inventory dump inventory database .SH SEE ALSO rmt(8), xfsdump(8), xfsinvutil(8), xfs_quota(8), attr_set(2). .SH DIAGNOSTICS The exit code is 0 on normal completion, and non-zero if an error occurred or the restore was terminated by the operator. .P For all verbosity levels greater than 0 (\f3silent\f1) the final line of the output shows the exit status of the restore. It is of the form: .EX xfsdump: Restore Status: \f2code\f1 .EE Where \f2code\f1 takes one of the following values: \f3SUCCESS\f1 (normal completion), \f3INTERRUPT\f1 (interrupted), \f3QUIT\f1 (media no longer usable), \f3INCOMPLETE\f1 (restore incomplete), \f3FAULT\f1 (software error), and \f3ERROR\f1 (resource error). Every attempt will be made to keep both the syntax and the semantics of this log message unchanged in future versions of xfsrestore. However, it may be necessary to refine or expand the set of exit codes, or their interpretation at some point in the future. .SH BUGS Pathnames of restored non-directory files (relative to the \f2dest\f1 directory) must be 1023 characters (MAXPATHLEN) or less. Longer pathnames are discarded and a warning message displayed. .P There is no verify option to \f2xfsrestore\f1. This would allow the operator to compare a filesystem dump to an existing filesystem, without actually doing a restore. .P The interactive commands (\f3\-i\f1 option) do not understand regular expressions. .P When the minimal rmt option is specified, \f2xfsrestore\f1 applies it to all remote tape sources. The same blocksize (specified by the .B \-b option) is used for all these remote drives. .P .I xfsrestore uses the alert program only when a media change is required. .P Cumulative mode (\f3\-r\f1 option) requires that the operator invoke .I xfsrestore for the base and for each delta to be applied in sequence to the base. It would be better to allow the operator to identify the last delta in the sequence of interest, and let .I xfsrestore work backwards from that delta to identify and apply the preceding deltas and base dump, all in one invocation. xfsdump-3.1.6+nmu1/man/Makefile0000644000000000000000000000054712607344125013176 0ustar # # Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = .. include $(TOPDIR)/include/builddefs SUBDIRS = man8 default : $(SUBDIRS) install : $(addsuffix -install,$(SUBDIRS)) install-dev : $(addsuffix -install-dev,$(SUBDIRS)) %-install: $(MAKE) -C $* install %-install-dev: $(MAKE) -C $* install-dev include $(BUILDRULES) xfsdump-3.1.6+nmu1/inventory/0000755000000000000000000000000012643557274013025 5ustar xfsdump-3.1.6+nmu1/inventory/inv_oref.c0000644000000000000000000002503312620476160014770 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include "config.h" #include "inv_priv.h" #include "inv_oref.h" /* * Resolve a stobj, invidx or fstab */ int oref_resolve_( invt_oref_t *obj, invt_objtype_t type) { int rval; type &= INVT_OTYPE_MASK; assert(type); assert(! OREF_ISRESOLVED(obj, INVT_OTYPE_MASK)); switch (type) { case INVT_OTYPE_INVIDX: rval = oref_resolve_invidx(obj); break; case INVT_OTYPE_STOBJ: rval = oref_resolve_stobj(obj); break; case INVT_OTYPE_FSTAB: rval = oref_resolve_fstab(obj); break; default: assert(0); break; } return rval; } /* * Resolve an object reference upto a specified point */ int oref_resolve_upto( invt_oref_t *obj, invt_objtype_t type) { int rval = INV_OK; assert (OREF_ISRESOLVED(obj, INVT_OTYPE_MASK)); assert (OREF_ISLOCKED(obj)); /* we arent interested in anything else */ type &= INVT_RES_MASK; assert(type); if (type >= INVT_RES_COUNTERS) { rval = oref_resolve_counters(obj); } if (type >= INVT_RES_ENTRIES && rval != INV_ERR) { rval = oref_resolve_entries(obj); } if (type >= INVT_RES_HDRS && rval != INV_ERR) { rval = oref_resolve_hdrs(obj); } if (type >= INVT_RES_SESSIONS && rval != INV_ERR) { rval = oref_resolve_sessions(obj); } if (type >= INVT_RES_STRMS && rval != INV_ERR) { rval = oref_resolve_strms(obj); } if (type >= INVT_RES_MFILES && rval != INV_ERR) { rval = oref_resolve_mfiles(obj); } return rval; } int oref_resolve_entries( invt_oref_t *obj) { if (OREF_ISRESOLVED(obj, INVT_RES_ENTRIES)) return INV_OK; assert(! OREF_ISRESOLVED(INVT_OTYPE_STOBJ)); if (OREF_ISRESOLVED(INVT_OTYPE_INVIDX)) { invt_entry_t *ent; assert(OREF_CNT_CURNUM(obj)); if (GET_ENTRIES(obj->fd, &ent, OREF_CNT_CURNUM(obj), sizeof(invt_entry_t)) < 0){ return INV_ERR; } obj->eu_ent = ent; } else { invt_fstab_t *ent; assert(OREF_CNT_CURNUM(obj)); if (GET_ENTRIES(obj->fd, &ent, OREF_CNT_CURNUM(obj), sizeof(invt_fstab_t)) < 0){ return INV_ERR; } obj->eu_fstabent = ent; } OREF_SET_TYPE(obj, INVT_RES_COUNTERS); return INV_OK; } int oref_resolve_counters( invt_oref_t *obj) { if (OREF_ISRESOLVED(obj, INVT_RES_COUNTERS)) return INV_OK; if (OREF_ISRESOLVED(INVT_OTYPE_STOBJ)) { invt_sescounter_t *sescnt; sescnt = calloc(1, sizeof(invt_sescounter_t)); if (GET_SESCOUNTERS(obj->fd, sescnt) < 0){ free(sescnt); return INV_ERR; } obj->cu_sescnt = sescnt; } else { invt_counter_t *cnt; cnt = calloc(1, sizeof(invt_counter_t)); if (GET_COUNTERS(obj->fd, cnt) < 0){ free(cnt); return INV_ERR; } obj->cu_cnt = cnt; } OREF_SET_TYPE(obj, INVT_RES_COUNTERS); return INV_OK; } int oref_sync( invt_oref_t *obj, invt_objtype_t type) { int rval; type &= INVT_RES_MASK; assert(type); assert(OREF_ISRESOLVED(obj, INVT_OTYPE_MASK)); assert(OREF_ISRESOLVED(obj, type)); assert(OREF_ISLOCKED(obj)); switch (type) { case INVT_RES_COUNTERS: rval = PUT_REC_NOLOCK(obj->fd, OREF_CNT(obj), sizeof(*OREF_CNT(obj)), (off64_t) 0); break; case INVT_RES_ENTRIES: assert(! OREF_ISRESOLVED(obj, INVT_OTYPE_STOBJ)); rval = PUT_REC_NOLOCK(obj->fd, OREF_ENTRIES(obj), sizeof(*OREF_ENTRIES(obj)), (off64_t) sizeof(*OREF_CNT(obj))); break; default: assert(0); break; } return rval; } int oref_sync_append( invt_oref_t *obj, invt_objtype_t type, void *entry, size_t entsz) { int rval; type &= INVT_RES_MASK; assert(type); assert(OREF_ISRESOLVED(obj, INVT_OTYPE_MASK)); assert(OREF_ISLOCKED(obj)); switch (type) { case INVT_RES_ENTRIES: assert(! OREF_ISRESOLVED(obj, INVT_OTYPE_STOBJ)); rval = PUT_REC_NOLOCK(obj->fd, entry, entsz, IDX_HDR_OFFSET(OREF_CNT_CURNUM(obj) - 1)); if (OREF_ISRESOLVED(obj, INVT_RES_ENTRIES)) free((oref)->eu_ent); OREF_UNSET_TYPE(obj, INVT_RES_ENTRIES); break; default: assert(0); break; } return rval; } void _oref_free( invt_oref_t *obj, bool_t freethis) { /* * Unlock the object *if* it is locked. * We dont want to actually close the fd because, * the tokens still need it. */ OREF_UNLOCK(obj); if (OREF_ISRESOLVED(obj, INVT_OTYPE_STOBJ) ){ if (OREF_ISRESOLVED(obj, INVT_RES_COUNTERS)) free((oref)->cu_sescnt); if (OREF_ISRESOLVED(obj, INVT_RES_HDRS)) free((oref)->eu_hdr); if (OREF_ISRESOLVED(obj, INVT_RES_SESSIONS)) free((oref)->eu_ses); if (OREF_ISRESOLVED(obj, INVT_RES_STRMS)) free((oref)->eu_strm); if (OREF_ISRESOLVED(obj, INVT_RES_MFILES)) free((oref)->eu_mfile); } else if (OREF_ISRESOLVED(obj, INVT_OTYPE_INVIDX)) { if (OREF_ISRESOLVED(obj, INVT_RES_COUNTERS)) free((oref)->cu_cnt); if (OREF_ISRESOLVED(obj, INVT_RES_ENTRIES)) free((oref)->eu_ent); } else if (OREF_ISRESOLVED(obj, INVT_OTYPE_FSTAB)) { if (OREF_ISRESOLVED(obj, INVT_RES_COUNTERS)) free((oref)->cu_cnt); if (OREF_ISRESOLVED(obj, INVT_RES_ENTRIES)) free((oref)->eu_fstabent); } OREF_INIT(obj); if (freethis) free(obj); } /* * Resolve the invidx and a suitable stobj. * Also resolves an idb_token as a side effect. */ int oref_resolve( invt_oref_t *invidx, inv_predicate_t bywhat, void *pred) { char fname[ INV_STRLEN ]; char uuname[ INV_STRLEN ]; int fd; invt_oref_t *stobj; int index; assert(! OREF_ISRESOLVED(invidx, INVT_OTYPE_MASK)); OREF_SET_TYPE(invidx, INVT_OTYPE_INVIDX); /* come up with the unique file suffix that refers to this filesystem */ if (fstab_get_fname(pred, uuname, bywhat) < 0) { return INV_ERR; } (void) strcpy(fname, uuname); strcat(fname, INV_INVINDEX_PREFIX); /* first check if the inv_index file exists: if not create it */ if ((fd = open(fname, O_RDWR)) == -1) { if (errno != ENOENT) { INV_PERROR (fname); return INV_ERR; } /* create the invidx */ return oref_resolve_new_invidx(invidx, fname); } invidx->fd = fd; OREF_LOCK(invidx, LOCK_EX); if (oref_resolve_child(invidx, &index) == INV_ERR) { OREF_UNLOCK(invidx); return INV_ERR; } stobj = OREF_CHILD(invidx); /* Now we need to make sure that this has enough space */ OREF_LOCK(stobj, LOCK_SH); if (oref_resolve_upto(stobj, INVT_RES_COUNTERS) == INV_ERR) { OREF_UNLOCK(stobj); OREF_UNLOCK(invidx); return INV_ERR; } /* create another storage object ( and, an inv_index entry for it too ) if we've filled this one up */ if (OREF_CNT_CURNUM(stobj) >= OREF_CNT_MAXNUM(stobj)) { int rval; #ifdef INVT_DEBUG mlog( MLOG_DEBUG | MLOG_INV, "$ INV: creating a new storage obj & " "index entry. \n" ); #endif /* Close(), Destroy() and mark unresolved */ OREF_UNRESOLVE_CHILD(invidx); rval = oref_resolve_new_stobj(invidx, BOOL_FALSE); /* rval = oref_idx_create_entry(invidx, BOOL_FALSE); */ OREF_UNLOCK(invidx); return rval; } OREF_UNLOCK(stobj); OREF_UNLOCK(invidx); tok = get_token(invidx->fd, stobj->fd); tok->d_invindex_off = IDX_HDR_OFFSET(index - 1); OREF_SET_TOKEN(tok); return INV_OK; } /* * Resolve the invidx entirely, and open the StObj. * Invidx is kept locked by caller */ int oref_resolve_child( invt_oref_t *invidx, int *index) { invt_entry_t *ent; assert(OREF_IS_LOCKED(invidx)); if (oref_resolve_upto(invidx, INVT_RES_ENTRIES) == INV_ERR) return INV_ERR; ent = OREF_ENTRIES(invidx); /* at this point we know that there should be at least one invindex entry present */ assert ( ent != NULL ); assert ( ent->ie_filename ); fd = open( ent->ie_filename, O_RDWR ); if ( fd < 0 ) { INV_PERROR( ent->ie_filename ); return INV_ERR; } stobj = calloc(1, sizeof(invt_oref_t)); OREF_SET_CHILD(invidx, stobj); stobj->fd = fd; return INV_OK; } /* used to be idx_create */ int oref_resolve_new_invidx( invt_oref_t *invidx, char *fname) { int stobjfd, fd; inv_idbtoken_t tok; if ((fd = open ( fname , O_RDWR | O_CREAT, S_IRUSR|S_IWUSR ) ) < 0 ) { INV_PERROR ( fname ); return INV_ERR; } invidx->fd = fd; OREF_LOCK(invidx, LOCK_EX); fchmod(fd, INV_PERMS); #ifdef INVT_DEBUG mlog( MLOG_NITTY | MLOG_INV, "creating InvIndex %s\n", fname); #endif /* create the new stobj as its first entry */ rval = oref_resolve_new_stobj(invidx, IS_EMPTY); OREF_UNLOCK(invidx); return rval; } /* formerly idx_create_entry() */ int oref_resolve_new_stobj( invt_oref_t *invidx, bool_t firstentry) { invt_entry_t ent; int fd; off64_t hoff; invt_oref_t *stobj; inv_idbtoken_t tok; assert(OREF_ISLOCKED(invidx)); memset ( &ent, 0, sizeof( ent ) ); stobj = calloc(1, sizeof(invt_oref_t)); OREF_SET_CHILD(invidx, stobj); /* initialize the start and end times to be the same */ ent.ie_timeperiod.tp_start = ent.ie_timeperiod.tp_end = (time32_t)0; stobj_makefname( ent.ie_filename ); if ( firstentry ) { invt_counter_t *cnt; cnt = malloc(sizeof(invt_counter_t)); cnt->ic_maxnum = INVT_MAX_INVINDICES; cnt->ic_curnum = 1; cnt->ic_vernum = INV_VERSION; fd = stobj_create( ent.ie_filename ); if ( fd < 0 ) { free(cnt); return INV_ERR; } stobj->fd = fd; OREF_SET_COUNTERS(invidx, cnt); OREF_SET_ENTRIES(invidx, &ent); if ((oref_sync(invidx, INVT_RES_COUNTERS) == INV_ERR) || (oref_sync(invidx, INVT_RES_ENTRIES) == INV_ERR)) return INV_ERR; } else { if (oref_resolve_upto(invidx, INVT_RES_COUNTERS) == INV_ERR) return INV_ERR; /* create the new storage object */ fd = stobj_create( ent.ie_filename ); if ( fd < 0 ) { return -1; } stobj->fd = fd; OREF_CNT_CURNUM(invidx)++; if ((oref_sync(invidx, INVT_RES_COUNTERS) == INV_ERR) || (oref_sync_append(invidx, INVT_RES_ENTRIES, &ent, sizeof(ent)) == INV_ERR)) return INV_ERR; } tok = get_token( invfd, fd ); tok->d_invindex_off = IDX_HDR_OFFSET(OREF_CNT_CURNUM(invidx) - 1); tok->d_update_flag |= NEW_INVINDEX; OREF_SET_TOKEN(invidx, tok); return INV_OK; } xfsdump-3.1.6+nmu1/inventory/inv_files.c0000644000000000000000000000567012620476160015144 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include "config.h" /*----------------------------------------------------------------------*/ /* */ /* Functions which access inventory paths: /var/[lib/]xfsdump/inventory */ /* The [lib] component was introduced for FHS compliance on Linux. */ /* */ /*----------------------------------------------------------------------*/ #define MGR_BASE_NEW "/var/lib/xfsdump" #define MGR_BASE_OLD "/var/xfsdump" #define MGR_DIRPATH "/inventory" /* preceed with inv_base */ #define MGR_FSTAB MGR_DIRPATH"/fstab" /* preceed with inv_base */ #define MGR_LOCKFILE MGR_DIRPATH"/invlock" /* preceed with inv_base */ #define MGR_PATH_MAX 64 /* PATH_MAX would be a tad wasteful here */ static char *inv_base; static char new_inv_base[] = MGR_BASE_NEW; static char old_inv_base[] = MGR_BASE_OLD; static char inv_fstabp[MGR_PATH_MAX]; static char inv_dirpathp[MGR_PATH_MAX]; static char inv_lockfilep[MGR_PATH_MAX]; char * inv_dirpath( void ) { assert(inv_base); return inv_dirpathp; } char * inv_fstab( void ) { assert(inv_base); return inv_fstabp; } char * inv_lockfile( void ) { assert(inv_base); return inv_lockfilep; } char * inv_basepath( void ) { assert(inv_base); return inv_base; } int inv_setup_base( void ) { struct stat64 new_sbuf, old_sbuf; int new_exists, old_exists; errno = 0; new_exists = !(stat64(new_inv_base, &new_sbuf) < 0 && errno == ENOENT); errno = 0; old_exists = !(stat64(old_inv_base, &old_sbuf) < 0 && errno == ENOENT); if (new_exists && old_exists) { if (new_sbuf.st_ino == old_sbuf.st_ino && new_sbuf.st_dev == old_sbuf.st_dev) { old_exists = 0; /* both the same, pretend */ } else { /* die! */ return 0; } } if (!old_exists) inv_base = new_inv_base; else inv_base = old_inv_base; /* also setup the dependent paths now */ strcpy(inv_dirpathp, inv_base); strcat(inv_dirpathp, MGR_DIRPATH); strcpy(inv_fstabp, inv_base); strcat(inv_fstabp, MGR_FSTAB); strcpy(inv_lockfilep, inv_base); strcat(inv_lockfilep, MGR_LOCKFILE); return 1; } xfsdump-3.1.6+nmu1/inventory/inventory.h0000644000000000000000000002337312620476160015230 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef INVENTORY_H #define INVENTORY_H #include "types.h" /* abstract interface to the inventory sub system of xfsdump * * the inventory contains a description of every xfsdump ever * done, unless explicitly deleted. It provides simple and specific * storage and query facilities. * * This was not an attempt to write a generic database. The inventory does have * knowledge of the functionalities, some abstractions, and even typical queries * of dump() and restore() and uses this knowledge in formulating its storage * structure on disk. All these things, of course, are completely abstract with * respect to the clients of the inventory. * */ #define INV_DIRPATH inv_dirpath() #define INV_TOKEN_NULL NULL #define INV_FSTAB inv_fstab() #define INV_INVINDEX_PREFIX ".InvIndex" #define INV_STOBJ_PREFIX ".StObj" /* length of labels, mntpts, etc */ #define INV_STRLEN GLOBAL_HDR_STRING_SZ typedef __uint32_t inv_version_t; /* This is the general inventory version. */ #define INV_VERSION (inv_version_t) 1 /* This is the version of the on-tape (packed) inventory. * version 2 has an extra inv_version_t in it to make everything * 64 bit aligned. */ #define PACKED_INV_VERSION_1 (inv_version_t) 1 #define PACKED_INV_VERSION_2 (inv_version_t) 2 #define PACKED_INV_VERSION PACKED_INV_VERSION_2 /* Print [-I] suboption -depth */ #define PR_DEFAULT 0 #define PR_FSONLY 1 #define PR_SESSONLY 2 #define PR_STRMSONLY 3 #define PR_ALL 4 #define PR_MAXDEPTH 5 #define PR_MAXLEVEL 255 /*----------------------------------------------------------------------*/ /* Inventory */ /* */ /* Users are first supposed to call inventory_open() specifying what */ /* type of handle s/he would like to supply. This can be BY_MOUNTPT, */ /* BY_DEVPATH, or BY_UUID. The inventory maintains its own table of file*/ /* systems and their uuids, mountpts, and device paths. */ /* The current implementation requires that a uuid be present for all */ /* its fs table entries. However, once the entry is there, caller can */ /* query by any of the other handles. */ /* */ /* For a read-session, ie. just querying, like in restore(), the token */ /* from inv_open() must always be passed. */ /* */ /* This inventory has a hierarchical token scheme. */ /* For write-sessions, the caller should obtain a session_token */ /* by calling inv_writesession_open() with the original token. */ /* In order to start writing media files, the caller must */ /* then obtain a stream-token via inv_stream_open() using that */ /* session-token. */ /* */ /* Once, done, stream_close(), writesession_close() and inv_close() */ /* must be called in that order. To obtain all the data written during */ /* the course of a single write-session, the user can call inv_get_ */ /* sessioninfo() while still holding the session-token. For inventory */ /* reconstruction, inv_put_sessioninfo() may be used, and there is no */ /* requirement to hold a token for that. */ /* */ /* inv_delete_mediaobj() is, of course, for deletion of all the media */ /* files contained in a media object. */ /* */ /*----------------------------------------------------------------------*/ /* Caller can open the inventory by any of these handles */ typedef enum { INV_BY_UUID, INV_BY_MOUNTPT, INV_BY_DEVPATH } inv_predicate_t; typedef enum { INV_SEARCH_ONLY, INV_SEARCH_N_MOD } inv_oflag_t; typedef struct inv_mediafile { uuid_t m_moid; /* media object id */ uint m_mfile_index; /* index within the media object */ xfs_ino_t m_startino; /* file that we started out with */ off64_t m_startino_off; xfs_ino_t m_endino; /* the dump file we ended this .. */ off64_t m_endino_off; /* .. media file with. */ off64_t m_size; /* size of mediafile in bytes */ bool_t m_isgood; /* distinguishes good mfiles */ bool_t m_isinvdump; /* is this the mfile that has the dump of the rest of the session? */ char m_label[INV_STRLEN]; /* media file label */ } inv_mediafile_t; typedef struct inv_stream { bool_t st_interrupted; /* was this stream interrupted ? */ /* duplicate info from mediafiles for speed */ xfs_ino_t st_startino; /* the starting pt */ off64_t st_startino_off; xfs_ino_t st_endino; /* where we actually ended up. this means we've written upto but not including this breakpoint. */ off64_t st_endino_off; char st_cmdarg[INV_STRLEN]; /* the driver path user entered */ uint st_nmediafiles; /* number of mediafiles */ inv_mediafile_t *st_mediafiles; /* array of all media files */ } inv_stream_t; /* * inventory_session_t * all the information that is kept on a single dump session of a single * file system in the inventory. * */ typedef struct inv_session { uuid_t s_fsid; /* file system */ uuid_t s_sesid; /* this session's id:16 bytes*/ time32_t s_time; /* time of the dump */ bool_t s_ispartial; /* was this a partial (dump) ? */ bool_t s_isresumed; /* was this a resumed (dump) ? */ u_char s_level; /* dump level */ char s_label[INV_STRLEN]; /* session label */ char s_mountpt[INV_STRLEN];/* path to the mount point */ char s_devpath[INV_STRLEN];/* path to the device */ uint s_nstreams; /* num of media streams recorded */ inv_stream_t *s_streams; /* array of streams */ uint s_refnum; /* storage location dependent ref. used in displaying the session and nowhere else */ } inv_session_t; struct invt_desc_entry; struct invt_sesdesc_entry; struct invt_strdesc_entry; /* The three kinds of access tokens for the inventory */ typedef struct invt_desc_entry *inv_idbtoken_t; typedef struct invt_sesdesc_entry *inv_sestoken_t; typedef struct invt_strdesc_entry *inv_stmtoken_t; /* inventory_open - initializes access to the inventory */ extern inv_idbtoken_t inv_open( inv_predicate_t bywhat, /* BY_UUID, BY_MOUNTPT, BY_DEVPATH */ inv_oflag_t forwhat,/* SEARCH_ONLY, SEARCH_N_MOD */ void *pred );/* uuid_t *,char * mntpt, or char *dev */ extern bool_t inv_close( inv_idbtoken_t tok ); extern inv_sestoken_t inv_writesession_open( inv_idbtoken_t tok, /* token obtained by inventory_init() */ uuid_t *fsid, uuid_t *sesid, char *label, bool_t ispartial, bool_t isresumed, u_char level, uint nstreams, time32_t time, char *mntpt, char *devpath ); extern bool_t inv_writesession_close( inv_sestoken_t tok ); extern inv_stmtoken_t inv_stream_open( inv_sestoken_t tok, char *cmdarg ); extern bool_t inv_stream_close( inv_stmtoken_t tok, bool_t wasinterrupted ); extern bool_t inv_put_mediafile( inv_stmtoken_t tok, uuid_t *moid, char *label, uint mfileindex, xfs_ino_t startino, off64_t startino_offset, xfs_ino_t endino, off64_t endino_offset, off64_t size, /* size of the mediafile in bytes */ bool_t isgood, /* to distinguish unimportant media files from others */ bool_t isinv_dump); /* lasttime_level_lessthan - finds the time of the last dump of the * specified file system at a level less than the specified level. * if never dumped below the current level, *time is set to NULL. * */ extern bool_t inv_lasttime_level_lessthan( uuid_t *fsidp, inv_idbtoken_t tok, u_char level, time32_t **time); /* out */ extern bool_t inv_lastsession_level_lessthan( uuid_t *fsidp, inv_idbtoken_t tok, u_char level, inv_session_t **ses); /* out */ extern bool_t inv_lastsession_level_equalto( uuid_t *fsidp, inv_idbtoken_t tok, u_char level, inv_session_t **ses); /* out */ /* Given a uuid of a session, return the session structure.*/ extern bool_t inv_get_session_byuuid( uuid_t *fsidp, uuid_t *sesid, inv_session_t **ses); extern bool_t inv_get_session_bylabel( uuid_t *fsidp, char *session_label, inv_session_t **ses); /* on return, *ses is NULL */ extern void inv_free_session( inv_session_t **ses); /* For dumping the inventory once a dump is done. */ extern bool_t inv_get_sessioninfo( inv_sestoken_t tok, void **bufpp, /* out */ size_t *bufszp ); /* out */ extern bool_t inv_delete_mediaobj( uuid_t *moid ); extern bool_t inv_DEBUG_print( int argc, char **argv ); extern int inv_setup_base( void ); extern char * inv_dirpath( void ); extern char * inv_fstab( void ); extern char * inv_lockfile( void ); extern char * inv_basepath( void ); #endif /* INVENTORY_H */ xfsdump-3.1.6+nmu1/inventory/Makefile0000644000000000000000000000054312607344125014454 0ustar # # Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = .. include $(TOPDIR)/include/builddefs LSRCFILES = inv_api.c inv_core.c inv_fstab.c inv_idx.c inv_mgr.c \ inv_oref.c inv_oref.h inv_priv.h inv_stobj.c inv_files.c \ inventory.h getopt.h testmain.c default install install-dev: include $(BUILDRULES) -include .ltdep xfsdump-3.1.6+nmu1/inventory/inv_stobj.c0000644000000000000000000012141712620476160015161 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "types.h" #include "timeutil.h" #include "mlog.h" #include "inv_priv.h" #include "arch_xlate.h" /*----------------------------------------------------------------------*/ /* stobj_insert_session */ /* */ /* Used in reconstruction of the inventory. We add a session to this */ /* storage object whether or not it has reached its maximum. */ /*----------------------------------------------------------------------*/ int stobj_insert_session( invt_idxinfo_t *idx, int fd, /* kept locked EX by caller */ invt_sessinfo_t *s ) { invt_sescounter_t *sescnt = NULL; if ( GET_SESCOUNTERS( fd, &sescnt ) < 0 ) { INVLOCK( fd, LOCK_UN ); return -1; } /* Check the existing sessions to make sure that we're not duplicating this session */ if ( sescnt->ic_curnum > 0 ) { uint i; invt_session_t *sessions = calloc( sescnt->ic_curnum, sizeof( invt_session_t ) ); if ( GET_REC_NOLOCK( fd, sessions, sescnt->ic_curnum * sizeof( invt_session_t ), (off64_t) ( sizeof( *sescnt ) + sescnt->ic_maxnum * sizeof( invt_seshdr_t ))) < 0 ) { free ( sescnt ); free ( sessions ); return -1; } for( i = 0; i < sescnt->ic_curnum; i++ ) { if ( uuid_compare( sessions[i].s_sesid, s->ses->s_sesid ) == 0 ) break; } free ( sessions ); if ( i < sescnt->ic_curnum ) { mlog( MLOG_DEBUG | MLOG_INV, "INV: attempt to insert an " "existing session.\n" ); free ( sescnt ); return 1; } } if ( sescnt->ic_curnum >= sescnt->ic_maxnum ) { if ( stobj_split( idx, fd, sescnt, s ) < 0 ) { free( sescnt ); return -1; } free( sescnt ); return 1; } if ( stobj_put_session( fd, sescnt, s->ses, s->seshdr, s->strms, s->mfiles ) < 0 ){ free ( sescnt); return -1; } free ( sescnt); return 1; } /*----------------------------------------------------------------------*/ /* stobj_find_splitpoint */ /* */ /* Load in all the session headers, and go thru them, one by one, */ /* beginning with last seshdr. We return once we find one with a */ /* different sh_time from the previous one. */ /*----------------------------------------------------------------------*/ /* ARGSUSED */ uint stobj_find_splitpoint( int fd, invt_seshdr_t *harr, uint ns, time32_t tm ) { uint i; if ( harr[ns-1].sh_time < tm ) return ns; /* since ns > 1, our split point > 0 */ for ( i = ns - 1; i > 0; i-- ) { /* these are ordered in ascending order */ if ( harr[i].sh_time > harr[i-1].sh_time ) return i; } /* All the entries have the same sh_time. It's not clear if that's really possible, but either way, we split at the last entry. This will impact the guarantee that invindex tries to give - that there's always a unique stobj for every session. */ mlog( MLOG_VERBOSE | MLOG_INV, _( "INV: failed to find a different sh_time to split\n") ); return ns - 1; } /*----------------------------------------------------------------------*/ /* */ /* */ /* */ /*----------------------------------------------------------------------*/ int stobj_split( invt_idxinfo_t *idx, int fd, invt_sescounter_t *sescnt, invt_sessinfo_t *newsess ) { invt_seshdr_t *harr = NULL; uint i, ix, ns = sescnt->ic_curnum; void *bufpp; size_t bufszp; invt_sessinfo_t sesinfo; invt_entry_t ient; if ( GET_SESHEADERS( fd, &harr, ns ) < 0 ) return -1; assert( harr != NULL ); if ( ( ix = stobj_find_splitpoint( fd, harr, ns, newsess->seshdr->sh_time ) ) == 0 ) return -1; if ( ix == ns ) { ient.ie_timeperiod.tp_start = ient.ie_timeperiod.tp_end = newsess->seshdr->sh_time; } else { ient.ie_timeperiod.tp_start = ient.ie_timeperiod.tp_end = harr[ix].sh_time; if ( harr[ix - 1].sh_time > newsess->seshdr->sh_time ) idx->iarr[idx->index].ie_timeperiod.tp_end = harr[ix - 1].sh_time; else idx->iarr[idx->index].ie_timeperiod.tp_end = newsess->seshdr->sh_time; } /* Get the new stobj to put the 'spilling' sessinfo in. We know the idx of the current stobj, and by definition, the new stobj should come right afterwards. */ newsess->stobjfd = idx_put_newentry( idx, &ient ); if ( newsess->stobjfd < 0 ) return -1; if ( ix == ns ) { invt_sescounter_t *scnt = NULL; off64_t rval; /* We dont need to split. So, just put the new session in the new stobj, and rest in peace */ idx->index++; if ( GET_SESCOUNTERS( newsess->stobjfd, &scnt ) < 0 ) return -1; rval = stobj_put_session( newsess->stobjfd, scnt, newsess->ses, newsess->seshdr, newsess->strms, newsess->mfiles ); free( scnt ); return (rval < 0)? -1: 1; } for ( i = ix; i < ns; i++ ) { invt_session_t session; bufpp = NULL; bufszp = 0; newsess->seshdr->sh_sess_off = harr[i].sh_sess_off; if ( GET_REC_NOLOCK( fd, &session, sizeof( invt_session_t ), harr[i].sh_sess_off ) < 0 ) return -1; if (! stobj_pack_sessinfo( fd, &session, &harr[i], &bufpp, &bufszp )) return -1; /* Now we need to put this in the new StObj. So, first unpack it. */ if (! stobj_unpack_sessinfo( bufpp, bufszp, &sesinfo ) ) return -1; /* There is no chance of a recursion here */ if ( stobj_insert_session( idx, newsess->stobjfd, &sesinfo ) < 0 ) return -1; /* Now delete that session from this StObj */ if (! stobj_delete_sessinfo( fd, sescnt, &session, &harr[i] ) ) return -1; free( bufpp ); } /* Put the new session in the stobj that we just split. Make sure that we use the updated sescnt and not the stale stuff from disk. stobj_put_session() writes sescnt and sessinfo to disk */ if ( stobj_put_session( fd, sescnt, newsess->ses, newsess->seshdr, newsess->strms, newsess->mfiles ) < 0 ) { free ( sescnt); return -1; } return 1; } /* ARGSUSED */ int stobj_delete_mfile( int fd, inv_stream_t *strm, invt_mediafile_t *mf, off64_t mfileoff ) { return 1; } /* ARGSUSED */ bool_t stobj_delete_sessinfo( int fd, /* kept locked EX by caller */ invt_sescounter_t *sescnt, invt_session_t *ses, invt_seshdr_t *hdr ) { /* we change the sescnt here, but dont write it back to disk until later */ sescnt->ic_curnum--; /* there is really no need to take out / zero out the deleted session. The seshdr and session will be over-written, but space taken by the streams and mediafiles will be wasted. */ return BOOL_TRUE; } /*----------------------------------------------------------------------*/ /* */ /* */ /* */ /*----------------------------------------------------------------------*/ off64_t stobj_put_session( int fd, invt_sescounter_t *sescnt, invt_session_t *ses, invt_seshdr_t *hdr, invt_stream_t *strms, invt_mediafile_t *mfiles ) { off64_t hoff; /* figure out the place where the header will go */ hoff = STOBJ_OFFSET( sescnt->ic_curnum, 0 ); /* figure out where the session information is going to go. */ if ( hdr->sh_sess_off < 0 ) hdr->sh_sess_off = STOBJ_OFFSET( sescnt->ic_maxnum, sescnt->ic_curnum ); sescnt->ic_curnum++; #ifdef INVT_DEBUG mlog ( MLOG_VERBOSE, "INV: create sess #%d @ offset %d ic_eof = %d\n", sescnt->ic_curnum, (int) hdr->sh_sess_off, (int) sescnt->ic_eof ); #endif /* we need to know where the streams begin, and where the media files will begin, at the end of the streams */ hdr->sh_streams_off = sescnt->ic_eof; if ( strms == NULL ) { sescnt->ic_eof += (off64_t)( ses->s_max_nstreams * sizeof( invt_stream_t ) ); } else { uint i; size_t nmf = 0; sescnt->ic_eof += (off64_t)( ses->s_cur_nstreams * sizeof( invt_stream_t ) ); for (i=0; is_cur_nstreams; i++) nmf += ( size_t ) strms[i].st_nmediafiles; sescnt->ic_eof += (off64_t)( sizeof( invt_mediafile_t ) * nmf ); if ( stobj_put_streams( fd, hdr, ses, strms, mfiles ) < 0 ) return -1; } /* we write back the counters of this storage object first */ if ( PUT_SESCOUNTERS( fd, sescnt ) < 0 ) return -1; /* write the header next; lseek to the right position */ if ( PUT_REC_NOLOCK( fd, hdr, sizeof( invt_seshdr_t ), hoff ) < 0 ) { return -1; } /* write the header information to the storage object */ if ( PUT_REC_NOLOCK( fd, ses, sizeof( invt_session_t ), hdr->sh_sess_off ) < 0 ) { return -1; } if ( strms != NULL ) stobj_sortheaders( fd, sescnt->ic_curnum ); return hoff; } /*----------------------------------------------------------------------*/ /* */ /* */ /* */ /*----------------------------------------------------------------------*/ int stobj_sortheaders( int fd, uint num ) { size_t sz = sizeof( invt_seshdr_t ) * num; invt_seshdr_t *hdrs; #ifdef INVT_DEBUG int i; #endif if ( num < 2 ) return 1; hdrs = malloc( sz ); assert( hdrs ); if ( GET_REC_NOLOCK( fd, hdrs, sz, STOBJ_OFFSET( 0, 0 ) ) < 0 ) { free ( hdrs ); return -1; } #ifdef INVT_DEBUG printf("\nBEF\n" ); for (i=0; i<(int)num; i++) printf("%ld\n", (long) hdrs[i].sh_time ); #endif qsort( (void*) hdrs, (size_t) num, sizeof( invt_seshdr_t ), stobj_hdrcmp ); #ifdef INVT_DEBUG printf("\n\nAFT\n" ); for (i=0; i<(int)num; i++) printf("%ld\n", (long) hdrs[i].sh_time ); #endif if ( PUT_REC_NOLOCK( fd, hdrs, sz, STOBJ_OFFSET( 0, 0 ) ) < 0 ) { free ( hdrs ); return -1; } free ( hdrs ); return 1; } /*----------------------------------------------------------------------*/ /* stobj_put_streams */ /* */ /* used only in reconstruction. */ /* puts the array of streams and the array of mediafiles in the stobj, */ /* after adjusting their offsets. */ /*----------------------------------------------------------------------*/ int stobj_put_streams( int fd, invt_seshdr_t *hdr, invt_session_t *ses, invt_stream_t *strms, invt_mediafile_t *mfiles ) { uint nstm = ses->s_cur_nstreams; off64_t off = hdr->sh_streams_off; off64_t mfileoff = off + (off64_t)( nstm * sizeof( invt_stream_t ) ); uint nmfiles = 0; uint i,j; /* fix the offsets in streams */ for ( i = 0; i < nstm; i++ ) { strms[i].st_firstmfile = mfileoff + (off64_t) ((size_t) nmfiles * sizeof( invt_mediafile_t ) ); /* now fix the offsets in mediafiles */ for ( j = 0; j < strms[i].st_nmediafiles; j++ ) { /* no need to fix the last element's next ptr */ if ( j < strms[i].st_nmediafiles - 1 ) mfiles[ nmfiles + j ].mf_nextmf = strms[i].st_firstmfile + (off64_t) ((j+1) * sizeof( invt_mediafile_t )); /* no need to fix the first element's prev ptr */ if ( j ) mfiles[ nmfiles + j ].mf_prevmf = strms[i].st_firstmfile + (off64_t) ((j-1) * sizeof( invt_mediafile_t )); } /* adjust the offsets of the first and the last elements in the mediafile chain */ mfiles[ nmfiles ].mf_prevmf = 0; nmfiles += strms[i].st_nmediafiles; mfiles[ nmfiles - 1 ].mf_nextmf = 0; } /* first put the streams. hdr already points at the right place */ if ( PUT_REC_NOLOCK( fd, strms, nstm * sizeof( invt_stream_t ), off ) < 0 ) return -1; if ( PUT_REC_NOLOCK( fd, mfiles, nmfiles * sizeof( invt_mediafile_t ), mfileoff ) < 0 ) return -1; return 1; } /*----------------------------------------------------------------------*/ /* */ /* */ /* */ /*----------------------------------------------------------------------*/ void stobj_makefname( char *fname ) { /* come up with a new unique name */ uuid_t fn; char str[UUID_STR_LEN + 1]; uuid_generate( fn ); uuid_unparse( fn, str ); strcpy( fname, INV_DIRPATH ); strcat( fname, "/" ); strcat( fname, str ); strcat( fname, INV_STOBJ_PREFIX ); assert( (int) strlen( fname ) < INV_STRLEN ); } /* NOTE: this doesnt update counters or headers in the inv_index */ int stobj_create( char *fname ) { int fd; invt_sescounter_t sescnt; inv_oflag_t forwhat = INV_SEARCH_N_MOD; #ifdef INVT_DEBUG mlog( MLOG_VERBOSE | MLOG_INV, "INV: creating storage obj %s\n", fname); #endif /* create the new storage object */ if (( fd = open( fname, INV_OFLAG(forwhat) | O_EXCL | O_CREAT, S_IRUSR|S_IWUSR )) < 0 ) { INV_PERROR ( fname ); memset( fname, 0, INV_STRLEN ); return -1; } INVLOCK( fd, LOCK_EX ); fchmod( fd, INV_PERMS ); sescnt.ic_vernum = INV_VERSION; sescnt.ic_curnum = 0; /* there are no sessions as yet */ sescnt.ic_maxnum = INVT_STOBJ_MAXSESSIONS; sescnt.ic_eof = SC_EOF_INITIAL_POS; if ( PUT_SESCOUNTERS ( fd, &sescnt ) < 0 ) { memset( fname, 0, INV_STRLEN ); INVLOCK( fd, LOCK_UN ); close( fd ); return -1; } INVLOCK( fd, LOCK_UN ); return fd; } /*----------------------------------------------------------------------*/ /* */ /* */ /* */ /*----------------------------------------------------------------------*/ int stobj_create_session( inv_sestoken_t tok, int fd, /* kept locked EX by caller */ invt_sescounter_t *sescnt, invt_session_t *ses, invt_seshdr_t *hdr ) { off64_t hoff; assert( tok && sescnt && ses && hdr ); hdr->sh_sess_off = -1; ses->s_cur_nstreams = 0; if ((hoff = stobj_put_session( fd, sescnt, ses, hdr, NULL, NULL )) < 0) { return -1; } tok->sd_sesshdr_off = hoff; tok->sd_session_off = hdr->sh_sess_off; return 1; } /*----------------------------------------------------------------------*/ /* */ /* */ /* The stobj_fd in the stream token is kept locked EX by caller. */ /*----------------------------------------------------------------------*/ int stobj_put_mediafile( inv_stmtoken_t tok, invt_mediafile_t *mf ) { int rval; invt_sescounter_t *sescnt = NULL; invt_stream_t stream; inv_sestoken_t sestok = tok->md_sesstok; int fd = sestok->sd_invtok->d_stobj_fd; off64_t pos; /* first we need to find out where the current write-position is. so, we first read the sescounter that is at the top of this storage object */ if ( GET_SESCOUNTERS( fd, &sescnt ) < 0 ) return -1; pos = sescnt->ic_eof; /* increment the pointer to give space for this media file */ sescnt->ic_eof += (off64_t) sizeof( invt_mediafile_t ); if ( PUT_SESCOUNTERS( fd, sescnt ) < 0 ) return -1; /* get the stream information, and update number of mediafiles. we also need to link the new mediafile into the linked-list of media files of this stream */ if ( GET_REC_NOLOCK( fd, &stream, sizeof( stream ), tok->md_stream_off ) < 0 ) return -1; /* We need to update the last ino of this STREAM, which is now the last ino of the new mediafile. If this is the first mediafile, we have to update the startino as well. Note that ino is a tuple */ if ( ! ( mf->mf_flag & INVT_MFILE_INVDUMP )) { if ( stream.st_nmediafiles == 0 ) stream.st_startino = mf->mf_startino; stream.st_endino = mf->mf_endino; } stream.st_nmediafiles++; #ifdef INVT_DEBUG mlog (MLOG_VERBOSE, "#################### mediafile #%d " "###################\n", stream.st_nmediafiles); #endif /* add the new mediafile at the tail of the list */ mf->mf_nextmf = tok->md_stream_off; mf->mf_prevmf = stream.st_lastmfile; if ( tok->md_lastmfile ) tok->md_lastmfile->mf_nextmf = pos; else { stream.st_firstmfile = pos; } stream.st_lastmfile = pos; /* write the stream to disk */ if ( PUT_REC_NOLOCK( fd, &stream, sizeof( stream ), tok->md_stream_off ) < 0 ) return -1; /* write the prev media file to disk too */ if ( tok->md_lastmfile ) { rval = PUT_REC_NOLOCK( fd, tok->md_lastmfile, sizeof( invt_mediafile_t ), mf->mf_prevmf ); free ( tok->md_lastmfile ); if ( rval < 0 ) return -1; } if ( ! ( mf->mf_flag & INVT_MFILE_INVDUMP )) { tok->md_lastmfile = mf; } else { tok->md_lastmfile = NULL; } /* at last, write the new media file to disk */ rval = PUT_REC_NOLOCK( fd, mf, sizeof( invt_mediafile_t ), pos ); if ( rval < 0 ) { return -1; } return rval; } /*----------------------------------------------------------------------*/ /* get_sessinfo */ /* */ /* get both the seshdr and session infomation. */ /* caller takes the responsibility of locking. */ /*----------------------------------------------------------------------*/ int stobj_get_sessinfo ( inv_sestoken_t tok, invt_seshdr_t *hdr, invt_session_t *ses ) { int rval; int fd = tok->sd_invtok->d_stobj_fd; /* get the session header first */ if ( ( rval = GET_REC_NOLOCK( fd, hdr, sizeof( invt_seshdr_t ), tok->sd_sesshdr_off ) ) > 0 ) { rval = GET_REC_NOLOCK( fd, ses, sizeof( invt_session_t ), tok->sd_session_off ); } return rval; } /*----------------------------------------------------------------------*/ /* */ /* */ /* */ /*----------------------------------------------------------------------*/ bool_t stobj_pack_sessinfo( int fd, invt_session_t *ses, invt_seshdr_t *hdr, void **bufpp, size_t *bufszp ) { size_t stmsz; uint i, j; size_t sessz; invt_stream_t *strms; char *sesbuf, *sesbufcp; off64_t off; invt_mediafile_t mf; stmsz = sizeof( invt_stream_t ) * ses->s_cur_nstreams; /* the initial size without the mediafiles */ sessz = strlen( INVTSESS_COOKIE ) * sizeof( char ) + sizeof( inv_version_t ) + sizeof( inv_version_t ) + /* added to fix 64 bit alignment prob */ sizeof( invt_session_t) + sizeof( invt_seshdr_t ) + stmsz; /* now get all the streams of this session */ strms = calloc ( ses->s_cur_nstreams, sizeof( invt_stream_t ) ); if ( GET_REC_NOLOCK( fd, strms, stmsz, hdr->sh_streams_off ) < 0 ) { free ( strms ); return BOOL_FALSE; } for ( i = 0; i < ses->s_cur_nstreams; i++ ) sessz += sizeof( invt_mediafile_t ) * (size_t) strms[i].st_nmediafiles; /* Now we know how big this entire thing is going to be */ sesbufcp = sesbuf = calloc( 1, sessz ); assert( sesbuf ); /* Copy everything. Note that we don't bother to adjust the offsets either in the seshdr or in the mediafiles, because we don't need those in order to restore this session ( since everything's contiguous ) */ /* magic cookie that we put for sanity checking in case of an earthquake or something :) */ strcpy( sesbuf, INVTSESS_COOKIE ); sesbuf += (size_t)( strlen( INVTSESS_COOKIE ) * sizeof( char ) ); /* This was originally INV_VERSION. Changed it to mean packed inventory * version number and added another inv_version_t to contain the INV_VERSION. * The primary intent of this change was to make everything 64 bit aligned, * but we also got the advantage of separating the packed inv version from * the general inventory version */ *(inv_version_t *)sesbuf = INT_GET(PACKED_INV_VERSION, ARCH_CONVERT); sesbuf += sizeof( inv_version_t ); /* This has the INV_VERSION */ *(inv_version_t *)sesbuf = INT_GET(INV_VERSION, ARCH_CONVERT); sesbuf += sizeof( inv_version_t ); xlate_invt_seshdr(hdr, (invt_seshdr_t *)sesbuf, 1); sesbuf += sizeof( invt_seshdr_t ); xlate_invt_session( ses, (invt_session_t *)sesbuf, 1 ); sesbuf += sizeof( invt_session_t ); for ( i = 0; i < ses->s_cur_nstreams; i++ ) { xlate_invt_stream( strms, (invt_stream_t *)sesbuf, 1 ); sesbuf += sizeof( invt_stream_t ); } /* now append all the mediafiles */ for ( i = 0; i < ses->s_cur_nstreams; i++ ) { off = strms[i].st_firstmfile; for ( j = 0; j < strms[i].st_nmediafiles; j++, off = mf.mf_nextmf ) { assert( off ); if ( GET_REC_NOLOCK( fd, &mf, sizeof( invt_mediafile_t ), off ) <= 0 ) { free( strms ); free( sesbuf ); return BOOL_FALSE; } xlate_invt_mediafile(&mf, (invt_mediafile_t *)sesbuf, 1); sesbuf += sizeof( invt_mediafile_t ); } } free( strms ); *bufpp = sesbufcp; *bufszp = sessz; return BOOL_TRUE; } /*----------------------------------------------------------------------*/ /* */ /* */ /* */ /*----------------------------------------------------------------------*/ bool_t stobj_getsession_byuuid( int fd, invt_seshdr_t *hdr, void *sesid, void **buf ) { invt_session_t ses; /* retrieve the session */ if ( GET_REC_NOLOCK( fd, &ses, sizeof( invt_session_t ), hdr->sh_sess_off ) < 0 ) return -1; /* now see if this is the one that caller is askin for */ if (uuid_compare(ses.s_sesid, *((uuid_t *)sesid))) { return BOOL_FALSE; } /* yay. we found the session. so, make the session struct and put it in the buffer */ stobj_copy_invsess(fd, hdr, &ses, (inv_session_t **)buf); return BOOL_TRUE; } /*----------------------------------------------------------------------*/ /* */ /* */ /* */ /*----------------------------------------------------------------------*/ bool_t stobj_getsession_bylabel( int fd, invt_seshdr_t *hdr, void *seslabel, void **buf ) { invt_session_t ses; /* retrieve the session */ if ( GET_REC_NOLOCK( fd, &ses, sizeof( invt_session_t ), hdr->sh_sess_off ) < 0 ) return -1; /* now see if this is the one that caller is askin for */ if (! STREQL(ses.s_label, (char *)seslabel)) { return BOOL_FALSE; } /* yay. we found the session. so, make the session struct and put it in the buffer */ stobj_copy_invsess(fd, hdr, &ses, (inv_session_t **)buf); return BOOL_TRUE; } /*----------------------------------------------------------------------*/ /* */ /* */ /* */ /*----------------------------------------------------------------------*/ /* ARGSUSED */ bool_t stobj_delete_mobj(int fd, invt_seshdr_t *hdr, void *arg , void **buf ) { /* XXX fd needs to be locked EX, not SH */ uuid_t *moid = *buf; invt_session_t ses; invt_stream_t *strms; off64_t off; invt_mediafile_t *mf, *mfiles; uint nmfiles; uint i, j; bool_t dirty; if ( GET_REC_NOLOCK( fd, &ses, sizeof( invt_session_t ), hdr->sh_sess_off ) < 0 ) return -1; /* now get all the streams of this session */ strms = calloc ( ses.s_cur_nstreams, sizeof( invt_stream_t ) ); if ( GET_REC_NOLOCK( fd, strms, sizeof( invt_stream_t ) * ses.s_cur_nstreams, hdr->sh_streams_off ) < 0 ) { free ( strms ); return BOOL_FALSE; } /* now look at all the mediafiles in all the streams */ for ( i = 0; i < ses.s_cur_nstreams; i++ ) { off = strms[i].st_firstmfile; nmfiles = strms[i].st_nmediafiles; mfiles = mf = calloc( nmfiles, sizeof( invt_mediafile_t ) ); for ( j = 0; j < nmfiles; j++, off = mf->mf_nextmf, mf++ ) { /* The prob is that we need to keep track of where we got these mfiles from as we get them, or we wont know how to put them back if they are dirty. */ assert( off ); if ( GET_REC_NOLOCK( fd, mf, sizeof( invt_mediafile_t ), off ) <= 0 ) { free( strms ); free( mfiles ); return BOOL_FALSE; } } /* We have all the media files of this stream. Make another pass, checking to see if we need to remove any mfiles */ dirty = BOOL_FALSE; for ( j = 0; j < nmfiles; j++ ) { mf = &mfiles[j]; if ( !uuid_compare( mf->mf_moid, *moid ) ) { #ifdef INVT_DEBUG printf(" found one\n" ); #endif /* dirty = BOOL_TRUE; if ( j == 0 ) strms[i].st_firstmfile = mf->mf_nextmf; else mfiles[j-1].mf_nextmf = mf->mf_nextmf; if ( j == nmfiles - 1 ) strms[i].st_lastmfile = ; */ } } free ( mfiles ); if ( dirty ); } free ( strms ); return BOOL_FALSE; /* ret FALSE, or it'll stop iteration */ } /*----------------------------------------------------------------------*/ /* stobj_unpack_sessinfo */ /* */ /* */ /*----------------------------------------------------------------------*/ bool_t stobj_unpack_sessinfo( void *bufp, size_t bufsz, invt_sessinfo_t *s ) { uint i; char *tmpbuf; char *p = (char *)bufp; assert ( bufp ); tmpbuf = (char *)malloc(bufsz); /* first make sure that the magic cookie at the beginning is right. this isn't null-terminated */ if (strncmp( p, INVTSESS_COOKIE, strlen( INVTSESS_COOKIE ) ) != 0) { mlog( MLOG_NORMAL | MLOG_INV, _( "INV: inv_put_session: unknown cookie\n") ); return BOOL_FALSE; } /* skip the cookie */ p += strlen( INVTSESS_COOKIE ) * sizeof( char ); /* Check the packing version number. In version 1 , this was the only version number. * see the comment in stobj_pack_sessinfo(). */ if ( INT_GET(*( inv_version_t *) p, ARCH_CONVERT) == PACKED_INV_VERSION_1 ) { char *temp_p; size_t tempsz; mlog( MLOG_DEBUG | MLOG_INV,"INV: packed inventory version = 1\n" ); p += sizeof( inv_version_t ); /* We hit a 64 bit alignment issue at this point leading to a * SIGBUS and core dump. The best way to handle it is to * bcopy the remaining part of bufp to a new malloc'ed area * which will be 64 bit aligned. This is a memory leak , but not much. * Have to do this because xfsrestore does another round of * unpack later , so can't disturb the original data. * This is fixed in PACKED_INV_VERSION_2 by adding another (inv_version_t) to * have the INV_VERSION. This makes everything 64 bit aligned. */ tempsz = bufsz - (strlen( INVTSESS_COOKIE ) * sizeof( char )) - sizeof( inv_version_t ) ; temp_p = calloc(1, tempsz); bcopy(p, temp_p, tempsz); p = temp_p; } else if ( INT_GET(*( inv_version_t *) p, ARCH_CONVERT) == PACKED_INV_VERSION_2 ) { mlog( MLOG_DEBUG | MLOG_INV,"INV: packed inventory version = 2\n" ); p += sizeof( inv_version_t ); /* skip the packed inventory version */ /* At this point , don't care about the INV_VERSION. Maybe in future */ p += sizeof( inv_version_t ); /* skip the inventory version */ } else { mlog( MLOG_NORMAL | MLOG_INV, _( "INV: inv_put_session: unknown packed inventory version" " %d\n"), *( inv_version_t *) p); return BOOL_FALSE; } xlate_invt_seshdr((invt_seshdr_t *)p, (invt_seshdr_t *)tmpbuf, 1); bcopy(tmpbuf, p, sizeof(invt_seshdr_t)); /* get the seshdr and then, the remainder of the session */ s->seshdr = (invt_seshdr_t *)p; s->seshdr->sh_sess_off = -1; p += sizeof( invt_seshdr_t ); xlate_invt_session((invt_session_t *)p, (invt_session_t *)tmpbuf, 1); bcopy (tmpbuf, p, sizeof(invt_session_t)); s->ses = (invt_session_t *)p; p += sizeof( invt_session_t ); /* the array of all the streams belonging to this session */ xlate_invt_stream((invt_stream_t *)p, (invt_stream_t *)tmpbuf, 1); bcopy(tmpbuf, p, sizeof(invt_stream_t)); s->strms = (invt_stream_t *)p; p += s->ses->s_cur_nstreams * sizeof( invt_stream_t ); /* all the media files */ s->mfiles = (invt_mediafile_t *)p; #ifdef INVT_DELETION { int tmpfd = open( "moids", O_RDWR | O_CREAT, S_IRUSR|S_IWUSR ); uint j; invt_mediafile_t *mmf = s->mfiles; for (i=0; i< s->ses->s_cur_nstreams; i++ ) { for (j=0; j< s->strms[ i ].st_nmediafiles; j++, mmf++ ) xlate_invt_mediafile((invt_mediafile_t *)mmf, (invt_mediafile_t *)tmpbuf, 1); bcopy(tmpbuf, mmf, sizeof(invt_mediafile_t)); put_invtrecord( tmpfd, &mmf->mf_moid, sizeof( uuid_t ), 0, SEEK_END, 0 ); } close( tmpfd ); } #endif for ( i = 0; i < s->ses->s_cur_nstreams; i++ ) { p += (size_t) ( s->strms[ i ].st_nmediafiles ) * sizeof( invt_mediafile_t ); } /* sanity check the size of the buffer given to us vs. the size it should be */ if ( (size_t) ( p - (char *) bufp ) != bufsz ) { mlog( MLOG_DEBUG | MLOG_INV, "p-bufp %d != bufsz %d entsz %d\n", (int)( p - (char *) bufp ), (int) bufsz, (int) ( sizeof( invt_entry_t ) ) ); } assert( (size_t) ( p - (char *) bufp ) == bufsz ); return BOOL_TRUE; } /*----------------------------------------------------------------------*/ /* */ /* */ /* */ /*----------------------------------------------------------------------*/ int stobj_make_invsess( int fd, inv_session_t **buf, invt_seshdr_t *hdr ) { invt_session_t ses; /* load in the rest of the session, but not the streams */ if ( GET_REC_NOLOCK( fd, &ses, sizeof(ses), hdr->sh_sess_off ) < 0 ) { return -1; } return stobj_copy_invsess(fd, hdr, &ses, buf); } void stobj_convert_mfile(inv_mediafile_t *expmf, invt_mediafile_t *mf) { /* copy the mediafile into the exported structure */ memcpy( &expmf->m_moid, &mf->mf_moid, sizeof( uuid_t ) ); strcpy( expmf->m_label, mf->mf_label ); expmf->m_mfile_index = mf->mf_mfileidx; expmf->m_startino = mf->mf_startino.ino; expmf->m_startino_off = mf->mf_startino.offset; expmf->m_endino = mf->mf_endino.ino; expmf->m_endino_off = mf->mf_endino.offset; expmf->m_size = mf->mf_size; expmf->m_isgood = (mf->mf_flag & INVT_MFILE_GOOD ) ? BOOL_TRUE : BOOL_FALSE; expmf->m_isinvdump = (mf->mf_flag & INVT_MFILE_INVDUMP)? BOOL_TRUE : BOOL_FALSE; } void stobj_convert_strm(inv_stream_t *expstrm, invt_stream_t *strm) { expstrm->st_interrupted = strm->st_interrupted; expstrm->st_startino = strm->st_startino.ino; expstrm->st_startino_off = strm->st_startino.offset; expstrm->st_endino = strm->st_endino.ino; expstrm->st_endino_off = strm->st_endino.offset; strcpy( expstrm->st_cmdarg, strm->st_cmdarg ); expstrm->st_nmediafiles = strm->st_nmediafiles; /* caller is responsible for initializing this */ expstrm->st_mediafiles = NULL; } void stobj_convert_session(inv_session_t *ises, invt_session_t *ses, invt_seshdr_t *hdr) { ises->s_time = hdr->sh_time; ises->s_level = hdr->sh_level; ises->s_ispartial = IS_PARTIAL_SESSION( hdr )? BOOL_TRUE: BOOL_FALSE; ises->s_isresumed = IS_RESUMED_SESSION( hdr )? BOOL_TRUE: BOOL_FALSE; ises->s_nstreams = ses->s_cur_nstreams; memcpy( &ises->s_sesid, &ses->s_sesid, sizeof( uuid_t ) ); memcpy( &ises->s_fsid, &ses->s_fsid, sizeof( uuid_t ) ); strcpy( ises->s_mountpt, ses->s_mountpt ); strcpy( ises->s_devpath, ses->s_devpath ); strcpy( ises->s_label, ses->s_label ); /* caller is responsible for initializing this */ ises->s_streams = NULL; } /*----------------------------------------------------------------------*/ /* */ /* */ /* */ /*----------------------------------------------------------------------*/ int stobj_copy_invsess(int fd, invt_seshdr_t *hdr, invt_session_t *ses, inv_session_t **buf) { inv_session_t *ises; invt_stream_t *strms; int i; invt_mediafile_t mf; strms = calloc ( ses->s_cur_nstreams, sizeof( invt_stream_t ) ); /* load in all the stream-headers */ if ( GET_REC_NOLOCK( fd, strms, ses->s_cur_nstreams * sizeof( invt_stream_t ), hdr->sh_streams_off ) < 0 ) { free (strms); return -1; } ises = calloc( 1, sizeof( inv_session_t ) ); stobj_convert_session(ises, ses, hdr); ises->s_streams = calloc(ses->s_cur_nstreams, sizeof( inv_stream_t )); /* fill in the stream structures too */ i = (int) ses->s_cur_nstreams; while ( i-- ) { off64_t off; uint j, nmf; stobj_convert_strm(&ises->s_streams[i], &strms[i]); nmf = strms[i].st_nmediafiles; off = strms[i].st_firstmfile; if (nmf) ises->s_streams[i].st_mediafiles = calloc( nmf, sizeof( inv_mediafile_t ) ); assert( !nmf || ises->s_streams[i].st_mediafiles ); for ( j = 0; j < nmf; j++, off = mf.mf_nextmf ) { assert( off ); if ( GET_REC_NOLOCK( fd, &mf, sizeof( invt_mediafile_t ), off ) <= 0 ) { INV_PERROR( "stobj::make_invsess\n" ); free( strms ); free( ises ); return -1; } /* copy the mediafile into the exported structure */ if (ises->s_streams[i].st_mediafiles) { stobj_convert_mfile( &ises->s_streams[i].st_mediafiles[j], &mf); } else { mlog(MLOG_ERROR, _( "Failed to get data from media file: " "possible file corruption\n") ); mlog_exit_hint(RV_CORRUPT); return -1; } } } free( strms ); *buf = ises; return 1; } /*----------------------------------------------------------------------*/ /* Given a sessinfo structure, this makes an exportable inv_session. */ /* */ /* */ /*----------------------------------------------------------------------*/ void stobj_convert_sessinfo(inv_session_t **buf, invt_sessinfo_t *sinfo) { inv_session_t *ises; int i, j, nmf; int nstreams; invt_mediafile_t *mf; ises = calloc( 1, sizeof( inv_session_t ) ); stobj_convert_session(ises, sinfo->ses, sinfo->seshdr); ises->s_streams = calloc( ises->s_nstreams, sizeof( inv_stream_t ) ); mf = sinfo->mfiles; nstreams = (int) ises->s_nstreams; for ( i = 0 ; i < nstreams ; i++ ) { stobj_convert_strm(&ises->s_streams[i], &sinfo->strms[i]); nmf = (int) ises->s_streams[i].st_nmediafiles; ises->s_streams[i].st_mediafiles = calloc( (uint) nmf, sizeof( inv_mediafile_t ) ); for ( j = 0; j < nmf; j++ ) { stobj_convert_mfile( &ises->s_streams[i].st_mediafiles[j], mf++ ); } } *buf = ises; } int stobj_hdrcmp( const void *h1, const void *h2 ) { return (int) ( ((invt_seshdr_t *)h1)->sh_time - ((invt_seshdr_t *)h2)->sh_time ); } void DEBUG_sessprint( invt_session_t *ses ) { char str[UUID_STR_LEN + 1]; uuid_unparse( ses->s_fsid, str ); printf("-------- session -------------\n"); printf("label\t%s\n", ses->s_label); printf("mount\t%s\n", ses->s_mountpt); printf("devpath\t%s\n", ses->s_devpath); printf("strms\t%d\n", ses->s_cur_nstreams ); printf("fsid\t%s\n", str); printf("-------- end -------------\n"); } bool_t mobj_eql ( inv_mediafile_t *mfp, invt_mobjinfo_t *mobj ) { if ( mobj->type == INVT_MOID ) { if ( !uuid_compare( *((uuid_t*) mobj->value), mfp->m_moid) ) { return BOOL_TRUE; } } else { if ( STREQL( (char*) mobj->value, mfp->m_label ) ) { return BOOL_TRUE; } } return BOOL_FALSE; } bool_t check_for_mobj ( inv_session_t *ses, invt_mobjinfo_t *mobj ) { int i; uint j; inv_mediafile_t *mfp; for (i = 0; i < (int) ses->s_nstreams; i++ ) { for ( j = 0 ; j < ses->s_streams[i].st_nmediafiles ; j++ ) { mfp = &ses->s_streams[i].st_mediafiles[j]; if (mobj_eql( mfp, mobj )) return BOOL_TRUE; } } return BOOL_FALSE; /* There are no matching media objects to print */ } void DEBUG_sessionprint( inv_session_t *ses, uint ref, invt_pr_ctx_t *prctx) { char str[UUID_STR_LEN + 1]; int i; inv_mediafile_t *mfp; static uint fsidxprinted = -1; invt_mobjinfo_t *mobj = &prctx->mobj; bool_t moidsearch = ( mobj && mobj->type != INVT_NULLTYPE ); if ( moidsearch ){ if (!check_for_mobj (ses, mobj)) return; } if ( ref == 0 || fsidxprinted != (uint) prctx->index ) { fsidxprinted = (uint) prctx->index; printf("file system %d:\n", prctx->index); uuid_unparse( ses->s_fsid, str ); printf("\tfs id:\t\t%s\n", str); } if (prctx->depth == PR_FSONLY) return; if ((prctx->level != PR_MAXLEVEL) && (prctx->level != ses->s_level)) return; printf("\tsession %d:\n", ref); printf("\t\tmount point:\t%s\n", ses->s_mountpt); printf("\t\tdevice:\t\t%s\n", ses->s_devpath); printf("\t\ttime:\t\t%s", ctime32( &ses->s_time )); printf("\t\tsession label:\t\"%s\"\n", ses->s_label); uuid_unparse( ses->s_sesid, str ); printf("\t\tsession id:\t%s\n", str); printf("\t\tlevel:\t\t%d\n", ses->s_level); printf("\t\tresumed:\t%s\n", ses->s_isresumed ? "YES" : "NO" ); printf( "\t\tsubtree:\t%s\n", ses->s_ispartial ? "YES" : "NO" ); printf("\t\tstreams:\t%d\n", ses->s_nstreams ); if (prctx->depth == PR_SESSONLY ) return; for (i = 0; i < (int) ses->s_nstreams; i++ ) { uint j; printf("\t\tstream %d:\n", i ); printf( "\t\t\tpathname:\t%s\n", ses->s_streams[i].st_cmdarg ); printf( "\t\t\tstart:\t\tino %llu offset %lld\n", (unsigned long long)ses->s_streams[i].st_startino, (long long)ses->s_streams[i].st_startino_off ); printf( "\t\t\tend:\t\tino %llu offset %lld\n", (unsigned long long)ses->s_streams[i].st_endino, (long long)ses->s_streams[i].st_endino_off ); printf( "\t\t\tinterrupted:\t%s\n", ses->s_streams[i].st_interrupted ? "YES" : "NO" ); printf( "\t\t\tmedia files:\t%d\n", ses->s_streams[i].st_nmediafiles); if (prctx->depth == PR_STRMSONLY ) continue; for ( j = 0 ; j < ses->s_streams[i].st_nmediafiles ; j++ ) { mfp = &ses->s_streams[i].st_mediafiles[j]; if ( moidsearch ) { if (! mobj_eql( mfp, mobj ) ) continue; } printf( "\t\t\tmedia file %d:", j ); /* if (mfp->m_isinvdump) printf(" SESSION INVENTORY"); */ printf( "\n"); printf( "\t\t\t\tmfile index:\t%d\n", mfp->m_mfile_index ); printf( "\t\t\t\tmfile type:\t" ); if (mfp->m_isinvdump) { printf( "inventory\n" ); } else { printf( "data\n" ); } printf( "\t\t\t\tmfile size:\t%llu\n", (unsigned long long)mfp->m_size); if (! mfp->m_isinvdump) { printf( "\t\t\t\tmfile start:" "\tino %llu offset %lld\n", (unsigned long long)mfp->m_startino, (long long)mfp->m_startino_off ); printf( "\t\t\t\tmfile end:" "\tino %llu offset %lld\n", (unsigned long long)mfp->m_endino, (long long)mfp->m_endino_off ); } printf( "\t\t\t\tmedia label:\t\"%s\"\n", mfp->m_label); uuid_unparse( mfp->m_moid, str ); printf( "\t\t\t\tmedia id:\t%s\n", str ); } } } xfsdump-3.1.6+nmu1/inventory/inv_api.c0000644000000000000000000007347712620476160014625 0ustar /* * Copyright (c) 2000-2002 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "types.h" #include "mlog.h" #include "inv_priv.h" #include "getopt.h" /*----------------------------------------------------------------------*/ /* inventory_open */ /* */ /* INV_BY_MOUNTPT, INV_BY_UUID or INV_BY_DEVPATH */ /*----------------------------------------------------------------------*/ inv_idbtoken_t inv_open( inv_predicate_t bywhat, inv_oflag_t forwhat, void *pred ) { int fd, stobjfd, num, retval; inv_idbtoken_t tok = INV_TOKEN_NULL; invt_sescounter_t *sescnt = 0; int index = 0; assert ( pred ); fd = retval = init_idb ( pred, bywhat, forwhat, &tok ); if ( retval == I_DONE ) return tok; /* if we just want to search the db, all we need is the invidx. at this point, we know that a tok wasnt created in init_idb() */ if ( forwhat == INV_SEARCH_ONLY ) { /* fd == I_EMPTYINV or fd == valid fd */ tok = get_token( fd, -1); tok->d_oflag = forwhat; return tok; } /* XXX also, see if it is too full. if so, make another and leave a reference to the new file in the old one */ stobjfd = idx_get_stobj( fd, forwhat, &index ); if ( stobjfd < 0 ) { close( fd ); return INV_TOKEN_NULL; } assert ( index > 0 ); /* Now we need to make sure that this has enough space */ INVLOCK( stobjfd, LOCK_SH ); num = GET_SESCOUNTERS( stobjfd, &sescnt ); if ( num < 0 ) { close( fd ); INVLOCK( stobjfd, LOCK_UN ); close( stobjfd ); return INV_TOKEN_NULL; } /* create another storage object ( and, an inv_index entry for it too ) if we've filled this one up */ if ( (uint) num >= sescnt->ic_maxnum ) { mlog( MLOG_DEBUG | MLOG_INV, "$ INV: creating a new storage obj & " "index entry. \n" ); INVLOCK( stobjfd, LOCK_UN ); close (stobjfd); INVLOCK( fd, LOCK_EX ); stobjfd = idx_create_entry( &tok, fd, BOOL_FALSE ); INVLOCK( fd, LOCK_UN ); free ( sescnt ); if ( stobjfd < 0 ) { close( fd ); return INV_TOKEN_NULL; } return tok; } INVLOCK( stobjfd, LOCK_UN ); free ( sescnt ); tok = get_token( fd, stobjfd ); tok->d_invindex_off = IDX_HDR_OFFSET( index - 1 ); tok->d_oflag = forwhat; return tok; } /*----------------------------------------------------------------------*/ /* */ /* */ /* */ /*----------------------------------------------------------------------*/ bool_t inv_close( inv_idbtoken_t tok ) { close ( tok->d_invindex_fd ); if ( tok->d_stobj_fd >= 0 ) close ( tok->d_stobj_fd ); destroy_token( tok ); return BOOL_TRUE; } /*----------------------------------------------------------------------*/ /* */ /* */ /* */ /*----------------------------------------------------------------------*/ inv_sestoken_t inv_writesession_open( inv_idbtoken_t tok, /* token obtained by inventory_open() */ uuid_t *fsid, uuid_t *sesid, char *label, bool_t ispartial, bool_t isresumed, u_char level, uint nstreams, time32_t time, char *mntpt, char *devpath ) { invt_session_t ses; int fd; int rval; invt_sescounter_t *sescnt = NULL; invt_seshdr_t hdr; inv_sestoken_t sestok; inv_oflag_t forwhat; assert ( tok != INV_TOKEN_NULL ); assert ( sesid && fsid && mntpt && devpath ); forwhat = tok->d_oflag; fd = tok->d_stobj_fd; assert ( forwhat != INV_SEARCH_ONLY ); assert ( fd > 0 ); if ( ! ( tok->d_update_flag & FSTAB_UPDATED ) ) { if ( fstab_put_entry( fsid, mntpt, devpath, forwhat ) < 0 ) { mlog( MLOG_NORMAL | MLOG_INV, _( "INV: put_fstab_entry failed.\n") ); return INV_TOKEN_NULL; } tok->d_update_flag |= FSTAB_UPDATED; } /* copy the session information to store */ memset( (void *)&ses, 0, sizeof( ses ) ); /* paranoia */ memcpy( &ses.s_sesid, sesid, sizeof( uuid_t ) ); memcpy( &ses.s_fsid, fsid, sizeof( uuid_t ) ); strcpy( ses.s_label, label ); strcpy( ses.s_mountpt, mntpt ); strcpy( ses.s_devpath, devpath ); ses.s_max_nstreams = nstreams; hdr.sh_pruned = 0; /* session is not pruned by invutil */ hdr.sh_time = time; hdr.sh_level = level; hdr.sh_flag = (ispartial) ? INVT_PARTIAL: 0; hdr.sh_flag |= (isresumed) ? INVT_RESUMED : 0; /* sh_streams_off and sh_sess_off will be set in create_session() */ sestok = get_sesstoken( tok ); /* we need to put the new session in the appropriate place in storage object. So first find out howmany sessions are there */ INVLOCK( fd, LOCK_EX ); if ( GET_SESCOUNTERS( fd, &sescnt) < 0 ) { free ( sestok ); INVLOCK( fd, LOCK_UN ); return INV_TOKEN_NULL; } /* create the writesession, and get ready for the streams to come afterwards */ rval = stobj_create_session( sestok, fd, sescnt, &ses, &hdr ); assert (rval > 0); INVLOCK( fd, LOCK_UN ); sestok->sd_sesstime = time; if ( tok->d_update_flag & NEW_INVINDEX ) { if ( idx_put_sesstime( sestok, INVT_STARTTIME ) < 0 ) { mlog( MLOG_NORMAL | MLOG_INV, _( "INV: put_starttime failed.\n") ); return INV_TOKEN_NULL; } tok->d_update_flag &= ~(NEW_INVINDEX); } free ( sescnt ); return ( rval < 0 )? INV_TOKEN_NULL: sestok; } /*----------------------------------------------------------------------*/ /* */ /* */ /* */ /*----------------------------------------------------------------------*/ bool_t inv_writesession_close( inv_sestoken_t tok ) { int rval; assert ( tok != INV_TOKEN_NULL ); /* now update end_time in the inv index header */ rval = idx_put_sesstime( tok, INVT_ENDTIME ); memset( tok, 0, sizeof( invt_sesdesc_entry_t ) ); free ( tok ); return ( rval < 0 ) ? BOOL_FALSE: BOOL_TRUE; } /*----------------------------------------------------------------------*/ /* inventory_stream_open */ /* */ /* Opens a stream for mediafiles to be put in. */ /*----------------------------------------------------------------------*/ inv_stmtoken_t inv_stream_open( inv_sestoken_t tok, char *cmdarg ) { inv_stmtoken_t stok; invt_stream_t stream; invt_session_t ses; invt_seshdr_t seshdr; int fd; bool_t err = BOOL_FALSE; assert ( tok != INV_TOKEN_NULL ); /* this memset is needed as a dump interrupted/crashed very soon * after starting results in an inventory with exteremely large * starting/ending inodes or offsets. This can be misleading. * See bug #463702 for an example. */ memset( (void *)&stream, 0 , sizeof(invt_stream_t) ); stream.st_nmediafiles = 0; stream.st_interrupted = BOOL_TRUE; /* fix for 353197 */ strcpy( stream.st_cmdarg, cmdarg ); /* XXX yukk... make the token descriptors not pointers */ stok = ( inv_stmtoken_t ) malloc( sizeof( invt_strdesc_entry_t ) ); stok->md_sesstok = tok; stok->md_lastmfile = 0; /* get the session to find out where the stream is going to go */ fd = tok->sd_invtok->d_stobj_fd; INVLOCK( fd, LOCK_EX ); /* get the session header and the session */ if ( stobj_get_sessinfo( tok, &seshdr, &ses ) <= 0 ) err = BOOL_TRUE; if ( ( ! err ) && ses.s_cur_nstreams < ses.s_max_nstreams ) { /* this is where this stream header will be written to */ stok->md_stream_off = (off64_t) (sizeof( invt_stream_t ) * ses.s_cur_nstreams ) + seshdr.sh_streams_off; ses.s_cur_nstreams++; /* write it back. */ if ( PUT_REC_NOLOCK( fd, &ses, sizeof( ses ), tok->sd_session_off ) < 0 ) err = BOOL_TRUE; } else if ( ! err ) { mlog ( MLOG_NORMAL, _( "INV: cant create more than %d streams." " Max'd out..\n"), ses.s_cur_nstreams ); err = BOOL_TRUE; } if ( ! err ) { stream.st_firstmfile = stream.st_lastmfile = stok->md_stream_off; /* now write the stream header on to the disk */ if ( PUT_REC_NOLOCK( fd, &stream, sizeof( invt_stream_t ), stok->md_stream_off ) > 0 ) { /* we're all set */ INVLOCK( fd, LOCK_UN ); return stok; } } /* error occured somewhere */ free ( stok ); INVLOCK( fd, LOCK_UN ); return INV_TOKEN_NULL; } /*----------------------------------------------------------------------*/ /* */ /* */ /* */ /*----------------------------------------------------------------------*/ bool_t inv_stream_close( inv_stmtoken_t tok, bool_t wasinterrupted ) { invt_stream_t strm; int fd = tok->md_sesstok->sd_invtok->d_stobj_fd; int rval; bool_t dowrite = BOOL_FALSE; rval = idx_put_sesstime( tok->md_sesstok, INVT_ENDTIME ); if (rval < 0) mlog( MLOG_NORMAL | MLOG_INV, _( "INV: idx_put_sesstime failed in " "inv_stream_close() \n") ); INVLOCK( fd, LOCK_EX ); if ((rval = GET_REC_NOLOCK( fd, &strm, sizeof( invt_stream_t ), tok->md_stream_off )) > 0 ) { if ( strm.st_interrupted != wasinterrupted ) { strm.st_interrupted = wasinterrupted; dowrite = BOOL_TRUE; } /* get the last media file to figure out what our last ino was. we have a pointer to that in the stream token */ if ( tok->md_lastmfile ){ if ( strm.st_endino.ino != tok->md_lastmfile->mf_endino.ino || strm.st_endino.offset != tok->md_lastmfile->mf_endino.offset) { mlog( MLOG_DEBUG | MLOG_INV, "INV: stream_close() " " - endinos dont match ! \n"); dowrite = BOOL_TRUE; strm.st_endino = tok->md_lastmfile->mf_endino; } } if (dowrite) { rval = PUT_REC_NOLOCK_SEEKCUR( fd, &strm, sizeof( invt_stream_t ), -(off64_t)(sizeof( invt_stream_t )) ); } } INVLOCK( fd, LOCK_UN ); if ( tok->md_lastmfile ) { free ( tok->md_lastmfile ); } memset( tok, 0, sizeof( invt_strdesc_entry_t ) ); free ( tok ); return ( rval < 0 ) ? BOOL_FALSE: BOOL_TRUE; } /*----------------------------------------------------------------------*/ /* */ /* */ /* */ /*----------------------------------------------------------------------*/ bool_t inv_put_mediafile( inv_stmtoken_t tok, uuid_t *moid, char *label, uint mfileindex, xfs_ino_t startino, off64_t startino_offset, xfs_ino_t endino, off64_t endino_offset, off64_t size, bool_t isgood, bool_t isinvdump) { invt_mediafile_t *mf; int rval; assert ( tok != INV_TOKEN_NULL ); assert ( tok->md_sesstok->sd_invtok->d_update_flag & FSTAB_UPDATED ); assert ( tok->md_sesstok->sd_invtok->d_stobj_fd >= 0 ); mf = (invt_mediafile_t *) calloc( 1, sizeof( invt_mediafile_t ) ); /* copy the media file information */ memcpy( &mf->mf_moid, moid, sizeof( uuid_t ) ); strcpy( mf->mf_label, label ); mf->mf_mfileidx = mfileindex; mf->mf_startino.ino = startino; mf->mf_startino.offset = startino_offset; mf->mf_endino.ino = endino; mf->mf_endino.offset = endino_offset; mf->mf_size = size; mf->mf_flag = 0; if ( isgood ) mf->mf_flag |= INVT_MFILE_GOOD; /* This flag is used to indicate the media file that contains the dump of the sessioninfo structure that contains all but this media file */ if ( isinvdump ) mf->mf_flag |= INVT_MFILE_INVDUMP; INVLOCK( tok->md_sesstok->sd_invtok->d_stobj_fd, LOCK_EX ); rval = stobj_put_mediafile( tok, mf ); INVLOCK( tok->md_sesstok->sd_invtok->d_stobj_fd, LOCK_UN ); /* we dont free the mfile here. we always keep the last mfile around, inside the inv_stmtoken, and when we add a new mfile, we free the previous one. The last one is freed in stream_close() */ return ( rval < 0 ) ? BOOL_FALSE: BOOL_TRUE; } /*----------------------------------------------------------------------*/ /* inv_get_sessioninfo */ /* */ /* This is to be called after a write-session is complete, but before it*/ /* is closed. ie. the token must still be valid, and all the streams */ /* and their mediafiles put in the inventory. */ /* */ /* On return, the buffer will be filled with all the data pertinent to */ /* the session referred to by the session token. The application of this*/ /* is to dump the inventory of a session to a media object. */ /*----------------------------------------------------------------------*/ bool_t inv_get_sessioninfo( inv_sestoken_t tok, void **bufpp, /* buf to fill */ size_t *bufszp )/* size of that buffer */ { invt_session_t ses; invt_seshdr_t hdr; bool_t rval; int fd; assert( tok != INV_TOKEN_NULL ); assert( tok->sd_invtok ); *bufpp = NULL; *bufszp = 0; fd = tok->sd_invtok->d_stobj_fd; INVLOCK( fd, LOCK_SH ); /* Next we get the session header, and the session information. Then we can figure out how much space to allocate */ if ( stobj_get_sessinfo( tok, &hdr, &ses ) <= 0 ) { INVLOCK( fd, LOCK_UN ); return BOOL_FALSE; } rval = stobj_pack_sessinfo( fd, &ses, &hdr, bufpp, bufszp ); INVLOCK( fd, LOCK_UN ); return rval; } /*----------------------------------------------------------------------*/ /* inv_put_sessioninfo */ /* */ /* This is used in reconstructing an inventory from dumped media objects*/ /* */ /* Most importantly, note that this is not in anyway an alternative to */ /* inv_open_writesession() - that is called while the dump is in progr- */ /* ess. This is really inv_put_dumpedsession(); We just didn't want to */ /* be *that* dump-specific :) */ /*----------------------------------------------------------------------*/ bool_t inv_put_sessioninfo( invt_sessinfo_t *s ) { static bool_t invdir_ok = BOOL_FALSE; if ( !invdir_ok ) { if ( make_invdirectory( INV_SEARCH_N_MOD ) < 0 ) return BOOL_FALSE; else invdir_ok = BOOL_TRUE; } return insert_session( s ); } /*----------------------------------------------------------------------*/ /* inv_free_session */ /* */ /* free the inv_session structure allocated as a result of calls to */ /* inv_get_session_byuuid, etc. */ /*----------------------------------------------------------------------*/ void inv_free_session( inv_session_t **ses) { uint i; assert(ses); assert(*ses); for ( i = 0; i < (*ses)->s_nstreams; i++ ) { /* the array of mediafiles is contiguous */ free ((*ses)->s_streams[i].st_mediafiles); } /* all streams are contiguous too */ free ((*ses)->s_streams); free (*ses); *ses = NULL; } /*----------------------------------------------------------------------*/ /* inv_lasttime_level_lessthan */ /* */ /* Given a file system uuid, token that refers to a file system, and a */ /* level, tm is populated with last time when a session of a lesser */ /* level was done. */ /* */ /* Returns TRUE on success. */ /*----------------------------------------------------------------------*/ bool_t inv_lasttime_level_lessthan( uuid_t *fsidp, inv_idbtoken_t tok, u_char level, time32_t **tm) { int rval; if ( tok != INV_TOKEN_NULL ) { rval = search_invt(fsidp, tok->d_invindex_fd, &level, (void **)tm, (search_callback_t)tm_level_lessthan); return ( rval < 0) ? BOOL_FALSE: BOOL_TRUE; } return invmgr_query_all_sessions(fsidp, /* fs uuid ptr */ (void *)&level, /* in */ (void **)tm, /* out */ (search_callback_t)tm_level_lessthan); } /*----------------------------------------------------------------------*/ /* inv_lastsession_level_lessthan */ /* */ /* Given a file system uuid, token that refers to a file system, and a */ /* level, ses is populated with a session of lesser than the level */ /* passed in. */ /* */ /* Returns FALSE on an error, TRUE if not. If (*ses) is NULL, then the */ /* search failed. */ /*----------------------------------------------------------------------*/ bool_t inv_lastsession_level_lessthan( uuid_t *fsidp, inv_idbtoken_t tok, u_char level, inv_session_t **ses) { int rval; if ( tok != INV_TOKEN_NULL ) { rval = search_invt(fsidp, tok->d_invindex_fd, &level, (void **)ses, (search_callback_t)lastsess_level_lessthan); return ( rval < 0) ? BOOL_FALSE: BOOL_TRUE; } return invmgr_query_all_sessions(fsidp, /* fs uuid */ (void *)&level, /* in */ (void **)ses, /* out */ (search_callback_t)lastsess_level_lessthan); } /*----------------------------------------------------------------------*/ /* inv_lastsession_level_equalto */ /* */ /* Given a file system uuid, token that refers to a file system, and a */ /* level, this populates ses with last time when a session of a lesser */ /* level was done. */ /* */ /* Return FALSE on an error, TRUE if not. If (*ses) is NULL, then the */ /* search failed. */ /*----------------------------------------------------------------------*/ bool_t inv_lastsession_level_equalto( uuid_t *fsidp, inv_idbtoken_t tok, u_char level, inv_session_t **ses ) { int rval; if ( tok != INV_TOKEN_NULL ) { rval = search_invt(fsidp, tok->d_invindex_fd, &level, (void **)ses, (search_callback_t)lastsess_level_equalto); return ( rval < 0) ? BOOL_FALSE: BOOL_TRUE; } return invmgr_query_all_sessions(fsidp, /* fs uuid */ (void *)&level, /* in */ (void **)ses, /* out */ (search_callback_t)lastsess_level_equalto); } /*----------------------------------------------------------------------*/ /* inv_getsession_byuuid */ /* */ /* Given a file system uuid and a session uuid , ses is populated with */ /* the session that contains the matching system uuid. */ /* */ /* Returns FALSE on an error, TRUE if the session was found. */ /*----------------------------------------------------------------------*/ bool_t inv_get_session_byuuid( uuid_t *fsidp, uuid_t *sesid, inv_session_t **ses) { return invmgr_query_all_sessions(fsidp, /* fs uuid */ (void *)sesid, /* in */ (void **)ses, /* out */ (search_callback_t)stobj_getsession_byuuid); } /*----------------------------------------------------------------------*/ /* inv_getsession_bylabel */ /* */ /* Given a file system uuid and a session uuid, ses is populated with */ /* the session that contains the matching system label. */ /* */ /* Returns FALSE on an error, TRUE if the session was found. */ /*----------------------------------------------------------------------*/ bool_t inv_get_session_bylabel( uuid_t *fsidp, char *session_label, inv_session_t **ses) { return invmgr_query_all_sessions(fsidp, /* fs uuid */ (void *)session_label, /* in */ (void **)ses, /* out */ (search_callback_t)stobj_getsession_bylabel); } /*----------------------------------------------------------------------*/ /* inv_delete_mediaobj */ /* */ /* We delete all the media files that are stored in the given mobj, and */ /* delete them one by one. We delete the session information only when */ /* all its mediafiles are deleted. This is because a single session can */ /* be striped across multiple mediaobjects. */ /*----------------------------------------------------------------------*/ bool_t inv_delete_mediaobj( uuid_t *moid ) { inv_oflag_t forwhat = INV_SEARCH_N_MOD; /* forall fsids (fs) in fstab { open invindex table (t) forall indices (i) in t { open stobj (st) forall sessions (s) in st { forall streams (strm) in s { forall mediafiles (m) in strm { if (m.mediaobj == moid) { // delete m if ( --strm.nmediafiles == 0 ) if ( --s.nstreams == 0 ) delete-session (s) } } } } } */ invt_counter_t *cnt; invt_fstab_t *arr; int numfs, i, fd, invfd; char fname[INV_STRLEN]; fd = fstab_getall( &arr, &cnt, &numfs, forwhat ); if ( fd < 0 || numfs <= 0 ) { mlog( MLOG_NORMAL | MLOG_INV, _("INV: Error in fstab\n") ); return BOOL_FALSE; } close( fd ); for ( i = 0; i < numfs; i++) { if ( fstab_get_fname( &arr[i].ft_uuid, fname, (inv_predicate_t)INV_BY_UUID, forwhat ) < 0 ) { mlog( MLOG_NORMAL | MLOG_INV, _( "INV: Cant get inv-name for uuid\n") ); return BOOL_FALSE; } strcat( fname, INV_INVINDEX_PREFIX ); invfd = open( fname, INV_OFLAG(forwhat)); if ( invfd < 0 ) { mlog( MLOG_NORMAL | MLOG_INV, _( "INV: Open failed on %s\n"), fname ); return BOOL_FALSE; } if (search_invt(&arr[i].ft_uuid, invfd, NULL, (void **)&moid, (search_callback_t)stobj_delete_mobj) < 0 ) return BOOL_FALSE; /* we have to delete the session, etc */ close( invfd ); } return BOOL_TRUE; } #define I_IFOUND 0x01 #define I_IDONE 0x02 #define I_IERR 0x04 static const char *myopts[] = { #define OPT_MNT 0 "mnt", #define OPT_FSID 1 "fsid", #define OPT_DEV 2 "dev", #define OPT_DEPTH 3 "depth", #define OPT_MOBJID 4 "mobjid", #define OPT_MOBJLABEL 5 "mobjlabel", #define OPT_FSTAB 6 "fstab", #define OPT_INVIDX 7 "invidx", #define OPT_INVCHECK 8 "check", #define OPT_INVLEVEL 9 "level", NULL }; int inv_getopt(int argc, char **argv, invt_pr_ctx_t *prctx) { int rval = 0; void *fs = 0; char *options, *value; extern char *optarg; extern int optind, opterr; inv_predicate_t bywhat = -1; int c, d; uuid_t fsid; int npreds = 0; int npreds2 = 0; char invoptstring[128], *rptr, *wptr; optind = 1; opterr = 0; /* * getopt doesn't handle both '-I' and '-I w/subopts' so... * First set I_IFOUND if -I is set at all (with or without * any suboptions). Do this by taking out the ':' so getopt * accepts it. Later, reset opts and go through again to * pick off any subopts. */ strcpy(invoptstring, GETOPT_CMDSTRING); wptr = strchr(invoptstring, 'I'); if (wptr != NULL) { wptr++; rptr = wptr + 1; while (*wptr != '\0') *wptr++ = *rptr++; while ( ( c = getopt( argc, argv, invoptstring)) != EOF ) { switch ( c ) { case GETOPT_INVPRINT: prctx->depth = 0; rval |= I_IFOUND ; break; } } optind = 1; opterr = 0; optarg = NULL; } while ( ( c = getopt( argc, argv, GETOPT_CMDSTRING )) != EOF ) { switch ( c ) { case GETOPT_INVPRINT: rval |= I_IFOUND ; if ((options = optarg) == NULL) break; while (*options != '\0') { d = getsubopt(&options,(constpp)myopts,&value); if (value == NULL && d != OPT_FSTAB && d != OPT_INVIDX && d != OPT_INVCHECK) continue; switch( d ) { /* process mntpt option */ case OPT_MNT: bywhat = (inv_predicate_t) INV_BY_MOUNTPT; fs = value; npreds++; break; /* process fsid option */ case OPT_FSID: bywhat = (inv_predicate_t) INV_BY_UUID; npreds++; uuid_parse(value, fsid); fs = fsid; break; case OPT_DEV: /* process dev option */ bywhat = (inv_predicate_t) INV_BY_DEVPATH; fs = value; npreds++; break; case OPT_DEPTH: prctx->depth = atoi(value); if (prctx->depth < 0 || prctx->depth > 4 ) prctx->depth = 0; break; case OPT_MOBJID: { uuid_t *u; u = malloc ( sizeof( uuid_t ) ); uuid_parse(value, *u); prctx->mobj.type = INVT_MOID; prctx->mobj.value = (void *)u; } npreds2++; break; case OPT_MOBJLABEL: prctx->mobj.type = INVT_LABEL; prctx->mobj.value = (void *)value; npreds2++; break; case OPT_FSTAB: prctx->fstab = BOOL_TRUE; break; case OPT_INVIDX: prctx->invidx = BOOL_TRUE; break; case OPT_INVCHECK: prctx->invcheck = BOOL_TRUE; break; case OPT_INVLEVEL: prctx->level = atoi(value); break; default: if ( strlen(value) == 1 && atoi(value) < PR_MAXDEPTH ) prctx->depth = atoi(value); else { mlog( MLOG_NORMAL | MLOG_INV, _( "INV: invalid sub-option %s" " for -I option\n"), value ); rval |= I_IERR; } break; } } break; /* case GETOPT_INVPRINT */ } } if (npreds > 1) { mlog( MLOG_NORMAL | MLOG_INV, _( "INV: Only one of mnt=,dev= and fsid=value can be used.\n") ); rval |= I_IERR; } else if (npreds2 > 1) { mlog( MLOG_NORMAL | MLOG_INV, _( "INV: Only one of mobjid= and mobjlabel= can be used.\n") ); rval |= I_IERR; } else if ( (rval & I_IFOUND) && !(rval & I_IERR) && fs && ! prctx->fstab && ! prctx->invcheck) { inv_idbtoken_t tok; /* A filesystem could be backed up, mkfs'ed then restored * to a new UUID value. Therefore, we can't simply stop * when we find the first matching mount point (pv564234). * This code loops through all filesystems and does the * comparison by hand. */ if (bywhat == INV_BY_MOUNTPT) { int fd, numfs, i; invt_fstab_t *arr = NULL; invt_counter_t *cnt = NULL; inv_oflag_t forwhat = INV_SEARCH_ONLY; fd = fstab_getall( &arr, &cnt, &numfs, forwhat ); free( cnt ); rval |= I_IERR; /* Cleared if successful */ if ( fd >= 0 ) { for ( i = 0; i < numfs; i++ ) { tok = inv_open( (inv_predicate_t )INV_BY_UUID, INV_SEARCH_ONLY, &arr[i].ft_uuid ); if ( tok == INV_TOKEN_NULL ) break; if ( STREQL( arr[i].ft_mountpt, fs) ) { prctx->index = i; invmgr_inv_print( tok->d_invindex_fd, prctx ); rval &= ~(I_IERR); } inv_close( tok ); } free ( arr ); rval |= I_IDONE; } if ( (rval&I_IERR) ) { mlog( MLOG_NORMAL | MLOG_INV, _( "INV: open failed on mount point \"%s\"\n"), fs); } return rval; } /* We have to print only one file system to print by UUID */ tok = inv_open( bywhat, INV_SEARCH_ONLY, fs); if ( tok != INV_TOKEN_NULL ) { prctx->index = 0; invmgr_inv_print(tok->d_invindex_fd, prctx); inv_close( tok ); rval |= I_IDONE; } else { mlog( MLOG_NORMAL | MLOG_INV, _( "INV: open failed on file system id \"%s\"\n"), fs); rval |= I_IERR; } } return rval; } /* This prints out all the sessions of a filesystem that are in the inventory */ bool_t inv_DEBUG_print( int argc, char **argv ) { invt_counter_t *cnt = NULL; invt_fstab_t *arr = NULL; int fd, numfs, i; inv_idbtoken_t tok; int rval; invt_pr_ctx_t prctx; inv_oflag_t forwhat = INV_SEARCH_ONLY; prctx.mobj.type = INVT_NULLTYPE; prctx.fstab = prctx.invidx = prctx.invcheck = BOOL_FALSE; prctx.level = PR_MAXLEVEL; /* If user didnt indicate -i option, we can't do anything */ rval = inv_getopt( argc, argv, &prctx ); if (!prctx.invcheck && ! prctx.fstab) { if (! (rval & I_IFOUND)) { return BOOL_TRUE; } else if ( rval & I_IERR || rval & I_IDONE ) { return BOOL_FALSE; } } fd = fstab_getall( &arr, &cnt, &numfs, forwhat ); free( cnt ); if ( fd >= 0 ) { if (prctx.fstab) { fstab_DEBUG_print( arr, numfs ); if (! prctx.invidx) return BOOL_FALSE; } for ( i = 0; i < numfs; i++ ) { tok = inv_open( ( inv_predicate_t )INV_BY_UUID, forwhat, &arr[i].ft_uuid ); if ( tok == INV_TOKEN_NULL ) { free ( arr ); return BOOL_FALSE; } if (prctx.invcheck) { mlog( MLOG_VERBOSE | MLOG_INV, _( "INV: checking fs \"%s\"\n"), &arr[i].ft_mountpt ); invmgr_inv_check(tok->d_invindex_fd); } else { prctx.index = i; invmgr_inv_print( tok->d_invindex_fd, &prctx ); } inv_close( tok ); } } return BOOL_FALSE; } #undef I_IFOUND #undef I_IDONE #undef I_IERR xfsdump-3.1.6+nmu1/inventory/getopt.h0000644000000000000000000000365612607344125014477 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GETOPT_H #define GETOPT_H /* getopt.h common getopt command string * * several modules parse the command line looking for arguments specific to * that module. Unfortunately, each of the getopt(3) calls needs the * complete command string, to know how to parse. This file's purpose is * to contain that command string. It also abstracts the option letters, * facilitating easy changes. */ #define GETOPT_CMDSTRING "gwrqdL:u:l:s:t:v:m:f:i" #define GETOPT_DUMPDEST 'f' /* dump dest. file (drive.c) */ #define GETOPT_LEVEL 'l' /* dump level (content_inode.c) */ #define GETOPT_SUBTREE 's' /* subtree dump (content_inode.c) */ #define GETOPT_VERBOSITY 'v' /* verbosity level (0 to 4 ) */ #define GETOPT_DUMPLABEL 'L' /* dump session label (global.c) */ #define GETOPT_MEDIALABEL 'M' /* media object label (content.c) */ #define GETOPT_RESUME 'R' /* resume intr dump (content_inode.c) */ #define GETOPT_INVPRINT 'i' /* just display the inventory */ /* * f - dump destination: drive.c * l - dump level content_inode.c * s - subtree content.c * v - verbosity mlog.c * L - dump session label global.c * M - media object label media.c * R - resume interrupted dump content_inode.c */ #endif /* GETOPT_H */ xfsdump-3.1.6+nmu1/inventory/inv_fstab.c0000644000000000000000000001445012620476160015135 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "types.h" #include "mlog.h" #include "inv_priv.h" /*----------------------------------------------------------------------*/ /* */ /* */ /* */ /*----------------------------------------------------------------------*/ int fstab_getall( invt_fstab_t **arr, invt_counter_t **cnt, int *numfs, inv_oflag_t forwhat ) { int fd; fd = open ( INV_FSTAB, INV_OFLAG(forwhat) ); if ( fd < 0 ) return -1; /* if ENOENT, fstab_put_entry will CREAT */ INVLOCK( fd, LOCK_EX ); if (( *numfs = GET_ALLHDRS_N_CNTS_NOLOCK( fd, (void**) arr, (void **)cnt, sizeof( invt_fstab_t ), sizeof( invt_counter_t ) ) ) < 0 ) { mlog( MLOG_NORMAL | MLOG_INV, _( "INV: couldn't get fstab headers\n") ); } #ifdef INVT_DEBUG mlog( MLOG_NITTY | MLOG_INV, "INV: number of filesystems in fstab %d\n", *numfs ); #endif /* fstab is left locked EX on exit. The caller takes does the unlocking */ return fd; } /*----------------------------------------------------------------------*/ /* */ /* */ /* caller takes the responsibility of calling this only when the FSTAB_ */ /* UPDATED flag in the inv_idbtoken is off, and also of updating the */ /* flag upon successful return from put_fstab_entry. */ /*----------------------------------------------------------------------*/ int fstab_put_entry( uuid_t *fsidp, char *mntpt, char *dev, inv_oflag_t forwhat ) { int numfs, i, fd; invt_counter_t *cnt; invt_fstab_t *arr; int rval = 1; assert( forwhat != INV_SEARCH_ONLY ); /* fd is locked on succesful return */ fd = fstab_getall( &arr, &cnt, &numfs, forwhat ); if ( fd < 0 ) { if ( errno != ENOENT ) { return -1; } if ((fd = open( INV_FSTAB, INV_OFLAG(forwhat) | O_CREAT, S_IRUSR|S_IWUSR )) < 0 ) { INV_PERROR ( INV_FSTAB ); return -1; } INVLOCK( fd, LOCK_EX ); fchmod( fd, INV_PERMS ); cnt = (invt_counter_t *) malloc( sizeof ( invt_counter_t ) ); cnt->ic_maxnum = -1; cnt->ic_curnum = 0; cnt->ic_vernum = INV_VERSION; } else if ( numfs > 0 ) { for (i = 0; i < numfs; i++) { if ( uuid_compare( *fsidp, arr[ i ].ft_uuid ) == 0 ) { /* if ( ( STREQL( arr[i].ft_mountpt, mntpt ) ) && ( STREQL( arr[i].ft_devpath, dev ) ) ) */ free ( arr ); free ( cnt ); close( fd ); return 1; } } /* entry not found. just follow thru to create a new one */ free ( arr ); } /* make a new fstab entry and insert it at the end. the table is locked EXclusively at this point */ { invt_fstab_t ent; off64_t hoff; memcpy( &ent.ft_uuid, fsidp, sizeof( uuid_t ) ); strcpy( ent.ft_mountpt, mntpt ); strcpy( ent.ft_devpath, dev ); /* increase the number of entries first */ #ifdef INVT_DEBUG mlog( MLOG_NITTY | MLOG_INV,"INV: putting new fstab entry for %s ....\n", mntpt); #endif cnt->ic_curnum++; hoff = (off64_t) ( sizeof( invt_counter_t ) + (size_t)( cnt->ic_curnum - 1 ) * sizeof( invt_fstab_t ) ); rval = PUT_COUNTERS( fd, cnt ); if ( rval > 0 ) { rval = PUT_REC_NOLOCK( fd, &ent, sizeof( ent ), hoff ); } } INVLOCK( fd, LOCK_UN ); free ( cnt ); close ( fd ); return rval; } int fstab_get_fname( void *pred, char *fname, inv_predicate_t bywhat, inv_oflag_t forwhat) { uuid_t *uuidp = 0; char uuidstr[UUID_STR_LEN + 1]; invt_fstab_t *arr; if (bywhat != INV_BY_UUID) { int numfs, i, fd; invt_counter_t *cnt; /* on sucessful return fd is locked */ fd = fstab_getall( &arr, &cnt, &numfs, forwhat ); if ( fd < 0 ) return -1; if ( numfs <= 0 ) { mlog( MLOG_NORMAL | MLOG_INV, _( "INV: No recorded filesystems in" " inventory's fstab.\n") ); return -1; } INVLOCK( fd, LOCK_UN ); close ( fd ); free ( cnt ); /* we dont need it */ /* first get hold of the uuid for this mount point/device */ for (i = 0; i < numfs; i++) { if ( ( bywhat == INV_BY_MOUNTPT && ( STREQL( arr[i].ft_mountpt, pred ) )) || ( bywhat == INV_BY_DEVPATH && ( STREQL( arr[i].ft_devpath, pred ) )) ) { uuidp = &arr[i].ft_uuid; break; } } #ifdef INVT_DEBUG if (! uuidp ) mlog( MLOG_DEBUG | MLOG_INV,"INV: get_fname: unable to find %s" " in the inventory\n", (char *)pred); #endif } else { uuidp = (uuid_t *)pred; } if (! uuidp ) return -1; uuid_unparse( *uuidp, uuidstr ); strncpy ( fname, INV_DIRPATH, INV_STRLEN ); strcat ( fname, "/" ); strcat ( fname, uuidstr); if ( bywhat != INV_BY_UUID ) free ( arr ); assert( (int) strlen( fname ) < INV_STRLEN ); return 1; } void fstab_DEBUG_print( invt_fstab_t *arr, int num ) { int i; char str[UUID_STR_LEN + 1]; mlog( MLOG_NORMAL | MLOG_INV, _("\n\n--------- fstab ------------\n") ); for ( i = 0; i < num; i++ ) { printf( _("Mount\t%s\n"), arr[i].ft_mountpt ); printf( _("Dev\t%s\n"), arr[i].ft_devpath ); uuid_unparse( arr[i].ft_uuid, str ); printf( _("FSid\t%s\n\n"), str ); } mlog( MLOG_NORMAL | MLOG_INV, "\n---------========------------\n" ); } xfsdump-3.1.6+nmu1/inventory/testmain.c0000644000000000000000000002553612620476160015015 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include "config.h" #include "types.h" #include "mlog.h" #include "getopt.h" #include "inv_priv.h" /*----------------------------------------------------------------------*/ /* These are hacked up routines meant ONLY for low-level debugging */ /* purposes. These are mostly unused since most the debugging code */ /* was ported to xfsdump and xfsrestore as formal suboptions of -I. */ /*----------------------------------------------------------------------*/ static char *mnt_str[] = { "/usr/lib", "/usr", "/u/sw/courses", "/pro/leda", "/root", "/a/xfs/xlv/e", "/dana/hates/me", "/the/krays" }; static char *dev_str[] = { "/dev/usr/lib", "/dev/usr", "/dev/u/sw/courses", "/dev/pro/leda", "/dev/root", "/dev/a/xfs/xlv/e", "/dev/dana/hates/me", "/dev/the/krays" }; typedef enum { BULL = -1, WRI, REC, QUE, DEL, MP, QUE2 } hi; void usage( void ); char *progname; char *sesfile; void CREAT_mfiles( inv_stmtoken_t tok, uuid_t *moid, ino_t f, ino_t n ) { uuid_t labelid; char label[128], strbuf[20]; char *str; unsigned int stat; uuid_create( &labelid, &stat ); uuid_to_string( &labelid, &str, &stat ); strncpy( strbuf, str, 8 ); free (str); strbuf[8] = '\0'; sprintf(label,"%s_%s (%d-%d)\0","MEDIA_FILE", strbuf, (int)f, (int)n ); inv_put_mediafile( tok, moid, label, 12, f, 0, n, 0, 0xffff, BOOL_TRUE, BOOL_FALSE ); } typedef struct ses{ uuid_t fsid; size_t sz; char *buf; } ses; #define SESLIM 240 int recons_test( int howmany ) { int fd, i, rval = 1; ses sarr[ SESLIM]; fd = open( sesfile, O_RDONLY ); for ( i=0; i 0 ); assert( sarr[i].sz > 0 ); sarr[i].buf = calloc( 1, sarr[i].sz ); rval = get_invtrecord( fd, sarr[i].buf, sarr[i].sz, 0, SEEK_CUR, BOOL_FALSE ); assert( rval > 0 ); } for ( i=0; id_invindex_fd); return 1; } for (i = 7; i<8; i++) { printf("\n\n\n----------------------------------\n" "$ Searching fs %s\n", mnt_str[7-i] ); tok = inv_open( INV_BY_MOUNTPT, INV_SEARCH_ONLY, mnt_str[7-i] ); if (! tok ) return -1; prctx.index = i; if (level == -1 ) invmgr_inv_print( tok->d_invindex_fd, &prctx ); else { if (inv_lasttime_level_lessthan( tok, level, &tm ) && tm) { printf("\n\nTIME %s %ld\n", ctime(tm), (long) *tm ); free (tm); } if (inv_lastsession_level_lessthan( tok, level, &ses ) && ses) { DEBUG_sessionprint( ses, 99, &prctx); free ( ses->s_streams ); free ( ses ); } if (inv_lastsession_level_equalto( tok, level, &ses ) && ses) { printf("Gotcha\n"); DEBUG_sessionprint( ses, 99, &prctx ); free ( ses->s_streams ); free ( ses ); } } inv_close( tok ); } return 1; } /*----------------------------------------------------------------------*/ /* */ /* */ /* */ /*----------------------------------------------------------------------*/ int write_test( int nsess, int nstreams, int nmedia, int dumplevel ) { int i,j,k,m,fd; unsigned int stat; uuid_t *fsidp; inv_idbtoken_t tok1; inv_sestoken_t tok2; inv_stmtoken_t tok3; char *dev, *mnt; char label[120]; uuid_t fsidarr[8], labelid; uuid_t sesidarr[8]; char *str; char strbuf[128]; void *bufp; size_t sz; int rfd; #ifdef FIRSTTIME printf("first time!\n"); for (i=0; i<8; i++) { uuid_create( &fsidarr[i], &stat ); assert ( stat == uuid_s_ok ); uuid_create( &sesidarr[i], &stat ); assert ( stat == uuid_s_ok ); } fd = open( "uuids", O_RDWR | O_CREAT ); PUT_REC(fd, (void *)fsidarr, sizeof (uuid_t) * 8, 0L ); PUT_REC(fd, (void *)sesidarr, sizeof (uuid_t) * 8, sizeof (uuid_t) * 8 ); close(fd); #endif fd = open("uuids", O_RDONLY ); GET_REC( fd, fsidarr, sizeof (uuid_t) * 8, 0L ); GET_REC( fd, sesidarr, sizeof (uuid_t) * 8, sizeof (uuid_t) * 8 ); close(fd); #ifdef RECONS rfd = open( sesfile, O_RDWR | O_CREAT ); fchmod( rfd, INV_PERMS ); #endif for ( i = 0; i < nsess; i++ ) { j = i % 8; /*mnt = mnt_str[j]; dev = dev_str[7-j];*/ mnt = mnt_str[0]; dev = dev_str[7]; fsidp = &fsidarr[0]; /* j */ tok1 = inv_open( INV_BY_UUID, INV_SEARCH_N_MOD, fsidp ); assert (tok1 != INV_TOKEN_NULL ); uuid_create( &labelid, &stat ); uuid_to_string( &labelid, &str, &stat ); strncpy( strbuf, str, 8 ); free (str); strbuf[8] = '\0'; sprintf(label,"%s_%s (%d)\0","SESSION_LABEL", strbuf, i ); tok2 = inv_writesession_open(tok1, fsidp, &labelid, label, (bool_t)i%2, (bool_t)i%2, dumplevel, nstreams, time(NULL), mnt, dev ); assert (tok2 != INV_TOKEN_NULL ); for (m = 0; m -s " "-t -m \n", optarg ); } int mp_test(int nstreams) { #if 0 tok1 = inv_open( INV_BY_UUID, fsidp ); assert (tok1 != INV_TOKEN_NULL ); tok2 = inv_writesession_open(tok1, fsidp, &labelid, label, (bool_t)i%2, (bool_t)i%2, dumplevel, nstreams, time(NULL), mnt, dev ); assert (tok2 != INV_TOKEN_NULL ); for (m = 0; m 1 ); mlog_init( argc, argv ); if (! inv_DEBUG_print(argc, argv)) return 0; optind = 1; optarg = 0; while( ( cc = getopt( argc, argv, GETOPT_CMDSTRING)) != EOF ) { switch ( cc ) { case 'w': op = WRI; break; case 'r': op = REC; break; case 'q': op = QUE; break; case 'd': op = DEL; break; case 'z': op = MP; break; case 'g': op = QUE2; break; case 'u': uuid = optarg; break; case 'L': label = optarg; break; case 's': nsess = atoi(optarg); break; case 'l': level = atoi(optarg); break; case 't': nstreams = atoi(optarg); break; case 'm': nmedia = atoi( optarg ); break; case 'v': break; case 'f': sesfile = optarg; break; default: usage(); break; } } if ( op == WRI ) rval = write_test( nsess, nstreams, nmedia, level ); else if ( op == QUE ) rval = query_test( level ); else if ( op == REC ) rval = recons_test( nsess ); else if ( op == DEL ) rval = delete_test( nsess ); else if ( op == MP ) rval = mp_test (nstreams); else if ( op == QUE2 ) { if (uuid) rval = sess_queries_byuuid(uuid); else if (label) rval = sess_queries_bylabel(label); } else usage(); if (rval < 0 ) printf( "aborted\n"); else printf( "done\n" ); } xfsdump-3.1.6+nmu1/inventory/inv_oref.h0000644000000000000000000002100712620476160014772 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _INV_OREF_H__ #define _INV_OREF_H__ #include "inv_priv.h" #define INVT_OTYPE_INVIDX 0x0001 #define INVT_OTYPE_FSTAB 0x0002 #define INVT_OTYPE_STOBJ 0x0004 #define INVT_OTYPE_MASK INVT_OTYPE_INVIDX | INVT_OTYPE_FSTAB | \ INVT_OTYPE_STOBJ #define INVT_RES_COUNTERS 0x0010 #define INVT_RES_ENTRIES 0x0020 #define INVT_STOBJ_RES_HDRS 0x0040 #define INVT_STOBJ_RES_SESSIONS 0x0080 #define INVT_STOBJ_RES_STRMS 0x0100 #define INVT_STOBJ_RES_MFILES 0x0200 #define INVT_RES_MASK 0x0FF0 /* Indicates if either its child or its parent has been resolved. Only one kin per object can exist. i.e. a child cant have children.*/ #define INVT_RES_CHILD 0x1000 #define INVT_RES_PARENT 0x2000 #define INVT_RES_KIN INVT_RES_PARENT | INVT_RES_CHILD typedef __uint32_t invt_objtype_t; #define INVT_LOCKED 0x0001 typedef struct invt_oref { int fd; /* counters - contains curnum, maxnum, etc */ union { invt_sescounter_t *sescnt; invt_counter_t *cnt; } oref_cnt_u; /* entries pointing at other invt objects */ union { invt_entry_t *ent; invt_fstab_t *fstabent; struct { invt_seshdr_t *hdr; invt_session_t *ses; invt_stream_t *strm; invt_mediafile_t *mfile; } eu_sessent; } oref_ent_u; union { struct invt_oref *invidx; /* parent */ struct invt_oref *stobj; /* child */ } oref_kin_u; /* indicates level of depth this has been resolved to */ invt_objtype_t type; int lockflag; void *token; } invt_oref_t; #define eu_hdr oref_ent_u.eu_sessent.hdr #define eu_ses oref_ent_u.eu_sessent.ses #define eu_strm oref_ent_u.eu_sessent.strm #define eu_mfile oref_ent_u.eu_sessent.mfile #define cu_cnt oref_cnt_u.cnt #define cu_sescnt oref_sescnt_u.sescnt #define ku_invidx oref_kin_u.invidx #define ku_stobj oref_kin_u.stobj /* * See if the object has been resolved to the given level. */ #define OREF_ISRESOLVED(oref, to_this_type) \ ((oref)->type & (to_this_type)) #define OREF_INIT(oref) \ { bzero((oref), sizeof(invt_oref_t)); \ (oref)->fd = -1; } #define OREF_DESTROY(oref) \ { if (OREF_ISRESOLVED(oref, INVT_RES_CHILD))\ _oref_free((oref)->ku_stobj, BOOL_TRUE); \ else if (OREF_ISRESOLVED(oref, INVT_RES_PARENT)) \ _oref_free((oref)->ku_invidx, BOOL_TRUE); \ _oref_free(oref, BOOL_FALSE); } #define OREF_COPY(src_oref, dst_oref) \ (bcopy((src_oref), (dst_oref), sizeof(invt_oref_t))) /* * For locking/unlocking orefs - mode { LOCK_SH, LOCK_EX, LOCK_UN } */ #define OREF_LOCKMODE_EQL(oref, mode) ((oref)->lockflag == mode ) #define OREF_ISLOCKED(oref) ((oref)->lockflag == 0 || (oref)->lockflag == LOCK_UN) #define OREF_LOCK(oref, mode) \ { if (! OREF_LOCKMODE_EQL(oref,mode)) \ { INVLOCK((oref)->fd, mode); \ (oref)->lockflag = mode; } \ } #define OREF_UNLOCK(oref) OREF_LOCK(oref, LOCK_UN) #define OREF_INVIDX_LOCK(oref, mode) \ { if (OREF_ISRESOLVED(oref, INVT_OTYPE_INVIDX)) \ OREF_LOCK(oref, mode); \ else if (OREF_ISRESOLVED(oref, INVT_OTYPE_STOBJ)) \ OREF_LOCK((oref)->invidx, mode); } #define OREF_STOBJ_LOCK(oref, mode) \ { if (OREF_ISRESOLVED(oref, INVT_OTYPE_STOBJ)) \ OREF_LOCK(oref, mode); \ else if (OREF_ISRESOLVED(oref, INVT_OTYPE_INVIDX)) \ OREF_LOCK((oref)->stobj, mode); } #define OREF_SET_TYPE(oref, type) \ { (oref)->type |= (type); } #define OREF_UNSET_TYPE(oref, type) \ { (oref)->type &= ~(type); } #define OREF_SET_TOKEN(oref, tok) \ { (oref)->token = tok; } #define OREF_SET_CNT(oref, cnt) \ { assert (OREF_ISRESOLVED(oref, INVT_OTYPE_MASK)); \ ((oref)->type & INVT_OTYPE_STOBJ) ? \ (oref)->cu_sescnt = (cnt): (oref)->cu_cnt = (cnt); \ (oref)->type |= INVT_RES_COUNTERS; } #define OREF_SET_ENTRIES(oref, ents) \ { assert ((oref)->type & (INVT_OTYPE_INVIDX | INVT_OTYPE_FSTAB));\ assert ((oref)->type & INVT_RES_COUNTERS); \ ((oref)->type & INVT_OTYPE_INVIDX) ? \ (oref)->eu_ent = ents : (oref)->eu_fstabent = ents; \ (oref)->type |= INVT_RES_ENTRIES; } #define OREF_SET_HDRS(oref, hdrs) \ { assert ((oref)->type & INVT_OTYPE_STOBJ); \ assert ((oref)->type & INVT_RES_COUNTERS); \ (oref)->eu_hdr = hdrs; \ (oref)->type |= INVT_STOBJ_RES_HDRS; } #define OREF_SET_SESSIONS(oref, ses) \ { assert ((oref)->type & INVT_OTYPE_STOBJ); \ assert ((oref)->type & INVT_RES_COUNTERS); \ (oref)->eu_ses = ses; \ (oref)->type |= INVT_STOBJ_RES_SESSIONS; } #define OREF_SET_STRMS(oref, strms) \ { assert ((oref)->type & INVT_OTYPE_STOBJ); \ assert ((oref)->type & INVT_RES_COUNTERS); \ (oref)->eu_strm = strms; \ (oref)->type |= INVT_STOBJ_RES_STRMS; } #define OREF_SET_CHILD(oref, stobjref) \ { assert (! OREF_ISRESOLVED(oref, INVT_RES_KIN)); \ (oref)->ku_child = stobjref; \ (oref)->type |= INVT_RES_CHILD; } #define OREF_SET_PARENT(oref, invidxref) \ { assert (! OREF_ISRESOLVED(oref, INVT_RES_KIN)); \ (oref)->ku_parent = invidxref; \ (oref)->type |= INVT_RES_PARENT; } #define OREF_UNRESOLVE_CHILD(oref) \ { assert (OREF_ISRESOLVED(oref, INVT_RES_CHILD)); \ close((oref)->ku_child->fd); \ OREF_DESTROY((oref)->ku_child); \ (oref)->ku_child = 0; \ OREF_UNSET_TYPE(oref, INVT_RES_CHILD); } #define OREF_TYPE(oref) ((oref)->type) #define OREF_CNT_CURNUM(oref) \ ((oref)->type & INVT_OTYPE_STOBJ) ? \ (oref)->cu_sescnt->ic_curnum : (oref)->cu_cnt->ic_curnum #define OREF_CNT_MAXNUM(oref) \ ((oref)->type & INVT_OTYPE_STOBJ) ? \ (oref)->cu_sescnt->ic_maxnum : (oref)->cu_cnt->ic_maxnum #define OREF_ENTRIES(oref) \ ((oref)->type & INVT_OTYPE_INVIDX) ? \ (oref)->eu_ent : (oref)->eu_fstabent #define OREF_HDRS(oref) ((oref)->eu_hdr) #define OREF_SESSIONS(oref) ((oref)->eu_ses) #define OREF_STRMS(oref) ((oref)->eu_strm) #define OREF_MEDIAFILES(oref) ((oref)->eu_mfile) #define OREF_TOKEN(oref) ((oref)->token) /*----------------------------------------------------------------------*/ /* Function Prototypes */ /* */ /* */ /*----------------------------------------------------------------------*/ int oref_resolve( invt_oref_t *invidx, inv_predicate_t bywhat, void *pred); int oref_resolve_upto( invt_oref_t *obj, invt_objtype_t type); int oref_resolve_entries( invt_oref_t *obj); int oref_resolve_counters( invt_oref_t *obj); void _oref_free( invt_oref_t *obj, bool_t freethis); #ifdef NOTDEF extern int xlv_oref_resolve ( xlv_oref_t *oref, xlv_tab_vol_entry_t *tab_vol_entry); extern int xlv_oref_resolve_from_list ( xlv_oref_t *oref, xlv_oref_t *oref_list); /* * Prints out the object referenced by an oref. */ extern void xlv_oref_print (xlv_oref_t *oref, int p_mode); /* * An iterator that applies a user-supplied function and arg * to every volume element that makes up an object. * The user-supplied function returns 0 to continue with the * iteration. Return 1 to stop. */ typedef int (*XLV_OREF_PF) (xlv_oref_t *, void *); extern void xlv_for_each_ve_in_obj ( xlv_oref_t *oref, XLV_OREF_PF operation, void *arg); extern void xlv_for_each_ve_in_vol ( xlv_oref_t *oref, XLV_OREF_PF operation, void *arg); extern int xlv_for_each_ve_in_subvol ( xlv_oref_t *oref, XLV_OREF_PF operation, void *arg); extern int xlv_for_each_ve_in_plex ( xlv_oref_t *oref, XLV_OREF_PF operation, void *arg); /* * Returns 1 if the oref is a null reference; i.e., it has just * been XLV_OREF_INIT'ed and no new fields have been set. */ extern int xlv_oref_is_null (xlv_oref_t *oref); #endif /* NOTDEF */ #endif /* _INV_OREF_H_ */ xfsdump-3.1.6+nmu1/inventory/inv_idx.c0000644000000000000000000003657512620476160014636 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "types.h" #include "mlog.h" #include "inv_priv.h" /*----------------------------------------------------------------------*/ /* insert_invindexentry */ /* */ /* given a time, find the invindex that has the time-period it can fit */ /* into. */ /*----------------------------------------------------------------------*/ uint idx_insert_newentry( int fd, /* kept locked EX by caller */ int *stobjfd, /* OUT */ invt_entry_t *iarr, invt_counter_t *icnt, time32_t tm ) { uint i; inv_oflag_t forwhat = INV_SEARCH_N_MOD; /* invt_entry_t ient; ient.ie_timeperiod.tp_start = ient.ie_timeperiod.tp_end = tm; */ /* If time period of the new entry is before our first invindex, we have to insert a new invindex in the first slot */ if ( iarr[0].ie_timeperiod.tp_start > tm ) { /* *stobjfd = idx_put_newentry( fd, 0, iarr, icnt, &ient );*/ *stobjfd = open( iarr[0].ie_filename, INV_OFLAG(forwhat) ); return 0; } for ( i = 0; i < icnt->ic_curnum; i++ ) { /* if our time is nicely within an existing entry's time period, hellalujah */ if ( IS_WITHIN( &iarr[i].ie_timeperiod, tm ) ) { #ifdef INVT_DEBUG mlog( MLOG_DEBUG | MLOG_INV, "INV: is_within %d\n",i ); #endif *stobjfd = open( iarr[i].ie_filename, INV_OFLAG(forwhat) ); return i; } if ( iarr[i].ie_timeperiod.tp_end == 0 && iarr[i].ie_timeperiod.tp_start == 0 ) { #ifdef INVT_DEBUG mlog( MLOG_DEBUG | MLOG_INV, "INV: end = start \n" ); mlog( MLOG_DEBUG | MLOG_INV,"BEF: st %ld end %ld\n", iarr[i].ie_timeperiod.tp_start, iarr[i].ie_timeperiod.tp_end ); #endif iarr[i].ie_timeperiod.tp_start = iarr[i].ie_timeperiod.tp_end = tm; PUT_REC_NOLOCK( fd, iarr, icnt->ic_curnum * sizeof(invt_entry_t), (off64_t) sizeof( invt_counter_t ) ); #ifdef INVT_DEBUG mlog( MLOG_DEBUG | MLOG_INV,"AFT: st %ld end %ld\n", iarr[i].ie_timeperiod.tp_start, iarr[i].ie_timeperiod.tp_end ); #endif *stobjfd = open( iarr[i].ie_filename, INV_OFLAG(forwhat) ); return i; } /* if it is beyond the end of this timeperiod, see if we belong to a timeperiod that doesn't have an entry */ if ( iarr[i].ie_timeperiod.tp_end < tm ) { /* see if we're the last entry here */ if ( i == icnt->ic_curnum - 1 ) { /* our slot is (i+1)th entry. Make the timeperiod's the same as it was. As far as I can see there is no way that timeperiods can overlap. insert the new entry and write back icnt and invindex entry */ /* *stobjfd = idx_put_newentry( fd, i+1, iarr, icnt, &ient );*/ *stobjfd = open( iarr[i].ie_filename, INV_OFLAG(forwhat) ); return i; } /* see if the next entry starts later than us */ if ( iarr[i+1].ie_timeperiod.tp_start > tm ) { /* We have the option of pushing entries after (i) forward by one slot, and taking the (i+1)th slot, OR just hooking up with the next entry. We choose the former. */ /* the timeperiods had better not overlap */ assert(( tm > iarr[i].ie_timeperiod.tp_end ) && ( tm < iarr[i+1].ie_timeperiod.tp_start )); /* shift everything from (i+1) onwards by one. Then insert the new entry and write back icnt and invindex entries */ /* *stobjfd = idx_put_newentry( fd, i+1, iarr, icnt, &ient );*/ *stobjfd = open( iarr[i].ie_filename, INV_OFLAG(forwhat) ); return i; } } } /* We couldnt find anything that fits */ assert( 0 ); /* We can't get here ! */ return -1; } /*----------------------------------------------------------------------*/ /* idx_put_newentry */ /* */ /* */ /*----------------------------------------------------------------------*/ int idx_put_newentry( invt_idxinfo_t *idx, invt_entry_t *ient ) { invt_entry_t *idxarr; int stobjfd; int fd = idx->invfd; /* kept locked EX by caller */ uint index = idx->index + 1; invt_entry_t *iarr = idx->iarr; invt_counter_t *icnt = idx->icnt; stobj_makefname( ient->ie_filename ); if ( ( stobjfd = stobj_create( ient->ie_filename ) ) < 0 ) return -1; icnt->ic_curnum++; /* there is no maximum */ idxarr = ( invt_entry_t * ) calloc ( icnt->ic_curnum, sizeof( invt_entry_t ) ); memcpy( idxarr, iarr, ( size_t ) ( sizeof( invt_entry_t ) * index ) ); /* shift everything from (i+1) onwards by one */ if ( index < icnt->ic_curnum - 1 ) memcpy( &idxarr[ index + 1 ], &iarr[ index ], ( size_t ) ( ( icnt->ic_curnum - index - 1 ) * sizeof( invt_entry_t ) ) ); /* insert the new entry */ memcpy( &idxarr[ index ], ient, sizeof( invt_entry_t ) ); if ( ( PUT_COUNTERS( fd, icnt ) < 0 ) || ( PUT_REC_NOLOCK( fd, idxarr, icnt->ic_curnum * sizeof( invt_entry_t ), sizeof( invt_counter_t ) ) < 0 ) ) { /* XXX delete the stobj that we just created */ memset( ient->ie_filename, 0 , INV_STRLEN ); free( idxarr ); return -1; } free( iarr ); idx->iarr = idxarr; return stobjfd; } /*----------------------------------------------------------------------*/ /* idx_find_stobj */ /* */ /* */ /*----------------------------------------------------------------------*/ int idx_find_stobj( invt_idxinfo_t *idx, time32_t tm ) { int stobjfd; /* since sessions can be inserted in random order, the invindex table can contain time-periods that don't have corresponding entries for */ if ( GET_ALLHDRS_N_CNTS_NOLOCK( idx->invfd, (void **)&idx->iarr, (void **)&idx->icnt, sizeof( invt_entry_t ), sizeof( invt_counter_t ) ) < 0 ) { return -1; } #ifdef INVT_DEBUG printf( "idx_find_stobj Time: %ld\n", tm ); idx_DEBUG_printinvindices( idx->iarr, idx->icnt->ic_curnum ); #endif /* Now figure out where we are going to insert this stobj among the invindices and put it there */ idx->index = idx_insert_newentry( idx->invfd, &stobjfd, idx->iarr, idx->icnt, tm ); return stobjfd; } /*----------------------------------------------------------------------*/ /* */ /* */ /* */ /*----------------------------------------------------------------------*/ inv_idbtoken_t idx_create( char *fname, inv_oflag_t forwhat ) { int stobjfd, fd; inv_idbtoken_t tok; /* This is not to be called when the user wants to open the db for SEARCH_ONLY. */ assert( forwhat != INV_SEARCH_ONLY ); if ((fd = open ( fname , INV_OFLAG(forwhat) | O_CREAT, S_IRUSR|S_IWUSR ) ) < 0 ) { INV_PERROR ( fname ); return INV_TOKEN_NULL; } INVLOCK( fd, LOCK_EX ); fchmod( fd, INV_PERMS ); #ifdef INVT_DEBUG mlog( MLOG_NITTY | MLOG_INV, "creating InvIndex %s\n", fname); #endif /* create the first entry in the new inv_index */ stobjfd = idx_create_entry( &tok, fd, BOOL_TRUE ); INVLOCK( fd, LOCK_UN ); if ( stobjfd < 0 ) return INV_TOKEN_NULL; return tok; } /*----------------------------------------------------------------------*/ /* idx_recons_time */ /* */ /* */ /*----------------------------------------------------------------------*/ int idx_recons_time( time32_t tm, invt_idxinfo_t *idx ) { invt_timeperiod_t *tp = &idx->iarr[idx->index].ie_timeperiod; if ( tp->tp_start && IS_WITHIN( tp, tm ) ) return 1; if ( tm > tp->tp_end || tp->tp_end == 0 ) tp->tp_end = tm; if ( tm < tp->tp_start || tp->tp_start == 0 ) tp->tp_start = tm; PUT_REC_NOLOCK( idx->invfd, &idx->iarr[idx->index], sizeof( invt_entry_t ), IDX_HDR_OFFSET(idx->index) ); return 1; } /*----------------------------------------------------------------------*/ /* put_sesstime */ /* */ /* */ /*----------------------------------------------------------------------*/ int idx_put_sesstime( inv_sestoken_t tok, bool_t whichtime) { int rval; invt_entry_t ent; int fd = tok->sd_invtok->d_invindex_fd; INVLOCK( fd, LOCK_EX ); rval = GET_REC_NOLOCK( fd, &ent, sizeof( invt_entry_t ), tok->sd_invtok->d_invindex_off); if ( rval < 0 ) { INVLOCK( fd, LOCK_UN ); return -1; } ent.ie_timeperiod.tp_end = tok->sd_sesstime; if ( whichtime == INVT_STARTTIME || ent.ie_timeperiod.tp_start == 0 ) { ent.ie_timeperiod.tp_start = tok->sd_sesstime; } #ifdef INVT_DEBUG mlog( MLOG_DEBUG | MLOG_INV,"Putsestime: st %ld end %ld\n", ent.ie_timeperiod.tp_start, ent.ie_timeperiod.tp_end ); #endif rval = PUT_REC_NOLOCK_SEEKCUR( fd, &ent, sizeof( invt_entry_t ), -(off64_t)(sizeof( invt_entry_t ))); #ifdef INVT_DEBUG { int nindices; invt_entry_t *iarr = NULL; invt_counter_t *icnt = NULL; if ( ( nindices = GET_ALLHDRS_N_CNTS_NOLOCK( fd, (void **)&iarr, (void **)&icnt, sizeof( invt_entry_t ), sizeof( invt_counter_t ))) < 0 ) { return -1; } idx_DEBUG_printinvindices( iarr, (uint) nindices ); free( iarr ); free( icnt ); } #endif INVLOCK( fd, LOCK_UN ); return rval; } /* an inventory index entry keeps track of a single storage object; it knows about its name (ie filename) and the timeperiod that the it contains dump sessions for. note that each file system has its own (set of) inventory indices. */ /*----------------------------------------------------------------------*/ /* */ /* */ /* */ /*----------------------------------------------------------------------*/ int idx_create_entry( inv_idbtoken_t *tok, int invfd, /* kept locked EX by caller */ bool_t firstentry ) { invt_entry_t ent; int fd; off64_t hoff; memset ( &ent, 0, sizeof( ent ) ); /* initialize the start and end times to be the same */ ent.ie_timeperiod.tp_start = ent.ie_timeperiod.tp_end = (time32_t)0; stobj_makefname( ent.ie_filename ); if ( firstentry ) { invt_counter_t cnt; cnt.ic_maxnum = INVT_MAX_INVINDICES; cnt.ic_curnum = 1; cnt.ic_vernum = INV_VERSION; fd = stobj_create( ent.ie_filename ); if ( fd < 0 ) { return -1; } if ( PUT_REC_NOLOCK( invfd, &cnt, sizeof(cnt), (off64_t)0 ) < 0 ) return -1; hoff = sizeof( invt_counter_t ); if ( PUT_REC_NOLOCK( invfd, &ent, sizeof( ent ), hoff ) < 0) return -1; } else { invt_counter_t *cnt = NULL; if ( GET_COUNTERS( invfd, &cnt ) < 0 ) { return -1; } /* XXX check if there are too many indices. if so, create another and leave a pointer to that in here */ /* create the new storage object */ fd = stobj_create( ent.ie_filename ); if ( fd < 0 ) { return -1; } ++(cnt->ic_curnum); if ( PUT_COUNTERS( invfd, cnt ) < 0 ) { return -1; } /* add the new index entry to the array, at the end */ hoff = IDX_HDR_OFFSET( cnt->ic_curnum - 1 ); free (cnt); #ifdef INVT_DEBUG mlog( MLOG_NITTY | MLOG_INV, "new stobj name %s @ offset %d\n", ent.ie_filename,(int)hoff ); #endif if (PUT_REC_NOLOCK( invfd, &ent, sizeof( ent ), hoff) < 0 ) return -1; } *tok = get_token( invfd, fd ); (*tok)->d_invindex_off = hoff; (*tok)->d_update_flag |= NEW_INVINDEX; (*tok)->d_oflag = INV_SEARCH_N_MOD; return fd; } /*----------------------------------------------------------------------*/ /* */ /* */ /* */ /*----------------------------------------------------------------------*/ int idx_get_stobj( int invfd, inv_oflag_t forwhat, int *index ) { invt_entry_t *ent = 0; int fd; /* if there's space anywhere at all, then it must be in the last entry. get_lastheader() does the locking */ if ((*index = get_lastheader( invfd, (void **)&ent, sizeof(invt_entry_t), sizeof(invt_counter_t) ) ) < 0 ) return -1; /* at this point we know that there should be at least one invindex entry present */ assert ( ent != NULL ); assert ( ent->ie_filename ); fd = open( ent->ie_filename, INV_OFLAG(forwhat) ); if ( fd < 0 ) INV_PERROR( ent->ie_filename ); free ( ent ); return fd; } int idx_DEBUG_printinvindices( invt_entry_t *iarr, uint num ) { uint i; uint k; char s[9]; printf( "\n ==================================\n" " InvIndex\n # StObjs\t%d\n", num ); #define INV_UUID_STR_LEN 36 /* not exported via uuid.h */ for ( i = 0; i < num; i++ ) { k = strlen( iarr[i].ie_filename ); strncpy( s, (char *) iarr[i].ie_filename + k - ( INV_UUID_STR_LEN + strlen(INV_STOBJ_PREFIX)), 8 ); s[8]= 0; printf("%d. %s \t( %d - %d )\n", i, s, iarr[i].ie_timeperiod.tp_start, iarr[i].ie_timeperiod.tp_end ); } #undef INV_UUID_STR_LEN printf( "\n ==================================\n"); return 1; } int idx_DEBUG_print ( int fd ) { int nindices; invt_entry_t *iarr = NULL; invt_counter_t *icnt = NULL; if ( ( nindices = GET_ALLHDRS_N_CNTS_NOLOCK( fd, (void **)&iarr, (void **)&icnt, sizeof( invt_entry_t ), sizeof( invt_counter_t ))) < 0 ) { return -1; } idx_DEBUG_printinvindices( iarr, (uint) nindices ); free( iarr ); free( icnt ); return 1; } int DEBUG_displayallsessions( int fd, invt_seshdr_t *hdr, uint ref, invt_pr_ctx_t *prctx) { inv_session_t *ses; if ( stobj_make_invsess( fd, &ses, hdr ) < 1 ) return -1; DEBUG_sessionprint( ses, ref, prctx); free( ses->s_streams ); free( ses ); return 0; } xfsdump-3.1.6+nmu1/inventory/inv_core.c0000644000000000000000000001411312620476160014762 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "types.h" #include "inv_priv.h" /*----------------------------------------------------------------------*/ /* get_counters, get_headers, get_invtrecord, put_invtrecord, ... */ /* */ /* These implement low level routines that take care of disk I/Os. */ /* In most cases, the caller has the option of locking before calling */ /* the routine. */ /* */ /*----------------------------------------------------------------------*/ int get_counters( int fd, void **cntpp, size_t cntsz ) { /* object must be locked at least SHARED by caller */ uint num; assert( cntsz >= sizeof( invt_counter_t ) ); *cntpp = calloc( 1, cntsz); /* find the number of sessions and the max possible */ if ( GET_REC_NOLOCK( fd, (void *) *cntpp, cntsz, (off64_t) 0 ) < 0 ) { free( *cntpp ); *cntpp = NULL; return -1; } num = ((invt_counter_t *)(*cntpp))->ic_curnum; if ( ( (invt_counter_t *)(*cntpp))->ic_vernum != INV_VERSION ) { mlog( MLOG_NORMAL | MLOG_INV, _( "INV : Unknown version %d - Expected version %d\n"), (int) ( (invt_counter_t *)(*cntpp))->ic_vernum, (int) INV_VERSION ); assert ( ((invt_counter_t *)(*cntpp))->ic_vernum == INV_VERSION ); } return (int) num; } /*----------------------------------------------------------------------*/ /* get_headers */ /*----------------------------------------------------------------------*/ int get_headers( int fd, void **hdrs, size_t bufsz, size_t off ) { *hdrs = malloc( bufsz ); if ( *hdrs == NULL ) { INV_PERROR( _("get_headers() - malloc(seshdrs)\n") ); return -1; } /* file must be locked at least SHARED by caller */ /* get the array of hdrs */ if ( GET_REC_NOLOCK( fd, (void *) *hdrs, bufsz, (off64_t)off ) < 0 ) { free ( *hdrs ); *hdrs = NULL; return -1; } return 1; } /*----------------------------------------------------------------------*/ /* get_invtrecord */ /*----------------------------------------------------------------------*/ int get_invtrecord( int fd, void *buf, size_t bufsz, off64_t off, int whence, bool_t dolock ) { int nread; assert ( fd >= 0 ); if ( dolock ) INVLOCK( fd, LOCK_SH ); if ( lseek( fd, (off_t)off, whence ) < 0 ) { INV_PERROR( _("Error in reading inventory record " "(lseek failed): ") ); if ( dolock ) INVLOCK( fd, LOCK_UN ); return -1; } nread = read( fd, buf, bufsz ); if ( nread != (int) bufsz ) { INV_PERROR( _("Error in reading inventory record :") ); if ( dolock ) INVLOCK( fd, LOCK_UN ); return -1; } if ( dolock ) INVLOCK( fd, LOCK_UN ); return nread; } /*----------------------------------------------------------------------*/ /* put_invtrecord */ /*----------------------------------------------------------------------*/ int put_invtrecord( int fd, void *buf, size_t bufsz, off64_t off, int whence, bool_t dolock ) { int nwritten; if ( dolock ) INVLOCK( fd, LOCK_EX ); if ( lseek( fd, (off_t)off, whence ) < 0 ) { INV_PERROR( _("Error in writing inventory record " "(lseek failed): ") ); if ( dolock ) INVLOCK( fd, LOCK_UN ); return -1; } if (( nwritten = write( fd, buf, bufsz ) ) != (int) bufsz ) { INV_PERROR( _("Error in writing inventory record :") ); if ( dolock ) INVLOCK( fd, LOCK_UN ); return -1; } if ( dolock ) INVLOCK( fd, LOCK_UN ); return nwritten; } /*----------------------------------------------------------------------*/ /* get_headerinfo */ /*----------------------------------------------------------------------*/ int get_headerinfo( int fd, void **hdrs, void **cnt, size_t hdrsz, size_t cntsz, bool_t dolock ) { int num; /* get a lock on the table for reading */ if ( dolock ) INVLOCK( fd, LOCK_SH ); num = get_counters( fd, cnt, cntsz ); /* If there are no sessions recorded yet, we're done too */ if ( num > 0 ) { if ( get_headers( fd, hdrs, hdrsz * (size_t)num, cntsz ) < 0 ) { free ( *cnt ); num = -1; } } if ( dolock ) INVLOCK( fd, LOCK_UN ); return num; } /*----------------------------------------------------------------------*/ /* get_lastheader */ /*----------------------------------------------------------------------*/ int get_lastheader( int fd, void **ent, size_t hdrsz, size_t cntsz ) { int nindices; void *arr = NULL; invt_counter_t *cnt = NULL; char *pos; /* get the entries in the inv_index */ if ( ( nindices = GET_ALLHDRS_N_CNTS( fd, &arr, (void **)&cnt, hdrsz, cntsz )) <= 0 ) { return -1; } /* if there's space anywhere at all, then it must be in the last entry */ *ent = malloc( hdrsz ); pos = (char *) arr + ( (uint)nindices - 1 ) * hdrsz; memcpy( *ent, pos, hdrsz ); free ( arr ); free ( cnt ); return nindices; } xfsdump-3.1.6+nmu1/inventory/inv_mgr.c0000644000000000000000000004414212620476160014624 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "types.h" #include "mlog.h" #include "inv_priv.h" /*----------------------------------------------------------------------*/ /* init_idb */ /* */ /* Returns -1 if we are done with initialization, the fd if not. */ /* The idb_token indicates whether there was an error or not, if the */ /* return value is -1. */ /*----------------------------------------------------------------------*/ int init_idb( void *pred, inv_predicate_t bywhat, inv_oflag_t forwhat, inv_idbtoken_t *tok ) { char fname[ INV_STRLEN ]; char uuname[ INV_STRLEN ]; int fd; *tok = INV_TOKEN_NULL; /* make sure INV_DIRPATH exists, and is writable */ if ( make_invdirectory( forwhat ) < 0 ) return I_DONE; /* come up with the unique file suffix that refers to this filesystem */ if ( fstab_get_fname( pred, uuname, bywhat, forwhat ) < 0 ) { return I_DONE; } ( void )strcpy( fname, uuname ); strcat ( fname, INV_INVINDEX_PREFIX ); /* first check if the inv_index file exists: if not create it */ if ( ( fd = open( fname, INV_OFLAG(forwhat) ) ) == -1 ) { if (errno != ENOENT) { INV_PERROR ( fname ); } else if (forwhat == INV_SEARCH_N_MOD) { *tok = idx_create( fname, forwhat ); } else { /* this happens when the inv is empty and the user wants to do a search. this is legal - not an error */ return I_EMPTYINV; } return I_DONE; /* we are done whether token's NULL or not */ } /* we've got to do more housekeeping stuff. so signal that */ return fd; } inv_idbtoken_t get_token( int invfd, int stobjfd ) { invt_desc_entry_t *desc; desc = (invt_desc_entry_t *) malloc ( sizeof( invt_desc_entry_t ) ); desc->d_invindex_fd = invfd; desc->d_stobj_fd = stobjfd; desc->d_update_flag = 0; desc->d_invindex_off = -1; return (inv_idbtoken_t) desc; /* yukky, but ok for the time being */ } void destroy_token( inv_idbtoken_t tok ) { free ( (invt_desc_entry_t *) tok ); } inv_sestoken_t get_sesstoken( inv_idbtoken_t tok ) { inv_sestoken_t stok; stok = (inv_sestoken_t) malloc( sizeof( invt_sesdesc_entry_t ) ); stok->sd_invtok = tok; stok->sd_session_off = stok->sd_sesshdr_off = -1; stok->sd_sesstime = (time32_t) 0; return stok; } /*---------------------------------------------------------------------------*/ /* */ /* */ /* */ /*---------------------------------------------------------------------------*/ bool_t invmgr_query_all_sessions ( uuid_t *fsidp, void *inarg, void **outarg, search_callback_t func) { invt_counter_t *cnt; invt_fstab_t *arr; int numfs, i, fd, invfd; char fname[INV_STRLEN]; int result; inv_oflag_t forwhat = INV_SEARCH_ONLY; void *objectfound; bool_t ret = BOOL_FALSE; /* if on return, this is still null, the search failed */ *outarg = NULL; assert(inarg); fd = fstab_getall( &arr, &cnt, &numfs, forwhat ); /* special case missing file: ok, outarg says zero */ if ( fd < 0 && errno == ENOENT ) { return BOOL_TRUE; } if ( fd < 0 || numfs <= 0 ) { mlog( MLOG_NORMAL | MLOG_INV, _("INV: Error in fstab\n") ); return ret; } close( fd ); for ( i = 0; i < numfs; i++) { if ( fstab_get_fname( &arr[i].ft_uuid, fname, (inv_predicate_t)INV_BY_UUID, forwhat) < 0 ) { mlog( MLOG_NORMAL | MLOG_INV, _( "INV: Cant get inv-name for uuid\n") ); continue; } strcat( fname, INV_INVINDEX_PREFIX ); invfd = open( fname, INV_OFLAG(forwhat) ); if ( invfd < 0 ) { mlog( MLOG_NORMAL | MLOG_INV, _( "INV: Open failed on %s\n"), fname ); continue; } result = search_invt(fsidp, invfd, inarg, &objectfound, func); close(invfd); /* if error return BOOL_FALSE */ if (result < 0) { return BOOL_FALSE; } else if ((result == 1) && *outarg) { /* multiple entries found, more info needed */ *outarg = NULL; return BOOL_TRUE; } else if (result == 1) { *outarg = objectfound; ret = BOOL_TRUE; } } /* return val indicates if there was an error or not. *buf says whether the search was successful */ return ret; } /*----------------------------------------------------------------------*/ /* search_invt */ /* */ /* Used by the toplevel (inv layer ) to do common searches on the inven-*/ /* tory. Caller supplies a callback routine that performs the real */ /* comparison/check. */ /*----------------------------------------------------------------------*/ int search_invt( uuid_t *fsidp, int invfd, void *arg, void **buf, search_callback_t do_chkcriteria) { int fd, i; invt_entry_t *iarr = NULL; invt_counter_t *icnt = NULL; int nindices; if (invfd == I_EMPTYINV) return -1; /* set the caller's buffer pointer to NULL initially. * if no session found, the caller will expect to see * NULL. */ *( char ** )buf = NULL; if ( ( nindices = GET_ALLHDRS_N_CNTS( invfd, (void **)&iarr, (void **)&icnt, sizeof( invt_entry_t ), sizeof( invt_counter_t )) ) <= 0 ) { return -1; } free( icnt ); /* we need to get all the invindex headers and seshdrs in reverse order */ for (i = nindices - 1; i >= 0; i--) { int nsess, j; invt_sescounter_t *scnt = NULL; invt_seshdr_t *harr = NULL; bool_t found; fd = open (iarr[i].ie_filename, O_RDONLY ); if (fd < 0) { INV_PERROR( iarr[i].ie_filename ); continue; } INVLOCK( fd, LOCK_SH ); /* Now see if we can find the session we're looking for */ if (( nsess = GET_ALLHDRS_N_CNTS_NOLOCK( fd, (void **)&harr, (void **)&scnt, sizeof( invt_seshdr_t ), sizeof( invt_sescounter_t )) ) < 0 ) { INV_PERROR( iarr[i].ie_filename ); INVLOCK( fd, LOCK_UN ); close( fd ); continue; } free ( scnt ); for (j = nsess - 1; j >= 0; j--) { invt_session_t ses; /* fd is kept locked until we return from the callback routine */ /* Check to see if this session has been pruned * by xfsinvutil before checking it. */ if (harr[j].sh_pruned) { continue; } /* if we need to check the fs uuid's and they don't * match or we fail to get the session record, * then keep looking */ if (fsidp) { int ret = GET_REC_NOLOCK(fd, &ses, sizeof(invt_session_t), harr[j].sh_sess_off); if (ret < 0) return ret; if (uuid_compare(ses.s_fsid, *fsidp)) continue; } found = (* do_chkcriteria)(fd, &harr[j], arg, buf); if (! found ) continue; /* we found what we need; just return */ INVLOCK( fd, LOCK_UN ); close( fd ); free( harr ); return found; /* == -1 or 1 */ } INVLOCK( fd, LOCK_UN ); close( fd ); } return 0; } /*---------------------------------------------------------------------------*/ /* */ /* */ /* */ /*---------------------------------------------------------------------------*/ int invmgr_inv_print( int invfd, invt_pr_ctx_t *prctx) { int fd, i; invt_entry_t *iarr = NULL; invt_counter_t *icnt = NULL; int nindices; uint ref = 0; if (invfd == I_EMPTYINV) return 0; if ( ( nindices = GET_ALLHDRS_N_CNTS( invfd, (void **)&iarr, (void **)&icnt, sizeof( invt_entry_t ), sizeof( invt_counter_t )) ) <= 0 ) { return -1; } free( icnt ); if (prctx->invidx) { idx_DEBUG_printinvindices( iarr, (uint) nindices ); free(iarr); return (0); } for ( i = 0; i < nindices; i++ ) { int nsess; invt_sescounter_t *scnt = NULL; invt_seshdr_t *harr = NULL; int s; fd = open (iarr[i].ie_filename, O_RDONLY ); if (fd < 0) { INV_PERROR( iarr[i].ie_filename ); continue; } INVLOCK( fd, LOCK_SH ); /* Now see if we can find the session we're looking for */ if (( nsess = GET_ALLHDRS_N_CNTS_NOLOCK( fd, (void **)&harr, (void **)&scnt, sizeof( invt_seshdr_t ), sizeof( invt_sescounter_t )) ) < 0 ) { INV_PERROR( iarr[i].ie_filename ); INVLOCK( fd, LOCK_UN ); close( fd ); continue; } free ( scnt ); for( s = 0; s < nsess; s++ ) { /* fd is kept locked until we return from the callback routine */ /* Check to see if this session has been pruned * by xfsinvutil before returning it. */ if ( harr[s].sh_pruned ) { continue; } (void)DEBUG_displayallsessions( fd, &harr[ s ], ref++, prctx); } INVLOCK( fd, LOCK_UN ); close( fd ); } free (iarr); return 0; } /*---------------------------------------------------------------------------*/ /* */ /* */ /* */ /*---------------------------------------------------------------------------*/ int invmgr_inv_check( int invfd) { int fd, i; invt_entry_t *iarr = NULL; invt_counter_t *icnt = NULL; int nindices; if (invfd == I_EMPTYINV) return 0; if ( ( nindices = GET_ALLHDRS_N_CNTS( invfd, (void **)&iarr, (void **)&icnt, sizeof( invt_entry_t ), sizeof( invt_counter_t )) ) <= 0 ) { return -1; } free( icnt ); for ( i = 0; i < nindices; i++ ) { int nsess; invt_sescounter_t *scnt = NULL; invt_seshdr_t *harr = NULL; int s; fd = open (iarr[i].ie_filename, O_RDONLY ); if (fd < 0) { INV_PERROR( iarr[i].ie_filename ); continue; } INVLOCK( fd, LOCK_SH ); /* Now see if we can find the session we're looking for */ if (( nsess = GET_ALLHDRS_N_CNTS_NOLOCK( fd, (void **)&harr, (void **)&scnt, sizeof( invt_seshdr_t ), sizeof( invt_sescounter_t )) ) < 0 ) { INV_PERROR( iarr[i].ie_filename ); INVLOCK( fd, LOCK_UN ); close( fd ); continue; } free ( scnt ); if ((iarr[i].ie_timeperiod.tp_start != harr[0].sh_time) || (iarr[i].ie_timeperiod.tp_end != harr[nsess-1].sh_time)) { printf(_("INV: Check %d failed.\n"), i+1); printf(_("invidx (%d)\t%d - %d\n"), i+1, iarr[i].ie_timeperiod.tp_start, iarr[i].ie_timeperiod.tp_end); for( s = 0; s < nsess; s++ ) { printf(_("tm (%d)\t%d\n"), s, harr[s].sh_time); } } else { printf(_("INV: Check %d out of %d succeeded\n"), i+1, nindices); } INVLOCK( fd, LOCK_UN ); close( fd ); } return 0; } /*----------------------------------------------------------------------*/ /* */ /* */ /* */ /*----------------------------------------------------------------------*/ /* ARGSUSED */ bool_t tm_level_lessthan( int fd, invt_seshdr_t *hdr, void *arg, void **tm ) { u_char level = *(u_char *)arg; *tm = NULL; if ( IS_PARTIAL_SESSION( hdr ) ) return 0; if (hdr->sh_level < level ) { #ifdef INVT_DEBUG mlog( MLOG_DEBUG | MLOG_INV, "$ found level %d < %d\n", hdr->sh_level, level ); #endif *tm = calloc( 1, sizeof( time32_t ) ); memcpy( *tm, &hdr->sh_time, sizeof( time32_t ) ); return 1; } return 0; } /*----------------------------------------------------------------------*/ /* */ /* */ /* */ /*----------------------------------------------------------------------*/ bool_t lastsess_level_lessthan( int fd, invt_seshdr_t *hdr, void *arg, void **buf ) { u_char level = *(u_char *)arg; *buf = NULL; if ( IS_PARTIAL_SESSION( hdr ) ) return 0; if (hdr->sh_level < level ) { #ifdef INVT_DEBUG mlog( MLOG_DEBUG | MLOG_INV, "$ found (ses) level %d < %d \n", hdr->sh_level, level ); #endif return stobj_make_invsess( fd, (inv_session_t **) buf, hdr ); } return 0; } /*----------------------------------------------------------------------*/ /* */ /* */ /* */ /*----------------------------------------------------------------------*/ bool_t lastsess_level_equalto( int fd, invt_seshdr_t *hdr, void *arg, void **buf ) { u_char level = *(u_char *)arg; *buf = NULL; if ( IS_PARTIAL_SESSION( hdr ) ) return 0; if (hdr->sh_level == level ) { #ifdef INVT_DEBUG mlog( MLOG_DEBUG | MLOG_INV, "$ found (ses) level %d == %d \n", hdr->sh_level, level ); #endif return stobj_make_invsess( fd, (inv_session_t **) buf, hdr ); } return 0; } /*----------------------------------------------------------------------*/ /* insert_session */ /* */ /* insert a session that may or may not be already in the inventory. */ /* this is used in reconstructing the database. */ /*----------------------------------------------------------------------*/ bool_t insert_session( invt_sessinfo_t *s) { inv_idbtoken_t tok = INV_TOKEN_NULL; int invfd, stobjfd = -1; invt_idxinfo_t idx; bool_t ret = BOOL_FALSE; inv_oflag_t forwhat = INV_SEARCH_N_MOD; /* initialize the inventory */ if ( ( invfd = init_idb ( (void *) s->ses->s_fsid, (inv_predicate_t) INV_BY_UUID, forwhat, &tok ) ) < 0 ) { if ( tok == INV_TOKEN_NULL ) { #ifdef INVT_DEBUG mlog( MLOG_DEBUG | MLOG_INV, "INV: insert_session: init_db " "failed\n" ); #endif return BOOL_FALSE; } invfd = tok->d_invindex_fd; close( tok->d_stobj_fd ); destroy_token( tok ); } /* at this point we know that invindex has at least one entry First we need to find out if this session is in the inventory already. To find the storage object that can possibly contain this session, it suffices to sequentially search the inventory indices of this filesystem for the particular invt-entry */ INVLOCK( invfd, LOCK_EX ); idx.invfd = invfd; stobjfd = idx_find_stobj( &idx, s->seshdr->sh_time ); if (stobjfd < 0) { INVLOCK( invfd, LOCK_UN ); free( idx.icnt ); free( idx.iarr ); return BOOL_FALSE; } /* Now put the session in the storage-object */ INVLOCK( stobjfd, LOCK_EX ); if ( ( stobj_insert_session( &idx, stobjfd, s ) < 0 ) || ( idx_recons_time ( s->seshdr->sh_time, &idx ) < 0 ) ) ret = BOOL_TRUE; INVLOCK( stobjfd, LOCK_UN ); INVLOCK( invfd, LOCK_UN ); free( idx.icnt ); free( idx.iarr ); if (ret) return BOOL_FALSE; /* make sure the fstab is uptodate too */ if ( fstab_put_entry( &s->ses->s_fsid, s->ses->s_mountpt, s->ses->s_devpath, forwhat ) < 0 ) return BOOL_FALSE; /* and we are done */ return BOOL_TRUE; } /*----------------------------------------------------------------------*/ /* */ /* */ /* */ /*----------------------------------------------------------------------*/ int make_invdirectory( inv_oflag_t forwhat ) { struct stat64 st; char path[PATH_MAX]; char *p; p = strcpy( path, INV_DIRPATH ); if ( stat64( path, &st ) == 0 ) return 1; if ( forwhat == INV_SEARCH_ONLY || errno != ENOENT ) return -1; do { p++; if ( *p == '/' ) { *p = '\0'; if ( mkdir( path, (mode_t)0755 ) < 0 ) { if ( errno != EEXIST ) { INV_PERROR( path ); return -1; } } *p = '/'; } } while ( *p ); if ( mkdir( path, (mode_t)0755 ) < 0 ) { if ( errno != EEXIST ) { INV_PERROR( path ); return -1; } } mlog( MLOG_VERBOSE | MLOG_INV, _("%s created\n"), path ); return 1; } #ifdef NOTDEF bool_t invmgr_lockinit( void ) { if ( invlock_fd == -1 ) { if (( invlock_fd = open( INV_LOCKFILE, O_RDONLY | O_CREAT, S_IRUSR|S_IWUSR )) < 0 ) { INV_PERROR( INV_LOCKFILE ); return BOOL_FALSE; } fchmod ( invlock_fd, INV_PERMS ); } return BOOL_TRUE; } bool_t invmgr_trylock( invt_mode_t mode ) { int md; assert( invlock_fd >= 0 ); md = (mode == INVT_RECONSTRUCT) ? LOCK_EX: LOCK_SH; if (INVLOCK( invlock_fd, md | LOCK_NB ) < 0) return BOOL_FALSE; return BOOL_TRUE; } void invmgr_unlock( void ) { assert( invlock_fd >= 0 ); INVLOCK( invlock_fd, LOCK_UN ); } #endif xfsdump-3.1.6+nmu1/inventory/inv_priv.h0000644000000000000000000004375712620476160015037 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _INV_PRIV_H_ #define _INV_PRIV_H_ #include /* for flock */ #include "global.h" #include "inventory.h" #include "mlog.h" /*----------------------------------------------------------------------*/ /* The Inventory stores its data in a hierarchical manner. */ /* */ /* At the first level is the Fstab, which maintains a table of unique */ /* file system ids for all file systems that it knows of. From this fsid*/ /* we can derive the Inventory Index for that file system. */ /* */ /* Inventory Index contains references to all the Storage Objects that */ /* carry data associated with (its) file system. The Storage Objects, */ /* the third level (of indirection) are reserved for certain (variable) */ /* time periods, and the inv-index keeps track of those timeperiods */ /* in its table. In other words, for a given time, there is a unique */ /* stobj that exists to contain a session that occured at that time.. */ /* */ /*----------------------------------------------------------------------*/ #define INV_LOCKFILE inv_lockfile() #define INVTSESS_COOKIE "idbsess0" #define INVT_STOBJ_MAXSESSIONS 5 #define INVT_MAX_INVINDICES -1 /* unlimited */ #define FSTAB_UPDATED 1 #define NEW_INVINDEX 2 /* session flags ( seshdr.sh_flag ) */ #define INVT_PARTIAL (uint)0x0001 #define INVT_RESUMED (uint)0x0002 /* media file flags ( mfile.mf_flag ) */ #define INVT_MFILE_GOOD (u_char)0x01 #define INVT_MFILE_INVDUMP (u_char)0x02 #define INVT_ENDTIME BOOL_FALSE #define INVT_STARTTIME BOOL_TRUE #define INVT_DOLOCK BOOL_TRUE #define INVT_DONTLOCK BOOL_FALSE #define INVLOCK( fd, m ) flock( fd, m ) /* return values */ #define INV_OK (int) 1 #define INV_ERR (int) -1 #define I_DONE (int) -1 #define I_EMPTYINV (int) -2 /* flags to oref_resolve_new_stobj() */ #define IS_EMPTY BOOL_TRUE #define IS_NOT_EMPTY BOOL_FALSE #define INV_PERMS S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH #define IS_WITHIN(ttpe, tm) ( tm >= (ttpe)->tp_start && \ tm <= (ttpe)->tp_end ) #define IDX_HDR_OFFSET(n) (off64_t) ( sizeof( invt_entry_t ) * \ (size_t) (n)\ + sizeof( invt_counter_t ) ) #define STOBJ_OFFSET( nhdrs, nsess ) (off64_t) ( \ sizeof( invt_sescounter_t ) + \ (size_t) nhdrs * sizeof( invt_seshdr_t ) + \ (size_t) nsess * sizeof( invt_session_t ) ) #define STREQL( n,m ) ( strcmp((n),(m)) == 0 ) #define UUID_EQL( n,m,t ) ( uuid_compare( n, m, t ) == 0 ) #define IS_PARTIAL_SESSION( h ) ( (h)->sh_flag & INVT_PARTIAL ) #define IS_RESUMED_SESSION( h ) ( (h)->sh_flag & INVT_RESUMED ) #define SC_EOF_INITIAL_POS (off64_t) (sizeof( invt_sescounter_t ) + \ INVT_STOBJ_MAXSESSIONS * \ ( sizeof( invt_seshdr_t ) + \ sizeof( invt_session_t ) ) ) #define INV_PERROR(s) mlog( MLOG_NORMAL,"INV: %s %s\n", s,strerror(errno) ) #define INV_OFLAG(f) ( f == INV_SEARCH_ONLY ) ? O_RDONLY: O_RDWR /*----------------------------------------------------------------------*/ /* On Disk Data Structures */ /* */ /*----------------------------------------------------------------------*/ typedef struct invt_session { uuid_t s_sesid; /* this session's id: 16 bytes*/ uuid_t s_fsid; /* file system id */ char s_label[INV_STRLEN]; /* session label */ char s_mountpt[INV_STRLEN];/* path to the mount point */ char s_devpath[INV_STRLEN];/* path to the device */ uint s_cur_nstreams;/* number of streams created under this session so far */ uint s_max_nstreams;/* number of media streams in the session */ char s_padding[16]; } invt_session_t; typedef struct invt_seshdr { off64_t sh_sess_off; /* offset to rest of the sessioninfo */ off64_t sh_streams_off; /* offset to start of the set of stream hdrs */ time32_t sh_time; /* time of the dump */ __uint32_t sh_flag; /* for misc flags */ u_char sh_level; /* dump level */ u_char sh_pruned; /* pruned by invutil flag */ char sh_padding[22]; } invt_seshdr_t; /* Each session consists of a number of media streams. While it is given that there won't be multiple writesessions (ie. dumpsessions) concurrently, there can be multiple media streams operating on a single file system, each writing media files within its own stream. Hence, we have a linked list of media files, that the stream keeps track of. */ typedef struct invt_breakpt { xfs_ino_t ino; /* the 64bit inumber */ off64_t offset; /* offset into the file */ } invt_breakpt_t; typedef struct invt_stream { /* duplicate info from mediafiles for speed */ invt_breakpt_t st_startino; /* the starting pt */ invt_breakpt_t st_endino; /* where we actually ended up. this means we've written upto but not including this breakpoint. */ off64_t st_firstmfile; /*offsets to the start and end of*/ off64_t st_lastmfile; /* .. linked list of mediafiles */ char st_cmdarg[INV_STRLEN]; /* drive path */ uint st_nmediafiles; /* number of mediafiles */ bool_t st_interrupted; /* was this stream interrupted ? */ char st_padding[16]; } invt_stream_t; typedef struct invt_mediafile { uuid_t mf_moid; /* media object id */ char mf_label[INV_STRLEN]; /* media file label */ invt_breakpt_t mf_startino; /* file that we started out with */ invt_breakpt_t mf_endino; /* the dump file we ended this media file with */ off64_t mf_nextmf; /* links to other mfiles */ off64_t mf_prevmf; uint mf_mfileidx; /* index within the media object */ u_char mf_flag; /* Currently MFILE_GOOD, INVDUMP */ off64_t mf_size; /* size of the media file */ char mf_padding[15]; } invt_mediafile_t; typedef struct invt_timeperiod { time32_t tp_start; time32_t tp_end; } invt_timeperiod_t; typedef struct invt_entry { invt_timeperiod_t ie_timeperiod; char ie_filename[INV_STRLEN]; char ie_padding[16]; } invt_entry_t; /* Cheap Inheritance, and an attempt to avoid a nested type */ #define INVT_COUNTER_FIELDS \ __uint32_t ic_vernum;/* on disk version number for posterity */\ uint ic_curnum;/* number of sessions/invindices recorded \ so far */ \ uint ic_maxnum;/* maximum number of sessions/inv_indices \ that we can record on this stobj */ #define INVT_COUNTER_FIELDS_SIZE 0xc typedef struct invt_counter { INVT_COUNTER_FIELDS char ic_padding[0x20 - INVT_COUNTER_FIELDS_SIZE]; } invt_counter_t; typedef struct invt_sescounter { INVT_COUNTER_FIELDS off64_t ic_eof; /* current end of the file, where the next media file or stream will be written to */ char ic_padding[0x20 - ( INVT_COUNTER_FIELDS_SIZE + sizeof( off64_t) )]; } invt_sescounter_t; typedef struct invt_fstab { uuid_t ft_uuid; char ft_mountpt[INV_STRLEN]; char ft_devpath[INV_STRLEN]; char ft_padding[16]; } invt_fstab_t; /*----------------------------------------------------------------------*/ /* The Tokens */ /* */ /*----------------------------------------------------------------------*/ typedef struct invt_desc_entry { int d_invindex_fd; /* open file descriptor of inv index */ int d_stobj_fd; /* fd of storage object */ u_char d_update_flag; /* indicates whether fstab was updated with this file system or not and also if we had to create a new invindex file */ inv_oflag_t d_oflag; /* the open mode (SEARCH_ONLY, SEARCH_N_MOD) */ off64_t d_invindex_off; /* for every session, we need a reference to its invindex entry, so that when we close a session, we know which one */ } invt_desc_entry_t; typedef struct invt_sesdesc_entry { invt_desc_entry_t *sd_invtok; /* generic inventory token */ off64_t sd_session_off; off64_t sd_sesshdr_off; time32_t sd_sesstime; /* time that session started. needed for closing the session */ } invt_sesdesc_entry_t; struct invt_mediafile; typedef struct invt_strdesc_entry { invt_sesdesc_entry_t *md_sesstok; /* the session token */ off64_t md_stream_off;/* offset to the media stream header */ struct invt_mediafile *md_lastmfile; /* just so that we dont have to get it back from disk when we add the next mfile to the linked list */ } invt_strdesc_entry_t; /*----------------------------------------------------------------------*/ /* Info Structures - simple logical containers for sessions and indices */ /* */ /*----------------------------------------------------------------------*/ typedef struct invt_sessinfo { int stobjfd; invt_seshdr_t *seshdr; invt_session_t *ses; invt_stream_t *strms; invt_mediafile_t *mfiles; } invt_sessinfo_t; typedef struct invt_idxinfo { int invfd; invt_counter_t *icnt; invt_entry_t *iarr; uint index; }invt_idxinfo_t; #define INVT_MOID 1 #define INVT_LABEL 2 #define INVT_NULLTYPE -1 typedef struct invt_mobjinfo { int type; void *value; } invt_mobjinfo_t; typedef struct invt_pr_ctx { int index; int depth; bool_t fstab; bool_t invidx; bool_t invcheck; invt_mobjinfo_t mobj; u_char level; } invt_pr_ctx_t; typedef bool_t (*search_callback_t) (int, invt_seshdr_t *, void *, void *); #define GET_REC( fd, buf, sz, off ) \ get_invtrecord( fd, buf, sz, off, SEEK_SET, INVT_DOLOCK ) #define GET_REC_NOLOCK( fd, buf, sz, off ) \ get_invtrecord( fd, buf, sz, off, SEEK_SET, INVT_DONTLOCK ) #define GET_REC_SEEKCUR( fd, buf, sz, off ) \ get_invtrecord( fd, buf, sz, off, SEEK_CUR, INVT_DOLOCK ) #define GET_ALLHDRS_N_CNTS( fd, h, c, hsz, csz ) \ get_headerinfo( fd, h, c, hsz, csz, INVT_DOLOCK ) #define GET_ALLHDRS_N_CNTS_NOLOCK( fd, h, c, hsz, csz ) \ get_headerinfo( fd, h, c, hsz, csz, INVT_DONTLOCK ) #define PUT_REC( fd, buf, sz, off ) \ put_invtrecord( fd, buf, sz, off, SEEK_SET, INVT_DOLOCK ) #define PUT_REC_NOLOCK( fd, buf, sz, off ) \ put_invtrecord( fd, buf, sz, off, SEEK_SET, INVT_DONTLOCK ) #define PUT_REC_SEEKCUR( fd, buf, sz, off ) \ put_invtrecord( fd, buf, sz, off, SEEK_CUR, INVT_DOLOCK ) #define PUT_REC_NOLOCK_SEEKCUR( fd, buf, sz, off ) \ put_invtrecord( fd, buf, sz, off, SEEK_CUR, INVT_DONTLOCK ) #define GET_COUNTERS( fd, cnt ) get_counters( fd, (void **)(cnt), \ sizeof(invt_counter_t) ) #define GET_SESCOUNTERS( fd, cnt ) get_counters( fd, (void **)(cnt), \ sizeof(invt_sescounter_t) ) #define PUT_COUNTERS( fd, cnt ) PUT_REC_NOLOCK( fd, (void *)(cnt), \ sizeof( invt_counter_t ), \ (off64_t) 0 ) #define PUT_SESCOUNTERS( fd, cnt ) PUT_REC_NOLOCK( fd, (void *)(cnt), \ sizeof( invt_sescounter_t ), \ (off64_t) 0 ) #define GET_SESHEADERS( fd, hdrs, n ) get_headers( fd, (void**)(hdrs), \ (size_t) ( n * sizeof(invt_seshdr_t ) ),\ sizeof( invt_sescounter_t ) ) #define GET_ENTRIES(fd, hdrs, n, sz) get_headers(fd, (void**)(hdrs), \ (size_t) (n * sz), sizeof(invt_counter_t)) /*----------------------------------------------------------------------*/ /* Function Prototypes */ /* */ /* */ /*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/ inv_idbtoken_t idx_create( char *fname, inv_oflag_t forwhat ); int idx_create_entry( inv_idbtoken_t *tok, int invfd, bool_t firstentry ); int idx_put_sesstime( inv_sestoken_t tok, bool_t whichtime); int idx_find_stobj( invt_idxinfo_t *idx, time32_t tm ); uint idx_insert_newentry( int fd, int *stobjfd, invt_entry_t *iarr, invt_counter_t *icnt, time32_t tm ); int idx_put_newentry( invt_idxinfo_t *idx, invt_entry_t *ient ); int idx_get_stobj( int invfd, inv_oflag_t forwhat, int *index ); int idx_recons_time( time32_t tm, invt_idxinfo_t *idx ); int idx_DEBUG_printinvindices( invt_entry_t *iarr, uint num ); int idx_DEBUG_print ( int fd ); /*----------------------------------------------------------------------*/ int stobj_create( char *fname ); int stobj_create_session( inv_sestoken_t tok, int fd, invt_sescounter_t *sescnt, invt_session_t *ses, invt_seshdr_t *hdr ); int stobj_put_mediafile( inv_stmtoken_t tok, invt_mediafile_t *mf ); off64_t stobj_put_session( int fd, invt_sescounter_t *sescnt, invt_session_t *ses, invt_seshdr_t *hdr, invt_stream_t *strms, invt_mediafile_t *mfiles ); int stobj_put_streams( int fd, invt_seshdr_t *hdr, invt_session_t *ses, invt_stream_t *strms, invt_mediafile_t *mfiles ); int stobj_hdrcmp( const void *h1, const void *h2 ); int stobj_sortheaders( int fd, uint num ); uint stobj_find_splitpoint( int fd, invt_seshdr_t *harr, uint ns, time32_t tm ); int stobj_split( invt_idxinfo_t *idx, int fd, invt_sescounter_t *sescnt, invt_sessinfo_t *newsess ); bool_t stobj_replace_session( int fd, invt_sescounter_t *sescnt, invt_session_t *ses, invt_seshdr_t *hdr, invt_sessinfo_t *newsess ); int stobj_delete_mfile( int fd, inv_stream_t *strm, invt_mediafile_t *mf, off64_t mfileoff ); bool_t stobj_pack_sessinfo( int fd, invt_session_t *ses, invt_seshdr_t *hdr, void **bufpp, size_t *bufszp ); bool_t stobj_unpack_sessinfo( void *bufp, size_t bufsz, invt_sessinfo_t *s ); bool_t stobj_delete_sessinfo( int fd, invt_sescounter_t *sescnt, invt_session_t *ses, invt_seshdr_t *hdr ); bool_t stobj_delete_mobj( int fd, invt_seshdr_t *hdr, void *arg, void **buf ); int stobj_get_sessinfo ( inv_sestoken_t tok, invt_seshdr_t *hdr, invt_session_t *ses ); void stobj_makefname( char *fname ); int stobj_insert_session( invt_idxinfo_t *idx, int fd, invt_sessinfo_t *s ); int stobj_make_invsess( int fd, inv_session_t **buf, invt_seshdr_t *hdr ); int stobj_copy_invsess( int fd, invt_seshdr_t *hdr, invt_session_t *ses, inv_session_t **buf); void DEBUG_sessionprint( inv_session_t *ses, uint ref, invt_pr_ctx_t *prctx); void DEBUG_sessprint( invt_session_t *ses ); bool_t stobj_getsession_byuuid(int fd, invt_seshdr_t *hdr, void *sesid, void **buf); bool_t stobj_getsession_bylabel(int fd, invt_seshdr_t *hdr, void *label, void **buf); void stobj_convert_session(inv_session_t *ises, invt_session_t *ses, invt_seshdr_t *hdr); void stobj_convert_strm(inv_stream_t *expstrm, invt_stream_t *strm); void stobj_convert_mfile(inv_mediafile_t *expmf, invt_mediafile_t *mf); void stobj_convert_sessinfo(inv_session_t **buf, invt_sessinfo_t *sinfo); /*----------------------------------------------------------------------*/ int fstab_get_fname( void *pred, char *fname, inv_predicate_t bywhat, inv_oflag_t forwhat ); int fstab_put_entry( uuid_t *fsidp, char *mntpt, char *dev, inv_oflag_t forwhat ); int fstab_getall( invt_fstab_t **arr, invt_counter_t **cnt, int *numfs, inv_oflag_t forwhat ); void fstab_DEBUG_print( invt_fstab_t *arr, int num ); /*----------------------------------------------------------------------*/ int get_invtentry( char *fname, time32_t tm, invt_entry_t *buf, size_t bufsz ); int get_invtrecord( int fd, void *buf, size_t bufsz, off64_t off, int, bool_t dolock ); int put_invtrecord( int fd, void *buf, size_t bufsz, off64_t off, int, bool_t dolock ); inv_idbtoken_t get_token( int fd, int objfd ); void destroy_token( inv_idbtoken_t tok ); int get_headers( int fd, void **hdrs, size_t bufsz, size_t cntsz ); int get_counters( int fd, void **cntpp, size_t sz ); int get_sescounters( int fd, invt_sescounter_t **cntpp ); int get_lastheader( int fd, void **ent, size_t hdrsz, size_t cntsz ); inv_sestoken_t get_sesstoken( inv_idbtoken_t tok ); int get_headerinfo( int fd, void **hdrs, void **cnt, size_t hdrsz, size_t cntsz, bool_t doblock ); bool_t invmgr_query_all_sessions(uuid_t *fsidp, void *inarg, void **outarg, search_callback_t func); int search_invt(uuid_t *fsidp, int invfd, void *arg, void **buf, search_callback_t do_chkcriteria); int invmgr_inv_print( int invfd, invt_pr_ctx_t *prctx); int invmgr_inv_check( int invfd ); bool_t tm_level_lessthan( int fd, invt_seshdr_t *hdr, void *arg, void **tm ); bool_t lastsess_level_lessthan( int fd, invt_seshdr_t *hdr, void *arg, void **buf ); bool_t lastsess_level_equalto( int fd, invt_seshdr_t *hdr, void *arg, void **buf ); int DEBUG_displayallsessions( int fd, invt_seshdr_t *hdr, uint ref, invt_pr_ctx_t *prctx); int make_invdirectory( inv_oflag_t forwhat ); bool_t init_idb( void *pred, inv_predicate_t bywhat, inv_oflag_t forwhat, inv_idbtoken_t *tok ); int inv_getopt( int argc, char **argv, invt_pr_ctx_t *prctx); bool_t insert_session( invt_sessinfo_t *s); /* To reconstruct a complete inventory from dumped inventories */ extern bool_t inv_put_sessioninfo( invt_sessinfo_t *s ); #endif xfsdump-3.1.6+nmu1/librmt/0000755000000000000000000000000012643557274012261 5ustar xfsdump-3.1.6+nmu1/librmt/rmtopen.c0000644000000000000000000001351112620476160014077 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc.; provided copyright in * certain portions may be held by third parties as indicated herein. * All Rights Reserved. * * The code in this source file represents an aggregation of work from * Georgia Tech, Fred Fish, Jeff Lee, Arnold Robbins and other Silicon * Graphics engineers over the period 1985-2000. * * 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. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "rmtlib.h" #define RMT_DEBUG_FILE "/tmp/librmt_debug" /* file for debug output on server */ static int _rmt_open(char *, int, int); int _rmt_Ctp[MAXUNIT][2] = { {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1} }; int _rmt_Ptc[MAXUNIT][2] = { {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1} }; int _rmt_host[MAXUNIT] = { -1, -1, -1, -1}; struct uname_table { int id; char *name; }; struct uname_table uname_table[] = { {UNAME_LINUX, "Linux"}, {UNAME_IRIX, "IRIX"}, {0,0} }; /* * Open a local or remote file. Looks just like open(2) to * caller. */ int rmtopen (path, oflag, mode) char *path; int oflag; int mode; { if (strchr (path, ':') != NULL) { return (_rmt_open (path, oflag, mode) | REM_BIAS); } else { return (open (path, oflag, mode)); } } /* * _rmt_open --- open a magtape device (or file) on system specified, * as given user * * file name has the form system[.user]:???? */ #define MAXHOSTLEN 257 #define MAXDBGPATH 100 /* ARGSUSED */ static int _rmt_open (char *path, int oflag, int mode) { int i, rc; char buffer[BUFMAGIC]; char system[MAXHOSTLEN]; char device[BUFMAGIC]; char login[BUFMAGIC]; char *sys, *dev, *user; char *rsh_path; char *rmt_path; char rmt_cmd[MAXDBGPATH]; sys = system; dev = device; user = login; if ((rsh_path = getenv("RSH")) == NULL) { rsh_path = RSH_PATH; } if ((rmt_path = getenv("RMT")) == NULL) { rmt_path = RMT_PATH; } /* * first, find an open pair of file descriptors */ for (i = 0; i < MAXUNIT; i++) if (READ(i) == -1 && WRITE(i) == -1) break; if (i == MAXUNIT) { setoserror( EMFILE ); return(-1); } /* * pull apart system and device, and optional user * don't munge original string */ while (*path != '@' && *path != ':') { *user++ = *path++; } *user = '\0'; path++; if (*(path - 1) == '@') { while (*path != ':') { *sys++ = *path++; } *sys = '\0'; path++; } else { for ( user = login; (*sys = *user); user++, sys++ ) ; user = login; } while (*path) { *dev++ = *path++; } *dev = '\0'; _rmt_turnonmsgsbyenv(); /* try to find out the uname of the remote host */ { #define MAX_UNAMECMD MAXHOSTLEN+40 #define MAX_UNAME 20 FILE *rmt_f; char cmd[MAX_UNAMECMD]; char uname[MAX_UNAME]; struct uname_table *p; if (user != login) { snprintf(cmd, sizeof(cmd), "%s -l %s %s uname", rsh_path, login, system); } else { snprintf(cmd, sizeof(cmd), "%s %s uname", rsh_path, system); } rmt_f = popen(cmd, "r"); if (rmt_f == NULL) { _rmt_msg(RMTWARN, _( "rmtopen: failed to detect remote host type using \"%s\"\n"), cmd); RMTHOST(i) = UNAME_UNDEFINED; goto do_rmt; } else { int len; char *c = fgets(uname, sizeof(uname), rmt_f); pclose(rmt_f); if (c == NULL) { _rmt_msg(RMTWARN, _( "rmtopen: failed to detect remote host type reading \"%s\"\n"), cmd); RMTHOST(i) = UNAME_UNDEFINED; goto do_rmt; } len = strlen(uname); if (len > 0 && uname[len-1] == '\n') uname[len-1] = '\0'; /* chomp the '\n' */ } for(p = &uname_table[0]; p->name != 0; p++) { if (strncmp(p->name, uname, strlen(p->name)) == 0) break; } if (p->name == 0) { RMTHOST(i) = UNAME_UNKNOWN; _rmt_msg(RMTWARN, _( "rmtopen: remote host type, \"%s\", is unknown to librmt\n"), uname); } else { RMTHOST(i) = p->id; _rmt_msg(RMTDBG, "rmtopen: RMTHOST(%d) = %s\n", i, p->name); } } /* * setup the pipes for the 'rsh' command and fork */ do_rmt: if (pipe(_rmt_Ptc[i]) == -1 || pipe(_rmt_Ctp[i]) == -1) return(-1); if ((rc = fork()) == -1) return(-1); if (rc == 0) { close(0); dup(_rmt_Ptc[i][0]); close(_rmt_Ptc[i][0]); close(_rmt_Ptc[i][1]); close(1); dup(_rmt_Ctp[i][1]); close(_rmt_Ctp[i][0]); close(_rmt_Ctp[i][1]); (void) setuid (getuid ()); (void) setgid (getgid ()); if (_rmt_msgson() == RMTDBG) { snprintf(rmt_cmd, sizeof(rmt_cmd), "%s %s.%d", rmt_path, RMT_DEBUG_FILE, getpid()); } else { strncpy(rmt_cmd, rmt_path, sizeof(rmt_cmd)); } if (user != login) { execl(rsh_path, "rsh", system, "-l", login, rmt_cmd, (char *) 0); } else { execl(rsh_path, "rsh", system, rmt_cmd, (char *) 0); } /* * bad problems if we get here */ fprintf(stderr, "librmt: problem finding either RSH(%s) or RMT(%s): %s\n", rsh_path, rmt_path, strerror(errno)); exit(1); } close(_rmt_Ptc[i][0]); close(_rmt_Ctp[i][1]); /* * now attempt to open the tape device */ sprintf(buffer, "O%s\n%d\n", device, oflag); if (_rmt_command(i, buffer) == -1 || _rmt_status(i) == -1) return(-1); return(i); } xfsdump-3.1.6+nmu1/librmt/isrmt.c0000644000000000000000000000217412607344125013554 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc.; provided copyright in * certain portions may be held by third parties as indicated herein. * All Rights Reserved. * * The code in this source file represents an aggregation of work from * Georgia Tech, Fred Fish, Jeff Lee, Arnold Robbins and other Silicon * Graphics engineers over the period 1985-2000. * * 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. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "rmtlib.h" /* * Isrmt. Let a programmer know he has a remote device. */ int isrmt (fd) int fd; { return (fd >= REM_BIAS); } xfsdump-3.1.6+nmu1/librmt/rmtlib.h0000644000000000000000000000506412620476160013715 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc.; provided copyright in * certain portions may be held by third parties as indicated herein. * All Rights Reserved. * * The code in this source file represents an aggregation of work from * Georgia Tech, Fred Fish, Jeff Lee, Arnold Robbins and other Silicon * Graphics engineers over the period 1985-2000. * * 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. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* * This file is only included by the library routines. It is not * required for user code. * */ /* * Note that local vs remote file descriptors are distinquished * by adding a bias to the remote descriptors. This is a quick * and dirty trick that may not be portable to some systems. * It should be greater than the largest open filedescriptor * than can be returned by the OS, and should be a power of 2. */ #define REM_BIAS 8192 /* * BUFMAGIC --- Magic buffer size * MAXUNIT --- Maximum number of remote tape file units */ #define BUFMAGIC 64 #define MAXUNIT 4 /* * Useful macros. * * READ --- Return the number of the read side file descriptor * WRITE --- Return the number of the write side file descriptor * RMTHOST --- Return an id which says host type from uname */ /* rmt msg types */ #define RMTWARN 1 #define RMTDBG 2 /* includes warning */ #define READ(fd) (_rmt_Ctp[fd][0]) #define WRITE(fd) (_rmt_Ptc[fd][1]) #define RMTHOST(fd) (_rmt_host[fd]) #define RSH_PATH "/usr/bin/rsh" #define RMT_PATH "/etc/rmt" #define UNAME_UNDEFINED -1 #define UNAME_LINUX 0 #define UNAME_IRIX 1 #define UNAME_UNKNOWN 2 extern int _rmt_Ctp[MAXUNIT][2]; extern int _rmt_Ptc[MAXUNIT][2]; extern int _rmt_host[MAXUNIT]; #define setoserror(err) (errno = err) /* TODO: multithread check */ /* prototypes */ int isrmt (int); void _rmt_abort(int); int _rmt_command(int, char *); int _rmt_dev (char *); int _rmt_status(int); int _rmt_msgson(void); void _rmt_msg(int level, const char *msg, ...); void _rmt_turnonmsgsbyenv(void); void rmt_turnonmsgs(int code); xfsdump-3.1.6+nmu1/librmt/rmtcommand.c0000644000000000000000000000300712620476160014553 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc.; provided copyright in * certain portions may be held by third parties as indicated herein. * All Rights Reserved. * * The code in this source file represents an aggregation of work from * Georgia Tech, Fred Fish, Jeff Lee, Arnold Robbins and other Silicon * Graphics engineers over the period 1985-2000. * * 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. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include "rmtlib.h" /* * _rmt_command --- attempt to perform a remote tape command */ int _rmt_command(fildes, buf) int fildes; char *buf; { register int blen; _rmt_msg(RMTDBG, "rmtcommand: fd = %d, buf = %s\n", fildes, buf); /* * try to make the request */ blen = strlen(buf); if (write(WRITE(fildes), buf, blen) == blen) { return(0); } /* * something went wrong. close down and go home */ _rmt_abort(fildes); setoserror( EIO ); return(-1); } xfsdump-3.1.6+nmu1/librmt/rmtclose.c0000644000000000000000000000314412620476160014244 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc.; provided copyright in * certain portions may be held by third parties as indicated herein. * All Rights Reserved. * * The code in this source file represents an aggregation of work from * Georgia Tech, Fred Fish, Jeff Lee, Arnold Robbins and other Silicon * Graphics engineers over the period 1985-2000. * * 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. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "rmtlib.h" static int _rmt_close(int); /* * Close a file. Looks just like close(2) to caller. */ int rmtclose (fildes) int fildes; { if (isrmt (fildes)) { /* no longer know what host we have for this fildes */ RMTHOST(fildes - REM_BIAS) = UNAME_UNKNOWN; return (_rmt_close (fildes - REM_BIAS)); } else { return (close (fildes)); } } /* * _rmt_close --- close a remote magtape unit and shut down */ static int _rmt_close(int fildes) { int rc; if (_rmt_command(fildes, "C\n") != -1) { rc = _rmt_status(fildes); _rmt_abort(fildes); return(rc); } return(-1); } xfsdump-3.1.6+nmu1/librmt/rmtdev.c0000644000000000000000000000252412607344125013716 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc.; provided copyright in * certain portions may be held by third parties as indicated herein. * All Rights Reserved. * * The code in this source file represents an aggregation of work from * Georgia Tech, Fred Fish, Jeff Lee, Arnold Robbins and other Silicon * Graphics engineers over the period 1985-2000. * * 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. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include /* * Test pathname to see if it is local or remote. A remote device * is any string that contains ":/dev/". Returns 1 if remote, * 0 otherwise. */ int _rmt_dev (path) register char *path; { if ((path = strchr (path, ':')) != (char *)0) { if (strncmp (path + 1, "/dev/", 5) == 0) { return (1); } } return (0); } xfsdump-3.1.6+nmu1/librmt/rmtwrite.c0000644000000000000000000000341612620476160014273 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc.; provided copyright in * certain portions may be held by third parties as indicated herein. * All Rights Reserved. * * The code in this source file represents an aggregation of work from * Georgia Tech, Fred Fish, Jeff Lee, Arnold Robbins and other Silicon * Graphics engineers over the period 1985-2000. * * 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. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include "rmtlib.h" static int _rmt_write(int, char *, unsigned int); /* * Write to stream. Looks just like write(2) to caller. */ int rmtwrite (fildes, buf, nbyte) int fildes; char *buf; unsigned int nbyte; { if (isrmt (fildes)) { return (_rmt_write (fildes - REM_BIAS, buf, nbyte)); } else { return (write (fildes, buf, nbyte)); } } /* * _rmt_write --- write a buffer to the remote tape */ static int _rmt_write(int fildes, char *buf, unsigned int nbyte) { char buffer[BUFMAGIC]; sprintf(buffer, "W%d\n", nbyte); if (_rmt_command(fildes, buffer) == -1) return(-1); if (write(WRITE(fildes), buf, nbyte) == nbyte) { return(_rmt_status(fildes)); } _rmt_abort(fildes); setoserror( EIO ); return(-1); } xfsdump-3.1.6+nmu1/librmt/rmtioctl.c0000644000000000000000000003325612620476160014260 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc.; provided copyright in * certain portions may be held by third parties as indicated herein. * All Rights Reserved. * * The code in this source file represents an aggregation of work from * Georgia Tech, Fred Fish, Jeff Lee, Arnold Robbins and other Silicon * Graphics engineers over the period 1985-2000. * * 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. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include "config.h" #include "rmtlib.h" #include "swap.h" /* * uses old_mtget IRIX structure since we don't bother * sending the "V" version command. */ struct irix_mtget { short mt_type; /* type of magtape device */ unsigned short mt_dsreg; /* ``drive status'' register */ short mt_erreg; /* ``error'' register */ short mt_resid; /* residual count */ int mt_fileno; /* file number of current position */ int mt_blkno; /* block number of current position */ }; struct linux32_mtget { int32_t mt_type; /* Type of magtape device. */ int32_t mt_resid; /* Residual count: */ /* The following registers are device dependent. */ int32_t mt_dsreg; /* Status register. */ int32_t mt_gstat; /* Generic (device independent) status. */ int32_t mt_erreg; /* Error register. */ /* The next two fields are not always used. */ int32_t mt_fileno; /* Number of current file on tape. */ int32_t mt_blkno; /* Current block number. */ }; struct linux64_mtget { int64_t mt_type; /* Type of magtape device. */ int64_t mt_resid; /* Residual count. */ /* The following registers are device dependent. */ int64_t mt_dsreg; /* Status register. */ int64_t mt_gstat; /* Generic (device independent) status. */ int64_t mt_erreg; /* Error register. */ /* The next two fields are not always used. */ int32_t mt_fileno; /* Number of current file on tape. */ int32_t mt_blkno; /* Current block number. */ }; /* IRIX tape device status values */ #define IRIX_MT_EOT 0x01 /* tape is at end of media */ #define IRIX_MT_BOT 0x02 /* tape is at beginning of media */ #define IRIX_MT_WPROT 0x04 /* tape is write-protected */ #define IRIX_MT_EW 0x08 /* hit early warning marker */ #define IRIX_MT_ONL 0x40 /* drive is online */ #define IRIX_MT_EOD 0x4000 /* tape is at end of data */ #define IRIX_MT_FMK 0x8000 /* tape is at file mark */ /* IRIX mt operations (mt_op values for MTIOCTOP) */ #define IRIX_MTWEOF 0 /* write an end-of-file record */ #define IRIX_MTFSF 1 /* forward space file */ #define IRIX_MTBSF 2 /* backward space file */ #define IRIX_MTFSR 3 /* forward space record */ #define IRIX_MTBSR 4 /* backward space record */ #define IRIX_MTREW 5 /* rewind */ #define IRIX_MTOFFL 6 /* rewind and put the drive offline */ #define IRIX_MTERASE 12 /* erase tape from current position to EOT */ #define IRIX_MTUNLOAD 13 /* unload tape from drive */ /* std (common) mt op codes */ #define STD_MTWEOF 0 /* write an end-of-file record */ #define STD_MTFSF 1 /* forward space file */ #define STD_MTBSF 2 /* backward space file */ #define STD_MTFSR 3 /* forward space record */ #define STD_MTBSR 4 /* backward space record */ #define STD_MTREW 5 /* rewind */ #define STD_MTOFFL 6 /* rewind and put the drive offline */ #define MT_MAX 40 /* encompass potential range of mt_op values */ static int mtop_irixmap[MT_MAX] = {-1}; static int mtop_stdmap[MT_MAX] = {-1}; static void init_mtop_map(void) { /* set all other values to sentinel (-1) */ /* only map the ones which xfsdump/restore are interested in */ mtop_irixmap[MTWEOF] = IRIX_MTWEOF; mtop_irixmap[MTFSF] = IRIX_MTFSF; mtop_irixmap[MTBSF] = IRIX_MTBSF; mtop_irixmap[MTFSR] = IRIX_MTFSR; mtop_irixmap[MTBSR] = IRIX_MTBSR; mtop_irixmap[MTREW] = IRIX_MTREW; mtop_irixmap[MTOFFL] = IRIX_MTOFFL; mtop_irixmap[MTERASE] = IRIX_MTERASE; mtop_irixmap[MTUNLOAD] = IRIX_MTUNLOAD; mtop_stdmap[MTWEOF] = STD_MTWEOF; mtop_stdmap[MTFSF] = STD_MTFSF; mtop_stdmap[MTBSF] = STD_MTBSF; mtop_stdmap[MTFSR] = STD_MTFSR; mtop_stdmap[MTBSR] = STD_MTBSR; mtop_stdmap[MTREW] = STD_MTREW; mtop_stdmap[MTOFFL] = STD_MTOFFL; mtop_stdmap[MTUNLOAD] = STD_MTOFFL; } static int _rmt_ioctl(int, unsigned int, void *); /* * Do ioctl on file. Looks just like ioctl(2) to caller. */ int rmtioctl(int fildes, unsigned int request, void *arg) { if (isrmt (fildes)) { return (_rmt_ioctl (fildes - REM_BIAS, request, arg)); } else { return (ioctl (fildes, request, arg)); } } /* * _rmt_ioctl --- perform raw tape operations remotely */ /* * WARNING: MTIOCGET code is highly dependent on the format * of mtget on different platforms * We only support Linux 32/ia64 and IRIX 32/64 for this case. * We use the result of uname(1) (in rmtopen()) and * the size of the mtget structure to determine which * architecture it is. */ static int _rmt_ioctl(int fildes, unsigned int op, void *arg) { char buffer[BUFMAGIC]; int rc, cnt, ssize; char *p = NULL, *irixget = NULL, *linux32get = NULL, *linux64get = NULL; struct irix_mtget irix_mtget; struct linux32_mtget linux32_mtget; struct linux64_mtget linux64_mtget; int islinux32 = 1; /* is remote machine Linux 32 bit */ static int onetrip = 0; if (!onetrip) { onetrip = 1; init_mtop_map(); } /* * MTIOCTOP is the easy one. nothing is transfered in binary */ if (op == MTIOCTOP) { int mt_op = ((struct mtop *) arg)->mt_op; int mt_count = ((struct mtop *) arg)->mt_count; if (RMTHOST(fildes) == UNAME_UNDEFINED) { _rmt_msg(RMTWARN, _("rmtioctl: remote host type not supported for MTIOCTOP\n")); setoserror( EPROTONOSUPPORT ); return(-1); } /* map the linux op code to the irix op code */ if (RMTHOST(fildes) == UNAME_IRIX) { mt_op = mtop_irixmap[mt_op]; if (mt_op == -1) { setoserror( EINVAL ); return(-1); } } else if (RMTHOST(fildes) != UNAME_LINUX) { /* map the linux op code to the standard/fallback op code */ mt_op = mtop_stdmap[mt_op]; if (mt_op == -1) { setoserror( EINVAL ); return(-1); } } sprintf(buffer, "I%d\n%d\n", mt_op, mt_count); if (_rmt_command(fildes, buffer) == -1) { return(-1); } return(_rmt_status(fildes)); } else if (op == MTIOCGET) { /* * Grab the status and read it directly into the structure. * Since the data is binary data, and the other machine might * be IRIX or Linux of a different byte-order, * we have to be careful in converting the data. * * NOTE: the original /etc/rmt did NOT support a newline after * the S command, and Sun still does not. Neither does the * current bsd source, all the way through the tahoe release. * So do NOT add the \n to this! The sgi rmt command will * work either way. Olson, 4/91 */ if (_rmt_command(fildes, "S") == -1 || (rc = _rmt_status(fildes)) == -1) return(-1); /* If undefined then try and define it by looking * and the size of the get structure. * If we know our rmt host, then verify that the * structure is the correct size for the supported ones */ switch (RMTHOST(fildes)) { case UNAME_UNDEFINED: _rmt_msg(RMTWARN, _("rmtioctl: remote host type not supported for MTIOCGET\n")); setoserror( EPROTONOSUPPORT ); return(-1); case UNAME_IRIX: if (sizeof(struct irix_mtget) != rc) { _rmt_msg(RMTWARN, _("rmtioctl: IRIX mtget structure of wrong size" " - got %d, wanted %d\n"), rc, sizeof(struct irix_mtget)); setoserror( EPROTONOSUPPORT ); return(-1); } break; case UNAME_LINUX: if (sizeof(struct linux32_mtget) == rc) { islinux32 = 1; } else if (sizeof(struct linux64_mtget) == rc) { islinux32 = 0; } else { _rmt_msg(RMTWARN, _("rmtioctl: Linux mtget structure of wrong size " "- got %d, wanted %d or %d\n"), rc, sizeof(struct linux32_mtget), sizeof(struct linux64_mtget)); setoserror( EPROTONOSUPPORT ); return(-1); } break; default: setoserror( EPROTONOSUPPORT ); return(-1); } assert(RMTHOST(fildes)==UNAME_LINUX || RMTHOST(fildes)==UNAME_IRIX); if (RMTHOST(fildes) == UNAME_IRIX) { p = irixget = (char *)&irix_mtget; } else if (islinux32) { p = linux32get = (char *)&linux32_mtget; } else { p = linux64get = (char *)&linux64_mtget; } /* read in all the data */ ssize = rc; for (; ssize > 0; ssize -= cnt, p += cnt) { cnt = read(READ(fildes), p, ssize); if (cnt <= 0) { _rmt_abort(fildes); setoserror( EIO ); return(-1); } } /* * May need to byteswap */ if (RMTHOST(fildes) == UNAME_IRIX) { struct irix_mtget *irixp = (struct irix_mtget *)irixget; if (irixp->mt_type > 0xff) { /* assume that mt_type should fit in 1 byte */ irixp->mt_type = INT_SWAP(irixp->mt_type, irixp->mt_type); irixp->mt_dsreg = INT_SWAP(irixp->mt_dsreg, irixp->mt_dsreg); irixp->mt_erreg = INT_SWAP(irixp->mt_erreg, irixp->mt_erreg); irixp->mt_resid = INT_SWAP(irixp->mt_resid, irixp->mt_resid); irixp->mt_fileno = INT_SWAP(irixp->mt_fileno, irixp->mt_fileno); irixp->mt_blkno = INT_SWAP(irixp->mt_blkno, irixp->mt_blkno); } } else if (islinux32) { struct linux32_mtget *linuxp = (struct linux32_mtget *)linux32get; if (linuxp->mt_type > 0xffff) { /* assume that mt_type should fit in 2 bytes */ linuxp->mt_type = INT_SWAP(linuxp->mt_type, linuxp->mt_type); linuxp->mt_dsreg = INT_SWAP(linuxp->mt_dsreg, linuxp->mt_dsreg); linuxp->mt_erreg = INT_SWAP(linuxp->mt_erreg, linuxp->mt_erreg); linuxp->mt_resid = INT_SWAP(linuxp->mt_resid, linuxp->mt_resid); linuxp->mt_fileno = INT_SWAP(linuxp->mt_fileno, linuxp->mt_fileno); linuxp->mt_blkno = INT_SWAP(linuxp->mt_blkno, linuxp->mt_blkno); linuxp->mt_gstat = INT_SWAP(linuxp->mt_gstat, linuxp->mt_gstat); } } else { struct linux64_mtget *linuxp = (struct linux64_mtget *)linux64get; if (linuxp->mt_type > 0xffff) { /* assume that mt_type should fit in 2 bytes */ linuxp->mt_type = INT_SWAP(linuxp->mt_type, linuxp->mt_type); linuxp->mt_dsreg = INT_SWAP(linuxp->mt_dsreg, linuxp->mt_dsreg); linuxp->mt_erreg = INT_SWAP(linuxp->mt_erreg, linuxp->mt_erreg); linuxp->mt_resid = INT_SWAP(linuxp->mt_resid, linuxp->mt_resid); linuxp->mt_fileno = INT_SWAP(linuxp->mt_fileno, linuxp->mt_fileno); linuxp->mt_blkno = INT_SWAP(linuxp->mt_blkno, linuxp->mt_blkno); linuxp->mt_gstat = INT_SWAP(linuxp->mt_gstat, linuxp->mt_gstat); } } /* * now mtget has the correct (byte-swapped if needed) data, * so we just need to copy over the fields which are possibly * of different length and different semantics. */ if (RMTHOST(fildes) == UNAME_IRIX) { struct mtget *dstp = (struct mtget *)arg; struct irix_mtget *srcp = (struct irix_mtget *)irixget; short status = srcp->mt_dsreg; dstp->mt_type = srcp->mt_type; dstp->mt_erreg = srcp->mt_erreg; dstp->mt_resid = srcp->mt_resid; dstp->mt_fileno = srcp->mt_fileno; dstp->mt_blkno = srcp->mt_blkno; dstp->mt_dsreg = srcp->mt_dsreg; /* different semantics */ /* need to do tape status conversions */ dstp->mt_gstat = 0; if (status & IRIX_MT_EOT) dstp->mt_gstat |= GMT_EOT(0xffffffff); if (status & IRIX_MT_BOT) dstp->mt_gstat |= GMT_BOT(0xffffffff); if (status & IRIX_MT_WPROT) dstp->mt_gstat |= GMT_WR_PROT(0xffffffff); if (status & IRIX_MT_ONL) dstp->mt_gstat |= GMT_ONLINE(0xffffffff); if (status & IRIX_MT_EOD) dstp->mt_gstat |= GMT_EOD(0xffffffff); if (status & IRIX_MT_FMK) dstp->mt_gstat |= GMT_EOF(0xffffffff); if (status & IRIX_MT_EW) ;/* No GMT_ to map it to */ } else if (islinux32) { struct mtget *dstp = (struct mtget *)arg; struct linux32_mtget *srcp = (struct linux32_mtget *)linux32get; dstp->mt_type = srcp->mt_type; dstp->mt_erreg = srcp->mt_erreg; dstp->mt_resid = srcp->mt_resid; dstp->mt_fileno = srcp->mt_fileno; dstp->mt_blkno = srcp->mt_blkno; dstp->mt_dsreg = srcp->mt_dsreg; dstp->mt_gstat = srcp->mt_gstat; } else { struct mtget *dstp = (struct mtget *)arg; struct linux64_mtget *srcp = (struct linux64_mtget *)linux64get; dstp->mt_type = srcp->mt_type; dstp->mt_erreg = srcp->mt_erreg; dstp->mt_resid = srcp->mt_resid; dstp->mt_fileno = srcp->mt_fileno; dstp->mt_blkno = srcp->mt_blkno; dstp->mt_dsreg = srcp->mt_dsreg; dstp->mt_gstat = srcp->mt_gstat; } return(0); } else { setoserror( EINVAL ); return(-1); } } xfsdump-3.1.6+nmu1/librmt/rmtlseek.c0000644000000000000000000000331112620476160014236 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc.; provided copyright in * certain portions may be held by third parties as indicated herein. * All Rights Reserved. * * The code in this source file represents an aggregation of work from * Georgia Tech, Fred Fish, Jeff Lee, Arnold Robbins and other Silicon * Graphics engineers over the period 1985-2000. * * 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. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include "rmtlib.h" static off_t _rmt_lseek(int, off_t, int); /* * Perform lseek on file. Looks just like lseek(2) to caller. */ off_t rmtlseek (fildes, offset, whence) int fildes; off_t offset; int whence; { if (isrmt (fildes)) { return (_rmt_lseek (fildes - REM_BIAS, offset, whence)); } else { return (lseek (fildes, offset, whence)); } } /* * _rmt_lseek --- perform an imitation lseek operation remotely */ static off_t _rmt_lseek(int fildes, off_t offset, int whence) { char buffer[BUFMAGIC]; sprintf(buffer, "L%ld\n%d\n", (long)offset, whence); if (_rmt_command(fildes, buffer) == -1) return(-1); return(_rmt_status(fildes)); } xfsdump-3.1.6+nmu1/librmt/rmtabort.c0000644000000000000000000000242412620476160014246 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc.; provided copyright in * certain portions may be held by third parties as indicated herein. * All Rights Reserved. * * The code in this source file represents an aggregation of work from * Georgia Tech, Fred Fish, Jeff Lee, Arnold Robbins and other Silicon * Graphics engineers over the period 1985-2000. * * 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. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "rmtlib.h" /* * abort --- close off a remote tape connection */ void _rmt_abort(int fildes) { close(READ(fildes)); close(WRITE(fildes)); READ(fildes) = -1; WRITE(fildes) = -1; RMTHOST(fildes) = -1; _rmt_msg(RMTDBG, "rmtabort(%d)\n", fildes); } xfsdump-3.1.6+nmu1/librmt/Makefile0000644000000000000000000000102712607344125013706 0ustar # # Copyright (c) 2000-2001 Silicon Graphics, Inc. # TOPDIR = .. include $(TOPDIR)/include/builddefs LTLIBRARY = librmt.la LTLDFLAGS = # empty, forces a static-only library build HFILES = rmtlib.h CFILES = \ isrmt.c rmtclose.c rmtdev.c rmtisatty.c rmtread.c \ rmtabort.c rmtcommand.c rmtfstat.c rmtlseek.c rmtstatus.c \ rmtaccess.c rmtcreat.c rmtioctl.c rmtopen.c rmtwrite.c \ rmtmsg.c default: ltdepend $(LTLIBRARY) include $(BUILDRULES) install install-dev: default -include .ltdep xfsdump-3.1.6+nmu1/librmt/rmtread.c0000644000000000000000000000355212620476160014055 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc.; provided copyright in * certain portions may be held by third parties as indicated herein. * All Rights Reserved. * * The code in this source file represents an aggregation of work from * Georgia Tech, Fred Fish, Jeff Lee, Arnold Robbins and other Silicon * Graphics engineers over the period 1985-2000. * * 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. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include "rmtlib.h" static int _rmt_read(int, char *, unsigned int); /* * Read from stream. Looks just like read(2) to caller. */ int rmtread (fildes, buf, nbyte) int fildes; char *buf; unsigned int nbyte; { if (isrmt (fildes)) { return (_rmt_read (fildes - REM_BIAS, buf, nbyte)); } else { return (read (fildes, buf, nbyte)); } } /* * _rmt_read --- read a buffer from a remote tape */ static int _rmt_read(int fildes, char *buf, unsigned int nbyte) { int rc, i; char buffer[BUFMAGIC]; sprintf(buffer, "R%d\n", nbyte); if (_rmt_command(fildes, buffer) == -1 || (rc = _rmt_status(fildes)) == -1) return(-1); for (i = 0; i < rc; i += nbyte, buf += nbyte) { nbyte = read(READ(fildes), buf, rc); if (nbyte <= 0) { _rmt_abort(fildes); setoserror(EIO); return(-1); } } return(rc); } xfsdump-3.1.6+nmu1/librmt/rmtfstat.c0000644000000000000000000000460312620476160014261 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc.; provided copyright in * certain portions may be held by third parties as indicated herein. * All Rights Reserved. * * The code in this source file represents an aggregation of work from * Georgia Tech, Fred Fish, Jeff Lee, Arnold Robbins and other Silicon * Graphics engineers over the period 1985-2000. * * 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. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "rmtlib.h" #include #include #include #include #include static int _rmt_fstat(int, char *); /* * Get file status. Looks just like fstat(2) to caller. */ int rmtfstat (fildes, buf) int fildes; struct stat *buf; { if (isrmt (fildes)) { return (_rmt_fstat (fildes - REM_BIAS, (char *)buf)); } else { int i; i = fstat(fildes, buf); return i; } } static int _rmt_fstat(int fildes, char *arg) { char buffer[ BUFMAGIC ]; int rc, cnt, adj_rc; sprintf( buffer, "Z%d\n", fildes ); /* * grab the status and read it directly into the structure * this assumes that the status buffer is (hopefully) not * padded and that 2 shorts fit in a long without any word * alignment problems, ie - the whole struct is contiguous * NOTE - this is probably NOT a good assumption. */ if (_rmt_command(fildes, buffer) == -1 || (rc = _rmt_status(fildes)) == -1) return(-1); /* adjust read count to prevent overflow */ adj_rc = (rc > sizeof(struct stat)) ? sizeof(struct stat) : rc ; rc -= adj_rc; for (; adj_rc > 0; adj_rc -= cnt, arg += cnt) { cnt = read(READ(fildes), arg, adj_rc); if (cnt <= 0) { abortit: _rmt_abort(fildes); setoserror( EIO ); return(-1); } } /* handle any bytes we didn't know what to do with */ while (rc-- > 0) if (read(READ(fildes), buffer, 1) <= 0) goto abortit; return(0); } xfsdump-3.1.6+nmu1/librmt/rmtisatty.c0000644000000000000000000000226212607344125014454 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc.; provided copyright in * certain portions may be held by third parties as indicated herein. * All Rights Reserved. * * The code in this source file represents an aggregation of work from * Georgia Tech, Fred Fish, Jeff Lee, Arnold Robbins and other Silicon * Graphics engineers over the period 1985-2000. * * 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. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "rmtlib.h" /* * Rmtisatty. Do the isatty function. */ int rmtisatty (fd) int fd; { if (isrmt (fd)) { return (0); } else { return (isatty (fd)); } } xfsdump-3.1.6+nmu1/librmt/rmtaccess.c0000644000000000000000000000244012607344125014376 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc.; provided copyright in * certain portions may be held by third parties as indicated herein. * All Rights Reserved. * * The code in this source file represents an aggregation of work from * Georgia Tech, Fred Fish, Jeff Lee, Arnold Robbins and other Silicon * Graphics engineers over the period 1985-2000. * * 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. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "rmtlib.h" /* * Test pathname for specified access. Looks just like access(2) * to caller. */ int rmtaccess (path, amode) char *path; int amode; { if (_rmt_dev (path)) { return (0); /* Let /etc/rmt find out */ } else { return (access (path, amode)); } } xfsdump-3.1.6+nmu1/librmt/rmtcreat.c0000644000000000000000000000262512607344125014240 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc.; provided copyright in * certain portions may be held by third parties as indicated herein. * All Rights Reserved. * * The code in this source file represents an aggregation of work from * Georgia Tech, Fred Fish, Jeff Lee, Arnold Robbins and other Silicon * Graphics engineers over the period 1985-2000. * * 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. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* * Create a file from scratch. Looks just like creat(2) to the caller. */ #include #include #include /* use this one for S5 with remote stuff */ #include "rmtlib.h" extern int rmtopen(char*, int, int); int rmtcreat (path, mode) char *path; int mode; { if (_rmt_dev (path)) { return (rmtopen (path, 1 | O_CREAT, mode)); } else { return (creat (path, mode)); } } xfsdump-3.1.6+nmu1/librmt/rmtstatus.c0000644000000000000000000000373112620476160014464 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc.; provided copyright in * certain portions may be held by third parties as indicated herein. * All Rights Reserved. * * The code in this source file represents an aggregation of work from * Georgia Tech, Fred Fish, Jeff Lee, Arnold Robbins and other Silicon * Graphics engineers over the period 1985-2000. * * 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. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include "rmtlib.h" /* * _rmt_status --- retrieve the status from the pipe */ int _rmt_status(fildes) int fildes; { int i; char c, *cp; char buffer[BUFMAGIC]; /* * read the reply command line */ for (i = 0, cp = buffer; i < BUFMAGIC; i++, cp++) { if (read(READ(fildes), cp, 1) != 1) { _rmt_abort(fildes); setoserror( EIO ); return(-1); } if (*cp == '\n') { *cp = 0; break; } } if (i == BUFMAGIC) { _rmt_abort(fildes); setoserror( EIO ); return(-1); } /* * check the return status */ for (cp = buffer; *cp; cp++) if (*cp != ' ') break; if (*cp == 'E' || *cp == 'F') { setoserror( atoi(cp + 1) ); while (read(READ(fildes), &c, 1) == 1) if (c == '\n') break; if (*cp == 'F') _rmt_abort(fildes); return(-1); } /* * check for mis-synced pipes */ if (*cp != 'A') { _rmt_abort(fildes); setoserror( EIO ); return(-1); } return(atoi(cp + 1)); } xfsdump-3.1.6+nmu1/librmt/rmtmsg.c0000644000000000000000000000366012620476160013730 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc.; provided copyright in * certain portions may be held by third parties as indicated herein. * All Rights Reserved. * * The code in this source file represents an aggregation of work from * Georgia Tech, Fred Fish, Jeff Lee, Arnold Robbins and other Silicon * Graphics engineers over the period 1985-2000. * * 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. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include "config.h" #include "rmtlib.h" /* * Provide functions for warning and debug messages. */ static int rmt_debug_code = 0; static void checkcode(void) { if (rmt_debug_code != RMTWARN && rmt_debug_code != RMTDBG) { rmt_debug_code = 0; } } void _rmt_turnonmsgsbyenv(void) { char *rmt_debug_str = getenv("RMTDEBUG"); if (rmt_debug_str != NULL) { rmt_debug_code = atoi(rmt_debug_str); checkcode(); } } void rmt_turnonmsgs(int code) { rmt_debug_code = code; checkcode(); } int _rmt_msgson(void) { return rmt_debug_code; } #define RMT_MAX_MSG_STR 256 void _rmt_msg(int level, const char *msg, ...) { static char msg_str[RMT_MAX_MSG_STR]; va_list arg; if (rmt_debug_code >= level) { va_start(arg, msg); vsprintf(msg_str, msg, arg); va_end(arg); fprintf(stderr, "%s%s", level==RMTWARN ? _("WARNING: "):"", msg_str); } } xfsdump-3.1.6+nmu1/install-sh0000755000000000000000000001546112607344146012773 0ustar #! /bin/bash # # Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved. # # This script emulates bsd install and also recognises # two environment variables, with the following semantics :- # # $DIST_MANIFEST - if set, the name of the file to append manifest # information in the following format: # File : f mode owner group src target # Directory: d mode owner group target # Symlink : l linkval target # # $DIST_ROOT - if set, prepend to target # # The sematics of all combinations of these two variables # are as follows: # # $DIST_MANIFEST? $DIST_ROOT? | Copy? Append Manifest? # -----------------------------+-------------------------- # not set not set | yes no # not set set | yes no # set not set | no yes # set set | yes yes # _usage() { echo "Usage: $prog [-o owner] [-g group] [-m mode] -d directory" echo "or $prog [-D] [-o owner] [-g group] [-m mode] file directory/file" echo "or $prog [-o owner] [-g group] [-m mode] file [file ...] directory" echo "or $prog -S file target (creates \"target\" symlink)" echo "or $prog -T lt_arg [-o owner] [-g group] [-m mode] libtool.lai directory" echo "" echo "The \$DIST_MANIFEST and \$DIST_ROOT environment variables affect the" echo "behaviour of this command - see comments in the script." echo "The -D flag is only available for the second usage, and causes" echo "the target directory to be created before installing the file." echo "" exit 1 } _chown () { _st=255 if [ $# -eq 3 ] ; then chown $1:$2 $3 _st=$? if [ $_st -ne 0 ] ; then if [ $REAL_UID != '0' ] ; then if [ ! -f $DIST_ROOT/.chown.quiet ] ; then echo '===============================================' echo Ownership of files under ${DIST_ROOT:-/} echo cannot be changed echo '===============================================' if [ -n "$DIST_ROOT" ] ; then touch $DIST_ROOT/.chown.quiet fi fi _st=0 fi fi fi return $_st } _manifest () { echo $* | sed -e 's/\/\//\//g' >>${DIST_MANIFEST:-/dev/null} } prog=`basename $0` HERE=`pwd` dflag=false Dflag=false Sflag=false Tflag=false DIRMODE=755 FILEMODE=644 OWNER=`id -u` GROUP=`id -g` REAL_UID=$OWNER # default is to install and don't append manifest INSTALL=true MANIFEST=: : ${DIST_ROOT:=${DESTDIR}} [ -n "$DIST_MANIFEST" -a -z "$DIST_ROOT" ] && INSTALL=false [ -n "$DIST_MANIFEST" ] && MANIFEST="_manifest" [ $# -eq 0 ] && _usage if $INSTALL then CP=cp; LN=ln; MKDIR=mkdir; CHMOD=chmod; CHOWN=_chown else CP=true; LN=true; MKDIR=true; CHMOD=true; CHOWN=true fi [ -n "$DIST_ROOT" -a $REAL_UID -ne 0 ] && CHOWN=true while getopts "Dcm:d:S:o:g:T:" c $* do case $c in c) ;; g) GROUP=$OPTARG ;; o) OWNER=$OPTARG ;; m) DIRMODE=`expr $OPTARG` FILEMODE=$DIRMODE ;; D) Dflag=true ;; S) symlink=$OPTARG Sflag=true ;; d) dir=$DIST_ROOT/$OPTARG dflag=true ;; T) lt_install=$OPTARG Tflag=true ;; *) _usage ;; esac done shift `expr $OPTIND - 1` status=0 if $dflag then # # first usage # $MKDIR -p $dir status=$? if [ $status -eq 0 ] then $CHMOD $DIRMODE $dir status=$? fi if [ $status -eq 0 ] then $CHOWN $OWNER $GROUP $dir status=$? fi $MANIFEST d $DIRMODE $OWNER $GROUP ${dir#$DIST_ROOT} elif $Sflag then # # fourth usage (symlink) # if [ $# -ne 1 ] then _usage else target=$DIST_ROOT/$1 fi $LN -s -f $symlink $target status=$? $MANIFEST l $symlink ${target#$DIST_ROOT} elif $Tflag then # # -T (install libs built by libtool) # if [ $# -ne 2 ] then _usage else libtool_lai=$1 # source the libtool variables if [ ! -f $libtool_lai ] then echo "$prog: Unable to find libtool library file $libtool_lai" exit 2 fi . ./$libtool_lai target=$DIST_ROOT/$2 fi case $lt_install in so_dot_version) # Loop until we find libfoo.so.x.y.z, then break out. for solib in $library_names do # does it have enough parts? libfoo.so.x.y.z == 5 cnt=`echo "$solib" | sed -e 's/\./ /g' | wc -w` if [ $cnt -eq 5 ] then install_name=$target/$solib $CP $solib $install_name status=$? $MANIFEST f $FILEMODE $OWNER $GROUP $HERE/$solib ${install_name#$DIST_ROOT} break fi done ;; so_*) case $lt_install in so_dot_current) # ln -s libfoo.so.x.y.z to libfoo.so.x from_parts=5 # libfoo.so.x.y.z to_parts=3 # libfoo.so.x ;; so_base) # ln -s libfoo.so.x to libfoo.so from_parts=3 # libfoo.so.x to_parts=2 # libfoo.so ;; *) echo "$prog: -T $lt_install invalid" exit 2 ;; esac # Loop until we find the names, then break out. for solib in $library_names do # does it have enough parts? cnt=`echo "$solib" | sed -e 's/\./ /g' | wc -w` if [ $cnt -eq $from_parts ] then from_name=$solib elif [ $cnt -eq $to_parts ] then to_name=$solib fi if [ -n "$from_name" ] && [ -n "$to_name" ] then install_name=$target/$to_name $LN -s -f $from_name $install_name status=$? $MANIFEST l $from_name ${install_name#$DIST_ROOT} break fi done ;; old_lib) install_name=$target/$old_library $CP $old_library $install_name status=$? $MANIFEST f $FILEMODE $OWNER $GROUP $HERE/$old_library ${install_name#$DIST_ROOT} ;; *) echo "$prog: -T $lt_install invalid" exit 2 ;; esac case $lt_install in old_lib|so_dot_version) if [ $status -eq 0 ] then $CHMOD $FILEMODE $install_name $CHOWN $OWNER $GROUP $install_name fi ;; esac else list="" dir="" if [ $# -eq 2 ] then # # second usage # f=$1 dir=$DIST_ROOT/$2 if $Dflag then mkdir -p `dirname $dir` fi $CP $f $dir status=$? if [ $status -eq 0 ] then if [ -f $dir/$f ] then $CHMOD $FILEMODE $dir/$f status=$? if [ $status -eq 0 ] then $CHOWN $OWNER $GROUP $dir/$f status=$? fi $MANIFEST f $FILEMODE $OWNER $GROUP $HERE/$f ${dir#$DIST_ROOT}/$f else $CHMOD $FILEMODE $dir status=$? if [ $status -eq 0 ] then $CHOWN $OWNER $GROUP $dir status=$? fi $MANIFEST f $FILEMODE $OWNER $GROUP $HERE/$dir ${dir#$DIST_ROOT} fi fi else # # third usage # n=1 while [ $# -gt 0 ] do if [ $# -gt 1 ] then list="$list $1" else dir=$DIST_ROOT/$1 fi shift done # echo DIR=$dir list=\"$list\" for f in $list do $CP $f $dir status=$? if [ $status -eq 0 ] then $CHMOD $FILEMODE $dir/$f status=$? if [ $status -eq 0 ] then $CHOWN $OWNER $GROUP $dir/$f status=$? fi $MANIFEST f $FILEMODE $OWNER $GROUP $HERE/$f ${dir#$DIST_ROOT}/$f fi [ $status -ne 0 ] && break done fi fi exit $status xfsdump-3.1.6+nmu1/Makefile0000644000000000000000000000641112607344125012417 0ustar # # Copyright (c) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. # ifeq ("$(origin V)", "command line") BUILD_VERBOSE = $(V) endif ifndef BUILD_VERBOSE BUILD_VERBOSE = 0 endif ifeq ($(BUILD_VERBOSE),1) Q = else Q = @ endif MAKEOPTS = --no-print-directory Q=$(Q) TOPDIR = . HAVE_BUILDDEFS = $(shell test -f $(TOPDIR)/include/builddefs && echo yes || echo no) ifeq ($(HAVE_BUILDDEFS), yes) include $(TOPDIR)/include/builddefs endif SRCDIR = $(PKG_NAME)-$(PKG_VERSION) SRCTAR = $(PKG_NAME)-$(PKG_VERSION).tar.gz CONFIGURE = aclocal.m4 configure config.guess config.sub install-sh ltmain.sh LSRCFILES = configure.ac release.sh README VERSION $(CONFIGURE) SRCTARINC = m4/libtool.m4 m4/lt~obsolete.m4 m4/ltoptions.m4 m4/ltsugar.m4 \ m4/ltversion.m4 .gitcensus $(CONFIGURE) LDIRT = config.log .ltdep .dep config.status config.cache confdefs.h \ conftest* built .census install.* install-dev.* *.gz \ autom4te.cache/* libtool include/builddefs include/config.h ifeq ($(HAVE_BUILDDEFS), yes) LDIRDIRT = $(SRCDIR) LDIRT += $(SRCTAR) endif LIB_SUBDIRS = librmt TOOL_SUBDIRS = common inventory invutil dump restore m4 man doc po debian SUBDIRS = include $(LIB_SUBDIRS) $(TOOL_SUBDIRS) default: include/builddefs include/config.h ifeq ($(HAVE_BUILDDEFS), no) $(Q)$(MAKE) $(MAKEOPTS) -C . $@ else $(Q)$(MAKE) $(MAKEOPTS) $(SUBDIRS) endif # tool/lib dependencies $(LIB_SUBDIRS) $(TOOL_SUBDIRS): include invutil dump restore: librmt ifeq ($(HAVE_BUILDDEFS), yes) include $(BUILDRULES) else clean: # if configure hasn't run, nothing to clean endif # Recent versions of libtool require the -i option for copying auxiliary # files (config.sub, config.guess, install-sh, ltmain.sh), while older # versions will copy those files anyway, and don't understand -i. LIBTOOLIZE_INSTALL = `libtoolize -n -i >/dev/null 2>/dev/null && echo -i` configure: libtoolize -c $(LIBTOOLIZE_INSTALL) -f cp include/install-sh . aclocal -I m4 autoconf include/builddefs: configure ./configure $$LOCAL_CONFIGURE_OPTIONS include/config.h: include/builddefs ## Recover from the removal of $@ @if test -f $@; then :; else \ rm -f include/builddefs; \ $(MAKE) $(AM_MAKEFLAGS) include/builddefs; \ fi install: default $(addsuffix -install,$(SUBDIRS)) $(INSTALL) -m 755 -d $(PKG_DOC_DIR) $(INSTALL) -m 644 README $(PKG_DOC_DIR) install-dev: default $(addsuffix -install-dev,$(SUBDIRS)) %-install: $(Q)$(MAKE) -C $* install %-install-dev: $(Q)$(MAKE) -C $* install-dev distclean: clean rm -f $(LDIRT) realclean: distclean rm -f $(CONFIGURE) .gitcensus # # All this gunk is to allow for a make dist on an unconfigured tree # dist: include/builddefs include/config.h default ifeq ($(HAVE_BUILDDEFS), no) $(Q)$(MAKE) $(MAKEOPTS) -C . $@ else $(Q)$(MAKE) $(MAKEOPTS) $(SRCTAR) endif deb: include/builddefs include/config.h ifeq ($(HAVE_BUILDDEFS), no) $(MAKE) $(MAKEOPTS) -C . $@ else $(Q)$(MAKE) $(MAKEOPTS) $(SRCDIR) $(Q)cd $(SRCDIR) && dpkg-buildpackage endif $(SRCDIR) : $(_FORCE) $(SRCTAR) rm -fr $@ $(Q)$(TAR) -zxvf $(SRCTAR) $(SRCTAR) : default $(SRCTARINC) .gitcensus $(Q)$(TAR) --transform "s,^,$(SRCDIR)/," -zcf $(SRCDIR).tar.gz \ `cat .gitcensus` $(SRCTARINC) echo Wrote: $@ .gitcensus: $(_FORCE) $(Q) if test -d .git; then \ git ls-files > .gitcensus && echo "new .gitcensus"; \ fi xfsdump-3.1.6+nmu1/po/0000755000000000000000000000000012643557274011406 5ustar xfsdump-3.1.6+nmu1/po/pl.po0000644000000000000000000035210212607344125012351 0ustar # Polish translation for xfsdump. # This file is distributed under the same license as the xfsdump package. # Jakub Bogusz , 2011-2014. # msgid "" msgstr "" "Project-Id-Version: xfsdump 3.1.3+git\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2014-07-15 15:38+0200\n" "PO-Revision-Date: 2014-07-15 16:28+0200\n" "Last-Translator: Jakub Bogusz \n" "Language-Team: Polish \n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: .././common/cldmgr.c:87 #, c-format msgid "" "cannot create %s thread for stream %u: too many child threads (max allowed " "is %d)\n" msgstr "" "nie można utworzyć wÄ…tku %s dla strumienia %u: za dużo wÄ…tków potomnych " "(maksymalnie dozwolonych: %d)\n" #: .././common/cldmgr.c:102 #, c-format msgid "failed creating %s thread for stream %u: %s\n" msgstr "nie udaÅ‚o siÄ™ utworzyć wÄ…tku %s dla strumienia %u: %s\n" #: .././common/content_common.c:65 .././restore/content.c:6928 msgid "change media dialog" msgstr "zmiana noÅ›nika" #: .././common/content_common.c:75 .././restore/content.c:6940 #, c-format msgid "please change media in drive %u\n" msgstr "proszÄ™ zmienić noÅ›nik w napÄ™dzie %u\n" #: .././common/content_common.c:83 .././restore/content.c:6953 msgid "media change declined" msgstr "odmowa zmiany noÅ›nika" #: .././common/content_common.c:85 .././restore/content.c:6964 msgid "media changed" msgstr "noÅ›nik zmieniony" #: .././common/content_common.c:104 .././restore/content.c:6983 msgid "examining new media\n" msgstr "badanie nowego noÅ›nika\n" #: .././common/content_common.c:106 .././restore/content.c:6985 msgid "media change aborted\n" msgstr "zmiana noÅ›nika przerwana\n" #: .././common/content_common.c:109 .././common/dlog.c:490 #: .././restore/content.c:7021 .././restore/content.c:7154 #: .././restore/tree.c:2735 msgid "keyboard interrupt\n" msgstr "przerwanie z klawiatury\n" #: .././common/content_common.c:117 .././common/global.c:356 #: .././common/main.c:1964 .././restore/content.c:6993 #: .././restore/content.c:7029 .././restore/tree.c:2752 #: .././restore/tree.c:2793 msgid "end dialog" msgstr "koniec dialogu" #: .././common/dlog.c:111 #, c-format msgid "could not fstat stdin (fd %d): %s (%d)\n" msgstr "nie udaÅ‚o siÄ™ wykonać fstat na stdin (fd %d): %s (%d)\n" #: .././common/dlog.c:213 msgid " (default)" msgstr " (domyÅ›lne)" #: .././common/dlog.c:221 #, c-format msgid " (timeout in %u sec)" msgstr " (limit czasu %u s)" #: .././common/dlog.c:258 #, c-format msgid "please enter a value between 1 and %d inclusive " msgstr "proszÄ™ wpisać wartość miÄ™dzy 1 a %d włącznie " #: .././common/dlog.c:310 #, c-format msgid " (timeout in %u sec)\n" msgstr " (limit czasu %u s)\n" #: .././common/dlog.c:398 #, c-format msgid "(timeout in %d sec)" msgstr "(limit czasu %d s)" #: .././common/dlog.c:486 msgid "timeout\n" msgstr "limit czasu\n" #: .././common/dlog.c:495 msgid "hangup\n" msgstr "rozłączenie\n" #: .././common/dlog.c:499 msgid "terminate\n" msgstr "zakoÅ„czenie\n" #: .././common/dlog.c:503 msgid "keyboard quit\n" msgstr "wyjÅ›cie z klawiatury\n" #: .././common/dlog.c:508 msgid "abnormal dialog termination\n" msgstr "nieprawidÅ‚owe zakoÅ„czenie dialogu\n" #: .././common/drive.c:132 .././common/drive_minrmt.c:433 #: .././common/drive_minrmt.c:511 .././common/drive_minrmt.c:550 #: .././common/drive_scsitape.c:593 .././common/drive_scsitape.c:626 #: .././common/drive_scsitape.c:639 .././common/global.c:138 #: .././common/global.c:156 .././common/global.c:178 .././common/main.c:221 #: .././common/main.c:243 .././common/main.c:269 .././common/main.c:1136 #: .././common/media.c:118 .././dump/content.c:597 .././dump/content.c:616 #: .././dump/content.c:634 .././dump/content.c:669 .././dump/content.c:685 #: .././dump/content.c:1642 .././restore/content.c:980 #: .././restore/content.c:1006 .././restore/content.c:1067 #: .././restore/content.c:1096 .././restore/content.c:1118 #: .././restore/content.c:1164 #, c-format msgid "-%c argument missing\n" msgstr "brak argumentu dla -%c\n" #: .././common/drive.c:155 msgid "cannot specify source files and stdout together\n" msgstr "" "nie można okreÅ›lić jednoczeÅ›nie plików źródÅ‚owych i standardowego wyjÅ›cia\n" #: .././common/drive.c:158 msgid "cannot specify source files and stdin together\n" msgstr "" "nie można okreÅ›lić jednoczeÅ›nie plików źródÅ‚owych i standardowego wejÅ›cia\n" #: .././common/drive.c:186 msgid "no destination file(s) specified\n" msgstr "nie okreÅ›lono plików docelowych\n" #: .././common/drive.c:189 msgid "no source file(s) specified\n" msgstr "nie podano plików źródÅ‚owych\n" #: .././common/drive.c:223 #, c-format msgid "using %s strategy\n" msgstr "użyto strategii %s\n" #: .././common/drive_minrmt.c:455 #, c-format msgid "Minimal rmt cannot be used without specifying blocksize. Use -%c\n" msgstr "" "Minimalny rmt nie może być użyty bez podawania rozmiaru bloku. ProszÄ™ użyć -" "%c\n" #: .././common/drive_minrmt.c:520 .././common/drive_scsitape.c:602 #, c-format msgid "-%c argument must be between %u and %u: ignoring %u\n" msgstr "Argument -%c musi mieÅ›cić siÄ™ miÄ™dzy %u i %u: zignorowano %u\n" #: .././common/drive_minrmt.c:545 msgid "Overwrite command line option\n" msgstr "Opcja nadpisania z linii poleceÅ„\n" #: .././common/drive_minrmt.c:557 #, c-format msgid "-%c argument must be a positive number (MB): ignoring %u\n" msgstr "Argument -%c musi być liczbÄ… dodatniÄ… (MB): zignorowano %u\n" #: .././common/drive_minrmt.c:603 .././common/drive_scsitape.c:693 msgid "unable to allocate memory for I/O buffer ring\n" msgstr "nie można przydzielić pamiÄ™ci dla krÄ™gu buforów we/wy\n" #: .././common/drive_minrmt.c:607 .././common/drive_scsitape.c:697 msgid "not enough physical memory to pin down I/O buffer ring\n" msgstr "za maÅ‚o pamiÄ™ci fizycznej do podłączenia krÄ™gu buforów we/wy\n" #: .././common/drive_minrmt.c:611 .././common/drive_scsitape.c:701 msgid "not allowed to pin down I/O buffer ring\n" msgstr "brak uprawnieÅ„ do podłączenia krÄ™gu buforów we/wy\n" #: .././common/drive_minrmt.c:1162 .././common/drive_scsitape.c:1275 #, c-format msgid "could not forward space %d tape blocks: rval == %d, errno == %d (%s)\n" msgstr "" "nie udaÅ‚o siÄ™ przekierować bloków taÅ›my przestrzeni %d: rval == %d, errno == " "%d (%s)\n" #: .././common/drive_minrmt.c:1407 .././common/drive_scsitape.c:1522 msgid "unable to locate next mark in media file\n" msgstr "nie można zlokalizować nastÄ™pnego znacznika w pliku noÅ›nika\n" #: .././common/drive_minrmt.c:1431 #, c-format msgid "" "unexpected error attempting to read record: read returns %d, errno %s (%s)\n" msgstr "" "nieoczekiwany błąd podczas próby odczytu rekordu: read zwróciÅ‚o %d, errno %s " "(%s)\n" #: .././common/drive_minrmt.c:1458 .././common/drive_scsitape.c:1602 #, c-format msgid "valid record %lld but no mark\n" msgstr "poprawny rekord %lld, ale brak znacznika\n" #: .././common/drive_minrmt.c:1484 .././common/drive_scsitape.c:1628 #, c-format msgid "resynchronized at record %lld offset %u\n" msgstr "ponowna synchronizacja na rekordzie %lld, offset %u\n" #: .././common/drive_minrmt.c:1498 .././common/drive_scsitape.c:1641 #, c-format msgid "" "could not forward space one tape block beyond read error: rval == %d, errno " "== %d (%s)\n" msgstr "" "nie udaÅ‚o siÄ™ przemieÅ›cić taÅ›my o blok za miejsce błędu odczytu: rval == %d, " "errno == %d (%s)\n" #: .././common/drive_minrmt.c:2243 .././common/drive_scsitape.c:2426 msgid "advancing tape to next media file\n" msgstr "przewijanie taÅ›my do nastÄ™pnego pliku noÅ›nika\n" #: .././common/drive_minrmt.c:2265 .././common/drive_scsitape.c:2453 msgid "FSF tape command failed\n" msgstr "Polecenie FSF dla taÅ›my nie powiodÅ‚o siÄ™\n" #: .././common/drive_minrmt.c:2489 .././common/drive_scsitape.c:2727 #, c-format msgid "drive %u " msgstr "napÄ™d %u " #: .././common/drive_minrmt.c:2573 .././common/drive_scsitape.c:2930 #, c-format msgid "could not read from drive: %s (%d)\n" msgstr "nie powiódÅ‚ siÄ™ odczyt z napÄ™du: %s (%d)\n" #: .././common/drive_minrmt.c:2586 msgid "encountered EOD : assuming blank media\n" msgstr "napotkano EOD: przyjÄ™to czysty noÅ›nik\n" #: .././common/drive_minrmt.c:2589 msgid "encountered EOD : end of data\n" msgstr "napotkano EOD: koniec danych\n" #: .././common/drive_minrmt.c:2643 msgid "tape record checksum error\n" msgstr "błąd sumy kontrolnej rekordu na taÅ›mie\n" #: .././common/drive_minrmt.c:2758 .././common/drive_scsitape.c:3290 #, c-format msgid "" "recommended media file size of %llu Mb less than estimated file header size " "%llu Mb for %s\n" msgstr "" "zalecany rozmiar pliku noÅ›nika %llu Mb jest mniejszy niż przewidywany " "rozmiar nagłówka pliku %llu Mb dla %s\n" #: .././common/drive_minrmt.c:2832 msgid "audio" msgstr "dźwiÄ™k" #: .././common/drive_minrmt.c:2878 .././common/drive_scsitape.c:3566 #: .././common/drive_scsitape.c:3919 msgid "tape is write protected\n" msgstr "taÅ›ma jest zabezpieczona przed zapisem\n" #: .././common/drive_minrmt.c:2890 .././common/drive_scsitape.c:3576 msgid "tape media error on write operation\n" msgstr "błąd noÅ›nika taÅ›my podczas zapisu\n" #: .././common/drive_minrmt.c:2893 .././common/drive_scsitape.c:3579 msgid "no more data can be written to this tape\n" msgstr "na tej taÅ›mie nie można już zapisać wiÄ™cej danych\n" #: .././common/drive_minrmt.c:2965 .././common/drive_scsitape.c:3658 #, c-format msgid "RMTOPEN( %s, %d ) returns %d: errno=%d (%s)\n" msgstr "RMTOPEN( %s, %d ) zwraca %d: errno=%d (%s)\n" #: .././common/drive_minrmt.c:2979 .././common/drive_scsitape.c:3672 #, c-format msgid "RMTCLOSE( %d ) returns %d: errno=%d (%s)\n" msgstr "RMTCLOSE( %d ) zwraca %d: errno=%d (%s)\n" #: .././common/drive_minrmt.c:2992 .././common/drive_scsitape.c:3685 #, c-format msgid "RMTIOCTL( %d, %d, 0x%x ) returns %d: errno=%d (%s)\n" msgstr "RMTIOCTL( %d, %d, 0x%x ) zwraca %d: errno=%d (%s)\n" #: .././common/drive_minrmt.c:3007 .././common/drive_scsitape.c:3700 #, c-format msgid "RMTREAD( %d, 0x%x, %u ) returns %d: errno=%d (%s)\n" msgstr "RMTREAD( %d, 0x%x, %u ) zwraca %d: errno=%d (%s)\n" #: .././common/drive_minrmt.c:3022 .././common/drive_scsitape.c:3715 #, c-format msgid "RMTWRITE( %d, 0x%x, %u ) returns %d: errno=%d (%s)\n" msgstr "RMTWRITE( %d, 0x%x, %u ) zwraca %d: errno=%d (%s)\n" #: .././common/drive_minrmt.c:3043 .././common/drive_scsitape.c:3743 #, c-format msgid "attempt to access/open remote tape drive %s failed: %d (%s)\n" msgstr "" "próba dostÄ™pu/odczytu ze zdalnego napÄ™du taÅ›mowego %s nie powiodÅ‚a siÄ™: %d " "(%s)\n" #: .././common/drive_minrmt.c:3080 .././common/drive_scsitape.c:3870 msgid "preparing drive\n" msgstr "przygotowywanie napÄ™du\n" #: .././common/drive_minrmt.c:3167 .././common/drive_scsitape.c:4063 msgid "giving up attempt to determining tape record size\n" msgstr "poddano siÄ™ przy próbie okreÅ›lenia rozmiaru rekordu na taÅ›mie\n" #: .././common/drive_minrmt.c:3282 #, c-format msgid "unexpected tape error: errno %d nread %d blksz %d recsz %d \n" msgstr "nieoczekiwany błąd taÅ›my: errno %d nread %d blksz %d recsz %d\n" #: .././common/drive_minrmt.c:3305 .././common/drive_scsitape.c:4497 #, c-format msgid "media file header version (%d) invalid: advancing\n" msgstr "błędna wersja nagłówka pliku noÅ›nika (%d): przewijanie\n" #: .././common/drive_minrmt.c:3316 .././common/drive_scsitape.c:4508 msgid "may be an EFS dump at BOT\n" msgstr "pod BOT może być zrzut EFS\n" #: .././common/drive_minrmt.c:3321 msgid "This tape was erased earlier by xfsdump.\n" msgstr "Ta taÅ›ma byÅ‚a wczeÅ›niej wykasowana przez program xfsdump.\n" #: .././common/drive_minrmt.c:3327 .././common/drive_scsitape.c:4511 msgid "bad media file header at BOT indicates foreign or corrupted tape\n" msgstr "" "błędny nagłówek pliku noÅ›nika pod BOT oznacza obcÄ… lub uszkodzonÄ… taÅ›mÄ™\n" #: .././common/drive_minrmt.c:3354 .././common/drive_scsitape.c:4553 #: .././common/drive_scsitape.c:4592 msgid "cannot determine tape block size after two tries\n" msgstr "nie można okreÅ›lić rozmiaru bloku na taÅ›mie po dwóch próbach\n" #: .././common/drive_minrmt.c:3357 .././common/drive_scsitape.c:4563 #: .././common/drive_scsitape.c:4602 msgid "assuming media is corrupt or contains non-xfsdump data\n" msgstr "" "prawdopodobnie noÅ›nik jest uszkodzony lub zawiera dane inne niż xfsdump\n" #: .././common/drive_minrmt.c:3375 .././common/drive_scsitape.c:4581 #: .././common/drive_scsitape.c:4622 msgid "cannot determine tape block size\n" msgstr "nie można okreÅ›lić rozmiaru bloku na taÅ›mie\n" #: .././common/drive_minrmt.c:3526 .././common/drive_scsitape.c:4806 #, c-format msgid "record %lld corrupt: bad record checksum\n" msgstr "uszkodzony rekord %lld: błędna suma kontrolna rekordu\n" #: .././common/drive_minrmt.c:3536 .././common/drive_scsitape.c:4816 #, c-format msgid "record %lld corrupt: bad magic number\n" msgstr "uszkodzony rekord %lld: błędna liczba magiczna\n" #: .././common/drive_minrmt.c:3544 .././common/drive_scsitape.c:4824 #, c-format msgid "record %lld corrupt: null dump id\n" msgstr "uszkodzony rekord %lld: zerowy identyfikator zrzutu\n" #: .././common/drive_minrmt.c:3552 .././common/drive_scsitape.c:4832 #, c-format msgid "record %lld corrupt: dump id mismatch\n" msgstr "uszkodzony rekord %lld: niezgodność identyfikatora zrzutu\n" #: .././common/drive_minrmt.c:3563 .././common/drive_scsitape.c:4839 #, c-format msgid "record %lld corrupt: incorrect record size in header\n" msgstr "uszkodzony rekord %lld: nieprawidÅ‚owy rozmiar rekordu w nagłówku\n" #: .././common/drive_minrmt.c:3577 .././common/drive_scsitape.c:4846 #, c-format msgid "" "record %lld corrupt: record offset in header not a multiple of record size\n" msgstr "" "uszkodzony rekord %lld: pozycja rekordu w nagłówku nie jest wielokrotnoÅ›ciÄ… " "rozmiaru rekordu\n" #: .././common/drive_minrmt.c:3589 .././common/drive_scsitape.c:4858 #, c-format msgid "record %lld corrupt: incorrect record offset in header (0x%llx)\n" msgstr "" "uszkodzony rekord %lld: nieprawidÅ‚owa pozycja rekordu w nagłówku (0x%llx)\n" #: .././common/drive_minrmt.c:3600 .././common/drive_scsitape.c:4869 #, c-format msgid "record %lld corrupt: incorrect record padding offset in header\n" msgstr "" "uszkodzony rekord %lld: nieprawidÅ‚owa pozycja wyrównania rekordu w nagłówku\n" #: .././common/drive_minrmt.c:3637 msgid "read_record encountered EOD : assuming blank media\n" msgstr "napotkano EOD w read_record: prawdopodobnie czysty noÅ›nik\n" #: .././common/drive_minrmt.c:3640 msgid "read_record encountered EOD : end of data\n" msgstr "napotkano EOD w read_record: koniec danych\n" #: .././common/drive_minrmt.c:3655 msgid "unexpected EIO error attempting to read record\n" msgstr "nieoczekiwany błąd EIO przy próbie odczytu rekordu\n" #: .././common/drive_minrmt.c:3678 .././common/drive_scsitape.c:4958 #, c-format msgid "" "unexpected error attempting to read record %lld: read returns %d, errno %d " "(%s)\n" msgstr "" "nieoczekiwany błąd przy próbie odczytu rekordu %lld: odczyt zwróciÅ‚ %d, " "errno %d (%s)\n" #: .././common/drive_minrmt.c:3851 .././common/drive_minrmt.c:3859 msgid "KB" msgstr "kB" #: .././common/drive_minrmt.c:3856 msgid "MB" msgstr "MB" #: .././common/drive_minrmt.c:3863 .././common/drive_scsitape.c:5147 #, c-format msgid "" "I/O metrics: %u by %s%s %sring; %lld/%lld (%.0lf%%) records streamed; %.0lfB/" "s\n" msgstr "" "Pomiary we/wy: %u na %s%s, pierÅ›cieÅ„%s; przesÅ‚ano rekordów: %lld/%lld (%.0lf" "%%); %0lfB/s\n" #: .././common/drive_minrmt.c:3870 .././common/drive_scsitape.c:5154 msgid "pinned " msgstr " dowiÄ…zany" #: .././common/drive_scsitape.c:647 #, c-format msgid "-%c argument must be a positive number (Mb): ignoring %u\n" msgstr "argument -%c musi być liczbÄ… dodatniÄ… (MB): zignorowano %u\n" #: .././common/drive_scsitape.c:1575 #, c-format msgid "" "unexpected error attempting to read record: read returns %d, errno %d (%s)\n" msgstr "" "nieoczekiwany błąd przy próbie odczytu rekordu: odczyt zwróciÅ‚ %d, errno %d " "(%s)\n" #: .././common/drive_scsitape.c:2867 msgid "file mark missing from tape (hit EOD)\n" msgstr "brak znacznika pliku na taÅ›mie (napotkano EOD)\n" #: .././common/drive_scsitape.c:2870 msgid "writing file mark at EOD\n" msgstr "zapis znacznika pliku pod EOD\n" #: .././common/drive_scsitape.c:2874 #, c-format msgid "unable to write file mark at eod: %s (%d)\n" msgstr "nie udaÅ‚o siÄ™ zapisać znacznika pliku pod EOD: %s (%d)\n" #: .././common/drive_scsitape.c:2891 msgid "file mark missing from tape\n" msgstr "brak znacznika pliku na taÅ›mie\n" #: .././common/drive_scsitape.c:2940 msgid "unexpectedly encountered EOD at BOT: assuming corrupted media\n" msgstr "" "nieoczekiwanie napotkano EOD pod BOT: prawdopodobnie uszkodzony noÅ›nik\n" #: .././common/drive_scsitape.c:2990 msgid "unexpectedly encountered a file mark: assuming corrupted media\n" msgstr "" "nieoczekiwanie napotkano znacznik pliku: prawdopodobnie uszkodzony noÅ›nik\n" #: .././common/drive_scsitape.c:3196 #, c-format msgid "unable to set block size to %d\n" msgstr "nie udaÅ‚o siÄ™ ustawić rozmiaru bloku na %d\n" #: .././common/drive_scsitape.c:3750 #, c-format msgid "attempt to access/open device %s failed: %d (%s)\n" msgstr "próba dostÄ™pu/otwarcia urzÄ…dzenia %s nie powiodÅ‚a siÄ™: %d (%s)\n" #: .././common/drive_scsitape.c:3779 #, c-format msgid "attempt to get status of remote tape drive %s failed: %d (%s)\n" msgstr "" "próba uzyskania statusu zdalnego napÄ™du taÅ›mowego %s nie powiodÅ‚a siÄ™: %d " "(%s)\n" #: .././common/drive_scsitape.c:3786 #, c-format msgid "attempt to get status of tape drive %s failed: %d (%s)\n" msgstr "" "próba uzyskania statusu napÄ™du taÅ›mowego %s nie powiodÅ‚a siÄ™: %d (%s)\n" #: .././common/drive_scsitape.c:3954 msgid "giving up waiting for drive to indicate online\n" msgstr "poddano siÄ™ przy oczekiwaniu na gotowość napÄ™du\n" #: .././common/drive_scsitape.c:3962 #, c-format msgid "tape drive %s is not ready (0x%x): retrying ...\n" msgstr "napÄ™d taÅ›mowy %s nie jest gotowy (0x%x): ponawianie próby...\n" #: .././common/drive_scsitape.c:3984 msgid "" "use of QIC drives via variable blocksize device nodes is not supported\n" msgstr "" "korzystanie z napÄ™dów QIC poprzez urzÄ…dzenia blokowe o zmiennym rozmiarze " "bloku nie jest obsÅ‚ugiwane\n" #: .././common/drive_scsitape.c:4122 .././common/drive_scsitape.c:4148 msgid "unable to backspace/rewind media\n" msgstr "nie można wycofać/przewinąć noÅ›nika wstecz\n" #: .././common/drive_scsitape.c:4447 #, c-format msgid "" "unexpected tape error: errno %d nread %d blksz %d recsz %d isvar %d wasatbot " "%d eod %d fmk %d eot %d onl %d wprot %d ew %d \n" msgstr "" "nieoczekiwany błąd taÅ›my: errno %d nread %d blksz %d recsz %d isvar %d " "wasatbot %d eod %d fmk %d eot %d onl %d wprot %d ew %d\n" #: .././common/drive_scsitape.c:4478 #, c-format msgid "likely problem is that the block size, %d, is too large for Linux\n" msgstr "" "prawdopodobnie problem wynika z tego, że rozmiar bloku %d jest zbyt duży dla " "Linuksa\n" #: .././common/drive_scsitape.c:4482 msgid "" "either try using a smaller block size with the -b option, or increase " "max_sg_segs for the scsi tape driver\n" msgstr "" "proszÄ™ spróbować podać mniejszy rozmiar bloku opcjÄ… -b, lub zwiÄ™kszyć " "max_sg_segs dla sterownika napÄ™dów taÅ›mowych SCSI\n" #: .././common/drive_scsitape.c:4557 .././common/drive_scsitape.c:4596 msgid "will rewind and try again\n" msgstr "przewiniÄ™cie wstecz i ponowienie próby\n" #: .././common/drive_scsitape.c:4778 msgid "unable to backspace tape: assuming media error\n" msgstr "nie można wycofać taÅ›my: prawdopodobnie błąd noÅ›nika\n" #: .././common/drive_simple.c:276 .././common/drive_simple.c:361 #: .././dump/content.c:1369 #, c-format msgid "unable to open %s: %s\n" msgstr "nie udaÅ‚o siÄ™ otworzyć %s: %s\n" #: .././common/drive_simple.c:290 .././common/drive_simple.c:331 #, c-format msgid "stat of %s failed: %s\n" msgstr "stat %s nie powiódÅ‚ siÄ™: %s\n" #: .././common/drive_simple.c:320 #, c-format msgid "cannot dump to %s file type %x\n" msgstr "nie można zrzucić do pliku %s typu %x\n" #: .././common/drive_simple.c:350 #, c-format msgid "cannot restore from %s file type %x\n" msgstr "nie można odtworzyć z pliku %s typu %x\n" #: .././common/drive_simple.c:509 .././common/drive_simple.c:957 msgid "media file header checksum error\n" msgstr "błąd sumy kontrolnej nagłówka pliku noÅ›nika\n" #: .././common/drive_simple.c:527 #, c-format msgid "media file header magic number mismatch: %s, %s\n" msgstr "niezgodność liczby magicznej nagłówka pliku noÅ›nika: %s, %s\n" #: .././common/drive_simple.c:537 #, c-format msgid "unrecognized media file header version (%d)\n" msgstr "nierozpoznana wersja nagłówka pliku noÅ›nika (%d)\n" #: .././common/drive_simple.c:546 #, c-format msgid "unrecognized drive strategy ID (media says %d, expected %d)\n" msgstr "nierozpoznane ID strategii napÄ™du (wg noÅ›nika %d, oczekiwano %d)\n" #: .././common/drive_simple.c:907 #, c-format msgid "attempt to truncate %s failed: %d (%s)\n" msgstr "próba uciÄ™cia %s nie powiodÅ‚a siÄ™: %d (%s)\n" #: .././common/drive_simple.c:1069 #, c-format msgid "could not save first mark: %d (%s)\n" msgstr "nie udaÅ‚o siÄ™ zapisać pierwszego znacznika: %d (%s)\n" #: .././common/drive_simple.c:1273 .././common/drive_simple.c:1367 #, c-format msgid "write to %s failed: %d (%s)\n" msgstr "zapis do %s nie powiódÅ‚ siÄ™: %d (%s)\n" #: .././common/drive_simple.c:1421 #, c-format msgid "could not rewind %s: %s\n" msgstr "nie udaÅ‚o siÄ™ przewinąć %s: %s\n" #: .././common/drive_simple.c:1457 #, c-format msgid "could not rewind %s in prep for erase: %s\n" msgstr "nie udaÅ‚o siÄ™ przewinąć %s przed wyczyszczeniem: %s\n" #: .././common/drive_simple.c:1468 #, c-format msgid "could not erase %s: %s (%d)\n" msgstr "nie udaÅ‚o siÄ™ wyczyÅ›cić %s: %s (%d)\n" #: .././common/fs.c:170 #, c-format msgid "unable to determine uuid of fs mounted at %s: %s\n" msgstr "" "nie udaÅ‚o siÄ™ okreÅ›lić UUID-u systemu plików zamontowanego pod %s: %s\n" #: .././common/fs.c:250 #, c-format msgid "Can't open %s for mount information\n" msgstr "Nie można otworzyć %s w celu uzyskania informacji o montowaniu\n" #: .././common/global.c:108 #, c-format msgid "unable to determine hostname: %s\n" msgstr "nie udaÅ‚o siÄ™ okreÅ›lić nazwy hosta: %s\n" #: .././common/global.c:114 msgid "hostname length is zero\n" msgstr "zerowa dÅ‚ugość nazwy hosta\n" #: .././common/global.c:128 .././common/media.c:108 #: .././restore/content.c:1057 #, c-format msgid "too many -%c arguments: \"-%c %s\" already given\n" msgstr "za dużo argumentów -%c: już podano \"-%c %s\"\n" #: .././common/global.c:149 .././restore/content.c:1089 #, c-format msgid "too many -%c arguments\n" msgstr "za dużo argumentów -%c\n" #: .././common/global.c:164 .././restore/content.c:1103 #, c-format msgid "-%c argument not a valid uuid\n" msgstr "argument -%c nie jest poprawnym UUID-em\n" #: .././common/global.c:186 #, c-format msgid "unable to stat %s: %s\n" msgstr "nie udaÅ‚o siÄ™ wykonać stat na %s: %s\n" #: .././common/global.c:215 msgid "no session label specified\n" msgstr "nie podano etykiety sesji\n" #: .././common/global.c:307 msgid "please enter label for this dump session" msgstr "proszÄ™ wprowadzić etykietÄ™ dla tej sesji zrzutu" #: .././common/global.c:325 msgid "dump label dialog" msgstr "dialog nt. etykiety zrzutu" #: .././common/global.c:344 msgid "session label entered: \"" msgstr "wprowadzono etykietÄ™ sesji: \"" #: .././common/global.c:348 msgid "session label left blank\n" msgstr "pozostawiono pustÄ… etykietÄ™ sesji\n" #: .././common/hsmapi.c:863 #, c-format msgid "error removing temp DMF attr on %s: %s\n" msgstr "błąd podczas usuwania tymczasowego atrybutu DMF na %s: %s\n" #: .././common/main.c:232 .././common/main.c:254 #, c-format msgid "-%c argument (%s) invalid\n" msgstr "błędny argument -%c (%s)\n" #: .././common/main.c:294 #, c-format msgid "" "specified minimum stack size is larger than maximum: min is 0x%llx, max is " "0x%llx\n" msgstr "" "podany minimalny rozmiar stosu jest wiÄ™kszy od maksymalnego: min 0x%llx, max " "0x%llx\n" #: .././common/main.c:383 #, c-format msgid "unable to determine current directory: %s\n" msgstr "nie można okreÅ›lić bieżącego katalogu: %s\n" #: .././common/main.c:393 msgid "both /var/lib/xfsdump and /var/xfsdump exist - fatal\n" msgstr "" "istniejÄ… jednoczeÅ›nie /var/lib/xfsdump i /var/xfsdump - błąd krytyczny\n" #: .././common/main.c:401 #, c-format msgid "version %s (dump format %d.0)\n" msgstr "wersja %s (format zrzutu %d.0)\n" #: .././common/main.c:424 msgid "effective user ID must be root\n" msgstr "efektywny ID użytkownika musi być rootem\n" #: .././common/main.c:474 #, c-format msgid "version %s (dump format %d.0)" msgstr "wersja %s (format zrzutu %d.0)" #: .././common/main.c:478 #, c-format msgid " - type %s for status and control\n" msgstr " - aby przejść do stanu i sterowania, należy wcisnąć %s\n" #: .././common/main.c:707 msgid "session interrupt timeout\n" msgstr "przekroczony limit czasu przerwania sesji\n" #: .././common/main.c:775 msgid "session interrupt in progress: please wait\n" msgstr "przerwanie sesji w trakcie: proszÄ™ czekać\n" #: .././common/main.c:790 #, c-format msgid "initiating session interrupt (timeout in %d sec)\n" msgstr "rozpoczynanie przerwania sesji (limit czasu %d s)\n" #: .././common/main.c:896 #, c-format msgid "%s: usage: %s " msgstr "%s: skÅ‚adnia: %s " #: .././common/main.c:900 msgid "(dump DMF dualstate files as offline)" msgstr "(zrzut plików dwustanowych DMF jako offline)" #: .././common/main.c:901 .././common/main.c:953 msgid "" msgstr "" #: .././common/main.c:902 .././common/main.c:954 msgid " " msgstr " " #: .././common/main.c:903 msgid " " msgstr " " #: .././common/main.c:904 msgid "(allow files to be excluded)" msgstr "(możliwość wykluczenia plików)" #: .././common/main.c:905 msgid " ..." msgstr " ..." #: .././common/main.c:906 .././common/main.c:957 msgid "(help)" msgstr "(pomoc)" #: .././common/main.c:907 msgid "" msgstr "" #: .././common/main.c:908 .././common/main.c:959 msgid "(force usage of minimal rmt)" msgstr "(wymuszenie użycia minimalnego rmt)" #: .././common/main.c:909 msgid "(overwrite tape)" msgstr "(nadpisanie taÅ›my)" #: .././common/main.c:910 .././common/main.c:962 msgid "" msgstr "" #: .././common/main.c:911 .././common/main.c:963 msgid "" msgstr "" #: .././common/main.c:912 .././common/main.c:965 msgid " ..." msgstr " ..." #: .././common/main.c:913 msgid " (use file mtime for dump time" msgstr " (użycie mtime pliku jako czasu zrzutu)" #: .././common/main.c:914 .././common/main.c:967 msgid "" msgstr "" #: .././common/main.c:915 msgid "" msgstr "" #: .././common/main.c:916 msgid "(don't dump extended file attributes)" msgstr "(bez zrzutu rozszerzonych atrybutów plików)" #: .././common/main.c:917 msgid "" msgstr "" #: .././common/main.c:919 msgid "(generate tape record checksums)" msgstr "(generowanie sum kontrolnych rekordów na taÅ›mie)" #: .././common/main.c:921 msgid "(skip unchanged directories)" msgstr "(pomijanie nie zmienionych katalogów)" #: .././common/main.c:922 msgid "(pre-erase media)" msgstr "(wczeÅ›niejsze kasowanie noÅ›nika)" #: .././common/main.c:923 .././common/main.c:976 msgid "(don't prompt)" msgstr "(bez pytaÅ„)" #: .././common/main.c:925 msgid "" msgstr "" #: .././common/main.c:926 msgid "" msgstr "" #: .././common/main.c:928 .././common/main.c:977 msgid "(display dump inventory)" msgstr "(wyÅ›wietlenie inwentarza zrzutu)" #: .././common/main.c:929 .././common/main.c:978 msgid "(inhibit inventory update)" msgstr "(bez uaktualnienia inwentarza)" #: .././common/main.c:930 msgid "(generate format 2 dump)" msgstr "(generowanie zrzutu w formacie 2)" #: .././common/main.c:931 .././common/main.c:980 msgid "" msgstr "" #: .././common/main.c:932 msgid " ..." msgstr " ..." #: .././common/main.c:934 .././common/main.c:982 msgid "(timestamp messages)" msgstr "(znaczniki czasu dla komunikatów)" #: .././common/main.c:936 .././common/main.c:984 msgid "" msgstr "" #: .././common/main.c:938 .././common/main.c:986 msgid "(pin down I/O buffers)" msgstr "(dowiÄ…zanie buforów we/wy)" #: .././common/main.c:940 .././common/main.c:989 msgid "(resume)" msgstr "(wznowienie)" #: .././common/main.c:941 .././common/main.c:991 msgid "(don't timeout dialogs)" msgstr "(bez limitów czasu dialogów)" #: .././common/main.c:943 .././common/main.c:993 msgid "(unload media when change needed)" msgstr "(wysuniÄ™cie noÅ›nika przy potrzebie zmiany)" #: .././common/main.c:944 .././common/main.c:994 msgid "(show subsystem in messages)" msgstr "(wyÅ›wietlanie podsystemu w komunikatach)" #: .././common/main.c:945 .././common/main.c:995 msgid "(show verbosity in messages)" msgstr "(wyÅ›wietlanie szczegółowoÅ›ci w komunikatach)" #: .././common/main.c:947 .././common/main.c:998 msgid "" msgstr "" #: .././common/main.c:948 msgid "- (stdout)" msgstr "- (standardowe wyjÅ›cie)" #: .././common/main.c:949 msgid "" msgstr "<źródÅ‚o (punkt montowania|urzÄ…dzenie)>" #: .././common/main.c:952 msgid " ..." msgstr " ..." #: .././common/main.c:955 msgid "(don't overwrite existing files)" msgstr "(bez nadpisywania istniejÄ…cych plików)" #: .././common/main.c:956 msgid " ..." msgstr "<źródÅ‚o> ..." #: .././common/main.c:958 msgid "(interactive)" msgstr "(tryb interaktywny)" #: .././common/main.c:960 msgid " (restore only if newer than)" msgstr " (odtworzenie tylko jeÅ›li nowszy od pliku)" #: .././common/main.c:961 msgid "(restore owner/group even if not root)" msgstr "(odtworzenie wÅ‚aÅ›ciciela/grupy nawet jeÅ›li nie root)" #: .././common/main.c:964 msgid "(cumulative restore)" msgstr "(odtwarzanie skumulowane)" #: .././common/main.c:966 msgid "(contents only)" msgstr "(tylko zawartość)" #: .././common/main.c:968 msgid "(use small tree window)" msgstr "(użycie maÅ‚ego okna drzewa)" #: .././common/main.c:969 msgid "(don't restore extended file attributes)" msgstr "(bez przywracania rozszerzonych atrybutów plików)" #: .././common/main.c:970 msgid "(restore root dir owner/permissions)" msgstr "(odtworzenie wÅ‚aÅ›ciciela/uprawnieÅ„ katalogu głównego)" #: .././common/main.c:971 msgid "(restore DMAPI event settings)" msgstr "(odtworzenie ustawieÅ„ zdarzeÅ„ DMAPI)" #: .././common/main.c:973 msgid "(check tape record checksums)" msgstr "(sprawdzenie sum kontrolnych)" #: .././common/main.c:975 msgid "(don't overwrite if changed)" msgstr "(bez nadpisywania w przypadku zmiany)" #: .././common/main.c:979 msgid "(force use of format 2 generation numbers)" msgstr "(wymuszenie użycia liczb z formatu generacji 2)" #: .././common/main.c:988 msgid "(force interrupted session completion)" msgstr "(wymuszenie dokoÅ„czenia przerwanej sesji)" #: .././common/main.c:990 msgid "" msgstr "" #: .././common/main.c:997 msgid " ..." msgstr " ..." #: .././common/main.c:999 msgid "- (stdin)" msgstr "- (stdin)" #: .././common/main.c:1000 msgid "" msgstr "" #: .././common/main.c:1143 #, c-format msgid "-%c allowed only once\n" msgstr "-%c jest dozwolone tylko raz\n" #: .././common/main.c:1164 #, c-format msgid "cannot open option file %s: %s (%d)\n" msgstr "nie można otworzyć pliku opcji %s: %s (%d)\n" #: .././common/main.c:1176 #, c-format msgid "cannot stat option file %s: %s (%d)\n" msgstr "nie można wykonać stat na pliku opcji %s: %s (%d)\n" #: .././common/main.c:1188 #, c-format msgid "given option file %s is not ordinary file\n" msgstr "podany plik opcji %s nie jest zwykÅ‚ym plikiem\n" #: .././common/main.c:1229 #, c-format msgid "read of option file %s failed: %s (%d)\n" msgstr "odczyt pliku opcji %s nie powiódÅ‚ siÄ™: %s (%d)\n" #: .././common/main.c:1382 #, c-format msgid "received signal %d (%s): cleanup and exit\n" msgstr "otrzymano sygnaÅ‚ %d (%s): sprzÄ…tanie i zakoÅ„czenie\n" #: .././common/main.c:1464 msgid "please enter seconds between progress reports, or 0 to disable" msgstr "" "proszÄ™ wpisać liczbÄ™ sekund miÄ™dzy informacjami o postÄ™pach lub 0, aby " "wyłączyć" #: .././common/main.c:1467 msgid "please enter seconds between progress reports" msgstr "proszÄ™ wpisać liczbÄ™ sekund miÄ™dzy informacjami o postÄ™pach" #: .././common/main.c:1521 msgid "status and control dialog" msgstr "okno stanu i sterowania" #: .././common/main.c:1533 msgid "" "\n" "session interrupt in progress\n" msgstr "" "\n" "przerywanie sesji w trakcie\n" #: .././common/main.c:1542 msgid "please select one of the following operations\n" msgstr "proszÄ™ wybrać jednÄ… z nastÄ™pujÄ…cych operacji\n" #: .././common/main.c:1548 .././common/main.c:1592 msgid "interrupt this session" msgstr "przerwanie tej sesji" #: .././common/main.c:1554 msgid "change verbosity" msgstr "zmiana iloÅ›ci informacji" #: .././common/main.c:1556 msgid "display metrics" msgstr "wyÅ›wietlenie metryk" #: .././common/main.c:1559 msgid "confirm media change" msgstr "potwierdzenie zmiany noÅ›nika" #: .././common/main.c:1564 msgid "other controls" msgstr "inne funkcje" #: .././common/main.c:1566 .././common/main.c:1594 .././common/main.c:1748 #: .././common/main.c:1785 .././common/main.c:1849 .././restore/content.c:2881 #: .././restore/content.c:2921 msgid "continue" msgstr "kontynuacja" #: .././common/main.c:1588 msgid "please confirm\n" msgstr "proszÄ™ potwierdzić\n" #: .././common/main.c:1611 .././common/main.c:1802 .././common/main.c:1959 #: .././restore/content.c:2936 .././restore/content.c:2939 msgid "continuing\n" msgstr "kontynuacja\n" #: .././common/main.c:1613 msgid "interrupt request accepted\n" msgstr "przyjÄ™to żądanie przerwania\n" #: .././common/main.c:1624 msgid "please select one of the following subsystems\n" msgstr "proszÄ™ wybrać jeden z nastÄ™pujÄ…cych podsystemów\n" #: .././common/main.c:1634 msgid "all of the above" msgstr "wszystkie powyższe" #: .././common/main.c:1636 .././common/main.c:1676 msgid "no change" msgstr "bez zmian" #: .././common/main.c:1653 .././common/main.c:1707 .././common/main.c:1888 #: .././common/main.c:1895 .././common/main.c:1926 .././common/main.c:1931 msgid "no change\n" msgstr "bez zmian\n" #: .././common/main.c:1656 msgid "" "all subsystems selected\n" "\n" msgstr "" "wybrano wszystkie podsystemy\n" "\n" #: .././common/main.c:1669 msgid "silent" msgstr "cisza" #: .././common/main.c:1670 msgid "verbose" msgstr "szczegóły" #: .././common/main.c:1671 msgid "trace" msgstr "Å›ledzenie" #: .././common/main.c:1672 msgid "debug" msgstr "diagnostyka" #: .././common/main.c:1673 msgid "nitty" msgstr "drobiazgi" #: .././common/main.c:1674 msgid "nitty + 1" msgstr "drobiazgi + 1" #: .././common/main.c:1686 msgid " (current)" msgstr " (bieżący)" #: .././common/main.c:1724 msgid "level changed\n" msgstr "poziom zmieniony\n" #: .././common/main.c:1735 msgid "please select one of the following metrics\n" msgstr "proszÄ™ wybrać jednÄ… z nastÄ™pujÄ…cych metryk\n" #: .././common/main.c:1740 msgid "I/O" msgstr "we/wy" #: .././common/main.c:1743 msgid "media inventory status" msgstr "stan inwentarza noÅ›nika" #: .././common/main.c:1745 msgid "needed media objects" msgstr "wymagane obiekty noÅ›nika" #: .././common/main.c:1819 msgid "please select one of the following controls\n" msgstr "proszÄ™ wybrać jednÄ… z nastÄ™pujÄ…cych funkcji\n" #: .././common/main.c:1825 msgid "change interval of or disable progress reports" msgstr "zmiana czÄ™stotliwoÅ›ci lub wyłączenie informacji o postÄ™pach" #: .././common/main.c:1828 msgid "enable progress reports" msgstr "włączenie informacji o postÄ™pach" #: .././common/main.c:1832 msgid "hide log message levels" msgstr "ukrycie poziomów komunikatów logu" #: .././common/main.c:1834 msgid "show log message levels" msgstr "wyÅ›wietlanie poziomów komunikatów logu" #: .././common/main.c:1838 msgid "hide log message subsystems" msgstr "ukrycie podsystemów komunikatów logu" #: .././common/main.c:1840 msgid "show log message subsystems" msgstr "wyÅ›wietlanie podsystemów komunikatów logu" #: .././common/main.c:1844 msgid "hide log message timestamps" msgstr "ukrycie znaczników czasu komunikatów logu" #: .././common/main.c:1846 msgid "show log message timestamps" msgstr "wyÅ›wietlanie znaczników czasu komunikatów logu" #: .././common/main.c:1897 msgid "changing progress report interval to " msgstr "zmiana czÄ™stotliwoÅ›ci informacji o postÄ™pach na " #: .././common/main.c:1899 #, c-format msgid "%d seconds\n" msgstr "%d sekund\n" #: .././common/main.c:1910 msgid "enabling progress reports at " msgstr "włączanie informacji o postÄ™pach " #: .././common/main.c:1912 #, c-format msgid "%d second intervals\n" msgstr "co %d sekund\n" #: .././common/main.c:1924 msgid "disabling progress reports\n" msgstr "wyłączanie informacji o postÄ™pach\n" #: .././common/main.c:1936 msgid "showing log message levels\n" msgstr "wyÅ›wietlanie poziomów komunikatów logu\n" #: .././common/main.c:1938 msgid "hiding log message levels\n" msgstr "ukrywanie poziomów komunikatów logu\n" #: .././common/main.c:1943 msgid "showing log message subsystems\n" msgstr "wyÅ›wietlanie podsystemów komunikatów logu\n" #: .././common/main.c:1945 msgid "hiding log message subsystems\n" msgstr "ukrywanie podsystemów komunikatów logu\n" #: .././common/main.c:1950 msgid "showing log message timestamps\n" msgstr "wyÅ›wietlanie znaczników czasu komunikatów logu\n" #: .././common/main.c:1952 msgid "hiding log message timestamps\n" msgstr "ukrywanie znaczników czasu komunikatów logu\n" #: .././common/main.c:2088 #, c-format msgid "unable to raise stack size hard limit from 0x%llx to 0x%llx\n" msgstr "" "nie udaÅ‚o siÄ™ podnieść twardego limitu rozmiaru stosu z 0x%llx do 0x%llx\n" #: .././common/main.c:2115 #, c-format msgid "unable to raise stack size soft limit from 0x%llx to 0x%llx\n" msgstr "" "nie udaÅ‚o siÄ™ podnieść miÄ™kkiego limitu rozmiaru stosu z 0x%llx do 0x%llx\n" #: .././common/main.c:2143 #, c-format msgid "unable to lower stack size soft limit from 0x%llx to 0x%llx\n" msgstr "" "nie udaÅ‚o siÄ™ zmniejszyć miÄ™kkiego limitu rozmiaru stosu z 0x%llx do 0x%llx\n" #: .././common/media.c:180 msgid "no media strategy available for selected dump destination(s)\n" msgstr "brak dostÄ™pnej strategii noÅ›nika dla wybranego celu zrzutu\n" #: .././common/media.c:184 msgid "no media strategy available for selected restore source(s)\n" msgstr "brak dostÄ™pnej strategii noÅ›nika dla wybranego źródÅ‚a odtwarzania\n" #: .././common/mlog.c:191 #, c-format msgid "%s: -%c argument missing\n" msgstr "%s: brak argumentu -%c\n" #: .././common/mlog.c:207 .././common/mlog.c:249 #, c-format msgid "%s: -%c argument invalid\n" msgstr "%s: błędny argumentu -%c\n" #: .././common/mlog.c:219 #, c-format msgid "%s: -%c subsystem subargument %s requires a verbosity value\n" msgstr "%s: podargument podsystemu -%c %s wymaga wartoÅ›ci szczegółowoÅ›ci\n" #: .././common/mlog.c:235 #, c-format msgid "%s: -%c argument does not require a value\n" msgstr "%s: argument -%c nie wymaga wartoÅ›ci\n" #: .././common/mlog.c:425 #, c-format msgid "%s%s%s%s: drive %d: " msgstr "%s%s%s%s: napÄ™d %d: " #: .././common/mlog.c:721 #, c-format msgid "%s: %s Summary:\n" msgstr "%s: %s - podsumowanie:\n" #: .././common/mlog.c:747 #, c-format msgid "%s: stream %d %s %s (%s)\n" msgstr "%s: strumieÅ„ %d %s %s (%s)\n" #: .././common/openutil.c:78 .././common/openutil.c:94 #, c-format msgid "could not create %s: %s\n" msgstr "nie udaÅ‚o siÄ™ utworzyć %s: %s\n" #: .././common/qlock.c:116 #, c-format msgid "lock already held: tid %lu ord %d map %x\n" msgstr "blokada już przyznana: tid %lu ord %d map %x\n" #: .././common/qlock.c:127 #, c-format msgid "lock ordinal violation: tid %lu ord %d map %x\n" msgstr "naruszenie porzÄ…dku blokad: tid %lu ord %d map %x\n" #: .././common/ring.c:127 msgid "slave" msgstr "podrzÄ™dnego" #: .././common/util.c:188 .././dump/content.c:2867 #, c-format msgid "failed to get bulkstat information for inode %llu\n" msgstr "nie udaÅ‚o siÄ™ uzyskać informacji bulkstat dla i-wÄ™zÅ‚a %llu\n" #: .././common/util.c:194 #, c-format msgid "failed to get valid bulkstat information for inode %llu\n" msgstr "" "nie udaÅ‚o siÄ™ uzyskać poprawnych informacji bulkstat dla i-wÄ™zÅ‚a %llu\n" #: .././common/util.c:243 #, c-format msgid "syssgi( SGI_FS_BULKSTAT ) on fsroot failed: %s\n" msgstr "syssgi( SGI_FS_BULKSTAT) na fsroot nie powiodÅ‚o siÄ™: %s\n" #: .././common/util.c:288 .././restore/content.c:1967 #, c-format msgid "malloc of stream context failed (%d bytes): %s\n" msgstr "malloc dla kontekstu strumienia nie powiódÅ‚ siÄ™ (bajtów: %d): %s\n" #: .././common/util.c:371 #, c-format msgid "WARNING: unable to open directory ino %llu: %s\n" msgstr "UWAGA: nie udaÅ‚o siÄ™ otworzyć i-wÄ™zÅ‚a katalogu %llu: %s\n" #: .././common/util.c:402 #, c-format msgid "WARNING: unable to read dirents (%d) for directory ino %llu: %s\n" msgstr "" "UWAGA: nie udaÅ‚o siÄ™ odczytać wpisów (%d) dla i-wÄ™zÅ‚a katalogu %llu: %s\n" #: .././common/util.c:450 #, c-format msgid "WARNING: could not stat dirent %s ino %llu: %s\n" msgstr "UWAGA: nie udaÅ‚o siÄ™ wykonać stat na wpisie %s i-wÄ™zÅ‚a %llu: %s\n" #: .././common/util.c:465 #, c-format msgid "WARNING: unable to process dirent %s: ino %llu too large\n" msgstr "UWAGA: nie udaÅ‚o siÄ™ przetworzyć wpisu %s: i-wÄ™zeÅ‚ %llu zbyt duży\n" # used as: ... rozsz. atrybut/atrybutu przestrzeni %s #: .././dump/content.c:217 .././restore/content.c:8874 msgid "root" msgstr "roota" # used as: ... rozsz. atrybut/atrybutu przestrzeni %s #: .././dump/content.c:218 .././restore/content.c:8876 msgid "secure" msgstr "bezpieczeÅ„stwa" # used as: ... atrybut/atrybutu przestrzeni %s #: .././dump/content.c:219 .././restore/content.c:8878 msgid "non-root" msgstr "nie-roota" # used as: ... i-wÄ™zeÅ‚/i-wÄ™zÅ‚a %s #: .././dump/content.c:224 msgid "dir" msgstr "katalogu" # used as: ... i-wÄ™zeÅ‚/i-wÄ™zÅ‚a %s #: .././dump/content.c:224 msgid "nondir" msgstr "nie-katalogu" #: .././dump/content.c:605 #, c-format msgid "-%c argument must be between 0 and %d\n" msgstr "argument dla -%c musi być liczbÄ… miÄ™dzy 0 a %d\n" #: .././dump/content.c:623 #, c-format msgid "-%c argument (subtree) must be a relative pathname\n" msgstr "argument (poddrzewo) dla -%c musi być Å›cieżkÄ… wzglÄ™dnÄ…\n" #: .././dump/content.c:644 #, c-format msgid "-%c argument is not a valid file size\n" msgstr "argument dla -%c nie jest poprawnym rozmiarem pliku\n" #: .././dump/content.c:694 #, c-format msgid "-%c argument not a valid dump session id\n" msgstr "argument dla -%c nie jest poprawnym id sesji dumpa\n" #: .././dump/content.c:706 #, c-format msgid "may not specify both -%c and -%c\n" msgstr "nie można przekazać jednoczeÅ›nie -%c i -%c\n" #: .././dump/content.c:725 msgid "source file system not specified\n" msgstr "nie okreÅ›lono źródÅ‚owego systemu plików\n" #: .././dump/content.c:776 #, c-format msgid "%s does not identify a file system\n" msgstr "%s nie identyfikuje systemu plików\n" #: .././dump/content.c:788 #, c-format msgid "%s must be mounted to be dumped\n" msgstr "%s musi być zamontowany, aby można wykonać zrzut\n" #: .././dump/content.c:827 #, c-format msgid "failed to save %s information, continuing\n" msgstr "nie udaÅ‚o siÄ™ zapisać informacji %s, kontynuacja\n" #: .././dump/content.c:878 #, c-format msgid "could not find specified base dump (%s) in inventory\n" msgstr "nie odnaleziono podanej podstawy zrzutu (%s) w inwentarzu\n" #: .././dump/content.c:951 #, c-format msgid "" "cannot select dump session %d as base for incremental dump: level must be " "less than %d\n" msgstr "" "nie można wybrać sesji dumpa %d jako podstawy do zrzutu przyrostowego: " "poziom musi być niższy niż %d\n" #: .././dump/content.c:982 msgid "cannot calculate incremental dump: online inventory not available\n" msgstr "" "nie można wyliczyć zrzutu przyrostowego: inwentarz online nie jest dostÄ™pny\n" #: .././dump/content.c:1109 #, c-format msgid "" "most recent level %d dump was interrupted, but not resuming that dump since " "resume (-R) option not specified\n" msgstr "" "zrzut najnowszego poziomu %d zostaÅ‚ przerwany, ale nie jest wznawiany, " "ponieważ nie podano opcji wznowienia (-R)\n" #: .././dump/content.c:1126 .././dump/content.c:1192 #, c-format msgid "" "most recent base for incremental dump was interrupted (level %u): must " "resume or redump at or below level %d\n" msgstr "" "najnowsza podstawa dla zrzutu przyrostowego zostaÅ‚a przerwana (poziom %u): " "trzeba wznowić lub wykonać zrzut ponownie na poziomie %d lub niższym\n" #: .././dump/content.c:1137 .././dump/content.c:1203 #, c-format msgid "" "level %u incremental subtree dump will be based on non-subtree level %u " "dump\n" msgstr "" "przyrostowy zrzut poddrzewa poziomu %u bÄ™dzie oparty na zrzucie " "niepoddrzewowym poziomu %u\n" #: .././dump/content.c:1146 .././dump/content.c:1212 #, c-format msgid "" "level %u incremental non-subtree dump will be based on subtree level %u " "dump\n" msgstr "" "przyrostowy zrzut niepoddrzewowy poziomu %u bÄ™dzie oparty na zrzucie " "poddrzewa poziomu %u\n" #: .././dump/content.c:1164 #, c-format msgid "" "level %u incremental subtree dump will be based on non-subtree level %u " "resumed dump\n" msgstr "" "przyrostowy zrzut poddrzewa poziomu %u bÄ™dzie oparty na wznowionym zrzucie " "niepoddrzewowym poziomu %u\n" #: .././dump/content.c:1173 #, c-format msgid "" "level %u incremental non-subtree dump will be based on subtree level %u " "resumed dump\n" msgstr "" "przyrostowy zrzut niepoddrzewowy poziomu %u bÄ™dzie oparty na wznowionym " "zrzucie poddrzewa poziomu %u\n" #: .././dump/content.c:1231 #, c-format msgid "" "level %u subtree dump will be based on non-subtree level %u resumed dump\n" msgstr "" "zrzut poddrzewa poziomu %u bÄ™dzie oparty na wznowionym zrzucie " "niepoddrzewowym poziomu %u\n" #: .././dump/content.c:1240 #, c-format msgid "" "level %u non-subtree dump will be based on subtree level %u resumed dump\n" msgstr "" "zrzut niepoddrzewowy poziomu %u bÄ™dzie oparty na wznowionym zrzucie " "poddrzewa poziomu %u\n" #: .././dump/content.c:1258 #, c-format msgid "cannot find earlier dump to base level %d increment upon\n" msgstr "" "nie znaleziono wczeÅ›niejszego zrzutu dla poziomu bazowego %d, na którym " "miaÅ‚by być oparty przyrost\n" #: .././dump/content.c:1270 #, c-format msgid "most recent base dump (level %d begun %s) was interrupted: aborting\n" msgstr "" "najnowszy zrzut bazowy (poziom %d rozpoczÄ™ty %s) zostaÅ‚ przerwany: nie można " "kontynuować\n" #: .././dump/content.c:1281 #, c-format msgid "" "resume (-R) option inappropriate: no interrupted level %d dump to resume\n" msgstr "" "niewÅ‚aÅ›ciwie podana opcja wznowienia (-R): brak przerwanego zrzutu poziomu " "%d do wznowienia\n" #: .././dump/content.c:1300 #, c-format msgid "" "resuming level %d incremental dump of %s:%s begun %s (incremental base level " "%d begun %s)\n" msgstr "" "wznawianie zrzutu przyrostowego poziomu %d z %s:%s rozpoczÄ™te %s (podstawowy " "poziom przyrostu %d rozpoczÄ™ty %s)\n" #: .././dump/content.c:1311 #, c-format msgid "level %d incremental dump of %s:%s based on level %d dump begun %s\n" msgstr "" "zrzut przyrostowy poziomu %d z %s:%s oparty na zrzucie poziomu %d rozpoczÄ™ty " "%s\n" #: .././dump/content.c:1322 #, c-format msgid "resuming level %d dump of %s:%s begun %s\n" msgstr "wznawianie zrzutu poziomu %d z %s:%s rozpoczÄ™te %s\n" #: .././dump/content.c:1329 #, c-format msgid "level %d dump of %s:%s\n" msgstr "zrzut poziomu %d z %s:%s\n" #: .././dump/content.c:1343 #, c-format msgid "dump date: %s\n" msgstr "data zrzutu: %s\n" #: .././dump/content.c:1352 .././restore/content.c:9578 #, c-format msgid "session id: %s\n" msgstr "id sesji: %s\n" #: .././dump/content.c:1359 #, c-format msgid "session label: \"%s\"\n" msgstr "etykieta sesji: \"%s\"\n" #: .././dump/content.c:1383 #, c-format msgid "could not stat %s\n" msgstr "nie udaÅ‚o siÄ™ wykonać stat na %s\n" #: .././dump/content.c:1393 msgid "failed to get bulkstat information for root inode\n" msgstr "nie udaÅ‚o siÄ™ pobrać informacji bulkstat dla głównego i-wÄ™zÅ‚a\n" #: .././dump/content.c:1404 .././restore/content.c:1790 #, c-format msgid "unable to construct a file system handle for %s: %s\n" msgstr "nie udaÅ‚o siÄ™ utworzyć uchwytu systemu plików dla %s: %s\n" #: .././dump/content.c:1526 #, c-format msgid "estimated dump size: %llu bytes\n" msgstr "szacowany rozmiar zrzutu (w bajtach): %llu\n" #: .././dump/content.c:1531 #, c-format msgid "estimated dump size per stream: %llu bytes\n" msgstr "szacowany rozmiar zrzutu na strumieÅ„ (w bajtach): %llu\n" #: .././dump/content.c:1634 #, c-format msgid "more -%c arguments than number of drives\n" msgstr "podano wiÄ™cej argumentów -%c niż napÄ™dów\n" #: .././dump/content.c:1655 #, c-format msgid "media labels given for only %d out of %d drives\n" msgstr "podano etykiety noÅ›ników tylko dla %d z %d napÄ™dów\n" #: .././dump/content.c:2231 msgid "" "media change timeout will be treated as a request to stop using drive: can " "resume later\n" msgstr "" "przekroczenie limitu czasu na zmianÄ™ noÅ›nika bÄ™dzie traktowane jako żądanie " "zaprzestania używania napÄ™du; możliwe jest późniejsze wznowienie\n" #: .././dump/content.c:2239 msgid "" "media change decline will be treated as a request to stop using drive: can " "resume later\n" msgstr "" "odmowa zmiany noÅ›nika bÄ™dzie traktowana jako żądanie zaprzestania używania " "napÄ™du; możliwe jest późniejsze wznowienie\n" #: .././dump/content.c:2262 #, c-format msgid "creating dump session media file %u (media %u, file %u)\n" msgstr "tworzenie pliku noÅ›nika %u dla sesji zrzutu (noÅ›nik %u, plik %u)\n" #: .././dump/content.c:2276 msgid "dumping ino map\n" msgstr "trwa zrzut mapy i-wÄ™złów\n" #: .././dump/content.c:2351 msgid "dumping non-directory files\n" msgstr "trwa zrzut plików nie bÄ™dÄ…cych katalogami\n" #: .././dump/content.c:2470 msgid "ending media file\n" msgstr "koÅ„czenie pliku noÅ›nika\n" #: .././dump/content.c:2486 #, c-format msgid "media file size %lld bytes\n" msgstr "rozmiar pliku noÅ›nika w bajtach: %lld\n" #: .././dump/content.c:2570 msgid "inventory media file put failed\n" msgstr "przesÅ‚anie pliku noÅ›nika do inwentarza nie powiodÅ‚o siÄ™\n" #: .././dump/content.c:2600 msgid "waiting for synchronized session inventory dump\n" msgstr "oczekiwanie na zsynchronizowany zrzut inwentarza sesji\n" #: .././dump/content.c:2631 #, c-format msgid "ending stream: %ld seconds elapsed\n" msgstr "koÅ„czenie strumienia: upÅ‚ynęło %ld s\n" #: .././dump/content.c:2654 #, c-format msgid "dump size (non-dir files) : %llu bytes\n" msgstr "rozmiar zrzutu (plików nie-katalogów) w bajtach: %llu\n" #: .././dump/content.c:2662 .././dump/content.c:6585 #, c-format msgid "unable to remove %s: %s\n" msgstr "nie udaÅ‚o siÄ™ usunąć %s: %s\n" #: .././dump/content.c:2670 #, c-format msgid "dump complete: %ld seconds elapsed\n" msgstr "zrzut zakoÅ„czony: upÅ‚ynęło %ld s\n" #: .././dump/content.c:2677 #, c-format msgid "" "dump interrupted: %ld seconds elapsed: may resume later using -%c option\n" msgstr "" "zrzut przerwany: upÅ‚ynęło %ld s; możliwe jest późniejsze wznowienie opcjÄ… -" "%c\n" #: .././dump/content.c:2686 #, c-format msgid "dump interrupted: %ld seconds elapsed\n" msgstr "zrzut przerwany: upÅ‚ynęło %ld s\n" #: .././dump/content.c:2804 msgid "dumping directories\n" msgstr "trwa zrzut katalogów\n" #: .././dump/content.c:2830 #, c-format msgid "SGI_FS_BULKSTAT failed: %s (%d)\n" msgstr "SGI_FS_BULKSTAT nie powiodÅ‚o siÄ™: %s (%d)\n" #: .././dump/content.c:2971 #, c-format msgid "unable to dump directory: ino %llu too large\n" msgstr "nie udaÅ‚o siÄ™ zrzucić katalogu: i-wÄ™zeÅ‚ %llu zbyt duży\n" #: .././dump/content.c:2985 #, c-format msgid "unable to open directory: ino %llu: %s\n" msgstr "nie udaÅ‚o siÄ™ otworzyć katalogu: i-wÄ™zeÅ‚ %llu: %s\n" #: .././dump/content.c:3013 #, c-format msgid "unable to read dirents (%d) for directory ino %llu: %s\n" msgstr "" "nie udaÅ‚o siÄ™ odczytać wpisów katalogu (%d) dla i-wÄ™zÅ‚a katalogu %llu: %s\n" #: .././dump/content.c:3076 #, c-format msgid "encountered 0 ino (%s) in directory ino %llu: NOT dumping\n" msgstr "napotkano i-wÄ™zeÅ‚ 0 (%s) w i-węźle katalogu %llu: BEZ zrzutu\n" #: .././dump/content.c:3095 #, c-format msgid "" "could not stat dirent %s ino %llu: %s: using null generation count in " "directory entry\n" msgstr "" "nie udaÅ‚o siÄ™ wykonać stat wpisu katalogu %s i-wÄ™zeÅ‚ %llu: %s: użycie " "zerowego licznika generacji we wpisie katalogu\n" #: .././dump/content.c:3200 #, c-format msgid "could not get list of %s attributes for %s ino %llu: %s (%d)\n" msgstr "" "nie udaÅ‚o siÄ™ pobrać listy atrybutów przestrzeni %s dla i-wÄ™zÅ‚a %s %llu: %s " "(%d)\n" #: .././dump/content.c:3297 #, c-format msgid "HSM could not filter %s attribute %s for %s ino %llu\n" msgstr "" "nie udaÅ‚o siÄ™ odfiltrować przez HSM atrybutu przestrzeni %s %s dla i-wÄ™zÅ‚a " "%s %llu\n" #: .././dump/content.c:3348 #, c-format msgid "could not retrieve %s attributes for %s ino %llu: %s (%d)\n" msgstr "" "nie udaÅ‚o siÄ™ odczytać atrybutów przestrzeni %s dla i-wÄ™zÅ‚a %s %llu: %s " "(%d)\n" #: .././dump/content.c:3377 #, c-format msgid "" "attr_multi indicates error while retrieving %s attribute [%s] for %s ino " "%llu: %s (%d)\n" msgstr "" "attr_multi zgÅ‚asza błąd przy próbie odczytu atrybutu przestrzeni %s [%s] dla " "i-wÄ™zÅ‚a %s %llu: %s (%d)\n" #: .././dump/content.c:3449 #, c-format msgid "HSM could not add new %s attribute #%d for %s ino %llu\n" msgstr "" "nie udaÅ‚o siÄ™ dodać przez HSM nowego atrybutu przestrzeni %s #%d dla i-wÄ™zÅ‚a " "%s %llu\n" #: .././dump/content.c:3576 #, c-format msgid "" "%s extended attribute name for %s ino %llu too long: %u, max is %u: " "skipping\n" msgstr "" "nazwa rozszerzonego atrybutu przestrzeni %s dla i-wÄ™zÅ‚a %s %llu zbyt dÅ‚uga: " "%u, maksimum to %u: pominiÄ™to\n" #: .././dump/content.c:3589 #, c-format msgid "" "%s extended attribute value for %s ino %llu too long: %u, max is %u: " "skipping\n" msgstr "" "wartość rozszerzonego atrybutu przestrzeni %s dla -i-wÄ™zÅ‚a %s %llu zbyt " "dÅ‚uga: %u, maksimum to %u: pominiÄ™to\n" #: .././dump/content.c:3784 #, c-format msgid "inomap inconsistency ino %llu: %s but is now non-dir: NOT dumping\n" msgstr "" "niespójność mapy dla i-wÄ™zÅ‚a %llu: %s, ale teraz to nie katalog; BEZ zrzutu\n" #: .././dump/content.c:3802 #, c-format msgid "inomap inconsistency ino %llu: hsm detected error: NOT dumping\n" msgstr "" "niespójność mapy dla i-wÄ™zÅ‚a %llu: przez HSM wykryto błąd; BEZ zrzutu\n" #: .././dump/content.c:3880 #, c-format msgid "don't know how to dump ino %llu: mode %08x\n" msgstr "nie wiadomo, jak zrzucić i-wÄ™zeÅ‚ %llu: tryb %08x\n" #: .././dump/content.c:4008 #, c-format msgid "could not open regular file ino %llu mode 0x%08x: %s: not dumped\n" msgstr "" "nie udaÅ‚o siÄ™ otworzyć zwykÅ‚ego pliku: i-wÄ™zeÅ‚ %llu, tryb 0x%08x: %s; bez " "zrzutu\n" #: .././dump/content.c:4058 #, c-format msgid "dump interrupted prior to ino %llu offset %lld\n" msgstr "zrzut przerwany przed i-wÄ™zÅ‚em %llu, offset %lld\n" #: .././dump/content.c:4293 #, c-format msgid "locking check failed ino %llu\n" msgstr "sprawdzenie blokady nie powiodÅ‚o siÄ™ na i-węźle %llu\n" #: .././dump/content.c:4342 #, c-format msgid "dioinfo failed ino %llu\n" msgstr "dioinfo nie powiodÅ‚o siÄ™ na i-węźle %llu\n" #: .././dump/content.c:4411 #, c-format msgid "" "getbmapx %d ino %lld mode 0x%08x offset %lld ix %d returns negative entry " "count\n" msgstr "" "getbmapx %d, i-wÄ™zeÅ‚ %lld, tryb 0x%08x, offset %lld, ix %d zwróciÅ‚o ujemnÄ… " "liczbÄ™ wpisów\n" #: .././dump/content.c:4426 #, c-format msgid "getbmapx %d ino %lld mode 0x%08x offset %lld failed: %s\n" msgstr "" "getbmapx %d, i-wÄ™zeÅ‚ %lld, tryb 0x%08x, offset %lld nie powiodÅ‚o siÄ™: %s\n" #: .././dump/content.c:4448 #, c-format msgid "hsm detected an extent map error in ino %lld, skipping\n" msgstr "poprzez hsm wykryto błąd mapy ekstentów w i-węźle %lld, pominiÄ™to\n" #: .././dump/content.c:4791 #, c-format msgid "can't lseek ino %llu\n" msgstr "nie można wykonać lseek na i-wÄ™zeÅ‚ %llu\n" #: .././dump/content.c:4805 #, c-format msgid "can't read ino %llu at offset %d (act=%d req=%d) rt=%d\n" msgstr "" "nie można odczytać i-wÄ™zÅ‚a %llu pod offsetem %d (act=%d req=%d) rt=%d\n" #: .././dump/content.c:5094 #, c-format msgid "unable to dump directory %llu entry %s (%llu): name too long\n" msgstr "" "nie udaÅ‚o siÄ™ wykonać zrzutu katalogu %llu, wpis %s (%llu): nazwa zbyt " "dÅ‚uga\n" #: .././dump/content.c:5195 msgid "dumping session inventory\n" msgstr "trwa zrzut inwentarza sesji\n" #: .././dump/content.c:5204 msgid "unable to get session inventory to dump\n" msgstr "nie udaÅ‚o siÄ™ pobrać inwentarza sesji do zrzutu\n" #: .././dump/content.c:5226 msgid "beginning inventory media file\n" msgstr "rozpoczynanie pliku noÅ›nika inwentarza\n" #: .././dump/content.c:5235 msgid "media change timeout: session inventory not dumped\n" msgstr "upÅ‚ynÄ…Å‚ limit czasu na zmianÄ™ noÅ›nika: bez zrzutu inwentarza sesji\n" #: .././dump/content.c:5241 msgid "media change declined: session inventory not dumped\n" msgstr "odmowa zmiany noÅ›nika: bez zrzutu inwentarza sesji\n" #: .././dump/content.c:5253 .././dump/content.c:5397 #, c-format msgid "media file %u (media %u, file %u)\n" msgstr "plik noÅ›nika %u (noÅ›nik %u, plik %u)\n" #: .././dump/content.c:5281 msgid "ending inventory media file\n" msgstr "koÅ„czenie pliku noÅ›nika inwentarza\n" #: .././dump/content.c:5300 #, c-format msgid "encountered EOM while writing inventory media file size %lld bytes\n" msgstr "" "napotkano EOM w trakcie zapisu pliku noÅ›nika inwentarza o rozmiarze (w " "bajtach) %lld\n" #: .././dump/content.c:5306 #, c-format msgid "inventory media file size %lld bytes\n" msgstr "rozmiar pliku noÅ›nika inwentarza w bajtach: %lld\n" #: .././dump/content.c:5332 msgid "inventory session media file put failed\n" msgstr "przesÅ‚anie pliku noÅ›nika sesji inwentarza nie powiodÅ‚o siÄ™\n" #: .././dump/content.c:5357 msgid "writing stream terminator\n" msgstr "zapis terminatora strumienia\n" #: .././dump/content.c:5372 msgid "beginning media stream terminator\n" msgstr "rozpoczynanie terminatora strumienia noÅ›nika\n" #: .././dump/content.c:5381 msgid "media change timeout: media stream terminator not written\n" msgstr "" "przekroczony limit czasu zmiany noÅ›nika: terminator strumienia noÅ›nika nie " "zostaÅ‚ zapisany\n" #: .././dump/content.c:5386 msgid "media change declined: media stream terminator not written\n" msgstr "" "odmowa zmiany noÅ›nika: terminator strumienia noÅ›nika nie zostaÅ‚ zapisany\n" #: .././dump/content.c:5403 msgid "ending media stream terminator\n" msgstr "koÅ„czenie terminatora strumienia noÅ›nika\n" #: .././dump/content.c:5422 #, c-format msgid "encountered EOM while writing media stream terminator size %lld bytes\n" msgstr "" "napotkano EOM podczas zapisu terminatora strumienia noÅ›nika o rozmiarze (w " "bajtach) %lld\n" #: .././dump/content.c:5427 #, c-format msgid "media stream terminator size %lld bytes\n" msgstr "rozmiar terminatora strumienia noÅ›nika (w bajtach): %lld\n" #: .././dump/content.c:5624 #, c-format msgid "positioned at media file %u: dump %u, stream %u\n" msgstr "ustawiono na pliku noÅ›nika %u: zrzut %u, strumieÅ„ %u\n" #: .././dump/content.c:5672 .././dump/content.c:6036 msgid "cannot interleave dump streams: must supply a blank media object\n" msgstr "nie można przeplatać strumieni zrzutów: trzeba podać pusty noÅ›nik\n" #: .././dump/content.c:5678 msgid "media contains valid xfsdump but does not support append\n" msgstr "noÅ›nik zawiera poprawny xfsdump, ale nie obsÅ‚uguje dołączania\n" #: .././dump/content.c:5685 msgid "stream terminator found\n" msgstr "znaleziono terminator strumienia\n" #: .././dump/content.c:5693 msgid "encountered media error attempting BSF\n" msgstr "napotkano błąd noÅ›nika podczas próby BSF\n" #: .././dump/content.c:5707 msgid "" "media contains non-xfsdump data or a corrupt xfsdump media file header at " "beginning of media\n" msgstr "" "noÅ›nik zawiera dane inne niż xfsdump lub uszkodzony nagłówek pliku noÅ›nika " "xfsdump na poczÄ…tku noÅ›nika\n" #: .././dump/content.c:5737 msgid "unable to overwrite\n" msgstr "nie można nadpisać\n" #: .././dump/content.c:5742 msgid "repositioning to overwrite\n" msgstr "zmiana pozycji w celu nadpisania\n" #: .././dump/content.c:5760 msgid "media may contain data. Overwrite option specified\n" msgstr "noÅ›nik może zawierać dane. Podano opcjÄ™ nadpisania\n" #: .././dump/content.c:5788 msgid "at end of data\n" msgstr "na koÅ„cu danych\n" #: .././dump/content.c:5807 msgid "" "encountered EOD but expecting a media stream terminator: assuming full " "media\n" msgstr "" "napotkano EOD, ale oczekiwano terminatora strumienia noÅ›nika: przyjÄ™to peÅ‚ny " "noÅ›nik\n" #: .././dump/content.c:5819 msgid "encountered EOM: media is full\n" msgstr "napotkano EOM: noÅ›nik jest peÅ‚ny\n" #: .././dump/content.c:5842 msgid "encountered corrupt or foreign data: assuming corrupted media\n" msgstr "napotkano uszkodzone lub obce dane: przyjÄ™to uszkodzony noÅ›nik\n" #: .././dump/content.c:5860 msgid "" "encountered corrupt or foreign data but expecting a media stream terminator: " "assuming corrupted media\n" msgstr "" "napotkano uszkodzone lub obce dane, ale oczekiwano terminatora strumienia " "noÅ›nika: przyjÄ™to uszkodzony noÅ›nik\n" #: .././dump/content.c:5868 msgid "" "encountered corrupt or foreign data: unable to overwrite: assuming corrupted " "media\n" msgstr "" "napotkano uszkodzone lub obce dane: nie można nadpisać: przyjÄ™to uszkodzony " "noÅ›nik\n" #: .././dump/content.c:5876 msgid "encountered corrupt or foreign data: repositioning to overwrite\n" msgstr "napotkano uszkodzone lub obce dane: zmiana pozycji w celu nadpisania\n" #: .././dump/content.c:5895 #, c-format msgid "unexpected error from do_begin_read: %d\n" msgstr "nieoczekiwany błąd w do_begin_read: %d\n" #: .././dump/content.c:5904 msgid "erasing media\n" msgstr "kasowanie noÅ›nika\n" #: .././dump/content.c:5952 .././restore/content.c:4800 #, c-format msgid "please change media: type %s to confirm media change\n" msgstr "proszÄ™ zmienić noÅ›nik i wpisać %s, aby potwierdzić zmianÄ™\n" #: .././dump/content.c:6087 msgid "no media label specified\n" msgstr "nie podano etykiety noÅ›nika\n" #: .././dump/content.c:6112 msgid "encountered end of media while attempting to begin new media file\n" msgstr "" "napotkano koniec noÅ›nika w trakcie próby rozpoczÄ™cia nowego pliku noÅ›nika\n" #: .././dump/content.c:6158 msgid "encountered end of media while ending media file\n" msgstr "napotkano koniec noÅ›nika w trakcie koÅ„czenia pliku noÅ›nika\n" #: .././dump/content.c:6301 #, c-format msgid "drive does not support media erase: ignoring -%c option\n" msgstr "urzÄ…dzenie nie obsÅ‚uguje kasowania noÅ›nika: zignorowano opcjÄ™ -%c\n" #: .././dump/content.c:6577 #, c-format msgid "saving %s information for: %s\n" msgstr "zapis informacji %s dla: %s\n" #: .././dump/content.c:6580 #, c-format msgid "overwriting: %s\n" msgstr "nadpisywanie: %s\n" #: .././dump/content.c:6604 #, c-format msgid "%s failed with exit status: %d\n" msgstr "%s nie powiodÅ‚o siÄ™ z kodem wyjÅ›cia: %d\n" #: .././dump/content.c:6610 #, c-format msgid "open failed %s: %s\n" msgstr "nie udaÅ‚o siÄ™ otworzyć %s: %s\n" #: .././dump/content.c:6617 #, c-format msgid "stat failed %s: %s\n" msgstr "stat na %s nie powiodÅ‚o siÄ™: %s\n" #: .././dump/inomap.c:244 msgid "ino map phase 1: constructing initial dump list\n" msgstr "mapa i-wÄ™złów faza 1: tworzenie poczÄ…tkowej listy zrzutu\n" #: .././dump/inomap.c:281 #, c-format msgid "pruned %llu files: maximum size exceeded\n" msgstr "wyciÄ™to %llu plików: przekroczony maksymalny rozmiar\n" #: .././dump/inomap.c:286 #, c-format msgid "pruned %llu files: skip attribute set\n" msgstr "wyciÄ™to %llu plików: ustawiony atrybut pominiÄ™cia\n" #: .././dump/inomap.c:297 msgid "ino map phase 2: pruning unneeded subtrees\n" msgstr "mapa i-wÄ™złów faza 2: wycinanie niepotrzebnych poddrzew\n" #: .././dump/inomap.c:318 msgid "ino map phase 2: skipping (no pruning necessary)\n" msgstr "mapa i-wÄ™złów faza 2: pominiÄ™to (wycinanie zbÄ™dne)\n" #: .././dump/inomap.c:330 msgid "ino map phase 3: identifying stream starting points\n" msgstr "mapa i-wÄ™złów faza 3: identyfikowanie poczÄ…tkowych punktów strumieni\n" #: .././dump/inomap.c:334 msgid "ino map phase 3: skipping (only one dump stream)\n" msgstr "mapa i-wÄ™złów faza 3: pominiÄ™to (tylko jeden strumieÅ„ zrzutu)\n" #: .././dump/inomap.c:374 #, c-format msgid "stream %u: ino %llu offset %lld to " msgstr "strumieÅ„ %u: i-wÄ™zeÅ‚ %llu offset %lld do " #: .././dump/inomap.c:380 msgid "end\n" msgstr "koÅ„ca\n" #: .././dump/inomap.c:383 #, c-format msgid "ino %llu offset %lld\n" msgstr "i-wÄ™zÅ‚a %llu offsetu %lld\n" #: .././dump/inomap.c:393 msgid "ino map construction complete\n" msgstr "tworzenie mapy i-wÄ™złów zakoÅ„czone\n" #: .././dump/inomap.c:1177 #, c-format msgid "failed to allocate inomap context: %s\n" msgstr "nie udaÅ‚o siÄ™ przydzielić kontekstu inomap: %s\n" #: .././dump/inomap.c:1500 msgid "subtree not present" msgstr "brak poddrzewa" #: .././dump/inomap.c:1501 msgid "invalid subtree specified" msgstr "podano błędne poddrzewo" #: .././dump/inomap.c:1653 #, c-format msgid "could not open ino %llu to read extent map: %s\n" msgstr "" "nie udaÅ‚o siÄ™ otworzyć i-wÄ™zÅ‚a %llu w celu odczytu mapy ekstentów: %s\n" #: .././dump/inomap.c:1666 #, c-format msgid "could not read extent map for ino %llu: %s\n" msgstr "nie udaÅ‚o siÄ™ odczytać mapy ekstentów dla i-wÄ™zÅ‚a %llu: %s\n" #: .././dump/inomap.c:1736 #, c-format msgid "unknown inode type: ino=%llu, mode=0x%04x 0%06o\n" msgstr "nieznany typ i-wÄ™zÅ‚a: ino=%llu, tryb=0x%04x 0%06o\n" #: .././dump/var.c:64 .././restore/content.c:1324 .././restore/tree.c:400 #, c-format msgid "unable to create %s: %s\n" msgstr "nie udaÅ‚o siÄ™ utworzyć %s: %s\n" #: .././dump/var.c:71 #, c-format msgid "unable to chown %s: %s\n" msgstr "nie udaÅ‚o siÄ™ wykonać chown na %s: %s\n" #: .././dump/var.c:92 #, c-format msgid "unable to determine uuid of fs containing %s: %s\n" msgstr "nie udaÅ‚o siÄ™ okreÅ›lić uuid-a systemu plików zawierajÄ…cego %s: %s\n" #: .././dump/var.c:121 #, c-format msgid "unable to get status of %s: %s\n" msgstr "nie udaÅ‚o siÄ™ uzyskać stanu %s: %s\n" #: .././dump/var.c:140 #, c-format msgid "unable to open directory %s\n" msgstr "nie udaÅ‚o siÄ™ otworzyć katalogu %s\n" #: .././inventory/inv_api.c:183 msgid "INV: put_fstab_entry failed.\n" msgstr "INV: put_fstab_entry nie powiodÅ‚o siÄ™.\n" #: .././inventory/inv_api.c:231 msgid "INV: put_starttime failed.\n" msgstr "INV: put_starttime nie powiodÅ‚o siÄ™.\n" #: .././inventory/inv_api.c:331 #, c-format msgid "INV: cant create more than %d streams. Max'd out..\n" msgstr "" "INV: nie można utworzyć wiÄ™cej niż %d strumieni. Wyczerpano możliwoÅ›ci...\n" #: .././inventory/inv_api.c:378 msgid "INV: idx_put_sesstime failed in inv_stream_close() \n" msgstr "INV: idx_put_sesstime nie powiodÅ‚o siÄ™ w inv_stream_close()\n" #: .././inventory/inv_api.c:763 .././inventory/inv_mgr.c:159 msgid "INV: Error in fstab\n" msgstr "INV: błąd w pliku fstab\n" #: .././inventory/inv_api.c:777 .././inventory/inv_mgr.c:170 msgid "INV: Cant get inv-name for uuid\n" msgstr "INV: nie można pobrać inv-name dla uuida\n" #: .././inventory/inv_api.c:784 .././inventory/inv_mgr.c:178 #, c-format msgid "INV: Open failed on %s\n" msgstr "INV: nie udaÅ‚o siÄ™ otworzyć %s\n" #: .././inventory/inv_api.c:968 #, c-format msgid "INV: invalid sub-option %s for -I option\n" msgstr "INV: błędna podopcja %s dla opcji -I\n" #: .././inventory/inv_api.c:982 msgid "INV: Only one of mnt=,dev= and fsid=value can be used.\n" msgstr "INV: można użyć tylko jednej z opcji mnt=, dev= i fsid=.\n" #: .././inventory/inv_api.c:988 msgid "INV: Only one of mobjid= and mobjlabel= can be used.\n" msgstr "INV: można użyć tylko jednej z opcji mobjid= i mobjlabel=.\n" #: .././inventory/inv_api.c:1034 #, c-format msgid "INV: open failed on mount point \"%s\"\n" msgstr "INV: nie udaÅ‚o siÄ™ otworzyć punktu montowania \"%s\"\n" #: .././inventory/inv_api.c:1049 #, c-format msgid "INV: open failed on file system id \"%s\"\n" msgstr "INV: nie udaÅ‚o siÄ™ otworzyć systemu plików o id \"%s\"\n" #: .././inventory/inv_api.c:1105 #, c-format msgid "INV: checking fs \"%s\"\n" msgstr "INV: sprawdzanie systemu plików \"%s\"\n" #: .././inventory/inv_core.c:62 #, c-format msgid "INV : Unknown version %d - Expected version %d\n" msgstr "INV: nieznana wersja %d - oczekiwano wersji %d\n" #: .././inventory/inv_core.c:86 msgid "get_headers() - malloc(seshdrs)\n" msgstr "get_headers() - malloc(seshdrs)\n" #: .././inventory/inv_core.c:119 msgid "Error in reading inventory record (lseek failed): " msgstr "Błąd podczas odczytu rekordu inwentarza (lseek nie powiodÅ‚o siÄ™): " #: .././inventory/inv_core.c:129 msgid "Error in reading inventory record :" msgstr "Błąd podczas odczytu rekordu inwentarza: " #: .././inventory/inv_core.c:160 msgid "Error in writing inventory record (lseek failed): " msgstr "Błąd podczas zapisu rekordu inwentarza (lseek nie powiodÅ‚o siÄ™): " #: .././inventory/inv_core.c:168 msgid "Error in writing inventory record :" msgstr "Błąd podczas zapisu rekordu inwentarza: " #: .././inventory/inv_fstab.c:62 msgid "INV: couldn't get fstab headers\n" msgstr "INV: nie udaÅ‚o siÄ™ pobrać nagłówków fstab\n" #: .././inventory/inv_fstab.c:190 msgid "INV: No recorded filesystems in inventory's fstab.\n" msgstr "INV: brak zapisanych systemów plików w fstab inwentarza.\n" #: .././inventory/inv_fstab.c:243 msgid "" "\n" "\n" "--------- fstab ------------\n" msgstr "" "\n" "\n" "--------- fstab ------------\n" #: .././inventory/inv_fstab.c:245 #, c-format msgid "Mount\t%s\n" msgstr "Montowanie\t%s\n" #: .././inventory/inv_fstab.c:246 #, c-format msgid "Dev\t%s\n" msgstr "UrzÄ…dzenie\t%s\n" #: .././inventory/inv_fstab.c:248 #, c-format msgid "" "FSid\t%s\n" "\n" msgstr "" "FSid \t%s\n" "\n" #: .././inventory/inv_mgr.c:457 #, c-format msgid "INV: Check %d failed.\n" msgstr "INV: test %d nie powiódÅ‚ siÄ™.\n" #: .././inventory/inv_mgr.c:458 #, c-format msgid "invidx (%d)\t%d - %d\n" msgstr "invidx (%d)\t%d - %d\n" #: .././inventory/inv_mgr.c:463 #, c-format msgid "tm (%d)\t%d\n" msgstr "tm (%d)\t%d\n" #: .././inventory/inv_mgr.c:467 #, c-format msgid "INV: Check %d out of %d succeeded\n" msgstr "INV: test %d z %d powiódÅ‚ siÄ™\n" #: .././inventory/inv_mgr.c:684 #, c-format msgid "%s created\n" msgstr "Utworzono %s\n" #: .././inventory/inv_stobj.c:140 msgid "INV: failed to find a different sh_time to split\n" msgstr "INV: nie udaÅ‚o siÄ™ odnaleźć innego sh_time do podziaÅ‚u\n" #: .././inventory/inv_stobj.c:1016 msgid "INV: inv_put_session: unknown cookie\n" msgstr "INV: inv_put_session: nieznane cookie\n" #: .././inventory/inv_stobj.c:1056 #, c-format msgid "INV: inv_put_session: unknown packed inventory version %d\n" msgstr "INV: inv_put_session: nieznana wersja spakowanego inwentarza %d\n" #: .././inventory/inv_stobj.c:1262 msgid "Failed to get data from media file: possible file corruption\n" msgstr "Nie udaÅ‚o siÄ™ pobrać danych z pliku: możliwe uszkodzenie pliku\n" #: .././librmt/rmtioctl.c:192 msgid "rmtioctl: remote host type not supported for MTIOCTOP\n" msgstr "rmtioctl: typ zdalnego hosta nie jest obsÅ‚ugiwany dla MTIOCTOP\n" #: .././librmt/rmtioctl.c:247 msgid "rmtioctl: remote host type not supported for MTIOCGET\n" msgstr "rmtioctl: typ zdalnego hosta nie jest obsÅ‚ugiwany dla MTIOCGET\n" #: .././librmt/rmtioctl.c:253 #, c-format msgid "rmtioctl: IRIX mtget structure of wrong size - got %d, wanted %d\n" msgstr "" "rmtioctl: IRIX-owa struktura mtget o zÅ‚ym rozmiarze - otrzymano %d, " "oczekiwano %d\n" #: .././librmt/rmtioctl.c:269 #, c-format msgid "" "rmtioctl: Linux mtget structure of wrong size - got %d, wanted %d or %d\n" msgstr "" "rmtioctl: linuksowa struktura mtget o zÅ‚ym rozmiarze - otrzymano %d, " "oczekiwano %d lub %d\n" #: .././librmt/rmtmsg.c:78 msgid "WARNING: " msgstr "WARNING: " #: .././librmt/rmtopen.c:176 #, c-format msgid "rmtopen: failed to detect remote host type using \"%s\"\n" msgstr "rmtopen: nie udaÅ‚o siÄ™ wykryć typu zdalnego hosta przy użyciu \"%s\"\n" #: .././librmt/rmtopen.c:188 #, c-format msgid "rmtopen: failed to detect remote host type reading \"%s\"\n" msgstr "rmtopen: nie udaÅ‚o siÄ™ wykryć typu zdalnego hosta czytajÄ…c \"%s\"\n" #: .././librmt/rmtopen.c:205 #, c-format msgid "rmtopen: remote host type, \"%s\", is unknown to librmt\n" msgstr "rmtopen: typ zdalnego hosta \"%s\" jest nieznany librmt\n" #: .././restore/content.c:987 #, c-format msgid "unable to get status of -%c argument %s: %s\n" msgstr "nie udaÅ‚o siÄ™ pobrać stanu argumentu -%c %s: %s\n" #: .././restore/content.c:1016 #, c-format msgid "-%c argument %s is an invalid pathname\n" msgstr "argument -%c %s jest błędnÄ… Å›cieżkÄ…\n" #: .././restore/content.c:1034 #, c-format msgid "cannot stat -%c argument %s (%s): %s\n" msgstr "nie można wykonać stat na argumencie -%c %s (%s): %s\n" #: .././restore/content.c:1044 #, c-format msgid "-%c argument %s (%s) is not a directory\n" msgstr "argument -%c %s (%s) nie jest katalogiem\n" #: .././restore/content.c:1076 #, c-format msgid "-%c argument %s too long: max is %d\n" msgstr "argument -%c %s zbyt dÅ‚ugi: maksimum to %d\n" #: .././restore/content.c:1125 #, c-format msgid "-%c argument must be relative\n" msgstr "argument -%c musi być wzglÄ™dny\n" #: .././restore/content.c:1149 #, c-format msgid "-%c unavailable: no /dev/tty\n" msgstr "-%c niedostÄ™pny: brak /dev/tty\n" #: .././restore/content.c:1193 .././restore/content.c:1201 #, c-format msgid "-%c and -%c option cannot be used together\n" msgstr "opcje -%c i -%c nie mogÄ… być użyte razem\n" #: .././restore/content.c:1236 #, c-format msgid "destination directory %s invalid pathname\n" msgstr "błędna Å›cieżka katalogu docelowego %s\n" #: .././restore/content.c:1253 #, c-format msgid "cannot stat destination directory %s: %s\n" msgstr "nie można wykonać stat na katalogu docelowym %s: %s\n" #: .././restore/content.c:1262 #, c-format msgid "specified destination %s is not a directory\n" msgstr "podany cel %s nie jest katalogiem\n" #: .././restore/content.c:1272 #, c-format msgid "" "do not specify destination directory if contents only restore invoked (-%c " "option)\n" msgstr "" "nie można podawać katalogu docelowego, jeÅ›li wybrano tylko odtworzenie " "zawartoÅ›ci (opcja -%c)\n" #: .././restore/content.c:1295 .././restore/content.c:1407 msgid "destination directory not specified\n" msgstr "nie podano katalogu docelowego\n" #: .././restore/content.c:1342 #, c-format msgid "could not open/create persistent state file %s: %s\n" msgstr "nie udaÅ‚o siÄ™ otworzyć/utworzyć pliku trwaÅ‚ego stanu %s: %s\n" #: .././restore/content.c:1356 #, c-format msgid "could not map persistent state file hdr %s: %s\n" msgstr "nie udaÅ‚o siÄ™ odwzorować nagłówka pliku trwaÅ‚ego stanu %s: %s\n" #: .././restore/content.c:1376 #, c-format msgid "%s format corrupt or wrong endianness (0x%x, expected 0x%x)\n" msgstr "" "format %s uszkodzony lub o błędnej kolejnoÅ›ci bajtów (0x%x, oczekiwano 0x" "%x)\n" #: .././restore/content.c:1385 #, c-format msgid "%s format version differs from previous restore (%u, expected %u)\n" msgstr "" "format %s w wersji innej niż przy poprzednim odtwarzaniu (%u, oczekiwano " "%u)\n" #: .././restore/content.c:1394 #, c-format msgid "" "%s format differs from previous restore due to page size change (was %lu, " "now %lu)\n" msgstr "" "format %s inny niż przy poprzednim odtwarzaniu z powodu zmiany rozmiaru " "strony (poprzednio %lu, teraz %lu)\n" #: .././restore/content.c:1413 #, c-format msgid "destination directory pathname too long: max is %d characters\n" msgstr "" "Å›cieżka do katalogu docelowego zbyt dÅ‚uga: maksymalna liczba znaków to %d\n" #: .././restore/content.c:1421 .././restore/content.c:1444 #, c-format msgid "-%c option invalid: there is no interrupted restore to resume\n" msgstr "błędna opcja -%c: nie ma przerwanego odtwarzania do wznowienia\n" #: .././restore/content.c:1429 .././restore/content.c:1452 #, c-format msgid "" "-%c option invalid: there is no interrupted restore to force completion of\n" msgstr "" "błędna opcja -%c: nie ma przerwanego odtwarzania do wymuszenia zakoÅ„czenia\n" #: .././restore/content.c:1438 #, c-format msgid "must rm -rf %s prior to noncumulative restore\n" msgstr "przed odtwarzaniem nieprzyrostowym trzeba wykonać rm -rf %s\n" #: .././restore/content.c:1460 .././restore/content.c:1467 #: .././restore/content.c:1474 .././restore/content.c:1481 #: .././restore/content.c:1496 #, c-format msgid "-%c valid only when initiating cumulative restore\n" msgstr "-%c jest poprawne tylko przy rozpoczynaniu odtwarzania przyrostowego\n" #: .././restore/content.c:1488 #, c-format msgid "-%c and -%c valid only when initiating cumulative restore\n" msgstr "" "-%c i -%c sÄ… poprawne tylko przy rozpoczynaniu odtwarzania przyrostowego\n" #: .././restore/content.c:1504 #, c-format msgid "" "-%c option required to resume or -%c option required to force completion of " "previously interrupted restore session\n" msgstr "" "wymagana jest opcja -%c do wznowienia lub opcja -%c do wymuszenia " "zakoÅ„czenia uprzednio przerwanej sesji odtwarzania\n" #: .././restore/content.c:1515 .././restore/content.c:1521 #: .././restore/content.c:1527 .././restore/content.c:1533 #: .././restore/content.c:1539 .././restore/content.c:1545 #: .././restore/content.c:1551 .././restore/content.c:1564 #, c-format msgid "-%c valid only when initiating restore\n" msgstr "-%c jest poprawne tylko przy rozpoczynaniu odtwarzania\n" #: .././restore/content.c:1557 #, c-format msgid "-%c and -%c valid only when initiating restore\n" msgstr "-%c i -%c sÄ… poprawne tylko przy rozpoczynaniu odtwarzania\n" #: .././restore/content.c:1573 .././restore/content.c:1580 #, c-format msgid "-%c cannot reset flag from previous restore\n" msgstr "-%c nie może przywrócić flagi z poprzedniego odtwarzania\n" #: .././restore/content.c:1607 .././restore/content.c:1946 #, c-format msgid "chdir %s failed: %s\n" msgstr "chdir %s nie powiodÅ‚o siÄ™: %s\n" #: .././restore/content.c:1678 #, c-format msgid "resuming restore previously begun %s\n" msgstr "wznawianie odtwarzania poprzednio rozpoczÄ™tego %s\n" #: .././restore/content.c:1698 #, c-format msgid "could not map persistent state file %s: %s\n" msgstr "nie udaÅ‚o siÄ™ odwzorować pliku trwaÅ‚ego stanu %s: %s\n" #: .././restore/content.c:1813 #, c-format msgid "could not map persistent state file inv %s: %s (%d)\n" msgstr "nie udaÅ‚o siÄ™ odwzorować pliku trwaÅ‚ego stanu inw %s: %s (%d)\n" #: .././restore/content.c:2025 msgid "searching media for dump\n" msgstr "poszukiwanie zrzutu na noÅ›niku\n" #: .././restore/content.c:2097 msgid "found dump matching specified id:\n" msgstr "znaleziono zrzut pasujÄ…cy do podanego id:\n" #: .././restore/content.c:2111 msgid "found dump matching specified label:\n" msgstr "znaleziono zrzut pasujÄ…cy do podanej etykiety:\n" #: .././restore/content.c:2142 msgid "dump description: \n" msgstr "opis zrzutu: \n" #: .././restore/content.c:2186 .././restore/content.c:3758 msgid "using online session inventory\n" msgstr "korzystanie z inwentarza sesji online\n" #: .././restore/content.c:2217 msgid "searching media for directory dump\n" msgstr "poszukiwanie zrzutu katalogów na noÅ›niku\n" #: .././restore/content.c:2293 msgid "no directory dump found\n" msgstr "nie znaleziono zrzutu katalogu\n" #: .././restore/content.c:2385 msgid "reading directories\n" msgstr "odczyt katalogów\n" #: .././restore/content.c:2455 msgid "directory post-processing\n" msgstr "przetwarzanie katalogów\n" #: .././restore/content.c:2534 msgid "reading non-directory files\n" msgstr "odczyt plików nie-katalogów\n" #: .././restore/content.c:2537 msgid "restoring non-directory files\n" msgstr "odtwarzanie plików nie-katalogów\n" #: .././restore/content.c:2635 #, c-format msgid "table of contents display complete: %ld seconds elapsed\n" msgstr "wyÅ›wietlanie spisu zawartoÅ›ci zakoÅ„czone; minęło %ld s\n" #: .././restore/content.c:2654 msgid "use 'xfs_quota' to restore quotas\n" msgstr "aby odtworzyć limity (quota), należy użyć 'xfs_quota'\n" #: .././restore/content.c:2657 #, c-format msgid "restore complete: %ld seconds elapsed\n" msgstr "odtwarzanie zakoÅ„czone; minęło %ld s\n" #: .././restore/content.c:2664 #, c-format msgid "table of contents display interrupted: %ld seconds elapsed\n" msgstr "wyÅ›wietlanie spisu zawartoÅ›ci przerwane; minęło %ld s\n" #: .././restore/content.c:2670 #, c-format msgid "" "restore interrupted: %ld seconds elapsed: may resume later using -%c option\n" msgstr "" "odtwarzanie przerwane; minęło %ld s; można wznowić później przy użyciu opcji " "-%c\n" #: .././restore/content.c:2741 #, c-format msgid "" "status at %02d:%02d:%02d: %llu/%llu directories reconstructed, %.1f%%%% " "complete, %llu directory entries processed, %ld seconds elapsed\n" msgstr "" "status przy %02d:%02d:%02d: odtworzono katalogów: %llu/%llu, wykonane %.1f%%" "%%, przetworzono wpisów katalogów: %llu, minęło %ld s\n" #: .././restore/content.c:2784 #, c-format msgid "" "status at %02d:%02d:%02d: %llu/%llu files restored, %.1f%%%% complete, %ld " "seconds elapsed\n" msgstr "" "status przy %02d:%02d:%02d: odtworzono plików: %llu/%llu, wykonane %.1f%%%%, " "minęło %ld s\n" #: .././restore/content.c:2861 msgid "select a drive to acknowledge media change\n" msgstr "proszÄ™ wybrać napÄ™d w celu potwierdzenia zmiany noÅ›nika\n" #: .././restore/content.c:2868 #, c-format msgid "drive %u" msgstr "napÄ™d %u" #: .././restore/content.c:2878 msgid "display needed media objects" msgstr "wyÅ›wietlenie wymaganych obiektów noÅ›nika" #: .././restore/content.c:2898 msgid "media change acknowledged\n" msgstr "potwierdzono zmianÄ™ noÅ›nika\n" #: .././restore/content.c:2982 msgid "" "dump is not self-contained, orphaned files expected if base dump(s) was not " "applied\n" msgstr "" "zrzut nie jest samodzielny, można oczekiwać osieroconych plików, jeÅ›li nie " "naÅ‚ożono zrzutów bazowych\n" #: .././restore/content.c:3139 #, c-format msgid "%llu directories and %llu entries processed\n" msgstr "przetworzono katalogów: %llu, wpisów: %llu\n" #: .././restore/content.c:3361 #, c-format msgid "subtree argument %s invalid\n" msgstr "błędny argument poddrzewa %s\n" #: .././restore/content.c:3501 .././restore/content.c:3556 msgid "" "unable to resync media file: some portion of dump will NOT be restored\n" msgstr "" "nie udaÅ‚o siÄ™ zresynchronizować pliku noÅ›nika - pewna część zrzutu NIE " "zostanie odtworzona\n" #: .././restore/content.c:3569 #, c-format msgid "resynchronization achieved at ino %llu offset %lld\n" msgstr "udaÅ‚o siÄ™ zresynchronizować pod i-wÄ™zÅ‚em %llu, offset %lld\n" #: .././restore/content.c:4026 .././restore/content.c:4303 #: .././restore/content.c:4413 .././restore/content.c:4446 #: .././restore/content.c:4511 .././restore/content.c:4664 msgid "rewinding\n" msgstr "przewijanie\n" #: .././restore/content.c:4051 #, c-format msgid "examining media file %u\n" msgstr "badanie pliku noÅ›nika %u\n" #: .././restore/content.c:4223 #, c-format msgid "" "inventory session uuid (%s) does not match the media header's session uuid " "(%s)\n" msgstr "" "uuid sesji inwentarza (%s) nie zgadza siÄ™ z uuidem sesji nagłówka noÅ›nika " "(%s)\n" #: .././restore/content.c:4558 msgid "seeking past portion of media file already restored\n" msgstr "przemieszczanie za już odtworzonÄ… część pliku noÅ›nika\n" #: .././restore/content.c:4577 .././restore/content.c:4596 msgid "seeking past media file directory dump\n" msgstr "przemieszczanie za zrzut katalogu plików noÅ›nika\n" #: .././restore/content.c:4755 msgid "media object not useful\n" msgstr "obiekt noÅ›nika nieprzydatny\n" #: .././restore/content.c:4758 msgid "media object empty\n" msgstr "obiekt noÅ›nika pusty\n" #: .././restore/content.c:4761 msgid "all media files examined, none selected for restoral\n" msgstr "" "zbadano wszystkie pliki noÅ›nika, żaden nie zostaÅ‚ wybrany do odtworzenia\n" #: .././restore/content.c:4951 #, c-format msgid "could not remap persistent state file inv %s: %d (%s)\n" msgstr "nie udaÅ‚o siÄ™ przemapować pliku trwaÅ‚ego stanu inw %s: %d (%s)\n" #: .././restore/content.c:5470 msgid "on-media session inventory corrupt\n" msgstr "uszkodzony inwentarz sesji na noÅ›niku\n" #: .././restore/content.c:5479 msgid "incorporating on-media session inventory into online inventory\n" msgstr "nanoszenie inwentarza sesji z noÅ›nika do inwentarza online\n" #: .././restore/content.c:6463 #, c-format msgid "" "hit EOD at stream %u object %u, yet inventory indicates last object index is " "%u\n" msgstr "" "napotkano EOD w strumieniu %u, obiekcie %u, ale inwentarz okreÅ›la indeks " "ostatniego obiektu %u\n" #: .././restore/content.c:6526 #, c-format msgid "" "hit next dump at stream %u object %u file %u, yet inventory indicates last " "object index is %u\n" msgstr "" "napotkano nastÄ™pny zrzut w strumieniu %u, obiekcie %u, pliku %u, ale " "inwentarz okreÅ›la ostatni indeks obiektu %u\n" #: .././restore/content.c:6808 msgid "unable to open inventory to validate dump\n" msgstr "" "nie udaÅ‚o siÄ™ otworzyć inwentarza w celu sprawdzenia poprawnoÅ›ci zrzutu\n" #: .././restore/content.c:6825 msgid "unable to find base dump in inventory to validate dump\n" msgstr "" "nie udaÅ‚o siÄ™ odnaleźć podstawowego zrzutu w inwentarzu w celu sprawdzenia " "poprawnoÅ›ci zrzutu\n" #: .././restore/content.c:6854 msgid "" "cumulative restores must begin with an initial (not resumed) level 0 dump\n" msgstr "" "odtwarzanie przyrostowe musi rozpocząć siÄ™ od poczÄ…tkowego (nie wznowionego) " "zrzutu poziomu 0\n" #: .././restore/content.c:6863 msgid "cumulative restores must begin with a level 0 dump\n" msgstr "odtwarzanie przyrostowe musi rozpocząć siÄ™ od zrzutu poziomu 0\n" #: .././restore/content.c:6874 msgid "selected resumed dump not a resumption of previously applied dump\n" msgstr "" "wybrano wznowiony zrzut, a nie wznowienie poprzednio naÅ‚ożonego zrzutu\n" #: .././restore/content.c:6885 msgid "selected dump not based on previously applied dump\n" msgstr "wybrano zrzut nie oparty na poprzednio naÅ‚ożonym zrzucie\n" #: .././restore/content.c:6945 #, c-format msgid "please change media in drive\n" msgstr "proszÄ™ zmienić noÅ›nik w napÄ™dzie\n" #: .././restore/content.c:6956 msgid "display media inventory status" msgstr "wyÅ›wietlenie stanu inwentarza noÅ›nika" #: .././restore/content.c:6958 msgid "list needed media objects" msgstr "wypisanie wymaganych obiektów noÅ›nika" #: .././restore/content.c:7085 msgid "dump selection dialog" msgstr "dialog wyboru zrzutu" #: .././restore/content.c:7096 #, c-format msgid "" "the following dump has been found on drive %u\n" "\n" msgstr "" "w napÄ™dzie %u znaleziono nastÄ™pujÄ…cy zrzut\n" "\n" #: .././restore/content.c:7102 #, c-format msgid "" "the following dump has been found\n" "\n" msgstr "" "znaleziono nastÄ™pujÄ…cy zrzut\n" "\n" #: .././restore/content.c:7116 msgid "" "\n" "examine this dump?\n" msgstr "" "\n" "zbadać ten zrzut?\n" #: .././restore/content.c:7119 msgid "" "\n" "interactively restore from this dump?\n" msgstr "" "\n" "interaktywnie odtworzyć z tego zrzutu?\n" #: .././restore/content.c:7120 msgid "" "\n" "restore this dump?\n" msgstr "" "\n" "odtworzyć ten zrzut?\n" #: .././restore/content.c:7125 msgid "skip" msgstr "pominąć" #: .././restore/content.c:7128 msgid "interactively restore\n" msgstr "odtworzyć interaktywnie\n" #: .././restore/content.c:7128 msgid "restore\n" msgstr "odtworzyć\n" #: .././restore/content.c:7148 msgid "this dump selected for interactive restoral\n" msgstr "zrzut wybrany do interaktywnego odtworzenia\n" #: .././restore/content.c:7149 msgid "this dump selected for restoral\n" msgstr "zrzut wybrany do odtworzenia\n" #: .././restore/content.c:7151 msgid "dump skipped\n" msgstr "zrzut pominiÄ™ty\n" #: .././restore/content.c:7323 #, c-format msgid "ino %llu: unknown file type: %08x\n" msgstr "i-wÄ™zeÅ‚ %llu: nieznany typ pliku: %08x\n" #: .././restore/content.c:7338 #, c-format msgid "unable to unlink current file prior to linking %s to %s: %s\n" msgstr "nie udaÅ‚o siÄ™ usunąć bieżącego pliku przed dowiÄ…zaniem %s do %s: %s\n" #: .././restore/content.c:7349 #, c-format msgid "attempt to link %s to %s failed: %s\n" msgstr "próba dowiÄ…zania %s do %s nie powiodÅ‚a siÄ™: %s\n" #: .././restore/content.c:7386 .././restore/content.c:7895 #: .././restore/content.c:8050 #, c-format msgid "chown (uid=%u, gid=%u) %s failed: %s\n" msgstr "chown (uid=%u, gid=%u) pliku %s nie powiodÅ‚o siÄ™: %s\n" #: .././restore/content.c:7391 #, c-format msgid "stripping setuid bit on %s since chown failed\n" msgstr "kasowanie bitu setuid pliku %s z powodu niepowodzenia chown\n" #: .././restore/content.c:7398 #, c-format msgid "stripping setgid bit on %s since chown failed\n" msgstr "kasowanie bitu setgid pliku %s z powodu niepowodzenia chown\n" #: .././restore/content.c:7409 #, c-format msgid "unable to strip setuid/setgid on %s, unlinking file.\n" msgstr "nie udaÅ‚o siÄ™ skasować bitu setuid/setgid pliku %s, usuwanie pliku.\n" #: .././restore/content.c:7454 #, c-format msgid "%s (offset %lld)\n" msgstr "%s (offset %lld)\n" #: .././restore/content.c:7481 #, c-format msgid "open of %s failed: %s: discarding ino %llu\n" msgstr "otwarcie %s nie powiodÅ‚o siÄ™: %s: porzucanie i-wÄ™zÅ‚a %llu\n" #: .././restore/content.c:7491 #, c-format msgid "attempt to stat %s failed: %s\n" msgstr "próba wykonania stat na %s nie powiodÅ‚a siÄ™: %s\n" #: .././restore/content.c:7505 #, c-format msgid "attempt to truncate %s failed: %s\n" msgstr "próba uciÄ™cia %s nie powiodÅ‚a siÄ™: %s\n" #: .././restore/content.c:7532 .././restore/content.c:7753 #, c-format msgid "" "attempt to set extended attributes (xflags 0x%x, extsize = 0x%x, projid = 0x" "%x) of %s failed: %s\n" msgstr "" "próba ustawienia rozszerzonych atrybutów (xflags 0x%x, extsize = 0x%x, " "projid = 0x%x) pliku %s nie powiodÅ‚a siÄ™: %s\n" #: .././restore/content.c:7696 .././restore/content.c:7921 #, c-format msgid "unable to set access and modification times of %s: %s\n" msgstr "nie udaÅ‚o siÄ™ ustawić czasów dostÄ™pu i modyfikacji pliku %s: %s\n" #: .././restore/content.c:7715 .././restore/content.c:7909 #, c-format msgid "unable to set mode of %s: %s\n" msgstr "nie udaÅ‚o siÄ™ ustawić uprawnieÅ„ pliku %s: %s\n" #: .././restore/content.c:7731 #, c-format msgid "attempt to set DMI attributes of %s failed: %s\n" msgstr "próba ustawienia atrybutów DMI pliku %s nie powiodÅ‚a siÄ™: %s\n" #: .././restore/content.c:7783 msgid "block special file" msgstr "plik urzÄ…dzenia blokowego" #: .././restore/content.c:7786 msgid "char special file" msgstr "plik urzÄ…dzenia znakowego" #: .././restore/content.c:7789 msgid "named pipe" msgstr "nazwany potok" #: .././restore/content.c:7793 msgid "XENIX named pipe" msgstr "nazwany potok XENIX" #: .././restore/content.c:7797 msgid "UNIX domain socket" msgstr "gniazdo uniksowe" #: .././restore/content.c:7801 #, c-format msgid "%s: unknown file type: mode 0x%x ino %llu\n" msgstr "%s: nieznany rodzaj pliku: tryb 0x%x i-wÄ™zeÅ‚ %llu\n" #: .././restore/content.c:7829 .././restore/content.c:7877 #, c-format msgid "unable to create %s ino %llu %s: %s: discarding\n" msgstr "nie udaÅ‚o siÄ™ utworzyć %s, i-wÄ™zeÅ‚ %llu %s: %s: porzucono\n" #: .././restore/content.c:7841 #, c-format msgid "pathname too long for bind of %s ino %llu %s: discarding\n" msgstr "Å›cieżka zbyt dÅ‚uga do dowiÄ…zania %s, i-wÄ™zeÅ‚ %llu %s: porzucono\n" #: .././restore/content.c:7858 #, c-format msgid "unable to bind %s ino %llu %s: %s: discarding\n" msgstr "nie udaÅ‚o siÄ™ dowiÄ…zać %s, i-wÄ™zeÅ‚ %llu %s: %s: porzucono\n" #: .././restore/content.c:8010 #, c-format msgid "unable to create symlink ino %llu %s: src too long: discarding\n" msgstr "" "nie udaÅ‚o siÄ™ utworzyć dowiÄ…zania symbolicznego, i-wÄ™zeÅ‚ %llu %s: źródÅ‚o " "zbyt dÅ‚ugie: porzucono\n" #: .././restore/content.c:8034 #, c-format msgid "unable to create symlink ino %llu %s: %s: discarding\n" msgstr "" "nie udaÅ‚o siÄ™ utworzyć dowiÄ…zania symbolicznego, i-wÄ™zeÅ‚ %llu %s: %s: " "porzucono\n" #: .././restore/content.c:8121 msgid "corrupt file header\n" msgstr "uszkodzony nagłówek pliku\n" #: .././restore/content.c:8126 msgid "bad file header checksum\n" msgstr "błędna suma kontrolna nagłówka pliku\n" #: .././restore/content.c:8180 msgid "corrupt extent header\n" msgstr "uszkodzony nagłówek ekstentu\n" #: .././restore/content.c:8185 msgid "bad extent header checksum\n" msgstr "błędna suma kontrolna nagłówka ekstentu\n" #: .././restore/content.c:8244 .././restore/content.c:8259 msgid "bad directory entry header checksum\n" msgstr "błędna suma kontrolna nagłówka wpisu katalogu\n" #: .././restore/content.c:8272 msgid "corrupt directory entry header\n" msgstr "uszkodzony nagłówek wpisu katalogu\n" #: .././restore/content.c:8367 msgid "bad extattr header checksum\n" msgstr "błędna suma kontrolna nagłówka rozszerzonych atrybutów\n" #: .././restore/content.c:8378 msgid "ignoring old-style extattr header checksums\n" msgstr "" "zignorowano sumy kontrolne nagłówka rozszerzonych atrybutów starego typu\n" #: .././restore/content.c:8384 msgid "corrupt extattr header\n" msgstr "uszkodzony nagłówek rozszerzonych atrybutów\n" #: .././restore/content.c:8452 #, c-format msgid "" "attempt to seek %s to %lld failed: %s: not restoring extent off %lld sz " "%lld\n" msgstr "" "próba przemieszczenia %s na %lld nie powiodÅ‚a siÄ™: %s: nie przywracanie " "ekstentu offset %lld rozm %lld\n" #: .././restore/content.c:8467 #, c-format msgid "dioinfo %s failed: %s: discarding ino %llu\n" msgstr "dioinfo %s nie powiodÅ‚o siÄ™: %s: porzucono i-wÄ™zeÅ‚ %llu\n" #: .././restore/content.c:8495 .././restore/content.c:8511 #: .././restore/content.c:8515 msgid "end of media file" msgstr "koniec pliku noÅ›nika" #: .././restore/content.c:8499 msgid "end of recorded data" msgstr "koniec zapisanych danych" #: .././restore/content.c:8503 msgid "end of media" msgstr "koniec noÅ›nika" #: .././restore/content.c:8507 msgid "media error or no media" msgstr "błąd noÅ›nika lub brak noÅ›nika" #: .././restore/content.c:8520 msgid "dumping core" msgstr "zrzut pamiÄ™ci" #: .././restore/content.c:8524 #, c-format msgid "attempt to read %u bytes failed: %s\n" msgstr "próba odczytu bloku %u-bajtowego nie powiodÅ‚a siÄ™: %s\n" #: .././restore/content.c:8611 .././restore/content.c:8646 #, c-format msgid "" "attempt to write %u bytes to %s at offset %lld failed: only %d bytes " "written\n" msgstr "" "próba zapisu bloku %u-bajtowego do %s pod %lld nie powiodÅ‚a siÄ™: zapisano " "tylko %d bajtów\n" #: .././restore/content.c:8637 #, c-format msgid "attempt to write %u bytes to %s at offset %lld failed: %s\n" msgstr "próba zapisu bloku %u-bajtowego do %s pod %lld nie powiodÅ‚a siÄ™: %s\n" #: .././restore/content.c:8686 msgid "Failed to allocate extended attribute buffer\n" msgstr "Nie udaÅ‚o siÄ™ przydzielić bufora rozszerzonych atrybutów\n" #: .././restore/content.c:8882 #, c-format msgid "unable to set %s extended attribute for %s: %s (%d)\n" msgstr "" "nie udaÅ‚o siÄ™ ustawić rozszerzonego atrybutu przestrzeni %s dla %s: %s (%d)\n" #: .././restore/content.c:9055 msgid "partial_reg: Out of records. Extend attrs applied early.\n" msgstr "partial_reg: Brak rekordów. WczeÅ›nie naÅ‚ożone rozszerzone atrybuty.\n" #: .././restore/content.c:9227 msgid "overwrites inhibited" msgstr "nadpisania zabronione" #: .././restore/content.c:9235 msgid "too old" msgstr "za stare" #: .././restore/content.c:9244 msgid "existing version is newer" msgstr "istniejÄ…ca wersja jest nowsza" #: .././restore/content.c:9324 msgid "session inventory unknown\n" msgstr "nieznany inwentarz sesji\n" #: .././restore/content.c:9329 msgid "session inventory display\n" msgstr "wyÅ›wietlenie inwentarza sesji\n" #: .././restore/content.c:9342 #, c-format msgid "" "\n" "media stream %u:\n" msgstr "" "\n" "strumieÅ„ noÅ›nika %u:\n" #: .././restore/content.c:9346 msgid "" "\n" " media objects not yet identified\n" msgstr "" "\n" " nie zidentyfikowano jeszcze obiektów noÅ›nika\n" #: .././restore/content.c:9360 #, c-format msgid "" "\n" " media object %u:\n" "\n" msgstr "" "\n" " obiekt noÅ›nika %u:\n" "\n" #: .././restore/content.c:9365 msgid " label: " msgstr " etykieta: " #: .././restore/content.c:9371 msgid " label is blank\n" msgstr " etykieta jest pusta\n" #: .././restore/content.c:9378 #, c-format msgid " id: %s\n" msgstr " id: %s\n" #: .././restore/content.c:9383 msgid " label not identified\n" msgstr " etykieta nie zidentyfikowana\n" #: .././restore/content.c:9387 #, c-format msgid " index within object of first media file: %u\n" msgstr " indeks wewnÄ…trz obiektu pierwszego pliku noÅ›nika: %u\n" #: .././restore/content.c:9393 #, c-format msgid " index within stream of first media file: %u\n" msgstr " indeks wewnÄ…trz strumienia pierwszego pliku noÅ›nika: %u\n" #: .././restore/content.c:9401 .././restore/content.c:9637 #, c-format msgid " now in drive %u\n" msgstr " teraz w napÄ™dzie %u\n" #: .././restore/content.c:9405 .././restore/content.c:9645 msgid " now in drive\n" msgstr " teraz w napÄ™dzie\n" #: .././restore/content.c:9411 msgid " media files not yet identified\n" msgstr " pliki noÅ›nika jeszcze nie zidentyfikowane\n" #: .././restore/content.c:9424 #, c-format msgid "" "\n" " media file %u" msgstr "" "\n" " plik noÅ›nika %u" #: .././restore/content.c:9436 #, c-format msgid " size: %lld bytes\n" msgstr " rozmiar: %lld (bajtów)\n" #: .././restore/content.c:9442 msgid " used for directory restoral\n" msgstr " użyto do odtworzenia katalogu\n" #: .././restore/content.c:9447 #, c-format msgid " first extent contained: ino %llu off %lld\n" msgstr " pierwszy ekstent zawieraÅ‚: i-wÄ™zeÅ‚ %llu offset %lld\n" #: .././restore/content.c:9452 #, c-format msgid " next extent to restore: ino %llu off %lld\n" msgstr " nastÄ™pny ekstent do odtworzenia: i-wÄ™zeÅ‚ %llu offset %lld\n" #: .././restore/content.c:9457 #, c-format msgid " rollback mark %lld\n" msgstr " znacznik wycofania %lld\n" #: .././restore/content.c:9462 msgid " contains no selected non-directories\n" msgstr " nie zawiera wybranych nie-katalogów\n" #: .././restore/content.c:9467 msgid " non-directories done\n" msgstr " nie-katalogi skoÅ„czone\n" #: .././restore/content.c:9471 msgid " contains session inventory\n" msgstr " zawiera inwentarz sesji\n" #: .././restore/content.c:9476 msgid " is stream terminator\n" msgstr " jest znacznikiem zakoÅ„czenia strumienia\n" #: .././restore/content.c:9480 msgid " now reading\n" msgstr " trwa odczyt\n" #: .././restore/content.c:9485 msgid "" "\n" " may be additional unidentified media files\n" msgstr "" "\n" " mogÄ… być dodatkowe niezidentyfikowane pliki noÅ›nika\n" #: .././restore/content.c:9491 msgid "" "\n" " may be additional unidentified media objects\n" "\n" msgstr "" "\n" " mogÄ… być dodatkowe niezidentyfikowane obiekty noÅ›nika\n" "\n" #: .././restore/content.c:9545 #, c-format msgid "hostname: %s\n" msgstr "nazwa hosta: %s\n" #: .././restore/content.c:9548 #, c-format msgid "mount point: %s\n" msgstr "punkt montowania: %s\n" #: .././restore/content.c:9551 #, c-format msgid "volume: %s\n" msgstr "wolumen: %s\n" #: .././restore/content.c:9554 #, c-format msgid "session time: %s" msgstr "czas sesji: %s" #: .././restore/content.c:9557 #, c-format msgid "level: %s%s\n" msgstr "poziom: %s%s\n" #: .././restore/content.c:9561 msgid " resumed" msgstr " wznowiony" #: .././restore/content.c:9565 msgid "session label: " msgstr "etykieta sesji: " #: .././restore/content.c:9570 msgid "media label: " msgstr "etykieta noÅ›nika: " #: .././restore/content.c:9575 #, c-format msgid "file system id: %s\n" msgstr "ID systemu plików: %s\n" #: .././restore/content.c:9581 #, c-format msgid "media id: %s\n" msgstr "ID noÅ›nika: %s\n" #: .././restore/content.c:9601 msgid "" "the following media objects contain media files not yet tried for directory " "hierarchy restoral:\n" msgstr "" "nastÄ™pujÄ…ce obiekty noÅ›nika zawierajÄ… pliki noÅ›nika, które jeszcze nie byÅ‚y " "użyte do próby odtworzenia hierarchii katalogów:\n" #: .././restore/content.c:9607 msgid "the following media objects are needed:\n" msgstr "sÄ… potrzebne nastÄ™pujÄ…ce obiekty noÅ›nika:\n" #: .././restore/content.c:9620 #, c-format msgid "%2u. label: " msgstr "%2u. etykieta: " #: .././restore/content.c:9626 msgid " id: " msgstr " id: " #: .././restore/content.c:9656 msgid "" "\n" "there are additional unidentified media objects containing media files not " "yet tried for directory hierarchy restoral:\n" msgstr "" "\n" "istniejÄ… dodatkowe, niezidentyfikowane obiekty noÅ›nika zawierajÄ…ce pliki " "noÅ›nika jeszcze nie użyte do próby odtworzenia hierarchii katalogów:\n" #: .././restore/content.c:9660 msgid "" "\n" "there are unidentified media objects containing media files not yet tried " "for directory hierarchy restoral:\n" msgstr "" "\n" "istniejÄ… niezidentyfikowane obiekty noÅ›nika, zawierajÄ…ce pliki noÅ›nika " "jeszcze nie użyte do próby odtworzenia hierarchii katalogów:\n" #: .././restore/content.c:9667 msgid "" "\n" "there are additional unidentified media objects not yet fully restored\n" msgstr "" "\n" "istniejÄ… dodatkowe, niezidentyfikowane obiekty noÅ›nika, jeszcze nie w peÅ‚ni " "odtworzone\n" #: .././restore/content.c:9670 msgid "" "\n" "there are unidentified media objects not yet fully restored\n" msgstr "" "\n" "istniejÄ… niezidentyfikowane obiekty noÅ›nika, jeszcze nie w peÅ‚ni odtworzone\n" #: .././restore/content.c:9677 msgid "" "\n" "there may be additional unidentified media objects containing media files " "not yet tried for directory hierarchy restoral:\n" msgstr "" "\n" "mogÄ… istnieć dodatkowe, niezidentyfikowane obiekty noÅ›nika, zawierajÄ…ce " "pliki noÅ›nika jeszcze nie użyte do próby odtworzenia hierarchii katalogów:\n" #: .././restore/content.c:9681 msgid "" "\n" "there may be unidentified media objects containing media files not yet tried " "for directory hierarchy restoral:\n" msgstr "" "\n" "mogÄ… istnieć niezidentyfikowane obiekty noÅ›nika, zawierajÄ…ce pliki noÅ›nika " "jeszcze nie użyte do próby odtworzenia hierarchii katalogów:\n" #: .././restore/content.c:9689 msgid "" "\n" "there may be additional unidentified media objects not yet fully restored\n" msgstr "" "\n" "mogÄ… istnieć dodatkowe, niezidentyfikowane obiekty noÅ›nika, jeszcze nie w " "peÅ‚ni odtworzone\n" #: .././restore/content.c:9692 msgid "\there may be unidentified media objects not yet fully restored\n" msgstr "" "\tmogÄ… istnieć niezidentyfikowane obiekty noÅ›nika, jeszcze nie w peÅ‚ni " "odtworzone\n" #: .././restore/content.c:9699 msgid "no additional media objects needed\n" msgstr "nie sÄ… potrzebne dodatkowe obiekty noÅ›nika\n" #: .././restore/content.c:9714 .././restore/tree.c:2531 #, c-format msgid "path_to_handle of %s failed:%s\n" msgstr "path_to_handle na %s nie powiodÅ‚o siÄ™: %s\n" #: .././restore/content.c:9723 #, c-format msgid "fssetdm_by_handle of %s failed %s\n" msgstr "fssetdm_by_handle na %s nie powiodÅ‚o siÄ™: %s\n" #: .././restore/content.c:9742 #, c-format msgid "%s quota information written to '%s'\n" msgstr "informacje o limitach %s zapisano do '%s'\n" #: .././restore/dirattr.c:230 #, c-format msgid "could not find directory attributes file %s: %s\n" msgstr "nie udaÅ‚o siÄ™ odnaleźć pliku atrybutów katalogów %s: %s\n" #: .././restore/dirattr.c:246 #, c-format msgid "could not create directory attributes file %s: %s\n" msgstr "nie udaÅ‚o siÄ™ odnaleźć pliku atrybutów katalogów %s: %s\n" #: .././restore/dirattr.c:291 .././restore/namreg.c:206 #, c-format msgid "attempt to reserve %lld bytes for %s using %s failed: %s (%d)\n" msgstr "" "próba zarezerwowania %lld bajtów dla %s przy użyciu %s nie powiodÅ‚a siÄ™: %s " "(%d)\n" #: .././restore/dirattr.c:320 .././restore/inomap.c:233 #: .././restore/inomap.c:398 .././restore/namreg.c:235 .././restore/tree.c:435 #: .././restore/tree.c:610 #, c-format msgid "unable to map %s: %s\n" msgstr "nie można odwzorować %s: %s\n" #: .././restore/dirattr.c:407 .././restore/dirattr.c:799 #: .././restore/dirattr.c:1002 .././restore/dirattr.c:1079 #, c-format msgid "lseek of dirattr failed: %s\n" msgstr "lseek pliku dirattr nie powiodÅ‚o siÄ™: %s\n" #: .././restore/dirattr.c:491 .././restore/dirattr.c:642 #, c-format msgid "could not open/create directory extended attributes file %s: %s (%d)\n" msgstr "" "nie udaÅ‚o siÄ™ otworzyć/utworzyć pliku rozszerzonych atrybutów katalogów %s: " "%s (%d)\n" #: .././restore/dirattr.c:510 .././restore/dirattr.c:591 #: .././restore/dirattr.c:668 #, c-format msgid "could not seek to into extended attributes file %s: %s (%d)\n" msgstr "" "nie udaÅ‚o siÄ™ przemieÅ›cić w pliku rozszerzonych atrybutów %s: %s (%d)\n" #: .././restore/dirattr.c:528 .././restore/dirattr.c:686 #: .././restore/dirattr.c:703 .././restore/dirattr.c:722 #, c-format msgid "could not read extended attributes file %s: %s (%d)\n" msgstr "nie udaÅ‚o siÄ™ odczytać pliku rozszerzonych atrybutów %s: %s (%d)\n" #: .././restore/dirattr.c:544 #, c-format msgid "could not seek to end of extended attributes file %s: %s (%d)\n" msgstr "" "nie udaÅ‚o siÄ™ przemieÅ›cić na koniec pliku rozszerzonych atrybutów %s: %s " "(%d)\n" #: .././restore/dirattr.c:559 .././restore/dirattr.c:606 #, c-format msgid "could not write extended attributes file %s: %s (%d)\n" msgstr "nie udaÅ‚o siÄ™ zapisać pliku rozszerzonych atrybutów %s: %s (%d)\n" #: .././restore/dirattr.c:571 #, c-format msgid "could not write at end of extended attributes file %s: %s (%d)\n" msgstr "" "nie udaÅ‚o siÄ™ zapisać na koÅ„cu pliku rozszerzonych atrybutów %s: %s (%d)\n" #: .././restore/dirattr.c:825 #, c-format msgid "update of dirattr failed: %s\n" msgstr "uaktualnienie dirattr nie powiodÅ‚o siÄ™: %s\n" #: .././restore/dirattr.c:933 #, c-format msgid "write of dirattr buffer failed: %s\n" msgstr "zapis bufora dirattr nie powiódÅ‚ siÄ™: %s\n" #: .././restore/dirattr.c:937 #, c-format msgid "" "write of dirattr buffer failed: expected to write %ld, actually wrote %ld\n" msgstr "" "zapis bufora dirattr nie powiódÅ‚ siÄ™: oczekiwano zapisania %ld, zapisano " "%ld\n" #: .././restore/dirattr.c:1015 #, c-format msgid "read of dirattr failed: %s\n" msgstr "odczyt dirattr nie powiódÅ‚ siÄ™: %s\n" #: .././restore/dirattr.c:1092 #, c-format msgid "flush of dirattr failed: %s\n" msgstr "opróżnienie bufora dirattr nie powiodÅ‚o siÄ™: %s\n" #: .././restore/inomap.c:217 .././restore/tree.c:420 .././restore/tree.c:595 #, c-format msgid "could not open %s: %s\n" msgstr "nie udaÅ‚o siÄ™ otworzyć %s: %s\n" #: .././restore/inomap.c:377 #, c-format msgid "unable to map %s hdr: %s\n" msgstr "nie można odwzorować nagłówka %s: %s\n" #: .././restore/namreg.c:145 #, c-format msgid "could not find name registry file %s: %s\n" msgstr "nie udaÅ‚o siÄ™ odnaleźć pliku rejestru nazw %s: %s\n" #: .././restore/namreg.c:161 #, c-format msgid "could not create name registry file %s: %s\n" msgstr "nie udaÅ‚o siÄ™ utworzyć pliku rejestru nazw %s: %s\n" #: .././restore/namreg.c:274 .././restore/namreg.c:427 #, c-format msgid "lseek of namreg failed: %s\n" msgstr "lseek pliku namreg nie powiodÅ‚o siÄ™: %s\n" #: .././restore/namreg.c:347 #, c-format msgid "write of namreg buffer failed: %s\n" msgstr "zapis bufora namreg nie powiódÅ‚ siÄ™: %s\n" #: .././restore/namreg.c:351 #, c-format msgid "" "write of namreg buffer failed: expected to write %ld, actually wrote %ld\n" msgstr "" "zapis bufora namreg nie powiódÅ‚ siÄ™: oczekiwano zapisania %ld, zapisano %ld\n" #: .././restore/namreg.c:441 #, c-format msgid "read of namreg failed: %s (nread = %d)\n" msgstr "odczyt pliku namreg nie powiódÅ‚ siÄ™: %s (nread = %d)\n" #: .././restore/node.c:293 #, c-format msgid "" "not enough virtual memory for node abstraction: remaining-vsmz=%llu need=" "%llu\n" msgstr "" "za maÅ‚o pamiÄ™ci wirtualnej na abstrakcjÄ™ wÄ™złów: pozostaÅ‚e vsmz=%llu " "potrzeba=%llu\n" #: .././restore/node.c:305 #, c-format msgid "dump contains %llu inodes, restore can only handle %u\n" msgstr "" "zrzut zawiera za dużo i-wÄ™złów (%llu), restore może obsÅ‚użyć tylko %u\n" #: .././restore/node.c:347 .././restore/node.c:413 #, c-format msgid "unable to map node hdr of size %d: %s\n" msgstr "nie można odwzorować nagłówka wÄ™zÅ‚a rozmiaru %d: %s\n" #: .././restore/node.c:493 #, c-format msgid "unable to autogrow node segment %u: %s (%d)\n" msgstr "nie można automatycznie powiÄ™kszyć segmentu wÄ™zÅ‚a %u: %s (%d)\n" #: .././restore/node.c:508 #, c-format msgid "dump contains too many dirents, restore can only handle %llu\n" msgstr "" "zrzut zawiera zbyt dużo wpisów katalogów, restore może obsÅ‚użyć tylko %llu\n" #: .././restore/tree.c:395 #, c-format msgid "%s already exists: rm -rf prior to initating restore\n" msgstr "" "%s już istnieje: przed poczÄ…tkowym odtworzeniem należy wykonać rm -rf\n" #: .././restore/tree.c:511 #, c-format msgid "dump format version %u used truncated inode generation numbers\n" msgstr "wersja %u formatu zrzutu używaÅ‚a skróconych liczb generacji i-wÄ™złów\n" #: .././restore/tree.c:516 msgid "forcing use of truncated inode generation numbers\n" msgstr "wymuszenie użycia skróconych liczb generacji i-wÄ™złów\n" #: .././restore/tree.c:580 #, c-format msgid "unable to recreate %s: %s\n" msgstr "nie można ponownie utworzyć %s: %s\n" #: .././restore/tree.c:626 msgid "" "using truncated inode generation numbers for compatibility with previously " "applied restore\n" msgstr "" "użycie skróconych liczb generacji i-wÄ™złów dla kompatybilnoÅ›ci z uprzednio " "odtworzonym zrzutem\n" #: .././restore/tree.c:660 #, c-format msgid "encountered dump format %d after a restore of format %d or newer\n" msgstr "" "napotkano format zrzutu %d po odtworzeniu zrzutu w formacie %d lub nowszym\n" #: .././restore/tree.c:664 #, c-format msgid "" "to restore this series of dumps, use the -%c option on the first restore\n" msgstr "" "aby odtworzyć tÄ™ seriÄ™ zrzutów, należy użyć opcji -%c przy pierwszym " "odtwarzaniu\n" #: .././restore/tree.c:1294 msgid "noref debug" msgstr "diagnostyka noref" #: .././restore/tree.c:1326 .././restore/tree.c:1532 msgid "rmdir" msgstr "rmdir" #: .././restore/tree.c:1341 .././restore/tree.c:2647 #, c-format msgid "unable to rmdir %s: %s\n" msgstr "nie można wykonać rmdir %s: %s\n" #: .././restore/tree.c:1363 msgid "tmp dir rename src" msgstr "zmiany nazwy katalogu źródÅ‚owego" #: .././restore/tree.c:1373 msgid "tmp dir rename dst" msgstr "zmiany nazwy katalogu docelowego" #: .././restore/tree.c:1392 .././restore/tree.c:1704 #, c-format msgid "unable to rename dir %s to dir %s: %s\n" msgstr "nie można zmienić nazwy katalogu %s na %s: %s\n" #: .././restore/tree.c:1481 msgid "tmp nondir rename src" msgstr "zmiany nazwy nie-katalogu źródÅ‚owego" #: .././restore/tree.c:1491 msgid "tmp nondir rename dst" msgstr "nazwy nie-katalogu docelowego" #: .././restore/tree.c:1510 #, c-format msgid "unable to rename nondir %s to nondir %s: %s\n" msgstr "nie można zmienić nazwy nie-katalogu %s na %s: %s\n" #: .././restore/tree.c:1547 #, c-format msgid "unable to unlink nondir %s: %s\n" msgstr "nie można usunąć nie-katalogu %s: %s\n" #: .././restore/tree.c:1597 msgid "makedir" msgstr "makedir" #: .././restore/tree.c:1611 #, c-format msgid "mkdir %s failed: %s\n" msgstr "mkdir %s nie powiodÅ‚o siÄ™: %s\n" #: .././restore/tree.c:1678 .././restore/tree.c:1686 msgid "rename dir" msgstr "zmiany nazwy katalogu" #: .././restore/tree.c:1776 msgid "restore" msgstr "odtworzenia" #: .././restore/tree.c:1797 #, c-format msgid "cannot restore %s (ino %llu gen %u): pathname contains %s\n" msgstr "nie można odtworzyć %s (i-wÄ™zeÅ‚ %llu gen %u): Å›cieżka zawiera %s\n" #: .././restore/tree.c:1841 #, c-format msgid "unable to unlink current file prior to restore: %s: %s: discarding\n" msgstr "" "nie można usunąć bieżącego pliku przed odtworzeniem: %s: %s: porzucono\n" #: .././restore/tree.c:1939 #, c-format msgid "ino %llu salvaging file, placing in %s\n" msgstr "i-wÄ™zeÅ‚ %llu: ratowanie pliku, umieszczono w %s\n" #: .././restore/tree.c:1949 #, c-format msgid "ino %llu gen %u not referenced: placing in orphanage\n" msgstr "i-wÄ™zeÅ‚ %llu gen %u bez odwoÅ‚aÅ„: umieszczanie w sierociÅ„cu\n" #: .././restore/tree.c:1960 #, c-format msgid "node allocation failed when placing ino %llu in orphanage\n" msgstr "" "przydzielanie wÄ™zÅ‚a nie powiodÅ‚o siÄ™ podczas umieszczania i-wÄ™zÅ‚a %llu w " "sierociÅ„cu\n" #: .././restore/tree.c:1966 msgid "orphan" msgstr "osierocenia" #: .././restore/tree.c:2100 msgid "set dir extattr" msgstr "ustawiania extattr katalogu" #: .././restore/tree.c:2102 #, c-format msgid "tree_extattr_recurse: Could not convert node to path for %s\n" msgstr "" "tree:extattr_recurse: nie udaÅ‚o siÄ™ przeksztaÅ‚cić wÄ™zÅ‚a na Å›cieżkÄ™ dla %s\n" #: .././restore/tree.c:2294 msgid "rename to" msgstr "zmiany nazwy na" #: .././restore/tree.c:2314 msgid "rename from" msgstr "zmiany nazwy z" #: .././restore/tree.c:2332 #, c-format msgid "unable to rename nondir %s to %s: %s\n" msgstr "nie można zmienić nazwy nie-katalogu z %s na %s: %s\n" #: .././restore/tree.c:2353 msgid "link" msgstr "dowiÄ…zania" #: .././restore/tree.c:2357 #, c-format msgid "unable to use %s as a hard link source\n" msgstr "nie można użyć %s jako źródÅ‚a dowiÄ…zania zwykÅ‚ego\n" #: .././restore/tree.c:2414 msgid "unlink" msgstr "usuwania" #: .././restore/tree.c:2430 #, c-format msgid "unable to unlink %s: %s\n" msgstr "nie można usunąć %s: %s\n" #: .././restore/tree.c:2501 msgid "set dirattr" msgstr "ustawienia dirattr" #: .././restore/tree.c:2537 #, c-format msgid "open_by_handle of %s failed:%s\n" msgstr "open_by_handle %s nie powiodÅ‚o siÄ™: %s\n" #: .././restore/tree.c:2574 #, c-format msgid "could not set access and modification times of %s: %s\n" msgstr "nie udaÅ‚o siÄ™ ustawić czasów dostÄ™pu i modyfikacji %s: %s\n" #: .././restore/tree.c:2586 #, c-format msgid "chown (uid=%d, gid=%d) %s failed: %s\n" msgstr "chown (uid=%d, gid=%d) %s nie powiodÅ‚o siÄ™: %s\n" #: .././restore/tree.c:2596 #, c-format msgid "chmod %s failed: %s\n" msgstr "chmod %s nie powiodÅ‚o siÄ™: %s\n" #: .././restore/tree.c:2616 #, c-format msgid "" "attempt to set extended attributes (xflags 0x%x, extsize = 0x%x, projid = 0x" "%x)of %s failed: %s\n" msgstr "" "próba ustawienia rozszerzonych atrybutów (xflags 0x%x, extsize = 0x%x, " "projid = 0x%x) %s nie powiodÅ‚a siÄ™: %s\n" #: .././restore/tree.c:2643 #, c-format msgid "unable to rmdir %s: not empty\n" msgstr "nie można wykonać rmdir %s: katalog nie jest pusty\n" #: .././restore/tree.c:2699 msgid "subtree selection dialog" msgstr "dialog wyboru poddrzewa" #: .././restore/tree.c:2737 msgid "abort\n" msgstr "przerwano\n" #: .././restore/tree.c:2804 msgid "Unmark and quit\n" msgstr "UsuniÄ™cie zaznaczenia i zakoÅ„czenie\n" #: .././restore/tree.c:2988 .././restore/tree.c:4941 #, c-format msgid "%s is not a directory\n" msgstr "%s nie jest katalogiem\n" #: .././restore/tree.c:3180 msgid "the following commands are available:\n" msgstr "dostÄ™pne sÄ… nastÄ™pujÄ…ce polecenia:\n" #: .././restore/tree.c:3299 #, c-format msgid "parent of %s is not a directory\n" msgstr "rodzic %s nie jest katalogiem\n" #: .././restore/tree.c:3320 #, c-format msgid "%s above root\n" msgstr "%s powyżej katalogu głównego\n" #: .././restore/tree.c:3374 #, c-format msgid "%s not found\n" msgstr "nie znaleziono %s\n" #: .././restore/tree.c:3461 #, c-format msgid "failed to map in node (node handle: %u)\n" msgstr "nie udaÅ‚o siÄ™ odwzorować w węźle (uchwyt wÄ™zÅ‚a: %u)\n" #: .././restore/tree.c:3488 #, c-format msgid "unable %s ino %llu gen %u: relative pathname too long (partial %s)\n" msgstr "" "nie można wykonać %s, i-wÄ™zeÅ‚ %llu gen %u: Å›cieżka wzglÄ™dna zbyt dÅ‚uga " "(częściowa %s)\n" #: .././restore/tree.c:3645 msgid "attempt to disown child which has no parent!\n" msgstr "próba odpiÄ™cia potomka, który nie ma rodzica!\n" #: .././restore/tree.c:3653 msgid "attempt to disown child when parent has no children!\n" msgstr "próba odpiÄ™cia potomka, kiedy rodzic nie ma potomków!\n" #: .././restore/tree.c:4154 .././restore/tree.c:4200 #, c-format msgid "unable to mmap hash array into %s: %s\n" msgstr "nie można wykonać mmap dla tablicy haszujÄ…cej do %s: %s\n" #: .././restore/tree.c:4425 #, c-format msgid "nh 0x%x np 0x%x hash link not null\n" msgstr "nh 0x%x np 0x%x dowiÄ…zanie hasza nie jest nullem\n" #: .././restore/tree.c:4577 #, c-format msgid "node %x %s %llu %u parent NULL\n" msgstr "wÄ™zeÅ‚ %x %s %llu %u rodzic NULL\n" #: .././restore/tree.c:4585 #, c-format msgid "node %x %s %llu %u parent mismatch: nodepar %x par %x\n" msgstr "wÄ™zeÅ‚ %x %s %llu %u niezgodność rodzica: nodepar %x par %x\n" #: .././restore/win.c:272 msgid "all map windows in use. Check virtual memory limits\n" msgstr "" "wszystkie okna odwzorowaÅ„ w użyciu. ProszÄ™ sprawdzić limity pamiÄ™ci " "wirtualnej\n" #: .././restore/win.c:301 #, c-format msgid "win_map(): unable to map a node segment of size %d at %d: %s\n" msgstr "" "win_map(): nie udaÅ‚o siÄ™ odwzorować segmentu wÄ™zÅ‚a rozmiaru %d pod %d: %s\n" #: .././restore/win.c:312 msgid "win_map(): try to select a different win_t\n" msgstr "win_map(): próba wybrania innego win_t\n" xfsdump-3.1.6+nmu1/po/Makefile0000644000000000000000000000057212607344125013037 0ustar # # Copyright (c) 2001-2002 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = .. include $(TOPDIR)/include/builddefs POTHEAD = $(PKG_NAME).pot LINGUAS = de pl LSRCFILES = $(LINGUAS:%=%.po) LDIRT = $(POTHEAD) XGETTEXTFILES = $(LOCALIZED_FILES) default: $(POTHEAD) $(LINGUAS:%=%.mo) include $(BUILDRULES) install: default $(INSTALL_LINGUAS) install-dev install-lib: xfsdump-3.1.6+nmu1/po/de.po0000644000000000000000000035366212607344125012342 0ustar # Copyright (C) 2000-2002 Silicon Graphics, Inc. # This file is distributed under the same license as the xfsdump package. # Chris Leick , 2010. # msgid "" msgstr "" "Project-Id-Version: xfsdump 3.0.4\n" "Report-Msgid-Bugs-To: Nathan Scott nathans@debian.org\n" "POT-Creation-Date: 2010-01-14 13:42+1100\n" "PO-Revision-Date: 2012-08-28 10:58+0200\n" "Last-Translator: Chris Leick \n" "Language-Team: German \n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" #: .././common/cldmgr.c:90 #, c-format msgid "" "cannot create %s thread for stream %u: too many child threads (max allowed " "is %d)\n" msgstr "" "%s-Thread für Datenstrom %u kann nicht angelegt werden: Zu viele " "Kind-Threads (maximal sind %d erlaubt)\n" #: .././common/cldmgr.c:104 #, c-format msgid "sproc failed creating %s thread for stream %u: %s\n" msgstr "" "%s-Thread für Datenstrom %u kann nicht mit »sproc« angelegt werden: %s\n" #: .././common/content_common.c:65 .././restore/content.c:6806 msgid "change media dialog" msgstr "Medienwechseldialog" #: .././common/content_common.c:75 .././restore/content.c:6818 #, c-format msgid "please change media in drive %u\n" msgstr "Bitte wechseln Sie das Medium in Laufwerk %u\n" #: .././common/content_common.c:83 .././restore/content.c:6831 msgid "media change declined" msgstr "Medienwechsel abgelehnt" #: .././common/content_common.c:85 .././restore/content.c:6842 msgid "media changed" msgstr "Medium gewechselt" #: .././common/content_common.c:104 .././restore/content.c:6861 msgid "examining new media\n" msgstr "Neues Medium wird untersucht\n" #: .././common/content_common.c:106 .././restore/content.c:6863 msgid "media change aborted\n" msgstr "Medienwechsel abgebrochen\n" #: .././common/content_common.c:109 .././common/dlog.c:481 #: .././restore/tree.c:2667 .././restore/content.c:6899 #: .././restore/content.c:7032 msgid "keyboard interrupt\n" msgstr "Tastatur-Unterbrechung\n" #: .././common/content_common.c:117 .././common/global.c:351 #: .././common/main.c:2216 .././restore/tree.c:2684 .././restore/tree.c:2725 #: .././restore/content.c:6871 .././restore/content.c:6907 msgid "end dialog" msgstr "Schlussdialog" #: .././common/dlog.c:109 #, c-format msgid "could not fstat stdin (fd %d): %s (%d)\n" msgstr "fstat stdin (fd %d) kann nicht durchgeführt werden: %s (%d)\n" #: .././common/dlog.c:213 msgid " (default)" msgstr " (Vorgabe)" #: .././common/dlog.c:221 #, c-format msgid " (timeout in %u sec)" msgstr " (Zeitüberschreitung in %u Sek.)" #: .././common/dlog.c:253 #, c-format msgid "please enter a single digit response (1 to %d)" msgstr "" "Bitte geben Sie eine Antwort in Form einer einstelligen Zahl ein (1 bis %d)" #: .././common/dlog.c:261 #, c-format msgid "please enter a single digit between 1 and %d inclusive " msgstr "" "Bitte geben Sie eine einstellige Zahl zwischen 1 und einschließlich %d ein." #: .././common/dlog.c:309 #, c-format msgid " (timeout in %u sec)\n" msgstr " (Zeitüberschreitung in %u Sek.)\n" #: .././common/dlog.c:396 #, c-format msgid "(timeout in %d sec)" msgstr "(Zeitüberschreitung in %d Sek.)" #: .././common/dlog.c:477 msgid "timeout\n" msgstr "Zeitüberschreitung\n" #: .././common/dlog.c:486 msgid "hangup\n" msgstr "blockieren\n" #: .././common/dlog.c:490 msgid "terminate\n" msgstr "beenden\n" #: .././common/dlog.c:494 msgid "keyboard quit\n" msgstr "Tastatur-Beendigung\n" #: .././common/dlog.c:499 #, c-format msgid "unknown signal during dialog: %d\n" msgstr "unbekanntes Signal beim Dialog: %d\n" #: .././common/drive.c:110 #, c-format msgid "too many -%c arguments: maximum is %d when running in miniroot\n" msgstr "zu viele -%c-Argumente: Maximum beim Ausführen in Miniroot ist %d\n" #: .././common/drive.c:148 .././common/drive_minrmt.c:452 #: .././common/drive_minrmt.c:529 .././common/drive_minrmt.c:568 #: .././common/drive_scsitape.c:611 .././common/drive_scsitape.c:644 #: .././common/drive_scsitape.c:657 .././common/global.c:138 #: .././common/global.c:156 .././common/global.c:178 .././common/main.c:239 #: .././common/main.c:261 .././common/main.c:290 .././common/main.c:1220 #: .././common/media.c:118 .././dump/content.c:602 .././dump/content.c:621 #: .././dump/content.c:639 .././dump/content.c:671 .././dump/content.c:688 #: .././dump/content.c:1673 .././restore/content.c:930 #: .././restore/content.c:956 .././restore/content.c:1017 #: .././restore/content.c:1046 .././restore/content.c:1068 #: .././restore/content.c:1114 #, c-format msgid "-%c argument missing\n" msgstr "-%c-Argument fehlt\n" #: .././common/drive.c:183 msgid "cannot specify source files and stdout together\n" msgstr "Quelldateien und STDOUT können nicht zusammen angegeben werden\n" #: .././common/drive.c:186 msgid "cannot specify source files and stdin together\n" msgstr "Quelldateien und STDIN können nicht zusammen angegeben werden\n" #: .././common/drive.c:214 msgid "no destination file(s) specified\n" msgstr "keine Zieldatei(en) angegeben\n" #: .././common/drive.c:217 msgid "no source file(s) specified\n" msgstr "keine Quelldatei(en) angegeben\n" #: .././common/drive.c:252 #, c-format msgid "using %s strategy\n" msgstr "Strategie %s wird benutzt\n" #: .././common/drive_minrmt.c:474 #, c-format msgid "Minimal rmt cannot be used without specifying blocksize. Use -%c\n" msgstr "" "Minimal-Rmt kann nicht ohne Angabe der Blockgröße benutzt werden. Benutzen " "Sie -%c\n" #: .././common/drive_minrmt.c:538 .././common/drive_scsitape.c:620 #, c-format msgid "-%c argument must be between %u and %u: ignoring %u\n" msgstr "-%c-Argument muss zwischen %u und %u liegen: %u wird ignoriert\n" #: .././common/drive_minrmt.c:563 msgid "Overwrite command line option\n" msgstr "Befehlszeilenoption überschreiben\n" #: .././common/drive_minrmt.c:575 #, c-format msgid "-%c argument must be a positive number (MB): ignoring %u\n" msgstr "-%c-Argument muss eine positive Zahl (MB) sein: %u wird ignoriert\n" #: .././common/drive_minrmt.c:621 .././common/drive_scsitape.c:711 msgid "unable to allocate memory for I/O buffer ring\n" msgstr "Speicher für I/O-Puffer-Ring konnte nicht reserviert werden\n" #: .././common/drive_minrmt.c:625 .././common/drive_scsitape.c:715 msgid "not enough physical memory to pin down I/O buffer ring\n" msgstr "" "physischer Speicher reicht nicht aus, um I/O-Puffer-Ring festzusetzen\n" #: .././common/drive_minrmt.c:629 .././common/drive_scsitape.c:719 msgid "not allowed to pin down I/O buffer ring\n" msgstr "I/O-Puffer-Ring festzusetzen nicht erlaubt\n" #: .././common/drive_minrmt.c:1180 .././common/drive_scsitape.c:1293 #, c-format msgid "could not forward space %d tape blocks: rval == %d, errno == %d (%s)\n" msgstr "" "Bereich für %d Bandblöcke konnte nicht weitergeleitet werden: rval == %d, " "Fehlernummer == %d (%s)\n" #: .././common/drive_minrmt.c:1425 .././common/drive_scsitape.c:1540 msgid "unable to locate next mark in media file\n" msgstr "nächste Markierung in Mediendatei kann nicht gefunden werden\n" #: .././common/drive_minrmt.c:1449 #, c-format msgid "" "unexpected error attempting to read record: read returns %d, errno %s (%s)\n" msgstr "" "unerwarteter Fehler beim Versuch Datensatz zu lesen: Lesen gab %d zurück, " "Fehlernummer %s (%s)\n" #: .././common/drive_minrmt.c:1476 .././common/drive_scsitape.c:1620 #, c-format msgid "valid record %lld but no mark\n" msgstr "gültiger Datensatz %lld, aber keine Markierung\n" #: .././common/drive_minrmt.c:1502 .././common/drive_scsitape.c:1646 #, c-format msgid "resynchronized at record %lld offset %u\n" msgstr "neu synchronisiert bei Datensatz %lld, Versatz %u\n" #: .././common/drive_minrmt.c:1516 .././common/drive_scsitape.c:1659 #, c-format msgid "" "could not forward space one tape block beyond read error: rval == %d, errno " "== %d (%s)\n" msgstr "" "Bereich konnte nicht einen Bandblock hinter Lesefehler weitergeleitet " "werden: rval == %d, Fehlernummer == %d (%s)\n" #: .././common/drive_minrmt.c:2261 .././common/drive_scsitape.c:2444 msgid "advancing tape to next media file\n" msgstr "Band auf nächste Mediendatei vorspulen\n" #: .././common/drive_minrmt.c:2283 .././common/drive_scsitape.c:2471 msgid "FSF tape command failed\n" msgstr "FSF-Bandbefehl fehlgeschlagen\n" #: .././common/drive_minrmt.c:2507 .././common/drive_scsitape.c:2745 #, c-format msgid "drive %u " msgstr "Laufwerk %u" #: .././common/drive_minrmt.c:2591 .././common/drive_scsitape.c:2948 #, c-format msgid "could not read from drive: %s (%d)\n" msgstr "vom Laufwerk kann nicht gelesen werden: %s (%d)\n" #: .././common/drive_minrmt.c:2604 msgid "encountered EOD : assuming blank media\n" msgstr "EOD (Datenende) vorgefunden: Leeres Medium wird vermutet\n" #: .././common/drive_minrmt.c:2607 msgid "encountered EOD : end of data\n" msgstr "EOD vorgefunden: Datenende\n" #: .././common/drive_minrmt.c:2661 msgid "tape record checksum error\n" msgstr "Banddatensatz-Prüfsummenfehler\n" #: .././common/drive_minrmt.c:2777 .././common/drive_scsitape.c:3309 #, c-format msgid "" "recommended media file size of %llu Mb less than estimated file header size %" "llu Mb for %s\n" msgstr "" "empfohlene Mediendateigröße von %llu MB ist kleiner als geschätzte " "Datei-Header-Größe %llu MB für %s\n" #: .././common/drive_minrmt.c:2852 msgid "audio" msgstr "Audio" #: .././common/drive_minrmt.c:2898 .././common/drive_scsitape.c:3586 #: .././common/drive_scsitape.c:3941 msgid "tape is write protected\n" msgstr "Band ist schreibgeschützt\n" #: .././common/drive_minrmt.c:2910 .././common/drive_scsitape.c:3596 msgid "tape media error on write operation\n" msgstr "Bandmedienfehler bei Schreiboperation\n" #: .././common/drive_minrmt.c:2913 .././common/drive_scsitape.c:3599 msgid "no more data can be written to this tape\n" msgstr "auf dieses Band können keine Daten mehr geschrieben werden\n" #: .././common/drive_minrmt.c:2986 .././common/drive_scsitape.c:3679 #, c-format msgid "RMTOPEN( %s, %d ) returns %d: errno=%d (%s)\n" msgstr "RMTOPEN( %s, %d ) gibt %d zurück: Fehlernummer=%d (%s)\n" #: .././common/drive_minrmt.c:3000 .././common/drive_scsitape.c:3693 #, c-format msgid "RMTCLOSE( %d ) returns %d: errno=%d (%s)\n" msgstr "RMTCLOSE( %d ) gibt %d zurück: Fehlernummer=%d (%s)\n" #: .././common/drive_minrmt.c:3013 .././common/drive_scsitape.c:3706 #, c-format msgid "RMTIOCTL( %d, %d, 0x%x ) returns %d: errno=%d (%s)\n" msgstr "RMTIOCTL( %d, %d, 0x%x ) gibt %d zurück: Fehlernummer=%d (%s)\n" #: .././common/drive_minrmt.c:3028 .././common/drive_scsitape.c:3721 #, c-format msgid "RMTREAD( %d, 0x%x, %u ) returns %d: errno=%d (%s)\n" msgstr "RMTREAD( %d, 0x%x, %u ) gibt %d zurück: Fehlernummer=%d (%s)\n" #: .././common/drive_minrmt.c:3043 .././common/drive_scsitape.c:3736 #, c-format msgid "RMTWRITE( %d, 0x%x, %u ) returns %d: errno=%d (%s)\n" msgstr "RMTWRITE( %d, 0x%x, %u ) gibt %d zurück: Fehlernummer=%d (%s)\n" #: .././common/drive_minrmt.c:3065 .././common/drive_scsitape.c:3765 #, c-format msgid "attempt to access/open remote tape drive %s failed: %d (%s)\n" msgstr "" "Versuch (auf) fernes Bandlaufwerk %s zuzugreifen/zu öffnen fehlgeschlagen: " "%d (%s)\n" #: .././common/drive_minrmt.c:3102 .././common/drive_scsitape.c:3892 msgid "preparing drive\n" msgstr "Laufwerk wird vorbereitet\n" #: .././common/drive_minrmt.c:3189 .././common/drive_scsitape.c:4085 msgid "giving up attempt to determining tape record size\n" msgstr "Versuch, die Band-Datensatzgröße festzulegen, wird aufgegeben\n" #: .././common/drive_minrmt.c:3304 #, c-format msgid "unexpected tape error: errno %d nread %d blksz %d recsz %d \n" msgstr "unerwarteter Bandfehler: Fehlernummer %d nread %d blksz %d recsz %d \n" #: .././common/drive_minrmt.c:3327 .././common/drive_scsitape.c:4519 #, c-format msgid "media file header version (%d) invalid: advancing\n" msgstr "Mediendatei-Kopfzeilenversion (%d) ungültig: Es wird fortgefahren.\n" #: .././common/drive_minrmt.c:3338 .././common/drive_scsitape.c:4530 msgid "may be an EFS dump at BOT\n" msgstr "bei BOT (Massenübertragung) könnte eine EFS-Ausgabe sein\n" #: .././common/drive_minrmt.c:3343 msgid "This tape was erased earlier by xfsdump.\n" msgstr "Dieses Band wurde früher mit Xfsdump gelöscht.\n" #: .././common/drive_minrmt.c:3349 .././common/drive_scsitape.c:4533 msgid "bad media file header at BOT indicates foreign or corrupted tape\n" msgstr "" "falsche Mediendatei-Kopfzeilen bei BOT (Massenübertragung) deuten auf " "fremdes oder beschädigtes Band hin\n" #: .././common/drive_minrmt.c:3376 .././common/drive_scsitape.c:4575 #: .././common/drive_scsitape.c:4614 msgid "cannot determine tape block size after two tries\n" msgstr "Band-Blockgröße kann nach zwei Versuchen nicht festgelegt werden\n" #: .././common/drive_minrmt.c:3379 .././common/drive_scsitape.c:4585 #: .././common/drive_scsitape.c:4624 msgid "assuming media is corrupt or contains non-xfsdump data\n" msgstr "" "es wird vermutet, dass das Medium beschädigt ist oder keine Xfsdump-Daten " "enthält\n" #: .././common/drive_minrmt.c:3397 .././common/drive_scsitape.c:4603 #: .././common/drive_scsitape.c:4644 msgid "cannot determine tape block size\n" msgstr "Band-Blockgröße kann nicht festgelegt werden\n" #: .././common/drive_minrmt.c:3548 .././common/drive_scsitape.c:4828 #, c-format msgid "record %lld corrupt: bad record checksum\n" msgstr "Datensatz %lld beschädigt: Falsche Datensatz-Prüfsumme\n" #: .././common/drive_minrmt.c:3558 .././common/drive_scsitape.c:4838 #, c-format msgid "record %lld corrupt: bad magic number\n" msgstr "Datensatz %lld beschädigt: Falsche Magische Zahl\n" #: .././common/drive_minrmt.c:3566 .././common/drive_scsitape.c:4846 #, c-format msgid "record %lld corrupt: null dump id\n" msgstr "Datensatz %lld beschädigt: Ausgabe-ID Null\n" #: .././common/drive_minrmt.c:3574 .././common/drive_scsitape.c:4854 #, c-format msgid "record %lld corrupt: dump id mismatch\n" msgstr "Datensatz %lld beschädigt: Ausgabe-ID stimmt nicht überein\n" #: .././common/drive_minrmt.c:3585 .././common/drive_scsitape.c:4861 #, c-format msgid "record %lld corrupt: incorrect record size in header\n" msgstr "" "Datensatz %lld beschädigt: Datensatzgröße in Kopfzeilen nicht korrekt\n" #: .././common/drive_minrmt.c:3599 .././common/drive_scsitape.c:4868 #, c-format msgid "" "record %lld corrupt: record offset in header not a multiple of record size\n" msgstr "" "Datensatz %lld beschädigt: Datensatz-Versatz in Kopfzeilen kein Vielfaches " "der Datensatzgröße\n" #: .././common/drive_minrmt.c:3611 .././common/drive_scsitape.c:4880 #, c-format msgid "record %lld corrupt: incorrect record offset in header (0x%llx)\n" msgstr "" "Datensatz %lld beschädigt: Datensatz-Versatz in Kopfzeilen (0x%llx) nicht " "korrekt\n" #: .././common/drive_minrmt.c:3622 .././common/drive_scsitape.c:4891 #, c-format msgid "record %lld corrupt: incorrect record padding offset in header\n" msgstr "" "Datensatz %lld beschädigt: Datensatz-Füllungsversatz in Kopfzeilen nicht " "korrekt\n" #: .././common/drive_minrmt.c:3659 msgid "read_record encountered EOD : assuming blank media\n" msgstr "read_record fand EOD (Datenende) vor: Medium vermutlich leer\n" #: .././common/drive_minrmt.c:3662 msgid "read_record encountered EOD : end of data\n" msgstr "read_record fand EOD vor: Datenende\n" #: .././common/drive_minrmt.c:3677 msgid "unexpected EIO error attempting to read record\n" msgstr "unerwarteter EIO-Fehler beim Versuch den Datensatz zu lesen\n" #: .././common/drive_minrmt.c:3700 .././common/drive_scsitape.c:4980 #, c-format msgid "" "unexpected error attempting to read record %lld: read returns %d, errno %d (%" "s)\n" msgstr "" "unerwarteter Fehler beim Versuch den Datensatz %lld zu lesen: Lesen gab %d " "zurück, Fehlernummer %d (%s)\n" #: .././common/drive_minrmt.c:3823 msgid "slave" msgstr "Slave" #: .././common/drive_minrmt.c:3891 .././common/drive_minrmt.c:3899 msgid "KB" msgstr "KB" #: .././common/drive_minrmt.c:3896 msgid "MB" msgstr "MB" #: .././common/drive_minrmt.c:3903 .././common/drive_scsitape.c:5187 #, c-format msgid "" "I/O metrics: %u by %s%s %sring; %lld/%lld (%.0lf%%) records streamed; %.0lfB/" "s\n" msgstr "" "I/O-Metrik: %u mit %s%s %sring; %lld/%lld (%.0lf%%) Datensätze übertragen; " "%.0lfB/s\n" #: .././common/drive_minrmt.c:3910 .././common/drive_scsitape.c:5194 msgid "pinned " msgstr "aufgesteckt" #: .././common/drive_scsitape.c:665 #, c-format msgid "-%c argument must be a positive number (Mb): ignoring %u\n" msgstr "-%c-Argument muss eine positive Zahl (MB) sein: %u wird ignoriert\n" #: .././common/drive_scsitape.c:1593 #, c-format msgid "" "unexpected error attempting to read record: read returns %d, errno %d (%s)\n" msgstr "" "unerwarteter Fehler beim Versuch den Datensatz zu lesen: Lesen gab %d " "zurück, Fehlernummer %d (%s)\n" #: .././common/drive_scsitape.c:2885 msgid "file mark missing from tape (hit EOD)\n" msgstr "Dateimarkierung vom Band fehlt (drücken Sie EOD [Datenende])\n" #: .././common/drive_scsitape.c:2888 msgid "writing file mark at EOD\n" msgstr "Dateimarkierung bei EOD (Datenende) wird geschrieben\n" #: .././common/drive_scsitape.c:2892 #, c-format msgid "unable to write file mark at eod: %s (%d)\n" msgstr "" "Dateimarkierung bei EOD (Datenende) kann nicht geschrieben werden: %s (%d)\n" #: .././common/drive_scsitape.c:2909 msgid "file mark missing from tape\n" msgstr "Dateimarkierung vom Band fehlt\n" #: .././common/drive_scsitape.c:2958 msgid "unexpectedly encountered EOD at BOT: assuming corrupted media\n" msgstr "" "unerwartetes EOD (Datenende) bei BOT (Massenübertragung) vorgefunden:\n" "Medium vermutlich beschädigt\n" #: .././common/drive_scsitape.c:3008 msgid "unexpectedly encountered a file mark: assuming corrupted media\n" msgstr "" "eine unerwartete Dateimarkierung vorgefunden: Medium vermutlich beschädigt\n" #: .././common/drive_scsitape.c:3214 #, c-format msgid "unable to set block size to %d\n" msgstr "Blockgröße kann nicht auf %d gesetzt werden\n" #: .././common/drive_scsitape.c:3772 #, c-format msgid "attempt to access/open device %s failed: %d (%s)\n" msgstr "" "Versuch, (auf) Gerät %s zuzugreifen/zu öffnen, fehlgeschlagen: %d (%s)\n" #: .././common/drive_scsitape.c:3801 #, c-format msgid "attempt to get status of remote tape drive %s failed: %d (%s)\n" msgstr "" "Versuch, den Status des fernen Bandlaufwerks %s abzufragen, fehlgeschlagen: " "%d (%s)\n" #: .././common/drive_scsitape.c:3808 #, c-format msgid "attempt to get status of tape drive %s failed: %d (%s)\n" msgstr "" "Versuch, den Status des Bandlaufwerks %s abzufragen, fehlgeschlagen: %d " "(%s)\n" #: .././common/drive_scsitape.c:3976 msgid "giving up waiting for drive to indicate online\n" msgstr "" "Warten auf Laufwerk, um festzustellen ob es online ist, wird aufgegeben\n" #: .././common/drive_scsitape.c:3984 #, c-format msgid "tape drive %s is not ready (0x%x): retrying ...\n" msgstr "Bandlaufwerk %s ist nicht bereit (0x%x): neuer Versuch ...\n" #: .././common/drive_scsitape.c:4006 msgid "" "use of QIC drives via variable blocksize device nodes is not supported\n" msgstr "" "Benutzung von QIC-Laufwerken über Geräteknoten variabler Blockgröße wird " "nicht unterstützt\n" #: .././common/drive_scsitape.c:4144 .././common/drive_scsitape.c:4170 msgid "unable to backspace/rewind media\n" msgstr "Medium kann nicht zurückgesetzt/-gespult werden\n" #: .././common/drive_scsitape.c:4469 #, c-format msgid "" "unexpected tape error: errno %d nread %d blksz %d recsz %d isvar %d wasatbot " "%d eod %d fmk %d eot %d onl %d wprot %d ew %d \n" msgstr "" "unerwarteter Bandfehler: Fehlernummer %d nread %d blksz %d recsz %d " "isvar %d wasatbot %d eod %d fmk %d eot %d onl %d wprot %d ew %d \n" #: .././common/drive_scsitape.c:4500 #, c-format msgid "likely problem is that the block size, %d, is too large for Linux\n" msgstr "" "wahrscheinliches Problem ist die Blockgröße, %d ist für Linux zu groß\n" #: .././common/drive_scsitape.c:4504 msgid "" "either try using a smaller block size with the -b option, or increase " "max_sg_segs for the scsi tape driver\n" msgstr "" "versuchen Sie entweder eine kleinere Blockgröße mit der Option -b oder " "erhöhen Sie »max_sg_segs« für den SCSI-Bandtreiber\n" #: .././common/drive_scsitape.c:4579 .././common/drive_scsitape.c:4618 msgid "will rewind and try again\n" msgstr "wird zurückgespult und erneut versucht\n" #: .././common/drive_scsitape.c:4800 msgid "unable to backspace tape: assuming media error\n" msgstr "" "Band kann nicht zurückgesetzt werden: Es wird ein Medienfehler vermutet\n" #: .././common/drive_simple.c:278 .././common/drive_simple.c:363 #: .././dump/content.c:1393 #, c-format msgid "unable to open %s: %s\n" msgstr "%s kann nicht geöffnet werden: %s\n" #: .././common/drive_simple.c:292 .././common/drive_simple.c:333 #, c-format msgid "stat of %s failed: %s\n" msgstr "»stat« von %s fehlgeschlagen: %s\n" #: .././common/drive_simple.c:322 #, c-format msgid "cannot dump to %s file type %x\n" msgstr "Ausgabe in Datei %s vom Typ %x kann nicht erstellt werden\n" #: .././common/drive_simple.c:352 #, c-format msgid "cannot restore from %s file type %x\n" msgstr "aus Datei %s Typ %x kann nicht wiederhergestellt werden\n" #: .././common/drive_simple.c:511 .././common/drive_simple.c:959 msgid "media file header checksum error\n" msgstr "Prüfsummenfehler von Mediendateikopfzeilen\n" #: .././common/drive_simple.c:529 #, c-format msgid "media file header magic number mismatch: %s, %s\n" msgstr "" "Magische Zahl von Mediendateikopfzeilen stimmt nicht überein: %s, %s\n" #: .././common/drive_simple.c:539 #, c-format msgid "unrecognized media file header version (%d)\n" msgstr "Dateikopfzeilenversion (%d) nicht erkannt\n" #: .././common/drive_simple.c:548 #, c-format msgid "unrecognized drive strategy ID (media says %d, expected %d)\n" msgstr "" "Laufwerks-Strategie-ID nicht erkannt (laut Medium %d, erwartet wurde %d)\n" #: .././common/drive_simple.c:909 #, c-format msgid "attempt to truncate %s failed: %d (%s)\n" msgstr "Versuch, %s zu kürzen, fehlgeschlagen: %d (%s)\n" #: .././common/drive_simple.c:1071 #, c-format msgid "could not save first mark: %d (%s)\n" msgstr "erste Markierung kann nicht gesichert werden: %d (%s)\n" #: .././common/drive_simple.c:1275 .././common/drive_simple.c:1369 #, c-format msgid "write to %s failed: %d (%s)\n" msgstr "Schreiben auf %s fehlgeschlagen: %d (%s)\n" #: .././common/drive_simple.c:1423 #, c-format msgid "could not rewind %s: %s\n" msgstr "%s kann nicht zurückgespult werden: %s\n" #: .././common/drive_simple.c:1459 #, c-format msgid "could not rewind %s in prep for erase: %s\n" msgstr "%s kann als Vorbereitung zum Löschen nicht zurückgespult werden: %s\n" #: .././common/drive_simple.c:1470 #, c-format msgid "could not erase %s: %s (%d)\n" msgstr "%s kann nicht gelöscht werden: %s (%d)\n" #: .././common/fs.c:170 #, c-format msgid "unable to determine uuid of fs mounted at %s: %s\n" msgstr "" "UUID des bei %s eingehängten Dateisystems kann nicht bestimmt werden:%s\n" #: .././common/fs.c:250 #, c-format msgid "Can't open %s for mount information\n" msgstr "" "%s kann zur Ermittlung der Einhängeinformationen nicht geöffnet werden\n" #: .././common/global.c:108 #, c-format msgid "unable to determine hostname: %s\n" msgstr "Rechnername kann nicht bestimmt werden: %s\n" #: .././common/global.c:114 msgid "hostname length is zero\n" msgstr "Länge des Rechnernamens ist null\n" #: .././common/global.c:128 .././common/media.c:108 #: .././restore/content.c:1007 #, c-format msgid "too many -%c arguments: \"-%c %s\" already given\n" msgstr "zu viele -%c-Argumente: »-%c %s« bereits angegeben\n" #: .././common/global.c:149 .././restore/content.c:1039 #, c-format msgid "too many -%c arguments\n" msgstr "zu viele -%c-Argumente\n" #: .././common/global.c:164 .././restore/content.c:1053 #, c-format msgid "-%c argument not a valid uuid\n" msgstr "-%c-Argument ist keine gültige UUID\n" #: .././common/global.c:186 #, c-format msgid "unable to stat %s: %s\n" msgstr "Abfragen von %s mit »stat« nicht möglich: %s\n" #: .././common/global.c:211 msgid "no session label specified\n" msgstr "Keine Sitzungskennung angegeben\n" #: .././common/global.c:302 msgid "please enter label for this dump session" msgstr "bitte geben Sie eine Kennung für diese Ausgabesitzung ein" #: .././common/global.c:320 msgid "dump label dialog" msgstr "Ausgabesitzungsdialog" #: .././common/global.c:339 msgid "session label entered: \"" msgstr "eingegebene Sitzungskennung: \"" #: .././common/global.c:343 msgid "session label left blank\n" msgstr "Sitzungskennung leer gelassen\n" #: .././common/hsmapi.c:863 #, c-format msgid "error removing temp DMF attr on %s: %s\n" msgstr "Fehler beim Entfernen des temporären »DMF attr« auf %s: %s\n" #: .././common/main.c:250 .././common/main.c:272 #, c-format msgid "-%c argument (%s) invalid\n" msgstr "-%c-Argument (%s) ungültig\n" #: .././common/main.c:315 #, c-format msgid "" "specified minimum stack size is larger than maximum: min is 0x%llx, max is " "0x%llx\n" msgstr "" "Angegebene minimale Stack-Größe ist größer als das Maximun: Minimum ist " "0x%llx, Maximum ist 0x%llx\n" #: .././common/main.c:418 #, c-format msgid "unable to determine current directory: %s\n" msgstr "aktuelles Verzeichnis kann nicht bestimmt werden: %s\n" #: .././common/main.c:428 msgid "both /var/lib/xfsdump and /var/xfsdump exist - fatal\n" msgstr "sowohl /var/lib/xfsdump als auch /var/xfsdump existieren - fatal\n" #: .././common/main.c:436 #, c-format msgid "version %s (dump format %d.%d)\n" msgstr "Version %s (Ausgabeformat %d.%d)\n" #: .././common/main.c:461 msgid "effective user ID must be root\n" msgstr "effektive Benutzer-ID muss »root« sein\n" #: .././common/main.c:512 #, c-format msgid "version %s (dump format %d.%d)" msgstr "Version %s (Ausgabeformat %d.%d)" #: .././common/main.c:518 msgid " - Running single-threaded\n" msgstr " - In Einzel-Threads ausführen\n" #: .././common/main.c:522 #, c-format msgid " - type %s for status and control\n" msgstr " - geben Sie für Status und Steuerung %s ein\n" #: .././common/main.c:722 #, c-format msgid "child (pid %d) faulted: signal number %d (%s)\n" msgstr "Kind (PID %d) fehlerhaft: Signalnummer %d (%s)\n" #: .././common/main.c:747 msgid "session interrupt timeout\n" msgstr "Sitzungsunterbrechungs-Zeitüberschreitung\n" #: .././common/main.c:825 msgid "session interrupt in progress: please wait\n" msgstr "Sitzung wird unterbrochen: Bitte warten\n" #: .././common/main.c:840 #, c-format msgid "initiating session interrupt (timeout in %d sec)\n" msgstr "Sitzungsunterbrechung wird initiiert (Zeitüberschreitung in %d Sek.)\n" #: .././common/main.c:967 #, c-format msgid "%s: usage: %s " msgstr "%s: Aufruf: %s " #: .././common/main.c:971 msgid "(dump DMF dualstate files as offline)" msgstr "(Ausgabe von DMF-Dualstate-Dateien offline)" #: .././common/main.c:972 .././common/main.c:1027 msgid "" msgstr "" #: .././common/main.c:973 .././common/main.c:1028 msgid " " msgstr " " #: .././common/main.c:974 msgid " " msgstr " " #: .././common/main.c:975 msgid "(allow files to be excluded)" msgstr "(erlaubt das Ausschließen von Dateien)" #: .././common/main.c:976 msgid " ..." msgstr " ..." #: .././common/main.c:977 .././common/main.c:1031 msgid "(help)" msgstr "(Hilfe)" #: .././common/main.c:978 msgid "" msgstr "" #: .././common/main.c:979 .././common/main.c:1033 msgid "(force usage of minimal rmt)" msgstr "(Benutzung von minimalen Rmt erzwingen)" #: .././common/main.c:980 msgid "(overwrite tape)" msgstr "(Band überschreiben)" #: .././common/main.c:981 .././common/main.c:1036 msgid "" msgstr "" #: .././common/main.c:982 .././common/main.c:1037 msgid "" msgstr "" #: .././common/main.c:983 .././common/main.c:1039 msgid " ..." msgstr " ..." #: .././common/main.c:984 msgid " (use file mtime for dump time" msgstr " (»mtime« der Datei als Ausgabezeit benutzen" #: .././common/main.c:985 .././common/main.c:1041 msgid "" msgstr "" #: .././common/main.c:986 msgid "" msgstr "" #: .././common/main.c:987 msgid "(don't dump extended file attributes)" msgstr "(keine Ausgabe erweiterter Dateiattribute)" #: .././common/main.c:989 msgid "" msgstr "" #: .././common/main.c:992 msgid "(generate tape record checksums)" msgstr "(Prüfsumme der Banddatensätze generieren)" #: .././common/main.c:994 msgid "(pre-erase media)" msgstr "(vorher gelöschtes Medium)" #: .././common/main.c:995 .././common/main.c:1050 msgid "(don't prompt)" msgstr "(nicht auffordern)" #: .././common/main.c:997 msgid "" msgstr "" #: .././common/main.c:998 msgid "" msgstr "" #: .././common/main.c:1000 .././common/main.c:1051 msgid "(display dump inventory)" msgstr "(Ausgabebestand anzeigen)" #: .././common/main.c:1001 .././common/main.c:1052 msgid "(inhibit inventory update)" msgstr "(Aktualisieren des Bestands verhindern)" #: .././common/main.c:1002 .././common/main.c:1053 msgid "" msgstr "" #: .././common/main.c:1003 msgid " ..." msgstr " ..." #: .././common/main.c:1005 .././common/main.c:1055 msgid "(timestamp messages)" msgstr "(Zeitstempel-Nachrichten)" #: .././common/main.c:1007 .././common/main.c:1057 msgid "" msgstr "" #: .././common/main.c:1009 .././common/main.c:1059 msgid "(pin down I/O buffers)" msgstr "(I/O-Puffer festsetzen)" #: .././common/main.c:1011 .././common/main.c:1064 msgid "(resume)" msgstr "(fortsetzen)" #: .././common/main.c:1012 .././common/main.c:1066 msgid "(don't timeout dialogs)" msgstr "(keine Zeitüberschreitung für Dialoge)" #: .././common/main.c:1014 .././common/main.c:1068 msgid "(unload media when change needed)" msgstr "(Medium entladen, falls Änderung erforderlich)" #: .././common/main.c:1015 .././common/main.c:1069 msgid "(show subsystem in messages)" msgstr "(Untersystem in Nachrichten anzeigen)" #: .././common/main.c:1016 .././common/main.c:1070 msgid "(show verbosity in messages)" msgstr "(Detailgrad in Nachrichten anzeigen)" #: .././common/main.c:1018 .././common/main.c:1073 msgid "" msgstr "" #: .././common/main.c:1020 .././common/main.c:1075 msgid "(miniroot restrictions)" msgstr "(Miniroot-Einschränkungen)" #: .././common/main.c:1022 msgid "- (stdout)" msgstr "- (STDOUT)" #: .././common/main.c:1023 msgid "" msgstr "" #: .././common/main.c:1026 msgid " ..." msgstr " ..." #: .././common/main.c:1029 msgid "(don't overwrite existing files)" msgstr "(existierende Dateien nicht überschreiben)" #: .././common/main.c:1030 msgid " ..." msgstr " ..." #: .././common/main.c:1032 msgid "(interactive)" msgstr "(interaktiv)" #: .././common/main.c:1034 msgid " (restore only if newer than)" msgstr " (nur wiederherstellen, wenn neuer)" #: .././common/main.c:1035 msgid "(restore owner/group even if not root)" msgstr "(Besitzer/Gruppe auch dann herstellen, wenn nicht »root«)" #: .././common/main.c:1038 msgid "(cumulative restore)" msgstr "(kumulatives Wiederherstellen)" #: .././common/main.c:1040 msgid "(contents only)" msgstr "(nur Inhalte)" #: .././common/main.c:1042 msgid "(use small tree window)" msgstr "(kleines Fenster mit Baumansicht benutzen)" #: .././common/main.c:1043 msgid "(don't restore extended file attributes)" msgstr "(erweiterte Dateiattribute nicht wiederherstellen)" #: .././common/main.c:1044 msgid "(restore root dir owner/permissions)" msgstr "(Besitzer/Rechte des Wurzelverzeichnisses wiederherstellen)" #: .././common/main.c:1045 msgid "(restore DMAPI event settings)" msgstr "(DMAPI-Ereigniseinstellungen wiederherstellen)" #: .././common/main.c:1047 msgid "(check tape record checksums)" msgstr "(Prüfsummen der Banddatensätze prüfen)" #: .././common/main.c:1049 msgid "(don't overwrite if changed)" msgstr "(nicht überschreiben, wenn geändert)" #: .././common/main.c:1062 msgid "(force interrupted session completion)" msgstr "(Vervollständigung der unterbrochenen Sitzung erzwingen)" #: .././common/main.c:1065 msgid "" msgstr "" #: .././common/main.c:1072 msgid " ..." msgstr " ..." #: .././common/main.c:1077 msgid "- (stdin)" msgstr "- (STDIN)" #: .././common/main.c:1078 msgid "" msgstr "" #: .././common/main.c:1227 #, c-format msgid "-%c allowed only once\n" msgstr "-%c nur einmal erlaubt\n" #: .././common/main.c:1248 #, c-format msgid "cannot open option file %s: %s (%d)\n" msgstr "Optionsdatei %s kann nicht geöffnet werden: %s (%d)\n" #: .././common/main.c:1260 #, c-format msgid "cannot stat option file %s: %s (%d)\n" msgstr "Optionsdatei %s kann nicht mit »stat« abgefragt werden: %s (%d)\n" #: .././common/main.c:1272 #, c-format msgid "given option file %s is not ordinary file\n" msgstr "angegebene Optionsdatei %s ist keine normale Datei\n" #: .././common/main.c:1313 #, c-format msgid "read of option file %s failed: %s (%d)\n" msgstr "Lesen der Optionsdatei %s fehlgeschlagen: %s (%d)\n" #: .././common/main.c:1526 #, c-format msgid "received signal %d (%s): cleanup and exit\n" msgstr "Signal %d erhalten (%s): Es wird aufgeräumt und beendet\n" #: .././common/main.c:1716 msgid "please enter seconds between progress reports, or 0 to disable" msgstr "" "bitte geben Sie die Zeit in Sekunden zwischen Fortschrittsberichten ein " "oder 0, um sie auszuschalten." #: .././common/main.c:1719 msgid "please enter seconds between progress reports" msgstr "" "bitte geben Sie die Zeit in Sekunden zwischen Fortschrittsberichten ein" #: .././common/main.c:1773 msgid "status and control dialog" msgstr "Status- und Steuerungsdialog" #: .././common/main.c:1785 msgid "" "\n" "session interrupt in progress\n" msgstr "" "\n" "Sitzung wird gerade unterbrochen\n" #: .././common/main.c:1794 msgid "please select one of the following operations\n" msgstr "bitte wählen Sie eine der folgenden Operationen\n" #: .././common/main.c:1800 .././common/main.c:1844 msgid "interrupt this session" msgstr "diese Sitzung unterbrechen" #: .././common/main.c:1806 msgid "change verbosity" msgstr "Detailgrad ändern" #: .././common/main.c:1808 msgid "display metrics" msgstr "Maße anzeigen" #: .././common/main.c:1811 msgid "confirm media change" msgstr "Medienwechsel bestätigen" #: .././common/main.c:1816 msgid "other controls" msgstr "andere Steuerungen" #: .././common/main.c:1818 .././common/main.c:1846 .././common/main.c:2000 #: .././common/main.c:2037 .././common/main.c:2101 .././restore/content.c:2785 #: .././restore/content.c:2825 msgid "continue" msgstr "fortfahren" #: .././common/main.c:1840 msgid "please confirm\n" msgstr "bitte bestätigen\n" #: .././common/main.c:1863 .././common/main.c:2054 .././common/main.c:2211 #: .././restore/content.c:2840 .././restore/content.c:2843 msgid "continuing\n" msgstr "weiter\n" #: .././common/main.c:1865 msgid "interrupt request accepted\n" msgstr "Unterbrechungsanfrage akzeptiert\n" #: .././common/main.c:1876 msgid "please select one of the following subsystems\n" msgstr "bitte wählen Sie eines der folgenden Untersysteme\n" #: .././common/main.c:1886 msgid "all of the above" msgstr "alle obigen" #: .././common/main.c:1888 .././common/main.c:1928 msgid "no change" msgstr "keine Änderung" #: .././common/main.c:1905 .././common/main.c:1959 .././common/main.c:2140 #: .././common/main.c:2147 .././common/main.c:2178 .././common/main.c:2183 msgid "no change\n" msgstr "keine Änderung\n" #: .././common/main.c:1908 msgid "" "all subsystems selected\n" "\n" msgstr "" "alle Untersysteme ausgewählt\n" "\n" #: .././common/main.c:1921 msgid "silent" msgstr "still" #: .././common/main.c:1922 msgid "verbose" msgstr "detailliert" #: .././common/main.c:1923 msgid "trace" msgstr "Nachverfolgung" #: .././common/main.c:1924 msgid "debug" msgstr "Fehlersuche" #: .././common/main.c:1925 msgid "nitty" msgstr "verrückt" #: .././common/main.c:1926 msgid "nitty + 1" msgstr "total verrückt" #: .././common/main.c:1938 msgid " (current)" msgstr "(aktuell)" #: .././common/main.c:1976 msgid "level changed\n" msgstr "Stufe geändert\n" #: .././common/main.c:1987 msgid "please select one of the following metrics\n" msgstr "bitte wählen Sie eines der folgenden Maße\n" #: .././common/main.c:1992 msgid "I/O" msgstr "I/O" #: .././common/main.c:1995 msgid "media inventory status" msgstr "Medien-Bestandsstatus" #: .././common/main.c:1997 msgid "needed media objects" msgstr "benötigte Medienobjekte" #: .././common/main.c:2071 msgid "please select one of the following controls\n" msgstr "bitte wählen Sie eine der folgenden Steuerungen aus\n" #: .././common/main.c:2077 msgid "change interval of or disable progress reports" msgstr "Intervall ändern oder Fortschrittsberichte ausschalten" #: .././common/main.c:2080 msgid "enable progress reports" msgstr "Fortschrittsberichte einschalten" #: .././common/main.c:2084 msgid "hide log message levels" msgstr "Protokollnachrichtenstufen verbergen" #: .././common/main.c:2086 msgid "show log message levels" msgstr "Protokollnachrichtenstufen anzeigen" #: .././common/main.c:2090 msgid "hide log message subsystems" msgstr "Protokollnachrichtenuntersysteme verbergen" #: .././common/main.c:2092 msgid "show log message subsystems" msgstr "Protokollnachrichtenuntersysteme anzeigen" #: .././common/main.c:2096 msgid "hide log message timestamps" msgstr "Protokollnachrichtenzeitstempel verbergen" #: .././common/main.c:2098 msgid "show log message timestamps" msgstr "Protokollnachrichtenzeitstempel anzeigen" #: .././common/main.c:2149 msgid "changing progress report interval to " msgstr "Intervall der Fortschrittsberichte wird geändert in " #: .././common/main.c:2151 #, c-format msgid "%d seconds\n" msgstr "%d Sekunden\n" #: .././common/main.c:2162 msgid "enabling progress reports at " msgstr "Fortschrittsberichte werden eingeschaltet bei " #: .././common/main.c:2164 #, c-format msgid "%d second intervals\n" msgstr "%d Sekundenintervallen\n" #: .././common/main.c:2176 msgid "disabling progress reports\n" msgstr "Fortschrittsberichte werden ausgeschaltet\n" #: .././common/main.c:2188 msgid "showing log message levels\n" msgstr "Protokollnachrichtenstufen werden angezeigt\n" #: .././common/main.c:2190 msgid "hiding log message levels\n" msgstr "Protokollnachrichtenstufen werden verborgen\n" #: .././common/main.c:2195 msgid "showing log message subsystems\n" msgstr "Protokollnachrichtenuntersysteme werden angezeigt\n" #: .././common/main.c:2197 msgid "hiding log message subsystems\n" msgstr "Protokollnachrichtenuntersysteme werden verborgen\n" #: .././common/main.c:2202 msgid "showing log message timestamps\n" msgstr "Protokollnachrichtenzeitstempel werden angezeigt\n" #: .././common/main.c:2204 msgid "hiding log message timestamps\n" msgstr "Protokollnachrichtenzeitstempel werden verborgen\n" #: .././common/main.c:2340 #, c-format msgid "unable to raise stack size hard limit from 0x%llx to 0x%llx\n" msgstr "" "harte Beschränkung der Stack-Größe kann nicht von 0x%llx auf 0x%llx erhöht " "werden\n" #: .././common/main.c:2367 #, c-format msgid "unable to raise stack size soft limit from 0x%llx to 0x%llx\n" msgstr "" "weiche Beschränkung der Stack-Größe kann nicht von 0x%llx auf 0x%llx erhöht " "werden\n" #: .././common/main.c:2395 #, c-format msgid "unable to lower stack size soft limit from 0x%llx to 0x%llx\n" msgstr "" "weiche Beschränkung der Stack-Größe kann nicht von 0x%llx auf 0x%llx " "verringert werden\n" #: .././common/media.c:180 msgid "no media strategy available for selected dump destination(s)\n" msgstr "" "für die/den ausgewählte(n) Ausgabebestimmungsort(e) ist keine " "Medienstrategie verfügbar\n" #: .././common/media.c:184 msgid "no media strategy available for selected restore source(s)\n" msgstr "" "für die/den ausgewählte(n) Wiederherstellungsquelle(n) ist keine " "Medienstrategie verfügbar\n" #: .././common/mlog.c:190 #, c-format msgid "%s: -%c argument missing\n" msgstr "%s: -%c-Argument fehlt\n" #: .././common/mlog.c:206 .././common/mlog.c:248 #, c-format msgid "%s: -%c argument invalid\n" msgstr "%s: -%c-Argument ungültig\n" #: .././common/mlog.c:218 #, c-format msgid "%s: -%c subsystem subargument %s requires a verbosity value\n" msgstr "" "%s: -%c-Untersystem-Unterargument %s benötigt einen Detailgrad\n" #: .././common/mlog.c:234 #, c-format msgid "%s: -%c argument does not require a value\n" msgstr "%s: -%c-Argument benötigt keinen Wert\n" #: .././common/mlog.c:424 #, c-format msgid "%s%s%s%s: drive %d: " msgstr "%s%s%s%s: Laufwerk %d: " #: .././common/mlog.c:725 #, c-format msgid "%s: %s Summary:\n" msgstr "%s: %s Zusammenfassung:\n" #: .././common/mlog.c:751 #, c-format msgid "%s: stream %d (pid %d) %s %s (%s)\n" msgstr "%s: Datenstrom %d (PID %d) %s %s (%s)\n" #: .././common/namreg.c:101 .././restore/inomap.c:217 .././restore/tree.c:405 #: .././restore/tree.c:567 #, c-format msgid "could not open %s: %s\n" msgstr "%s kann nicht geöffnet werden: %s\n" #: .././common/namreg.c:131 .././common/namreg.c:202 .././restore/namreg.c:279 #: .././restore/namreg.c:425 #, c-format msgid "lseek of namreg failed: %s\n" msgstr "»lseek« von »namreg« fehlgeschlagen: %s\n" #: .././common/namreg.c:151 .././common/namreg.c:162 #, c-format msgid "write of namreg failed: %s\n" msgstr "Schreiben von »namreg« fehlgeschlagen: %s\n" #: .././common/namreg.c:213 .././restore/namreg.c:438 #, c-format msgid "read of namreg failed: %s (nread = %d)\n" msgstr "Lesen von »namreg« fehlgeschlagen: %s (nread = %d)\n" #: .././common/namreg.c:231 #, c-format msgid "read of namreg failed: %s\n" msgstr "Lesen von »namreg« fehlgeschlagen: %s\n" #: .././common/openutil.c:78 .././common/openutil.c:94 #, c-format msgid "could not create %s: %s\n" msgstr "%s konnte nicht erstellt werden: %s\n" #: .././common/qlock.c:169 #, c-format msgid "unable to configure shared arena for auto unlink: %s\n" msgstr "" "gemeinsamer Schauplatz für automatisches Löschen von Verknüpfungen kann nicht " "eingerichtet werden: %s\n" #: .././common/qlock.c:179 #, c-format msgid "unable to allocate shared arena for thread locks: %s\n" msgstr "" "es kann kein gemeinsamer Speicherplatz für Thread-Sperren reserviert werden: " "%s\n" #: .././common/qlock.c:215 #, c-format msgid "unable to add thread to shared arena: %s\n" msgstr "es kann kein Thread zu gemeinsamem Speicherplatz hinzugefügt werden: %s\n" #: .././common/qlock.c:301 #, c-format msgid "lock already held: thrd %d pid %d ord %d map %x\n" msgstr "Sperre bereits gehalten: Thrd %d PID %d Ord %d Map %x\n" #: .././common/qlock.c:313 #, c-format msgid "lock ordinal violation: thrd %d pid %d ord %d map %x\n" msgstr "Ordinale Verletzung der Sperre: Thrd %d PID %d Ord %d Map %x\n" #: .././common/qlock.c:446 #, c-format msgid "unable to \"P\" semaphore: rval == %d, errno == %d (%s)\n" msgstr "»P« auf Semaphor nicht möglich: Rval == %d, Fehlernummer == %d (%s)\n" #: .././common/qlock.c:473 #, c-format msgid "unable to \"V\" semaphore: rval == %d, errno == %d (%s)\n" msgstr "»V« auf Semaphor nicht möglich: Rval == %d, Fehlernummer == %d (%s)\n" #: .././common/util.c:188 .././dump/content.c:2943 #, c-format msgid "failed to get bulkstat information for inode %llu\n" msgstr "Bulkstat-Informationen für Inode %llu abfragen fehlgeschlagen\n" #: .././common/util.c:194 #, c-format msgid "failed to get valid bulkstat information for inode %llu\n" msgstr "" "gültige Bulkstat-Informationen für Inode %llu können nicht abgefragt werden\n" #: .././common/util.c:243 #, c-format msgid "syssgi( SGI_FS_BULKSTAT ) on fsroot failed: %s\n" msgstr "syssgi( SGI_FS_BULKSTAT ) auf »fsroot« fehlgeschlagen: %s\n" #: .././common/util.c:288 .././restore/content.c:1869 #, c-format msgid "malloc of stream context failed (%d bytes): %s\n" msgstr "»Malloc« des Datenstrom-Kontextes fehlgeschlagen (%d Byte): %s\n" #: .././common/util.c:371 #, c-format msgid "WARNING: unable to open directory ino %llu: %s\n" msgstr "WARNUNG: Verzeichnis-Ino %llu kann nicht geöffnet werden: %s\n" #: .././common/util.c:402 #, c-format msgid "WARNING: unable to read dirents (%d) for directory ino %llu: %s\n" msgstr "" "WARNUNG: Dirents (%d) für Verzeichnis-Ino %llu können nicht gelesen werden: " "%s\n" #: .././common/util.c:450 #, c-format msgid "WARNING: could not stat dirent %s ino %llu: %s\n" msgstr "" "WARNUNG: »stat« kann nicht für Dirent %s Ino %llu ausgeführt werden: %s\n" #: .././common/util.c:465 #, c-format msgid "WARNING: unable to process dirent %s: ino %llu too large\n" msgstr "WARNUNG: Dirent %s kann nicht verarbeitet werden: Ino %llu zu groß\n" #: .././dump/inomap.c:241 msgid "ino map phase 1: constructing initial dump list\n" msgstr "Ino-Map Phase 1: Anfängliche Ausgabeliste aufstellen\n" #: .././dump/inomap.c:278 #, c-format msgid "pruned %llu files: maximum size exceeded\n" msgstr "%llu Dateien verkleinert: Maximale Größe überschritten\n" #: .././dump/inomap.c:283 #, c-format msgid "pruned %llu files: skip attribute set\n" msgstr "" "%llu Dateien verkleinert: Attributszusammenstellung wird übersprungen\n" #: .././dump/inomap.c:294 msgid "ino map phase 2: pruning unneeded subtrees\n" msgstr "Ino-Map Phase 2: Nicht benötigte Unterbäume werden verkleinert\n" #: .././dump/inomap.c:315 msgid "ino map phase 2: skipping (no pruning necessary)\n" msgstr "Ino-Map Phase 2: Wird übersprungen (kein Verkleinern nötig)\n" #: .././dump/inomap.c:327 msgid "ino map phase 3: identifying stream starting points\n" msgstr "Ino-Map Phase 3: Datenstrom-Startpunkte werden identifiziert\n" #: .././dump/inomap.c:331 msgid "ino map phase 3: skipping (only one dump stream)\n" msgstr "Ino-Map Phase 3: Wird übersprungen (nur ein Ausgabedatenstrom)\n" #: .././dump/inomap.c:371 #, c-format msgid "stream %u: ino %llu offset %lld to " msgstr "Datenstrom %u: Ino %llu Versatz %lld bis " #: .././dump/inomap.c:377 msgid "end\n" msgstr "Ende\n" #: .././dump/inomap.c:380 #, c-format msgid "ino %llu offset %lld\n" msgstr "Ino %llu Versatz %lld\n" #: .././dump/inomap.c:390 msgid "ino map construction complete\n" msgstr "Ino-Map-Konstruktion vollständig\n" #: .././dump/inomap.c:1209 #, c-format msgid "failed to allocate inomap context: %s\n" msgstr "Reservieren des Inomap-Kontexts fehlgeschlagen: %s\n" #: .././dump/inomap.c:1552 msgid "subtree not present" msgstr "Teilbaum nicht vorhanden" #: .././dump/inomap.c:1553 msgid "invalid subtree specified" msgstr "ungültiger Teilbaum angegeben" #: .././dump/inomap.c:1705 #, c-format msgid "could not open ino %llu to read extent map: %s\n" msgstr "" "Ino %llu kann nicht zum Lesen der Bereichsabbildung geöffnet werden: %s\n" #: .././dump/inomap.c:1718 #, c-format msgid "could not read extent map for ino %llu: %s\n" msgstr "Bereichsabbildung für %llu kann nicht zum Lesen geöffnet werden: %s\n" #: .././dump/inomap.c:1788 #, c-format msgid "unknown inode type: ino=%llu, mode=0x%04x 0%06o\n" msgstr "unbekannter Inode-Typ: Ino=%llu, Modus=0x%04x 0%06o\n" #: .././dump/var.c:64 .././restore/tree.c:385 .././restore/content.c:1267 #, c-format msgid "unable to create %s: %s\n" msgstr "%s kann nicht erstellt werden: %s\n" #: .././dump/var.c:71 #, c-format msgid "unable to chown %s: %s\n" msgstr "»chown %s« nicht möglich: %s\n" #: .././dump/var.c:92 #, c-format msgid "unable to determine uuid of fs containing %s: %s\n" msgstr "" "UUID des Dateisystems, das %s enthält, kann nicht festgestellt werden: %s\n" #: .././dump/var.c:121 #, c-format msgid "unable to get status of %s: %s\n" msgstr "Status von %s kann nicht geholt werden: %s\n" #: .././dump/var.c:140 #, c-format msgid "unable to open directory %s\n" msgstr "Verzeichnis %s kann nicht geöffnet werden\n" #: .././dump/content.c:220 .././restore/content.c:8710 msgid "root" msgstr "Root" #: .././dump/content.c:221 .././restore/content.c:8712 msgid "secure" msgstr "sicher" #: .././dump/content.c:222 .././restore/content.c:8714 msgid "non-root" msgstr "Kein Root-Benutzer" #: .././dump/content.c:227 msgid "dir" msgstr "Verz." #: .././dump/content.c:227 msgid "nondir" msgstr "kein Verz." #: .././dump/content.c:610 #, c-format msgid "-%c argument must be between 0 and %d\n" msgstr "-%c-Argument muss zwischen 0 und %d liegen\n" #: .././dump/content.c:628 #, c-format msgid "-%c argument (subtree) must be a relative pathname\n" msgstr "-%c-Argument (Teilbaum) muss ein relativer Pfadname sein\n" #: .././dump/content.c:649 #, c-format msgid "-%c argument is not a valid file size\n" msgstr "-%c-Argument ist keine gültige Dateigröße\n" #: .././dump/content.c:697 #, c-format msgid "-%c argument not a valid dump session id\n" msgstr "-%c-Argument ist keine gültige Ausgabedatei-ID\n" #: .././dump/content.c:711 #, c-format msgid "may not specify both -%c and -%c\n" msgstr "es können nicht sowohl -%c als auch -%c angegeben werden\n" #: .././dump/content.c:731 msgid "source file system not specified\n" msgstr "Quelldateisystem nicht angegeben\n" #: .././dump/content.c:782 #, c-format msgid "%s does not identify a file system\n" msgstr "%s bezeichnet kein Dateisystem\n" #: .././dump/content.c:794 #, c-format msgid "%s must be mounted to be dumped\n" msgstr "%s muss eingehängt sein, um ausgegeben werden zu können\n" #: .././dump/content.c:847 #, c-format msgid "failed to save %s information, continuing\n" msgstr "sichern von %s-Informationen fehlgeschlagen, wird fortgesetzt\n" #: .././dump/content.c:899 #, c-format msgid "could not find specified base dump (%s) in inventory\n" msgstr "angegebene Basisausgabe (%s) kann nicht im Bestand gefunden werden\n" #: .././dump/content.c:972 #, c-format msgid "" "cannot select dump session %d as base for incremental dump: level must be " "less than %d\n" msgstr "" "Ausgabessitzung %d kann nicht als Basis für inkrementelle Ausgabe ausgewählt " "werden: Stufe muss kleiner als %d sein\n" #: .././dump/content.c:1004 msgid "cannot calculate incremental dump: online inventory not available\n" msgstr "" "inkrementelle Ausgabe kann nicht berechnet werden: Online-Bestand nicht " "verfügbar\n" #: .././dump/content.c:1133 #, c-format msgid "" "most recent level %d dump was interrupted, but not resuming that dump since " "resume (-R) option not specified\n" msgstr "" "Ausgabe der aktuellsten Stufe %d wurde unterbrochen, aber nicht wieder " "aufgenommen, so dass Ausgabe seit der Option »resume« (-R) nicht angegeben " "ist\n" #: .././dump/content.c:1150 .././dump/content.c:1216 #, c-format msgid "" "most recent base for incremental dump was interrupted (level %u): must " "resume or redump at or below level %d\n" msgstr "" "aktuellste Basis für inkrementelle Ausgabe wurde unterbrochen (Stufe %u): " "Muss auf oder über Stufe %d wieder aufgenommen oder erneut ausgegeben " "werden\n" #: .././dump/content.c:1161 .././dump/content.c:1227 #, c-format msgid "" "level %u incremental subtree dump will be based on non-subtree level %u " "dump\n" msgstr "" "Stufe %u der inkrementellen Teilbaumausgabe wird auf einer Ausgabe der " "Nicht-Teilbaumstufe %u basieren\n" #: .././dump/content.c:1170 .././dump/content.c:1236 #, c-format msgid "" "level %u incremental non-subtree dump will be based on subtree level %u " "dump\n" msgstr "" "Stufe %u der inkrementellen Nicht-Teilbaumausgabe wird auf einer Ausgabe der " "Teilbaumstufe %u basieren\n" #: .././dump/content.c:1188 #, c-format msgid "" "level %u incremental subtree dump will be based on non-subtree level %u " "resumed dump\n" msgstr "" "Stufe %u der inkrementellen Teilbaumausgabe wird auf einer wieder " "aufgenommenen Ausgabe der Nicht-Teilbaumstufe %u basieren\n" #: .././dump/content.c:1197 #, c-format msgid "" "level %u incremental non-subtree dump will be based on subtree level %u " "resumed dump\n" msgstr "" "Stufe %u der inkrementellen Nicht-Teilbaumausgabe wird auf einer wieder " "aufgenommenen Ausgabe der Teilbaumstufe %u basieren\n" #: .././dump/content.c:1255 #, c-format msgid "" "level %u subtree dump will be based on non-subtree level %u resumed dump\n" msgstr "" "Stufe %u der Teilbaumausgabe wird auf einer wieder aufgenommenen Ausgabe der " "Nicht-Teilbaumstufe %u basieren\n" #: .././dump/content.c:1264 #, c-format msgid "" "level %u non-subtree dump will be based on subtree level %u resumed dump\n" msgstr "" "Stufe %u der Nicht-Teilbaumausgabe wird auf einer wieder aufgenommenen " "Ausgabe der Teilbaumstufe %u basieren\n" #: .././dump/content.c:1282 #, c-format msgid "cannot find earlier dump to base level %d increment upon\n" msgstr "" "es können keine früheren Ausgaben gefunden werden, die als Basis für die " "inkrementelle Ausgabe Stufe %d dienen könnten.\n" #: .././dump/content.c:1294 #, c-format msgid "most recent base dump (level %d begun %s) was interrupted: aborting\n" msgstr "" "aktuellste Basisausgabe (Stufe %d begonnen %s) wurde unterbrochen: Abbruch\n" #: .././dump/content.c:1305 #, c-format msgid "" "resume (-R) option inappropriate: no interrupted level %d dump to resume\n" msgstr "" "Option »resume« (-R) ungeeignet: Keine unterbrochene Stufe %d der Ausgabe " "zur Wiederaufnahme\n" #: .././dump/content.c:1324 #, c-format msgid "" "resuming level %d incremental dump of %s:%s begun %s (incremental base level " "%d begun %s)\n" msgstr "" "Stufe %d der inkrementellen Ausgabe von %s wird wieder aufgenommen: %s " "begann %s (inkrementelle Basisstufe %d begann %s)\n" #: .././dump/content.c:1335 #, c-format msgid "level %d incremental dump of %s:%s based on level %d dump begun %s\n" msgstr "" "Stufe %d der inkrementellen Ausgabe von %s: %s basiert auf Stufe %d der " "Ausgabe begonnen %s\n" #: .././dump/content.c:1346 #, c-format msgid "resuming level %d dump of %s:%s begun %s\n" msgstr "Stufe-%d-Ausgabe von %s wird wieder aufgenommen: %s begann %s\n" #: .././dump/content.c:1353 #, c-format msgid "level %d dump of %s:%s\n" msgstr "Stufe-%d-Ausgabe von %s: %s\n" #: .././dump/content.c:1367 #, c-format msgid "dump date: %s\n" msgstr "Ausgabedatum: %s\n" #: .././dump/content.c:1376 .././restore/content.c:9402 #, c-format msgid "session id: %s\n" msgstr "Sitzungs-ID: %s\n" #: .././dump/content.c:1383 #, c-format msgid "session label: \"%s\"\n" msgstr "Sitzungskennung: »%s«\n" #: .././dump/content.c:1407 #, c-format msgid "could not stat %s\n" msgstr "%s kann nicht mit »stat« abgefragt werden\n" #: .././dump/content.c:1417 msgid "failed to get bulkstat information for root inode\n" msgstr "" "Erhalt von »bulkstat«-Informationen über den Wurzel-Inode fehlgeschlagen\n" #: .././dump/content.c:1428 .././restore/content.c:1692 #, c-format msgid "unable to construct a file system handle for %s: %s\n" msgstr "es kann kein Dateisystem-Handle für %s konstruiert werden: %s\n" #: .././dump/content.c:1556 #, c-format msgid "estimated dump size: %llu bytes\n" msgstr "geschätzte Ausgabegröße: %llu Byte\n" #: .././dump/content.c:1561 #, c-format msgid "estimated dump size per stream: %llu bytes\n" msgstr "geschätzte Ausgabegröße pro Datenstrom: %llu Byte\n" #: .././dump/content.c:1665 #, c-format msgid "more -%c arguments than number of drives\n" msgstr "mehr -%c-Argumente als Anzahl der Geräte\n" #: .././dump/content.c:1686 #, c-format msgid "media labels given for only %d out of %d drives\n" msgstr "es wurden nur für %d von %d Laufwerken Medien-Kennungen angegeben\n" #: .././dump/content.c:2277 msgid "" "media change timeout will be treated as a request to stop using drive: can " "resume later\n" msgstr "" "Zeitüberschreitung des Medienwechsels wird als Stopp-Anfrage für die " "Benutzung des Laufwerks betrachtet: Kann später fortgesetzt werden\n" #: .././dump/content.c:2285 msgid "" "media change decline will be treated as a request to stop using drive: can " "resume later\n" msgstr "" "Ablehnen des Medienwechsels wird als Stopp-Anfrage für die Benutzung des " "Laufwerks betrachtet: Kann später fortgesetzt werden\n" #: .././dump/content.c:2308 #, c-format msgid "creating dump session media file %u (media %u, file %u)\n" msgstr "Ausgabesitzungs-Mediendatei %u wird erstellt (Medium %u, Datei %u)\n" #: .././dump/content.c:2322 msgid "dumping ino map\n" msgstr "Ausgabe der Ino-Map\n" #: .././dump/content.c:2395 msgid "dumping non-directory files\n" msgstr "Ausgabe der Nicht-Verzeichnisdateien\n" #: .././dump/content.c:2514 msgid "ending media file\n" msgstr "Ende der Mediendatei\n" #: .././dump/content.c:2530 #, c-format msgid "media file size %lld bytes\n" msgstr "Mediendateigröße %lld Byte\n" #: .././dump/content.c:2628 msgid "inventory media file put failed\n" msgstr "Bereitstellen der Medienbestandsdatei fehlgeschlagen\n" #: .././dump/content.c:2659 msgid "waiting for synchronized session inventory dump\n" msgstr "es wird auf die synchronisierte Sitzungsbestandsausgabe gewartet\n" #: .././dump/content.c:2691 #, c-format msgid "ending stream: %ld seconds elapsed\n" msgstr "Ende des Datenstroms: %ld Sekunden verstrichen\n" #: .././dump/content.c:2714 #, c-format msgid "dump size (non-dir files) : %llu bytes\n" msgstr "Ausgabegröße (Nicht-Verzeichnisdateien): %llu Byte\n" #: .././dump/content.c:2722 .././dump/content.c:6720 #, c-format msgid "unable to remove %s: %s\n" msgstr "%s kann nicht entfernt werden: %s\n" #: .././dump/content.c:2730 #, c-format msgid "dump complete: %ld seconds elapsed\n" msgstr "Ausgabe vollständig: %ld Sekunden verstrichen\n" #: .././dump/content.c:2737 #, c-format msgid "" "dump interrupted: %ld seconds elapsed: may resume later using -%c option\n" msgstr "" "Ausgabe unterbrochen: %ld Sekunden verstrichen: Könnte später unter " "Benutzung der Option -%c fortgesetzt werden\n" #: .././dump/content.c:2746 #, c-format msgid "dump interrupted: %ld seconds elapsed\n" msgstr "Ausgabe unterbrochen: %ld Sekunden verstrichen\n" #: .././dump/content.c:2868 msgid "waiting for synchronized directory dump\n" msgstr "es wird auf die synchronisierte Verzeichnisausgabe gewartet\n" #: .././dump/content.c:2880 msgid "dumping directories\n" msgstr "Ausgabe der Verzeichnisse\n" #: .././dump/content.c:2906 #, c-format msgid "SGI_FS_BULKSTAT failed: %s (%d)\n" msgstr "SGI_FS_BULKSTAT fehlgeschlagen: %s (%d)\n" #: .././dump/content.c:3099 #, c-format msgid "unable to dump directory: ino %llu too large\n" msgstr "Verzeichnis kann nicht ausgegeben werden: Ino %llu zu groß\n" #: .././dump/content.c:3113 #, c-format msgid "unable to open directory: ino %llu: %s\n" msgstr "Verzeichnis kann nicht ausgegeben werden: Ino %llu: %s\n" #: .././dump/content.c:3141 #, c-format msgid "unable to read dirents (%d) for directory ino %llu: %s\n" msgstr "" "Dirents (%d) für Verzeichnis-Ino %llu können nicht gelesen werden: %s\n" #: .././dump/content.c:3204 #, c-format msgid "encountered 0 ino (%s) in directory ino %llu: NOT dumping\n" msgstr "0-Ino (%s) in Verzeichnis-Ino %llu vorgefunden: KEINE Ausgabe\n" #: .././dump/content.c:3224 #, c-format msgid "" "could not stat dirent %s ino %llu: %s: using null generation count in " "directory entry\n" msgstr "" "»stat dirent %s ino %llu« konnte nicht ausgeführt werden: %s: »null " "generation count« wird im Verzeichniseintrag benutzt\n" #: .././dump/content.c:3329 #, c-format msgid "could not get list of %s attributes for %s ino %llu: %s (%d)\n" msgstr "" "Liste von %s-Attributen für %s-Ino %llu konnte nicht geholt werden: %s (%d)\n" #: .././dump/content.c:3426 #, c-format msgid "HSM could not filter %s attribute %s for %s ino %llu\n" msgstr "HSM konnte %s-Attribut %s für %s-Ino %llu nicht filtern\n" #: .././dump/content.c:3477 #, c-format msgid "could not retrieve %s attributes for %s ino %llu: %s (%d)\n" msgstr "%s-Attribute für %s Ino %llu konnten nicht abgefragt werden: %s (%d)\n" #: .././dump/content.c:3506 #, c-format msgid "" "attr_multi indicates error while retrieving %s attribute [%s] for %s ino %" "llu: %s (%d)\n" msgstr "" "»attr_multi« zeigt Fehler während des Abfragens von %s-Attribut [%s] für %s " "Ino %llu: %s (%d)\n" #: .././dump/content.c:3578 #, c-format msgid "HSM could not add new %s attribute #%d for %s ino %llu\n" msgstr "HSM konnte %s-Attribut #%d für %s-Ino %llu nicht hinzufügen\n" #: .././dump/content.c:3705 #, c-format msgid "" "%s extended attribute name for %s ino %llu too long: %u, max is %u: " "skipping\n" msgstr "" "%s erweiterter Attributsname für %s-Ino %llu zu lang: %u, Maximum ist %u: " "Wird übersprungen\n" #: .././dump/content.c:3718 #, c-format msgid "" "%s extended attribute value for %s ino %llu too long: %u, max is %u: " "skipping\n" msgstr "" "%s erweiterter Attributswert für %s Ino %llu zu lang: %u, Maximum ist %u: " "Wird übersprungen\n" #: .././dump/content.c:3929 #, c-format msgid "inomap inconsistency ino %llu: %s but is now non-dir: NOT dumping\n" msgstr "" "»inomap«-Unvollständigkeit Ino %llu: %s ist nun aber kein Verzeichnis: Wird " "NICHT ausgegeben\n" #: .././dump/content.c:3947 #, c-format msgid "inomap inconsistency ino %llu: hsm detected error: NOT dumping\n" msgstr "" "»inomap«-Unvollständigkeit Ino %llu: HSM entdeckt Fehler: Wird NICHT " "ausgegeben\n" #: .././dump/content.c:4036 #, c-format msgid "don't know how to dump ino %llu: mode %08x\n" msgstr "" "es ist nicht bekannt, wie Ino %llu ausgegeben werden soll: Modus %08x\n" #: .././dump/content.c:4161 #, c-format msgid "could not open regular file ino %llu mode 0x%08x: %s: not dumped\n" msgstr "" "regulärer Datei-Ino %llu Modus 0x%08x kann nicht geöffnet werden: %s: Nicht " "ausgegeben\n" #: .././dump/content.c:4210 #, c-format msgid "dump interrupted prior to ino %llu offset %lld\n" msgstr "Ausgabe unterbrochen vor Ino %llu Versatz %lld\n" #: .././dump/content.c:4445 #, c-format msgid "locking check failed ino %llu\n" msgstr "Prüfung der Sperre fehlgeschlagen Ino %llu\n" #: .././dump/content.c:4494 #, c-format msgid "dioinfo failed ino %llu\n" msgstr "»dioinfo« fehlgeschlagen Ino %llu\n" #: .././dump/content.c:4563 #, c-format msgid "" "getbmapx %d ino %lld mode 0x%08x offset %lld ix %d returns negative entry " "count\n" msgstr "" "»getbmapx« %d Ino %lld Modus 0x%08x Versatz %lld ix %d gibt negative Anzahl " "Einträge zurück\n" #: .././dump/content.c:4578 #, c-format msgid "getbmapx %d ino %lld mode 0x%08x offset %lld failed: %s\n" msgstr "»getbmapx« %d Ino %lld Modus 0x%08x Versatz %lld fehlgeschlagen: %s\n" #: .././dump/content.c:4600 #, c-format msgid "hsm detected an extent map error in ino %lld, skipping\n" msgstr "" "HSM entdeckte einen Bereichs-Abbildungsfehler in Ino %lld, wird " "übersprungen\n" #: .././dump/content.c:4943 #, c-format msgid "can't lseek ino %llu\n" msgstr "»lseek ino %llu« kann nicht ausgeführt werden\n" #: .././dump/content.c:4957 #, c-format msgid "can't read ino %llu at offset %d (act=%d req=%d) rt=%d\n" msgstr "" "Ino %llu bei Versatz %d kann nicht gelesen werden (act=%d req=%d) rt=%d\n" #: .././dump/content.c:5263 #, c-format msgid "unable to dump directory %llu entry %s (%llu): name too long\n" msgstr "" "Verzeichnis %llu Eintrag %s (%llu) kann nicht ausgegeben werden: Name zu " "lang\n" #: .././dump/content.c:5343 msgid "dumping session inventory\n" msgstr "Sitzungsbestand wird ausgegeben\n" #: .././dump/content.c:5352 msgid "unable to get session inventory to dump\n" msgstr "Sitzungsbestand kann nicht zur Ausgabe geholt werden\n" #: .././dump/content.c:5374 msgid "beginning inventory media file\n" msgstr "Anfang der Medienbestandsdatei\n" #: .././dump/content.c:5383 msgid "media change timeout: session inventory not dumped\n" msgstr "" "Zeitüberschreitung beim Medienwechsel: Sitzungsbestand nicht ausgegeben\n" #: .././dump/content.c:5389 msgid "media change declined: session inventory not dumped\n" msgstr "Medienwechsel abgelehnt: Sitzungsbestand nicht ausgegeben\n" #: .././dump/content.c:5401 .././dump/content.c:5545 #, c-format msgid "media file %u (media %u, file %u)\n" msgstr "Mediendatei %u (Medium %u, Datei %u)\n" #: .././dump/content.c:5429 msgid "ending inventory media file\n" msgstr "Ende der Medienbestandsdatei\n" #: .././dump/content.c:5448 #, c-format msgid "encountered EOM while writing inventory media file size %lld bytes\n" msgstr "" "beim Schreiben der Bestandsmedien-Dateigröße %lld Byte wurde EOM " "vorgefunden\n" #: .././dump/content.c:5454 #, c-format msgid "inventory media file size %lld bytes\n" msgstr "Bestandsmedien-Dateigröße %lld Byte\n" #: .././dump/content.c:5480 msgid "inventory session media file put failed\n" msgstr "Bereitstellen der Sitzungsmediendatei fehlgeschlagen\n" #: .././dump/content.c:5505 msgid "writing stream terminator\n" msgstr "Datenstrom-Terminator wird geschrieben\n" #: .././dump/content.c:5520 msgid "beginning media stream terminator\n" msgstr "Datenstrom-Terminator wird begonnen\n" #: .././dump/content.c:5529 msgid "media change timeout: media stream terminator not written\n" msgstr "" "Zeitüberschreitung beim Medienwechsel: Datenstrom-Terminator für Medium " "nicht geschrieben\n" #: .././dump/content.c:5534 msgid "media change declined: media stream terminator not written\n" msgstr "" "Medienwechsel abgelehnt: Datenstrom-Terminator für Medium nicht geschrieben\n" #: .././dump/content.c:5551 msgid "ending media stream terminator\n" msgstr "Datenstrom-Terminator wird beendet\n" #: .././dump/content.c:5570 #, c-format msgid "encountered EOM while writing media stream terminator size %lld bytes\n" msgstr "" "beim Schreiben der Datenstrom-Terminator-Größe %lld Byte wurde EOM " "vorgefunden\n" #: .././dump/content.c:5575 #, c-format msgid "media stream terminator size %lld bytes\n" msgstr "Datenstrom-Terminator-Größe %lld Byte\n" #: .././dump/content.c:5772 #, c-format msgid "positioned at media file %u: dump %u, stream %u\n" msgstr "positioniert auf Mediendatei %u: Ausgabe %u, Datenstrom %u\n" #: .././dump/content.c:5820 .././dump/content.c:6184 msgid "cannot interleave dump streams: must supply a blank media object\n" msgstr "" "Auszugsdatenströme können nicht überlappen: Es muss ein leeres Medienobjekt " "bereitgestellt werden\n" #: .././dump/content.c:5826 msgid "media contains valid xfsdump but does not support append\n" msgstr "Medium enthält gültiges »xfsdump«, unterstützt aber kein Anhängen\n" #: .././dump/content.c:5833 msgid "stream terminator found\n" msgstr "Datenstrom-Terminator gefunden\n" #: .././dump/content.c:5841 msgid "encountered media error attempting BSF\n" msgstr "Medienfehler beim Versuch von BSF vorgefunden\n" #: .././dump/content.c:5855 msgid "" "media contains non-xfsdump data or a corrupt xfsdump media file header at " "beginning of media\n" msgstr "" "Medium enthält Nicht-Xfsdump-Daten oder beschädigte " "Xfsdump-Mediendatei-Kopfzeilen am Anfang des Mediums\n" #: .././dump/content.c:5885 msgid "unable to overwrite\n" msgstr "kann nicht überschrieben werden\n" #: .././dump/content.c:5890 msgid "repositioning to overwrite\n" msgstr "wird zum Überschreiben neu positioniert\n" #: .././dump/content.c:5908 msgid "media may contain data. Overwrite option specified\n" msgstr "Medium könnte Daten enthalten. Überschreiboption angegeben\n" #: .././dump/content.c:5936 msgid "at end of data\n" msgstr "am Ende der Daten\n" #: .././dump/content.c:5955 msgid "" "encountered EOD but expecting a media stream terminator: assuming full " "media\n" msgstr "" "EOD (Datenende) wurde vorgefunden, aber ein Medien-Datenstromterminator " "erwartet: Medium vermutlich voll\n" #: .././dump/content.c:5967 msgid "encountered EOM: media is full\n" msgstr "EOD (Datenende) wurde vorgefunden: Medium ist voll\n" #: .././dump/content.c:5990 msgid "encountered corrupt or foreign data: assuming corrupted media\n" msgstr "" "beschädigte oder fremde Daten vorgefunden: Medium vermutlich beschädigt\n" #: .././dump/content.c:6008 msgid "" "encountered corrupt or foreign data but expecting a media stream terminator: " "assuming corrupted media\n" msgstr "" "beschädigte oder falsche Daten vorgefunden, aber Mediendatenstrom-Terminator " "erwartet: Medium vermutlich beschädigt\n" #: .././dump/content.c:6016 msgid "" "encountered corrupt or foreign data: unable to overwrite: assuming corrupted " "media\n" msgstr "" "beschädigte oder falsche Daten vorgefunden: Können nicht überschrieben " "werden: Medium vermutlich beschädigt\n" #: .././dump/content.c:6024 msgid "encountered corrupt or foreign data: repositioning to overwrite\n" msgstr "" "beschädigte oder falsche Daten vorgefunden: Zum Überschreiben neu " "positioniert\n" #: .././dump/content.c:6043 #, c-format msgid "unexpected error from do_begin_read: %d\n" msgstr "unerwarteter Fehler von »do_begin_read«: %d\n" #: .././dump/content.c:6052 msgid "erasing media\n" msgstr "Medium wird gelöscht\n" #: .././dump/content.c:6100 .././restore/content.c:4675 #, c-format msgid "please change media: type %s to confirm media change\n" msgstr "" "bitte Medium wechseln: Geben Sie %s ein, um Medienwechsel zu bestätigen\n" #: .././dump/content.c:6235 msgid "no media label specified\n" msgstr "Kein Medien-Kennung angegeben\n" #: .././dump/content.c:6260 msgid "encountered end of media while attempting to begin new media file\n" msgstr "" "Ende des Mediums vorgefunden, während versucht wird neue Mediendatei " "anzufangen\n" #: .././dump/content.c:6306 msgid "encountered end of media while ending media file\n" msgstr "Ende des Mediums vorgefunden, während Mediendatei endete\n" #: .././dump/content.c:6449 #, c-format msgid "drive does not support media erase: ignoring -%c option\n" msgstr "" "Laufwerk unterstützt nicht das Löschen von Medien: Option -%c wird " "ignoriert\n" #: .././dump/content.c:6712 #, c-format msgid "saving %s information for: %s\n" msgstr "%s-Informationen werden gespeichert für: %s\n" #: .././dump/content.c:6715 #, c-format msgid "overwriting: %s\n" msgstr "wird überschrieben: %s\n" #: .././dump/content.c:6739 #, c-format msgid "%s failed with exit status: %d\n" msgstr "%s fehlgeschlagen mit Beendigungsstatus: %d\n" #: .././dump/content.c:6745 #, c-format msgid "open failed %s: %s\n" msgstr "%s zu öffnen fehlgeschlagen: %s\n" #: .././inventory/inv_api.c:183 msgid "INV: put_fstab_entry failed.\n" msgstr "INV: put_fstab_entry fehlgeschlagen\n" #: .././inventory/inv_api.c:231 msgid "INV: put_starttime failed.\n" msgstr "INV: put_starttime fehlgeschlagen\n" #: .././inventory/inv_api.c:331 #, c-format msgid "INV: cant create more than %d streams. Max'd out..\n" msgstr "" "INV: Es können nicht mehr als %d Datenströme erstellt werden. Übergröße ...\n" #: .././inventory/inv_api.c:378 msgid "INV: idx_put_sesstime failed in inv_stream_close() \n" msgstr "INV: idx_put_sesstime in inv_stream_close() fehlgeschlagen\n" #: .././inventory/inv_api.c:763 .././inventory/inv_mgr.c:159 msgid "INV: Error in fstab\n" msgstr "INV: Fehler in fstab\n" #: .././inventory/inv_api.c:777 .././inventory/inv_mgr.c:170 msgid "INV: Cant get inv-name for uuid\n" msgstr "INV: inv-name für UUID kann nicht geholt werden\n" #: .././inventory/inv_api.c:784 .././inventory/inv_mgr.c:178 #, c-format msgid "INV: Open failed on %s\n" msgstr "INV: Öffnen auf %s fehlgeschlagen\n" #: .././inventory/inv_api.c:968 #, c-format msgid "INV: invalid sub-option %s for -I option\n" msgstr "INV: Ungültige Unteroption %s für Option -I\n" #: .././inventory/inv_api.c:982 msgid "INV: Only one of mnt=,dev= and fsid=value can be used.\n" msgstr "INV: Nur eines von mnt=,dev= und fsid=Wert kann benutzt werden.\n" #: .././inventory/inv_api.c:988 msgid "INV: Only one of mobjid= and mobjlabel= can be used.\n" msgstr "INV: Nur eines von mobjid= und mobjlabel= kann benutzt werden.\n" #: .././inventory/inv_api.c:1034 #, c-format msgid "INV: open failed on mount point \"%s\"\n" msgstr "INV: Öffnen auf Einhängepunkt »%s« fehlgeschlagen\n" #: .././inventory/inv_api.c:1049 #, c-format msgid "INV: open failed on file system id \"%s\"\n" msgstr "INV: Öffnen auf Dateisystem-ID »%s« fehlgeschlagen\n" #: .././inventory/inv_api.c:1105 #, c-format msgid "INV: checking fs \"%s\"\n" msgstr "INV: Dateisystem »%s« wird geprüft\n" #: .././inventory/inv_core.c:62 #, c-format msgid "INV : Unknown version %d - Expected version %d\n" msgstr "INV : Unbekannte Version %d - erwartete Version %d\n" #: .././inventory/inv_core.c:86 msgid "get_headers() - malloc(seshdrs)\n" msgstr "get_headers() - malloc(seshdrs)\n" #: .././inventory/inv_core.c:119 msgid "Error in reading inventory record (lseek failed): " msgstr "Fehler im gelesenen Bestandsdatensatz (lseek fehlgeschlagen): " #: .././inventory/inv_core.c:129 msgid "Error in reading inventory record :" msgstr "Fehler im gelesenen Bestandsdatensatz :" #: .././inventory/inv_core.c:160 msgid "Error in writing inventory record (lseek failed): " msgstr "Fehler im geschriebenen Bestandsdatensatz (lseek fehlgeschlagen): " #: .././inventory/inv_core.c:168 msgid "Error in writing inventory record :" msgstr "Fehler im geschriebenen Bestandsdatensatz :" #: .././inventory/inv_fstab.c:62 msgid "INV: couldn't get fstab headers\n" msgstr "INV: Fstab-Kopfzeilen konnten nicht geholt werden\n" #: .././inventory/inv_fstab.c:190 msgid "INV: No recorded filesystems in inventory's fstab.\n" msgstr "INV: Keine aufgezeichneten Dateisysteme in der Fstab des Bestands.\n" #: .././inventory/inv_fstab.c:243 msgid "" "\n" "\n" "--------- fstab ------------\n" msgstr "" "\n" "\n" "--------- fstab ------------\n" #: .././inventory/inv_fstab.c:245 #, c-format msgid "Mount\t%s\n" msgstr "Einhängen\t%s\n" #: .././inventory/inv_fstab.c:246 #, c-format msgid "Dev\t%s\n" msgstr "Dev\t%s\n" #: .././inventory/inv_fstab.c:248 #, c-format msgid "" "FSid\t%s\n" "\n" msgstr "" "FSid\t%s\n" "\n" #: .././inventory/inv_mgr.c:457 #, c-format msgid "INV: Check %d failed.\n" msgstr "INV: Prüfen von %d fehlgeschlagen.\n" #: .././inventory/inv_mgr.c:458 #, c-format msgid "invidx (%d)\t%d - %d\n" msgstr "invidx (%d)\t%d - %d\n" #: .././inventory/inv_mgr.c:463 #, c-format msgid "tm (%d)\t%d\n" msgstr "tm (%d)\t%d\n" #: .././inventory/inv_mgr.c:467 #, c-format msgid "INV: Check %d out of %d succeeded\n" msgstr "INV: Prüfen von %d von %d erfolgreich\n" #: .././inventory/inv_mgr.c:684 #, c-format msgid "%s created\n" msgstr "%s erstellt\n" #: .././inventory/inv_stobj.c:140 msgid "INV: failed to find a different sh_time to split\n" msgstr "" "INV: Eine unterschiedliche sh_time zum Aufteilen zu finden fehlgeschlagen\n" #: .././inventory/inv_stobj.c:1016 msgid "INV: inv_put_session: unknown cookie\n" msgstr "INV: inv_put_session: Unbekanntes Cookie\n" #: .././inventory/inv_stobj.c:1056 #, c-format msgid "INV: inv_put_session: unknown packed inventory version %d\n" msgstr "INV: inv_put_session: Unbekannte Paketbestandsversion %d\n" #: .././inventory/inv_stobj.c:1262 msgid "Failed to get data from media file: possible file corruption\n" msgstr "" "Daten aus der Mediendatei abzufragen fehlgeschlagen: Datei möglicherweise " "beschädigt\n" #: .././librmt/rmtioctl.c:192 msgid "rmtioctl: remote host type not supported for MTIOCTOP\n" msgstr "rmtioctl: Ferner Rechnertyp nicht für MTIOCTOP unterstützt\n" #: .././librmt/rmtioctl.c:247 msgid "rmtioctl: remote host type not supported for MTIOCGET\n" msgstr "rmtioctl: Ferner Rechnertyp nicht für MTIOCGET unterstützt\n" #: .././librmt/rmtioctl.c:253 #, c-format msgid "rmtioctl: IRIX mtget structure of wrong size - got %d, wanted %d\n" msgstr "" "rmtioctl: IRIX-mtget-Struktur mit falscher Größe - %d erhalten, %d gesucht\n" #: .././librmt/rmtioctl.c:269 #, c-format msgid "" "rmtioctl: Linux mtget structure of wrong size - got %d, wanted %d or %d\n" msgstr "" "rmtioctl: Linux-mtget-Struktur mit falscher Größe - %d erhalten,\n" "%d oder %d gesucht\n" #: .././librmt/rmtmsg.c:78 msgid "WARNING: " msgstr "WARNUNG: " #: .././librmt/rmtopen.c:176 #, c-format msgid "rmtopen: failed to detect remote host type using \"%s\"\n" msgstr "" "rmtopen: Ermitteln des fernen Rechnertyps unter Benutzung von »%s« " "fehlgeschlagen\n" #: .././librmt/rmtopen.c:188 #, c-format msgid "rmtopen: failed to detect remote host type reading \"%s\"\n" msgstr "" "rmtopen: Ermitteln des fernen Rechnertyps durch Lesen von »%s« " "fehlgeschlagen\n" #: .././librmt/rmtopen.c:205 #, c-format msgid "rmtopen: remote host type, \"%s\", is unknown to librmt\n" msgstr "rmtopen: ferner Rechnertyp »%s« ist »librmt« unbekannt\n" #: .././restore/dirattr.c:232 #, c-format msgid "could not find directory attributes file %s: %s\n" msgstr "Datei mit Verzeichnisattributen %s konnte nicht gefunden werden: %s\n" #: .././restore/dirattr.c:248 #, c-format msgid "could not create directory attributes file %s: %s\n" msgstr "Datei mit Verzeichnisattributen %s konnte nicht erstellt werden: %s\n" #: .././restore/dirattr.c:293 .././restore/namreg.c:212 #, c-format msgid "attempt to reserve %lld bytes for %s using %s failed: %s (%d)\n" msgstr "" "Versuch, %lld Byte für %s unter Benutzung von %s zu reservieren, " "fehlgeschlagen: %s (%d)\n" #: .././restore/dirattr.c:322 .././restore/inomap.c:233 #: .././restore/inomap.c:398 .././restore/namreg.c:241 .././restore/tree.c:420 #: .././restore/tree.c:582 #, c-format msgid "unable to map %s: %s\n" msgstr "%s kann nicht abgebildet werden: %s\n" #: .././restore/dirattr.c:409 .././restore/dirattr.c:801 #: .././restore/dirattr.c:1004 .././restore/dirattr.c:1081 #, c-format msgid "lseek of dirattr failed: %s\n" msgstr "lseek von dirattr fehlgeschlagen: %s\n" #: .././restore/dirattr.c:493 .././restore/dirattr.c:644 #, c-format msgid "could not open/create directory extended attributes file %s: %s (%d)\n" msgstr "" "erweiterte Verzeichnis-Attributsdatei %s konnte nicht geöffnet/erstellt " "werden: %s (%d)\n" #: .././restore/dirattr.c:512 .././restore/dirattr.c:593 #: .././restore/dirattr.c:670 #, c-format msgid "could not seek to into extended attributes file %s: %s (%d)\n" msgstr "" "in erweiterter Verzeichnis-Attributsdatei %s konnte nicht gesucht werden: %s " "(%d)\n" #: .././restore/dirattr.c:530 .././restore/dirattr.c:688 #: .././restore/dirattr.c:705 .././restore/dirattr.c:724 #, c-format msgid "could not read extended attributes file %s: %s (%d)\n" msgstr "" "erweiterte Verzeichnis-Attributsdatei %s konnte nicht gelesen werden: %s " "(%d)\n" #: .././restore/dirattr.c:546 #, c-format msgid "could not seek to end of extended attributes file %s: %s (%d)\n" msgstr "" "es konnte nicht bis zum Ende der erweiterten Attributsdatei %s gesucht " "werden: %s (%d)\n" #: .././restore/dirattr.c:561 .././restore/dirattr.c:608 #, c-format msgid "could not write extended attributes file %s: %s (%d)\n" msgstr "" "erweiterte Attributsdatei %s konnte nicht geschrieben werden: %s (%d)\n" #: .././restore/dirattr.c:573 #, c-format msgid "could not write at end of extended attributes file %s: %s (%d)\n" msgstr "" "es konnte nicht am Ende der erweiterten Attributsdatei %s geschrieben " "werden: %s (%d)\n" #: .././restore/dirattr.c:827 #, c-format msgid "update of dirattr failed: %s\n" msgstr "Aktualisieren von »dirattr« fehlgeschlagen: %s\n" #: .././restore/dirattr.c:935 #, c-format msgid "write of dirattr buffer failed: %s\n" msgstr "Schreiben des »dirattr«-Puffers fehlgeschlagen: %s\n" #: .././restore/dirattr.c:939 #, c-format msgid "" "write of dirattr buffer failed: expected to write %ld, actually wrote %ld\n" msgstr "" "Schreiben des »dirattr«-Puffers fehlgeschlagen: Erwartet %ld zu schreiben, " "tatsächlich %ld\n" #: .././restore/dirattr.c:1017 #, c-format msgid "read of dirattr failed: %s\n" msgstr "Lesen von »dirattr« fehlgeschlagen: %s\n" #: .././restore/dirattr.c:1094 #, c-format msgid "flush of dirattr failed: %s\n" msgstr "Leeren von »dirattr« fehlgeschlagen: %s\n" #: .././restore/inomap.c:377 #, c-format msgid "unable to map %s hdr: %s\n" msgstr "%s-hdr kann nicht abgebildet werden: %s\n" #: .././restore/namreg.c:151 #, c-format msgid "could not find name registry file %s: %s\n" msgstr "Namensregistrierungsdatei %s konnte nicht gefunden werden: %s\n" #: .././restore/namreg.c:167 #, c-format msgid "could not create name registry file %s: %s\n" msgstr "Namensregistrierungsdatei %s konnte nicht erstellt werden: %s\n" #: .././restore/namreg.c:352 #, c-format msgid "write of namreg buffer failed: %s\n" msgstr "Schreiben des »namereg«-Puffers fehlgeschlagen: %s\n" #: .././restore/namreg.c:356 #, c-format msgid "" "write of namreg buffer failed: expected to write %ld, actually wrote %ld\n" msgstr "" "Schreiben des »namereg«-Puffers fehlgeschlagen: Erwartet %ld zu schreiben, " "tatsächlich %ld\n" #: .././restore/node.c:266 .././restore/node.c:354 #, c-format msgid "unable to map node hdr of size %d: %s\n" msgstr "Knoten-»hdr« der Größe %d kann nicht abgebildet werden: %s\n" #: .././restore/node.c:303 #, c-format msgid "unable to autogrow first node segment: %s (%d)\n" msgstr "erstes Knotensegment kann nicht automatisch anwachsen: %s (%d)\n" #: .././restore/node.c:483 #, c-format msgid "unable to autogrow node segment %llu: %s (%d)\n" msgstr "Knotensegment %llu kann nicht automatisch anwachsen: %s (%d)\n" #: .././restore/tree.c:380 #, c-format # FIXME initiating msgid "%s already exists: rm -rf prior to initating restore\n" msgstr "%s exisitiert bereits: »rm -rf« vor Beginn der Wiederherstellung\n" #: .././restore/tree.c:552 #, c-format msgid "unable to recreate %s: %s\n" msgstr "%s kann nicht wieder erstellt werden: %s\n" #: .././restore/tree.c:1233 msgid "noref debug" msgstr "»noref«-Fehlersuche" #: .././restore/tree.c:1265 .././restore/tree.c:1471 msgid "rmdir" msgstr "rmdir" #: .././restore/tree.c:1280 .././restore/tree.c:2579 #, c-format msgid "unable to rmdir %s: %s\n" msgstr "»rmdir %s« kann nicht ausgeführt werden: %s\n" #: .././restore/tree.c:1302 msgid "tmp dir rename src" msgstr "tmp dir rename src" #: .././restore/tree.c:1312 msgid "tmp dir rename dst" msgstr "tmp dir rename dst" #: .././restore/tree.c:1331 .././restore/tree.c:1643 #, c-format msgid "unable to rename dir %s to dir %s: %s\n" msgstr "Verzeichnis %s kann nicht in %s umbenannt werden: %s\n" #: .././restore/tree.c:1420 msgid "tmp nondir rename src" msgstr "tmp nondir rename src" #: .././restore/tree.c:1430 msgid "tmp nondir rename dst" msgstr "tmp nondir rename dst" #: .././restore/tree.c:1449 #, c-format msgid "unable to rename nondir %s to nondir %s: %s\n" msgstr "»nondir %s« kann nicht zu »nondir %s« umbenannt werden: %s\n" #: .././restore/tree.c:1486 #, c-format msgid "unable to unlink nondir %s: %s\n" msgstr "»nondir %s« kann nicht gelöscht werden: %s\n" #: .././restore/tree.c:1536 msgid "makedir" msgstr "makedir" #: .././restore/tree.c:1550 #, c-format msgid "mkdir %s failed: %s\n" msgstr "»mkdir %s« fehlgeschlagen: %s\n" #: .././restore/tree.c:1617 .././restore/tree.c:1625 msgid "rename dir" msgstr "Verzeichnis umbenennen" #: .././restore/tree.c:1712 msgid "restore" msgstr "wiederherstellen" #: .././restore/tree.c:1733 #, c-format msgid "cannot restore %s (ino %llu gen %u): pathname contains %s\n" msgstr "" "%s (Ino %llu Gen %u) kann nicht wiederhergestellt werden: Pfadname enthält " "%s\n" #: .././restore/tree.c:1777 #, c-format msgid "unable to unlink current file prior to restore: %s: %s: discarding\n" msgstr "" "aktuelle Datei kann nicht vor der Wiederherstellung gelöscht werden: %s: %s: " "Wird verworfen\n" #: .././restore/tree.c:1871 #, c-format msgid "ino %llu salvaging file, placing in %s\n" msgstr "Ino %llu rettet Datei, wird in %s platziert\n" #: .././restore/tree.c:1881 #, c-format msgid "ino %llu gen %u not referenced: placing in orphanage\n" msgstr "Ino %llu Gen %u ohne Bezug: Wird bei Verwaisten platziert\n" #: .././restore/tree.c:1892 #, c-format msgid "node allocation failed when placing ino %llu in orphanage\n" msgstr "" "Knotenreservierung beim Platzieren von Ino %llu bei Verwaisten \n" "fehlgeschlagen\n" #: .././restore/tree.c:1898 msgid "orphan" msgstr "Waise" #: .././restore/tree.c:2032 msgid "set dir extattr" msgstr "Verzeichnis-»extattr« setzen" #: .././restore/tree.c:2034 #, c-format msgid "tree_extattr_recurse: Could not convert node to path for %s\n" msgstr "" "tree_extattr_recurse: Konvertieren von Knoten zu Pfad für %s nicht möglich\n" #: .././restore/tree.c:2226 msgid "rename to" msgstr "umbenennen in" #: .././restore/tree.c:2246 msgid "rename from" msgstr "umbenennen von" #: .././restore/tree.c:2264 #, c-format msgid "unable to rename nondir %s to %s: %s\n" msgstr "»nondir« %s kann nicht in %s umbenannt werden: %s\n" #: .././restore/tree.c:2285 msgid "link" msgstr "verknüpfen" #: .././restore/tree.c:2289 #, c-format msgid "unable to use %s as a hard link source\n" msgstr "%s kann nicht als Quelle für Hard-Link benutzt werden\n" #: .././restore/tree.c:2346 msgid "unlink" msgstr "löschen" #: .././restore/tree.c:2362 #, c-format msgid "unable to unlink %s: %s\n" msgstr "%s kann nicht gelöscht werden: %s\n" #: .././restore/tree.c:2433 msgid "set dirattr" msgstr "»dirattr« setzen" #: .././restore/tree.c:2463 .././restore/content.c:9538 #, c-format msgid "path_to_handle of %s failed:%s\n" msgstr "path_to_handle von %s fehlgeschlagen: %s\n" #: .././restore/tree.c:2469 #, c-format msgid "open_by_handle of %s failed:%s\n" msgstr "open_by_handle von %s fehlgeschlagen: %s\n" #: .././restore/tree.c:2506 #, c-format msgid "could not set access and modification times of %s: %s\n" msgstr "" "Zugriffs- und Änderungszeiten von %s konnten nicht gesetzt werden: %s\n" #: .././restore/tree.c:2518 #, c-format msgid "chown (uid=%d, gid=%d) %s failed: %s\n" msgstr "chown (uid=%d, gid=%d) %s fehlgeschlagen: %s\n" #: .././restore/tree.c:2528 #, c-format msgid "chmod %s failed: %s\n" msgstr "chmod %s fehlgeschlagen: %s\n" #: .././restore/tree.c:2548 #, c-format msgid "" "attempt to set extended attributes (xflags 0x%x, extsize = 0x%x, projid = 0x%" "x) of %s failed: %s\n" msgstr "" "Versuch erweiterte Attribute (xflags 0x%x, extsize = 0x%x, projid = 0x%x) " "von %s zu setzen fehlgeschlagen: %s\n" #: .././restore/tree.c:2575 #, c-format msgid "unable to rmdir %s: not empty\n" msgstr "»rmdir %s« kann nicht ausgeführt werden: Nicht leer\n" #: .././restore/tree.c:2631 msgid "subtree selection dialog" msgstr "Teilbaum-Auswahldialog" #: .././restore/tree.c:2669 msgid "abort\n" msgstr "Abbrechen\n" #: .././restore/tree.c:2736 msgid "Unmark and quit\n" msgstr "Markierung entfernen und beenden\n" #: .././restore/tree.c:2920 .././restore/tree.c:4880 #, c-format msgid "%s is not a directory\n" msgstr "%s ist kein Verzeichnis\n" #: .././restore/tree.c:3139 msgid "the following commands are available:\n" msgstr "die folgenden Befehle sind verfügbar:\n" #: .././restore/tree.c:3258 #, c-format msgid "parent of %s is not a directory\n" msgstr "übergeordnetes Element von %s ist kein Verzeichnis\n" #: .././restore/tree.c:3279 #, c-format msgid "%s above root\n" msgstr "%s oberhalb der Wurzel\n" #: .././restore/tree.c:3333 #, c-format msgid "%s not found\n" msgstr "%s nicht gefunden\n" #: .././restore/tree.c:3419 #, c-format msgid "failed to map in node (node handle: %u)\n" msgstr "Abbilden in Knoten fehlgeschlagen (Knoten-Handle: %u)\n" #: .././restore/tree.c:3446 #, c-format msgid "unable %s ino %llu gen %u: relative pathname too long (partial %s)\n" msgstr "" "%s Ino %llu Gen %u nicht möglich: Relativer Pfadname zu lang (partiell %s)\n" #: .././restore/tree.c:3580 msgid "attempt to disown child which has no parent!\n" msgstr "" "Versuch von »disown« für untergeordnetes Element, das kein übergeordnetes " "Element hat!\n" #: .././restore/tree.c:3588 msgid "attempt to disown child when parent has no children!\n" msgstr "" "Versuch von »disown« für untergeordnetes Element, wenn übergeordnetes " "Element keine untergeordneten Elemente hat!\n" #: .././restore/tree.c:4089 .././restore/tree.c:4135 #, c-format msgid "unable to mmap hash array into %s: %s\n" msgstr "»mmap« für Hash-Array in %s nicht möglich: %s\n" #: .././restore/tree.c:4360 #, c-format msgid "nh 0x%x np 0x%x hash link not null\n" msgstr "nh 0x%x np 0x%x Hash-Verknüpfung nicht null\n" #: .././restore/tree.c:4512 #, c-format msgid "node %x %s %llu %u parent NULL\n" msgstr "Knoten %x %s %llu %u übergeordnetes Element NULL\n" #: .././restore/tree.c:4520 #, c-format msgid "node %x %s %llu %u parent mismatch: nodepar %x par %x\n" msgstr "" "Knoten %x %s %llu %u übergeordnetes Element passt nicht: Nodepar %x par %x\n" #: .././restore/win.c:287 msgid "all map windows in use. Check virtual memory limits\n" msgstr "" "alle Abbildungsfenster im Gebrauch. Prüfen Sie die Beschränkungen des " "virtuellen Speichers\n" #: .././restore/win.c:312 #, c-format msgid "win_map(): unable to map a node segment of size %d at %d: %s\n" msgstr "" "win_map(): Ein Knotensegment der Größe %d bei %d kann nicht abgebildet " "werden: %s\n" #: .././restore/win.c:323 msgid "win_map(): try to select a different win_t\n" msgstr "win_map(): Es wird versucht ein anderes »win_t« auszuwählen\n" #: .././restore/content.c:937 #, c-format msgid "unable to get status of -%c argument %s: %s\n" msgstr "Status des -%c-Arguments %s kann nicht geholt werden: %s\n" #: .././restore/content.c:966 #, c-format msgid "-%c argument %s is an invalid pathname\n" msgstr "-%c-Argument %s ist ein ungültiger Pfadname\n" #: .././restore/content.c:984 #, c-format msgid "cannot stat -%c argument %s (%s): %s\n" msgstr "»stat« kann nicht für -%c-Argument %s (%s) ausgeführt werden: %s\n" #: .././restore/content.c:994 #, c-format msgid "-%c argument %s (%s) is not a directory\n" msgstr " -%c-Argument %s (%s) ist kein Verzeichnis\n" #: .././restore/content.c:1026 #, c-format msgid "-%c argument %s too long: max is %d\n" msgstr " -%c-Argument %s ist zu lang: Maximum ist %d\n" #: .././restore/content.c:1075 #, c-format msgid "-%c argument must be relative\n" msgstr " -%c-Argument muss relativ sein\n" #: .././restore/content.c:1099 #, c-format msgid "-%c unavailable: no /dev/tty\n" msgstr "-%c nicht verfügbar: Kein /dev/tty\n" #: .././restore/content.c:1142 .././restore/content.c:1150 #, c-format msgid "-%c and -%c option cannot be used together\n" msgstr "Optionen -%c und -%c können nicht zusammen benutzt werden\n" #: .././restore/content.c:1179 #, c-format msgid "destination directory %s invalid pathname\n" msgstr "Zielverzeichnis %s ungültiger Pfadname\n" #: .././restore/content.c:1196 #, c-format msgid "cannot stat destination directory %s: %s\n" msgstr "Zielverzeichnis %s kann nicht mit »stat« abgefragt werden: %s\n" #: .././restore/content.c:1205 #, c-format msgid "specified destination %s is not a directory\n" msgstr "angegebenes Ziel %s ist kein Verzeichnis\n" #: .././restore/content.c:1215 #, c-format msgid "" "do not specify destination directory if contents only restore invoked (-%c " "option)\n" msgstr "" "geben Sie das Zielverzeicnis nicht an, wenn Inhalte nur wiederhergestellt " "aufgerufen werden (Option -%c)\n" #: .././restore/content.c:1238 .././restore/content.c:1307 msgid "destination directory not specified\n" msgstr "Zielverzeichnis nicht angegeben\n" #: .././restore/content.c:1285 #, c-format msgid "could not open/create persistent state file %s: %s\n" msgstr "beständige Statusdatei %s kann nicht geöffnet/erstellt werden: %s\n" #: .././restore/content.c:1299 #, c-format msgid "could not map persistent state file hdr %s: %s\n" msgstr "beständiger Statusdatei-Hdr %s kann nicht abgebildet werden: %s\n" #: .././restore/content.c:1313 #, c-format msgid "destination directory pathname too long: max is %d characters\n" msgstr "Zielverzeichnis-Pfadname zu lang: Maximal %d Zeichen\n" #: .././restore/content.c:1321 .././restore/content.c:1346 #, c-format msgid "-%c option invalid: there is no interrupted restore to resume\n" msgstr "" "Option -%c ungültig: Es gibt keine unterbrochene Wiederherstellung zur " "Wiederaufnahme\n" #: .././restore/content.c:1330 .././restore/content.c:1355 #, c-format msgid "" "-%c option invalid: there is no interrupted restore to force completion of\n" msgstr "" "Option -%c ungültig: Es gibt keine unterbrochene Wiederherstellung, um die " "Komplettierung zu erzwingen von\n" #: .././restore/content.c:1340 #, c-format msgid "must rm -rf %s prior to noncumulative restore\n" msgstr "" "vor nicht-kumulativer Wiederherstellung muss »rm -rf %s« ausgeführt werden\n" #: .././restore/content.c:1364 .././restore/content.c:1371 #: .././restore/content.c:1378 .././restore/content.c:1385 #, c-format msgid "-%c valid only when initiating cumulative restore\n" msgstr "-%c ist nur gültig, wenn kumulative Wiederherstellung gestartet wird\n" #: .././restore/content.c:1392 #, c-format msgid "-%c and -%c valid only when initiating cumulative restore\n" msgstr "" "-%c und -%c sind nur gültig, wenn kumulative Wiederherstellung gestartet " "wird\n" #: .././restore/content.c:1402 #, c-format msgid "" "-%c option required to resume or -%c option required to force completion of " "previously interrupted restore session\n" msgstr "" "Option -%c zum Fortfahren erforderlich oder Option -%c benötigt, um die " "Vervollständigung von vorher unterbrochenen Wiederherstellungssitzungen zu " "erzwingen\n" #: .././restore/content.c:1414 #, c-format msgid "-%c option required to resume previously interrupted restore session\n" msgstr "" "Option -%c zum Fortsetzen von vorher unterbrochener " "Wiederherstellungssitzung benötigt\n" #: .././restore/content.c:1422 .././restore/content.c:1428 #: .././restore/content.c:1434 .././restore/content.c:1440 #: .././restore/content.c:1446 .././restore/content.c:1452 #: .././restore/content.c:1458 #, c-format msgid "-%c valid only when initiating restore\n" msgstr "-%c ist nur gültig, wenn Wiederherstellung gestartet wird\n" #: .././restore/content.c:1464 #, c-format msgid "-%c and -%c valid only when initiating restore\n" msgstr "-%c und -%c sind nur gültig, wenn Wiederherstellung gestartet wird\n" #: .././restore/content.c:1474 .././restore/content.c:1481 #, c-format msgid "-%c cannot reset flag from previous restore\n" msgstr "" "-%c kann Markierung von vorheriger Wiederherstellung nicht zurücksetzen\n" #: .././restore/content.c:1509 .././restore/content.c:1848 #, c-format msgid "chdir %s failed: %s\n" msgstr "chdir %s fehlgeschlagen: %s\n" #: .././restore/content.c:1580 #, c-format msgid "resuming restore previously begun %s\n" msgstr "vorher begonnene Wiederherstellung %s wird fortgesetzt\n" #: .././restore/content.c:1600 #, c-format msgid "could not map persistent state file %s: %s\n" msgstr "beständige Statusdatei %s konnte nicht abgebildet werden: %s\n" #: .././restore/content.c:1715 #, c-format msgid "could not map persistent state file inv %s: %s (%d)\n" msgstr "" "beständige Statusdatei-Inv %s konnte nicht abgebildet werden: %s (%d)\n" #: .././restore/content.c:1927 msgid "searching media for dump\n" msgstr "Medium zur Ausgabe wird gesucht\n" #: .././restore/content.c:1999 msgid "found dump matching specified id:\n" msgstr "zur angegebenen ID passende Ausgabe gefunden:\n" #: .././restore/content.c:2013 msgid "found dump matching specified label:\n" msgstr "zur angegebenen Kennung passende Ausgabe gefunden:\n" #: .././restore/content.c:2044 msgid "dump description: \n" msgstr "Ausgabebeschreibung: \n" #: .././restore/content.c:2090 .././restore/content.c:3633 msgid "using online session inventory\n" msgstr "Online-Sitzungsbestand wird benutzt\n" #: .././restore/content.c:2123 msgid "searching media for directory dump\n" msgstr "Medium zur Verzeichnisausgabe wird gesucht\n" #: .././restore/content.c:2258 msgid "reading directories\n" msgstr "Verzeichnisse werden gelesen\n" #: .././restore/content.c:2328 msgid "directory post-processing\n" msgstr "Vorverarbeitung des Verzeichnisses\n" #: .././restore/content.c:2407 msgid "reading non-directory files\n" msgstr "Nicht-Verzeichnisdateien werden gelesen\n" #: .././restore/content.c:2410 msgid "restoring non-directory files\n" msgstr "Nicht-Verzeichnisdateien werden wiederhergestellt\n" #: .././restore/content.c:2539 #, c-format msgid "table of contents display complete: %ld seconds elapsed\n" msgstr "" "Anzeige des Inhaltsverzeichnisses vollständig: %ld Sekunden verstrichen\n" #: .././restore/content.c:2558 msgid "use 'xfs_quota' to restore quotas\n" msgstr "benutzen Sie zum Wiederherstellen von Quotas »xfs_quota«\n" #: .././restore/content.c:2561 #, c-format msgid "restore complete: %ld seconds elapsed\n" msgstr "Wiederherstellung vollständig: %ld Sekunden verstrichen\n" #: .././restore/content.c:2568 #, c-format msgid "table of contents display interrupted: %ld seconds elapsed\n" msgstr "" "Anzeige des Inhaltsverzeichnisses unterbrochen: %ld Sekunden verstrichen\n" #: .././restore/content.c:2574 #, c-format msgid "" "restore interrupted: %ld seconds elapsed: may resume later using -%c option\n" msgstr "" "Wiederherstellung unterbrochen: %ld Sekunden verstrichen: Könnte später " "unter Benutzung der Option -%c fortfahren\n" #: .././restore/content.c:2645 #, c-format msgid "" "status at %02d:%02d:%02d: %llu/%llu directories reconstructed, %.1f%%%% " "complete, %llu directory entries processed, %ld seconds elapsed\n" msgstr "" "Status bei %02d:%02d:%02d: %llu/%llu Verzeichnisse rekonstruiert, %.1f%%%% " "komplett, %llu Verzeichniseinträge verarbeitet, %ld Sekunden verstrichen\n" #: .././restore/content.c:2688 #, c-format msgid "" "status at %02d:%02d:%02d: %llu/%llu files restored, %.1f%%%% complete, %ld " "seconds elapsed\n" msgstr "" "Status bei %02d:%02d:%02d: %llu/%llu Dateien rekonstruiert, %.1f%%%% " "komplett, %ld Sekunden verstrichen\n" #: .././restore/content.c:2765 msgid "select a drive to acknowledge media change\n" msgstr "wählen Sie ein Laufwerk, um den Medienwechsel zu bestätigen\n" #: .././restore/content.c:2772 #, c-format msgid "drive %u" msgstr "Laufwerk %u" #: .././restore/content.c:2782 msgid "display needed media objects" msgstr "Benötigte Medienobjekte anzeigen" #: .././restore/content.c:2802 msgid "media change acknowledged\n" msgstr "Bestätigung des Medienwechsels\n" #: .././restore/content.c:3036 #, c-format msgid "%llu directories and %llu entries processed\n" msgstr "%llu Verzeichnisse und %llu Einträge verarbeitet\n" #: .././restore/content.c:3258 #, c-format msgid "subtree argument %s invalid\n" msgstr "Teilbaumargument %s ungültig\n" #: .././restore/content.c:3388 .././restore/content.c:3441 msgid "" "unable to resync media file: some portion of dump will NOT be restored\n" msgstr "" "Mediendatei kann nicht erneut synchronisiert werden: Einige Teile der " "Ausgabe werden NICHT wiederhergestellt\n" #: .././restore/content.c:3453 #, c-format msgid "resynchronization achieved at ino %llu offset %lld\n" msgstr "erneute Synchronisation bei Ino %llu, Versatz %lld erreicht\n" #: .././restore/content.c:3901 .././restore/content.c:4178 #: .././restore/content.c:4288 .././restore/content.c:4321 #: .././restore/content.c:4386 .././restore/content.c:4539 msgid "rewinding\n" msgstr "wird zurückgespult\n" #: .././restore/content.c:3926 #, c-format msgid "examining media file %u\n" msgstr "Mediendatei %u wird untersucht\n" #: .././restore/content.c:4098 #, c-format msgid "" "inventory session uuid (%s) does not match the media header's session uuid (%" "s)\n" msgstr "" "Bestandssitzungs-UUID (%s) passt nicht zu der " "Medienkopfzeilen-Sitzungs-UUID (%s)\n" #: .././restore/content.c:4433 msgid "seeking past portion of media file already restored\n" msgstr "" "es wird nach früherem Teil der bereits wiederhergestellten Mediendatei " "gesucht\n" #: .././restore/content.c:4452 .././restore/content.c:4471 msgid "seeking past media file directory dump\n" msgstr "es wird nach früherer Ausgabe des Mediendateiverzeichnisses gesucht\n" #: .././restore/content.c:4630 msgid "media object not useful\n" msgstr "Medienobjekt nicht nützlich\n" #: .././restore/content.c:4633 msgid "media object empty\n" msgstr "Medienobjekt leer\n" #: .././restore/content.c:4636 msgid "all media files examined, none selected for restoral\n" msgstr "" "alle Mediendateien wurden untersucht, keines wurde für die Wiederherstellung " "ausgewählt\n" #: .././restore/content.c:4826 #, c-format msgid "could not remap persistent state file inv %s: %d (%s)\n" msgstr "" "beständige Statusdatei-Inv %s konnte nicht erneut abgebildet werden: %d " "(%s)\n" #: .././restore/content.c:5345 msgid "on-media session inventory corrupt\n" msgstr "Sitzungsbestand auf dem Medium beschädigt\n" #: .././restore/content.c:5354 msgid "incorporating on-media session inventory into online inventory\n" msgstr "Sitzungsbestand auf dem Medium wird in Online-Bestand aufgenommen\n" #: .././restore/content.c:6338 #, c-format msgid "" "hit EOD at stream %u object %u, yet inventory indicates last object index is " "%u\n" msgstr "" "drücken Sie EOD (Datenende) bei Datenstrom %u, Objekt %u, Bestand zeigt " "schon an, dass letzter Objektindex %u ist\n" #: .././restore/content.c:6404 #, c-format msgid "" "hit next dump at stream %u object %u file %u, yet inventory indicates last " "object index is %u\n" msgstr "" "starten Sie auf die nächste Ausgabe bei Datenstrom %u, Objekt %u, Datei %u, " "Bestand zeigt schon an, dass letzter Objektindex %u ist\n" #: .././restore/content.c:6686 msgid "unable to open inventory to validate dump\n" msgstr "Bestand kann nicht geöffnet werden, um Ausgabe zu überprüfen\n" #: .././restore/content.c:6703 msgid "unable to find base dump in inventory to validate dump\n" msgstr "" "Basisausgabe kann nicht im Bestand gefunden werden, um Ausgabe zu " "überprüfen\n" #: .././restore/content.c:6732 msgid "" "cumulative restores must begin with an initial (not resumed) level 0 dump\n" msgstr "" "kumulative Wiederherstellungen müssen mit einer anfänglichen (nicht " "fortgesetzten) Ausgabe der Stufe 0 beginnen\n" #: .././restore/content.c:6741 msgid "cumulative restores must begin with a level 0 dump\n" msgstr "" "kumulative Wiederherstellungen müssen mit einer Ausgabe der Stufe 0 " "beginnen\n" #: .././restore/content.c:6752 msgid "selected resumed dump not a resumption of previously applied dump\n" msgstr "" "ausgewählte fortgesetzte Ausgabe ist keine Fortsetzung der vorher " "zugrundegelegten Ausgabe\n" #: .././restore/content.c:6763 msgid "selected dump not based on previously applied dump\n" msgstr "" "ausgewählte Ausgabe basiert nicht auf einer vorher zugrundegelegten Ausgabe\n" #: .././restore/content.c:6823 #, c-format msgid "please change media in drive\n" msgstr "bitte wechseln Sie das Medium im Laufwerk\n" #: .././restore/content.c:6834 msgid "display media inventory status" msgstr "Medienbestandsstatus anzeigen" #: .././restore/content.c:6836 msgid "list needed media objects" msgstr "Benötigte Medienobjekte auflisten" #: .././restore/content.c:6963 msgid "dump selection dialog" msgstr "Ausgabe-Auswahldialog" #: .././restore/content.c:6974 #, c-format msgid "" "the following dump has been found on drive %u\n" "\n" msgstr "" "die folgende Ausgabe wurde auf dem Laufwerk %u gefunden\n" "\n" #: .././restore/content.c:6980 #, c-format msgid "" "the following dump has been found\n" "\n" msgstr "" "die folgende Ausgabe wurde gefunden\n" "\n" #: .././restore/content.c:6994 msgid "" "\n" "examine this dump?\n" msgstr "" "\n" "diese Ausgabe untersuchen?\n" #: .././restore/content.c:6997 msgid "" "\n" "interactively restore from this dump?\n" msgstr "" "\n" "interaktiv aus dieser Ausgabe wiederherstellen?\n" #: .././restore/content.c:6998 msgid "" "\n" "restore this dump?\n" msgstr "" "\n" "diese Ausgabe wiederherstellen?\n" #: .././restore/content.c:7003 msgid "skip" msgstr "überspringen" #: .././restore/content.c:7006 msgid "interactively restore\n" msgstr "interaktiv wiederherstellen\n" #: .././restore/content.c:7006 msgid "restore\n" msgstr "wiederherstellen\n" #: .././restore/content.c:7026 msgid "this dump selected for interactive restoral\n" msgstr "diese Ausgabe ist für die interaktive Wiederherstellung ausgewählt\n" #: .././restore/content.c:7027 msgid "this dump selected for restoral\n" msgstr "diese Ausgabe ist für die Wiederherstellung ausgewählt\n" #: .././restore/content.c:7029 msgid "dump skipped\n" msgstr "Ausgabe übersprungen\n" #: .././restore/content.c:7189 #, c-format msgid "ino %llu: unknown file type: %08x\n" msgstr "Ino %llu: Unbekannter Dateityp: %08x\n" #: .././restore/content.c:7204 #, c-format msgid "unable to unlink current file prior to linking %s to %s: %s\n" msgstr "" "aktuelle Datei kann nicht gelöscht werden bevor %s mit %s verknüpft wird: " "%s\n" #: .././restore/content.c:7215 #, c-format msgid "attempt to link %s to %s failed: %s\n" msgstr "Versuch, %s mit %s zu verknüpfen, fehlgeschlagen: %s\n" #: .././restore/content.c:7265 #, c-format msgid "%s (offset %lld)\n" msgstr "%s (Versatz %lld)\n" #: .././restore/content.c:7292 #, c-format msgid "open of %s failed: %s: discarding ino %llu\n" msgstr "Öffnen von %s fehlgeschlagen: %s: Ino %llu wird verworfen\n" #: .././restore/content.c:7302 #, c-format msgid "attempt to stat %s failed: %s\n" msgstr "Versuch, %s mit »stat« abzufragen, fehlgeschlagen: %s\n" #: .././restore/content.c:7316 #, c-format msgid "attempt to truncate %s failed: %s\n" msgstr "Versuch, %s zu kürzen, fehlgeschlagen: %s\n" #: .././restore/content.c:7493 .././restore/content.c:7760 #, c-format msgid "unable to set access and modification times of %s: %s\n" msgstr "" "Zugriffs- und Veränderungszeiten von %s können nicht gesetzt werden: %s\n" #: .././restore/content.c:7509 .././restore/content.c:7734 #: .././restore/content.c:7889 #, c-format msgid "chown (uid=%u, gid=%u) %s failed: %s\n" msgstr "chown (uid=%u, gid=%u) %s fehlgeschlagen: %s\n" #: .././restore/content.c:7517 #, c-format msgid "stripping setuid bit on %s since chown failed\n" msgstr "Setuid-Bit von %s wird entfernt, da »chown« fehlgeschlagen ist\n" #: .././restore/content.c:7524 #, c-format msgid "stripping setgid bit on %s since chown failed\n" msgstr "Setgid-Bit von %s wird entfernt, da »chown« fehlgeschlagen ist\n" #: .././restore/content.c:7533 #, c-format msgid "unable to strip setuid/setgid on %s, unlinking file.\n" msgstr "" "Setuid/Setgid auf %s konnte nicht entfernt werden, Datei wird gelöscht.\n" #: .././restore/content.c:7547 .././restore/content.c:7748 #, c-format msgid "unable to set mode of %s: %s\n" msgstr "Modus von %s kann nicht gesetzt werden: %s\n" #: .././restore/content.c:7563 #, c-format msgid "attempt to set DMI attributes of %s failed: %s\n" msgstr "Versuch, die DMI-Attribute von %s zu setzen, fehlgeschlagen: %s\n" #: .././restore/content.c:7615 msgid "block special file" msgstr "spezielle Blockdatei" #: .././restore/content.c:7618 msgid "char special file" msgstr "spezielle Zeichendatei" #: .././restore/content.c:7621 msgid "named pipe" msgstr "benannte Weiterleitung" #: .././restore/content.c:7625 msgid "XENIX named pipe" msgstr "XENIX benannte Weiterleitung" #: .././restore/content.c:7630 msgid "UNIX domain socket" msgstr "Unix-Domänen-Socket" #: .././restore/content.c:7635 #, c-format msgid "%s: unknown file type: mode 0x%x ino %llu\n" msgstr "%s: Unbekannter Dateityp: Modus 0x%x Ino %llu\n" #: .././restore/content.c:7664 .././restore/content.c:7714 #, c-format msgid "unable to create %s ino %llu %s: %s: discarding\n" msgstr " %s Ino %llu %s kann nicht erstellt werden: %s: Wird verworfen\n" #: .././restore/content.c:7676 #, c-format msgid "pathname too long for bind of %s ino %llu %s: %s: discarding\n" msgstr "" "Pfadname zu lang für Verbindung von %s Ino %llu %s: %s: Wird verworfen\n" #: .././restore/content.c:7693 #, c-format msgid "unable to bind %s ino %llu %s: %s: discarding\n" msgstr "%s Ino %llu %s kann nicht verbunden werden: %s: Wird verworfen\n" #: .././restore/content.c:7849 #, c-format msgid "unable to create symlink ino %llu %s: src too long: discarding\n" msgstr "" "Symlink Ino %llu %s kann nicht erstellt werden: Src zu lang: Wird " "verworfen\n" #: .././restore/content.c:7873 #, c-format msgid "unable to create symlink ino %llu %s: %s: discarding\n" msgstr "Symlink Ino %llu %s kann nicht erstellt werden: %s: Wird verworfen\n" #: .././restore/content.c:7966 msgid "corrupt file header\n" msgstr "Beschädigte Dateikopfzeilen\n" #: .././restore/content.c:7972 msgid "bad file header checksum\n" msgstr "falsche Dateikopfzeilen-Prüfsumme\n" #: .././restore/content.c:8033 msgid "corrupt extent header\n" msgstr "Beschädigte Bereichs-Dateikopfzeilen\n" #: .././restore/content.c:8039 msgid "bad extent header checksum\n" msgstr "falsche Prüfsumme der Bereichs-Dateikopfzeilen\n" #: .././restore/content.c:8105 msgid "corrupt directory entry header\n" msgstr "beschädigte Verzeichniseintrags-Kopfzeilen\n" #: .././restore/content.c:8111 msgid "bad directory entry header checksum\n" msgstr "falsche Prüfsumme der Verzeichniseintrags-Kopfzeilen\n" #: .././restore/content.c:8213 msgid "corrupt extattr header\n" msgstr "beschädigte »extattr«-Kopfzeilen\n" #: .././restore/content.c:8219 msgid "bad extattr header checksum\n" msgstr "falsche Prüfsumme der »extattr«-Kopfzeilen\n" #: .././restore/content.c:8288 #, c-format msgid "" "attempt to seek %s to %lld failed: %s: not restoring extent off %lld sz %" "lld\n" msgstr "" "Versuch, %s zu %lld zu suchen, fehlgeschlagen: %s: Bereich von %lld sz %lld " "wird nicht wiederhergestellt\n" #: .././restore/content.c:8303 #, c-format msgid "dioinfo %s failed: %s: discarding ino %llu\n" msgstr "»dioinfo %s« fehlgeschlagen: %s: Ino %llu wird verworfen\n" #: .././restore/content.c:8331 .././restore/content.c:8347 #: .././restore/content.c:8351 msgid "end of media file" msgstr "Ende der Mediendatei" #: .././restore/content.c:8335 msgid "end of recorded data" msgstr "Ende der aufgezeichneten Daten" #: .././restore/content.c:8339 msgid "end of media" msgstr "Ende des Mediums" #: .././restore/content.c:8343 msgid "media error or no media" msgstr "Medienfehler oder kein Medium" #: .././restore/content.c:8356 msgid "dumping core" msgstr "Ausgabe des Kerns" #: .././restore/content.c:8360 #, c-format msgid "attempt to read %u bytes failed: %s\n" msgstr "Versuch, %u Bytes zu lesen, fehlgeschlagen: %s\n" #: .././restore/content.c:8447 .././restore/content.c:8482 #, c-format msgid "" "attempt to write %u bytes to %s at offset %lld failed: only %d bytes " "written\n" msgstr "" "Versuch, %u Byte nach %s bei Versatz %lld zu schreiben, fehlgeschlagen: Nur " "%d Byte geschrieben\n" #: .././restore/content.c:8473 #, c-format msgid "attempt to write %u bytes to %s at offset %lld failed: %s\n" msgstr "" "Versuch, %u Byte nach %s bei Versatz %lld zu schreiben, fehlgeschlagen: %s\n" #: .././restore/content.c:8522 msgid "Failed to allocate extended attribute buffer\n" msgstr "Reservieren des erweiterten Attribut-Puffers fehlgeschlagen\n" #: .././restore/content.c:8718 #, c-format msgid "unable to set %s extended attribute for %s: %s (%d)\n" msgstr "erweitertes Attribut %s für %s kann nicht gesetzt werden: %s (%d)\n" #: .././restore/content.c:8884 msgid "partial_reg: Out of records. Extend attrs applied early.\n" msgstr "" "partial_reg: Keine verbleibenden Datensätze. Erweiterte »attrs« frühzeitig " "angewendet.\n" #: .././restore/content.c:9051 msgid "overwrites inhibited" msgstr "Überschreiben verhindert" #: .././restore/content.c:9059 msgid "too old" msgstr "zu alt" #: .././restore/content.c:9068 msgid "existing version is newer" msgstr "existierende Version ist neuer" #: .././restore/content.c:9148 msgid "session inventory unknown\n" msgstr "Sitzungsbestand unbekannt\n" #: .././restore/content.c:9153 msgid "session inventory display\n" msgstr "Sitzungsbestandsanzeige\n" #: .././restore/content.c:9166 #, c-format msgid "" "\n" "media stream %u:\n" msgstr "" "\n" "Medien-Datenstrom %u:\n" #: .././restore/content.c:9170 msgid "" "\n" " media objects not yet identified\n" msgstr "" "\n" " Medienobjekte noch nicht identifiziert\n" #: .././restore/content.c:9184 #, c-format msgid "" "\n" " media object %u:\n" "\n" msgstr "" "\n" " Medienobjekt %u:\n" "\n" #: .././restore/content.c:9189 msgid " label: " msgstr " Kennung: " #: .././restore/content.c:9195 msgid " label is blank\n" msgstr " Kennung ist leer\n" #: .././restore/content.c:9202 #, c-format msgid " id: %s\n" msgstr " ID: %s\n" #: .././restore/content.c:9207 msgid " label not identified\n" msgstr " Kennung nicht identifiziert\n" #: .././restore/content.c:9211 #, c-format msgid " index within object of first media file: %u\n" msgstr " Index innerhalb Objekt der ersten Mediendatei: %u\n" #: .././restore/content.c:9217 #, c-format msgid " index within stream of first media file: %u\n" msgstr " Index innerhalb Datenstrom der ersten Mediendatei: %u\n" #: .././restore/content.c:9225 .././restore/content.c:9461 #, c-format msgid " now in drive %u\n" msgstr " nun in Laufwerk %u\n" #: .././restore/content.c:9229 .././restore/content.c:9469 msgid " now in drive\n" msgstr " nun in Laufwerk\n" #: .././restore/content.c:9235 msgid " media files not yet identified\n" msgstr " Mediendateien noch nicht identifiziert\n" #: .././restore/content.c:9248 #, c-format msgid "" "\n" " media file %u" msgstr "" "\n" " Mediendatei %u" #: .././restore/content.c:9260 #, c-format msgid " size: %lld bytes\n" msgstr " Größe: %lld Byte\n" #: .././restore/content.c:9266 msgid " used for directory restoral\n" msgstr " benutzt für Verzeichniswiederherstellung\n" #: .././restore/content.c:9271 #, c-format msgid " first extent contained: ino %llu off %lld\n" msgstr " erster Bereich enthielt: Ino %llu aus %lld\n" #: .././restore/content.c:9276 #, c-format msgid " next extent to restore: ino %llu off %lld\n" msgstr " nächster Bereich zur Wiederherstellung: Ino %llu aus %lld\n" #: .././restore/content.c:9281 #, c-format msgid " rollback mark %lld\n" msgstr " Wiederherstellungsmarkierung %lld\n" #: .././restore/content.c:9286 msgid " contains no selected non-directories\n" msgstr " enthält keine ausgewählten Nicht-Verzeichnisse\n" #: .././restore/content.c:9291 msgid " non-directories done\n" msgstr " Nicht-Verzeichnisse erledigt\n" #: .././restore/content.c:9295 msgid " contains session inventory\n" msgstr " enthält Sitzungsbestand\n" #: .././restore/content.c:9300 msgid " is stream terminator\n" msgstr " ist Datenstrom-Terminator\n" #: .././restore/content.c:9304 msgid " now reading\n" msgstr " wird nun gelesen\n" #: .././restore/content.c:9309 msgid "" "\n" " may be additional unidentified media files\n" msgstr "" "\n" " könnten zusätzliche nicht identifizierte Mediendateien sein\n" #: .././restore/content.c:9315 msgid "" "\n" " may be additional unidentified media objects\n" "\n" msgstr "" "\n" " könnten zusätzliche nicht identifizierte Medienobjekte sein\n" "\n" #: .././restore/content.c:9369 #, c-format msgid "hostname: %s\n" msgstr "Rechnername: %s\n" #: .././restore/content.c:9372 #, c-format msgid "mount point: %s\n" msgstr "Einhängepunkt: %s\n" #: .././restore/content.c:9375 #, c-format msgid "volume: %s\n" msgstr "Datenträger: %s\n" #: .././restore/content.c:9378 #, c-format msgid "session time: %s" msgstr "Sitzungszeit: %s" #: .././restore/content.c:9381 #, c-format msgid "level: %s%s\n" msgstr "Stufe: %s%s\n" #: .././restore/content.c:9385 msgid " resumed" msgstr " wieder aufgenommen" #: .././restore/content.c:9389 msgid "session label: " msgstr "Sitzungskennung: " #: .././restore/content.c:9394 msgid "media label: " msgstr "Medienkennung: " #: .././restore/content.c:9399 #, c-format msgid "file system id: %s\n" msgstr "Datensystem-ID: %s\n" #: .././restore/content.c:9405 #, c-format msgid "media id: %s\n" msgstr "Medien-ID: %s\n" #: .././restore/content.c:9425 msgid "" "the following media objects contain media files not yet tried for directory " "hierarchy restoral:\n" msgstr "" "die folgenden Medienobjekte enthalten Mediendateien, bei denen noch nicht " "versucht wurde, die Verzeichnishierarchie wiederherzustellen:\n" #: .././restore/content.c:9431 msgid "the following media objects are needed:\n" msgstr "die folgenden Medienobjekte sind nötig:\n" #: .././restore/content.c:9444 #, c-format msgid "%2u. label: " msgstr "%2u. Eitkett: " #: .././restore/content.c:9450 msgid " id: " msgstr " ID: " #: .././restore/content.c:9480 msgid "" "\n" "there are additional unidentified media objects containing media files not " "yet tried for directory hierarchy restoral:\n" msgstr "" "\n" "es gibt zusätzliche nicht identifizierte Medienobjekte, die Mediendateien " "enthalten, bei denen noch nicht versucht wurde, die Verzeichnishierarchie " "wiederherzustellen:\n" #: .././restore/content.c:9484 msgid "" "\n" "there are unidentified media objects containing media files not yet tried " "for directory hierarchy restoral:\n" msgstr "" "\n" "es gibt nicht identifizierte Medienobjekte, die Mediendateien enthalten, bei " "denen noch nicht versucht wurde, die Verzeichnishierarchie " "wiederherzustellen:\n" #: .././restore/content.c:9491 msgid "" "\n" "there are additional unidentified media objects not yet fully restored\n" msgstr "" "\n" "es gibt zusätzliche nicht identifizierte Medienobjekte, die nicht " "vollständig wiederhergestellt sind\n" #: .././restore/content.c:9494 msgid "" "\n" "there are unidentified media objects not yet fully restored\n" msgstr "" "\n" "es gibt nicht identifizierte Medienobjekte, die nicht vollständig " "wiederhergestellt sind\n" #: .././restore/content.c:9501 msgid "" "\n" "there may be additional unidentified media objects containing media files " "not yet tried for directory hierarchy restoral:\n" msgstr "" "\n" "es könnte zusätzliche nicht identifizierte Medienobjekte geben, die " "Mediendateien enthalten, bei denen noch nicht versucht wurde, die " "Verzeichnishierarchie wiederherzustellen:\n" #: .././restore/content.c:9505 msgid "" "\n" "there may be unidentified media objects containing media files not yet tried " "for directory hierarchy restoral:\n" msgstr "" "\n" "es könnte nicht identifizierte Medienobjekte geben, die Mediendateien " "enthalten, bei denen noch nicht versucht wurde, die Verzeichnishierarchie " "wiederherzustellen:\n" #: .././restore/content.c:9513 msgid "" "\n" "there may be additional unidentified media objects not yet fully restored\n" msgstr "" "\n" "es könnte zusätzliche nicht identifizierte Medienobjekte geben, die nicht " "vollständig wiederhergestellt sind\n" #: .././restore/content.c:9516 msgid "\there may be unidentified media objects not yet fully restored\n" msgstr "" "\tes könnte hier nicht identifizierte Medienobjekte geben, die nicht " "vollständig wiederhergestellt sind\n" #: .././restore/content.c:9523 msgid "no additional media objects needed\n" msgstr "keine zusätzlichen Mediendateien benötigt\n" #: .././restore/content.c:9547 #, c-format msgid "fssetdm_by_handle of %s failed %s\n" msgstr "fssetdm_by_handle von %s fehlgeschlagen %s\n" #: .././restore/content.c:9566 #, c-format msgid "%s quota information written to '%s'\n" msgstr "%s Quota-Informationen nach »%s« geschrieben\n" xfsdump-3.1.6+nmu1/restore/0000755000000000000000000000000012643557274012453 5ustar xfsdump-3.1.6+nmu1/restore/bag.c0000644000000000000000000000705612620476160013345 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include "config.h" #include "types.h" #include "mlog.h" #include "bag.h" bag_t * bag_alloc( void ) { bag_t *bagp; bagp = ( bag_t * )calloc( 1, sizeof( bag_t )); assert( bagp ); return bagp; } void bag_insert( bag_t *bagp, bagelem_t *newp, size64_t key, void *payloadp ) { register bagelem_t *nextp; register bagelem_t *prevp; assert( ! newp->be_loaded ); newp->be_loaded = BOOL_TRUE; assert( ! newp->be_bagp ); newp->be_bagp = bagp; newp->be_key = key; newp->be_payloadp = payloadp; if ( bagp->b_headp ) { nextp = bagp->b_headp; prevp = bagp->b_headp->be_prevp; } else { nextp = newp; prevp = newp; } newp->be_nextp = nextp; newp->be_prevp = prevp; nextp->be_prevp = newp; prevp->be_nextp = newp; bagp->b_headp = newp; } void bag_remove( bag_t *bagp, bagelem_t *oldp, size64_t *keyp, void **payloadpp ) { register bagelem_t *nextp; register bagelem_t *prevp; assert( oldp->be_loaded ); assert( oldp->be_bagp == bagp ); nextp = oldp->be_nextp; prevp = oldp->be_prevp; nextp->be_prevp = prevp; prevp->be_nextp = nextp; if ( bagp->b_headp == oldp ) { if ( nextp == oldp ) { assert( prevp == oldp ); bagp->b_headp = 0; } else { bagp->b_headp = nextp; } } *keyp = oldp->be_key; *payloadpp = oldp->be_payloadp; memset( ( void * )oldp, 0, sizeof( bagelem_t )); } bagelem_t * bag_find( bag_t *bagp, size64_t key, void **payloadpp ) { register bagelem_t *p; for ( p = bagp->b_headp ; p && p->be_nextp != bagp->b_headp && p->be_key != key ; p = p->be_nextp ) ; if ( ! p || p->be_key != key ) { *payloadpp = 0; return 0; } else { assert( p->be_loaded ); assert( p->be_bagp == bagp ); *payloadpp = p->be_payloadp; return p; } } void bagiter_init( bag_t *bagp, bagiter_t *iterp ) { iterp->bi_bagp = bagp; if ( ! bagp->b_headp ) { iterp->bi_nextp = 0; return; } iterp->bi_lastp = bagp->b_headp->be_prevp; iterp->bi_nextp = bagp->b_headp; } bagelem_t * bagiter_next( bagiter_t *iterp, void **payloadpp ) { bagelem_t *returnp; /* termination condition */ if ( ! iterp->bi_nextp ) { *payloadpp = 0; return 0; } /* save the element to be returned */ returnp = iterp->bi_nextp; /* calculate next. if returning last, set next to NULL */ if ( iterp->bi_nextp == iterp->bi_lastp ) { iterp->bi_nextp = 0; } else { iterp->bi_nextp = iterp->bi_nextp->be_nextp; } *payloadpp = returnp->be_payloadp; return returnp; } void bag_free( bag_t *bagp ) { register bagelem_t *p; p = bagp->b_headp; while ( p ) { register bagelem_t *nextp = p->be_nextp; memset( ( void * )p, 0, sizeof( bagelem_t )); p = nextp; if ( p == bagp->b_headp ) { break; } assert( p ); } memset( ( void * )bagp, 0, sizeof( bag_t )); free( ( void * )bagp ); } xfsdump-3.1.6+nmu1/restore/mmap.h0000644000000000000000000000146112607344125013545 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef MMAP_H #define MMAP_H void *mmap_autogrow(size_t len, int fd, off_t offset); #endif xfsdump-3.1.6+nmu1/restore/dirattr.c0000644000000000000000000006373712620476160014275 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* * Directory attributes are written on tape during the directory dump phase, * which precedes the non-dir dump phase. The directory attributes cannot be * restored, however, until all of the non-dir files have been restored * (directory timestamps would be wrong, directory inherit flags would * interfere, etc.) These routines allow the directory attributes to be stored * on disk when they are read from the dump stream so that they can be applied * at a later time. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "types.h" #include "util.h" #include "mlog.h" #include "global.h" #include "drive.h" #include "media.h" #include "content.h" #include "content_inode.h" #include "dirattr.h" #include "openutil.h" #include "mmap.h" /* structure definitions used locally ****************************************/ /* node handle limits */ #ifdef DIRATTRCHK /* macros for manipulating dirattr handles when handle consistency * checking is enabled. the upper bits of a handle will be loaded * with a handle checksum. */ #define HDLSUMCNT 4 #define HDLSUMSHIFT ( NBBY * sizeof ( dah_t ) - HDLSUMCNT ) #define HDLSUMLOMASK ( ( 1 << HDLSUMCNT ) - 1 ) #define HDLSUMMASK ( HDLSUMLOMASK << HDLSUMSHIFT ) #define HDLDIXCNT HDLSUMSHIFT #define HDLDIXMASK ( ( 1 << HDLDIXCNT ) - 1 ) #define HDLGETSUM( h ) ( ( uint16_t ) \ ( ( ( int )h >> HDLSUMSHIFT ) \ & \ HDLSUMLOMASK )) #define HDLGETDIX( h ) ( ( dix_t )( ( int )h & HDLDIXMASK )) #define HDLMKHDL( s, d ) ( ( dah_t )( ( ( ( int )s << HDLSUMSHIFT )\ & \ HDLSUMMASK ) \ | \ ( ( int )d & HDLDIXMASK ))) #define DIX_MAX ( ( off64_t )HDLDIXMASK ) /* each dirattr will hold two check fields: a handle checksum, and unique * pattern, to differentiate a valid dirattr from random file contents. */ #define DIRATTRUNQ 0xa116 #else /* DIRATTRCHK */ #define DIX_MAX ( ( ( off64_t )1 \ << \ ( ( off64_t )NBBY \ * \ ( off64_t )sizeof( dah_t ))) \ - \ ( off64_t )2 ) /* 2 to avoid DAH_NULL */ #endif /* DIRATTRCHK */ /* dirattr definition */ struct dirattr { #ifdef DIRATTRCHK uint16_t d_unq; uint16_t d_sum; #endif /* DIRATTRCHK */ mode_t d_mode; uid_t d_uid; gid_t d_gid; time32_t d_atime; time32_t d_mtime; time32_t d_ctime; uint32_t d_xflags; uint32_t d_extsize; uint32_t d_projid; uint32_t d_dmevmask; uint32_t d_dmstate; off64_t d_extattroff; }; typedef struct dirattr dirattr_t; #define DIRATTR_EXTATTROFFNULL ( ( off64_t )OFF64MAX ) /* dirattr persistent context definition */ struct dirattr_pers { off64_t dp_appendoff; }; typedef struct dirattr_pers dirattr_pers_t; #define DIRATTR_PERS_SZ pgsz /* dirattr transient context definition */ #define DIRATTR_BUFSIZE 32768 struct dirattr_tran { char *dt_pathname; int dt_fd; bool_t dt_at_endpr; dah_t dt_cachedh; dirattr_t dt_cached_dirattr; size_t dt_off; char dt_buf[DIRATTR_BUFSIZE]; char *dt_extattrpathname; int dt_extattrfd; bool_t dt_extattrfdbadpr; }; typedef struct dirattr_tran dirattr_tran_t; /* a dirattr is identified internally by its index into the backing store. * this index is the offset of the dirattr (relative to the end of the dirattr * persistent state hdr) into the backing store divided by the size of a * dirattr. a special index is reserved to represent the null index. a type * is defined for dirattr index (dix_t). it is a 64 bit signed for direct use * in the lseek64 system call. */ typedef off64_t dix_t; #define DIX2OFF( dix ) ( ( off64_t )( dix * ( off64_t )sizeof( dirattr_t ) \ + \ ( off64_t )DIRATTR_PERS_SZ )) #define OFF2DIX( doff ) ( ( dix_t )( ( doff - ( off64_t )DIRATTR_PERS_SZ ) \ / \ ( off64_t )sizeof( dirattr_t ))) /* declarations of externally defined global symbols *************************/ extern size_t pgsz; /* forward declarations of locally defined static functions ******************/ static void dirattr_get( dah_t ); static void dirattr_cacheflush( void ); #ifdef DIRATTRCHK static uint16_t calcdixcum( dix_t dix ); #endif /* DIRATTRCHK */ /* definition of locally defined global variables ****************************/ /* definition of locally defined static variables *****************************/ static char *dirattrfile = "dirattr"; static char *dirextattrfile = "dirextattr"; static dirattr_tran_t *dtp = 0; static dirattr_pers_t *dpp = 0; /* definition of locally defined global functions ****************************/ bool_t dirattr_init( char *hkdir, bool_t resume, uint64_t dircnt ) { if ( dtp ) { return BOOL_TRUE; } /* sanity checks */ assert( sizeof( dirattr_pers_t ) <= DIRATTR_PERS_SZ ); assert( ! dtp ); assert( ! dpp ); /* allocate and initialize context */ dtp = ( dirattr_tran_t * )calloc( 1, sizeof( dirattr_tran_t )); assert( dtp ); dtp->dt_cachedh = DAH_NULL; dtp->dt_fd = -1; dtp->dt_extattrfd = -1; /* generate a string containing the pathname of the dirattr file */ dtp->dt_pathname = open_pathalloc( hkdir, dirattrfile, 0 ); /* open the dirattr file */ if ( resume ) { /* open existing file */ dtp->dt_fd = open( dtp->dt_pathname, O_RDWR ); if ( dtp->dt_fd < 0 ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "could not find directory attributes file %s: " "%s\n"), dtp->dt_pathname, strerror( errno )); return BOOL_FALSE; } } else { /* create the dirattr file, first unlinking any older version * laying around */ ( void )unlink( dtp->dt_pathname ); dtp->dt_fd = open( dtp->dt_pathname, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR ); if ( dtp->dt_fd < 0 ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "could not create directory attributes file %s: " "%s\n"), dtp->dt_pathname, strerror( errno )); return BOOL_FALSE; } /* reserve space for the backing store. try to use RESVSP64. * if doesn't work, try ALLOCSP64. the former is faster, as * it does not zero the space. */ { bool_t successpr; unsigned int ioctlcmd; int loglevel; size_t trycnt; for ( trycnt = 0, successpr = BOOL_FALSE, ioctlcmd = XFS_IOC_RESVSP64, loglevel = MLOG_VERBOSE ; ! successpr && trycnt < 2 ; trycnt++, ioctlcmd = XFS_IOC_ALLOCSP64, loglevel = max( MLOG_NORMAL, loglevel - 1 )) { off64_t initsz; struct flock64 flock64; int rval; if ( ! ioctlcmd ) { continue; } initsz = ( off64_t )DIRATTR_PERS_SZ + ( ( off64_t )dircnt * sizeof( dirattr_t )); flock64.l_whence = 0; flock64.l_start = 0; flock64.l_len = initsz; rval = ioctl( dtp->dt_fd, ioctlcmd, &flock64 ); if ( rval ) { if ( errno != ENOTTY ) { mlog( loglevel | MLOG_NOTE, _( "attempt to reserve %lld bytes for %s " "using %s " "failed: %s (%d)\n"), initsz, dtp->dt_pathname, ioctlcmd == XFS_IOC_RESVSP64 ? "XFS_IOC_RESVSP64" : "XFS_IOC_ALLOCSP64", strerror( errno ), errno ); } } else { successpr = BOOL_TRUE; } } } } /* mmap the persistent descriptor */ assert( ! ( DIRATTR_PERS_SZ % pgsz )); dpp = ( dirattr_pers_t * )mmap_autogrow( DIRATTR_PERS_SZ, dtp->dt_fd, ( off_t )0 ); assert( dpp ); if ( dpp == ( dirattr_pers_t * )-1 ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "unable to map %s: %s\n"), dtp->dt_pathname, strerror( errno )); return BOOL_FALSE; } /* initialize persistent state */ if ( ! resume ) { dpp->dp_appendoff = ( off64_t )DIRATTR_PERS_SZ; } /* initialize transient state */ dtp->dt_at_endpr = BOOL_FALSE; /* calculate the dir extattr pathname, and set the fd to -1. * file will be created on demand. */ dtp->dt_extattrpathname = open_pathalloc( hkdir, dirextattrfile, 0 ); dtp->dt_extattrfd = -1; dtp->dt_extattrfdbadpr = BOOL_FALSE; if ( resume ) { ( void )unlink( dtp->dt_extattrpathname ); } return BOOL_TRUE; } void dirattr_cleanup( void ) { /* REFERENCED */ int rval; if ( ! dtp ) { return; } if ( dpp ) { rval = munmap( ( void * )dpp, DIRATTR_PERS_SZ ); assert( ! rval ); dpp = 0; } if ( dtp->dt_fd >= 0 ) { ( void )close( dtp->dt_fd ); dtp->dt_fd = -1; } if ( dtp->dt_pathname ) { ( void )unlink( dtp->dt_pathname ); free( ( void * )dtp->dt_pathname ); } if ( dtp->dt_extattrfd >= 0 ) { ( void )close( dtp->dt_extattrfd ); dtp->dt_extattrfd = -1; } if ( dtp->dt_extattrpathname ) { ( void )unlink( dtp->dt_extattrpathname ); free( ( void * )dtp->dt_extattrpathname ); } free( ( void * )dtp ); dtp = 0; } dah_t dirattr_add( filehdr_t *fhdrp ) { dirattr_t dirattr; off64_t oldoff; dix_t dix; #ifdef DIRATTRCHK uint16_t sum; #endif /* DIRATTRCHK */ dah_t dah; /* sanity checks */ assert( dtp ); assert( dpp ); /* make sure file pointer is positioned to write at end of file */ if ( ! dtp->dt_at_endpr ) { off64_t newoff; newoff = lseek64( dtp->dt_fd, dpp->dp_appendoff, SEEK_SET ); if ( newoff == ( off64_t )-1 ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "lseek of dirattr failed: %s\n"), strerror( errno )); return DAH_NULL; } assert( dpp->dp_appendoff == newoff ); dtp->dt_at_endpr = BOOL_TRUE; } if (dtp->dt_off + sizeof(dirattr_t) > sizeof(dtp->dt_buf)) { if (dirattr_flush() != RV_OK) { return DAH_NULL; } } /* calculate the index of this dirattr */ oldoff = dpp->dp_appendoff; dix = OFF2DIX( oldoff ); assert( dix <= DIX_MAX ); /* populate a dirattr */ dirattr.d_mode = ( mode_t )fhdrp->fh_stat.bs_mode; dirattr.d_uid = ( uid_t )fhdrp->fh_stat.bs_uid; dirattr.d_gid = ( gid_t )fhdrp->fh_stat.bs_gid; dirattr.d_atime = ( time32_t )fhdrp->fh_stat.bs_atime.tv_sec; dirattr.d_mtime = ( time32_t )fhdrp->fh_stat.bs_mtime.tv_sec; dirattr.d_ctime = ( time32_t )fhdrp->fh_stat.bs_ctime.tv_sec; dirattr.d_xflags = fhdrp->fh_stat.bs_xflags; dirattr.d_extsize = ( uint32_t )fhdrp->fh_stat.bs_extsize; dirattr.d_projid = bstat_projid(&(fhdrp->fh_stat)); dirattr.d_dmevmask = fhdrp->fh_stat.bs_dmevmask; dirattr.d_dmstate = ( uint32_t )fhdrp->fh_stat.bs_dmstate; #ifdef DIRATTRCHK dirattr.d_unq = DIRATTRUNQ; sum = calcdixcum( dix ); dirattr.d_sum = sum; #endif /* DIRATTRCHK */ dirattr.d_extattroff = DIRATTR_EXTATTROFFNULL; /* write the entry into our buffer */ memcpy(dtp->dt_buf + dtp->dt_off, (void *)&dirattr, sizeof(dirattr_t)); dtp->dt_off += sizeof(dirattr_t); /* update the next write offset */ assert( dpp->dp_appendoff <= OFF64MAX - ( off64_t )sizeof(dirattr_t) ); dpp->dp_appendoff += ( off64_t )sizeof(dirattr_t); #ifdef DIRATTRCHK dah = HDLMKHDL( sum, dix ); #else /* DIRATTRCHK */ dah = ( dah_t )dix; #endif /* DIRATTRCHK */ return dah; } void dirattr_addextattr( dah_t dah, extattrhdr_t *ahdrp ) { off64_t oldoff; off64_t off; off64_t seekoff; off64_t nulloff; int nread; int nwritten; /* pull the selected dir attributes into the cache */ dirattr_get( dah ); /* open/create extended attributes file if not yet done */ if ( dtp->dt_extattrfd < 0 ) { if ( dtp->dt_extattrfdbadpr ) { return; } dtp->dt_extattrfd = open( dtp->dt_extattrpathname, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR ); if ( dtp->dt_extattrfd < 0 ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "could not open/create directory " "extended attributes file %s: " "%s (%d)\n"), dtp->dt_extattrpathname, strerror( errno ), errno ); dtp->dt_extattrfdbadpr = BOOL_TRUE; return; } } /* seek to the end of the dir extattr list */ off = dtp->dt_cached_dirattr.d_extattroff; oldoff = DIRATTR_EXTATTROFFNULL; while ( off != DIRATTR_EXTATTROFFNULL ) { seekoff = lseek64( dtp->dt_extattrfd, off, SEEK_SET ); if ( seekoff < 0 ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "could not seek to into extended attributes " "file %s: " "%s (%d)\n"), dtp->dt_extattrpathname, strerror( errno ), errno ); dtp->dt_extattrfdbadpr = BOOL_TRUE; return; } assert( seekoff == off ); oldoff = off; nread = read( dtp->dt_extattrfd, ( void * )&off, sizeof( off )); if ( nread != ( int )sizeof( off )) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "could not read extended attributes " "file %s: " "%s (%d)\n"), dtp->dt_extattrpathname, strerror( errno ), errno ); dtp->dt_extattrfdbadpr = BOOL_TRUE; return; } } /* append the extended attributes */ off = lseek64( dtp->dt_extattrfd, 0, SEEK_END ); if ( off < 0 ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "could not seek to end of extended attributes " "file %s: " "%s (%d)\n"), dtp->dt_extattrpathname, strerror( errno ), errno ); dtp->dt_extattrfdbadpr = BOOL_TRUE; return; } nulloff = DIRATTR_EXTATTROFFNULL; nwritten = write( dtp->dt_extattrfd, ( void * )&nulloff, sizeof( nulloff )); if ( nwritten != ( int )sizeof( nulloff )) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "could not write extended attributes " "file %s: " "%s (%d)\n"), dtp->dt_extattrpathname, strerror( errno ), errno ); dtp->dt_extattrfdbadpr = BOOL_TRUE; return; } nwritten = write( dtp->dt_extattrfd, ( void * )ahdrp, ahdrp->ah_sz ); if ( nwritten != ( int )( ahdrp->ah_sz )) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "could not write at end of extended attributes " "file %s: " "%s (%d)\n"), dtp->dt_extattrpathname, strerror( errno ), errno ); dtp->dt_extattrfdbadpr = BOOL_TRUE; return; } /* fill in the offset of the extended attributes into the * linked list */ if ( oldoff == DIRATTR_EXTATTROFFNULL ) { dtp->dt_cached_dirattr.d_extattroff = off; dirattr_cacheflush( ); } else { seekoff = lseek64( dtp->dt_extattrfd, oldoff, SEEK_SET ); if ( seekoff < 0 ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "could not seek to into extended attributes " "file %s: " "%s (%d)\n"), dtp->dt_extattrpathname, strerror( errno ), errno ); dtp->dt_extattrfdbadpr = BOOL_TRUE; return; } assert( seekoff == oldoff ); nwritten = write( dtp->dt_extattrfd, ( void * )&off, sizeof( off )); if ( nwritten != ( int )sizeof( off )) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "could not write extended attributes " "file %s: " "%s (%d)\n"), dtp->dt_extattrpathname, strerror( errno ), errno ); dtp->dt_extattrfdbadpr = BOOL_TRUE; return; } } } bool_t dirattr_cb_extattr( dah_t dah, bool_t ( * cbfunc )( extattrhdr_t *ahdrp, void *ctxp ), extattrhdr_t *ahdrp, void *ctxp ) { off64_t off; /* pull the selected dir attributes into the cache */ dirattr_get( dah ); /* open/create extended attributes file if not yet done */ if ( dtp->dt_extattrfd < 0 ) { if ( dtp->dt_extattrfdbadpr ) { return BOOL_TRUE; } dtp->dt_extattrfd = open( dtp->dt_extattrpathname, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR ); if ( dtp->dt_extattrfd < 0 ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "could not open/create directory " "extended attributes file %s: " "%s (%d)\n"), dtp->dt_extattrpathname, strerror( errno ), errno ); dtp->dt_extattrfdbadpr = BOOL_TRUE; return BOOL_TRUE; } } /* walk through the dirattr list for this dah */ off = dtp->dt_cached_dirattr.d_extattroff; while ( off != DIRATTR_EXTATTROFFNULL ) { off64_t seekoff; int nread; off64_t nextoff; size_t recsz; bool_t ok; /* seek to the extattr */ seekoff = lseek64( dtp->dt_extattrfd, off, SEEK_SET ); if ( seekoff < 0 ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "could not seek to into extended attributes " "file %s: " "%s (%d)\n"), dtp->dt_extattrpathname, strerror( errno ), errno ); dtp->dt_extattrfdbadpr = BOOL_TRUE; return BOOL_TRUE; } assert( seekoff == off ); /* peel off the next offset */ nread = read( dtp->dt_extattrfd, ( void * )&nextoff, sizeof( nextoff )); if ( nread != ( int )sizeof( nextoff )) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "could not read extended attributes " "file %s: " "%s (%d)\n"), dtp->dt_extattrpathname, strerror( errno ), errno ); dtp->dt_extattrfdbadpr = BOOL_TRUE; return BOOL_TRUE; } /* read the extattr hdr */ nread = read( dtp->dt_extattrfd, ( void * )ahdrp, EXTATTRHDR_SZ ); if ( nread != EXTATTRHDR_SZ ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "could not read extended attributes " "file %s: " "%s (%d)\n"), dtp->dt_extattrpathname, strerror( errno ), errno ); dtp->dt_extattrfdbadpr = BOOL_TRUE; return BOOL_TRUE; } /* read the remainder of the extattr */ recsz = ( size_t )ahdrp->ah_sz; assert( recsz >= EXTATTRHDR_SZ ); nread = read( dtp->dt_extattrfd, ( void * )&ahdrp[ 1 ], recsz - EXTATTRHDR_SZ ); if ( nread != ( int )( recsz - EXTATTRHDR_SZ )) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "could not read extended attributes " "file %s: " "%s (%d)\n"), dtp->dt_extattrpathname, strerror( errno ), errno ); dtp->dt_extattrfdbadpr = BOOL_TRUE; return BOOL_TRUE; } /* call the callback func */ ok = ( * cbfunc )( ahdrp, ctxp ); if ( ! ok ) { return BOOL_FALSE; } /* go th the next one */ off = nextoff; } return BOOL_TRUE; } void dirattr_update( dah_t dah, filehdr_t *fhdrp ) { dix_t dix; #ifdef DIRATTRCHK uint16_t sum; #endif /* DIRATTRCHK */ off64_t argoff; off64_t newoff; dirattr_t dirattr; int nwritten; /* sanity checks */ assert( dtp ); assert( dpp ); assert( dah != DAH_NULL ); #ifdef DIRATTRCHK sum = HDLGETSUM( dah ); dix = HDLGETDIX( dah ); #else /* DIRATTRCHK */ dix = ( dix_t )dah; #endif /* DIRATTRCHK */ assert( dix >= 0 ); assert( dix <= DIX_MAX ); argoff = DIX2OFF( dix ); assert( argoff >= 0 ); assert( argoff >= ( off64_t )DIRATTR_PERS_SZ ); assert( argoff <= dpp->dp_appendoff - ( off64_t )sizeof( dirattr_t )); #ifdef DIRATTRCHK dirattr_get( dah ); assert( dtp->dt_cached_dirattr.d_unq == DIRATTRUNQ ); assert( dtp->dt_cached_dirattr.d_sum == sum ); #endif /* DIRATTRCHK */ if ( dtp->dt_at_endpr && dtp->dt_off ) { if (dirattr_flush() != RV_OK) { assert( 0 ); return; } } /* seek to the dirattr */ newoff = lseek64( dtp->dt_fd, argoff, SEEK_SET ); if ( newoff == ( off64_t )-1 ) { mlog( MLOG_NORMAL, _( "lseek of dirattr failed: %s\n"), strerror( errno )); assert( 0 ); } assert( newoff == argoff ); /* populate a dirattr */ dirattr.d_mode = ( mode_t )fhdrp->fh_stat.bs_mode; dirattr.d_uid = ( uid_t )fhdrp->fh_stat.bs_uid; dirattr.d_gid = ( gid_t )fhdrp->fh_stat.bs_gid; dirattr.d_atime = ( time32_t )fhdrp->fh_stat.bs_atime.tv_sec; dirattr.d_mtime = ( time32_t )fhdrp->fh_stat.bs_mtime.tv_sec; dirattr.d_ctime = ( time32_t )fhdrp->fh_stat.bs_ctime.tv_sec; dirattr.d_xflags = fhdrp->fh_stat.bs_xflags; dirattr.d_extsize = ( uint32_t )fhdrp->fh_stat.bs_extsize; dirattr.d_projid = bstat_projid(&(fhdrp->fh_stat)); dirattr.d_dmevmask = fhdrp->fh_stat.bs_dmevmask; dirattr.d_dmstate = ( uint32_t )fhdrp->fh_stat.bs_dmstate; dirattr.d_extattroff = DIRATTR_EXTATTROFFNULL; /* write the dirattr */ nwritten = write( dtp->dt_fd, ( void * )&dirattr, sizeof( dirattr )); if ( ( size_t )nwritten != sizeof( dirattr )) { mlog( MLOG_NORMAL, _( "update of dirattr failed: %s\n"), strerror( errno )); assert( 0 ); } dtp->dt_at_endpr = BOOL_FALSE; dtp->dt_cachedh = dah; } /* ARGSUSED */ void dirattr_del( dah_t dah ) { } mode_t dirattr_get_mode( dah_t dah ) { dirattr_get( dah ); return dtp->dt_cached_dirattr.d_mode; } uid_t dirattr_get_uid( dah_t dah ) { dirattr_get( dah ); return dtp->dt_cached_dirattr.d_uid; } uid_t dirattr_get_gid( dah_t dah ) { dirattr_get( dah ); return dtp->dt_cached_dirattr.d_gid; } time32_t dirattr_get_atime( dah_t dah ) { dirattr_get( dah ); return dtp->dt_cached_dirattr.d_atime; } time32_t dirattr_get_mtime( dah_t dah ) { dirattr_get( dah ); return dtp->dt_cached_dirattr.d_mtime; } time32_t dirattr_get_ctime( dah_t dah ) { dirattr_get( dah ); return dtp->dt_cached_dirattr.d_ctime; } uint32_t dirattr_get_xflags( dah_t dah ) { dirattr_get( dah ); return dtp->dt_cached_dirattr.d_xflags; } uint32_t dirattr_get_extsize( dah_t dah ) { dirattr_get( dah ); return dtp->dt_cached_dirattr.d_extsize; } uint32_t dirattr_get_projid( dah_t dah ) { dirattr_get( dah ); return dtp->dt_cached_dirattr.d_projid; } uint32_t dirattr_get_dmevmask( dah_t dah ) { dirattr_get( dah ); return dtp->dt_cached_dirattr.d_dmevmask; } uint32_t dirattr_get_dmstate( dah_t dah ) { dirattr_get( dah ); return dtp->dt_cached_dirattr.d_dmstate; } rv_t dirattr_flush() { ssize_t nwritten; /* sanity checks */ assert ( dtp ); if (dtp->dt_off) { /* write the accumulated dirattr entries */ nwritten = write( dtp->dt_fd, ( void * )dtp->dt_buf, dtp->dt_off); if ( nwritten != dtp->dt_off ) { if ( nwritten < 0 ) { mlog( MLOG_NORMAL | MLOG_ERROR, _("write of dirattr buffer failed: %s\n"), strerror( errno )); } else { mlog( MLOG_NORMAL | MLOG_ERROR, _("write of dirattr buffer failed: " "expected to write %ld, actually " "wrote %ld\n"), dtp->dt_off, nwritten); } assert( 0 ); return RV_UNKNOWN; } dtp->dt_off = 0; } return RV_OK; } /* definition of locally defined static functions ****************************/ static void dirattr_get( dah_t dah ) { dix_t dix; off64_t argoff; off64_t newoff; int nread; #ifdef DIRATTRCHK uint16_t sum; #endif /* DIRATTRCHK */ /* sanity checks */ assert( dtp ); assert( dpp ); assert( dah != DAH_NULL ); /* if we are already holding this dirattr in cache, * just return */ if ( dtp->dt_cachedh == dah ) { return; } #ifdef DIRATTRCHK sum = HDLGETSUM( dah ); dix = HDLGETDIX( dah ); #else /* DIRATTRCHK */ dix = ( dix_t )dah; #endif /* DIRATTRCHK */ assert( dix >= 0 ); assert( dix <= DIX_MAX ); argoff = DIX2OFF( dix ); assert( argoff >= 0 ); assert( argoff >= ( off64_t )DIRATTR_PERS_SZ ); assert( argoff <= dpp->dp_appendoff - ( off64_t )sizeof( dirattr_t )); if ( dtp->dt_at_endpr && dtp->dt_off ) { if (dirattr_flush() != RV_OK) { assert( 0 ); return; } } /* seek to the dirattr */ newoff = lseek64( dtp->dt_fd, argoff, SEEK_SET ); if ( newoff == ( off64_t )-1 ) { mlog( MLOG_NORMAL, _( "lseek of dirattr failed: %s\n"), strerror( errno )); assert( 0 ); } assert( newoff == argoff ); /* read the dirattr */ nread = read( dtp->dt_fd, ( void * )&dtp->dt_cached_dirattr, sizeof( dtp->dt_cached_dirattr )); if ( ( size_t )nread != sizeof( dtp->dt_cached_dirattr )) { mlog( MLOG_NORMAL, _( "read of dirattr failed: %s\n"), strerror( errno )); assert( 0 ); } #ifdef DIRATTRCHK assert( dtp->dt_cached_dirattr.d_unq == DIRATTRUNQ ); assert( dtp->dt_cached_dirattr.d_sum == sum ); #endif /* DIRATTRCHK */ dtp->dt_at_endpr = BOOL_FALSE; dtp->dt_cachedh = dah; } static void dirattr_cacheflush( void ) { dah_t dah; dix_t dix; #ifdef DIRATTRCHK uint16_t sum; #endif /* DIRATTRCHK */ off64_t argoff; off64_t newoff; int nwritten; /* sanity checks */ assert( dtp ); assert( dpp ); /* if nothing in the cache, ignore */ dah = dtp->dt_cachedh; assert( dah != DAH_NULL ); if ( dah == DAH_NULL ) { return; } #ifdef DIRATTRCHK sum = HDLGETSUM( dah ); dix = HDLGETDIX( dah ); #else /* DIRATTRCHK */ dix = ( dix_t )dah; #endif /* DIRATTRCHK */ #ifdef DIRATTRCHK assert( dtp->dt_cached_dirattr.d_unq == DIRATTRUNQ ); assert( dtp->dt_cached_dirattr.d_sum == sum ); #endif /* DIRATTRCHK */ assert( dix >= 0 ); assert( dix <= DIX_MAX ); argoff = DIX2OFF( dix ); assert( argoff >= 0 ); assert( argoff >= ( off64_t )DIRATTR_PERS_SZ ); assert( argoff <= dpp->dp_appendoff - ( off64_t )sizeof( dirattr_t )); /* seek to the dirattr */ newoff = lseek64( dtp->dt_fd, argoff, SEEK_SET ); if ( newoff == ( off64_t )-1 ) { mlog( MLOG_NORMAL, _( "lseek of dirattr failed: %s\n"), strerror( errno )); assert( 0 ); } assert( newoff == argoff ); /* write the dirattr */ nwritten = write( dtp->dt_fd, ( void * )&dtp->dt_cached_dirattr, sizeof( dtp->dt_cached_dirattr )); if ( ( size_t )nwritten != sizeof( dtp->dt_cached_dirattr )) { mlog( MLOG_NORMAL, _( "flush of dirattr failed: %s\n"), strerror( errno )); assert( 0 ); } dtp->dt_at_endpr = BOOL_FALSE; } #ifdef DIRATTRCHK static uint16_t calcdixcum( dix_t dix ) { uint16_t sum; ix_t nibcnt; ix_t nibix; assert( ( sizeof( dah_t ) / HDLSUMCNT ) * HDLSUMCNT == sizeof( dah_t )); nibcnt = ( sizeof( dah_t ) / HDLSUMCNT ) - 1; sum = 0; for ( nibix = 0 ; nibix < nibcnt ; nibix++ ) { sum += ( uint16_t )( dix & HDLSUMLOMASK ); dix >>= HDLSUMCNT; } sum = ( uint16_t )( ( ~sum + 1 ) & HDLSUMLOMASK ); return sum; } #endif /* DIRATTRCHK */ xfsdump-3.1.6+nmu1/restore/namreg.h0000644000000000000000000000412212620476160014061 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef NAMREG_H #define NAMREG_H /* namreg.[hc] - directory entry registry * * provides unique directory entry ID's and storage for the entry * name. */ /* nrh_t - handle to a registered name */ typedef size64_t nrh_t; #define NRH_NULL SIZE64MAX /* namreg_init - creates the name registry. resync is TRUE if the * registry should already exist, and we are resynchronizing. * if NOT resync, inocnt hints at how many names will be held */ extern bool_t namreg_init( char *housekeepingdir, bool_t resync, uint64_t inocnt ); /* namreg_add - registers a name. name does not need to be null-terminated. * returns handle for use with namreg_get(). */ extern nrh_t namreg_add( char *name, size_t namelen ); /* namreg_del - remove a name from the registry */ extern void namreg_del( nrh_t nrh ); /* namreg_map - mmap the name registry, allowing for much * faster namreg_get() lookups. once called, additional * entries cannot be added. */ extern rv_t namreg_map( void ); /* namreg_get - retrieves the name identified by the index. * fills the buffer with the null-terminated name from the registry. * returns the strlen() of the name. returns -1 if the buffer is too * small to fit the null-terminated name. return -2 if the name * not in the registry. return -3 if a system call fails. */ extern int namreg_get( nrh_t nrh, char *bufp, size_t bufsz ); #endif /* NAMREG_H */ xfsdump-3.1.6+nmu1/restore/inomap.h0000644000000000000000000000611412620476160014076 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef INOMAP_H #define INOMAP_H /* inomap.[hc] - inode map abstraction * * an inode map describes the inode numbers (inos) in a file system dump. * the map identifies which inos are in-use by the fs, which of those are * directories, and which are dumped. * * the map is represented as a list of map segments. a map segment is * a 64-bit starting ino and two 64-bit bitmaps. the bitmaps describe * the 64 inos beginning with the starting ino. two bits are available * for each ino. */ /* map state values */ #define MAP_INO_UNUSED 0 /* ino not in use by fs */ #define MAP_DIR_NOCHNG 1 /* dir, ino in use by fs, but not dumped */ #define MAP_NDR_NOCHNG 2 /* non-dir, ino in use by fs, but not dumped */ #define MAP_DIR_CHANGE 3 /* dir, changed since last dump */ #define MAP_NDR_CHANGE 4 /* non-dir, changed since last dump */ #define MAP_DIR_SUPPRT 5 /* dir, unchanged but needed for hierarchy */ #define MAP_NDR_NOREST 6 /* was MAP_NDR_CHANGE, but not to be restored */ #define MAP_RESERVED2 7 /* this state currently not used */ /* the inomap is implemented as a linked list of chunks. each chunk contains * an array of map segments. a map segment contains a start ino and a * bitmap of 64 3-bit state values (see MAP_... in inomap.h). the SEG_macros * index and manipulate the 3-bit state values. */ struct seg { xfs_ino_t base; uint64_t lobits; uint64_t mebits; uint64_t hibits; }; typedef struct seg seg_t; #define INOPERSEG ( sizeofmember( seg_t, lobits ) * NBBY ) #define HNKSZ ( 4 * PGSZ ) #define SEGPERHNK ( ( HNKSZ / sizeof( seg_t )) - 1 ) struct hnk { seg_t seg[ SEGPERHNK ]; xfs_ino_t maxino; struct hnk *nextp; char pad[sizeof( seg_t ) - sizeof( xfs_ino_t ) - sizeof( struct hnk * )]; }; typedef struct hnk hnk_t; extern bool_t inomap_sync_pers( char *hkdir ); extern rv_t inomap_restore_pers( drive_t *drivep, content_inode_hdr_t *scrhdrp, char *hkdir ); extern void inomap_del_pers( char *hkdir ); extern void inomap_sanitize( void ); extern bool_t inomap_rst_needed( xfs_ino_t begino, xfs_ino_t endino ); extern void inomap_rst_add( xfs_ino_t ino ); extern void inomap_rst_del( xfs_ino_t ino ); extern rv_t inomap_discard( drive_t *drivep, content_inode_hdr_t *scrhdrp ); extern void inomap_cbiter( int mapstatemask, bool_t ( * cbfunc )( void *ctxp, xfs_ino_t ino ), void *ctxp ); #endif /* INOMAP_H */ xfsdump-3.1.6+nmu1/restore/content.c0000644000000000000000000072732612620476160014277 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* only for util.h */ #include "config.h" #include "types.h" #include "timeutil.h" #include "util.h" /* only for r/w routines, ALIGN_PTR */ #include "cldmgr.h" #include "qlock.h" #include "lock.h" #include "path.h" #include "openutil.h" #include "exit.h" #include "getopt.h" #include "mlog.h" #include "dlog.h" #include "bag.h" #include "node.h" #include "namreg.h" #include "stream.h" #include "global.h" #include "drive.h" #include "media.h" #include "content.h" #include "content_inode.h" #include "inomap.h" #include "dirattr.h" #include "tree.h" #include "inventory.h" #include "mmap.h" #include "arch_xlate.h" #include "win.h" #include "hsmapi.h" /* content.c - manages restore content */ /* structure definitions used locally ****************************************/ #define HOUSEKEEPING_MAGIC 0x686b6d61 /* "hkma" - see the housekeeping_magic field of pers_t below. */ #define HOUSEKEEPING_VERSION 2 /* see the housekeeping_version field of pers_t below. * version 2 changed the size of a gen_t, which caused node_t * to change in size. also p_truncategenpr was added to treepers_t. */ #define WRITE_TRIES_MAX 3 /* retry loop tuning for write(2) workaround */ typedef enum { SYNC_INIT, SYNC_BUSY, SYNC_DONE } sync_t; /* for lock-step synchronization */ typedef struct { xfs_ino_t eg_ino; off64_t eg_off; } egrp_t; /* extent group descriptor */ typedef char label_t[ GLOBAL_HDR_STRING_SZ ]; /* dump or mobj label */ typedef enum { PURP_SEARCH, PURP_DIR, PURP_NONDIR } purp_t; /* to describe purpose for a media file request. may be for * searching for a dump to restore, for dir restore, or non-dir */ typedef off_t dh_t; /* handles for descriptors in persistent state inventory * encoded as byte offset plus one of descriptor into descriptor * portion of persistent state. plus one so DH_NULL can be zero. */ #define DH_NULL ( ( dh_t )0 ) /* NULL inv. descriptor handles, to terminate linked descriptor lists. * must be zero-valued, so memset of pers.s sets freeh to DH_NULL. */ #define DH2F( h ) ( ( pers_file_t * )( ( char * )descp + ( h - 1 ))) #define DH2O( h ) ( ( pers_obj_t * )( ( char * )descp + ( h - 1 ))) #define DH2S( h ) ( ( pers_strm_t * )( ( char * )descp + ( h - 1 ))) #define DH2D( h ) ( ( pers_desc_t * )( ( char * )descp + ( h - 1 ))) /* convert file, object, and stream inv. descriptor handle into * descriptor pointers */ #define DAU 1 /* number of descriptor pages to allocate when free list exhausted */ #define IBPGINCR 32 /* session inv. restore retry buffer increment */ /* Media state abstraction */ struct Media { drive_t *M_drivep; global_hdr_t *M_grhdrp; drive_hdr_t *M_drhdrp; media_hdr_t *M_mrhdrp; content_hdr_t *M_crhdrp; content_inode_hdr_t *M_scrhdrp; enum { POS_UNKN, /* whenever media file not open */ POS_ATHDR, /* at beginning of media file */ POS_INDIR, /* at beginning of inomap/dirdump */ POS_ATNONDIR, /* at first non-dir file */ POS_END, /* EOM/EOD */ POS_USELESS, /* current object contains nothing useful */ POS_BLANK /* like useless */ } M_pos; /* media positioning info. initially UNKN, set back to * unkn whenever end_read op called. */ ix_t M_fmfix; ix_t M_lmfix; ix_t M_pmfix; bool_t M_pmfixvalpr; purp_t M_mfixpurp; bool_t M_flmfixvalpr; /* the indices within the current media object of the first * and last media files seen, as well as previous last. * invalidated whenever purpose changes or media is changed. * previous (pmfix) not valid until second media file seen. */ ix_t M_fsfix; ix_t M_fsoix; ix_t M_fssix; bool_t M_fsfixvalpr; /* index within the current media object of the first * media file that is part of dump being restored, * and indices of the obj and stream containing that mfile. * invalidated on media change. */ }; typedef struct Media Media_t; /* persistent state - mmapped, has linked lists of dump streams, media * objects, and media files. descriptors for each fit into PERS_DESCSZ * bytes, and are allocated from a common free pool. */ /* persistent media file descriptor */ struct pers_file { dh_t f_nexth; /* singly-linked list of files withing object */ dh_t f_parh; /* parent object */ bool_t f_szvalpr; off64_t f_sz; /* if this info came from an inventory (on-line or on-media), * we know the media file size */ bool_t f_dirtriedpr; /* set if attempted to restore dirs from this media file. * says nothing about success or failure. prevents us from * trying to restore dirs from this media file again. */ bool_t f_valpr; /* following three fields are valid */ egrp_t f_firstegrp; /* first extent group in this media file */ egrp_t f_curegrp; /* next extent group to be restored from this media file. * initially equals f_firstegrp. */ drive_mark_t f_curmark; /* drive manager mark for seeking to current extent group */ bool_t f_nondirdonepr; /* TRUE when non-dirs from this media file completely restored, * or as restored as they can be (some or all lost due to * media corruption). */ bool_t f_nondirskippr; /* no non-dirs are needed from this nmedia file (due to * subtree or interactive selections) */ int f_flags; /* mark terminators and inventories */ bool_t f_underheadpr; /* the drive is currently positioned at or in this media file */ }; /* f_flags */ #define PF_INV ( 1 << 0 ) #define PF_TERM ( 1 << 1 ) typedef struct pers_file pers_file_t; /* persistent media object descriptor */ struct pers_obj { dh_t o_nexth; /* singly-linked list of objects in stream */ dh_t o_parh; /* parent dump stream descriptor */ dh_t o_cldh; /* head of list of pertinent media files contained in * this media object */ bool_t o_idlabvalpr; /* id and label fields are valid */ uuid_t o_id; /* uuid of media object */ label_t o_lab; /* label of media object */ ix_t o_fmfmix; bool_t o_fmfmixvalpr; /* 0-based index into this mobj's mfiles of first * mfile in the mobj that is part of the dump stream. */ ix_t o_fmfsix; bool_t o_fmfsixvalpr; /* 0-based index into this dump stream's mfiles of first * mfile in the mobj that is part of the dump stream. */ bool_t o_lmfknwnpr; /* TRUE if last media file on object is represented in * children list. */ bool_t o_indrivepr; ix_t o_indriveix; /* TRUE if this object is in a drive, and which drive it is * in. */ }; typedef struct pers_obj pers_obj_t; /* media dump stream descriptor */ struct pers_strm { dh_t s_nexth; /* singly-linked list of streams generated by dump */ dh_t s_cldh; /* head of list of mobjs containing this dstrm's mfiles */ bool_t s_lastobjknwnpr; /* TRUE if if last object in the stream is represented in * children list. */ }; typedef struct pers_strm pers_strm_t; /* media descriptor allocation object (for free list) */ union pers_desc { dh_t d_nexth; /* singly-linked free list of descriptors */ pers_file_t d_file; /* media file descriptor overlay; */ pers_obj_t d_obj; /* media object descriptor overlay; */ pers_strm_t d_strm; /* media stream descriptor overlay; */ }; typedef union pers_desc pers_desc_t; #define PERS_DESCSZ 512 /* size of media object, media file, and media stream descriptors. * need to fit integral number into a page, single allocator * used allocate and free all types . */ /* subtree descriptor - the subtree command line arguments are transcribed * into variable-length descriptors and placed in an integral number of * pages after the persistent header, and before the media descriptor free list. */ #define STDESCALIGN 8 struct stdesc { bool_t std_sensepr; /* TRUE if this is a subtree to INCLUDE, FALSE if EXCLUDE */ off_t std_nextoff; /* offset to next descriptor, in bytes relative to this */ char std_path[ 1 ]; /* first character of a NULL-terminated string containing the * the relative subtree pathname */ }; typedef struct stdesc stdesc_t; /* byte span descriptor - registers a span of a file restored. */ struct bytespan { off64_t offset; off64_t endoffset; } ; typedef struct bytespan bytespan_t; /* partial restore descriptor - Keeps track of different byte spans restored * for a specific inode. Used to sync operations between restore streams. */ struct partial_rest { xfs_ino_t is_ino; /* inode number */ bytespan_t is_bs[STREAM_SIMMAX]; /* each stream could conceivably be writing to a single * file simultaneously if one file spans all device streams. * Need a record for each possible place in the file. */ }; typedef struct partial_rest partial_rest_t; struct stream_context { bstat_t sc_bstat; char sc_path[2 * MAXPATHLEN]; int sc_fd; int sc_hsmflags; /* * we have to set the owner before we set extended attributes otherwise * capabilities will not be restored correctly as setting the owner with * fchmod will strip the capability attribute from the file. Hence we * need to do this before restoring xattrs and record it so we don't do * it again on completion of file restoration. */ bool_t sc_ownerset; }; typedef struct stream_context stream_context_t; /* persistent state file header - on-disk format information plus * accumulation state (which spans several sessions) and session state. * the latter two have a valid bit, and their fields are not valid until * the valid bit is set. all elements defined such that a bzero results * in a valid initial state. */ struct pers { /* on-disk format information used to verify that xfsrestore * can make sense of the data in xfsrestorehousekeepingdir * when running in cumulative mode or when resuming a restore. * * for backwards/forwards compatibility, this struct must be * the first field! also any changes to the struct must address * compatibility with other xfsrestore versions. */ struct { size32_t housekeeping_magic; /* used to determine if this struct has been * initialized, and whether the machine's * endianness is the same as the previous * invocation. (data written to xfsrestore's * state directory is not converted to an * endian-neutral format since it only persists * for the life of one or more restore sessions.) */ size32_t housekeeping_version; /* version of the data structures used in the * state files in housekeepingdir. this must be * bumped whenever the on-disk format changes. */ size64_t pagesize; /* headers in the persistent state files * are aligned on page size boundaries, so * this cannot change betweeen invocations. */ } v; /* command line arguments from first session, and session * history. */ struct { bool_t valpr; /* not set until a BASE dump has been identified * and validated for restoral, and an attempt has * been made to load the dump inventory into persistent * state, and the namreg and tree abstractions * have been initialized, and the session history * has been initialized and validated. */ char dstdir[ MAXPATHLEN ]; /* absolute pathname of the destination directory */ bool_t dstdirisxfspr; /* destination directory is an xfs filesystem; xfs-specific * calls can be made when needed. */ ix_t dumpcnt; /* how many dumps have been applied completedly (A1) */ uuid_t lastdumpid; /* uuid of the last dump completely restored (A1) */ label_t lastdumplab; /* label of the last dump completely restored (A1) */ bool_t cumpr; /* is a cumulative restore (-r) */ bool_t interpr; /* interactive mode specified on command line (-i) */ bool_t existpr; /* existing files may not be overwritten (-e) */ bool_t changepr; /* only missing or old files may be overwritten (-E) */ bool_t newerpr; time32_t newertime; /* only files older than example may be overwritten (-n) */ bool_t ownerpr; /* attempt to restore owner/group (-o) */ ix_t stcnt; /* how many subtree args (both inclusive and exclusive) * are recorded in the subtree pages (-s) */ bool_t firststsensepr; bool_t firststsenseprvalpr; /* sense of first subtree arg */ ix_t stpgcnt; /* how many pages following the header page are reserved * for the subtree descriptors */ bool_t restoredmpr; /* restore DMAPI event settings */ bool_t restoreextattrpr; /* restore extended attributes */ ix_t parrestcnt; /* Count of partialy restored files. Used to speed * up searches in parrest. */ partial_rest_t parrest[ STREAM_SIMMAX * 2 - 2 ]; /* record of bytes restored to partially restored files. * Max possible is two per stream except the first * drive will never finish another drives file and the * last drive will never leave a file for another to * complete. */ } a; /* session state. */ struct { bool_t valpr; /* until this is true, a resume will ignore (and bzero) * this structure. validate just prior to applying * the directory dump, and after all fields marked (A2) * are correct. invalidate as soon as the session is * complete, and atomically update all fields marked * (A1) at the same time. dirattr abstraction must be * initialized prior to setting this. */ time32_t accumtime; /* for measuring elapsed time of restore */ uuid_t dumpid; /* id of dump currently being applied */ label_t dumplab; /* label of the dump being applied (A2) */ time32_t begintime; /* set when session begun and each time resumed */ bool_t stat_valpr; /* the following stats are not valid until the * first media file header has been read. */ uint64_t stat_inocnt; /* number of non-dir inos to restore during session */ uint64_t stat_inodone; /* number of non-dir inos restored so far */ off64_t stat_datacnt; /* bytes of ordinary files to restore during session */ off64_t stat_datadone; /* bytes of ordinary files restored so far */ ix_t descpgcnt; /* number of pages mapped for pers. media descriptors */ dh_t descfreeh; /* linked list of free media descriptor alloc objs (A2) */ dh_t strmheadh; /* head of singly-linked list of stream descriptors (A2) */ bool_t fullinvpr; /* have discovered and incorporated a full inventory * description into pers. may come from online or a * inventory media file. */ bool_t marknorefdonepr; /* have marked tree nodes as unreferenced by directory * entries, and nulled dirattr handles. */ bool_t dirdonepr; /* have applied all directories from a dirdump. */ bool_t adjrefdonepr; /* have adjusted marking of nodes no longer referenced * by directory entries. */ bool_t inomapsanitizedonepr; /* the inomap needs to b sanitized prior to subtree * or interactive selections */ bool_t stdonepr; /* have applied subtree selections */ bool_t interdonepr; /* have completed interactive subtree dialog */ bool_t treepostdonepr; /* all of the above treep ost-processing steps have * been completed. */ /* * nondir restore done here */ bool_t dirattrdonepr; /* directory attributes have been restored and * directory attributes registry has been deleted */ bool_t orphdeltriedpr; /* removed (or tried to remove) orphanage */ bool_t inomapdelpr; /* deleted session ino map */ } s; }; typedef struct pers pers_t; /* transient state. re-generated during each restore session */ struct tran { time32_t t_starttime; /* for measuring elapsed time of restore session */ size64_t t_dircnt; size64_t t_dirdonecnt; size64_t t_direntcnt; /* for displaying stats on directory reconstruction */ size64_t t_vmsz; /* how much vm may be used. recorded here from main, * passed to tree_init() once we have a valid media * file header */ bool_t t_toconlypr; /* just display table of contents; don't restore files */ bool_t t_noinvupdatepr; /* true if inventory is NOT to be updated when on-media * inventory encountered. */ bool_t t_dumpidknwnpr; /* determined during initialization; if false, set during * per-stream init */ bool_t t_dirattrinitdonepr; bool_t t_namreginitdonepr; bool_t t_treeinitdonepr; /* determinied during initialization, used during * per-stream restore */ uuid_t t_reqdumpid; bool_t t_reqdumpidvalpr; /* uuid of the dump as requested on cmd line */ char * t_reqdumplab; bool_t t_reqdumplabvalpr; /* label of the dump as requested on cmd line */ char *t_hkdir; /* absolute pathname of housekeeping directory */ int t_persfd; /* file descriptor of the persistent state file */ size64_t t_dirdumps; /* bitset of streams which contain a directory dump */ bool_t t_truncategenpr; /* force use of truncated generation numbers */ sync_t t_sync1; /* to single-thread attempt to validate command line * selection of dump with online inventory */ sync_t t_sync2; /* to single-thread dump selection by media scan */ sync_t t_sync3; /* to single-thread attempt to apply dirdump to tree */ sync_t t_sync4; /* to single-thread attempt to do tree post-processing * prior to non-directory restore */ sync_t t_sync5; /* to single-thread cleanup after applying non-dir restore */ qlockh_t t_pilockh; /* to establish critical regions while updating pers * inventory */ }; typedef struct tran tran_t; /* declarations of externally defined global symbols *************************/ extern void usage( void ); extern bool_t preemptchk( void ); extern char *homedir; extern bool_t pipeline; extern bool_t stdoutpiped; extern char *sistr; extern size_t pgsz; extern size_t pgmask; /* forward declarations of locally defined static functions ******************/ static void toconly_cleanup( void ); static Media_t *Media_create( ix_t thrdix ); static void Media_indir( Media_t *Mediap ); static void Media_indir( Media_t *Mediap ); static void Media_atnondir( Media_t *Mediap ); static rv_t Media_mfile_next( Media_t *Mediap, purp_t purp, sync_t *donesyncp, dh_t *filehp, global_hdr_t **grhdrpp, drive_hdr_t **drhdrpp, media_hdr_t **mrhdrpp, content_hdr_t **crhdrpp, content_inode_hdr_t **scrhdrpp, drive_t **drivepp, filehdr_t *fhdr ); static void Media_end( Media_t *Mediap ); static bool_t Media_prompt_change( drive_t *drivep, purp_t purp, bag_t *bagp, bool_t knownholespr, bool_t maybeholespr ); static bool_t Inv_validate_cmdline( void ); static bool_t dumpcompat( bool_t resumepr, ix_t level, uuid_t baseid, bool_t logpr ); static bool_t promptdumpmatch( ix_t thrdix, global_hdr_t *grhdrp, media_hdr_t *mrhdrp, content_hdr_t *crhdrp, content_inode_hdr_t *scrhdrp ); static void pi_checkpoint( dh_t fileh, drive_mark_t *drivemarkp, xfs_ino_t ino, off64_t off ); static bool_t pi_transcribe( inv_session_t *sessp ); static dh_t pi_addfile( Media_t *Mediap, global_hdr_t *grhdrp, drive_hdr_t *drhdrp, media_hdr_t *mrhdrp, content_inode_hdr_t *scrhdrp, drive_t * drivep ); static void pi_seestrmend( ix_t strmix ); static void pi_seeobjstrmend( ix_t strmix, ix_t mediaix ); static xfs_ino_t pi_scanfileendino( dh_t fileh ); static bool_t pi_alldone( void ); static bag_t * pi_neededobjs_dir_alloc( bool_t *knownholesprp, bool_t *maybeholesprp ); static bag_t * pi_neededobjs_nondir_alloc( bool_t *knownholesprp, bool_t *maybeholesprp, bool_t showobjindrivepr, bool_t markskippr ); static void pi_neededobjs_free( bag_t *bagp ); static void pi_bracketneededegrps( dh_t thisfileh, egrp_t *first_egrp, egrp_t *next_egrp ); static void pi_update_stats( off64_t sz ); static void pi_hiteod( ix_t strmix, ix_t objix ); static void pi_hiteom( ix_t strmix, ix_t objix ); static void pi_hitnextdump( ix_t strmix, ix_t objix, ix_t lastfileix ); static bool_t pi_know_no_more_on_object( purp_t purp, ix_t strmix, ix_t objix ); static bool_t pi_know_no_more_beyond_on_object( purp_t purp, ix_t strmix, ix_t objix, ix_t fileix ); static void pi_preclean( void ); static void pi_driveempty( ix_t driveix ); static void pi_note_indrive( ix_t driveix, uuid_t mediaid ); static void pi_note_underhead( dh_t thisobjh, dh_t thisfileh ); static void pi_lock( void ); static void pi_unlock( void ); static rv_t applydirdump( drive_t *drivep, dh_t fileh, content_inode_hdr_t *scrhdrp, filehdr_t *fhdrp ); static rv_t treepost( char *path1, char *path2 ); static rv_t applynondirdump( drive_t *drivep, dh_t fileh, content_inode_hdr_t *scrhdrp, char *path1, char *path2, filehdr_t *fhdrp ); static rv_t finalize( char *path1, char *path2 ); static void wipepersstate( void ); static rv_t read_filehdr( drive_t *drivep, filehdr_t *fhdrp, bool_t fhcs ); static rv_t restore_file( drive_t *drivep, filehdr_t *fhdrp, bool_t ehcs, bool_t ahcs, char *path1, char *path2 ); static bool_t restore_reg( drive_t *drivep, filehdr_t *fhdrp, rv_t *rvp, char *path ); static bool_t restore_extent_group( drive_t *drivep, filehdr_t *fhdrp, char *path, int fd, bool_t ehcs, rv_t *rvp); static bool_t restore_complete_reg( stream_context_t* ); static bool_t restore_spec( filehdr_t *fhdrp, rv_t *rvp, char *path ); static bool_t restore_symlink( drive_t *drivep, filehdr_t *fhdrp, rv_t *rvp, char *path, char *scratchpath, bool_t ehcs ); static rv_t read_extenthdr( drive_t *drivep, extenthdr_t *ehdrp, bool_t ehcs ); static rv_t read_dirent( drive_t *drivep, direnthdr_t *dhdrp, size_t direntbufsz, bool_t dhcs ); static rv_t discard_padding( size_t sz, drive_t *drivep ); static rv_t restore_extent( filehdr_t *fhdrp, extenthdr_t *ehdrp, int fd, char *path, drive_t *drivep, off64_t *bytesreadp ); static bool_t askinvforbaseof( uuid_t baseid, inv_session_t *sessp ); static void addobj( bag_t *bagp, uuid_t *objidp, label_t objlabel, bool_t indrivepr, ix_t indriveix ); static size_t cntobj( bag_t *bagp ); static bool_t gapneeded( egrp_t *firstegrpp, egrp_t *lastegrpp ); static char * ehdr_typestr( int32_t type ); static int egrpcmp( egrp_t *egrpap, egrp_t *egrpbp ); static void display_dump_label( bool_t lockpr, int mllevel, char *introstr, global_hdr_t *grhdrp, media_hdr_t *mrhdrp, content_hdr_t *crhdrp, content_inode_hdr_t *scrhdrp ); static void display_needed_objects( purp_t purp, bag_t *bagp, bool_t knownholespr, bool_t maybeholespr ); static void set_mcflag( ix_t thrdix ); static void clr_mcflag( ix_t thrdix ); static void pi_show( char *introstring ); static void pi_show_nomloglock( void ); static bool_t extattr_init( size_t drivecnt ); static char * get_extattrbuf( ix_t which ); static rv_t restore_extattr( drive_t *drivep, filehdr_t *fhdrp, char *path, bool_t ahcs, bool_t isdirpr, bool_t onlydoreadpr, dah_t dah ); static bool_t restore_dir_extattr_cb( char *path, dah_t dah ); static bool_t restore_dir_extattr_cb_cb( extattrhdr_t *ahdrp, void *ctxp ); static void setextattr( char *path, extattrhdr_t *ahdrp ); static void partial_reg(ix_t d_index, xfs_ino_t ino, off64_t fsize, off64_t offset, off64_t sz); static bool_t partial_check (xfs_ino_t ino, off64_t fsize); static bool_t partial_check2 (partial_rest_t *isptr, off64_t fsize); static int do_fssetdm_by_handle( char *path, fsdmidata_t *fdmp); static int quotafilecheck(char *type, char *dstdir, char *quotafile); /* definition of locally defined global variables ****************************/ bool_t content_media_change_needed; bool_t restore_rootdir_permissions; char *media_change_alert_program = NULL; size_t perssz; /* definition of locally defined static variables *****************************/ static pers_t *persp; /* mapped at init, ok to use */ static tran_t *tranp; /* allocated at init, ok to use */ static pers_desc_t *descp = 0; /* mapped on the fly; don't use! (see macros) */ static char *hkdirname = "xfsrestorehousekeepingdir"; static char *persname = "state"; static char *perspath = 0; static bool_t mcflag[ STREAM_SIMMAX ]; /* media change flag */ /* definition of locally defined global functions ****************************/ bool_t content_init( int argc, char *argv[ ], size64_t vmsz ) { char *dstdir; /* abs. path to destination dir */ bool_t cumpr; /* cmd line cumulative restore specification */ bool_t resumepr;/* cmd line resumed restore specification */ bool_t existpr; /* cmd line overwrite inhibit specification */ bool_t newerpr; /* cmd line overwrite inhibit specification */ time32_t newertime = 0; bool_t changepr;/* cmd line overwrite inhibit specification */ bool_t interpr; /* cmd line interactive mode requested */ bool_t ownerpr; /* cmd line chown/chmod requested */ bool_t restoredmpr; /* cmd line restore dm api attrs specification */ bool_t restoreextattrpr; /* cmd line restore extended attr spec */ bool_t sesscpltpr; /* force completion of prev interrupted session */ ix_t stcnt; /* cmd line number of subtrees requested */ bool_t firststsensepr; bool_t firststsenseprvalpr; ix_t stsz; /* bytes required to record subtree selections */ ix_t stpgcnt; /* pages required to hold subtree selections */ ix_t newstpgcnt;/* pages required to hold subtree selections */ ix_t descpgcnt; /* pages allocated for persistent descriptors */ struct stat statbuf; pid_t pid; int c; bool_t ok; int rval; bool_t fullpr; /* Calculate the size needed for the persistent inventory */ for ( perssz = pgsz; perssz < sizeof(pers_t); perssz += pgsz ) ; /* sanity checks */ assert( sizeof( pers_desc_t ) <= PERS_DESCSZ ); assert( PERS_DESCSZ <= pgsz ); assert( ! ( pgsz % PERS_DESCSZ )); assert( sizeof( extattrhdr_t ) == EXTATTRHDR_SZ ); assert( ! ( perssz % pgsz )); assert( SYNC_INIT == 0 ); mlog( MLOG_NITTY, "sizeof( pers_desc_t ) == %d, pgsz == %d, perssz == %d \n", sizeof( pers_desc_t ), pgsz, perssz ); /* allocate transient state */ tranp = ( tran_t * )calloc( 1, sizeof( tran_t )); assert( tranp ); /* allocate a qlock for establishing pi critical regions */ tranp->t_pilockh = qlock_alloc( QLOCK_ORD_PI ); /* record vmsz; will be used later to init tree abstraction */ tranp->t_vmsz = vmsz; /* record the start time for stats display */ tranp->t_starttime = time( 0 ); /* get command line options */ cumpr = BOOL_FALSE; resumepr = BOOL_FALSE; existpr = BOOL_FALSE; newerpr = BOOL_FALSE; changepr = BOOL_FALSE; ownerpr = BOOL_FALSE; restoredmpr = BOOL_FALSE; restoreextattrpr = BOOL_TRUE; sesscpltpr = BOOL_FALSE; stcnt = 0; firststsensepr = firststsenseprvalpr = BOOL_FALSE; stsz = 0; interpr = BOOL_FALSE; restore_rootdir_permissions = BOOL_FALSE; optind = 1; opterr = 0; while ( ( c = getopt( argc, argv, GETOPT_CMDSTRING )) != EOF ) { switch ( c ) { case GETOPT_TOC: tranp->t_toconlypr = BOOL_TRUE; break; case GETOPT_CUMULATIVE: cumpr = BOOL_TRUE; break; case GETOPT_RESUME: resumepr = BOOL_TRUE; break; case GETOPT_EXISTING: existpr = BOOL_TRUE; break; case GETOPT_NEWER: if ( ! optarg || optarg[ 0 ] == '-' ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c argument missing\n"), c ); usage( ); return BOOL_FALSE; } if ( stat( optarg, &statbuf )) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "unable to get status of -%c argument %s:" " %s\n"), c, optarg, strerror( errno )); return BOOL_FALSE; } newerpr = BOOL_TRUE; newertime = statbuf.st_mtime; break; case GETOPT_CHANGED: changepr = BOOL_TRUE; break; case GETOPT_OWNER: ownerpr = BOOL_TRUE; break; case GETOPT_WORKSPACE: if ( ! optarg || optarg[ 0 ] == '-' ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c argument missing\n"), c ); usage( ); return BOOL_FALSE; } if ( optarg[ 0 ] != '/' ) { tranp->t_hkdir = path_reltoabs( optarg, homedir ); if ( ! tranp->t_hkdir ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c argument %s is an " "invalid pathname\n"), c, optarg ); usage( ); return BOOL_FALSE; } mlog( MLOG_DEBUG, "alternate workspace path converted " "from %s to %s\n", optarg, tranp->t_hkdir ); } else { tranp->t_hkdir = optarg; } rval = stat( tranp->t_hkdir, &statbuf ); if ( rval ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "cannot stat -%c argument %s (%s): %s\n"), c, optarg, tranp->t_hkdir, strerror( errno )); usage( ); return BOOL_FALSE; } if ( ( statbuf.st_mode & S_IFMT ) != S_IFDIR ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c argument %s (%s) " "is not a directory\n"), c, optarg, tranp->t_hkdir ); usage( ); return BOOL_FALSE; } break; case GETOPT_DUMPLABEL: if ( tranp->t_reqdumplabvalpr ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "too many -%c arguments: " "\"-%c %s\" already given\n"), c, c, tranp->t_reqdumplab ); usage( ); return BOOL_FALSE; } if ( ! optarg || optarg[ 0 ] == '-' ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c argument missing\n"), c ); usage( ); return BOOL_FALSE; } if ( strlen( optarg ) > sizeofmember( pers_t, s.dumplab )) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c argument %s too long: max is %d\n"), c, optarg, sizeofmember( pers_t, s.dumplab )); usage( ); return BOOL_FALSE; } tranp->t_reqdumplab = optarg; tranp->t_reqdumplabvalpr = BOOL_TRUE; break; case GETOPT_SESSIONID: if ( tranp->t_reqdumpidvalpr ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "too many -%c arguments\n"), c ); usage( ); return BOOL_FALSE; } if ( ! optarg || optarg[ 0 ] == '-' ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c argument missing\n"), c ); usage( ); return BOOL_FALSE; } if (uuid_parse( optarg, tranp->t_reqdumpid ) < 0 ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c argument not a valid uuid\n"), c ); usage( ); return BOOL_FALSE; } tranp->t_reqdumpidvalpr = BOOL_TRUE; break; case GETOPT_SUBTREE: case GETOPT_NOSUBTREE: if ( ! optarg || optarg[ 0 ] == 0 || optarg[ 0 ] == '-' ) { mlog( MLOG_NORMAL, _( "-%c argument missing\n"), c ); usage( ); return BOOL_FALSE; } if ( optarg[ 0 ] == '/' ) { mlog( MLOG_NORMAL, _( "-%c argument must be relative\n"), c ); usage( ); return BOOL_FALSE; } stcnt++; if ( ! firststsenseprvalpr ) { if ( c == GETOPT_SUBTREE ) { firststsensepr = BOOL_TRUE; } else { firststsensepr = BOOL_FALSE; } firststsenseprvalpr = BOOL_TRUE; } stsz += sizeof( stdesc_t ) + strlen( optarg ) + ( STDESCALIGN - 1 ); stsz &= ~( STDESCALIGN - 1 ); break; case GETOPT_INTERACTIVE: if ( ! dlog_allowed( )) { mlog( MLOG_NORMAL, _( "-%c unavailable: no /dev/tty\n"), GETOPT_INTERACTIVE ); return BOOL_FALSE; } interpr = BOOL_TRUE; break; case GETOPT_NOINVUPDATE: tranp->t_noinvupdatepr = BOOL_TRUE; break; case GETOPT_SETDM: restoredmpr = BOOL_TRUE; break; case GETOPT_ALERTPROG: if ( ! optarg || optarg[ 0 ] == '-' ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c argument missing\n"), c ); usage( ); return BOOL_FALSE; } media_change_alert_program = optarg; break; case GETOPT_NOEXTATTR: restoreextattrpr = BOOL_FALSE; break; case GETOPT_SESSCPLT: sesscpltpr = BOOL_TRUE; break; case GETOPT_SMALLWINDOW: /* obsolete */ break; case GETOPT_ROOTPERM: restore_rootdir_permissions = BOOL_TRUE; break; case GETOPT_FMT2COMPAT: tranp->t_truncategenpr = BOOL_TRUE; break; } } /* command line option error checking */ if ( cumpr && tranp->t_toconlypr ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c and -%c option cannot be used together\n"), GETOPT_TOC, GETOPT_CUMULATIVE ); usage( ); return BOOL_FALSE; } if ( resumepr && tranp->t_toconlypr ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c and -%c option cannot be used together\n"), GETOPT_TOC, GETOPT_RESUME ); usage( ); return BOOL_FALSE; } /* assume all streams contain a directory dump. streams will remove * themselves from this bitset if they do not contain a directory dump. */ assert( drivecnt <= sizeof(tranp->t_dirdumps) * NBBY ); tranp->t_dirdumps = ( 1ULL << drivecnt ) - 1; /* the user may specify stdin as the restore source stream, * by a single dash ('-') with no option letter. This must * appear between the last lettered argument and the destination * directory pathname. */ if ( optind < argc && ! strcmp( argv[ optind ], "-" )) { optind++; } /* the last argument must be the destination directory. not * required if table-of-contents display, or if a resumed restore * or a delta restore. */ if ( ! tranp->t_toconlypr ) { if ( optind >= argc ) { dstdir = 0; } else { if ( argv[ optind ][ 0 ] != '/' ) { dstdir = path_reltoabs( argv[ optind ], homedir ); if ( ! dstdir ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "destination directory %s " "invalid pathname\n"), argv[ optind ] ); usage( ); return BOOL_FALSE; } mlog( MLOG_DEBUG, "restore destination path converted " "from %s to %s\n", argv[ optind ], dstdir ); } else { dstdir = argv[ optind ]; } rval = stat( dstdir, &statbuf ); if ( rval ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "cannot stat destination directory %s: " "%s\n"), dstdir, strerror( errno )); usage( ); return BOOL_FALSE; } if ( ( statbuf.st_mode & S_IFMT ) != S_IFDIR ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "specified destination %s " "is not a directory\n"), dstdir ); usage( ); return BOOL_FALSE; } } } else { if ( optind < argc ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "do not specify destination directory if " "contents only restore invoked (-%c option)\n"), GETOPT_TOC ); usage( ); return BOOL_FALSE; } dstdir = "."; } /* generate a full pathname for the housekeeping dir. * the housekeeping dir will by default be placed in the * destination directory, unless this is a toc, in which case * it will be placed in the current directory. in either case, an * alternate directory may be specified on the command line. * if this is toconly, modify the housekeeping dir's name with * the pid. */ if ( ! tranp->t_hkdir ) { if ( tranp->t_toconlypr ) { tranp->t_hkdir = homedir; } else { if ( ! dstdir ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "destination directory " "not specified\n") ); usage( ); return BOOL_FALSE; } else { tranp->t_hkdir = dstdir; } } } if ( tranp->t_toconlypr ) { pid = getpid( ); } else { pid = 0; } tranp->t_hkdir = open_pathalloc( tranp->t_hkdir, hkdirname, pid ); /* if this is a table-of-contents only restore, register an * exit handler to get rid of the housekeeping directory and * its contents. NOTE: needs several tran fields initialized! */ if ( tranp->t_toconlypr ) { atexit( toconly_cleanup ); } /* create housekeeping dir if not present */ rval = mkdir( tranp->t_hkdir, S_IRWXU ); if ( rval && errno != EEXIST ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "unable to create %s: %s\n"), tranp->t_hkdir, strerror( errno )); return BOOL_FALSE; } /* build a full pathname to pers. state file */ assert( ! perspath ); perspath = open_pathalloc( tranp->t_hkdir, persname, 0 ); /* open, creating if non-existent */ tranp->t_persfd = open( perspath, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR ); if ( tranp->t_persfd < 0 ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "could not open/create persistent state file %s: %s\n"), perspath, strerror( errno )); return BOOL_FALSE; } /* temporarily mmap just the header, and validate the command line * arguments. three cases: no dumps applied so far, or one or more * dumps applied completely, or restore session was interrupted */ persp = ( pers_t * ) mmap_autogrow(perssz, tranp->t_persfd, 0); if ( persp == ( pers_t * )-1 ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "could not map persistent state file hdr %s: %s\n"), perspath, strerror( errno )); return BOOL_FALSE; } /* but first setup or verify the on-disk format information */ if ( ! persp->a.valpr ) { /* this is the first restore session */ persp->v.housekeeping_magic = HOUSEKEEPING_MAGIC; persp->v.housekeeping_version = HOUSEKEEPING_VERSION; persp->v.pagesize = pgsz; } else { /* cumulative or resuming a restore, verify the header */ if ( persp->v.housekeeping_magic != HOUSEKEEPING_MAGIC ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "%s format corrupt or wrong endianness " "(0x%x, expected 0x%x)\n"), hkdirname, persp->v.housekeeping_magic, HOUSEKEEPING_MAGIC ); return BOOL_FALSE; } if ( persp->v.housekeeping_version != HOUSEKEEPING_VERSION ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "%s format version differs from previous " "restore (%u, expected %u)\n"), hkdirname, persp->v.housekeeping_version, HOUSEKEEPING_VERSION ); return BOOL_FALSE; } if ( persp->v.pagesize != pgsz ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "%s format differs from previous " "restore due to page size change " "(was %lu, now %lu)\n"), hkdirname, persp->v.pagesize, pgsz ); return BOOL_FALSE; } } if ( ! persp->a.valpr ) { if ( ! dstdir ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "destination directory not specified\n") ); usage( ); return BOOL_FALSE; } if ( strlen( dstdir ) >= sizeofmember( pers_t, a.dstdir )) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "destination directory pathname too long: " "max is %d characters\n"), sizeofmember( pers_t, a.dstdir ) - 1 ); usage( ); return BOOL_FALSE; } if ( resumepr ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c option invalid: there is no " "interrupted restore to resume\n"), GETOPT_RESUME ); usage( ); return BOOL_FALSE; } if ( sesscpltpr ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c option invalid: there is no " "interrupted restore to force completion of\n"), GETOPT_SESSCPLT ); usage( ); return BOOL_FALSE; } } else if ( ! persp->s.valpr ) { if ( ! cumpr ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "must rm -rf %s prior to noncumulative restore\n"), tranp->t_hkdir ); return BOOL_FALSE; } if ( resumepr ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c option invalid: there is no " "interrupted restore to resume\n"), GETOPT_RESUME ); usage( ); return BOOL_FALSE; } if ( sesscpltpr ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c option invalid: there is no " "interrupted restore to force completion of\n"), GETOPT_SESSCPLT ); usage( ); return BOOL_FALSE; } if ( existpr ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c valid only when initiating " "cumulative restore\n"), GETOPT_EXISTING ); return BOOL_FALSE; } if ( newerpr ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c valid only when initiating " "cumulative restore\n"), GETOPT_NEWER ); return BOOL_FALSE; } if ( changepr ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c valid only when initiating " "cumulative restore\n"), GETOPT_CHANGED ); return BOOL_FALSE; } if ( ownerpr ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c valid only when initiating " "cumulative restore\n"), GETOPT_OWNER ); return BOOL_FALSE; } if ( stcnt ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c and -%c valid only when initiating " "cumulative restore\n"), GETOPT_SUBTREE, GETOPT_NOSUBTREE ); return BOOL_FALSE; } if ( tranp->t_truncategenpr ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c valid only when initiating " "cumulative restore\n"), GETOPT_FMT2COMPAT ); return BOOL_FALSE; } } else { if ( ! resumepr && ! sesscpltpr ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c option required to resume " "or " "-%c option required to force completion of " "previously " "interrupted restore session\n"), GETOPT_RESUME, GETOPT_SESSCPLT ); return BOOL_FALSE; } if ( tranp->t_reqdumplabvalpr ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c valid only when initiating restore\n"), GETOPT_DUMPLABEL ); return BOOL_FALSE; } if ( tranp->t_reqdumpidvalpr ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c valid only when initiating restore\n"), GETOPT_SESSIONID ); return BOOL_FALSE; } if ( existpr ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c valid only when initiating restore\n"), GETOPT_EXISTING ); return BOOL_FALSE; } if ( newerpr ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c valid only when initiating restore\n"), GETOPT_NEWER ); return BOOL_FALSE; } if ( changepr ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c valid only when initiating restore\n"), GETOPT_CHANGED ); return BOOL_FALSE; } if ( ownerpr ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c valid only when initiating restore\n"), GETOPT_OWNER ); return BOOL_FALSE; } if ( interpr ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c valid only when initiating restore\n"), GETOPT_INTERACTIVE ); return BOOL_FALSE; } if ( stcnt ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c and -%c valid only when initiating restore\n"), GETOPT_SUBTREE, GETOPT_NOSUBTREE ); return BOOL_FALSE; } if ( tranp->t_truncategenpr ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c valid only when initiating restore\n"), GETOPT_FMT2COMPAT ); return BOOL_FALSE; } } if ( persp->a.valpr ) { if ( restoredmpr && persp->a.restoredmpr != restoredmpr) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c cannot reset flag from previous restore\n"), GETOPT_SETDM ); return BOOL_FALSE; } if ( ! restoreextattrpr && persp->a.restoreextattrpr != restoreextattrpr) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "-%c cannot reset flag from previous restore\n"), GETOPT_NOEXTATTR ); return BOOL_FALSE; } } /* force owner option if root */ ownerpr = ( geteuid( ) == 0 ) ? BOOL_TRUE : ownerpr; /* force completion of interrupted restore if asked to do so */ if ( sesscpltpr ) { char *path1; char *path2; rv_t rv; int rval; path1 = ( char * )calloc( 1, 2 * MAXPATHLEN ); assert( path1 ); path2 = ( char * )calloc( 1, 2 * MAXPATHLEN ); assert( path2 ); assert( persp->a.valpr ); assert( persp->s.valpr ); rval = chdir( persp->a.dstdir ); if ( rval ) { mlog( MLOG_NORMAL, _( "chdir %s failed: %s\n"), persp->a.dstdir, strerror( errno )); return BOOL_FALSE; } ok = dirattr_init( tranp->t_hkdir, BOOL_TRUE, ( uint64_t )0 ); if ( ! ok ) { return BOOL_FALSE; } ok = namreg_init( tranp->t_hkdir, BOOL_TRUE, ( uint64_t )0 ); if ( ! ok ) { return BOOL_FALSE; } ok = inomap_sync_pers( tranp->t_hkdir ); if ( ! ok ) { return BOOL_FALSE; } /* This is only a full restore if we're doing a level * 0 restore. */ if (persp->a.dumpcnt == 0) { fullpr = BOOL_TRUE; } else { fullpr = BOOL_FALSE; } ok = tree_sync( tranp->t_hkdir, persp->a.dstdir, tranp->t_toconlypr, fullpr, persp->a.dstdirisxfspr ); if ( ! ok ) { return BOOL_FALSE; } rv = finalize( path1, path2 ); free( ( void * )path1 ); free( ( void * )path2 ); switch ( rv ) { case RV_OK: break; case RV_ERROR: return EXIT_ERROR; case RV_INTR: return EXIT_NORMAL; case RV_CORE: default: return EXIT_FAULT; } } /* for the three cases, calculate old and new mapping params * and wipe partial state */ if ( ! persp->a.valpr ) { stpgcnt = 0; newstpgcnt = ( stsz + pgmask ) / pgsz; descpgcnt = 0; memset( ( void * )&persp->a, 0, sizeof( pers_t ) - offsetofmember( pers_t, a )); } else if ( ! persp->s.valpr ) { stpgcnt = persp->a.stpgcnt; newstpgcnt = stpgcnt; descpgcnt = 0; memset( ( void * )&persp->s, 0, sizeofmember( pers_t, s )); } else { stpgcnt = persp->a.stpgcnt; newstpgcnt = stpgcnt; descpgcnt = persp->s.descpgcnt; assert( resumepr ); mlog( MLOG_VERBOSE, _( "resuming restore previously begun %s\n"), ctimennl( &persp->s.begintime )); persp->s.begintime = time( 0 ); } /* unmap temp mapping of hdr, truncate, and remap hdr/subtrees */ rval = munmap( ( void * )persp, perssz ); assert( ! rval ); rval = ftruncate( tranp->t_persfd, ( off_t )perssz + ( off_t )( stpgcnt + descpgcnt ) * ( off_t )pgsz ); assert( ! rval ); stpgcnt = newstpgcnt; persp = ( pers_t * ) mmap_autogrow( perssz + stpgcnt * pgsz, tranp->t_persfd, 0); if ( persp == ( pers_t * )-1 ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "could not map persistent state file %s: %s\n"), perspath, strerror( errno )); return BOOL_FALSE; } /* if first restore session, record cmd line args and subtrees * and start time. */ if ( ! persp->a.valpr ) { stdesc_t *stdescp; strcpy( persp->a.dstdir, dstdir ); persp->a.dstdirisxfspr = platform_test_xfs_path( dstdir ); if ( cumpr ) { persp->a.cumpr = cumpr; } if ( interpr ) { persp->a.interpr = interpr; } if ( existpr ) { persp->a.existpr = existpr; } if ( changepr ) { persp->a.changepr = changepr; } if ( ownerpr ) { persp->a.ownerpr = ownerpr; } if ( newerpr ) { persp->a.newerpr = newerpr; persp->a.newertime = newertime; } persp->a.restoredmpr = restoredmpr; if ( ! persp->a.dstdirisxfspr ) { restoreextattrpr = BOOL_FALSE; } persp->a.restoreextattrpr = restoreextattrpr; persp->a.stcnt = stcnt; persp->a.firststsensepr = firststsensepr; persp->a.firststsenseprvalpr = firststsenseprvalpr; persp->a.stpgcnt = stpgcnt; optind = 1; opterr = 0; stdescp = ( stdesc_t * )( ( char * )persp + perssz ); while ( ( c = getopt( argc, argv, GETOPT_CMDSTRING )) != EOF ) { size_t stdsz; switch ( c ) { case GETOPT_SUBTREE: case GETOPT_NOSUBTREE: stdescp->std_sensepr = ( c == GETOPT_SUBTREE ) ? BOOL_TRUE : BOOL_FALSE; stdsz = sizeof( stdesc_t ) + strlen( optarg ) + ( STDESCALIGN - 1 ); stdsz &= ~( STDESCALIGN - 1 ); assert( stdsz <= ( size_t )OFFMAX ); stdescp->std_nextoff = ( off_t )stdsz; strcpy( stdescp->std_path, optarg ); stdescp = ( stdesc_t * ) ( ( char * )stdescp + stdsz ); stcnt--; break; } } assert( stcnt == 0 ); } /* initialize the local extattr abstraction. must be done even if * we don't intend to restore extended attributes */ ok = extattr_init( drivecnt ); if ( ! ok ) { return BOOL_FALSE; } /* effectively initialize libhandle on this filesystem by * allocating a file system handle. this needs to be done * before any open_by_handle() calls (and possibly other * libhandle calls). */ if ( persp->a.dstdirisxfspr ) { void *fshanp; size_t fshlen=0; if(path_to_fshandle(persp->a.dstdir, &fshanp, &fshlen)) { mlog( MLOG_NORMAL, _("unable to construct a file " "system handle for %s: %s\n"), persp->a.dstdir, strerror( errno )); return BOOL_FALSE; } /* libhandle has it cached, release this copy */ free_handle(fshanp, fshlen); } /* map in pers. inv. descriptors, if any. NOTE: this ptr is to be * referenced ONLY via the macros provided; the descriptors will be * occasionally remapped, causing the ptr to change. */ assert( ! descp ); if ( descpgcnt ) { descp = ( pers_desc_t * ) mmap_autogrow( descpgcnt * pgsz, tranp->t_persfd, ( off_t )perssz + ( off_t )( stpgcnt * pgsz )); if ( descp == ( pers_desc_t * )-1 ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "could not map persistent state file inv %s: " "%s (%d)\n"), perspath, strerror( errno ), errno ); descp = 0; return BOOL_FALSE; } pi_preclean( ); } /* if resuming an interrupted restore, indicate we know the id * of the dump session being restored. otherwise, it will be determined * during coordination of per-drive threads. */ if ( persp->a.valpr && persp->s.valpr ) { persp->s.begintime = time( 0 ); tranp->t_dumpidknwnpr = BOOL_TRUE; } /* sync up with the directory attributes registry. * starts fresh with each dump session restored. * determine if full init needed instead. */ if ( persp->a.valpr && persp->s.valpr ) { ok = dirattr_init( tranp->t_hkdir, BOOL_TRUE, ( uint64_t )0 ); if ( ! ok ) { return BOOL_FALSE; } tranp->t_dirattrinitdonepr = BOOL_TRUE; } /* sync up with the name registry. created by the * first session, retained by subsequent sessions. * determine if full init needed instead. */ if ( persp->a.valpr ) { ok = namreg_init( tranp->t_hkdir, BOOL_TRUE, ( uint64_t )0 ); if ( ! ok ) { return BOOL_FALSE; } tranp->t_namreginitdonepr = BOOL_TRUE; } /* sync up with the inomap abstraction. created anew with each fresh * restore session, but persistent after tree updated with dirdump. * determine if full init needed instead. */ ok = inomap_sync_pers( tranp->t_hkdir ); if ( ! ok ) { return BOOL_FALSE; } /* sync up with the tree abstraction. created by the * first session, retained by subsequent sessions. * don't call tree_init( ) from here; can only be called * when a valid media file header is at hand. */ if ( persp->a.valpr ) { /* This is only a full restore if we're doing a level * 0 restore. */ if (persp->a.dumpcnt == 0) { fullpr = BOOL_TRUE; } else { fullpr = BOOL_FALSE; } ok = tree_sync( tranp->t_hkdir, persp->a.dstdir, tranp->t_toconlypr, fullpr, persp->a.dstdirisxfspr ); if ( ! ok ) { return BOOL_FALSE; } tranp->t_treeinitdonepr = BOOL_TRUE; } /* set media change flags to FALSE; */ { ix_t ix; ix_t endix = sizeof( mcflag ) / sizeof( mcflag[ 0 ] ); for ( ix = 0 ; ix < endix ; ix++ ) { mcflag[ ix ] = BOOL_FALSE; } } content_media_change_needed = BOOL_FALSE; pi_show( " at initialization" ); return BOOL_TRUE; } /* stream thread entry point - returns exit code */ int content_stream_restore( ix_t thrdix ) { dh_t fileh; Media_t *Mediap; /* local media abstraction */ char *path1; char *path2; drive_t *drivep; int dcaps; global_hdr_t *grhdrp; drive_hdr_t *drhdrp; media_hdr_t *mrhdrp; content_hdr_t *crhdrp; content_inode_hdr_t *scrhdrp; stream_context_t *strctxp; filehdr_t fhdr; /* save hdr terminating dir restore */ uuid_t lastdumprejectedid; rv_t rv; bool_t ok; int rval; /* allocate two path buffers */ path1 = ( char * )calloc( 1, 2 * MAXPATHLEN ); assert( path1 ); path2 = ( char * )calloc( 1, 2 * MAXPATHLEN ); assert( path2 ); /* set the current directory to dstdir. the tree abstraction * depends on the current directory being the root of the * destination file system. */ rval = chdir( persp->a.dstdir ); if ( rval ) { mlog( MLOG_NORMAL, _( "chdir %s failed: %s\n"), persp->a.dstdir, strerror( errno )); return mlog_exit(EXIT_ERROR, RV_ERROR); } /* set my file creation mask to zero, to avoid modifying the * dumped mode bits */ ( void )umask( 0 ); /* initialize the Media abstraction */ Mediap = Media_create( thrdix ); /* * initialize the stream context */ strctxp = (stream_context_t *)calloc(1, sizeof(stream_context_t)); if (!strctxp) { mlog( MLOG_NORMAL | MLOG_ERROR, _("malloc of stream context failed (%d bytes): %s\n"), sizeof(stream_context_t), strerror( errno )); return mlog_exit(EXIT_ERROR, RV_ERROR); } strctxp->sc_fd = -1; Mediap->M_drivep->d_strmcontextp = (void *)strctxp; /* if we don't know the dump session id to restore, * first see if command line options can be validated * against the online inventory to identify it. only * one stream needs to do this; the others just wait. * side-effect of validation is to incorporate the online * inventory into the persistent state. */ if ( tranp->t_dumpidknwnpr ) { tranp->t_sync1 = SYNC_DONE; } while ( tranp->t_sync1 != SYNC_DONE ) { lock( ); if ( tranp->t_sync1 == SYNC_BUSY ) { unlock( ); sleep( 1 ); if ( cldmgr_stop_requested( )) { return mlog_exit(EXIT_NORMAL, RV_INTR); } continue; } if ( tranp->t_sync1 == SYNC_DONE ) { unlock( ); continue; } tranp->t_sync1 = SYNC_BUSY; unlock( ); mlog( MLOG_DEBUG, "checking and validating command line dump id/label\n" ); ok = Inv_validate_cmdline( ); /* side-effect - searches for and incorporates online inv * into pi, and makes persp->s.dumpid valid. */ if ( ok == BOOL_ERROR ) { return mlog_exit(EXIT_ERROR, RV_OPT); } tranp->t_dumpidknwnpr = ok; tranp->t_sync1 = SYNC_DONE; } /* if we still don't know the session to restore, search the * media for a match either to the command line arguments or * until the operator selects a media file from the desired * dump. */ if ( tranp->t_dumpidknwnpr ) { tranp->t_sync2 = SYNC_DONE; } uuid_clear(lastdumprejectedid); if ( tranp->t_sync2 != SYNC_DONE ) { mlog( MLOG_VERBOSE, _( "searching media for dump\n") ); } while ( tranp->t_sync2 != SYNC_DONE ) { bool_t matchpr; inv_session_t *sessp; bool_t resumepr; ix_t level; uuid_t *baseidp; rv = Media_mfile_next( Mediap, PURP_SEARCH, &tranp->t_sync2, 0, &grhdrp, &drhdrp, &mrhdrp, &crhdrp, &scrhdrp, &drivep, &fhdr ); switch ( rv ) { case RV_OK: break; case RV_DONE: case RV_NOMORE: continue; case RV_INTR: case RV_QUIT: case RV_DRIVE: Media_end( Mediap ); return mlog_exit(EXIT_NORMAL, rv); case RV_CORE: default: Media_end( Mediap ); return mlog_exit(EXIT_FAULT, rv); } dcaps = drivep->d_capabilities; lock( ); while ( tranp->t_sync2 == SYNC_BUSY ) { unlock( ); sleep( 1 ); if ( cldmgr_stop_requested( )) { Media_end( Mediap ); return mlog_exit(EXIT_NORMAL, RV_INTR); } lock( ); } if ( tranp->t_sync2 == SYNC_DONE ) { unlock( ); continue; } tranp->t_sync2 = SYNC_BUSY; unlock( ); mlog( MLOG_DEBUG, "dump found: checking\n" ); matchpr = BOOL_FALSE; resumepr = ( scrhdrp->cih_dumpattr & CIH_DUMPATTR_RESUME ); assert( scrhdrp->cih_level >= 0 ); level = ( ix_t )scrhdrp->cih_level; baseidp = resumepr ? &scrhdrp->cih_resume_id : &scrhdrp->cih_last_id; if ( tranp->t_reqdumpidvalpr ) { if ( uuid_compare( tranp->t_reqdumpid, grhdrp->gh_dumpid) == 0) { matchpr = BOOL_TRUE; display_dump_label( BOOL_TRUE, /* lock */ MLOG_VERBOSE, _( "found dump matching " "specified id:\n"), grhdrp, mrhdrp, crhdrp, scrhdrp ); } } else if ( tranp->t_reqdumplabvalpr ) { if ( ! strncmp( tranp->t_reqdumplab, grhdrp->gh_dumplabel, sizeof( grhdrp->gh_dumplabel ))) { matchpr = BOOL_TRUE; display_dump_label( BOOL_TRUE, /* lock */ MLOG_VERBOSE, _( "found dump matching " "specified label:\n"), grhdrp, mrhdrp, crhdrp, scrhdrp ); } } else if ( dumpcompat( resumepr, level, *baseidp, BOOL_FALSE )) { if ( uuid_compare( lastdumprejectedid, grhdrp->gh_dumpid) == 0) { matchpr = BOOL_FALSE; } else { if ( dlog_allowed( ) && ( ( dcaps & DRIVE_CAP_FILES ) || ( dcaps & DRIVE_CAP_REMOVABLE ) || drivecnt > 1 )) { matchpr = promptdumpmatch( thrdix, grhdrp, mrhdrp, crhdrp, scrhdrp ); } else { matchpr = BOOL_TRUE; display_dump_label( BOOL_TRUE,/* lock */ MLOG_VERBOSE, _( "dump " "description: \n"), grhdrp, mrhdrp, crhdrp, scrhdrp ); } } } if ( cldmgr_stop_requested( )) { Media_end( Mediap ); return mlog_exit(EXIT_NORMAL, RV_INTR); } if ( ! matchpr ) { Media_end( Mediap ); uuid_copy(lastdumprejectedid, grhdrp->gh_dumpid); tranp->t_sync2 = SYNC_INIT; if ( ! dlog_allowed( ) || ( ! ( dcaps & DRIVE_CAP_FILES ) && ! ( dcaps & DRIVE_CAP_REMOVABLE ))) { return mlog_exit(EXIT_NORMAL, RV_QUIT); } continue; } if ( ! dumpcompat( resumepr, level, *baseidp, BOOL_TRUE )) { Media_end( Mediap ); return mlog_exit(EXIT_ERROR, RV_COMPAT); } strncpyterm( persp->s.dumplab, grhdrp->gh_dumplabel, sizeof( persp->s.dumplab )); sessp = 0; /* don't look at the online inventory if the input is piped */ if ( ! drivep->d_isnamedpipepr && ! drivep->d_isunnamedpipepr ) { ok = inv_get_session_byuuid(NULL, &grhdrp->gh_dumpid, &sessp); if ( ok && sessp ) { mlog( MLOG_VERBOSE, _( "using online session inventory\n") ); persp->s.fullinvpr = pi_transcribe( sessp ); inv_free_session( &sessp ); } } fileh = pi_addfile( Mediap, grhdrp, drhdrp, mrhdrp, scrhdrp, drivep ); /* done here because Media_mfile_next doesn't know * if this is a match */ if ( fileh == DH_NULL ) { return mlog_exit(EXIT_FAULT, RV_ERROR); } uuid_copy(persp->s.dumpid,grhdrp->gh_dumpid); persp->s.begintime = time( 0 ); tranp->t_dumpidknwnpr = BOOL_TRUE; tranp->t_sync2 = SYNC_DONE; } /* all drives coordinate in attempt to apply session dir dump. * only one actually completes. */ if ( persp->s.dirdonepr ) { tranp->t_sync3 = SYNC_DONE; } if ( tranp->t_sync3 != SYNC_DONE ) { mlog( MLOG_VERBOSE, _( "searching media for directory dump\n") ); } while ( tranp->t_sync3 != SYNC_DONE ) { rv = Media_mfile_next( Mediap, PURP_DIR, &tranp->t_sync3, &fileh, &grhdrp, &drhdrp, &mrhdrp, &crhdrp, &scrhdrp, &drivep, &fhdr ); switch ( rv ) { case RV_OK: break; case RV_DONE: case RV_NOMORE: continue; case RV_INTR: case RV_QUIT: case RV_DRIVE: Media_end( Mediap ); return mlog_exit(EXIT_NORMAL, rv); case RV_CORE: default: Media_end( Mediap ); return mlog_exit(EXIT_FAULT, rv); } dcaps = drivep->d_capabilities; assert( fileh != DH_NULL ); lock( ); if ( tranp->t_sync3 == SYNC_BUSY ) { unlock( ); mlog( MLOG_TRACE, "waiting for directories to be restored\n" ); lock( ); } while ( tranp->t_sync3 == SYNC_BUSY ) { unlock( ); #if DEBUG_DUMPSTREAMS { static int count[STREAM_MAX] = {0}; int streamix = stream_getix( pthread_self() ); if (++(count[streamix]) == 30) { mlog( MLOG_TRACE, "still waiting for dirs to be restored\n"); count[streamix] = 0; } } #endif sleep( 1 ); if ( cldmgr_stop_requested( )) { Media_end( Mediap ); return mlog_exit(EXIT_NORMAL, RV_INTR); } lock( ); } if ( tranp->t_sync3 == SYNC_DONE ) { unlock( ); continue; } if ( !(scrhdrp->cih_dumpattr & CIH_DUMPATTR_DIRDUMP) ) { /* if no streams have a directory dump, issue a * message and exit. first set SYNC_BUSY to prevent * other threads from coming through here and issuing * the same message. */ tranp->t_dirdumps &= ~(1ULL << thrdix); if ( !tranp->t_dirdumps ) { tranp->t_sync3 = SYNC_BUSY; } unlock( ); if ( !tranp->t_dirdumps ) { mlog( MLOG_VERBOSE | MLOG_ERROR, _( "no directory dump found\n") ); Media_end( Mediap ); return mlog_exit(EXIT_NORMAL, RV_ERROR); } sleep( 1 ); if ( cldmgr_stop_requested( )) { Media_end( Mediap ); return mlog_exit(EXIT_NORMAL, RV_INTR); } continue; } tranp->t_sync3 = SYNC_BUSY; unlock( ); if ( ! tranp->t_dirattrinitdonepr ) { mlog( MLOG_TRACE, "initializing directory attributes registry\n" ); mlog( MLOG_NITTY, "content_stream_restore: dircnt %llu\n", scrhdrp->cih_inomap_dircnt ); ok = dirattr_init( tranp->t_hkdir, BOOL_FALSE, scrhdrp->cih_inomap_dircnt ); if ( ! ok ) { Media_end( Mediap ); return mlog_exit(EXIT_ERROR, RV_ERROR); } tranp->t_dirattrinitdonepr = BOOL_TRUE; } if ( ! tranp->t_namreginitdonepr ) { mlog( MLOG_TRACE, "initializing directory entry name registry\n" ); ok = namreg_init( tranp->t_hkdir, BOOL_FALSE, scrhdrp->cih_inomap_dircnt + scrhdrp->cih_inomap_nondircnt ); if ( ! ok ) { Media_end( Mediap ); return mlog_exit(EXIT_ERROR, RV_ERROR); } tranp->t_namreginitdonepr = BOOL_TRUE; } if ( ! tranp->t_treeinitdonepr ) { bool_t fullpr; fullpr = ( scrhdrp->cih_level == 0 ) && ! ( scrhdrp->cih_dumpattr & CIH_DUMPATTR_RESUME ); mlog( MLOG_TRACE, "initializing directory hierarchy image\n" ); ok = tree_init( tranp->t_hkdir, persp->a.dstdir, tranp->t_toconlypr, persp->a.ownerpr, scrhdrp->cih_rootino, scrhdrp->cih_inomap_firstino, scrhdrp->cih_inomap_lastino, scrhdrp->cih_inomap_dircnt, scrhdrp->cih_inomap_nondircnt, tranp->t_vmsz, fullpr, persp->a.restoredmpr, persp->a.dstdirisxfspr, grhdrp->gh_version, tranp->t_truncategenpr ); if ( ! ok ) { Media_end( Mediap ); return mlog_exit(EXIT_ERROR, RV_ERROR); } tranp->t_treeinitdonepr = BOOL_TRUE; } else { ok = tree_check_dump_format( grhdrp->gh_version ); if ( ! ok ) { Media_end( Mediap ); return mlog_exit(EXIT_ERROR, RV_ERROR); } } /* commit the session and accumulative state */ persp->s.valpr = BOOL_TRUE; persp->a.valpr = BOOL_TRUE; mlog( MLOG_VERBOSE, _( "reading directories\n") ); win_locks_off(); /* we are single threaded here */ rv = applydirdump( drivep, fileh, scrhdrp, &fhdr ); win_locks_on(); mlog( MLOG_TRACE, "number of mmap calls for windows = %lu\n", win_getnum_mmaps()); switch ( rv ) { case RV_OK: DH2F( fileh )->f_dirtriedpr = BOOL_TRUE; Media_atnondir( Mediap ); tranp->t_sync3 = SYNC_DONE; break; case RV_CORRUPT: Media_indir( Mediap ); DH2F( fileh )->f_dirtriedpr = BOOL_TRUE; tranp->t_sync3 = SYNC_INIT; break; case RV_INTR: case RV_DRIVE: Media_end( Mediap ); return mlog_exit(EXIT_NORMAL, rv); case RV_CORE: default: Media_end( Mediap ); return mlog_exit(EXIT_FAULT, rv); } } /* now let one thread do all tree post-processing prior to * non-dir restore */ if ( persp->s.treepostdonepr ) { tranp->t_sync4 = SYNC_DONE; } while ( tranp->t_sync4 != SYNC_DONE ) { lock( ); if ( tranp->t_sync4 == SYNC_BUSY ) { unlock( ); mlog( MLOG_TRACE, "waiting for directory post-processing " "to complete\n" ); lock( ); } while ( tranp->t_sync4 == SYNC_BUSY ) { unlock( ); #if DEBUG_DUMPSTREAMS { static int count[STREAM_MAX] = {0}; int streamix = stream_getix( pthread_self() ); if (++(count[streamix]) == 30) { mlog( MLOG_NORMAL, "still waiting for dirs post-processing\n"); count[streamix] = 0; } } #endif sleep( 1 ); if ( cldmgr_stop_requested( )) { Media_end( Mediap ); return mlog_exit(EXIT_NORMAL, RV_INTR); } lock( ); } if ( tranp->t_sync4 == SYNC_DONE ) { unlock( ); continue; } tranp->t_sync4 = SYNC_BUSY; unlock( ); mlog( MLOG_VERBOSE, _( "directory post-processing\n") ); win_locks_off(); /* we are single threaded here */ rv = treepost( path1, path2 ); win_locks_on(); switch ( rv ) { case RV_OK: break; case RV_ERROR: Media_end( Mediap ); return mlog_exit(EXIT_ERROR, RV_ERROR); case RV_INTR: Media_end( Mediap ); return mlog_exit(EXIT_INTERRUPT, RV_INTR); case RV_CORE: default: Media_end( Mediap ); return mlog_exit(EXIT_FAULT, rv); } /* now that we have a tree and inomap, scan the * pi to see what media files can be skipped. * this func has cancer: too many flags and * side-effects! */ { bool_t dummyknownholespr; bool_t dummymaybeholespr; bag_t *bagp = pi_neededobjs_nondir_alloc( &dummyknownholespr, &dummymaybeholespr, BOOL_FALSE, BOOL_TRUE ); if ( bagp ) { pi_neededobjs_free( bagp ); bagp = 0; } } /* release exclusion */ tranp->t_sync4 = SYNC_DONE; } /* now all are free to do concurrent non-dir restore! * apply media files until there are no more, or we are interrupted */ for (;;) { mlog( MLOG_DEBUG, "getting next media file for non-dir restore\n" ); rv = Media_mfile_next( Mediap, PURP_NONDIR, 0, &fileh, &grhdrp, &drhdrp, &mrhdrp, &crhdrp, &scrhdrp, &drivep, &fhdr ); if ( rv == RV_NOMORE ) { break; } switch ( rv ) { case RV_OK: break; case RV_INTR: case RV_QUIT: case RV_DRIVE: Media_end( Mediap ); return mlog_exit(EXIT_NORMAL, rv); case RV_CORE: default: Media_end( Mediap ); return mlog_exit(EXIT_FAULT, rv); } dcaps = drivep->d_capabilities; assert( fileh > DH_NULL ); if ( tranp->t_toconlypr ) { mlog( MLOG_VERBOSE, _( "reading non-directory files\n") ); } else { mlog( MLOG_VERBOSE, _( "restoring non-directory files\n") ); } mlog( MLOG_TRACE, "media file %u in " "object %u " "of stream %u\n", mrhdrp->mh_mediafileix, mrhdrp->mh_mediaix, drhdrp->dh_driveix ); mlog( MLOG_DEBUG, "file %u in stream, " "file %u in dump %u on object\n", mrhdrp->mh_dumpfileix, mrhdrp->mh_dumpmediafileix, mrhdrp->mh_dumpmediaix ); rv = applynondirdump( drivep, fileh, scrhdrp, path1, path2, &fhdr ); switch ( rv ) { case RV_OK: DH2F( fileh )->f_nondirdonepr = BOOL_TRUE; Media_end( Mediap ); break; case RV_INTR: case RV_DRIVE: case RV_INCOMPLETE: Media_end( Mediap ); return mlog_exit(EXIT_NORMAL, rv); case RV_CORE: default: Media_end( Mediap ); return mlog_exit(EXIT_FAULT, rv); } } /* finally, choose one thread to do final processing * and cleanup. the winner waits, the losers all exit. * once the losers exit, the winner can perform cleanup. */ lock( ); if ( tranp->t_sync5 == SYNC_BUSY ) { unlock( ); return mlog_exit(EXIT_NORMAL, RV_DONE); } tranp->t_sync5 = SYNC_BUSY; unlock( ); if ( drivecnt > 1 ) { mlog( MLOG_TRACE, "waiting for other streams to exit\n" ); } while ( cldmgr_otherstreamsremain( thrdix )) { sleep( 1 ); } mlog( MLOG_DEBUG, "tree finalize\n" ); rv = finalize( path1, path2 ); if (rv == RV_OK || rv == RV_INTR) { rval = EXIT_NORMAL; } else if (rv == RV_ERROR) { rval = EXIT_ERROR; } else { rval = EXIT_FAULT; } return mlog_exit(rval, rv); } /* called after all threads have exited. scans state to decide * if interrupted or not. */ bool_t content_complete( void ) { bool_t completepr; time_t elapsed; if ( ! persp ) { completepr = BOOL_TRUE; } else if ( ! persp->a.valpr ) { completepr = BOOL_TRUE; } else if ( ! persp->s.valpr ) { completepr = BOOL_TRUE; } else { completepr = BOOL_FALSE; } elapsed = time( 0 ) - tranp->t_starttime; if ( persp ) { elapsed += persp->s.accumtime; } if ( completepr ) { if ( tranp->t_toconlypr ) { mlog( MLOG_VERBOSE, _( "table of contents display complete" ": %ld seconds elapsed" "\n"), elapsed ); } else { int found; found = quotafilecheck("user", persp->a.dstdir, CONTENT_QUOTAFILE); found += quotafilecheck("project", persp->a.dstdir, CONTENT_PQUOTAFILE); found += quotafilecheck("group", persp->a.dstdir, CONTENT_GQUOTAFILE); if (found) mlog( MLOG_NORMAL, _("use \'xfs_quota\' to restore quotas\n") ); mlog( MLOG_VERBOSE, _( "restore complete" ": %ld seconds elapsed" "\n"), elapsed ); } } else if ( tranp->t_toconlypr ) { mlog( MLOG_VERBOSE | MLOG_NOTE, _( "table of contents display interrupted" ": %ld seconds elapsed" "\n"), elapsed ); } else { mlog( MLOG_VERBOSE | MLOG_NOTE, _( "restore interrupted" ": %ld seconds elapsed" ": may resume later using -%c option" "\n"), elapsed, GETOPT_RESUME ); } /* accumulate total elapsed time */ if ( persp ) { persp->s.accumtime = elapsed; } if ( ! persp->a.valpr ) { wipepersstate( ); persp = 0; } return completepr; } #define STATLINESZ 160 size_t content_statline( char **linespp[ ] ) { static char statlinebuf[ 1 ][ STATLINESZ ]; static char *statline[ 1 ]; size64_t inodone; off64_t datadone; size64_t inocnt; off64_t datacnt; double percent; time_t elapsed; time_t now; struct tm *tmp; ix_t i; /* build and supply the line array */ for ( i = 0 ; i < 1 ; i++ ) { statline[ i ] = &statlinebuf[ i ][ 0 ]; } *linespp = statline; if ( ! persp->s.stat_valpr ) { return 0; } /* calculate the elapsed time */ elapsed = persp->s.accumtime + ( time( 0 ) - tranp->t_starttime ); /* get local time */ now = time( 0 ); tmp = localtime( &now ); if ( ! persp->s.dirdonepr ) { if ( ! tranp->t_dircnt ) { return 0; } percent = ( double )tranp->t_dirdonecnt / ( double )tranp->t_dircnt; percent *= 100.0; sprintf( statline[ 0 ], _( "status at %02d:%02d:%02d: " "%llu/%llu directories reconstructed, " "%.1f%%%% complete, " "%llu directory entries processed, " "%ld seconds elapsed\n"), tmp->tm_hour, tmp->tm_min, tmp->tm_sec, (unsigned long long)tranp->t_dirdonecnt, (unsigned long long)tranp->t_dircnt, percent, (unsigned long long)tranp->t_direntcnt, elapsed ); assert( strlen( statline[ 0 ] ) < STATLINESZ ); return 1; } /* get the accumulated totals for non-dir inos and data bytes dumped. * not under lock! */ inodone = persp->s.stat_inodone; datadone = persp->s.stat_datadone; inocnt = persp->s.stat_inocnt; datacnt = persp->s.stat_datacnt; /* calculate percentage of data dumped */ if ( datacnt ) { percent = ( double )datadone / ( double )datacnt; percent *= 100.0; } else { percent = 100.0; } if ( percent > 100.0 ) { percent = 100.0; } /* format the status line in a local static buffer (non-re-entrant!) */ sprintf( statline[ 0 ], _( "status at %02d:%02d:%02d: %llu/%llu files restored, " "%.1f%%%% complete, " "%ld seconds elapsed\n"), tmp->tm_hour, tmp->tm_min, tmp->tm_sec, (unsigned long long)inodone, (unsigned long long)inocnt, percent, elapsed ); assert( strlen( statline[ 0 ] ) < STATLINESZ ); /* return buffer to caller */ return 1; } void content_showinv( void ) { pi_show_nomloglock( ); } void content_showremainingobjects( void ) { bool_t knownholespr = BOOL_FALSE; bool_t maybeholespr = BOOL_FALSE; bag_t *bagp; bagp = pi_neededobjs_nondir_alloc( &knownholespr, &maybeholespr, BOOL_TRUE, BOOL_FALSE ); display_needed_objects( PURP_NONDIR, bagp, knownholespr, maybeholespr ); if ( bagp ) { pi_neededobjs_free( bagp ); bagp = 0; } } /* dlog_begin already called; this is a second-level dialog. * prompt for each thread currently waiting for confirmation, * as well as an info prompt. */ #define PREAMBLEMAX 3 #define QUERYMAX 36 #define CHOICEMAX 30 #define ACKMAX 3 #define POSTAMBLEMAX 3 #define DLOG_TIMEOUT 300 #define DLOG_TIMEOUT_MEDIA 3600 #define CHOICESTRSZ 10 typedef struct { ix_t thrdix; char choicestr[ CHOICESTRSZ ]; } cttm_t; char * content_mediachange_query( void ) { cttm_t choicetothrdmap[ STREAM_SIMMAX ]; char *querystr[ QUERYMAX ]; size_t querycnt; char *choicestr[ CHOICEMAX ]; size_t choicecnt; char *ackstr[ ACKMAX ]; size_t ackcnt; size_t maxdrvchoiceix; size_t infoix; size_t nochangeix; size_t responseix; ix_t thrdix; infoix = querycnt = 0; querystr[ querycnt++ ] = _("select a drive to acknowledge media change\n"); choicecnt = 0; maxdrvchoiceix = 0; for ( thrdix = 0 ; thrdix < STREAM_SIMMAX ; thrdix++ ) { if ( mcflag[ thrdix ] ) { choicetothrdmap[ choicecnt ].thrdix = thrdix; sprintf( choicetothrdmap[ choicecnt ].choicestr, _("drive %u"), (unsigned int)thrdix ); choicestr[ choicecnt ] = choicetothrdmap[ choicecnt ].choicestr; maxdrvchoiceix = choicecnt; choicecnt++; } } if ( persp->s.valpr ) { infoix = choicecnt; choicestr[ choicecnt++ ] = _("display needed media objects"); } nochangeix = choicecnt; choicestr[ choicecnt++ ] = _("continue"); assert( choicecnt <= CHOICEMAX ); responseix = dlog_multi_query( querystr, querycnt, choicestr, choicecnt, 0, /* hilitestr */ IXMAX, /* hiliteix */ 0, /* defaultstr */ nochangeix, /* defaultix */ DLOG_TIMEOUT, nochangeix, /* timeout ix */ nochangeix, /* sigint ix */ nochangeix, /* sighup ix */ nochangeix);/* sigquit ix */ if ( responseix <= maxdrvchoiceix ) { clr_mcflag( choicetothrdmap[ responseix ].thrdix ); return _("media change acknowledged\n"); } if ( responseix == infoix ) { bool_t knownholespr = BOOL_FALSE; bool_t maybeholespr = BOOL_FALSE; bag_t *bagp = pi_neededobjs_nondir_alloc( &knownholespr, &maybeholespr, BOOL_FALSE, BOOL_FALSE ); display_needed_objects( PURP_NONDIR, bagp, knownholespr, maybeholespr ); if ( bagp ) { pi_neededobjs_free( bagp ); bagp = 0; } ackcnt = 0; dlog_multi_ack( ackstr, ackcnt ); querycnt = 0; choicecnt = 0; nochangeix = choicecnt; choicestr[ choicecnt++ ] = _("continue"); assert( choicecnt <= CHOICEMAX ); responseix = dlog_multi_query( querystr, querycnt, choicestr, choicecnt, 0, /* hilitestr */ IXMAX, /* hiliteix */ 0, /* defaultstr */ nochangeix, /* defaultix */ DLOG_TIMEOUT, nochangeix, /* timeout ix */ nochangeix, /* sigint ix */ nochangeix, /* sighup ix */ nochangeix);/* sigquit ix */ return _("continuing\n"); } assert( responseix == nochangeix ); return _("continuing\n"); } /* definition of locally defined static functions ****************************/ /* does all pre-processing leading up to applying the dirdump, * then applies the dirdump. updates pers progress flags along the way. * does NOT do any post-processing! */ /* ARGSUSED */ static rv_t applydirdump( drive_t *drivep, dh_t fileh, content_inode_hdr_t *scrhdrp, filehdr_t *fhdrp ) { bool_t fhcs; bool_t dhcs; bool_t ahcs; fhcs = ( scrhdrp->cih_dumpattr & CIH_DUMPATTR_FILEHDR_CHECKSUM ) ? BOOL_TRUE : BOOL_FALSE; dhcs = ( scrhdrp->cih_dumpattr & CIH_DUMPATTR_DIRENTHDR_CHECKSUM ) ? BOOL_TRUE : BOOL_FALSE; ahcs = ( scrhdrp->cih_dumpattr & CIH_DUMPATTR_EXTATTRHDR_CHECKSUM ) ? BOOL_TRUE : BOOL_FALSE; if ( ! persp->s.marknorefdonepr ) { tree_marknoref( ); persp->s.marknorefdonepr = BOOL_TRUE; } if ( scrhdrp->cih_dumpattr & CIH_DUMPATTR_NOTSELFCONTAINED ) { mlog( MLOG_NORMAL | MLOG_NOTE, _( "dump is not self-contained, " "orphaned files expected if base dump(s) " "was not applied\n") ); } if ( ! persp->s.dirdonepr ) { rv_t rv; dah_t dah; char _direntbuf[ sizeof( direnthdr_t ) + NAME_MAX + 1 + DIRENTHDR_ALIGN ]; char *direntbuf = ALIGN_PTR(_direntbuf, DIRENTHDR_ALIGN); size_t direntbufsz = sizeof(_direntbuf) - (direntbuf - _direntbuf); mlog( MLOG_TRACE, "reading the ino map\n" ); rv = inomap_restore_pers( drivep, scrhdrp, tranp->t_hkdir ); if ( rv != RV_OK ) { return rv; } tranp->t_dircnt = scrhdrp->cih_inomap_dircnt; tranp->t_dirdonecnt = 0; tranp->t_direntcnt = 0; mlog( MLOG_TRACE, "reading the directories \n" ); dah = DAH_NULL; for (;;) { nh_t dirh; /* read the file header */ rv = read_filehdr( drivep, fhdrp, fhcs ); if ( rv ) { return rv; } /* if this is a null file hdr, we're done * reading dirs, and there are no nondirs. * done. */ if ( fhdrp->fh_flags & FILEHDR_FLAGS_NULL ) { break; } /* if its not a directory, must be the * first non-dir file. done. */ if ( ( fhdrp->fh_stat.bs_mode & S_IFMT ) != S_IFDIR ) { break; } /* if stop requested bail out gracefully */ if ( cldmgr_stop_requested( )) { return RV_INTR; } /* if in a pipeline , call preemptchk( ) to * print status reports */ if ( pipeline ) { mlog( MLOG_DEBUG , "preemptchk( )\n"); preemptchk( ); } /* may be an extended attributes file hdr */ if ( fhdrp->fh_flags & FILEHDR_FLAGS_EXTATTR ) { rv = restore_extattr( drivep, fhdrp, 0, ahcs, BOOL_TRUE, /* isdirpr */ BOOL_FALSE, /* onlydoreadpr */ dah ); if ( rv != RV_OK ) { return rv; } continue; } /* add the directory to the tree. save the * returned tree node id, to associate with * the directory entries. get the dirattr handle, * so that any extattr following will be associated * with that dir. */ dah = DAH_NULL; dirh = tree_begindir( fhdrp, &dah ); if (dirh == NH_NULL) return RV_ERROR; /* read the directory entries, and populate the * tree with them. we can tell when we are done * by looking for a null dirent. */ for ( ; ; ) { register direnthdr_t *dhdrp = ( direnthdr_t * )direntbuf; register size_t namelen; rv = read_dirent( drivep, dhdrp, direntbufsz, dhcs ); if ( rv != RV_OK ) { return rv; } /* if null, we're done with this dir. * break out of this inner loop and * move on th the next dir. */ if ( dhdrp->dh_ino == 0 ) { break; } namelen = strlen( dhdrp->dh_name ); assert( namelen <= NAME_MAX ); /* add this dirent to the tree. */ rv = tree_addent( dirh, dhdrp->dh_ino, dhdrp->dh_gen, dhdrp->dh_name, namelen ); if ( rv != RV_OK ) { return rv; } tranp->t_direntcnt++; } tree_enddir( dirh ); tranp->t_dirdonecnt++; } if ((rv = dirattr_flush()) != RV_OK) { return rv; } if ((rv = namreg_map()) != RV_OK) { return rv; } persp->s.dirdonepr = BOOL_TRUE; } mlog( MLOG_VERBOSE, _("%llu directories and %llu entries processed\n"), tranp->t_dirdonecnt, tranp->t_direntcnt); return RV_OK; } /* like applydirdump, but just eats up the inomap/dirdump portion of the * dump, doesn't use it. the first non-dir filehdr_t is copied into supplied * buffer. returns integer error code from drive ops used. */ /* ARGSUSED */ rv_t eatdirdump( drive_t *drivep, dh_t fileh, content_inode_hdr_t *scrhdrp, filehdr_t *fhdrp ) { bool_t fhcs; bool_t dhcs; bool_t ahcs; char _direntbuf[ sizeof( direnthdr_t ) + NAME_MAX + 1 + DIRENTHDR_ALIGN ]; char *direntbuf = ALIGN_PTR(_direntbuf, DIRENTHDR_ALIGN); size_t direntbufsz = sizeof(_direntbuf) - (direntbuf - _direntbuf); rv_t rv; fhcs = ( scrhdrp->cih_dumpattr & CIH_DUMPATTR_FILEHDR_CHECKSUM ) ? BOOL_TRUE : BOOL_FALSE; dhcs = ( scrhdrp->cih_dumpattr & CIH_DUMPATTR_DIRENTHDR_CHECKSUM ) ? BOOL_TRUE : BOOL_FALSE; ahcs = ( scrhdrp->cih_dumpattr & CIH_DUMPATTR_EXTATTRHDR_CHECKSUM ) ? BOOL_TRUE : BOOL_FALSE; mlog( MLOG_DEBUG, "discarding ino map\n" ); rv = inomap_discard( drivep, scrhdrp ); if ( rv != RV_OK ) { return rv; } mlog( MLOG_DEBUG, "discarding directories \n" ); for (;;) { /* read the file header */ rv = read_filehdr( drivep, fhdrp, fhcs ); if ( rv ) { return rv; } /* if this is a null file hdr, we're done * reading dirs, and there are no nondirs. * done. */ if ( fhdrp->fh_flags & FILEHDR_FLAGS_NULL ) { break; } /* if its not a directory, must be the * first non-dir file. done. */ if ( ( fhdrp->fh_stat.bs_mode & S_IFMT ) != S_IFDIR ) { break; } /* if stop requested bail out gracefully */ if ( cldmgr_stop_requested( )) { return RV_INTR; } /* may be an extended attributes file hdr */ if ( fhdrp->fh_flags & FILEHDR_FLAGS_EXTATTR ) { rv = restore_extattr( drivep, fhdrp, 0, ahcs, BOOL_TRUE, /* isdirpr */ BOOL_TRUE, /* onlydoreadpr */ DAH_NULL ); if ( rv != RV_OK ) { return rv; } continue; } /* read the directory entries. * we can tell when we are done * by looking for a null dirent. */ for ( ; ; ) { register direnthdr_t *dhdrp = ( direnthdr_t * )direntbuf; /* REFERENCED */ register size_t namelen; rv = read_dirent( drivep, dhdrp, direntbufsz, dhcs ); if ( rv ) { return rv; } /* if null, we're done with this dir. * break out of this inner loop and * move on th the next dir. */ if ( dhdrp->dh_ino == 0 ) { break; } namelen = strlen( dhdrp->dh_name ); assert( namelen <= NAME_MAX ); } } return RV_OK; } /* does all post-processing of the tree required prior to restoral of * the non-directory portion of the dump. only one thread at a time, * so no locking needed. since the steps are interdependent, loops * until no point in doing so. */ static rv_t treepost( char *path1, char *path2 ) { bool_t ok; #ifdef TREE_CHK /* first scan the tree for corruption */ mlog( MLOG_DEBUG | MLOG_TREE, "checking tree for consistency\n" ); if ( ! tree_chk( )) { return RV_CORE; } #endif /* TREE_CHK */ /* adjust ref flags based on what dirs were dumped */ if ( ! persp->s.adjrefdonepr ) { mlog( MLOG_DEBUG | MLOG_TREE, "adjusting dirent ref flags\n" ); ok = tree_adjref( ); if ( ! ok ) { return RV_INTR; } persp->s.adjrefdonepr = BOOL_TRUE; } /* if a subtree or interactive restore, sanitize the inomap * so only inos selected by subtree or interactive cmds will * be present in inomap. */ if ( ! persp->s.inomapsanitizedonepr ) { if ( persp->a.interpr || ( persp->a.firststsenseprvalpr && persp->a.firststsensepr )) { inomap_sanitize( ); } persp->s.inomapsanitizedonepr = BOOL_TRUE; } /* apply subtree selections */ if ( ! persp->s.stdonepr ) { ix_t stix; stdesc_t *stdescp; mlog( MLOG_DEBUG | MLOG_TREE, "applying subtree selections\n" ); /* if first subtree selection is inclusive in sense, * first mark the entire tree as unselected. otherwise, * select all (no subtree selections or first was excluding). */ if ( ( persp->a.interpr && ( ! persp->a.firststsenseprvalpr || persp->a.firststsensepr )) || ( persp->a.firststsenseprvalpr && persp->a.firststsensepr )) { tree_markallsubtree( BOOL_FALSE ); } else { tree_markallsubtree( BOOL_TRUE ); } /* now apply all subtree commands from command line */ for ( stix = 0, stdescp = ( stdesc_t * )( ( char * )persp + perssz ) ; stix < persp->a.stcnt ; stix++, stdescp = ( stdesc_t * )( ( char * )stdescp + stdescp->std_nextoff )) { ok = tree_subtree_parse( stdescp->std_sensepr, stdescp->std_path ); if ( ! ok ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "subtree argument %s invalid\n"), stdescp->std_path ); return RV_ERROR; } } persp->s.stdonepr = BOOL_TRUE; } /* next engage interactive subtree selection */ if ( ! persp->s.interdonepr ) { if ( persp->a.interpr ) { ok = tree_subtree_inter( ); if ( ! ok ) { return RV_INTR; } } persp->s.interdonepr = BOOL_TRUE; } ok = tree_post( path1, path2 ); if ( ! ok ) { return RV_INTR; } ok = tree_extattr( restore_dir_extattr_cb, path1 ); if ( ! ok ) { return RV_INTR; } persp->s.treepostdonepr = BOOL_TRUE; return RV_OK; } static rv_t applynondirdump( drive_t *drivep, dh_t fileh, content_inode_hdr_t *scrhdrp, char *path1, char *path2, filehdr_t *fhdrp ) { rv_t rv = RV_UNKNOWN; bool_t fhcs; bool_t ehcs; bool_t ahcs; egrp_t first_egrp; egrp_t next_egrp; stream_context_t *strctxp = (stream_context_t *)drivep->d_strmcontextp; /* determine if file header and/or extent heade checksums present */ fhcs = ( scrhdrp->cih_dumpattr & CIH_DUMPATTR_FILEHDR_CHECKSUM ) ? BOOL_TRUE : BOOL_FALSE; ehcs = ( scrhdrp->cih_dumpattr & CIH_DUMPATTR_EXTENTHDR_CHECKSUM ) ? BOOL_TRUE : BOOL_FALSE; ahcs = ( scrhdrp->cih_dumpattr & CIH_DUMPATTR_EXTATTRHDR_CHECKSUM ) ? BOOL_TRUE : BOOL_FALSE; /* determine the first and next egrps needed from this media file. * used to decide if stats should be updated */ pi_bracketneededegrps( fileh, &first_egrp, &next_egrp ); /* initialize the stream context */ memset(&strctxp->sc_bstat, 0, sizeof(bstat_t)); strctxp->sc_path[0] = '\0'; strctxp->sc_fd = -1; strctxp->sc_ownerset = BOOL_FALSE; for ( ; ; ) { drive_ops_t *dop = drivep->d_opsp; drive_mark_t drivemark; bstat_t *bstatp = &fhdrp->fh_stat; bool_t resyncpr = BOOL_FALSE; int rval; /* if a null file header, break */ if ( fhdrp->fh_flags & FILEHDR_FLAGS_NULL ) { rv = RV_OK; goto applynondirdump_out; } /* if working on a different file than we were previously, * complete the old one and begin the new one. */ if ( bstatp->bs_ino != strctxp->sc_bstat.bs_ino ) { restore_complete_reg(strctxp); /* start new ino */ memcpy(&strctxp->sc_bstat, bstatp, sizeof(bstat_t)); strctxp->sc_path[0] = '\0'; strctxp->sc_fd = -1; strctxp->sc_ownerset = BOOL_FALSE; rv = restore_file( drivep, fhdrp, ehcs, ahcs, path1, path2 ); } else if ( fhdrp->fh_flags & FILEHDR_FLAGS_EXTATTR ) { rv = restore_extattr( drivep, fhdrp, strctxp->sc_path, ahcs, BOOL_FALSE, /* isdirpr */ BOOL_FALSE, /* onlydoreadpr */ DAH_NULL ); } else { /* Must be another extent group for the current file */ restore_extent_group( drivep, fhdrp, strctxp->sc_path, strctxp->sc_fd, ehcs, &rv ); } switch( rv ) { case RV_OK: break; case RV_EOD: rv = RV_OK; goto applynondirdump_out; case RV_CORRUPT: rval = ( * dop->do_next_mark )( drivep ); if ( rval ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "unable to resync media file: " "some portion of dump will NOT " "be restored\n") ); rv = RV_OK; /* treat as EOD */ goto applynondirdump_out; } resyncpr = BOOL_TRUE; break; default: goto applynondirdump_out; } /* update stats if appropriate */ if ( ( ( bstatp->bs_mode & S_IFMT ) == S_IFREG ) && ! ( fhdrp->fh_flags & FILEHDR_FLAGS_EXTATTR ) && fhdrp->fh_offset == 0 ) { egrp_t cur_egrp; cur_egrp.eg_ino = fhdrp->fh_stat.bs_ino; cur_egrp.eg_off = fhdrp->fh_offset; if (cur_egrp.eg_ino > first_egrp.eg_ino ) { if ( cur_egrp.eg_ino < next_egrp.eg_ino || next_egrp.eg_off > 0 ) { assert( cur_egrp.eg_ino <= next_egrp.eg_ino ); pi_update_stats( bstatp->bs_blocks * ( off64_t ) bstatp->bs_blksize ); } } } do { /* get a mark for the next read, in case we restart here */ ( * dop->do_get_mark )( drivep, &drivemark ); /* read the file header. */ rv = read_filehdr( drivep, fhdrp, fhcs ); switch( rv ) { case RV_OK: break; case RV_EOD: rv = RV_OK; goto applynondirdump_out; case RV_CORRUPT: rval = ( * dop->do_next_mark )( drivep ); if ( rval ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "unable to resync media file: " "some portion of dump will NOT " "be restored\n") ); rv = RV_OK; /* treat as EOD */ goto applynondirdump_out; } resyncpr = BOOL_TRUE; default: goto applynondirdump_out; } if ( resyncpr && rv == RV_OK ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "resynchronization achieved at " "ino %llu offset %lld\n"), fhdrp->fh_stat.bs_ino, fhdrp->fh_offset ); resyncpr = BOOL_FALSE; } } while ( resyncpr ); /* checkpoint into persistent state if not a null file hdr */ if ( ! ( fhdrp->fh_flags & FILEHDR_FLAGS_NULL )) { pi_checkpoint( fileh, &drivemark, fhdrp->fh_stat.bs_ino, fhdrp->fh_offset ); } /* if in a pipeline , call preemptchk( ) to * print status reports */ if ( pipeline ) { mlog( MLOG_DEBUG , "preemptchk( )\n"); preemptchk( ); } } applynondirdump_out: /* We've hit the end of this media file or encountered corruption. * In either case, we may not be back to complete the metadata for * this file, so attempt to complete it now. */ restore_complete_reg(strctxp); return rv; } /* ARGSUSED */ static rv_t finalize( char *path1, char *path2 ) { bool_t ok; if ( ! tranp->t_toconlypr ) { /* restore directory attributes */ if ( ! persp->s.dirattrdonepr ) {; ok = tree_setattr( path1 ); if ( ! ok ) { return RV_INTR; } persp->s.dirattrdonepr = BOOL_TRUE; } /* remove orphanage if empty */ if ( ! persp->s.orphdeltriedpr ) {; ok = tree_delorph( ); if ( ! ok ) { return RV_INTR; } persp->s.orphdeltriedpr = BOOL_TRUE; } /* delete the persistent ino map */ if ( ! persp->s.inomapdelpr ) { inomap_del_pers( tranp->t_hkdir ); persp->s.inomapdelpr = BOOL_TRUE; } } /* at this point, all session-only persistent state has been deleted. * if this is a cumulative restore, just update the pers cum state and * invalidate the pers session state. otherwise, invalidate the * persistent state. content_complete will remove housekeeping dir. */ if ( persp->a.cumpr ) { /* following must be atomic! */ persp->a.dumpcnt++; uuid_copy(persp->a.lastdumpid, persp->s.dumpid); strcpy( persp->a.lastdumplab, persp->s.dumplab ); persp->s.valpr = BOOL_FALSE; } else { persp->a.valpr = BOOL_FALSE; } return RV_OK; } static void toconly_cleanup( void ) { if ( ! tranp ) { return; } if ( ! tranp->t_toconlypr ) { return; } if ( ! tranp->t_hkdir ) { return; } if ( ! strlen( tranp->t_hkdir )) { return; } wipepersstate( ); } static void wipepersstate( void ) { DIR *dirp; struct dirent64 *direntp; char pathname[ MAXPATHLEN ]; dirp = opendir( tranp->t_hkdir ); if ( ! dirp ) { return; } while ( ( direntp = readdir64( dirp )) != 0 ) { /* REFERENCED */ int len; if ( ! strcmp( direntp->d_name, "." )) { continue; } if ( ! strcmp( direntp->d_name, ".." )) { continue; } len = sprintf( pathname, "%s/%s", tranp->t_hkdir, direntp->d_name ); assert( len > 0 ); assert( len < MAXPATHLEN ); ( void )unlink( pathname ); closedir( dirp ); dirp = opendir( tranp->t_hkdir ); if ( ! dirp ) { return; } } closedir( dirp ); rmdir( tranp->t_hkdir ); } /* Inv abstraction ***********************************************************/ /* attempt to validate id or label against online inventory. * sets pers id/label and pers idvalpr etc as side-effect (does NOT set valpr!) */ static bool_t Inv_validate_cmdline( void ) { inv_session_t *sessp; bool_t ok; bool_t rok; assert( ! persp->s.valpr ); ok = BOOL_FALSE; sessp = 0; if ( tranp->t_reqdumpidvalpr ) { ok = inv_get_session_byuuid(NULL, &tranp->t_reqdumpid, &sessp); } else if ( tranp->t_reqdumplabvalpr ) { ok = inv_get_session_bylabel(NULL, tranp->t_reqdumplab, &sessp); } rok = BOOL_FALSE; if ( ok && sessp ) { uuid_t baseid; uuid_clear(baseid); askinvforbaseof( baseid, sessp ); if ( ! dumpcompat( sessp->s_isresumed, ( ix_t )( sessp->s_level ), baseid, BOOL_TRUE )) { inv_free_session( &sessp ); return BOOL_ERROR; } mlog( MLOG_VERBOSE, _( "using online session inventory\n") ); persp->s.fullinvpr = pi_transcribe( sessp ); if ( persp->s.fullinvpr ) { strncpyterm( persp->s.dumplab, sessp->s_label, sizeof( persp->s.dumplab )); uuid_copy(persp->s.dumpid, sessp->s_sesid); rok = BOOL_TRUE; } inv_free_session( &sessp ); } return rok; } /* Media abstraction *********************************************************/ static Media_t * Media_create( ix_t thrdix ) { drive_t *drivep = drivepp[ thrdix ]; global_hdr_t *grhdrp = drivep->d_greadhdrp; drive_hdr_t *drhdrp = drivep->d_readhdrp; media_hdr_t *mrhdrp = ( media_hdr_t * )drhdrp->dh_upper; content_hdr_t *crhdrp = ( content_hdr_t * )mrhdrp->mh_upper; content_inode_hdr_t *scrhdrp = ( content_inode_hdr_t * )crhdrp->ch_specific; Media_t *Mediap; mlog( MLOG_DEBUG, "Media_create\n" ); Mediap = ( Media_t * )calloc( 1, sizeof( Media_t )); Mediap->M_drivep = drivep; Mediap->M_grhdrp = grhdrp; Mediap->M_drhdrp = drhdrp; Mediap->M_mrhdrp = mrhdrp; Mediap->M_crhdrp = crhdrp; Mediap->M_scrhdrp = scrhdrp; assert( POS_UNKN == 0 ); return Mediap; } /* these calls allow the Media users to clue Media in to fine position changes * within the current media file */ static void Media_indir( Media_t *Mediap ) { mlog( MLOG_DEBUG, "Media_indir\n" ); Mediap->M_pos = POS_INDIR; } static void Media_atnondir( Media_t *Mediap ) { mlog( MLOG_DEBUG, "Media_atnondir\n" ); Mediap->M_pos = POS_ATNONDIR; } /* supplies pertinent media files to the caller. if purpose is search, * returns all media files. otherwise, returns only media files with the * dump ID. smart enough to know that if purpose was search but is now dir, * current media file can be returned again. same for other transitions. * always traverses the media object in a forward direction, beginning with * current media file, wrapping around to beginning of media if necessary. * also supplies fresh hdr pointers and drive manager. in current * implementation these do not change, but will when we use new TLM. does * fine positioning within media file according to purpose of request. * * Note: * The difference between rval and rv. * rval is used for the drive_* functions (e.g. do_begin_read) * and will take on values such as DRIVE_ERROR_*. * However, it also set to 0 for no error and 1 for error. * It is defaulted to 0 for no error. * rv, however, is of type rv_t and is used for functions returning * rv_t and for the result of this function. * It takes on values like RV_OK, RV_EOF. */ static rv_t Media_mfile_next( Media_t *Mediap, purp_t purp, sync_t *donesyncp, dh_t *filehp, global_hdr_t **grhdrpp, drive_hdr_t **drhdrpp, media_hdr_t **mrhdrpp, content_hdr_t **crhdrpp, content_inode_hdr_t **scrhdrpp, drive_t **drivepp, filehdr_t *fhdrp ) /*caller-supplied buf if NONDIR purp*/ { drive_t *drivep = Mediap->M_drivep; drive_ops_t *dop = drivep->d_opsp; global_hdr_t *grhdrp = Mediap->M_grhdrp; drive_hdr_t *drhdrp = Mediap->M_drhdrp; media_hdr_t *mrhdrp = Mediap->M_mrhdrp; content_hdr_t *crhdrp = Mediap->M_crhdrp; content_inode_hdr_t *scrhdrp = Mediap->M_scrhdrp; dh_t fileh; int rval = 0; /* no error by default */ rv_t rv; bool_t ok; uuid_t prevmfiledumpid; mlog( MLOG_DEBUG | MLOG_MEDIA, "Media_mfile_next: purp==%d pos==%d\n", purp, Mediap->M_pos ); /* pass back hdr and drive ptrs */ *grhdrpp = grhdrp; *drhdrpp = drhdrp; *mrhdrpp = mrhdrp; *crhdrpp = crhdrp; *scrhdrpp = scrhdrp; *drivepp = drivep; /* if ref return for pers mfile desc supplied, pre-zero */ if ( filehp ) { *filehp = DH_NULL; } /* keep a close eye on the validity of fileh */ fileh = DH_NULL; /* if purpose has changed, invalidate first, last, and previous indices */ if ( Mediap->M_flmfixvalpr ) { if ( purp != Mediap->M_mfixpurp ) { Mediap->M_flmfixvalpr = BOOL_FALSE; Mediap->M_pmfixvalpr = BOOL_FALSE; } } /* use a local variable to keep track of dump sessions seen on * media. if not in search mode, each time we see a different * dump session, log a message to keep the user informed. * invalidated each time we change media or rewind. */ uuid_clear(prevmfiledumpid); /* if restore is complete, return indication. be sure to end read * if active. */ if ( purp == PURP_NONDIR && pi_alldone( )) { if ( Mediap->M_pos == POS_ATHDR || Mediap->M_pos == POS_INDIR || Mediap->M_pos == POS_ATNONDIR ) { ( * dop->do_end_read )( drivep ); Mediap->M_pos = POS_UNKN; fileh = DH_NULL; } return RV_NOMORE; } /* loop searching for an acceptable media file. * change media as necessary. */ for ( ; ; ) { bool_t emptypr; /* begin_read says drive empty */ bool_t partofdumppr; bool_t hassomepr; bool_t resumepr; bool_t canseeknextpr; drive_mark_t chkpnt; bool_t fhcs; bag_t *bagp = NULL; bool_t knownholespr; bool_t maybeholespr; xfs_ino_t begino; xfs_ino_t endino; int dcaps = drivep->d_capabilities; dh_t objh = DH_NULL; emptypr = BOOL_FALSE; /* check if no point in going on */ if ( cldmgr_stop_requested( )) { return RV_INTR; } if ( donesyncp && *donesyncp == SYNC_DONE ) { return RV_DONE; } if ( purp == PURP_NONDIR && pi_alldone( )) { return RV_NOMORE; } /* if we have a useless media object, get another one */ if ( Mediap->M_pos == POS_USELESS || Mediap->M_pos == POS_BLANK ) { goto newmedia; } /* if the purpose if to search, and we already have * a media file, that media file has already been * searched, so set pos to cause another begin read */ if ( purp == PURP_SEARCH ) { if ( Mediap->M_pos == POS_ATHDR || Mediap->M_pos == POS_INDIR || Mediap->M_pos == POS_ATNONDIR ) { Mediap->M_pos = POS_UNKN; } } /* if already have a media file, skip the begin_read */ if ( Mediap->M_pos == POS_ATHDR || Mediap->M_pos == POS_INDIR || Mediap->M_pos == POS_ATNONDIR ) { goto validate; } /* see if the indices say we've seen all there is to see */ if ( Mediap->M_flmfixvalpr ) { if ( Mediap->M_pos == POS_UNKN ) { if ( Mediap->M_lmfix + 1 == Mediap->M_fmfix ) { goto newmedia; } } if ( Mediap->M_pos == POS_END ) { if ( Mediap->M_fmfix == 0 ) { goto newmedia; } if ( Mediap->M_fsfixvalpr && Mediap->M_fmfix <= Mediap->M_fsfix ) { goto newmedia; } } } /* if we are at the end, do a rewind, or get new media * if rewinds not possible. this may take a while, so * afterwards check for interrupt or if someone else * has finished the job. */ if ( Mediap->M_pos == POS_END ) { if ( ! ( dcaps & DRIVE_CAP_REWIND )) { goto newmedia; } mlog( MLOG_VERBOSE | MLOG_MEDIA, _( "rewinding\n") ); ( * drivep->d_opsp->do_rewind )( drivep ); Mediap->M_pos = POS_UNKN; if ( cldmgr_stop_requested( )) { return RV_INTR; } if ( donesyncp && *donesyncp == SYNC_DONE ) { return RV_DONE; } if ( purp == PURP_NONDIR && pi_alldone( )) { return RV_NOMORE; } } /* begin a new media file, and determine new position. * bail if catastrophic. also, tell pi about EOD/EOM * if appropriate. */ rval = ( * drivep->d_opsp->do_begin_read )( drivep ); switch ( rval ) { case 0: mlog_lock( ); mlog( MLOG_VERBOSE | MLOG_NOLOCK | MLOG_MEDIA, _( "examining media file %u\n"), mrhdrp->mh_mediafileix ); mlog( MLOG_TRACE | MLOG_NOLOCK | MLOG_MEDIA, "file %u in " "object %u " "of stream %u\n", mrhdrp->mh_mediafileix, mrhdrp->mh_mediaix, drhdrp->dh_driveix ); mlog( MLOG_TRACE | MLOG_NOLOCK | MLOG_MEDIA, "file %u in stream, " "file %u of dump %u on object\n", mrhdrp->mh_dumpfileix, mrhdrp->mh_dumpmediafileix, mrhdrp->mh_dumpmediaix ); mlog_unlock( ); Mediap->M_pos = POS_ATHDR; if ( Mediap->M_flmfixvalpr ) { Mediap->M_pmfix = Mediap->M_lmfix; Mediap->M_pmfixvalpr = BOOL_TRUE; } pi_note_indrive( drhdrp->dh_driveix, mrhdrp->mh_mediaid ); break; case DRIVE_ERROR_EOD: Mediap->M_pos = POS_END; if ( Mediap->M_fsfixvalpr ) { assert( purp != PURP_SEARCH ); pi_hiteod( Mediap->M_fssix, Mediap->M_fsoix ); } break; case DRIVE_ERROR_EOM: Mediap->M_pos = POS_END; if ( Mediap->M_fsfixvalpr ) { assert( purp != PURP_SEARCH ); pi_hiteom( Mediap->M_fssix, Mediap->M_fsoix ); } break; case DRIVE_ERROR_MEDIA: /* * pv: 766024; tes@engr * The setting of emptypr, in my opinion, should only happen * in the case that the drive does not have a tape online. * This corresponds to a couple of cases in prepare_drive(). * Otherwise, when we go to a newmedia we won't be able to eject * the tape when we want/need to. * This may need to be reviewed in the future. */ emptypr = BOOL_TRUE; /* so don't try to eject */ /* fall through */ case DRIVE_ERROR_FOREIGN: case DRIVE_ERROR_FORMAT: case DRIVE_ERROR_VERSION: case DRIVE_ERROR_EOF: Mediap->M_pos = POS_USELESS; break; case DRIVE_ERROR_BLANK: Mediap->M_pos = POS_BLANK; break; case DRIVE_ERROR_CORRUPTION: Mediap->M_pos = POS_UNKN; continue; case DRIVE_ERROR_STOP: return RV_INTR; case DRIVE_ERROR_DEVICE: return RV_DRIVE; default: return RV_CORE; } validate: /* update the positional indices */ if ( Mediap->M_pos == POS_ATHDR || Mediap->M_pos == POS_INDIR || Mediap->M_pos == POS_ATNONDIR ) { if ( ! Mediap->M_flmfixvalpr ) { Mediap->M_fmfix = mrhdrp->mh_mediafileix; Mediap->M_mfixpurp = purp; Mediap->M_flmfixvalpr = BOOL_TRUE; } Mediap->M_lmfix = mrhdrp->mh_mediafileix; } /* check for interrupt. be sure to end_read if necessary */ if ( cldmgr_stop_requested( )) { if ( Mediap->M_pos == POS_ATHDR || Mediap->M_pos == POS_INDIR || Mediap->M_pos == POS_ATNONDIR ) { ( * dop->do_end_read )( drivep ); Mediap->M_pos = POS_UNKN; fileh = DH_NULL; } return RV_INTR; } /* check if another thread has finished job (for this purpose). * don't end_read, we will be back. */ if ( donesyncp && *donesyncp == SYNC_DONE ) { return RV_DONE; } /* we may be done due to the actions of other threads. * if so, return indicating so */ if ( purp == PURP_NONDIR && pi_alldone( )) { return RV_NOMORE; } /* if the media object is useless, go get more */ if ( Mediap->M_pos == POS_USELESS || Mediap->M_pos == POS_BLANK ) { goto newmedia; } /* if we hit the end, this is not a search, and we've * seen at least one media file pertaining to the dump, * ask the inventory if there is any point in examining * the beginning of the object. */ if ( Mediap->M_pos == POS_END && purp != PURP_SEARCH && Mediap->M_fsfixvalpr && pi_know_no_more_on_object( purp, Mediap->M_fssix, Mediap->M_fsoix )) { goto newmedia; } /* if we hit the end, go back to the top, where * we will decide if we should rewind or get new media. */ if ( Mediap->M_pos == POS_END ) { continue; } /* if the purpose is to search, return this media file */ if ( purp == PURP_SEARCH ) { assert( Mediap->M_pos == POS_ATHDR ); return RV_OK; } /* see if this media file is part of the desired dump session */ partofdumppr = ( bool_t )(uuid_compare( persp->s.dumpid, grhdrp->gh_dumpid) == 0); if (!partofdumppr) { char gh_string_uuid[UUID_STR_LEN + 1]; char inv_string_uuid[UUID_STR_LEN + 1]; uuid_unparse( grhdrp->gh_dumpid, gh_string_uuid); uuid_unparse( persp->s.dumpid, inv_string_uuid); mlog( MLOG_VERBOSE | MLOG_MEDIA, _( "inventory session uuid (%s) does not match " "the media header's session uuid (%s)\n"), inv_string_uuid, gh_string_uuid ); } /* if media file dump id is different from the preceeding * media file, print something useful at TRACE verbosity. */ if ( uuid_compare( prevmfiledumpid, grhdrp->gh_dumpid) != 0) { char string_uuid[UUID_STR_LEN + 1]; mlog_lock( ); mlog( MLOG_TRACE | MLOG_NOLOCK | MLOG_MEDIA, "dump session label: \"%s\"\n", grhdrp->gh_dumplabel ); uuid_unparse( grhdrp->gh_dumpid, string_uuid); mlog( MLOG_TRACE | MLOG_NOLOCK | MLOG_MEDIA, "dump session id: %s\n", string_uuid ); mlog( MLOG_TRACE | MLOG_NOLOCK | MLOG_MEDIA, "stream %u, object %u, file %u\n", drhdrp->dh_driveix, mrhdrp->mh_mediaix, mrhdrp->mh_dumpmediafileix ); mlog_unlock( ); uuid_copy(prevmfiledumpid, grhdrp->gh_dumpid); } /* if this media file is not part of the desired dump session, * and a preceeding media file on this object was part of the * dump, we know we have hit the end of the stream. tell the * persistent inventory. */ if ( ! partofdumppr && Mediap->M_fsfixvalpr && Mediap->M_lmfix > Mediap->M_fsfix ) { pi_hitnextdump( Mediap->M_fssix, Mediap->M_fsoix, Mediap->M_lmfix ); } /* if this media file is not part of the desired dump session, * we are doing non-dir, and the preceeding media file on this * object was part of the dump, we know we have hit the end of * the stream. check if we are done. */ if ( ! partofdumppr && purp == PURP_NONDIR && Mediap->M_fsfixvalpr && Mediap->M_lmfix > Mediap->M_fsfix ) { if ( pi_alldone( )) { ( * dop->do_end_read )( drivep ); Mediap->M_pos = POS_UNKN; fileh = DH_NULL; return RV_NOMORE; } } /* if this media file is not part of the desired dump session, * and preceeding media files on this object were, decide if * we need to rewind and look at the beginning of the object. */ if ( ! partofdumppr && Mediap->M_fsfixvalpr && Mediap->M_fmfix <= Mediap->M_fsfix ) { ( * dop->do_end_read )( drivep ); Mediap->M_pos = POS_UNKN; fileh = DH_NULL; if ( dcaps & DRIVE_CAP_REWIND ) { mlog( MLOG_VERBOSE | MLOG_MEDIA, _( "rewinding\n") ); ( * drivep->d_opsp->do_rewind )( drivep ); continue; } else { goto newmedia; } } /* if this media file is not part of the desired dump session, * and the above conditions were not met, then keep looking */ if ( ! partofdumppr ) { ( * dop->do_end_read )( drivep ); Mediap->M_pos = POS_UNKN; fileh = DH_NULL; continue; } /* record the index within this media object of the first * media file in the dump stream */ if ( ! Mediap->M_fsfixvalpr ) { Mediap->M_fsfix = mrhdrp->mh_mediafileix - mrhdrp->mh_dumpmediafileix; Mediap->M_fsoix = mrhdrp->mh_mediaix; Mediap->M_fssix = drhdrp->dh_driveix; Mediap->M_fsfixvalpr = BOOL_TRUE; } /* this media file is part of the dump. add it to the * persistent inventory and get a file handle. */ fileh = pi_addfile( Mediap, grhdrp, drhdrp, mrhdrp, scrhdrp, drivep ); if ( fileh == DH_NULL ) { return RV_CORE; } pi_lock( ); objh = DH2F( fileh )->f_parh; DH2O( objh )->o_indriveix = drivep->d_index; DH2O( objh )->o_indrivepr = BOOL_TRUE; pi_unlock( ); pi_note_underhead( objh, fileh ); /* if purp is nondir, we may be done. */ if ( purp == PURP_NONDIR && pi_alldone( )) { ( * dop->do_end_read )( drivep ); Mediap->M_pos = POS_UNKN; return RV_NOMORE; } /* check for a wraparound */ if ( Mediap->M_flmfixvalpr ) { if ( Mediap->M_fsfixvalpr && Mediap->M_fmfix <= Mediap->M_fsfix && Mediap->M_lmfix < Mediap->M_fmfix ) { ( * dop->do_end_read )( drivep ); Mediap->M_pos = POS_UNKN; fileh = DH_NULL; goto newmedia; } if ( Mediap->M_pmfixvalpr && Mediap->M_pmfix < Mediap->M_fmfix && Mediap->M_lmfix > Mediap->M_fmfix ) { ( * dop->do_end_read )( drivep ); Mediap->M_pos = POS_UNKN; fileh = DH_NULL; goto newmedia; } } /* if this media file is an inventory or a terminator, * we have hit the end of the stream. don't tell the persistent * inventory; it already knows because of a pi_addfile. * decide if any preceeding media files are useful and if so * go get them. otherwise get another media object. */ if ( MEDIA_TERMINATOR_CHK( mrhdrp ) || scrhdrp->cih_mediafiletype == CIH_MEDIAFILETYPE_INVENTORY ) { ( * dop->do_end_read )( drivep ); Mediap->M_pos = POS_UNKN; fileh = DH_NULL; if ( pi_know_no_more_on_object( purp, Mediap->M_fssix, Mediap->M_fsoix )) { goto newmedia; } if ( Mediap->M_fmfix > Mediap->M_fsfix && ( dcaps & DRIVE_CAP_REWIND )) { pi_note_underhead( objh, DH_NULL ); mlog( MLOG_VERBOSE | MLOG_MEDIA, _( "rewinding\n") ); ( * drivep->d_opsp->do_rewind )( drivep ); continue; } goto newmedia; } /* if the purpose is dir, but this media file is not positioned * at the hdr or has already been tried, get another one. * use the persistent inventory to do this intelligently. */ if ( purp == PURP_DIR && ( Mediap->M_pos != POS_ATHDR || DH2F( fileh )->f_dirtriedpr )) { ( * dop->do_end_read )( drivep ); Mediap->M_pos = POS_UNKN; fileh = DH_NULL; if ( pi_know_no_more_beyond_on_object( purp, Mediap->M_fssix, Mediap->M_fsoix, mrhdrp->mh_dumpmediafileix )) { if ( pi_know_no_more_on_object( purp, Mediap->M_fssix, Mediap->M_fsoix )) { goto newmedia; } if ( Mediap->M_fmfix > Mediap->M_fsfix && ( dcaps & DRIVE_CAP_REWIND )) { pi_note_underhead( objh, DH_NULL ); mlog( MLOG_VERBOSE | MLOG_MEDIA, _( "rewinding\n") ); ( * drivep->d_opsp->do_rewind )(drivep); continue; } goto newmedia; } else { continue; } } /* if the purpose is dir, give it to the caller */ if ( purp == PURP_DIR ) { assert( Mediap->M_pos == POS_ATHDR ); if ( filehp ) { assert( fileh != DH_NULL ); *filehp = fileh; } return RV_OK; } /* if we made it this far, the purpose is NONDIR and this * is a valid media file from the desired dump session. */ /* see if this media file contains any inodes not yet restored */ assert( fileh != DH_NULL ); pi_lock( ); assert( DH2F( fileh )->f_valpr ); begino = DH2F( fileh )->f_curegrp.eg_ino; endino = pi_scanfileendino( fileh ); hassomepr = inomap_rst_needed( begino, endino ); /* if we have already given up on this media file or * it doesn't contains anything not yet restored, * or it can be skipped, move on. force the done flag on, * so we don't check it again. */ if ( DH2F( fileh )->f_nondirdonepr || DH2F( fileh )->f_nondirskippr || ! hassomepr ) { if ( ! DH2F( fileh )->f_nondirskippr ) { DH2F( fileh )->f_nondirdonepr = BOOL_TRUE; } pi_unlock( ); ( * dop->do_end_read )( drivep ); Mediap->M_pos = POS_UNKN; fileh = DH_NULL; if ( pi_know_no_more_beyond_on_object( purp, Mediap->M_fssix, Mediap->M_fsoix, mrhdrp->mh_dumpmediafileix )) { if ( pi_know_no_more_on_object( purp, Mediap->M_fssix, Mediap->M_fsoix )) { goto newmedia; } if ( Mediap->M_fmfix > Mediap->M_fsfix && ( dcaps & DRIVE_CAP_REWIND )) { pi_note_underhead( objh, DH_NULL ); mlog( MLOG_VERBOSE | MLOG_MEDIA, _( "rewinding\n") ); ( * drivep->d_opsp->do_rewind )(drivep); continue; } goto newmedia; } else { continue; } } /* so the purpose is NONDIR and we like this media file. * be sure we are positioned at the beginning of the * non-dir filehdr not yet restored, and supply to caller. */ /* need to position just after the first * non-dir filehdr_t not yet restored. * may be a problem if we are currently positioned * in the middle of the dir dump and have no * checkpoint to seek to. if at beginning * and no check point, can still get there * by doing dummy read of dirdump. */ assert( fileh != DH_NULL ); assert( DH2F( fileh )->f_valpr ); resumepr = ( ( DH2F( fileh )->f_firstegrp.eg_ino != DH2F( fileh )->f_curegrp.eg_ino ) || ( DH2F( fileh )->f_firstegrp.eg_off != DH2F( fileh )->f_curegrp.eg_off )); chkpnt = DH2F( fileh )->f_curmark; pi_unlock( ); fhcs = ( scrhdrp->cih_dumpattr & CIH_DUMPATTR_FILEHDR_CHECKSUM ) ? BOOL_TRUE : BOOL_FALSE; canseeknextpr = dcaps & DRIVE_CAP_NEXTMARK; switch( Mediap->M_pos ) { case POS_ATHDR: case POS_INDIR: if ( resumepr ) { mlog( MLOG_VERBOSE | MLOG_MEDIA, _( "seeking past portion of media file " "already restored\n") ); rval = ( * dop->do_seek_mark )( drivep, &chkpnt ); if ( ! rval ) { rv_t rv; rv = read_filehdr( drivep, fhdrp, fhcs ); if ( rv != RV_OK ) { rval = 1; } else { mlog( MLOG_TRACE | MLOG_MEDIA, "positioned at unrestored " "portion of media file\n" ); } } } else if ( canseeknextpr ) { mlog( MLOG_VERBOSE | MLOG_MEDIA, _( "seeking past media file " "directory dump\n") ); rval = ( * dop->do_next_mark )( drivep); if ( ! rval ) { rv_t rv; rv = read_filehdr( drivep, fhdrp, fhcs ); if ( rv != RV_OK ) { rval = 1; } else { mlog( MLOG_TRACE | MLOG_MEDIA, "positioned at " "media file " "non-directory dump\n" ); } } } else if ( Mediap->M_pos == POS_ATHDR ) { mlog( MLOG_VERBOSE | MLOG_MEDIA, _( "seeking past media file " "directory dump\n") ); rv = eatdirdump( drivep, fileh, scrhdrp, fhdrp ); if ( rv != RV_OK ) { rval = 1; } else { mlog( MLOG_TRACE | MLOG_MEDIA, "positioned at " "media file " "non-directory dump\n" ); } } else { rval = 1; } break; case POS_ATNONDIR: rval = 0; break; default: assert( 0 ); rval = 1; break; } /* if error encountered during fine positioning, * mark file so we won't try it again */ if ( rval ) { DH2F( fileh )->f_nondirdonepr = BOOL_TRUE; } else { Mediap->M_pos = POS_ATNONDIR; } /* if no error during fine positioning, return. */ if ( ! rval ) { if ( filehp ) { assert( fileh != DH_NULL ); *filehp = fileh; } return RV_OK; } /* an error occurred during fine positioning. any other useful * media files on this object? if so, continue; if not, get * more media. */ ( * dop->do_end_read )( drivep ); Mediap->M_pos = POS_UNKN; fileh = DH_NULL; assert( purp == PURP_NONDIR ); if ( pi_know_no_more_beyond_on_object( purp, Mediap->M_fssix, Mediap->M_fsoix, mrhdrp->mh_dumpmediafileix )) { if ( pi_know_no_more_on_object( purp, Mediap->M_fssix, Mediap->M_fsoix )) { goto newmedia; } if ( Mediap->M_fmfix > Mediap->M_fsfix && ( dcaps & DRIVE_CAP_REWIND )) { pi_note_underhead( objh, DH_NULL ); mlog( MLOG_VERBOSE | MLOG_MEDIA, _( "rewinding\n") ); ( * drivep->d_opsp->do_rewind )(drivep); continue; } goto newmedia; } else { continue; } /* fall through */ newmedia: /* invalidate prev id, so we log a TRACE msg for first * media file seen on new media */ uuid_clear(prevmfiledumpid); /* if we are searching and some other thread completed * the search, don't pop the media unless it is useless */ if ( purp == PURP_SEARCH && Mediap->M_pos != POS_USELESS && Mediap->M_pos != POS_BLANK && donesyncp && *donesyncp == SYNC_DONE ) { return RV_DONE; } /* if media not removable, just return */ if ( ( * dop->do_get_device_class )( drivep ) == DEVICE_NONREMOVABLE ) { /* if no error has already been detected then don't log a failure */ if (mlog_get_hint() == RV_NONE) mlog_exit_hint(RV_OK); return RV_QUIT; } /* check for an interrupt */ if ( cldmgr_stop_requested( )) { return RV_INTR; } /* check if we are done. */ switch( purp ) { case PURP_SEARCH: knownholespr = BOOL_TRUE; maybeholespr = BOOL_FALSE; bagp = 0; break; case PURP_DIR: knownholespr = BOOL_FALSE; maybeholespr = BOOL_FALSE; bagp = pi_neededobjs_dir_alloc( &knownholespr, &maybeholespr ); break; case PURP_NONDIR: knownholespr = BOOL_FALSE; maybeholespr = BOOL_FALSE; bagp = pi_neededobjs_nondir_alloc( &knownholespr, &maybeholespr, BOOL_FALSE, BOOL_FALSE ); break; default: assert( 0 ); } if ( ! bagp && ! knownholespr && ! maybeholespr ) { /* if PURP_DIR, this may be a problem */ if ( purp == PURP_NONDIR ) { return RV_NOMORE; } } /* eject media if drive not already empty */ if ( ! emptypr ) { int dcaps = drivep->d_capabilities; if ( purp == PURP_SEARCH ) { if ( Mediap->M_pos == POS_USELESS ) { mlog( MLOG_VERBOSE | MLOG_MEDIA, _( "media object not useful\n") ); } else if ( Mediap->M_pos == POS_BLANK ) { mlog( MLOG_VERBOSE | MLOG_MEDIA, _( "media object empty\n") ); } else { mlog( MLOG_VERBOSE | MLOG_MEDIA, _( "all media files examined, " "none selected for restoral\n") ); } } if ( dcaps & DRIVE_CAP_EJECT ) { ( * dop->do_eject_media )( drivep ); } } /* tell the persistent inventory this drive is now empty */ pi_driveempty( drivep->d_index ); /* invalidate all positional descriptors */ Mediap->M_pos = POS_UNKN; Mediap->M_flmfixvalpr = BOOL_FALSE; Mediap->M_pmfixvalpr = BOOL_FALSE; Mediap->M_fsfixvalpr = BOOL_FALSE; fileh = DH_NULL; /* ask for a media change: supply a list of media objects * which may contain useful media files */ if ( dlog_allowed( )) { /* If an alert program has been specified , run it. */ if (media_change_alert_program != NULL) system(media_change_alert_program); if ( drivecnt > 1 && ! stdoutpiped ) { ix_t thrdix = drivep->d_index; if ( bagp ) { pi_neededobjs_free( bagp ); bagp = 0; } assert( sistr ); mlog( MLOG_NORMAL | MLOG_NOTE | MLOG_MEDIA, _( "please change media: " "type %s to confirm media change\n"), sistr ); set_mcflag( thrdix ); while ( mcflag[ thrdix ] ) { sleep( 2 ); if ( cldmgr_stop_requested( )) { clr_mcflag( thrdix ); return RV_INTR; } if ( purp == PURP_NONDIR && pi_alldone( )) { clr_mcflag( thrdix ); return RV_NOMORE; } } ok = BOOL_TRUE; } else { ok = Media_prompt_change( drivep, purp, bagp, knownholespr, maybeholespr ); } } else { ok = BOOL_FALSE; } if ( bagp ) { pi_neededobjs_free( bagp ); bagp = 0; } if ( cldmgr_stop_requested( )) { return RV_INTR; } if ( ! ok ) { return RV_QUIT; } } /* NOTREACHED */ } /* figures out and calls if needed do_end_read( ). */ static void Media_end( Media_t *Mediap ) { drive_t *drivep = Mediap->M_drivep; drive_ops_t *dop = drivep->d_opsp; mlog( MLOG_DEBUG | MLOG_MEDIA, "Media_end: pos==%d\n", Mediap->M_pos ); if ( Mediap->M_pos == POS_ATHDR || Mediap->M_pos == POS_INDIR || Mediap->M_pos == POS_ATNONDIR ) { ( * dop->do_end_read )( drivep ); Mediap->M_pos = POS_UNKN; } } /* Persistent inventory operators *******************************************/ /* the persistent inventory is an mmap()ed file containing a hierarchical * representation of all the media files generated by a dump session. it * is useful for asking questions about how much of the dump remains to * be restored. * * the top of the hierarchy is a linked list of streams. each of these contains * a linked list of objects, which in turn each contain a linked list of files. * each stream descriptor also has a flag indicating the last object in the * stream is represented. each file descriptor contains a flag indicating the * last file in that object is represented. the object descriptor also contains * two indices; one indicating where in the dump stream the first media file * in that object lies, and where in the object the first media file pertaining * to the dump stream lies. each file descriptor describes the first extent * group in that media file, and the next extent group in the media file to be * restored. the file descriptor also contains flags indicating if an attempt * (successful or unsuccessful) to use the file for a directory dump, and * a similar flag for non-dir. * * all media files generated during the dump are represented, including * terminators and inventories. */ static void pi_lock( void ) { qlock_lock( tranp->t_pilockh ); } static void pi_unlock( void ) { qlock_unlock( tranp->t_pilockh ); } /* sets check point in media file descriptor */ static void pi_checkpoint( dh_t fileh, drive_mark_t *drivemarkp, xfs_ino_t ino, off64_t off ) { pi_lock( ); DH2F( fileh )->f_curmark = *drivemarkp; DH2F( fileh )->f_curegrp.eg_ino = ino; DH2F( fileh )->f_curegrp.eg_off = off; pi_unlock( ); } /* lock must be held by caller */ static bool_t pi_allocdesc( dh_t *deschp ) { dh_t desch; if ( persp->s.descfreeh == DH_NULL ) { ix_t stpgcnt = persp->a.stpgcnt; ix_t olddescpgcnt = persp->s.descpgcnt; ix_t newdescpgcnt = olddescpgcnt + DAU; ix_t descppg = pgsz / PERS_DESCSZ; ix_t descix; /* REFERENCED */ int rval; /* first unmap if any existing descriptors */ if ( descp ) { assert( olddescpgcnt > 0 ); rval = munmap( ( void * )descp, olddescpgcnt * pgsz ); assert( ! rval ); descp = 0; } else { assert( olddescpgcnt == 0 ); } /* remap with DAU more pages of descriptors */ assert( stpgcnt <= ( ix_t )INTGENMAX ); assert( newdescpgcnt > 0 ); descp = ( pers_desc_t * ) mmap_autogrow( newdescpgcnt * pgsz, tranp->t_persfd, ( off_t )perssz + ( off_t )( stpgcnt * pgsz )); if ( descp == ( pers_desc_t * )( -1 )) { pi_unlock( ); mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_MEDIA, _( "could not remap persistent state file " "inv %s: %d (%s)\n"), perspath, errno, strerror( errno )); pi_lock( ); descp = 0; return BOOL_FALSE; } persp->s.descfreeh = ( dh_t )( olddescpgcnt * pgsz + 1 ); for ( descix = 0, desch = persp->s.descfreeh ; descix < ( DAU * descppg ) - 1 ; descix++, desch += PERS_DESCSZ ) { DH2D( desch )->d_nexth = desch + PERS_DESCSZ; } DH2D( desch )->d_nexth = DH_NULL; persp->s.descpgcnt = newdescpgcnt; } desch = persp->s.descfreeh; persp->s.descfreeh = DH2D( desch )->d_nexth; memset( ( void * )DH2D( desch ), 0, sizeof( pers_desc_t )); assert( desch != DH_NULL ); *deschp = desch; return BOOL_TRUE; } /* inserts the indexed file into the given stream. ensures that all * previous files are represented as well. if dmfix is not valid, only * adds objects. */ static dh_t pi_insertfile( ix_t drivecnt, ix_t driveix, ix_t mediaix, bool_t idlabvalpr, uuid_t *mediaidp, label_t medialabel, bool_t previdlabvalpr, uuid_t *prevmediaidp, label_t prevmedialabel, bool_t mfixvalpr, ix_t mediafileix, bool_t dmfixvalpr, ix_t dumpmediafileix, bool_t dfixvalpr, ix_t dumpfileix, bool_t egrpvalpr, xfs_ino_t startino, off64_t startoffset, int flags, bool_t fileszvalpr, off64_t filesz ) { ix_t strmix; dh_t strmh; ix_t objix; dh_t objh; dh_t prevobjh; ix_t fileix; dh_t fileh; dh_t prevfileh; bool_t ok; pi_lock( ); /* first alloc stream descriptors if needed */ if ( persp->s.strmheadh == DH_NULL ) { for ( strmix = 0 ; strmix < drivecnt ; strmix++ ) { ok = pi_allocdesc( &strmh ); if ( ! ok ) { pi_unlock( ); return DH_NULL; } DH2S( strmh )->s_nexth = persp->s.strmheadh; persp->s.strmheadh = strmh; } } /* get handle to this stream */ for ( strmix = 0, strmh = persp->s.strmheadh ; strmix < driveix ; strmix++, strmh = DH2S( strmh )->s_nexth ) ; assert( strmh != DH_NULL ); /* get handle to this object by walking/constructing this stream's * object list, up to the desired object */ objh = prevobjh = DH_NULL; for ( objix = 0 ; objix <= mediaix ; objix++ ) { prevobjh = objh; if ( objix == 0 ) { objh = DH2S( strmh )->s_cldh; } else { objh = DH2O( prevobjh )->o_nexth; } if ( objh == DH_NULL ) { ok = pi_allocdesc( &objh ); if ( ! ok ) { pi_unlock( ); return DH_NULL; } DH2O( objh )->o_parh = strmh; if ( objix == 0 ) { DH2S( strmh )->s_cldh = objh; } else { DH2O( prevobjh )->o_nexth = objh; } } } /* update the object fields if not yet valid */ if ( idlabvalpr && ! DH2O( objh )->o_idlabvalpr ) { uuid_copy(DH2O( objh )->o_id, *mediaidp); strncpy( DH2O( objh )->o_lab, medialabel, sizeof( DH2O( objh )->o_lab )); DH2O( objh )->o_idlabvalpr = BOOL_TRUE; } if ( mfixvalpr && dmfixvalpr && ! DH2O( objh )->o_fmfmixvalpr ) { DH2O( objh )->o_fmfmix = mediafileix - dumpmediafileix; DH2O( objh )->o_fmfmixvalpr = BOOL_TRUE; } if ( dfixvalpr && dmfixvalpr && ! DH2O( objh )->o_fmfsixvalpr ) { DH2O( objh )->o_fmfsix = dumpfileix - dumpmediafileix; DH2O( objh )->o_fmfsixvalpr = BOOL_TRUE; } /* record the previous object's id and label if not yet valid */ if ( prevobjh != DH_NULL && previdlabvalpr && ! DH2O( prevobjh )->o_idlabvalpr ) { uuid_copy(DH2O( prevobjh )->o_id, *prevmediaidp); strncpy( DH2O( prevobjh )->o_lab, prevmedialabel, sizeof( DH2O( prevobjh )->o_lab )); DH2O( prevobjh )->o_idlabvalpr = BOOL_TRUE; } /* if the dump file and dump media file indices are valid, * and the previous object has at least one media file with its * dump file index valid, can infer the index of the last media * file on the previous dump object. */ if ( DH2O( objh )->o_fmfsixvalpr && prevobjh != DH_NULL && DH2O( prevobjh )->o_fmfsixvalpr && ! DH2O( prevobjh )->o_lmfknwnpr ) { size_t prevmfcnt; assert( DH2O( objh )->o_fmfsix > DH2O( prevobjh )->o_fmfsix ); prevmfcnt = DH2O( objh )->o_fmfsix - DH2O( prevobjh )->o_fmfsix; pi_unlock( ); assert( mediaix > 0 ); ( void )pi_insertfile( drivecnt, driveix, mediaix - 1, BOOL_FALSE, 0, 0, BOOL_FALSE, 0, 0, BOOL_FALSE, 0, BOOL_TRUE, prevmfcnt - 1, BOOL_TRUE, DH2O( objh )->o_fmfsix - 1, 0, 0, 0, 0, BOOL_FALSE, ( off64_t )0 ); pi_seeobjstrmend( strmix, mediaix - 1 ); pi_lock( ); } /* if don't know dump stream media file index, can't add any media files */ if ( ! dmfixvalpr ) { pi_unlock( ); pi_show( " after pi_insertfile no media file ix" ); return DH_NULL; } /* get handle to this file by walking/constructing this object's * file list, up to the desired file */ fileh = DH_NULL; for ( fileix = 0 ; fileix <= dumpmediafileix ; fileix++ ) { prevfileh = fileh; if ( fileix == 0 ) { fileh = DH2O( objh )->o_cldh; } else { fileh = DH2F( prevfileh )->f_nexth; } if ( fileh == DH_NULL ) { ok = pi_allocdesc( &fileh ); if ( ! ok ) { pi_unlock( ); return DH_NULL; } DH2F( fileh )->f_parh = objh; if ( fileix == 0 ) { DH2O( objh )->o_cldh = fileh; } else { DH2F( prevfileh )->f_nexth = fileh; } } } /* update the media file fields not yet valid */ if ( egrpvalpr && ! DH2F( fileh )->f_valpr ) { assert( ! ( DH2F( fileh )->f_flags & PF_INV )); assert( ! ( DH2F( fileh )->f_flags & PF_TERM )); DH2F( fileh )->f_firstegrp.eg_ino = startino; DH2F( fileh )->f_firstegrp.eg_off = startoffset; DH2F( fileh )->f_curegrp = DH2F( fileh )->f_firstegrp; DH2F( fileh )->f_valpr = BOOL_TRUE; } /* set flags */ DH2F( fileh )->f_flags = flags; /* if we know the file size, * update it */ if ( fileszvalpr ) { DH2F( fileh )->f_sz = filesz; DH2F( fileh )->f_szvalpr = BOOL_TRUE; } pi_unlock( ); pi_show( " after pi_insertfile" ); return fileh; } /* add pers file desc if not already present. will automatically * update/alloc pers obj and strm descriptors. If given a session inventory, * attempt to incorporate into pi. also, initializes completion stats. */ /* ARGSUSED */ static dh_t pi_addfile( Media_t *Mediap, global_hdr_t *grhdrp, drive_hdr_t *drhdrp, media_hdr_t *mrhdrp, content_inode_hdr_t *scrhdrp, drive_t * drivep ) { dh_t fileh; if ( ! persp->s.stat_valpr ) { persp->s.stat_inocnt = scrhdrp->cih_inomap_nondircnt; persp->s.stat_inodone = 0; assert( scrhdrp->cih_inomap_datasz <= OFF64MAX ); persp->s.stat_datacnt = ( off64_t )scrhdrp->cih_inomap_datasz; persp->s.stat_datadone = 0; persp->s.stat_valpr = BOOL_TRUE; } /* if we see a terminator, we know we have seen the end of * a stream. */ if ( MEDIA_TERMINATOR_CHK( mrhdrp )) { fileh = pi_insertfile( drhdrp->dh_drivecnt, drhdrp->dh_driveix, mrhdrp->mh_mediaix, BOOL_TRUE, &mrhdrp->mh_mediaid, mrhdrp->mh_medialabel, BOOL_TRUE, &mrhdrp->mh_prevmediaid, mrhdrp->mh_prevmedialabel, BOOL_TRUE, mrhdrp->mh_mediafileix, BOOL_TRUE, mrhdrp->mh_dumpmediafileix, BOOL_TRUE, mrhdrp->mh_dumpfileix, BOOL_FALSE, ( xfs_ino_t )0, ( off64_t )0, PF_TERM, BOOL_FALSE, ( off64_t )0 ); if ( fileh == DH_NULL ) { return DH_NULL; } pi_seestrmend( drhdrp->dh_driveix ); pi_seeobjstrmend( drhdrp->dh_driveix, mrhdrp->mh_mediaix ); return fileh; } /* data file */ if ( scrhdrp->cih_mediafiletype == CIH_MEDIAFILETYPE_DATA ) { /* tell the inventory about this media file */ fileh = pi_insertfile( drhdrp->dh_drivecnt, drhdrp->dh_driveix, mrhdrp->mh_mediaix, BOOL_TRUE, &mrhdrp->mh_mediaid, mrhdrp->mh_medialabel, BOOL_TRUE, &mrhdrp->mh_prevmediaid, mrhdrp->mh_prevmedialabel, BOOL_TRUE, mrhdrp->mh_mediafileix, BOOL_TRUE, mrhdrp->mh_dumpmediafileix, BOOL_TRUE, mrhdrp->mh_dumpfileix, BOOL_TRUE, scrhdrp->cih_startpt.sp_ino, scrhdrp->cih_startpt.sp_offset, 0, BOOL_FALSE, ( off64_t )0 ); if ( fileh == DH_NULL ) { return DH_NULL; } assert( drhdrp->dh_drivecnt > 0 ); if ( drhdrp->dh_driveix < drhdrp->dh_drivecnt - 1 ) { /* if this is not in the last stream, we know * there is at least one other media file in * the following stream, and we know its start pt */ ( void )pi_insertfile( drhdrp->dh_drivecnt, drhdrp->dh_driveix + 1, 0, BOOL_FALSE, 0, 0, BOOL_FALSE, 0, 0, BOOL_FALSE, 0, BOOL_TRUE, 0, BOOL_FALSE, 0, BOOL_TRUE, scrhdrp->cih_endpt.sp_ino, scrhdrp->cih_endpt.sp_offset, 0, BOOL_FALSE, ( off64_t )0 ); } if ( ! ( drivep->d_capabilities & DRIVE_CAP_FILES )) { /* if drive does not support multiple files, * we know this is end of object and stream */ pi_seestrmend( drhdrp->dh_driveix ); pi_seeobjstrmend( drhdrp->dh_driveix, mrhdrp->mh_mediaix ); } return fileh; } /* inventory file */ if ( scrhdrp->cih_mediafiletype == CIH_MEDIAFILETYPE_INVENTORY ) { fileh = pi_insertfile( drhdrp->dh_drivecnt, drhdrp->dh_driveix, mrhdrp->mh_mediaix, BOOL_TRUE, &mrhdrp->mh_mediaid, mrhdrp->mh_medialabel, BOOL_TRUE, &mrhdrp->mh_prevmediaid, mrhdrp->mh_prevmedialabel, BOOL_TRUE, mrhdrp->mh_mediafileix, BOOL_TRUE, mrhdrp->mh_dumpmediafileix, BOOL_TRUE, mrhdrp->mh_dumpfileix, BOOL_FALSE, ( xfs_ino_t )0, ( off64_t )0, PF_INV, BOOL_FALSE, ( off64_t )0 ); if ( fileh == DH_NULL ) { return DH_NULL; } pi_seestrmend( drhdrp->dh_driveix ); pi_seeobjstrmend( drhdrp->dh_driveix, mrhdrp->mh_mediaix ); if ( drhdrp->dh_driveix < drhdrp->dh_drivecnt - 1 ) { ( void )pi_insertfile( drhdrp->dh_drivecnt, drhdrp->dh_driveix + 1, 0, BOOL_FALSE, 0, 0, BOOL_FALSE, 0, 0, BOOL_FALSE, 0, BOOL_TRUE, 0, BOOL_FALSE, 0, BOOL_TRUE, scrhdrp->cih_endpt.sp_ino, scrhdrp->cih_endpt.sp_offset, 0, BOOL_FALSE, ( off64_t )0 ); } if ( ! persp->s.fullinvpr && Mediap->M_pos == POS_ATHDR ) { size_t bufszincr; size_t bufsz; size_t buflen; char *bufp; inv_session_t *sessp; invt_sessinfo_t sessinfo; bool_t ok; bool_t donepr; /* read inventory into buffer */ bufszincr = IBPGINCR * PGSZ; /* use 4096, no need to be correlated * with system page size */ bufsz = bufszincr; buflen = 0; bufp = ( char * )malloc( bufsz ); /* need to read until we hit EOF/EOD. that's the only * way to know how big the inventory is. mark the Media * current media file as no longer at hdr. */ Mediap->M_pos = POS_ATNONDIR; donepr = BOOL_FALSE; while ( ! donepr ) { int nread; drive_ops_t *dop = drivep->d_opsp; int rval = 0; nread = read_buf( bufp + buflen, bufszincr, ( void * )drivep, ( rfp_t )dop->do_read, ( rrbfp_t )dop->do_return_read_buf, &rval ); switch( rval ) { case 0: assert( nread == ( int )bufszincr ); buflen += ( size_t )nread; bufsz += bufszincr; bufp = ( char * )realloc(( void * )bufp, bufsz ); assert( bufp ); continue; case DRIVE_ERROR_EOD: case DRIVE_ERROR_EOF: buflen += ( size_t )nread; donepr = BOOL_TRUE; break; default: free( ( void * )bufp ); return fileh; } } /* ask inventory to convert buffer into session * desc. */ sessp = 0; if ( ! buflen ) { ok = BOOL_FALSE; } else { /* extract the session information from the buffer */ if ( stobj_unpack_sessinfo( bufp, buflen, &sessinfo )<0 ) { ok = BOOL_FALSE; } else { stobj_convert_sessinfo(&sessp, &sessinfo); ok = BOOL_TRUE; } } if ( ! ok || ! sessp ) { mlog( MLOG_DEBUG | MLOG_WARNING | MLOG_MEDIA, _( "on-media session " "inventory corrupt\n") ); } else { /* if root, update online inventory. */ if ( ! geteuid( ) && ! tranp->t_noinvupdatepr ) { mlog( MLOG_VERBOSE | MLOG_MEDIA, _( "incorporating on-media session " "inventory into online " "inventory\n") ); inv_put_sessioninfo( &sessinfo ); } /* convert into pi format */ mlog( MLOG_VERBOSE | MLOG_MEDIA, "using on-media session inventory\n" ); persp->s.fullinvpr = pi_transcribe( sessp ); inv_free_session( &sessp ); } free( ( void * )bufp ); } return fileh; } assert( 0 ); return DH_NULL; } /* translate a session inventory into a pi */ static bool_t pi_transcribe( inv_session_t *sessp ) { ix_t strmcnt; ix_t strmix; /* traverse inventory, transcribing into pers inv. */ strmcnt = ( size_t )sessp->s_nstreams; for ( strmix = 0 ; strmix < strmcnt ; strmix++ ) { inv_stream_t *strmp; size_t fileix; size_t filecnt; uuid_t lastobjid; label_t lastobjlabel; ix_t mediaix; size_t dumpmediafileix; strmp = &sessp->s_streams[ strmix ]; filecnt = strmp->st_nmediafiles; uuid_clear(lastobjid); lastobjlabel[ 0 ] = 0; mediaix = 0; dumpmediafileix = 0; /* insert all media files from this stream. note that * the media object representation is inverted */ for ( fileix = 0 ; fileix < filecnt ; fileix++ ) { inv_mediafile_t *filep; bool_t fileszvalpr; filep = &strmp->st_mediafiles[ fileix ]; if ( uuid_compare( filep->m_moid, lastobjid ) != 0) { dumpmediafileix = 0; if ( fileix != 0 ) { pi_seeobjstrmend( strmix, mediaix ); mediaix++; } } fileszvalpr = BOOL_TRUE; ( void )pi_insertfile( strmcnt, strmix, mediaix, BOOL_TRUE, &filep->m_moid, filep->m_label, BOOL_TRUE, &lastobjid, lastobjlabel, BOOL_TRUE, filep->m_mfile_index, BOOL_TRUE, dumpmediafileix, BOOL_TRUE, fileix, filep->m_isinvdump ? BOOL_FALSE : BOOL_TRUE, filep->m_startino, filep->m_startino_off, filep->m_isinvdump ? PF_INV : 0, fileszvalpr, filep->m_size ); uuid_copy(lastobjid, filep->m_moid); strncpy( lastobjlabel, filep->m_label, sizeof( lastobjlabel )); dumpmediafileix++; } pi_seestrmend( strmix ); pi_seeobjstrmend( strmix, mediaix ); } return BOOL_TRUE; } /* clean up pers. inv: initially no media objects in drives. flags may * be set from previously interrupted invocation. */ static void pi_preclean( void ) { dh_t strmh; dh_t objh; dh_t fileh; for ( strmh = persp->s.strmheadh ; strmh != DH_NULL ; strmh = DH2S( strmh )->s_nexth ) { for ( objh = DH2S( strmh )->s_cldh ; objh != DH_NULL ; objh = DH2O( objh )->o_nexth ) { DH2O( objh )->o_indrivepr = BOOL_FALSE; for ( fileh = DH2O( objh )->o_cldh ; fileh != DH_NULL ; fileh = DH2F( fileh )->f_nexth ) { DH2F( fileh )->f_underheadpr = BOOL_FALSE; } } } } /* tell pi no media objects are in this drive */ static void pi_driveempty( ix_t driveix ) { dh_t strmh; dh_t objh; dh_t fileh; pi_lock( ); for ( strmh = persp->s.strmheadh ; strmh != DH_NULL ; strmh = DH2S( strmh )->s_nexth ) { for ( objh = DH2S( strmh )->s_cldh ; objh != DH_NULL ; objh = DH2O( objh )->o_nexth ) { if ( DH2O( objh )->o_indrivepr && DH2O( objh )->o_indriveix == driveix ) { DH2O( objh )->o_indrivepr = BOOL_FALSE; for ( fileh = DH2O( objh )->o_cldh ; fileh != DH_NULL ; fileh = DH2F( fileh )->f_nexth ) { DH2F( fileh )->f_underheadpr = BOOL_FALSE; } } } } pi_unlock( ); } /* tell pi this media object is in the drive */ static void pi_note_indrive( ix_t driveix, uuid_t media_id ) { dh_t strmh; dh_t objh; pi_lock( ); for ( strmh = persp->s.strmheadh ; strmh != DH_NULL ; strmh = DH2S( strmh )->s_nexth ) { for ( objh = DH2S( strmh )->s_cldh ; objh != DH_NULL ; objh = DH2O( objh )->o_nexth ) { if ( DH2O( objh )->o_idlabvalpr && uuid_compare( DH2O( objh )->o_id, media_id) == 0) { DH2O( objh )->o_indrivepr = BOOL_TRUE; DH2O( objh )->o_indriveix = driveix; goto done; } } } done: pi_unlock( ); } /* tell pi this media file is under the head of the drive containing the object */ static void pi_note_underhead( dh_t thisobjh, dh_t thisfileh ) { dh_t fileh; if ( thisobjh == DH_NULL ) { return; } pi_lock( ); if ( thisfileh != DH_NULL ) { DH2F( thisfileh )->f_underheadpr = BOOL_TRUE; } for ( fileh = DH2O( thisobjh )->o_cldh ; fileh != DH_NULL ; fileh = DH2F( fileh )->f_nexth ) { if ( fileh != thisfileh ) { DH2F( fileh )->f_underheadpr = BOOL_FALSE; } } pi_unlock( ); } /* mark the pi stream indicating all objects in that stream are known. */ static void pi_seestrmend( ix_t strmix ) { ix_t ix; dh_t strmh; pi_lock( ); /* get handle to the indexed stream */ for ( ix = 0, strmh = persp->s.strmheadh ; strmh != DH_NULL && ix < strmix ; ix++, strmh = DH2S( strmh )->s_nexth ) ; /* if an empty stream (can happen when dump interrupted), * nothing need be done, so return */ if ( strmh == DH_NULL ) { pi_unlock( ); return; } /* set stream flag and object and file counts */ DH2S( strmh )->s_lastobjknwnpr = BOOL_TRUE; pi_unlock( ); pi_show( " after pi_seestrmend" ); } /* mark pi indicating all media files in object are known */ static void pi_seeobjstrmend( ix_t strmix, ix_t mediaix ) { ix_t ix; dh_t strmh; dh_t objh; pi_lock( ); /* get handle to the indexed stream */ for ( ix = 0, strmh = persp->s.strmheadh ; strmh != DH_NULL && ix < strmix ; ix++, strmh = DH2S( strmh )->s_nexth ) ; /* if an empty stream (can happen when dump interrupted), * nothing need be done, so return */ if ( strmh == DH_NULL ) { pi_unlock( ); return; } /* get handle to indexed object in stream */ for ( ix = 0, objh = DH2S( strmh )->s_cldh ; objh != DH_NULL && ix < mediaix ; ix++, objh = DH2O( objh )->o_nexth ) ; /* if an empty object (can happen when dump interrupted), * nothing need be done, so return */ if ( objh == DH_NULL ) { pi_unlock( ); return; } /* set object flag */ DH2O( objh )->o_lmfknwnpr = BOOL_TRUE; pi_unlock( ); pi_show( " after pi_seeobjstrmend" ); } /* scans pi to determine ino of last file wholly or partially contained on * this mfile. must err on the high side if partial info. * NOTE: assumes caller locks pi! */ static xfs_ino_t pi_scanfileendino( dh_t fileh ) { dh_t strmh; ix_t mode = 0; assert( fileh != DH_NULL ); /* traverse the pi tree, looking for the next media file after */ for ( strmh = persp->s.strmheadh ; strmh != DH_NULL ; strmh = DH2S( strmh )->s_nexth ) { dh_t objh; for ( objh = DH2S( strmh )->s_cldh ; objh != DH_NULL ; objh = DH2O( objh )->o_nexth ) { dh_t nexth; for ( nexth = DH2O( objh )->o_cldh ; nexth != DH_NULL ; nexth = DH2F( nexth )->f_nexth ) { switch( mode ) { case 0: if ( nexth == fileh ) { mode = 1; } break; default: if ( DH2F( nexth )->f_valpr ) { xfs_ino_t ino; assert( ! ( DH2F( nexth )->f_flags & PF_INV )); assert( ! ( DH2F( nexth )->f_flags & PF_TERM )); if ( DH2F( nexth )->f_firstegrp.eg_off ) { ino = DH2F( nexth )->f_firstegrp.eg_ino; return ino; } else { assert( DH2F( nexth )->f_firstegrp.eg_ino > 0 ); ino = DH2F( nexth )->f_firstegrp.eg_ino - 1; return ino; } } break; } } } } return INO64MAX; } /* used to detemine range of extent groups still to be restored * from media file. *--o */ static void pi_bracketneededegrps( dh_t thisfileh, egrp_t *first_egrp, egrp_t *next_egrp ) { dh_t strmh; bool_t thisfoundpr = BOOL_FALSE; dh_t prech = DH_NULL; dh_t follh = DH_NULL; assert( thisfileh != DH_NULL ); /* traverse the pi tree, looking for fileh */ pi_lock( ); assert( DH2F( thisfileh )->f_valpr ); for ( strmh = persp->s.strmheadh ; strmh != DH_NULL ; strmh = DH2S( strmh )->s_nexth ) { dh_t objh; for ( objh = DH2S( strmh )->s_cldh ; objh != DH_NULL ; objh = DH2O( objh )->o_nexth ) { dh_t fileh; for ( fileh = DH2O( objh )->o_cldh ; fileh != DH_NULL ; fileh = DH2F( fileh )->f_nexth ) { if ( ! thisfoundpr ) { if ( fileh == thisfileh ) { thisfoundpr = BOOL_TRUE; } else if ( DH2F( fileh )->f_valpr ) { assert( ! ( DH2F( fileh )->f_flags & PF_INV )); assert( ! ( DH2F( fileh )->f_flags & PF_TERM )); prech = fileh; } } else if ( DH2F( fileh )->f_valpr ) { assert( ! ( DH2F( fileh )->f_flags & PF_INV )); assert( ! ( DH2F( fileh )->f_flags & PF_TERM )); assert( follh == DH_NULL ); follh = fileh; goto done; } } } } done: assert( thisfoundpr ); /* initially the lower bracket is this file descriptor's * current egrp. this catches the case where a previous restore * session was interrupted while restoring this media file. */ *first_egrp = DH2F( thisfileh )->f_curegrp; /* if the closest valid preceeding media file's current egrp is * greater, use it as the lower bracket */ if ( prech != DH_NULL && egrpcmp( &DH2F( prech )->f_curegrp, first_egrp ) > 0 ) { *first_egrp = DH2F( prech )->f_curegrp; } /* the upper bracket is initially the end of the world. * if we found a valid following file descriptor describing a * media file which has already been at least restored, use * its first egrp as an upper bracket. */ next_egrp->eg_ino = INO64MAX; next_egrp->eg_off = OFF64MAX; if ( follh != DH_NULL && egrpcmp( &DH2F( follh )->f_curegrp, &DH2F( follh )->f_firstegrp ) > 0 ) { *next_egrp = DH2F( follh )->f_firstegrp; } pi_unlock( ); } static void pi_update_stats( off64_t sz ) { pi_lock( ); assert( persp->s.stat_valpr ); persp->s.stat_inodone++; persp->s.stat_datadone += sz; pi_unlock( ); } /* pi_iterator - each invocation of the iterator advances to the next media file * in the dump session, walking the media file hierarchy depth-wise. if * an object's file list is exhausted and the first media file in the next * object is returned and the exhausted object's last media file has not yet * been identified, the return-by-ref flag filemissingpr is set. similarly for * streams, objmissingpr. * NOTE: does not preset missingpr's to FALSE. * NOTE: caller must lock pi. */ struct pi_iter { bool_t initializedpr; dh_t strmh; dh_t objh; dh_t fileh; bool_t donepr; }; typedef struct pi_iter pi_iter_t; static pi_iter_t * pi_iter_alloc( void ) { pi_iter_t *iterp; iterp = ( pi_iter_t * )calloc( 1, sizeof( pi_iter_t )); assert( iterp ); return iterp; } static void pi_iter_free( pi_iter_t *iterp ) { free( ( void * )iterp ); } static dh_t pi_iter_nextfileh( pi_iter_t *iterp, bool_t *objmissingprp, bool_t *filemissingprp ) { assert( ! iterp->donepr ); if ( persp->s.strmheadh == DH_NULL ) { iterp->donepr = BOOL_TRUE; return DH_NULL; } if ( ! iterp->initializedpr ) { assert( persp->s.strmheadh != DH_NULL ); iterp->strmh = persp->s.strmheadh; iterp->objh = DH2S( iterp->strmh )->s_cldh; if ( iterp->objh == DH_NULL ) { if ( ! DH2S( iterp->strmh )->s_lastobjknwnpr ) { *objmissingprp = BOOL_TRUE; } } else { iterp->fileh = DH2O( iterp->objh )->o_cldh; if ( iterp->fileh == DH_NULL ) { if ( ! DH2O( iterp->objh )->o_lmfknwnpr ) { *filemissingprp = BOOL_TRUE; } } } while ( iterp->fileh == DH_NULL ) { while ( iterp->objh == DH_NULL ) { if ( ! DH2S( iterp->strmh )->s_lastobjknwnpr ) { *objmissingprp = BOOL_TRUE; } iterp->strmh = DH2S( iterp->strmh )->s_nexth; if ( iterp->strmh == DH_NULL ) { iterp->donepr = BOOL_TRUE; return DH_NULL; } iterp->objh = DH2S( iterp->strmh )->s_cldh; } iterp->fileh = DH2O( iterp->objh )->o_cldh; if ( iterp->fileh == DH_NULL ) { if ( ! DH2O( iterp->objh )->o_lmfknwnpr ) { *filemissingprp = BOOL_TRUE; } iterp->objh = DH2O( iterp->objh )->o_nexth; } } iterp->initializedpr = BOOL_TRUE; return iterp->fileh; } iterp->fileh = DH2F( iterp->fileh )->f_nexth; while ( iterp->fileh == DH_NULL ) { if ( ! DH2O( iterp->objh )->o_lmfknwnpr ) { *filemissingprp = BOOL_TRUE; } iterp->objh = DH2O( iterp->objh )->o_nexth; while ( iterp->objh == DH_NULL ) { if ( ! DH2S( iterp->strmh )->s_lastobjknwnpr ) { *objmissingprp = BOOL_TRUE; } iterp->strmh = DH2S( iterp->strmh )->s_nexth; if ( iterp->strmh == DH_NULL ) { iterp->donepr = BOOL_TRUE; return DH_NULL; } iterp->objh = DH2S( iterp->strmh )->s_cldh; } iterp->fileh = DH2O( iterp->objh )->o_cldh; } return iterp->fileh; } /* produces a list of media objects needed. also indicates if we know * some unidentified media objects are needed, and if it is possible * that we need some unidentifed objects, but don't know for sure. * if markskippr is set, set the f_nondirskipr flag if the media file * does not contain any nondirs of interest. */ struct bagobj { bagelem_t bagelem; uuid_t id; label_t label; bool_t indrivepr; ix_t indriveix; }; typedef struct bagobj bagobj_t; static bag_t * pi_neededobjs_nondir_alloc( bool_t *knownholesprp, bool_t *maybeholesprp, bool_t showobjindrivepr, bool_t markskippr ) { bag_t *bagp; pi_iter_t *headiterp; pi_iter_t *tailiterp; dh_t headh; dh_t tailh; egrp_t tailegrp; bool_t knownobjmissingpr; bool_t maybeobjmissingpr; bool_t maybefilemissingpr; dh_t lastobjaddedh; int objlistlen; /* no point in proceeding if pi not begun */ if ( persp->s.strmheadh == DH_NULL ) { *knownholesprp = BOOL_TRUE; *maybeholesprp = BOOL_FALSE; return 0; } /* to hold a list of media object handles: caller must free * using pi_neededobjs_free( ). */ bagp = bag_alloc( ); /* allocate two iterators to scan pi */ tailiterp = pi_iter_alloc( ); headiterp = pi_iter_alloc( ); /* set the handle to the last file added to the list to NULL. * this will be updated each time we add an object to the list, * preventing the same object from being added more than once. * this works because the media files for a given object will * always appear contiguous and just once in a pi iteration. */ lastobjaddedh = DH_NULL; objlistlen = 0; /* these will be set TRUE if the tail iterator ever indicates * we crossed an object or stream boundary and did not see a * valid last file or last object respectively. can accumulate * the booleans, since iterator never sets FALSE, just TRUE. */ maybeobjmissingpr = BOOL_FALSE; maybefilemissingpr = BOOL_FALSE; /* this will be set TRUE if we see a needed media file but the * object containing the media file has not been IDed. */ knownobjmissingpr = BOOL_FALSE; tailegrp.eg_ino = 0; tailegrp.eg_off = 0; tailh = DH_NULL; /* lock up the inventory during the scan */ pi_lock( ); do { egrp_t headegrp; bool_t foundgappr; /* advance the head until we see the next media file which has * a valid egrp, or until we run out of media files. */ do { bool_t dummyobjmissingpr; bool_t dummyfilemissingpr; headh = pi_iter_nextfileh( headiterp, &dummyobjmissingpr, &dummyfilemissingpr ); } while ( headh != DH_NULL && ! DH2F( headh )->f_valpr ); if ( headh == DH_NULL ) { headegrp.eg_ino = INO64MAX; headegrp.eg_off = OFF64MAX; } else { assert( ! ( DH2F( headh )->f_flags & PF_INV )); assert( ! ( DH2F( headh )->f_flags & PF_TERM )); headegrp = DH2F( headh )->f_firstegrp; } /* see if the range of egrps from head up to but not including * tail needed according to ino map */ if ( gapneeded( &tailegrp, &headegrp )) { foundgappr = BOOL_TRUE; } else { foundgappr = BOOL_FALSE; } /* now bring tail up to head, adding objects and setting flags * along the way. note special handling of NULL tailh. possible * only first time through: ignore. also, ignore inv and term. */ do { /* if requested, mark media files not needed */ if ( markskippr && ! foundgappr && tailh != DH_NULL && ! ( DH2F( tailh )->f_flags & PF_INV ) && ! ( DH2F( tailh )->f_flags & PF_TERM ) && ! DH2F( tailh )->f_nondirskippr ) { DH2F( tailh )->f_nondirskippr = BOOL_TRUE; } /* build up list of needed objects */ if ( foundgappr && tailh != DH_NULL && ! ( DH2F( tailh )->f_flags & PF_INV ) && ! ( DH2F( tailh )->f_flags & PF_TERM ) && ! DH2F( tailh )->f_nondirdonepr && ! DH2F( tailh )->f_nondirskippr ) { dh_t objh = DH2F( tailh )->f_parh; if ( ! DH2O( objh )->o_indrivepr || showobjindrivepr ) { if ( DH2O( objh )->o_idlabvalpr ) { if ( objh != lastobjaddedh ) { addobj( bagp, &DH2O( objh )->o_id, DH2O( objh )->o_lab, DH2O( objh )->o_indrivepr, DH2O( objh )->o_indriveix ); lastobjaddedh = objh; objlistlen++; } } else { knownobjmissingpr = BOOL_TRUE; } } } /* pull the tail up to the next media file */ tailh = pi_iter_nextfileh( tailiterp, &maybeobjmissingpr, &maybefilemissingpr ); } while ( tailh != headh ); tailegrp = headegrp; } while ( headh != DH_NULL ); pi_unlock( ); /* free the iterators */ pi_iter_free( tailiterp ); pi_iter_free( headiterp ); /* free the bag and return NULL if object list empty */ if ( objlistlen == 0 ) { bag_free( bagp ); bagp = 0; } *maybeholesprp = ( maybeobjmissingpr || maybefilemissingpr ); *knownholesprp = knownobjmissingpr; return bagp; } static bag_t * pi_neededobjs_dir_alloc( bool_t *knownholesprp, bool_t *maybeholesprp ) { bag_t *bagp; dh_t fileh; pi_iter_t *iterp; bool_t knownobjmissingpr; bool_t maybeobjmissingpr; bool_t maybefilemissingpr; dh_t lastobjaddedh; int objlistlen; bagp = bag_alloc( ); iterp = pi_iter_alloc( ); knownobjmissingpr = BOOL_FALSE; maybeobjmissingpr = BOOL_FALSE; maybefilemissingpr = BOOL_FALSE; lastobjaddedh = DH_NULL; objlistlen = 0; pi_lock( ); while ( ( fileh = pi_iter_nextfileh( iterp, &maybeobjmissingpr, &maybefilemissingpr )) != DH_NULL ) { if ( ! DH2F( fileh )->f_dirtriedpr ) { dh_t objh = DH2F( fileh )->f_parh; if ( ! DH2O( objh )->o_indrivepr ) { if ( DH2O( objh )->o_idlabvalpr ) { if ( objh != lastobjaddedh ) { addobj( bagp, &DH2O( objh )->o_id, DH2O( objh )->o_lab, DH2O( objh )->o_indrivepr, DH2O( objh )->o_indriveix ); lastobjaddedh = objh; objlistlen++; } } else { knownobjmissingpr = BOOL_TRUE; } } } } pi_unlock( ); pi_iter_free( iterp ); if ( objlistlen == 0 ) { bag_free( bagp ); bagp = 0; } *maybeholesprp = ( maybeobjmissingpr || maybefilemissingpr ); *knownholesprp = knownobjmissingpr; return bagp; } static void pi_neededobjs_free( bag_t *bagp ) { bagiter_t bagiter; bagobj_t *bagobjp; bagelem_t *bagelemp; size64_t dummykey; void *dummypayloadp; assert( bagp ); bagiter_init( bagp, &bagiter ); bagobjp = 0; while (( bagelemp = bagiter_next( &bagiter, ( void ** )&bagobjp ) )) { bag_remove( bagp, bagelemp, &dummykey, &dummypayloadp ); assert( bagobjp ); assert( bagobjp == ( bagobj_t * )dummypayloadp ); free( ( void * )bagobjp ); bagobjp = 0; } bag_free( bagp ); } /* a macro predicate to indicate if we know we are done. if we are not * done or don't know, returns FALSE. */ static bool_t pi_alldone( void ) { bag_t *bagp; bool_t knownholespr; bool_t maybeholespr; size_t cnt; knownholespr = BOOL_FALSE; maybeholespr = BOOL_FALSE; bagp = pi_neededobjs_nondir_alloc( &knownholespr, &maybeholespr, BOOL_TRUE, BOOL_FALSE ); if ( bagp ) { cnt = cntobj( bagp ); pi_neededobjs_free( bagp ); } else { cnt = 0; } if ( cnt || knownholespr || maybeholespr ) { return BOOL_FALSE; } else { return BOOL_TRUE; } } /* tells the persistent inventory we hit end-of-data while examining the * object specified by the index param. this tells us we've seen the end * of the stream as well as the end of the object. */ static void pi_hiteod( ix_t strmix, ix_t objix ) { ix_t ix; dh_t strmh; dh_t objh; size_t objcnt; ix_t lastobjix; pi_lock( ); /* get handle to the indexed stream */ for ( ix = 0, strmh = persp->s.strmheadh ; strmh != DH_NULL && ix < strmix ; ix++, strmh = DH2S( strmh )->s_nexth ) ; assert( strmh != DH_NULL ); /* get index to last object in stream */ for ( objcnt = 0, objh = DH2S( strmh )->s_cldh ; objh != DH_NULL ; objh = DH2O( objh )->o_nexth, objcnt++ ) ; assert( objcnt != 0 ); lastobjix = objcnt - 1; pi_unlock( ); /* can't possibly happen, but check for case where pi indicates * other media objects beyond this one. */ if ( objix != lastobjix ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_MEDIA, _( "hit EOD at stream %u object %u, " "yet inventory indicates last object index is %u\n"), strmix, objix, lastobjix ); } else { pi_seestrmend( strmix ); } pi_seeobjstrmend( strmix, lastobjix ); } /* tells the persistent inventory we hit end-of-media while examining the * object specified by the index param. this tells us we've seen the end * of the object. */ static void pi_hiteom( ix_t strmix, ix_t objix ) { pi_seeobjstrmend( strmix, objix ); } static void pi_hitnextdump( ix_t strmix, ix_t objix, ix_t lastfileix ) { ix_t ix; dh_t strmh; dh_t objh; size_t objcnt; ix_t lastobjix; pi_lock( ); /* get handle to the indexed stream */ for ( ix = 0, strmh = persp->s.strmheadh ; strmh != DH_NULL && ix < strmix ; ix++, strmh = DH2S( strmh )->s_nexth ) ; assert( strmh != DH_NULL ); /* get index to last object in stream */ for ( objcnt = 0, objh = DH2S( strmh )->s_cldh ; objh != DH_NULL ; objh = DH2O( objh )->o_nexth, objcnt++ ) ; assert( objcnt != 0 ); lastobjix = objcnt - 1; pi_unlock( ); /* can't possibly happen, but check for case where pi indicates * other media objects beyond this one. */ if ( objix != lastobjix ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_MEDIA, _( "hit next dump at stream %u object %u file %u, " "yet inventory indicates last object index is %u\n"), strmix, objix, lastfileix, lastobjix ); } else { pi_seestrmend( strmix ); } pi_seeobjstrmend( strmix, lastobjix ); } /* returns TRUE if pi is certain no more useful media files remaining * on object. if any doubt, such as not knowing the last media file on * the object, returns FALSE. */ static bool_t pi_know_no_more_on_object( purp_t purp, ix_t strmix, ix_t objix ) { ix_t ix; dh_t strmh; dh_t objh; dh_t fileh; assert( purp == PURP_DIR || purp == PURP_NONDIR ); pi_lock( ); /* get handle to the indexed stream */ for ( ix = 0, strmh = persp->s.strmheadh ; strmh != DH_NULL && ix < strmix ; ix++, strmh = DH2S( strmh )->s_nexth ) ; assert( strmh != DH_NULL ); /* get handle to indexed object */ for ( ix = 0, objh = DH2S( strmh )->s_cldh ; objh != DH_NULL && ix < objix ; ix++, objh = DH2O( objh )->o_nexth ) ; assert( objh != DH_NULL ); /* if don't know last media file on object, return FALSE */ if ( ! DH2O( objh )->o_lmfknwnpr ) { pi_unlock( ); return BOOL_FALSE; } /* check all media files on object. if any are not marked done, * return FALSE. */ for ( fileh = DH2O( objh )->o_cldh ; fileh != DH_NULL ; fileh = DH2F( fileh )->f_nexth ) { if ( DH2F( fileh )->f_flags & PF_INV ) { continue; } if ( DH2F( fileh )->f_flags & PF_TERM ) { continue; } if ( purp == PURP_DIR ) { if ( ! DH2F( fileh )->f_dirtriedpr ) { pi_unlock( ); return BOOL_FALSE; } } else { if ( ! DH2F( fileh )->f_nondirskippr && ! DH2F( fileh )->f_nondirdonepr ) { pi_unlock( ); return BOOL_FALSE; } } } pi_unlock( ); return BOOL_TRUE; } static bool_t pi_know_no_more_beyond_on_object( purp_t purp, ix_t strmix, ix_t objix, ix_t fileix ) { ix_t ix; dh_t strmh; dh_t objh; dh_t fileh; assert( purp == PURP_DIR || purp == PURP_NONDIR ); pi_lock( ); /* get handle to the indexed stream */ for ( ix = 0, strmh = persp->s.strmheadh ; strmh != DH_NULL && ix < strmix ; ix++, strmh = DH2S( strmh )->s_nexth ) ; assert( strmh != DH_NULL ); /* get handle to indexed object */ for ( ix = 0, objh = DH2S( strmh )->s_cldh ; objh != DH_NULL && ix < objix ; ix++, objh = DH2O( objh )->o_nexth ) ; assert( objh != DH_NULL ); /* if don't know last media file on object, return FALSE */ if ( ! DH2O( objh )->o_lmfknwnpr ) { pi_unlock( ); return BOOL_FALSE; } /* check all files on object after indexed file. if any are not marked * done, return FALSE. skip inventory and terminator files. */ for ( ix = 0, fileh = DH2O( objh )->o_cldh ; fileh != DH_NULL ; ix++, fileh = DH2F( fileh )->f_nexth ) { if ( ix <= fileix ) { continue; } if ( DH2F( fileh )->f_flags & PF_INV ) { continue; } if ( DH2F( fileh )->f_flags & PF_TERM ) { continue; } if ( purp == PURP_DIR ) { if ( ! DH2F( fileh )->f_dirtriedpr ) { pi_unlock( ); return BOOL_FALSE; } } else { if ( ! DH2F( fileh )->f_nondirdonepr && ! DH2F( fileh )->f_nondirskippr ) { pi_unlock( ); return BOOL_FALSE; } } } pi_unlock( ); return BOOL_TRUE; } /* indicates if the given extent group range is called for by the * ino map. *---o (endpoint not inclusive) */ static bool_t gapneeded( egrp_t *firstegrpp, egrp_t *lastegrpp ) { xfs_ino_t endino; if ( firstegrpp->eg_ino > lastegrpp->eg_ino ) { return BOOL_FALSE; } if ( firstegrpp->eg_ino == lastegrpp->eg_ino && firstegrpp->eg_off > lastegrpp->eg_off ) { return BOOL_FALSE; } if ( lastegrpp->eg_off > 0 || lastegrpp->eg_ino == 0 ) { endino = lastegrpp->eg_ino; } else { endino = lastegrpp->eg_ino - 1; } if ( ! inomap_rst_needed( firstegrpp->eg_ino, endino )) { return BOOL_FALSE; } return BOOL_TRUE; } static void addobj( bag_t *bagp, uuid_t *idp, label_t label, bool_t indrivepr, ix_t indriveix ) { bagobj_t *bagobjp; bagobjp = ( bagobj_t * )calloc( 1, sizeof( bagobj_t )); assert( bagobjp ); uuid_copy(bagobjp->id, *idp); strncpy( bagobjp->label, label, sizeof( bagobjp->label )); bagobjp->indrivepr = indrivepr; bagobjp->indriveix = indriveix; bag_insert( bagp, &bagobjp->bagelem, ( size64_t )0, ( void * )bagobjp ); } static size_t cntobj( bag_t *bagp ) { bagiter_t bagiter; bagobj_t *bagobjp; size_t cnt; assert( bagp ); bagiter_init( bagp, &bagiter ); cnt = 0; bagobjp = 0; /* keep lint happy */ while ( bagiter_next( &bagiter, ( void ** )&bagobjp )) { cnt++; bagobjp = 0; /* keep lint happy */ } return cnt; } /* misc. static functions ***************************************************/ /* queries inventory for the base of the given session. if the given session * was a resumed dump, then must be last dump of same level. otherwise, * must be last dump of a lesser level */ static bool_t askinvforbaseof( uuid_t baseid, inv_session_t *sessp ) { ix_t level; bool_t resumedpr; inv_idbtoken_t invtok; inv_session_t *basesessp; bool_t ok; level = ( ix_t )sessp->s_level; resumedpr = sessp->s_isresumed; /* don't look for base if level 0 and not resumed */ if ( level == 0 && ! resumedpr ) { return BOOL_TRUE; } /* open the inventory for this file system */ invtok = inv_open( INV_BY_UUID, INV_SEARCH_ONLY, ( void * )&sessp->s_fsid ); if ( invtok == INV_TOKEN_NULL ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_MEDIA, _( "unable to open inventory to validate dump\n") ); return BOOL_FALSE; } /* get the base session */ if ( resumedpr ) { ok = inv_lastsession_level_equalto(&sessp->s_fsid, invtok, (u_char_t)level, &basesessp); } else { ok = inv_lastsession_level_lessthan(&sessp->s_fsid, invtok, (u_char_t)level, &basesessp); } if ( ! ok ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_MEDIA, _( "unable to find base dump in inventory " "to validate dump\n") ); return BOOL_FALSE; } /* close the inventory */ ok = inv_close( invtok ); assert( ok ); /* return id of base session */ uuid_copy(baseid, basesessp->s_sesid); /* free the base session descriptor */ inv_free_session( &basesessp ); return BOOL_TRUE; } static bool_t dumpcompat( bool_t resumepr, ix_t level, uuid_t baseid, bool_t logpr ) { if ( persp->a.cumpr ) { if ( persp->a.dumpcnt == 0 ) { if ( resumepr ) { if ( logpr ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "cumulative restores must begin with " "an initial (not resumed) " "level 0 dump\n") ); } return BOOL_FALSE; } if ( level > 0 ) { if ( logpr ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "cumulative restores must begin with " "a level 0 dump\n") ); } return BOOL_FALSE; } } else { if ( resumepr ) { if ( uuid_compare( persp->a.lastdumpid, baseid) != 0) { if ( logpr ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "selected resumed dump " "not a resumption of " "previously applied dump\n")); } return BOOL_FALSE; } } else { if ( uuid_compare( persp->a.lastdumpid, baseid) != 0) { if ( logpr ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "selected dump not based on " "previously applied dump\n")); } return BOOL_FALSE; } } } } return BOOL_TRUE; } /* prompts for a new media object. supplies list of media objects still * needed, and indicates if there are or may be unidentified media objects * still needed/available */ static bool_t Media_prompt_change( drive_t *drivep, purp_t purp, bag_t *bagp, bool_t knownholespr, bool_t maybeholespr ) { fold_t fold; char question[ 100 ]; char *preamblestr[ PREAMBLEMAX ]; size_t preamblecnt; char *querystr[ QUERYMAX ]; size_t querycnt; char *choicestr[ CHOICEMAX ]; size_t choicecnt; char *ackstr[ ACKMAX ]; size_t ackcnt; char *postamblestr[ POSTAMBLEMAX ]; size_t postamblecnt; ix_t doix; ix_t dontix; ix_t invstatix; ix_t neededix; ix_t responseix; ix_t sigintix; retry: fold_init( fold, _("change media dialog"), '=' ); preamblecnt = 0; preamblestr[ preamblecnt++ ] = "\n"; preamblestr[ preamblecnt++ ] = fold; preamblestr[ preamblecnt++ ] = "\n\n"; assert( preamblecnt <= PREAMBLEMAX ); dlog_begin( preamblestr, preamblecnt ); /* query: ask if media changed or declined */ if ( drivecnt > 1 ) { sprintf( question, _( "please change media in " "drive %u\n"), (unsigned int)drivep->d_index ); } else { sprintf( question, _( "please change media in " "drive\n") ); } querycnt = 0; querystr[ querycnt++ ] = question; assert( querycnt <= QUERYMAX ); choicecnt = 0; dontix = choicecnt; choicestr[ choicecnt++ ] = _("media change declined"); if ( purp != PURP_SEARCH ) { invstatix = choicecnt; choicestr[ choicecnt++ ] = _("display media inventory status"); neededix = choicecnt; choicestr[ choicecnt++ ] = _("list needed media objects"); } else { invstatix = IXMAX; neededix = IXMAX; } doix = choicecnt; choicestr[ choicecnt++ ] = _("media changed"); assert( choicecnt <= CHOICEMAX ); sigintix = IXMAX - 1; responseix = dlog_multi_query( querystr, querycnt, choicestr, choicecnt, 0, /* hilitestr */ IXMAX, /* hiliteix */ 0, /* defaultstr */ doix, /* defaultix */ DLOG_TIMEOUT_MEDIA, dontix, /* timeout ix */ sigintix, /* sigint ix */ dontix, /* sighup ix */ dontix ); /* sigquit ix */ ackcnt = 0; if ( responseix == doix ) { ackstr[ ackcnt++ ] = _("examining new media\n"); } else if ( responseix == dontix ) { ackstr[ ackcnt++ ] = _("media change aborted\n"); } else if ( responseix == invstatix ) { ackstr[ ackcnt++ ] = "\n"; assert( ackcnt <= ACKMAX ); dlog_multi_ack( ackstr, ackcnt ); pi_show_nomloglock( ); postamblecnt = 0; fold_init( fold, _("end dialog"), '-' ); postamblestr[ postamblecnt++ ] = "\n"; postamblestr[ postamblecnt++ ] = fold; postamblestr[ postamblecnt++ ] = "\n\n"; assert( postamblecnt <= POSTAMBLEMAX ); dlog_end( postamblestr, postamblecnt ); goto retry; } else if ( responseix == neededix ) { ackstr[ ackcnt++ ] = "\n"; assert( ackcnt <= ACKMAX ); dlog_multi_ack( ackstr, ackcnt ); display_needed_objects( purp, bagp, knownholespr, maybeholespr ); postamblecnt = 0; fold_init( fold, "end dialog", '-' ); postamblestr[ postamblecnt++ ] = "\n"; postamblestr[ postamblecnt++ ] = fold; postamblestr[ postamblecnt++ ] = "\n\n"; assert( postamblecnt <= POSTAMBLEMAX ); dlog_end( postamblestr, postamblecnt ); goto retry; } else { assert( responseix == sigintix ); ackstr[ ackcnt++ ] = _("keyboard interrupt\n"); } assert( ackcnt <= ACKMAX ); dlog_multi_ack( ackstr, ackcnt ); postamblecnt = 0; fold_init( fold, _("end dialog"), '-' ); postamblestr[ postamblecnt++ ] = "\n"; postamblestr[ postamblecnt++ ] = fold; postamblestr[ postamblecnt++ ] = "\n\n"; assert( postamblecnt <= POSTAMBLEMAX ); dlog_end( postamblestr, postamblecnt ); if ( responseix == sigintix ) { if ( cldmgr_stop_requested( )) { return BOOL_FALSE; } sleep( 1 ); /* to allow main thread to begin dialog */ mlog( MLOG_NORMAL | MLOG_BARE, "" ); /* to block until main thread dialog complete */ sleep( 1 ); /* to allow main thread to request children die */ if ( cldmgr_stop_requested( )) { return BOOL_FALSE; } mlog( MLOG_DEBUG, "retrying media change dialog\n" ); goto retry; } return responseix == doix; } /* prompts the operator, asking if the current media file header describes * the dump to be restored */ static bool_t promptdumpmatch( ix_t thrdix, global_hdr_t *grhdrp, media_hdr_t *mrhdrp, content_hdr_t *crhdrp, content_inode_hdr_t *scrhdrp ) { fold_t fold; char introstring[ 80 ]; char *preamblestr[ PREAMBLEMAX ]; size_t preamblecnt; char *querystr[ QUERYMAX ]; size_t querycnt; char *choicestr[ CHOICEMAX ]; size_t choicecnt; char *ackstr[ ACKMAX ]; size_t ackcnt; char *postamblestr[ POSTAMBLEMAX ]; size_t postamblecnt; ix_t doix; ix_t dontix; ix_t responseix; ix_t sigintix; retry: preamblecnt = 0; fold_init( fold, _("dump selection dialog"), '=' ); preamblestr[ preamblecnt++ ] = "\n"; preamblestr[ preamblecnt++ ] = fold; preamblestr[ preamblecnt++ ] = "\n\n"; assert( preamblecnt <= PREAMBLEMAX ); dlog_begin( preamblestr, preamblecnt ); /* display vital stats and ask if this one should be restored */ if ( drivecnt > 0 ) { sprintf( introstring, _( "the following dump has been found" " on drive %u" "\n\n"), (unsigned int)thrdix ); } else { sprintf( introstring, _( "the following dump has been found" "\n\n") ); } assert( strlen( introstring ) < sizeof( introstring )); display_dump_label( BOOL_FALSE, MLOG_NORMAL | MLOG_BARE, introstring, grhdrp, mrhdrp, crhdrp, scrhdrp ); querycnt = 0; if ( tranp->t_toconlypr ) { querystr[ querycnt++ ] = _("\nexamine this dump?\n"); } else { querystr[ querycnt++ ] = (persp->a.interpr) ? _("\ninteractively restore from this dump?\n") : _("\nrestore this dump?\n"); } assert( querycnt <= QUERYMAX ); choicecnt = 0; dontix = choicecnt; choicestr[ choicecnt++ ] = _("skip"); doix = choicecnt; choicestr[ choicecnt++ ] = (persp->a.interpr) ? _("interactively restore\n") : _("restore\n"); assert( choicecnt <= CHOICEMAX ); sigintix = IXMAX - 1; responseix = dlog_multi_query( querystr, querycnt, choicestr, choicecnt, 0, /* hilitestr */ IXMAX, /* hiliteix */ 0, /* defaultstr */ doix, /* defaultix */ 0, IXMAX, /* timeout ix */ sigintix, /* sigint ix */ dontix, /* sighup ix */ dontix ); /* sigquit ix */ ackcnt = 0; if ( responseix == doix ) { ackstr[ ackcnt++ ] = (persp->a.interpr) ? _("this dump selected for interactive restoral\n") : _("this dump selected for restoral\n"); } else if ( responseix == dontix ) { ackstr[ ackcnt++ ] = _("dump skipped\n"); } else { assert( responseix == sigintix ); ackstr[ ackcnt++ ] = _("keyboard interrupt\n"); } assert( ackcnt <= ACKMAX ); dlog_multi_ack( ackstr, ackcnt ); postamblecnt = 0; fold_init( fold, "end dialog", '-' ); postamblestr[ postamblecnt++ ] = "\n"; postamblestr[ postamblecnt++ ] = fold; postamblestr[ postamblecnt++ ] = "\n\n"; assert( postamblecnt <= POSTAMBLEMAX ); dlog_end( postamblestr, postamblecnt ); if ( responseix == sigintix ) { if ( cldmgr_stop_requested( )) { return BOOL_FALSE; } sleep( 1 ); /* to allow main thread to begin dialog */ mlog( MLOG_NORMAL | MLOG_BARE, "" ); /* to block until main thread dialog complete */ sleep( 1 ); /* to allow main thread to request children die */ if ( cldmgr_stop_requested( )) { return BOOL_FALSE; } mlog( MLOG_DEBUG, "retrying dump selection dialog\n" ); goto retry; } return responseix == doix; } /* restore_file - knows how to restore non-directory files * * uses the tree's callback iterator, which will call me for each * link to the specified inode. */ struct cb_context { drive_t *cb_drivep; filehdr_t *cb_fhdrp; rv_t cb_rv; bool_t cb_ehcs; bool_t cb_ahcs; char *cb_path1; char *cb_path2; }; typedef struct cb_context cb_context_t; static bool_t restore_file_cb( void *, bool_t, char *, char * ); static rv_t restore_file( drive_t *drivep, filehdr_t *fhdrp, bool_t ehcs, bool_t ahcs, char *path1, char *path2 ) { rv_t rv; bstat_t *bstatp = &fhdrp->fh_stat; cb_context_t context; /* ask the tree to call me back for each link to this inode. * my callback will restore the file the first time it is * invoked, and create a hard link in subsequent calls. */ context.cb_drivep = drivep; context.cb_fhdrp = fhdrp; context.cb_rv = RV_OK; context.cb_ehcs = ehcs; context.cb_ahcs = ahcs; context.cb_path1 = path1; context.cb_path2 = path2; rv = tree_cb_links( bstatp->bs_ino, bstatp->bs_gen, bstatp->bs_ctime.tv_sec, bstatp->bs_mtime.tv_sec, restore_file_cb, &context, path1, path2 ); if (context.cb_rv) /* context error result has precedence */ return context.cb_rv; /* this would be set by callback */ else return rv; } /* called for each link to the file described by fhdr. the first * call is detected by noting linkpr is FALSE, and is used to create/ * update the first link to the file, using path1. subsequent calls have * linkpr set false, and should link path1 to path2. if path1 is ever null, * just pull from media: don't create. * if this func returns FALSE, will cause tree_cb_links to abort */ static bool_t restore_file_cb( void *cp, bool_t linkpr, char *path1, char *path2 ) { cb_context_t *contextp = ( cb_context_t * )cp; drive_t *drivep = contextp->cb_drivep; filehdr_t *fhdrp = contextp->cb_fhdrp; bstat_t *bstatp = &fhdrp->fh_stat; rv_t *rvp = &contextp->cb_rv; bool_t ehcs = contextp->cb_ehcs; bool_t ahcs = contextp->cb_ahcs; stream_context_t *strctxp = (stream_context_t *)drivep->d_strmcontextp; int rval; bool_t ok; if ( cldmgr_stop_requested( )) { *rvp = RV_INTR; return BOOL_FALSE; } if ( ! linkpr ) { if (path1) { /* cache the path for use in restoring attributes * and extended attributes */ strcpy(strctxp->sc_path, path1); } /* call type-specific function to create the file */ switch( bstatp->bs_mode & S_IFMT ) { case S_IFREG: ok = restore_reg( drivep, fhdrp, rvp, path1 ); if (!ok) return ok; if ( fhdrp->fh_flags & FILEHDR_FLAGS_EXTATTR ) { *rvp = restore_extattr( drivep, fhdrp, path1, ahcs, BOOL_FALSE, /* isdirpr */ BOOL_FALSE, /* onlydoreadpr */ DAH_NULL ); } else { ok = restore_extent_group( drivep, fhdrp, path1, strctxp->sc_fd, ehcs, rvp ); } return ok; case S_IFBLK: case S_IFCHR: case S_IFIFO: #ifdef S_IFNAM case S_IFNAM: #endif case S_IFSOCK: ok = restore_spec( fhdrp, rvp, path1 ); return ok; case S_IFLNK: ok = restore_symlink( drivep, fhdrp, rvp, path1, path2, ehcs ); return ok; default: mlog( MLOG_NORMAL | MLOG_WARNING, _( "ino %llu: unknown file type: %08x\n"), bstatp->bs_ino, bstatp->bs_mode ); return BOOL_FALSE; } } else if ( ! tranp->t_toconlypr ) { assert( path1 ); assert( path2 ); mlog( MLOG_TRACE, "linking %s to %s\n", path1, path2 ); rval = unlink( path2 ); if ( rval && errno != ENOENT ) { mlog( MLOG_VERBOSE | MLOG_WARNING, _( "unable to unlink " "current file prior to linking " "%s to %s:" " %s\n"), path1, path2, strerror( errno )); } else { rval = link( path1, path2 ); if ( rval ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "attempt to " "link %s to %s failed:" " %s\n"), path1, path2, strerror( errno )); } } return BOOL_TRUE; } else { mlog( MLOG_NORMAL | MLOG_BARE, "%s\n", path2 ); return BOOL_TRUE; } } /* * Set the file owner and strip suid/sgid if necessary. On failure, it will * close the file descriptor, unlink the file and return -1. On success, * it will mark the stream contexts as having set the owner and return 0. */ static int set_file_owner( char *path, int *fdp, stream_context_t *strcxtp) { bstat_t *bstatp = &strcxtp->sc_bstat; mode_t mode = (mode_t)bstatp->bs_mode; int rval; rval = fchown(*fdp, (uid_t)bstatp->bs_uid, (gid_t)bstatp->bs_gid ); if (!rval) goto done; mlog(MLOG_VERBOSE | MLOG_WARNING, _("chown (uid=%u, gid=%u) %s failed: %s\n"), bstatp->bs_uid, bstatp->bs_gid, path, strerror(errno)); if (mode & S_ISUID) { mlog(MLOG_VERBOSE | MLOG_WARNING, _("stripping setuid bit on %s since chown failed\n"), path); mode &= ~S_ISUID; } if ((mode & (S_ISGID|S_IXGRP)) == (S_ISGID|S_IXGRP)) { mlog(MLOG_VERBOSE | MLOG_WARNING, _("stripping setgid bit on %s since chown failed\n"), path); mode &= ~S_ISGID; } if (mode == (mode_t)bstatp->bs_mode) goto done; rval = fchmod(*fdp, mode); if (rval) { mlog(MLOG_VERBOSE | MLOG_ERROR, _("unable to strip setuid/setgid on %s, unlinking file.\n"), path); unlink(path); close(*fdp); *fdp = -1; return -1; } done: strcxtp->sc_ownerset = BOOL_TRUE; return 0; } /* called to begin a regular file. if no path given, or if just toc, * don't actually write, just read. also get into that situation if * cannot prepare destination. fd == -1 signifies no write. *statp * is set to indicate drive errors. returns FALSE if should abort * this iteration. */ static bool_t restore_reg( drive_t *drivep, filehdr_t *fhdrp, rv_t *rvp, char *path ) { bstat_t *bstatp = &fhdrp->fh_stat; stream_context_t *strctxp = (stream_context_t *)drivep->d_strmcontextp; int *fdp = &strctxp->sc_fd; int rval; struct fsxattr fsxattr; struct stat64 stat; int oflags; if ( !path ) return BOOL_TRUE; if ( fhdrp->fh_offset ) { if ( ! tranp->t_toconlypr ) { mlog( MLOG_TRACE, "restoring regular file ino %llu %s" " (offset %lld)\n", bstatp->bs_ino, path, fhdrp->fh_offset ); } else { mlog( MLOG_NORMAL | MLOG_BARE, _("%s (offset %lld)\n"), path, fhdrp->fh_offset ); } } else { if ( ! tranp->t_toconlypr ) { mlog( MLOG_TRACE, "restoring regular file ino %llu %s\n", bstatp->bs_ino, path ); } else { mlog( MLOG_NORMAL | MLOG_BARE, "%s\n", path ); } } if ( tranp->t_toconlypr ) return BOOL_TRUE; oflags = O_CREAT | O_RDWR; if (persp->a.dstdirisxfspr && bstatp->bs_xflags & XFS_XFLAG_REALTIME) oflags |= O_DIRECT; *fdp = open( path, oflags, S_IRUSR | S_IWUSR ); if ( *fdp < 0 ) { mlog( MLOG_NORMAL | MLOG_WARNING, _("open of %s failed: %s: discarding ino %llu\n"), path, strerror( errno ), bstatp->bs_ino ); return BOOL_TRUE; } rval = fstat64( *fdp, &stat ); if ( rval != 0 ) { mlog( MLOG_VERBOSE | MLOG_WARNING, _("attempt to stat %s failed: %s\n"), path, strerror( errno )); } else { if ( stat.st_size != bstatp->bs_size ) { mlog( MLOG_TRACE, "truncating %s from %lld to %lld\n", path, stat.st_size, bstatp->bs_size ); rval = ftruncate64( *fdp, bstatp->bs_size ); if ( rval != 0 ) { mlog( MLOG_VERBOSE | MLOG_WARNING, _("attempt to truncate %s failed: %s\n"), path, strerror( errno )); } } } if (strctxp->sc_ownerset == BOOL_FALSE && persp->a.ownerpr) { rval = set_file_owner(path, fdp, strctxp); if (rval) return BOOL_TRUE; } if ( persp->a.dstdirisxfspr ) { /* set the extended inode flags, except those which must * be set only after all data has been restored. */ assert( bstatp->bs_extsize >= 0 ); memset((void *)&fsxattr, 0, sizeof( fsxattr )); fsxattr.fsx_xflags = bstatp->bs_xflags & ~POST_DATA_XFLAGS; fsxattr.fsx_extsize = (uint32_t) bstatp->bs_extsize; fsxattr.fsx_projid = bstat_projid(bstatp); rval = ioctl( *fdp, XFS_IOC_FSSETXATTR, (void *)&fsxattr); if ( rval < 0 ) { mlog( MLOG_NORMAL | MLOG_WARNING, _("attempt to set extended attributes " "(xflags 0x%x, extsize = 0x%x, projid = 0x%x) " "of %s failed: %s\n"), fsxattr.fsx_xflags, fsxattr.fsx_extsize, fsxattr.fsx_projid, path, strerror(errno)); } } if ( persp->a.dstdirisxfspr && persp->a.restoredmpr ) { HsmBeginRestoreFile( bstatp, *fdp, &strctxp->sc_hsmflags ); } return BOOL_TRUE; } /* called to peel a regular file's extent groups from the media. * if no path given, or if just toc, don't actually write, just * read. fd == -1 signifies no write. *rvp is set to indicate * drive errors. returns FALSE if should abort this iteration. */ static bool_t restore_extent_group( drive_t *drivep, filehdr_t *fhdrp, char *path, int fd, bool_t ehcs, rv_t *rvp ) { bstat_t *bstatp = &fhdrp->fh_stat; off64_t restoredsz = 0; extenthdr_t ehdr; off64_t bytesread; rv_t rv; /* copy data extents from media to the file */ for ( ; ; ) { /* read the extent header */ rv = read_extenthdr( drivep, &ehdr, ehcs ); if ( rv != RV_OK ) { *rvp = rv; return BOOL_FALSE; } mlog( MLOG_NITTY, "read extent hdr type %s offset %lld sz %lld flags %x\n", ehdr_typestr( ehdr.eh_type ), ehdr.eh_offset, ehdr.eh_sz, ehdr.eh_flags ); /* if we see the specially marked last extent hdr, * we are done. */ if ( ehdr.eh_type == EXTENTHDR_TYPE_LAST ) { /* For a wholly sparse file, there is no HOLE * record; advance restoredsz to EOF. */ if (!restoredsz) restoredsz = bstatp->bs_size; break; } /* if its an ALIGNment extent, discard the extent. */ if ( ehdr.eh_type == EXTENTHDR_TYPE_ALIGN ) { size_t sz; assert( ehdr.eh_sz <= INTGENMAX ); sz = ( size_t )ehdr.eh_sz; rv = discard_padding( sz, drivep ); if ( rv != RV_OK ) { *rvp = rv; return BOOL_FALSE; } continue; } /* Add up extents restored to later check if the file * is done. */ restoredsz += ehdr.eh_sz; /* Increments of block size (usually 512) */ /* Holes do not need to be restored since we now * unlink the file at the start of the restore. */ if ( ehdr.eh_type == EXTENTHDR_TYPE_HOLE ) { continue; } /* real data */ assert( ehdr.eh_type == EXTENTHDR_TYPE_DATA ); bytesread = 0; rv = restore_extent( fhdrp, &ehdr, fd, path, drivep, &bytesread ); if ( rv != RV_OK ) { *rvp = rv; return BOOL_FALSE; } if ( cldmgr_stop_requested( )) { *rvp = RV_INTR; return BOOL_FALSE; } } /* The extent group has been restored. If the file is not * complete, we may need to co-ordinate with other restore * streams to time the restoration of extended attributes * and certain extended inode flags. Register the portion * of the file completed here in the persistent state. */ if (bstatp->bs_size > restoredsz) { partial_reg(drivep->d_index, bstatp->bs_ino, bstatp->bs_size, fhdrp->fh_offset, restoredsz); } return BOOL_TRUE; } /* apply the attributes that can only go on now that all data * and extended attributes have been applied. fd == -1 signifies * no write, due to unknown path or toc only. */ static bool_t restore_complete_reg(stream_context_t *strcxtp) { bstat_t *bstatp = &strcxtp->sc_bstat; char *path = strcxtp->sc_path; int fd = strcxtp->sc_fd; struct utimbuf utimbuf; int rval; // only applies to regular files if (!S_ISREG((strcxtp->sc_bstat.bs_mode))) return BOOL_TRUE; if (fd < 0) return BOOL_TRUE; if (!partial_check(bstatp->bs_ino, bstatp->bs_size)) { close(fd); return BOOL_TRUE; } /* set the access and modification times */ utimbuf.actime = ( time32_t )bstatp->bs_atime.tv_sec; utimbuf.modtime = ( time32_t )bstatp->bs_mtime.tv_sec; rval = utime( path, &utimbuf ); if ( rval ) { mlog( MLOG_VERBOSE | MLOG_WARNING, _( "unable to set access and modification " "times of %s: %s\n"), path, strerror( errno )); } /* set the owner and group (if enabled) */ if (strcxtp->sc_ownerset == BOOL_FALSE && persp->a.ownerpr) { rval = set_file_owner(path, &fd, strcxtp); if (rval) return BOOL_TRUE; } /* set the permissions/mode */ rval = fchmod( fd, ( mode_t )bstatp->bs_mode ); if ( rval ) { mlog( MLOG_VERBOSE | MLOG_WARNING, _( "unable to set mode of %s: %s\n"), path, strerror( errno )); } if ( persp->a.dstdirisxfspr && persp->a.restoredmpr ) { fsdmidata_t fssetdm; /* Set the DMAPI Fields. */ fssetdm.fsd_dmevmask = bstatp->bs_dmevmask; fssetdm.fsd_padding = 0; fssetdm.fsd_dmstate = bstatp->bs_dmstate; rval = ioctl( fd, XFS_IOC_FSSETDM, ( void * )&fssetdm ); if ( rval ) { mlog( MLOG_NORMAL | MLOG_WARNING, _("attempt to set DMI attributes of %s " "failed: %s\n"), path, strerror( errno )); } HsmEndRestoreFile( path, fd, &strcxtp->sc_hsmflags ); } /* set any extended inode flags that couldn't be set * prior to restoring the data. */ if ( persp->a.dstdirisxfspr && bstatp->bs_xflags & POST_DATA_XFLAGS ) { struct fsxattr fsxattr; memset((void *)&fsxattr, 0, sizeof( fsxattr )); fsxattr.fsx_xflags = bstatp->bs_xflags; fsxattr.fsx_extsize = (uint32_t)bstatp->bs_extsize; fsxattr.fsx_projid = bstat_projid(bstatp); rval = ioctl( fd, XFS_IOC_FSSETXATTR, (void *)&fsxattr ); if ( rval < 0 ) { mlog(MLOG_NORMAL | MLOG_WARNING, _("attempt to set extended attributes " "(xflags 0x%x, extsize = 0x%x, projid = 0x%x) " "of %s failed: %s\n"), fsxattr.fsx_xflags, fsxattr.fsx_extsize, fsxattr.fsx_projid, path, strerror(errno)); } } close(fd); return BOOL_TRUE; } /* ARGSUSED */ static bool_t restore_spec( filehdr_t *fhdrp, rv_t *rvp, char *path ) { bstat_t *bstatp = &fhdrp->fh_stat; struct utimbuf utimbuf; char *printstr; int rval; if ( ! path ) { return BOOL_TRUE; } switch ( bstatp->bs_mode & S_IFMT ) { case S_IFBLK: printstr = _("block special file"); break; case S_IFCHR: printstr = _("char special file"); break; case S_IFIFO: printstr = _("named pipe"); break; #ifdef S_IFNAM case S_IFNAM: printstr = _("XENIX named pipe"); break; #endif case S_IFSOCK: printstr = _("UNIX domain socket"); break; default: mlog( MLOG_NORMAL | MLOG_WARNING, _( "%s: unknown file type: mode 0x%x ino %llu\n"), path, bstatp->bs_mode, fhdrp->fh_stat.bs_ino ); return BOOL_TRUE; } if ( ! tranp->t_toconlypr ) { mlog( MLOG_TRACE, "restoring %s ino %llu %s\n", printstr, fhdrp->fh_stat.bs_ino, path ); } else { mlog( MLOG_NORMAL | MLOG_BARE, "%s\n", path ); } if ( ! tranp->t_toconlypr ) { if ( ( bstatp->bs_mode & S_IFMT ) == S_IFSOCK ) { int sockfd; struct sockaddr_un addr; size_t addrlen; sockfd = socket( AF_UNIX, SOCK_STREAM, 0 ); if ( sockfd < 0 ) { mlog( MLOG_VERBOSE | MLOG_WARNING, _( "unable to create " "%s ino %llu %s: %s: discarding\n"), printstr, fhdrp->fh_stat.bs_ino, path, strerror( errno )); return BOOL_TRUE; } memset( ( void * )&addr, 0, sizeof( addr )); addr.sun_family = AF_UNIX; if ( strlen( path ) >= sizeof( addr.sun_path )) { mlog( MLOG_VERBOSE | MLOG_WARNING, _( "pathname too long for bind of " "%s ino %llu %s: discarding\n"), printstr, fhdrp->fh_stat.bs_ino, path ); ( void )close( sockfd ); return BOOL_TRUE; } strcpy( addr.sun_path, path ); addrlen = strlen( addr.sun_path ) + sizeof( addr.sun_family ); rval = bind( sockfd, ( struct sockaddr * )&addr, ( int )addrlen ); if ( rval < 0 ) { mlog( MLOG_VERBOSE | MLOG_WARNING, _( "unable to bind " "%s ino %llu %s: %s: discarding\n"), printstr, fhdrp->fh_stat.bs_ino, path, strerror( errno )); ( void )close( sockfd ); return BOOL_TRUE; } ( void )close( sockfd ); } else { /* create the node */ rval = mknod( path, ( mode_t )bstatp->bs_mode, ( dev_t )IRIX_DEV_TO_KDEVT(bstatp->bs_rdev)); if ( rval && rval != EEXIST ) { mlog( MLOG_VERBOSE | MLOG_WARNING, _( "unable to create %s " "ino %llu %s: %s: discarding\n"), printstr, fhdrp->fh_stat.bs_ino, path, strerror( errno )); return BOOL_TRUE; } } /* set the owner and group (if enabled) */ if ( persp->a.ownerpr ) { rval = chown( path, ( uid_t )bstatp->bs_uid, ( gid_t )bstatp->bs_gid ); if ( rval ) { mlog( MLOG_VERBOSE | MLOG_WARNING, _("chown (uid=%u, gid=%u) %s " "failed: %s\n"), bstatp->bs_uid, bstatp->bs_gid, path, strerror( errno )); } } /* set the permissions/mode */ rval = chmod( path, ( mode_t )fhdrp->fh_stat.bs_mode ); if ( rval ) { mlog( MLOG_VERBOSE | MLOG_WARNING, _( "unable to set mode of %s: %s\n"), path, strerror( errno )); } /* set the access and modification times */ utimbuf.actime = ( time32_t )bstatp->bs_atime.tv_sec; utimbuf.modtime = ( time32_t )bstatp->bs_mtime.tv_sec; rval = utime( path, &utimbuf ); if ( rval ) { mlog( MLOG_VERBOSE | MLOG_WARNING, _( "unable to set access and modification " "times of %s: %s\n"), path, strerror( errno )); } } return BOOL_TRUE; } static bool_t restore_symlink( drive_t *drivep, filehdr_t *fhdrp, rv_t *rvp, char *path, char *scratchpath, bool_t ehcs ) { bstat_t *bstatp = &fhdrp->fh_stat; drive_ops_t *dop = drivep->d_opsp; extenthdr_t ehdr; char *scratch; int nread; int rval; rv_t rv; mode_t oldumask; if ( path ) { if ( ! tranp->t_toconlypr ) { mlog( MLOG_TRACE, "restoring symbolic link ino %llu %s\n", bstatp->bs_ino, path ); } else { mlog( MLOG_NORMAL | MLOG_BARE, "%s\n", path ); } } /* read the extent header */ rv = read_extenthdr( drivep, &ehdr, ehcs ); if ( rv != RV_OK ) { *rvp = rv; return BOOL_FALSE; } /* symlinks always have one extent */ assert( ehdr.eh_type == EXTENTHDR_TYPE_DATA ); /* read the link path extent */ if ( ehdr.eh_sz < ( off64_t )( 2 * MAXPATHLEN )) { scratch = scratchpath; } else { scratch = 0; } nread = read_buf( scratch, ( size_t )ehdr.eh_sz, ( void * )drivep, ( rfp_t )dop->do_read, ( rrbfp_t )dop->do_return_read_buf, &rval ); if ( rval ) { switch( rval ) { case DRIVE_ERROR_EOF: case DRIVE_ERROR_EOD: case DRIVE_ERROR_EOM: case DRIVE_ERROR_MEDIA: *rvp = RV_EOD; break; case DRIVE_ERROR_CORRUPTION: *rvp = RV_CORRUPT; break; case DRIVE_ERROR_DEVICE: *rvp = RV_DRIVE; break; case DRIVE_ERROR_CORE: default: *rvp = RV_CORE; } return BOOL_FALSE; } assert( ( off64_t )nread == ehdr.eh_sz ); if ( ! scratch ) { if ( path ) { mlog( MLOG_VERBOSE | MLOG_WARNING, _( "unable to create symlink ino %llu " "%s: src too long: discarding\n"), bstatp->bs_ino, path ); } return BOOL_TRUE; } scratchpath[ nread ] = 0; if ( ! tranp->t_toconlypr && path ) { /* create the symbolic link */ /* NOTE: There is no direct way to set mode for * sym links. Do it using umask. * No way of setting times for sym links. */ oldumask = umask( (( mode_t )(~bstatp->bs_mode)) & 0777 ); rval = symlink( scratchpath, path ); umask( oldumask ); if ( rval ) { mlog( MLOG_VERBOSE | MLOG_WARNING, _( "unable to create " "symlink ino %llu %s: %s: discarding\n"), bstatp->bs_ino, path, strerror( errno )); return BOOL_TRUE; } /* set the owner and group (if enabled) */ if ( persp->a.ownerpr ) { rval = lchown( path, ( uid_t )bstatp->bs_uid, ( gid_t )bstatp->bs_gid ); if ( rval ) { mlog( MLOG_VERBOSE | MLOG_WARNING, _("chown (uid=%u, gid=%u) %s " "failed: %s\n"), bstatp->bs_uid, bstatp->bs_gid, path, strerror( errno )); } } if ( persp->a.restoredmpr) { fsdmidata_t fssetdm; /* Restore DMAPI fields. */ fssetdm.fsd_dmevmask = bstatp->bs_dmevmask; fssetdm.fsd_padding = 0; fssetdm.fsd_dmstate = bstatp->bs_dmstate; rval = do_fssetdm_by_handle(path, &fssetdm); } } return BOOL_TRUE; } /* ARGSUSED */ static rv_t read_filehdr( drive_t *drivep, filehdr_t *fhdrp, bool_t fhcs ) { bstat_t *bstatp = &fhdrp->fh_stat; drive_ops_t *dop = drivep->d_opsp; /* REFERENCED */ int nread; int rval; filehdr_t tmpfh; nread = read_buf( ( char * )&tmpfh, sizeof( *fhdrp ), ( void * )drivep, ( rfp_t )dop->do_read, ( rrbfp_t )dop->do_return_read_buf, &rval ); xlate_filehdr(&tmpfh, fhdrp, 1); switch( rval ) { case 0: break; case DRIVE_ERROR_EOD: case DRIVE_ERROR_EOF: case DRIVE_ERROR_EOM: case DRIVE_ERROR_MEDIA: return RV_EOD; case DRIVE_ERROR_CORRUPTION: return RV_CORRUPT; case DRIVE_ERROR_DEVICE: return RV_DRIVE; case DRIVE_ERROR_CORE: default: return RV_CORE; } assert( ( size_t )nread == sizeof( *fhdrp )); mlog( MLOG_NITTY, "read file hdr off %lld flags 0x%x ino %llu mode 0x%08x\n", fhdrp->fh_offset, fhdrp->fh_flags, bstatp->bs_ino, bstatp->bs_mode ); if ( fhcs ) { if ( ! ( fhdrp->fh_flags & FILEHDR_FLAGS_CHECKSUM )) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "corrupt file header\n") ); return RV_CORRUPT; } if ( !is_checksum_valid( fhdrp, FILEHDR_SZ )) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "bad file header checksum\n") ); return RV_CORRUPT; } } return RV_OK; } /* ARGSUSED */ static rv_t read_extenthdr( drive_t *drivep, extenthdr_t *ehdrp, bool_t ehcs ) { drive_ops_t *dop = drivep->d_opsp; /* REFERENCED */ int nread; int rval; extenthdr_t tmpeh; nread = read_buf( ( char * )&tmpeh, sizeof( *ehdrp ), ( void * )drivep, ( rfp_t )dop->do_read, ( rrbfp_t )dop->do_return_read_buf, &rval ); xlate_extenthdr(&tmpeh, ehdrp, 1); switch( rval ) { case 0: break; case DRIVE_ERROR_EOD: case DRIVE_ERROR_EOF: case DRIVE_ERROR_EOM: case DRIVE_ERROR_MEDIA: return RV_EOD; case DRIVE_ERROR_CORRUPTION: return RV_CORRUPT; case DRIVE_ERROR_DEVICE: return RV_DRIVE; case DRIVE_ERROR_CORE: default: return RV_CORE; } assert( ( size_t )nread == sizeof( *ehdrp )); mlog( MLOG_NITTY, "read extent hdr size %lld offset %lld type %d flags %08x\n", ehdrp->eh_sz, ehdrp->eh_offset, ehdrp->eh_type, ehdrp->eh_flags ); if ( ehcs ) { if ( ! ( ehdrp->eh_flags & EXTENTHDR_FLAGS_CHECKSUM )) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "corrupt extent header\n") ); return RV_CORRUPT; } if ( !is_checksum_valid( ehdrp, EXTENTHDR_SZ )) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "bad extent header checksum\n") ); return RV_CORRUPT; } } return RV_OK; } /* ARGSUSED */ static rv_t read_dirent( drive_t *drivep, direnthdr_t *dhdrp, size_t direntbufsz, bool_t dhcs ) { global_hdr_t *grhdrp = drivep->d_greadhdrp; drive_ops_t *dop = drivep->d_opsp; /* REFERENCED */ int nread; int rval; direnthdr_t tmpdh; char *namep; // beginning of name following the direnthdr_t assert( sizeof( direnthdr_t ) == DIRENTHDR_SZ ); assert( sizeof( direnthdr_v1_t ) == DIRENTHDR_SZ ); /* read the head of the dirent */ nread = read_buf( ( char * )&tmpdh, DIRENTHDR_SZ, ( void * )drivep, ( rfp_t )dop->do_read, ( rrbfp_t ) dop->do_return_read_buf, &rval ); switch( rval ) { case 0: break; case DRIVE_ERROR_EOD: case DRIVE_ERROR_EOF: case DRIVE_ERROR_EOM: case DRIVE_ERROR_MEDIA: return RV_EOD; case DRIVE_ERROR_CORRUPTION: return RV_CORRUPT; case DRIVE_ERROR_DEVICE: return RV_DRIVE; case DRIVE_ERROR_CORE: default: return RV_CORE; } assert( ( size_t )nread == DIRENTHDR_SZ ); if ( grhdrp->gh_version >= GLOBAL_HDR_VERSION_3 ) { xlate_direnthdr(&tmpdh, dhdrp, 1); namep = dhdrp->dh_name + sizeof(dhdrp->dh_name); if ( dhcs && !is_checksum_valid( dhdrp, DIRENTHDR_SZ )) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "bad directory entry header checksum\n") ); return RV_CORRUPT; } } else { direnthdr_v1_t dhdr_v1; xlate_direnthdr_v1((direnthdr_v1_t *)&tmpdh, &dhdr_v1, 1); dhdrp->dh_ino = dhdr_v1.dh_ino; dhdrp->dh_gen = BIGGEN2GEN(dhdr_v1.dh_gen); dhdrp->dh_checksum = dhdr_v1.dh_checksum; dhdrp->dh_sz = dhdr_v1.dh_sz; memcpy(dhdrp->dh_name, dhdr_v1.dh_name, sizeof(dhdr_v1.dh_name)); namep = dhdrp->dh_name + sizeof(dhdr_v1.dh_name); if ( dhcs && !is_checksum_valid( &dhdr_v1, DIRENTHDR_SZ )) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "bad directory entry header checksum\n") ); return RV_CORRUPT; } } mlog( MLOG_NITTY, "read dirent hdr ino %llu gen %u size %u\n", dhdrp->dh_ino, ( size_t )dhdrp->dh_gen, ( size_t )dhdrp->dh_sz ); if ( dhdrp->dh_sz == 0 ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "corrupt directory entry header\n") ); return RV_CORRUPT; } /* if null, return */ if ( dhdrp->dh_ino == 0 ) { assert( ( size_t )dhdrp->dh_sz == sizeof( direnthdr_t )); return RV_OK; } /* read the remainder of the dirent. */ assert( ( size_t )dhdrp->dh_sz <= direntbufsz ); assert( ( size_t )dhdrp->dh_sz >= sizeof( direnthdr_t )); assert( ! ( ( size_t )dhdrp->dh_sz & ( DIRENTHDR_ALIGN - 1 ))); if ( ( size_t )dhdrp->dh_sz > sizeof( direnthdr_t )) { size_t remsz = ( size_t )dhdrp->dh_sz - sizeof( direnthdr_t ); nread = read_buf( namep, remsz, ( void * )drivep, ( rfp_t )dop->do_read, ( rrbfp_t ) dop->do_return_read_buf, &rval ); switch( rval ) { case 0: break; case DRIVE_ERROR_EOD: case DRIVE_ERROR_EOF: case DRIVE_ERROR_EOM: case DRIVE_ERROR_MEDIA: return RV_EOD; case DRIVE_ERROR_CORRUPTION: return RV_CORRUPT; case DRIVE_ERROR_DEVICE: return RV_DRIVE; case DRIVE_ERROR_CORE: default: return RV_CORE; } assert( ( size_t ) nread == remsz ); } return RV_OK; } /* ARGSUSED */ static rv_t read_extattrhdr( drive_t *drivep, extattrhdr_t *ahdrp, bool_t ahcs ) { drive_ops_t *dop = drivep->d_opsp; /* REFERENCED */ int nread; int rval; extattrhdr_t tmpah; nread = read_buf( ( char * )&tmpah, sizeof( *ahdrp ), ( void * )drivep, ( rfp_t )dop->do_read, ( rrbfp_t )dop->do_return_read_buf, &rval ); xlate_extattrhdr(&tmpah, ahdrp, 1); switch( rval ) { case 0: break; case DRIVE_ERROR_EOD: case DRIVE_ERROR_EOF: case DRIVE_ERROR_EOM: case DRIVE_ERROR_MEDIA: return RV_EOD; case DRIVE_ERROR_CORRUPTION: return RV_CORRUPT; case DRIVE_ERROR_DEVICE: return RV_DRIVE; case DRIVE_ERROR_CORE: default: return RV_CORE; } assert( ( size_t )nread == sizeof( *ahdrp )); mlog( MLOG_NITTY, "read extattr hdr sz %u valoff %u flags 0x%x valsz %u cs 0x%x\n", ahdrp->ah_sz, ( uint )ahdrp->ah_valoff, ( uint )ahdrp->ah_flags, ahdrp->ah_valsz, ahdrp->ah_checksum ); if ( ahcs ) { if ( ahdrp->ah_flags & EXTATTRHDR_FLAGS_CHECKSUM ) { if ( !is_checksum_valid( ahdrp, EXTATTRHDR_SZ )) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "bad extattr header checksum\n") ); return RV_CORRUPT; } } else if ( ahdrp->ah_flags & EXTATTRHDR_FLAGS_OLD_CHECKSUM ) { /* possibly a corrupt header, but most likely an old * header, which cannot be verified due to a bug in how * its checksum was calculated. */ static bool_t warned = BOOL_FALSE; if ( !warned ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "ignoring old-style extattr " "header checksums\n") ); warned = BOOL_TRUE; } } else { mlog( MLOG_NORMAL | MLOG_WARNING, _( "corrupt extattr header\n") ); return RV_CORRUPT; } } return RV_OK; } static rv_t discard_padding( size_t sz, drive_t *drivep ) { drive_ops_t *dop = drivep->d_opsp; /* REFERENCED */ int nread; int rval; nread = read_buf( 0, sz, ( void * )drivep, ( rfp_t )dop->do_read, ( rrbfp_t )dop->do_return_read_buf, &rval ); switch( rval ) { case 0: assert( ( size_t )nread == sz ); return RV_OK; case DRIVE_ERROR_EOF: case DRIVE_ERROR_EOD: case DRIVE_ERROR_EOM: case DRIVE_ERROR_MEDIA: return RV_EOD; case DRIVE_ERROR_CORRUPTION: return RV_CORRUPT; case DRIVE_ERROR_DEVICE: return RV_DRIVE; case DRIVE_ERROR_CORE: default: return RV_CORE; } } static rv_t restore_extent( filehdr_t *fhdrp, extenthdr_t *ehdrp, int fd, char *path, drive_t *drivep, off64_t *bytesreadp ) { bstat_t *bstatp = &fhdrp->fh_stat; drive_ops_t *dop = drivep->d_opsp; off64_t off = ehdrp->eh_offset; off64_t sz = ehdrp->eh_sz; off64_t new_off; struct dioattr da; bool_t isrealtime = BOOL_FALSE; *bytesreadp = 0; if ( fd != -1 ) { assert( path ); /* seek to the beginning of the extent. * must be on a basic fs blksz boundary. */ assert( ( off & ( off64_t )( BBSIZE - 1 )) == 0 ); new_off = lseek64( fd, off, SEEK_SET ); if ( new_off < 0 ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "attempt to seek %s to %lld failed: %s: " "not restoring extent off %lld sz %lld\n"), path, off, strerror( errno ), off, sz ); fd = -1; new_off = off; } assert( new_off == off ); } if ( (fd != -1) && (bstatp->bs_xflags & XFS_XFLAG_REALTIME) ) { if ( (ioctl(fd, XFS_IOC_DIOINFO, &da) < 0) ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "dioinfo %s failed: " "%s: discarding ino %llu\n"), path, strerror( errno ), fhdrp->fh_stat.bs_ino ); fd = -1; } else isrealtime = BOOL_TRUE; } /* move from media to fs. */ while ( sz ) { char *bufp; size_t req_bufsz; /* requested bufsz */ size_t sup_bufsz; /* supplied bufsz */ int nwritten; int rval; size_t ntowrite; req_bufsz = ( size_t )min( ( off64_t )INTGENMAX, sz ); bufp = ( * dop->do_read )(drivep, req_bufsz, &sup_bufsz, &rval); if ( rval ) { rv_t rv; char *reasonstr; switch( rval ) { case DRIVE_ERROR_EOF: rv = RV_EOD; reasonstr = _("end of media file"); break; case DRIVE_ERROR_EOD: rv = RV_EOD; reasonstr = _("end of recorded data"); break; case DRIVE_ERROR_EOM: rv = RV_EOD; reasonstr = _("end of media"); break; case DRIVE_ERROR_MEDIA: rv = RV_EOD; reasonstr = _("media error or no media"); break; case DRIVE_ERROR_CORRUPTION: rv = RV_CORRUPT; reasonstr = _("end of media file"); break; case DRIVE_ERROR_DEVICE: rv = RV_DRIVE; reasonstr = _("end of media file"); break; case DRIVE_ERROR_CORE: default: rv = RV_CORE; reasonstr = _("dumping core"); break; } mlog( MLOG_NORMAL, _( "attempt to read %u bytes failed: %s\n"), req_bufsz, reasonstr ); return rv; } if ( off >= bstatp->bs_size ) { assert( off == bstatp->bs_size ); ntowrite = 0; } else if ((off64_t)sup_bufsz > bstatp->bs_size - off ) { ntowrite = ( size_t )( bstatp->bs_size - off ); } else { ntowrite = sup_bufsz; } assert( ntowrite <= ( size_t )INTGENMAX ); if ( ntowrite > 0 ) { *bytesreadp += ( off64_t )ntowrite; if ( fd != -1 ) { size_t tries; size_t remaining; int rval; off64_t tmp_off; rval = 0; /* for lint */ for ( nwritten = 0, tries = 0, remaining = ntowrite, tmp_off = off ; nwritten < ( int )ntowrite && tries < WRITE_TRIES_MAX ; nwritten += rval, tries++, remaining -= ( size_t )rval, tmp_off += ( off64_t )rval ) { int rttrunc = 0; int trycnt = 0; assert( remaining <= ( size_t )INTGENMAX ); /* * Realtime files must be written * to the end of the block even if * it has been truncated back. */ if ( isrealtime && (remaining % da.d_miniosz != 0 || remaining < da.d_miniosz) ) { /* * Since the ring and static * buffers from the different * drives are always large, we * just need to write to the * end of the next block * boundry and truncate. */ rttrunc = remaining; remaining += da.d_miniosz - (remaining % da.d_miniosz); } /* * Do the write. Due to delayed allocation * it's possible to receive false ENOSPC * errors when the filesystem is nearly * full. XFS kernel code tries to avoid * this, but cannot always do so. Catch * ENOSPC and mimic the kernel behavior * by trying to flush the current file * first, then trying a system wide sync * if ENOSPC still occurs. */ for (trycnt = 0; trycnt < 3; trycnt++) { rval = write( fd, bufp, remaining ); if (rval >= 0 || errno != ENOSPC) break; ( trycnt == 0 ) ? fdatasync(fd) : sync(); } if ( rval < 0 ) { nwritten = rval; break; } assert( ( size_t )rval <= remaining ); if ( rval < remaining ) { mlog( MLOG_NORMAL | MLOG_WARNING, _("attempt to " "write %u bytes to %s at " "offset %lld failed: " "only %d bytes written\n"), remaining, path, tmp_off, rval ); } if (rttrunc) { /* truncate and re-set rval */ if (rval == remaining) rval = rttrunc; ftruncate(fd, bstatp->bs_size); } } } else { nwritten = ( int )ntowrite; } } else { nwritten = 0; } ( * dop->do_return_read_buf )( drivep, bufp, sup_bufsz ); if ( ( size_t )nwritten != ntowrite ) { if ( nwritten < 0 ) { mlog( MLOG_NORMAL, _( "attempt to write %u bytes to %s " "at offset %lld failed: %s\n"), ntowrite, path, off, strerror( errno )); } else { assert( ( size_t )nwritten < ntowrite ); mlog( MLOG_NORMAL, _( "attempt to write %u bytes to %s at " "offset %lld failed: only %d bytes " "written\n"), ntowrite, path, off, nwritten ); } /* stop attempting to write, but complete reads */ fd = -1; assert( ntowrite <= ( size_t )INTGENMAX ); nwritten = ( int )ntowrite; } sz -= ( off64_t )sup_bufsz; off += ( off64_t )nwritten; } return RV_OK; } static char *extattrbufp = 0; /* ptr to start of all the extattr buffers */ static size_t extattrbufsz = 0; /* size of each extattr buffer */ static bool_t extattr_init( size_t drivecnt ) { assert( ! extattrbufp ); extattrbufsz = EXTATTRHDR_SZ /* dump hdr */ + NAME_MAX /* attribute name */ + 1 /* NULL term. of name */ + ATTR_MAX_VALUELEN; /* attribute value */ extattrbufsz = roundup(extattrbufsz, EXTATTRHDR_ALIGN); extattrbufp = memalign( EXTATTRHDR_ALIGN, extattrbufsz * drivecnt ); if (extattrbufp == NULL) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "Failed to allocate extended attribute buffer\n") ); return BOOL_FALSE; } return BOOL_TRUE; } static char * get_extattrbuf( ix_t which ) { return extattrbufp + (extattrbufsz * which); } struct extattr_cb_ctx { extattrhdr_t *ecb_ahdrp; }; typedef struct extattr_cb_ctx extattr_cb_ctx_t; static rv_t restore_extattr( drive_t *drivep, filehdr_t *fhdrp, char *path, bool_t ahcs, bool_t isdirpr, bool_t onlydoreadpr, dah_t dah ) { drive_ops_t *dop = drivep->d_opsp; extattrhdr_t *ahdrp = ( extattrhdr_t * )get_extattrbuf( drivep->d_index ); stream_context_t *strctxp = (stream_context_t *)drivep->d_strmcontextp; bstat_t *bstatp = &fhdrp->fh_stat; bool_t isfilerestored = BOOL_FALSE; assert( extattrbufp ); if ( ! isdirpr ) isfilerestored = partial_check(bstatp->bs_ino, bstatp->bs_size); /* peel off extattrs until null hdr hit */ for ( ; ; ) { size_t recsz; /* REFERENCED */ int nread; int rval; rv_t rv; rv = read_extattrhdr( drivep, ahdrp, ahcs ); if ( rv != RV_OK ) { return rv; } if ( ahdrp->ah_flags & EXTATTRHDR_FLAGS_NULL ) { return RV_OK; } recsz = ( size_t )ahdrp->ah_sz; assert( recsz <= extattrbufsz ); assert( recsz >= EXTATTRHDR_SZ ); nread = read_buf( ( char * )&ahdrp[ 1 ], recsz - EXTATTRHDR_SZ, ( void * )drivep, ( rfp_t )dop->do_read, ( rrbfp_t )dop->do_return_read_buf, &rval ); switch( rval ) { case 0: break; case DRIVE_ERROR_EOD: case DRIVE_ERROR_EOF: case DRIVE_ERROR_EOM: case DRIVE_ERROR_MEDIA: return RV_EOD; case DRIVE_ERROR_CORRUPTION: return RV_CORRUPT; case DRIVE_ERROR_DEVICE: return RV_DRIVE; case DRIVE_ERROR_CORE: default: return RV_CORE; } assert( nread == ( int )( recsz - EXTATTRHDR_SZ )); if ( ! persp->a.restoreextattrpr && ! persp->a.restoredmpr ) { continue; } if ( onlydoreadpr || tranp->t_toconlypr ) continue; /* NOTE: In the cases below, if we get errors then we issue warnings * but we do not stop the restoration. * We can still restore the file possibly without the * extended attributes. */ if ( isdirpr ) { assert( ! path ); if ( dah != DAH_NULL ) { dirattr_addextattr( dah, ahdrp ); } } else if ( isfilerestored && path[0] != '\0' ) { setextattr( path, ahdrp ); if ( persp->a.dstdirisxfspr && persp->a.restoredmpr ) { int flag = 0; char *attrname = (char *)&ahdrp[1]; if (ahdrp->ah_flags & EXTATTRHDR_FLAGS_ROOT) flag = ATTR_ROOT; else if (ahdrp->ah_flags & EXTATTRHDR_FLAGS_SECURE) flag = ATTR_SECURE; HsmRestoreAttribute( flag, attrname, &strctxp->sc_hsmflags ); } } } /* NOTREACHED */ } static bool_t restore_dir_extattr_cb( char *path, dah_t dah ) { /* * directory extattr's are built during the directory phase * by 1 thread so we only need one extattr buffer * -> we pick the 0th one */ extattrhdr_t *ahdrp = ( extattrhdr_t * )get_extattrbuf( 0 ); bool_t ok; /* ask the dirattr abstraction to call me back for each * extended dirattr associated with this dah. */ ok = dirattr_cb_extattr( dah, restore_dir_extattr_cb_cb, ahdrp, ( void * )path ); return ok; } static bool_t restore_dir_extattr_cb_cb( extattrhdr_t *ahdrp, void *ctxp ) { char *path = ( char * )ctxp; setextattr( path, ahdrp ); return BOOL_TRUE; } static void setextattr( char *path, extattrhdr_t *ahdrp ) { static char dmiattr[] = "SGI_DMI_"; bool_t isrootpr = ahdrp->ah_flags & EXTATTRHDR_FLAGS_ROOT; bool_t issecurepr = ahdrp->ah_flags & EXTATTRHDR_FLAGS_SECURE; bool_t isdmpr; int attr_namespace; int rval; isdmpr = ( isrootpr && !strncmp((char *)(&ahdrp[1]), dmiattr, sizeof(dmiattr)-1) ); /* If restoreextattrpr not set, then we are here because -D was * specified. So return unless it looks like a root DMAPI attribute. */ if ( !persp->a.restoreextattrpr && !isdmpr ) return; if ( isrootpr ) { attr_namespace = ATTR_ROOT; } else if ( issecurepr ) { attr_namespace = ATTR_SECURE; } else { attr_namespace = 0; } rval = attr_set( path, ( char * )( &ahdrp[ 1 ] ), ( ( char * )ahdrp ) + ( u_long_t )ahdrp->ah_valoff, ( int )ahdrp->ah_valsz, attr_namespace | ATTR_DONTFOLLOW ); if ( rval ) { char *namespace; if ( isrootpr ) { namespace = _("root"); } else if ( issecurepr ) { namespace = _("secure"); } else { namespace = _("non-root"); } mlog( MLOG_VERBOSE | MLOG_WARNING, _( "unable to set %s extended attribute for %s: " "%s (%d)\n"), namespace, path, strerror( errno ), errno ); } } #ifdef DEBUGPARTIALS /* * Debug code to view the partials in the partial register */ void dump_partials(void) { partial_rest_t *isptr = NULL; bytespan_t *bsptr = NULL; int i; pi_lock(); printf("\npartial_reg: count=%d\n", (int)persp->a.parrestcnt); if (persp->a.parrestcnt > 0) { for (i=0; i < partialmax; i++ ) { if (persp->a.parrest[i].is_ino > 0) { int j; isptr = &persp->a.parrest[i]; printf("\tino=%llu ", (unsigned long long)isptr->is_ino); for (j=0, bsptr=isptr->is_bs; j < drivecnt; j++, bsptr++) { if (bsptr->endoffset > 0) { printf("%d:%lld-%lld ", j, (long long)bsptr->offset, (long long)bsptr->endoffset); } } printf( "\n"); } } } printf("\n"); pi_unlock(); } /* There can only be at most 2 partials for a given stream. * An unfinished one from a split and the current one from * a multiple group extent or another split. * If there are more than 2, then there is an internal error. */ void check_valid_partials(void) { int *num_partials; /* array for sum of partials for a given drive */ partial_rest_t *isptr = NULL; bytespan_t *bsptr = NULL; int i; /* zero the sums for each stream */ num_partials = calloc(drivecnt, sizeof(int)); if (!num_partials) { perror("num_partials array allocation"); return; } pi_lock(); if (persp->a.parrestcnt > 0) { for (i=0; i < partialmax; i++ ) { if (persp->a.parrest[i].is_ino > 0) { int j; isptr = &persp->a.parrest[i]; for (j=0, bsptr=isptr->is_bs; j < drivecnt; j++, bsptr++) { if (bsptr->endoffset > 0) { num_partials[j]++; if (num_partials[j] > 2) { pi_unlock(); mlog( MLOG_NORMAL | MLOG_WARNING, "partial_reg: Too many partials (>2) for drive: %d\n", j); dump_partials(); exit(EXIT_ERROR); } } } } } } pi_unlock(); free(num_partials); } #endif /* partial_reg - Registers files that are only partially restored by * a dump stream into the persistent state. * * This is done because DMAPI extended attributes must not be set until * the entire file has been restored in order to co-ordinate with the * Data Migration Facility (DMF) daemons. Since extended attributes are * recorded with each extent group in the dump, this registry is used to * make sure only the final dump stream applies the extended attributes. * * Likewise, certain extended inode flags (e.g. XFS_XFLAG_IMMUTABLE) * should only be set after all data for a file has been restored. */ static void partial_reg( ix_t d_index, xfs_ino_t ino, off64_t fsize, off64_t offset, off64_t sz) { off64_t endoffset; partial_rest_t *isptr = NULL; bytespan_t *bsptr = NULL; int i; mlog(MLOG_NITTY, "partial_reg: d_index = %d, ino = %llu, " "fsize = %lld, offset = %lld, sz = %lld\n", d_index, ino, fsize, offset, sz); endoffset = offset + sz; if ( partialmax == 0 ) return; pi_lock(); /* Search for a matching inode. Gaps can exist so we must search * all entries. */ for (i=0; i < partialmax; i++ ) { if (persp->a.parrest[i].is_ino == ino) { isptr = &persp->a.parrest[i]; break; } } /* If not found, find a free one, fill it in and return */ if ( ! isptr ) { mlog(MLOG_NITTY | MLOG_NOLOCK, "partial_reg: no entry found for %llu\n", ino); /* find a free one */ for (i=0; i < partialmax; i++ ) { if (persp->a.parrest[i].is_ino == 0) { int j; isptr = &persp->a.parrest[i]; isptr->is_ino = ino; persp->a.parrestcnt++; /* Clear all endoffsets (this value is * used to decide if an entry is used or * not */ for (j=0, bsptr=isptr->is_bs; j < drivecnt; j++, bsptr++) { bsptr->endoffset = 0; } goto found; } } /* Should never get here. */ pi_unlock(); mlog( MLOG_NORMAL | MLOG_WARNING, _( "partial_reg: Out of records. Extend attrs applied early.\n")); #ifdef DEBUGPARTIALS dump_partials(); #endif return; } found: /* Update this drive's entry */ bsptr = &isptr->is_bs[d_index]; if (bsptr->endoffset == 0) { /* no existing entry for this drive, fill in the values */ bsptr->offset = offset; bsptr->endoffset = endoffset; mlog(MLOG_NITTY | MLOG_NOLOCK, "partial_reg: update entry [%d]: " "\n", d_index, offset, endoffset); } else { bool_t ret; /* entry exists for this drive, just extend the endoffset, the * records will be sequential for any given drive. */ bsptr->endoffset = endoffset; ret = partial_check2(isptr, fsize); mlog(MLOG_NITTY | MLOG_NOLOCK, "partial_reg: extend entry [%d]: \n", d_index, endoffset); mlog(MLOG_NITTY | MLOG_NOLOCK, "partial_reg: partial_check returns: %d\n", ret); } pi_unlock(); #ifdef DEBUGPARTIALS check_valid_partials(); dump_partials(); #endif } /* Checks the registry of files that are only partially restored by * any given dump stream to see if the remainder of the file has * been restored by another dump stream. */ static bool_t partial_check (xfs_ino_t ino, off64_t fsize) { partial_rest_t *isptr = NULL; bool_t ret; int i; if ( partialmax == 0 ) return BOOL_TRUE; pi_lock(); /* Check if no files are listed in the sync area */ if (persp->a.parrestcnt == 0) { pi_unlock(); return BOOL_TRUE; } /* Search for the inode. Gaps can exist so we must search * all entries. */ for (i=0; i < partialmax; i++ ) { if (persp->a.parrest[i].is_ino == ino) { isptr = &persp->a.parrest[i]; break; } } /* If not found, return okay */ if ( ! isptr ) { pi_unlock(); return BOOL_TRUE; } ret = partial_check2(isptr, fsize); pi_unlock(); #ifdef DEBUGPARTIALS check_valid_partials(); dump_partials(); #endif return ret; } /* * Checks the given parrest entry to see if the file has * been completely restored. * Always invoked with the persistent inventory locked (pi_lock) */ static bool_t partial_check2(partial_rest_t *isptr, off64_t fsize) { bytespan_t *bsptr = NULL; off64_t curoffset = 0; int i; gapsearch: /* Search the entire set of bytespan records to see if the next * span has been restored. Bytespans are not necessarily in order * so the search is repeated from the start each time. */ for (i=0, bsptr=isptr->is_bs; i < drivecnt; i++, bsptr++) { if (bsptr->endoffset > 0 && bsptr->offset <= curoffset && bsptr->endoffset > curoffset) { curoffset = bsptr->endoffset; goto gapsearch; } } /* Check if all bytes are accounted for. */ if (curoffset >= fsize) { isptr->is_ino = 0; /* clear the entry */ persp->a.parrestcnt--; return BOOL_TRUE; } else { return BOOL_FALSE; } } static char * ehdr_typestr( int32_t type ) { switch ( type ) { case EXTENTHDR_TYPE_LAST: return "LAST"; case EXTENTHDR_TYPE_ALIGN: return "ALIGN"; case EXTENTHDR_TYPE_DATA: return "DATA"; case EXTENTHDR_TYPE_HOLE: return "HOLE"; default: return "?"; } } /* ARGSUSED */ bool_t content_overwrite_ok( char *path, int32_t ctime, int32_t mtime, char **reasonstrp, bool_t *exists ) { struct stat statbuf; *exists = BOOL_TRUE; /* if file doesn't exist, allow */ if ( lstat( path, &statbuf )) { *reasonstrp = 0; if ( errno == ENOENT ) { *exists = BOOL_FALSE; } return BOOL_TRUE; } /* if overwrites absolutely inhibited, disallow */ if ( persp->a.existpr ) { *reasonstrp = _("overwrites inhibited"); return BOOL_FALSE; } /* if newer time specified, compare */ if ( persp->a.newerpr ) { if ( ( time32_t )ctime < persp->a.newertime ) { *reasonstrp = _("too old"); return BOOL_FALSE; } } /* don't overwrite changed files */ if ( persp->a.changepr ) { if ( statbuf.st_ctime >= ( time32_t )ctime ) { *reasonstrp = _("existing version is newer"); return BOOL_FALSE; } } *reasonstrp = 0; return BOOL_TRUE; } static void set_mcflag( ix_t thrdix ) { lock( ); mcflag[ thrdix ] = BOOL_TRUE; content_media_change_needed = BOOL_TRUE; unlock( ); } static void clr_mcflag( ix_t thrdix ) { lock( ); mcflag[ thrdix ] = BOOL_FALSE; for ( thrdix = 0 ; thrdix < drivecnt ; thrdix++ ) { if ( mcflag[ thrdix ] ) { unlock( ); return; } } content_media_change_needed = BOOL_FALSE; unlock( ); } /* debug functions ***********************************************************/ static void pi_show( char *introstring ) { char strbuf[ 100 ]; /* REFERENCED */ int strbuflen; fold_t fold; if ( mlog_level_ss[ MLOG_SS_MEDIA ] < MLOG_NITTY + 1 ) { return; } mlog_lock( ); strbuflen = sprintf( strbuf, "persistent inventory media file tree%s", introstring ); assert( ( size_t )strbuflen < sizeof( strbuf )); fold_init( fold, strbuf, ':' ); mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK, "\n%s\n\n", fold ); pi_show_nomloglock( ); fold_init( fold, "end persistent inventory display", '.' ); mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK, "\n%s\n\n", fold ); mlog_unlock( ); } static void pi_show_nomloglock( void ) { dh_t strmh; int strmix; /* no point in proceeding if pi not begun */ if ( persp->s.strmheadh == DH_NULL ) { mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK | MLOG_MEDIA, _( "session inventory unknown\n") ); return; } mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK | MLOG_MEDIA, _( "session inventory display\n") ); /* iterate over all streams */ for ( strmh = persp->s.strmheadh, strmix = 0 ; strmh != DH_NULL ; strmh = DH2S( strmh )->s_nexth, strmix++ ) { dh_t objh; int objix; mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK | MLOG_MEDIA, _("\nmedia stream %u:\n"), strmix ); if ( DH2S( strmh )->s_cldh == DH_NULL ) { mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK | MLOG_MEDIA, _("\n media objects not yet identified\n") ); continue; } /* iterate over all objects */ for ( objh = DH2S( strmh )->s_cldh, objix = 0 ; objh != DH_NULL ; objh = DH2O( objh )->o_nexth, objix++ ) { dh_t fileh; ix_t fileix; mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK | MLOG_MEDIA, _("\n media object %u:\n\n"), objix ); if ( DH2O( objh )->o_idlabvalpr ) { if ( strlen( DH2O( objh )->o_lab )) { mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK | MLOG_MEDIA, _(" label: ") ); mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK | MLOG_MEDIA, "\"%s\"\n", DH2O( objh )->o_lab ); } else { mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK | MLOG_MEDIA, _(" label is blank\n") ); } if ( ! uuid_is_null( DH2O( objh )->o_id)) { char media_string_uuid[UUID_STR_LEN + 1]; uuid_unparse( DH2O( objh )->o_id, media_string_uuid); mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK | MLOG_MEDIA, _(" id: %s\n"), media_string_uuid ); } } else { mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK | MLOG_MEDIA, _(" label not identified\n") ); } if ( DH2O( objh )->o_fmfmixvalpr ) { mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK | MLOG_MEDIA, _(" index within object " "of first media file: %u\n"), DH2O( objh )->o_fmfmix ); } if ( DH2O( objh )->o_fmfsixvalpr ) { mlog( MLOG_DEBUG | MLOG_BARE | MLOG_NOLOCK | MLOG_MEDIA, _(" index within stream " "of first media file: %u\n"), DH2O( objh )->o_fmfsix ); } if ( DH2O( objh )->o_indrivepr ) { if ( drivecnt > 1 ) { mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK | MLOG_MEDIA, _(" now in drive %u\n"), DH2O( objh )->o_indriveix ); } else { mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK | MLOG_MEDIA, _(" now in drive\n") ); } } if ( DH2O( objh )->o_cldh == DH_NULL ) { mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK | MLOG_MEDIA, _(" media files not yet " "identified\n") ); continue; } /* iterate over all files */ for ( fileh = DH2O( objh )->o_cldh, fileix = 0 ; fileh != DH_NULL ; fileh = DH2F( fileh )->f_nexth, fileix++ ) { mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK | MLOG_MEDIA, _("\n media file %u"), fileix ); if ( DH2O( objh )->o_fmfmixvalpr ) { mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK | MLOG_MEDIA, " (%u):\n", DH2O( objh )->o_fmfmix + fileix ); } else { mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK | MLOG_MEDIA, ":\n" ); } if ( DH2F( fileh )->f_szvalpr ) { mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK | MLOG_MEDIA, _(" size: " "%lld bytes\n"), DH2F( fileh )->f_sz ); } if ( DH2F( fileh )->f_dirtriedpr ) { mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK | MLOG_MEDIA, _(" used for directory " "restoral\n") ); } if ( DH2F( fileh )->f_valpr ) { mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK | MLOG_MEDIA, _(" first extent contained: " "ino %llu off %lld\n"), DH2F( fileh )->f_firstegrp.eg_ino, DH2F( fileh )->f_firstegrp.eg_off ); mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK | MLOG_MEDIA, _(" next extent to restore: " "ino %llu off %lld\n"), DH2F( fileh )->f_curegrp.eg_ino, DH2F( fileh )->f_curegrp.eg_off ); mlog( MLOG_DEBUG | MLOG_BARE | MLOG_NOLOCK | MLOG_MEDIA, _(" rollback mark %lld\n"), DH2F( fileh )->f_curmark ); } if ( DH2F( fileh )->f_nondirskippr ) { mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK | MLOG_MEDIA, _(" contains no selected " "non-directories\n") ); } if ( DH2F( fileh )->f_nondirdonepr ) { mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK | MLOG_MEDIA, _(" non-directories done\n") ); } if ( DH2F( fileh )->f_flags & PF_INV ) { mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK | MLOG_MEDIA, _(" contains session " "inventory\n") ); } if ( DH2F( fileh )->f_flags & PF_TERM ) { mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK | MLOG_MEDIA, _(" is stream terminator\n") ); } if ( DH2F( fileh )->f_underheadpr ) { mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK | MLOG_MEDIA, _(" now reading\n") ); } } if ( ! DH2O( objh )->o_lmfknwnpr ) { mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK | MLOG_MEDIA, _("\n may be additional " "unidentified media files\n") ); } } if ( ! DH2S( strmh )->s_lastobjknwnpr ) { mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK | MLOG_MEDIA, _("\n may be " "additional unidentified media objects\n\n") ); } } } static int egrpcmp( egrp_t *egrpap, egrp_t *egrpbp ) { if ( egrpap->eg_ino < egrpbp->eg_ino ) { return -1; } else if ( egrpap->eg_ino > egrpbp->eg_ino ) { return 1; } else if ( egrpap->eg_off < egrpbp->eg_off ) { return -1; } else if ( egrpap->eg_off > egrpbp->eg_off ) { return 1; } else { return 0; } } static void display_dump_label( bool_t lockpr, int mllevel, char *introstr, global_hdr_t *grhdrp, media_hdr_t *mrhdrp, content_hdr_t *crhdrp, content_inode_hdr_t *scrhdrp ) { char dateline[ 28 ]; char level_string[ 2 ]; char dump_string_uuid[UUID_STR_LEN + 1]; char media_string_uuid[UUID_STR_LEN + 1]; char fs_string_uuid[UUID_STR_LEN + 1]; assert( scrhdrp->cih_level >= 0 ); assert( scrhdrp->cih_level < 10 ); level_string[ 0 ] = ( char )( '0' + ( u_char_t )scrhdrp->cih_level ); level_string[ 1 ] = 0; uuid_unparse(grhdrp->gh_dumpid, dump_string_uuid); uuid_unparse(mrhdrp->mh_mediaid, media_string_uuid); uuid_unparse(crhdrp->ch_fsid, fs_string_uuid); if ( lockpr ) { mlog_lock( ); } mlog( mllevel | MLOG_NOLOCK, "%s", introstr ); mlog( mllevel | MLOG_NOLOCK, _("hostname: %s\n"), grhdrp->gh_hostname ); mlog( mllevel | MLOG_NOLOCK, _("mount point: %s\n"), crhdrp->ch_mntpnt ); mlog( mllevel | MLOG_NOLOCK, _("volume: %s\n"), crhdrp->ch_fsdevice ); mlog( mllevel | MLOG_NOLOCK, _("session time: %s"), ctime32_r( &grhdrp->gh_timestamp, dateline )); mlog( mllevel | MLOG_NOLOCK, _("level: %s%s\n"), level_string, ( scrhdrp->cih_dumpattr & CIH_DUMPATTR_RESUME ) ? _(" resumed") : "" ); mlog( mllevel | MLOG_NOLOCK, _("session label: ") ); mlog( mllevel | MLOG_NOLOCK | MLOG_BARE, "\"%s\"\n", grhdrp->gh_dumplabel ); mlog( mllevel | MLOG_NOLOCK, _("media label: ") ); mlog( mllevel | MLOG_NOLOCK | MLOG_BARE, "\"%s\"\n", mrhdrp->mh_medialabel ); mlog( mllevel | MLOG_NOLOCK, _("file system id: %s\n"), fs_string_uuid ); mlog( mllevel | MLOG_NOLOCK, _("session id: %s\n"), dump_string_uuid ); mlog( mllevel | MLOG_NOLOCK, _("media id: %s\n"), media_string_uuid ); if ( lockpr ) { mlog_unlock( ); } } static void display_needed_objects( purp_t purp, bag_t *bagp, bool_t knownholespr, bool_t maybeholespr ) { if ( bagp ) { ix_t ix; bagiter_t iter; bagobj_t *bagobjp; if ( purp == PURP_DIR ) { mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK, _( "the following media objects " "contain media files not yet tried " "for directory hierarchy restoral:\n") ); } if ( purp == PURP_NONDIR ) { mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK, _( "the following media objects " "are needed:\n") ); } bagiter_init( bagp, &iter ); bagobjp = 0; /* keep lint happy */ ix = 0; while ( bagiter_next( &iter, ( void ** )&bagobjp )) { char uuidstr[UUID_STR_LEN + 1]; uuid_unparse( bagobjp->id, uuidstr); mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK, "\n" ); mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK, _("%2u. label: "), ix ); mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK, "\"%s\"\n", bagobjp->label ); mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK, _(" id: ") ); mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK, "\"%s\"\n", uuidstr ); if ( bagobjp->indrivepr ) { if ( drivecnt > 1 ) { mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK, _(" now in drive %u\n"), bagobjp->indriveix ); } else { mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK, _(" now in drive\n") ); } } ix++; bagobjp = 0; /* keep lint happy */ } } if ( knownholespr ) { if ( purp == PURP_DIR ) { mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK, bagp ? _("\nthere are additional unidentified media " "objects containing media files not yet tried " "for directory hierarchy restoral:\n") : _("\nthere are unidentified media " "objects containing media files not yet tried " "for directory hierarchy restoral:\n") ); } if ( purp == PURP_NONDIR ) { mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK, bagp ? _("\nthere are additional unidentified media " "objects not yet fully restored\n") : _("\nthere are unidentified media objects " "not yet fully restored\n") ); } } else if ( maybeholespr ) { if ( purp == PURP_DIR ) { mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK, bagp ? _("\nthere may be additional unidentified media " "objects containing media files not yet tried " "for directory hierarchy restoral:\n") : _("\nthere may be unidentified media " "objects containing media files not yet tried " "for directory hierarchy restoral:\n") ); } if ( purp == PURP_NONDIR ) { mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK, bagp ? _("\nthere may be additional unidentified media " "objects not yet fully restored\n") : _("\there may be unidentified media " "objects not yet fully restored\n") ); } } if ( ! bagp && ! knownholespr && ! maybeholespr ) { mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK, _("no additional media objects needed\n") ); } } static int do_fssetdm_by_handle( char *path, fsdmidata_t *fdmp) { void *hanp; size_t hlen=0; int rc; if (path_to_handle(path, &hanp, &hlen)) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "path_to_handle of %s failed:%s\n"), path, strerror( errno )); return -1; } rc = fssetdm_by_handle(hanp, hlen, fdmp); free_handle(hanp, hlen); if (rc) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "fssetdm_by_handle of %s failed %s\n"), path, strerror( errno )); } return rc; } static int quotafilecheck(char *type, char *dstdir, char *quotafile) { struct stat s; char buf[MAXPATHLEN]; sprintf( buf, "%s/%s", dstdir, quotafile ); if ( stat (buf, &s ) >= 0 && S_ISREG(s.st_mode)) { mlog( MLOG_NORMAL, _( "%s quota information written to '%s'\n"), type, buf ); return 1; } return 0; } xfsdump-3.1.6+nmu1/restore/namreg.c0000644000000000000000000002561112620476160014062 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "types.h" #include "lock.h" #include "mlog.h" #include "namreg.h" #include "openutil.h" #include "mmap.h" /* structure definitions used locally ****************************************/ #define NAMREG_AVGLEN 10 /* persistent context for a namreg - placed in first page * of the namreg file by namreg_init if not a sync */ struct namreg_pers { off64_t np_appendoff; }; typedef struct namreg_pers namreg_pers_t; #define NAMREG_PERS_SZ pgsz /* transient context for a namreg - allocated by namreg_init() */ #define NAMREG_BUFSIZE 32768 struct namreg_tran { char *nt_pathname; int nt_fd; char *nt_map; bool_t nt_at_endpr; size_t nt_off; char nt_buf[NAMREG_BUFSIZE]; }; typedef struct namreg_tran namreg_tran_t; #ifdef NAMREGCHK /* macros for manipulating namreg handles when handle consistency * checking is enabled. */ #define CHKBITCNT 2 #define CHKBITSHIFT ( NBBY * sizeof( nrh_t ) - CHKBITCNT ) #define CHKBITLOMASK ( ( 1ULL << CHKBITCNT ) - 1 ) #define CHKBITMASK ( CHKBITLOMASK << CHKBITSHIFT ) #define CHKHDLCNT CHKBITSHIFT #define CHKHDLMASK ( ( 1ULL << CHKHDLCNT ) - 1 ) #define CHKGETBIT( h ) ( ( (h) >> CHKBITSHIFT ) & CHKBITLOMASK ) #define CHKGETHDL( h ) ( (h) & CHKHDLMASK ) #define CHKMKHDL( c, h ) ( ( ( (c) << CHKBITSHIFT ) & CHKBITMASK ) \ | \ ( (h) & CHKHDLMASK )) #define HDLMAX ( ( off64_t )CHKHDLMASK ) #else /* NAMREGCHK */ #define HDLMAX ( NRH_NULL - 1 ) #endif /* NAMREGCHK */ /* declarations of externally defined global symbols *************************/ extern size_t pgsz; /* forward declarations of locally defined static functions ******************/ static rv_t namreg_flush( void ); /* definition of locally defined global variables ****************************/ /* definition of locally defined static variables *****************************/ static char *namregfile = "namreg"; static namreg_tran_t *ntp = 0; static namreg_pers_t *npp = 0; /* definition of locally defined global functions ****************************/ bool_t namreg_init( char *hkdir, bool_t resume, uint64_t inocnt ) { if ( ntp ) { return BOOL_TRUE; } /* sanity checks */ assert( ! ntp ); assert( ! npp ); assert( sizeof( namreg_pers_t ) <= NAMREG_PERS_SZ ); /* allocate and initialize context */ ntp = ( namreg_tran_t * )calloc( 1, sizeof( namreg_tran_t )); assert( ntp ); /* generate a string containing the pathname of the namreg file */ ntp->nt_pathname = open_pathalloc( hkdir, namregfile, 0 ); /* open the namreg file */ if ( resume ) { /* open existing file */ ntp->nt_fd = open( ntp->nt_pathname, O_RDWR ); if ( ntp->nt_fd < 0 ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "could not find name registry file %s: " "%s\n"), ntp->nt_pathname, strerror( errno )); return BOOL_FALSE; } } else { /* create the namreg file, first unlinking any older version * laying around */ ( void )unlink( ntp->nt_pathname ); ntp->nt_fd = open( ntp->nt_pathname, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR ); if ( ntp->nt_fd < 0 ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "could not create name registry file %s: " "%s\n"), ntp->nt_pathname, strerror( errno )); return BOOL_FALSE; } /* reserve space for the backing store. try to use RESVSP64. * if doesn't work, try ALLOCSP64. the former is faster, as * it does not zero the space. */ { bool_t successpr; unsigned int ioctlcmd; int loglevel; size_t trycnt; for ( trycnt = 0, successpr = BOOL_FALSE, ioctlcmd = XFS_IOC_RESVSP64, loglevel = MLOG_VERBOSE ; ! successpr && trycnt < 2 ; trycnt++, ioctlcmd = XFS_IOC_ALLOCSP64, loglevel = max( MLOG_NORMAL, loglevel - 1 )) { off64_t initsz; struct flock64 flock64; int rval; if ( ! ioctlcmd ) { continue; } initsz = ( off64_t )NAMREG_PERS_SZ + ( ( off64_t )inocnt * NAMREG_AVGLEN ); flock64.l_whence = 0; flock64.l_start = 0; flock64.l_len = initsz; rval = ioctl( ntp->nt_fd, ioctlcmd, &flock64 ); if ( rval ) { if ( errno != ENOTTY ) { mlog( loglevel | MLOG_NOTE, _( "attempt to reserve %lld bytes for %s " "using %s " "failed: %s (%d)\n"), initsz, ntp->nt_pathname, ioctlcmd == XFS_IOC_RESVSP64 ? "XFS_IOC_RESVSP64" : "XFS_IOC_ALLOCSP64", strerror( errno ), errno ); } } else { successpr = BOOL_TRUE; } } } } /* mmap the persistent descriptor */ assert( ! ( NAMREG_PERS_SZ % pgsz )); npp = ( namreg_pers_t * ) mmap_autogrow( NAMREG_PERS_SZ, ntp->nt_fd, ( off_t )0 ); if ( npp == ( namreg_pers_t * )-1 ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "unable to map %s: %s\n"), ntp->nt_pathname, strerror( errno )); return BOOL_FALSE; } /* initialize persistent state */ if ( ! resume ) { npp->np_appendoff = ( off64_t )NAMREG_PERS_SZ; } /* initialize transient state */ ntp->nt_at_endpr = BOOL_FALSE; return BOOL_TRUE; } nrh_t namreg_add( char *name, size_t namelen ) { off64_t oldoff; unsigned char c; nrh_t nrh; /* sanity checks */ assert( ntp ); assert( npp ); assert( !ntp->nt_map ); /* make sure file pointer is positioned to append */ if ( ! ntp->nt_at_endpr ) { off64_t newoff; newoff = lseek64( ntp->nt_fd, npp->np_appendoff, SEEK_SET ); if ( newoff == ( off64_t )-1 ) { mlog( MLOG_NORMAL, _( "lseek of namreg failed: %s\n"), strerror( errno )); assert( 0 ); return NRH_NULL; } assert( npp->np_appendoff == newoff ); ntp->nt_at_endpr = BOOL_TRUE; } if (ntp->nt_off + namelen + 1 > sizeof(ntp->nt_buf)) { if (namreg_flush() != RV_OK) { return NRH_NULL; } } /* save the current offset */ oldoff = npp->np_appendoff; /* write a one byte unsigned string length into the buffer. */ assert( namelen < 256 ); c = ( unsigned char )( namelen & 0xff ); ntp->nt_buf[ntp->nt_off++] = c; /* write the name string into the buffer. */ memcpy(ntp->nt_buf + ntp->nt_off, name, namelen); ntp->nt_off += namelen; npp->np_appendoff += ( off64_t )( 1 + namelen ); assert( oldoff <= HDLMAX ); #ifdef NAMREGCHK /* encode the lsb of the len plus the first character into the handle. */ nrh = CHKMKHDL( ( nrh_t )namelen + ( nrh_t )*name, ( nrh_t )oldoff ); #else /* NAMREGCHK */ nrh = ( nrh_t )oldoff; #endif /* NAMREGCHK */ return nrh; } /* ARGSUSED */ void namreg_del( nrh_t nrh ) { /* currently not implemented - grows, never shrinks */ } static rv_t namreg_flush( void ) { ssize_t nwritten; /* sanity checks */ assert( ntp ); if (ntp->nt_off) { /* write the accumulated name strings. */ nwritten = write( ntp->nt_fd, ( void * )ntp->nt_buf, ntp->nt_off ); if ( nwritten != ntp->nt_off ) { if ( nwritten < 0 ) { mlog( MLOG_NORMAL | MLOG_ERROR, _("write of namreg buffer failed: %s\n"), strerror( errno )); } else { mlog( MLOG_NORMAL | MLOG_ERROR, _("write of namreg buffer failed: " "expected to write %ld, actually " "wrote %ld\n"), ntp->nt_off, nwritten); } assert( 0 ); return RV_UNKNOWN; } ntp->nt_off = 0; } return RV_OK; } int namreg_get( nrh_t nrh, char *bufp, size_t bufsz ) { off64_t newoff; int nread; size_t len; char *in_bufp; static char read_buf[256]; /* long enough for the longest allowed name (255), plus 1 for length */ #ifdef NAMREGCHK nrh_t chkbit; #endif /* NAMREGCHK */ /* sanity checks */ assert( ntp ); assert( npp ); /* make sure we aren't being given a NULL handle */ assert( nrh != NRH_NULL ); /* convert the handle into the offset */ #ifdef NAMREGCHK newoff = ( off64_t )( size64_t )CHKGETHDL( nrh ); chkbit = CHKGETBIT( nrh ); #else /* NAMREGCHK */ newoff = ( off64_t )( size64_t )nrh; #endif /* NAMREGCHK */ /* do sanity check on offset */ assert( newoff <= HDLMAX ); assert( newoff < npp->np_appendoff ); assert( newoff >= ( off64_t )NAMREG_PERS_SZ ); lock( ); if ( ntp->nt_map ) { in_bufp = ntp->nt_map + newoff - NAMREG_PERS_SZ; } else { if ( ntp->nt_at_endpr && ntp->nt_off ) { if (namreg_flush() != RV_OK) { unlock( ); return -3; } } /* seek to the name */ newoff = lseek64( ntp->nt_fd, newoff, SEEK_SET ); if ( newoff == ( off64_t )-1 ) { unlock( ); mlog( MLOG_NORMAL, _( "lseek of namreg failed: %s\n"), strerror( errno )); return -3; } ntp->nt_at_endpr = BOOL_FALSE; /* read the name length and the name itself in one call * NOTE: assumes read_buf is big enough for the longest * allowed name (255 chars) plus one byte for length. */ nread = read( ntp->nt_fd, ( void * )read_buf, sizeof(read_buf) ); if ( nread <= 0 ) { unlock( ); mlog( MLOG_NORMAL, _( "read of namreg failed: %s (nread = %d)\n"), strerror( errno ), nread ); return -3; } in_bufp = read_buf; } /* deal with a short caller-supplied buffer */ len = ( size_t )in_bufp[0]; if ( bufsz < len + 1 ) { unlock( ); return -1; } /* copy the name into the caller-supplied buffer. */ strncpy(bufp, in_bufp+1, len); #ifdef NAMREGCHK /* validate the checkbit */ assert( chkbit == ( ( ( nrh_t )len + ( nrh_t )bufp[ 0 ] ) & CHKBITLOMASK )); #endif /* NAMREGCHK */ /* null-terminate the string if room */ bufp[ len ] = 0; unlock( ); return ( int )len; } rv_t namreg_map( void ) { rv_t rv; /* ensure all entries have been written */ if ( (rv = namreg_flush()) != RV_OK ) { return rv; } ntp->nt_map = ( char * ) mmap_autogrow( npp->np_appendoff - NAMREG_PERS_SZ, ntp->nt_fd, NAMREG_PERS_SZ ); /* it's okay if this fails, just fall back to (the much slower) * seek-and-read lookups. */ if ( ntp->nt_map == ( char * )-1 ) { mlog( MLOG_DEBUG, "failed to map namreg: %s\n", strerror( errno ) ); ntp->nt_map = NULL; } return RV_OK; } /* definition of locally defined static functions ****************************/ xfsdump-3.1.6+nmu1/restore/tree.h0000644000000000000000000000770612620476160013562 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TREE_H #define TREE_H /* tree_init - creates a new tree abstraction. */ extern bool_t tree_init( char *hkdir, char *dstdir, bool_t toconlypr, bool_t ownerpr, xfs_ino_t rootino, xfs_ino_t firstino, xfs_ino_t lastino, size64_t dircnt, size64_t nondircnt, size64_t vmsz, bool_t fullpr, bool_t restoredmpr, bool_t dstdirisxfspr, uint32_t dumpformat, bool_t truncategenpr ); /* tree_sync - synchronizes with an existing tree abstraction */ extern bool_t tree_sync( char *hkdir, char *dstdir, bool_t toconlypr, bool_t fullpr, bool_t dstdirisxfspr ); /* tree_check_dump_format - detect the rare case where a * cumulative restore begins with a format 3 (or newer) * dump, and a later restore in the series encounters * a format 2 dump. the restore will fail unless the * original restore was told to use format 2 gen numbers. */ extern bool_t tree_check_dump_format( uint32_t dumpformat ); /* tree_begindir - begins application of dumped directory to tree. * returns handle to dir node. returns by reference the dirattr * handle if new. caller must pre-zero (DAH_NULL). */ extern nh_t tree_begindir( filehdr_t *fhdrp, dah_t *dahp ); /* tree_addent - adds a directory entry; takes dirh from above call */ extern rv_t tree_addent( nh_t dirh, xfs_ino_t ino, gen_t gen, char *name, size_t namelen ); /* ends application of dir */ extern void tree_enddir( nh_t dirh ); #ifdef TREE_CHK /* tree_chk - do a sanity check of the tree prior to post-processing and * non-dir restoral. returns FALSE if corruption detected. */ extern bool_t tree_chk( void ); #endif /* TREE_CHK */ /* tree_marknoref - mark all nodes as no reference, not dumped dirs, and * clear all directory attribute handles. done at the beginning * of the restoral of a dump session, in order to detect directory entries * no longer needed. */ extern void tree_marknoref( void ); /* mark all nodes in tree as either selected or unselected, depending on sense */ extern void tree_markallsubtree( bool_t sensepr ); extern bool_t tree_subtree_parse( bool_t sensepr, char *path ); extern bool_t tree_post( char *path1, char *path2 ); extern rv_t tree_cb_links( xfs_ino_t ino, gen_t gen, int32_t ctime, int32_t mtime, bool_t ( * funcp )( void *contextp, bool_t linkpr, char *path1, char *path2 ), void *contextp, char *path1, char *path2 ); /* called after all dirs have been restored. adjusts the ref flags, * by noting that dirents not refed because their parents were not dumped * are virtually reffed if their parents are refed. */ extern bool_t tree_adjref( void ); extern bool_t tree_setattr( char *path ); extern bool_t tree_delorph( void ); extern bool_t tree_subtree_inter( void ); extern bool_t tree_extattr( bool_t ( * cbfunc )( char *path, dah_t dah ), char *path ); /* does a depthwise bottom-up traversal of the tree, calling * the supplied callback for all directories with a non-NULL dirattr * handle. The callback will get called with the directory's pathname * and it dirattr handle. the traversal will be aborted if the * callback returns FALSE. returns FALSE if operator requests * an interrupt. */ #endif /* TREE_H */ xfsdump-3.1.6+nmu1/restore/win.h0000644000000000000000000000355312620476160013414 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef WIN_H #define WIN_H /* win.[ch] - windows into a very large file */ typedef int segix_t; /* initialize the window abstraction */ void win_init( int fd, off64_t rngoff, /* offset into file of windowing */ size64_t winsz, /* window size */ size_t wincntmax ); /* max number of windows to manage */ /* supply a pointer to the portion of the file identified by segix. */ void win_map( segix_t segix, /* segment index to be mapped */ void **pp ); /* returns pointer by reference */ /* invalidate the pointer previously supplied. SIDE-EFFECT: zeros * by reference the caller's pointer. */ void win_unmap( segix_t segix, /* must match win_map param */ void **pp ); /* ptr generated by win_map: ZEROED */ /* * Functions used to disable the window locking from happening. * This is used in the directory reconstruction phase where only * one thread is actually executing this code. * * Assumes called in region where only 1 thread can execute it. */ void win_locks_off(void); void win_locks_on(void); /* * Find out how many mmap calls were made for windows. */ size_t win_getnum_mmaps(void); #endif /* WIN_H */ xfsdump-3.1.6+nmu1/restore/bag.h0000644000000000000000000000515112607344125013344 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef BAG_H #define BAG_H /* bag.[hc] - bag abstraction * * user embeds a bagelem_t into items to be bagged. the element contains * an element key, and a user-specified pointer. items can be inserted * into the bag, removed from the bag, and searched for in the bag. the * user-embedded bagelem_t is soley owned by the bag: DON'T try to * reference bagelem_t members! */ struct bagelem { bool_t be_loaded; struct bag *be_bagp; size64_t be_key; void *be_payloadp; struct bagelem *be_nextp; struct bagelem *be_prevp; }; typedef struct bagelem bagelem_t; struct bag { bagelem_t *b_headp; }; typedef struct bag bag_t; /* creates a new bag */ extern bag_t *bag_alloc( void ); /* insert the item into the bag. the caller supplies a search key * and arbitrary payload. */ extern void bag_insert( bag_t *bagp, bagelem_t *bagelemp, size64_t key, void *payloadp ); /* remove the item from the bag. the key and payload originally supplied * to the insert operator are returned by reference. */ extern void bag_remove( bag_t *bagp, bagelem_t *bagelemp, size64_t *keyp, void **payloadpp ); /* search by key for an element in the bag. * returns the element pointer if a matching item is found, as well as * the payload (by reference). if the item is not in the bag, returns * a null pointer and (by reference) payload. */ extern bagelem_t *bag_find( bag_t *bagp, size64_t key, void **payloadpp ); /* private bag iterator */ struct bagiter { bag_t *bi_bagp; bagelem_t *bi_lastp; bagelem_t *bi_nextp; }; typedef struct bagiter bagiter_t; /* initializes a bag iterator */ extern void bagiter_init( bag_t *bagp, bagiter_t *iterp ); /* returns the next element in the bag. caller may remove the element * prior to the next call. */ extern bagelem_t * bagiter_next( bagiter_t *iterp, void **payloadpp ); /* destroys the bag. */ extern void bag_free( bag_t *bagp ); #endif /* BAG_H */ xfsdump-3.1.6+nmu1/restore/Makefile0000644000000000000000000000351212643556443014111 0ustar # # Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = .. include $(TOPDIR)/include/builddefs COMMINCL = \ arch_xlate.h \ cldmgr.h \ content.h \ content_inode.h \ dlog.h \ drive.h \ exit.h \ fs.h \ getdents.h \ global.h \ hsmapi.h \ lock.h \ media.h \ mlog.h \ openutil.h \ path.h \ qlock.h \ rec_hdr.h \ ring.h \ stream.h \ timeutil.h \ ts_mtio.h \ types.h \ util.h INVINCL = \ inventory.h \ inv_priv.h INVCOMMON = \ inv_api.c \ inv_core.c \ inv_files.c \ inv_fstab.c \ inv_idx.c \ inv_mgr.c \ inv_stobj.c COMMON = \ arch_xlate.c \ cldmgr.c \ dlog.c \ drive.c \ drive_scsitape.c \ drive_simple.c \ drive_minrmt.c \ fs.c \ getdents.c \ global.c \ hsmapi.c \ lock.c \ main.c \ mlog.c \ openutil.c \ path.c \ qlock.c \ ring.c \ stream.c \ timeutil.c \ util.c LOCALS = \ bag.c \ content.c \ dirattr.c \ inomap.c \ mmap.c \ namreg.c \ node.c \ tree.c \ win.c LOCALINCL = \ bag.h \ dirattr.h \ getopt.h \ inomap.h \ mmap.h \ namreg.h \ node.h \ tree.h \ win.h LTCOMMAND = xfsrestore CFILES = $(LOCALS) LCFILES = $(COMMON) $(INVCOMMON) HFILES = $(LOCALINCL) LHFILES = $(COMMINCL) $(INVINCL) LINKS = $(COMMINCL) $(COMMON) $(INVINCL) $(INVCOMMON) LDIRT = $(LINKS) LLDLIBS = $(LIBUUID) $(LIBHANDLE) $(LIBATTR) $(LIBRMT) $(LIBPTHREAD) LTDEPENDENCIES = $(LIBRMT) LCFLAGS = -DRESTORE default: depend $(LTCOMMAND) include $(BUILDRULES) install: default $(INSTALL) -m 755 -d $(PKG_ROOT_SBIN_DIR) $(LTINSTALL) -m 755 $(LTCOMMAND) $(PKG_ROOT_SBIN_DIR) $(INSTALL) -m 755 -d $(PKG_SBIN_DIR) install-dev: .dep: $(COMMINCL) $(COMMON) $(INVINCL) $(INVCOMMON) $(COMMINCL) $(COMMON): @echo " [LN] $@" $(Q)$(RM) $@; $(LN_S) ../common/$@ $@ $(INVINCL) $(INVCOMMON): @echo " [LN] $@" $(Q)$(RM) $@; $(LN_S) ../inventory/$@ $@ -include .dep xfsdump-3.1.6+nmu1/restore/win.c0000644000000000000000000002144312620476160013405 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include "config.h" #include "types.h" #include "mlog.h" #include "qlock.h" #include "mmap.h" #include "win.h" extern size_t pgsz; extern size_t pgmask; /* number of entries to add to the segmap if * it needs to be resized */ #define SEGMAP_INCR 16 /* * critical region */ #define CRITICAL_BEGIN() if (!locksoffpr) qlock_lock( tranp->t_qlockh ) #define CRITICAL_END() if (!locksoffpr) qlock_unlock( tranp->t_qlockh ) /* window descriptor */ struct win { segix_t w_segix; /* index of segment mapped by this window */ void *w_p; /* window virtual address */ size_t w_refcnt; /* reference count */ struct win *w_nextp; /* LRU list forward linkage */ struct win *w_prevp; /* LRU list backward linkage */ }; typedef struct win win_t; /* forward declarations */ static void win_segmap_resize( segix_t segix ); /* transient state */ struct tran { int t_fd; /* file descriptor of backing store to be windowed */ off64_t t_firstoff; /* offset of first seg within backing store (for mmap( )) */ size64_t t_segsz; /* backing store segment / window size */ size_t t_winmax; /* maximum number of windows to allocate */ size_t t_wincnt; /* number of windows allocated */ size_t t_winmmaps; /* number of window mmap calls made */ win_t *t_lruheadp; /* LRU head (re-use from this end) */ win_t *t_lrutailp; /* LRU tail (put here when no refs) */ win_t **t_segmap; /* mapping from segment index to window. an entry * points to a win_t struct if segment is currently * mapped, otherwise the entry is NULL. */ size_t t_segmaplen; /* number of segments currently represented in * t_segmap array. */ qlockh_t t_qlockh; /* for establishing critical regions */ }; typedef struct tran tran_t; static tran_t *tranp = 0; static bool_t locksoffpr = BOOL_FALSE; /* * assumes called in region where only 1 thread can execute it */ void win_locks_off(void) { locksoffpr = BOOL_TRUE; } /* * assumes called in region where only 1 thread can execute it */ void win_locks_on(void) { locksoffpr = BOOL_FALSE; } /* * tell me how many windows I used for the tree */ size_t win_getnum_mmaps(void) { return tranp->t_winmmaps; } void win_init( int fd, off64_t firstoff, size64_t segsz, size_t winmax ) { /* validate parameters */ assert( ( firstoff & ( off64_t )pgmask ) == 0 ); assert( ( segsz & pgmask ) == 0 ); /* allocate and initialize transient state */ assert( tranp == 0 ); tranp = ( tran_t * )calloc( 1, sizeof( tran_t )); assert( tranp ); tranp->t_fd = fd; tranp->t_firstoff = firstoff; tranp->t_segsz = segsz; tranp->t_winmax = winmax; tranp->t_segmaplen = SEGMAP_INCR; tranp->t_segmap = (win_t **) calloc( tranp->t_segmaplen, sizeof(win_t *) ); assert( tranp->t_segmap ); /* initialize critical region enforcer */ tranp->t_qlockh = qlock_alloc( QLOCK_ORD_WIN ); } void win_map( segix_t segix, void **pp ) { off64_t segoff; win_t *winp; CRITICAL_BEGIN(); #ifdef TREE_DEBUG mlog(MLOG_DEBUG | MLOG_TREE | MLOG_NOLOCK, "win_map(segix=%u,addr=%p)\n", segix, pp); #endif /* resize the array if necessary */ if ( segix >= tranp->t_segmaplen ) win_segmap_resize( segix ); /* see if segment already mapped. if ref cnt zero, * remove from LRU list. */ winp = tranp->t_segmap[segix]; if ( winp ) { #ifdef TREE_DEBUG mlog(MLOG_DEBUG | MLOG_TREE | MLOG_NOLOCK, "win_map(): requested segment already mapped\n"); #endif if ( winp->w_refcnt == 0 ) { assert( tranp->t_lruheadp ); assert( tranp->t_lrutailp ); if ( tranp->t_lruheadp == winp ) { if ( tranp->t_lrutailp == winp ) { tranp->t_lruheadp = 0; tranp->t_lrutailp = 0; } else { tranp->t_lruheadp = winp->w_nextp; tranp->t_lruheadp->w_prevp = 0; } } else { if ( tranp->t_lrutailp == winp ) { tranp->t_lrutailp = winp->w_prevp; tranp->t_lrutailp->w_nextp = 0; } else { winp->w_prevp->w_nextp = winp->w_nextp; winp->w_nextp->w_prevp = winp->w_prevp; } } winp->w_prevp = 0; winp->w_nextp = 0; } else { assert( ! winp->w_prevp ); assert( ! winp->w_nextp ); } winp->w_refcnt++; *pp = winp->w_p; CRITICAL_END(); return; } /* Allocate a new descriptor if we haven't yet hit the maximum, * otherwise reuse any descriptor on the LRU list. */ if ( tranp->t_wincnt < tranp->t_winmax ) { #ifdef TREE_DEBUG mlog(MLOG_DEBUG | MLOG_TREE | MLOG_NOLOCK, "win_map(): create a new window\n"); #endif winp = ( win_t * )calloc( 1, sizeof( win_t )); assert( winp ); tranp->t_wincnt++; } else if ( tranp->t_lruheadp ) { /* REFERENCED */ int rval; #ifdef TREE_DEBUG mlog(MLOG_DEBUG | MLOG_TREE | MLOG_NOLOCK, "win_map(): get head from lru freelist & unmap\n"); #endif assert( tranp->t_lrutailp ); winp = tranp->t_lruheadp; tranp->t_lruheadp = winp->w_nextp; if ( tranp->t_lruheadp ) { tranp->t_lruheadp->w_prevp = 0; } else { tranp->t_lrutailp = 0; } tranp->t_segmap[winp->w_segix] = NULL; rval = munmap( winp->w_p, tranp->t_segsz ); assert( ! rval ); memset( ( void * )winp, 0, sizeof( win_t )); } else { assert( tranp->t_wincnt == tranp->t_winmax ); *pp = NULL; CRITICAL_END(); mlog( MLOG_NORMAL | MLOG_WARNING, _( "all map windows in use. Check virtual memory limits\n")); return; } /* calculate offset of segment */ segoff = segix * ( off64_t )tranp->t_segsz; /* map the window */ assert( tranp->t_segsz >= 1 ); assert( tranp->t_firstoff <= OFF64MAX - segoff - ( off64_t )tranp->t_segsz + 1ll ); assert( ! ( tranp->t_segsz % pgsz )); assert( ! ( ( tranp->t_firstoff + segoff ) % ( off64_t )pgsz )); #ifdef TREE_DEBUG mlog(MLOG_DEBUG | MLOG_TREE | MLOG_NOLOCK, "win_map(): mmap segment at %lld, size = %llu\n", ( off64_t )( tranp->t_firstoff + segoff ), tranp->t_segsz); #endif tranp->t_winmmaps++; winp->w_p = mmap_autogrow( tranp->t_segsz, tranp->t_fd, ( off64_t )( tranp->t_firstoff + segoff )); if ( winp->w_p == (void *)-1 ) { int error = errno; mlog( MLOG_NORMAL | MLOG_ERROR, _( "win_map(): unable to map a node segment of size %d at %d: %s\n"), tranp->t_segsz, tranp->t_firstoff + segoff, strerror( error )); tranp->t_wincnt--; tranp->t_winmax--; CRITICAL_END(); free(winp); if (error == ENOMEM && tranp->t_lruheadp) { mlog( MLOG_NORMAL | MLOG_ERROR, _("win_map(): try to select a different win_t\n")); win_map(segix, pp); return; } *pp = NULL; return; } winp->w_segix = segix; assert( winp->w_refcnt == 0 ); winp->w_refcnt++; tranp->t_segmap[winp->w_segix] = winp; *pp = winp->w_p; CRITICAL_END(); } void win_unmap( segix_t segix, void **pp ) { win_t *winp; CRITICAL_BEGIN(); /* verify window mapped */ assert( segix < tranp->t_segmaplen ); winp = tranp->t_segmap[segix]; assert( winp ); /* validate p */ assert( pp ); assert( *pp ); assert( *pp >= winp->w_p ); assert( *pp < ( void * )( ( char * )( winp->w_p ) + tranp->t_segsz )); /* decrement the reference count. if zero, place at tail of LRU list. */ assert( winp->w_refcnt > 0 ); winp->w_refcnt--; assert( ! winp->w_prevp ); assert( ! winp->w_nextp ); if ( winp->w_refcnt == 0 ) { if ( tranp->t_lrutailp ) { assert( tranp->t_lruheadp ); winp->w_prevp = tranp->t_lrutailp; tranp->t_lrutailp->w_nextp = winp; tranp->t_lrutailp = winp; } else { assert( ! tranp->t_lruheadp ); assert( ! winp->w_prevp ); tranp->t_lruheadp = winp; tranp->t_lrutailp = winp; } assert( ! winp->w_nextp ); } /* zero the caller's pointer */ *pp = 0; CRITICAL_END(); } static void win_segmap_resize(segix_t segix) { size_t oldlen; win_t **new_part; oldlen = tranp->t_segmaplen; tranp->t_segmaplen = segix + SEGMAP_INCR; tranp->t_segmap = (win_t **) realloc( tranp->t_segmap, tranp->t_segmaplen * sizeof(win_t *) ); assert( tranp->t_segmap ); /* clear the new portion of the array */ new_part = tranp->t_segmap + oldlen; memset( new_part, 0, (tranp->t_segmaplen - oldlen) * sizeof(win_t *) ); } xfsdump-3.1.6+nmu1/restore/getopt.h0000644000000000000000000001001612607344125014111 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GETOPT_H #define GETOPT_H /* getopt.h common getopt command string * * several modules parse the command line looking for arguments specific to * that module. Unfortunately, each of the getopt(3) calls needs the * complete command string, to know how to parse. This file's sole * purpose is to contain that command string. */ #define GETOPT_CMDSTRING "a:b:c:def:himn:op:qrs:tv:wABCDEFG:H:I:JKL:M:NO:PQRS:TUVWX:Y:" #define GETOPT_WORKSPACE 'a' /* workspace dir (content.c) */ #define GETOPT_BLOCKSIZE 'b' /* blocksize for rmt */ #define GETOPT_ALERTPROG 'c' /* Media Change Alert prog(content.c) */ #define GETOPT_PV766024 'd' /* DRIVE_ERROR_MEDIA for pv#766024 */ #define GETOPT_EXISTING 'e' /* don't overwrite existing files */ #define GETOPT_DUMPDEST 'f' /* dump src. file (drive.c) */ /* 'g' */ #define GETOPT_HELP 'h' /* display version and usage */ #define GETOPT_INTERACTIVE 'i' /* interactive subtree selection */ /* 'j' */ /* 'k' */ /* 'l' */ #define GETOPT_MINRMT 'm' /* use minimal rmt protocol */ #define GETOPT_NEWER 'n' /* only restore files newer than arg */ #define GETOPT_OWNER 'o' /* restore owner/grp even if not root */ #define GETOPT_PROGRESS 'p' /* interval between progress reports */ #define GETOPT_QIC 'q' /* option to tell dump it's a QIC tape */ #define GETOPT_CUMULATIVE 'r' /* accumulating restore (content.c) */ #define GETOPT_SUBTREE 's' /* subtree restore (content.c) */ #define GETOPT_TOC 't' /* display contents only (content.c) */ /* 'u' */ #define GETOPT_VERBOSITY 'v' /* verbosity level (0 to 4 ) */ #define GETOPT_SMALLWINDOW 'w' /* use a small window for dir entries */ /* 'x' */ /* 'y' */ /* 'z' */ #define GETOPT_NOEXTATTR 'A' /* do not restore ext. file attr. */ #define GETOPT_ROOTPERM 'B' /* restore ownership and permissions for root directory */ #define GETOPT_RECCHKSUM 'C' /* use record checksums */ #define GETOPT_SETDM 'D' /* set DMAPI event mask and state */ #define GETOPT_CHANGED 'E' /* overwrite if missing or old */ #define GETOPT_FORCE 'F' /* don't prompt (getopt.c) */ #define GETOPT_MINSTACKSZ 'G' /* minimum stack size (bytes) */ #define GETOPT_MAXSTACKSZ 'H' /* maximum stack size (bytes) */ #define GETOPT_INVPRINT 'I' /* just display the inventory */ #define GETOPT_NOINVUPDATE 'J' /* do not update the dump inventory */ #define GETOPT_FMT2COMPAT 'K' /* force use format 2 gen numbers */ #define GETOPT_DUMPLABEL 'L' /* dump session label (global.c) */ #define GETOPT_MEDIALABEL 'M' /* media object label (media.c) */ #define GETOPT_TIMESTAMP 'N' /* show timestamps in log msgs */ #define GETOPT_OPTFILE 'O' /* specifycmd line options file */ #define GETOPT_RINGPIN 'P' /* pin down I/O buffer ring */ #define GETOPT_SESSCPLT 'Q' /* force completion of intr. session */ #define GETOPT_RESUME 'R' /* resume intr rest (content.c) */ #define GETOPT_SESSIONID 'S' /* dump session uuid (global.c) */ #define GETOPT_NOTIMEOUTS 'T' /* don't timeout dialogs */ #define GETOPT_UNLOAD 'U' /* unload media when change needed */ #define GETOPT_SHOWLOGSS 'V' /* show subsystem of log messages */ #define GETOPT_SHOWLOGLEVEL 'W' /* show level of log messages */ #define GETOPT_NOSUBTREE 'X' /* subtree to exclude */ #define GETOPT_RINGLEN 'Y' /* specify I/O buffer ring length */ /* 'Z' used on irix for miniroot */ #endif /* GETOPT_H */ xfsdump-3.1.6+nmu1/restore/node.c0000644000000000000000000003731712620476160013544 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include "config.h" #include "types.h" #include "mlog.h" #include "win.h" #include "node.h" #include "mmap.h" extern size_t pgsz; extern size_t pgmask; /* node handle limits */ #ifdef NODECHK /* macros for manipulating node handles when handle consistency * checking is enabled. the upper bits of a handle will be loaded * with the node gen count, described below. this should not be * used for production code, it cuts into the number of dirents * that xfsrestore can handle. */ #define HDLGENCNT 4 #define HDLGENSHIFT ( NBBY * sizeof ( nh_t ) - HDLGENCNT ) #define HDLGENLOMASK ( ( 1 << HDLGENCNT ) - 1 ) #define HDLGENMASK ( HDLGENLOMASK << HDLGENSHIFT ) #define HDLMASK ( ( 1 << HDLGENSHIFT ) - 1 ) #define HDLGETGEN( h ) ( ( u_char_t ) \ ( ( ( int )h >> HDLGENSHIFT ) \ & \ HDLGENLOMASK )) #define HDLGETNHDL( h ) ( ( nh_t )( ( int )h & HDLMASK )) #define HDLMKHDL( g, n ) ( ( nh_t )( ( ( ( int )g << HDLGENSHIFT )\ & \ HDLGENMASK ) \ | \ ( ( int )n & HDLMASK ))) #define NH_MAX ( HDLMASK ) /* the housekeeping byte of each node will hold two check fields: * a gen count, initialized to 0 and incremented each time a node * is allocated, to catch re-use of stale handles; and unique pattern, to * differentiate a valid node from random memory. two unique patterns will * be used; one when the node is on the free list, another when it is * allocated. this allows me to detect use of handles to nodes which have * be freed. */ #define HKPGENCNT HDLGENCNT #define HKPGENSHIFT ( NBBY - HKPGENCNT ) #define HKPGENLOMASK ( ( 1 << HKPGENCNT ) - 1 ) #define HKPGENMASK ( HKPGENLOMASK << HKPGENSHIFT ) #define HKPUNQCNT ( NBBY - HKPGENCNT ) #define HKPUNQMASK ( ( 1 << HKPUNQCNT ) - 1 ) #define HKPGETGEN( b ) ( ( u_char_t ) \ ( ( ( int )b >> HKPGENSHIFT ) \ & \ HKPGENLOMASK )) #define HKPGETUNQ( b ) ( ( u_char_t )( ( int )b & HKPUNQMASK )) #define HKPMKHKP( g, u ) ( ( u_char_t ) \ ( ( ( ( int )g << HKPGENSHIFT ) \ & \ HKPGENMASK ) \ | \ ( ( int )u & HKPUNQMASK ))) /* simple patterns for detecting a node */ #define NODEUNQFREE 0x9 #define NODEUNQALCD 0x6 #else /* NODECHK */ #define NH_MAX ( NH_NULL - 1 ) #endif /* NODECHK */ /* window constraints */ #define NODESPERSEG_MIN 1048576 #define WINMAP_MIN 4 /* reserve the firstpage for a header to save persistent context */ #define NODE_HDRSZ pgsz typedef int relnix_t; struct node_hdr { size_t nh_nodesz; /* internal node size - user may see something smaller */ ix_t nh_nodehkix; /* index of byte in each node the user has reserved * for use by me */ nh_t nh_nodesperseg; /* an integral number of internal nodes must fit into a * segment */ size64_t nh_segsz; /* the backing store is partitoned into segment, which * can be mapped into VM windows by the win abstraction */ size_t nh_winmapmax; /* maximum number of windows which can be mapped */ size_t nh_nodealignsz; /* user's constraint on node alignment */ nh_t nh_freenh; /* handle of first node of singly-linked list of free nodes */ off64_t nh_firstsegoff; /* offset into backing store of the first segment */ nh_t nh_virgnh; /* handle of next virgin node */ int nh_segixshift; /* bitshift used to extract the segment index from an nh_t */ relnix_t nh_relnixmask; /* bitmask used to extract the node index from an nh_t * (relative to the start of a segment) */ }; typedef struct node_hdr node_hdr_t; static node_hdr_t *node_hdrp; static int node_fd; static inline segix_t nh2segix( nh_t nh ) { return nh >> node_hdrp->nh_segixshift; } static inline relnix_t nh2relnix( nh_t nh ) { return nh & node_hdrp->nh_relnixmask; } static inline void node_map_internal( nh_t nh, void **pp ) { win_map( nh2segix( nh ), pp ); if ( *pp != NULL ) { relnix_t relnix = nh2relnix( nh ); *pp = ( void * )( ( char * )( *pp ) + ( ( off64_t )relnix * node_hdrp->nh_nodesz ) ); } } /* ARGSUSED */ static inline void node_unmap_internal( nh_t nh, void **pp, bool_t freepr ) { #ifdef NODECHK register u_char_t hkp; register u_char_t hdlgen; register u_char_t nodegen; register u_char_t nodeunq; #endif /* NODECHK */ assert( pp ); assert( *pp ); assert( nh != NH_NULL ); /* convert the handle into an index */ #ifdef NODECHK hdlgen = HDLGETGEN( nh ); nh = HDLGETNHDL( nh ); #endif /* NODECHK */ assert( nh <= NH_MAX ); #ifdef NODECHK hkp = *( *( u_char_t ** )pp + node_hdrp->nh_nodehkix ); nodegen = HKPGETGEN( hkp ); assert( nodegen == hdlgen ); nodeunq = HKPGETUNQ( hkp ); if ( ! freepr ) { assert( nodeunq != NODEUNQFREE ); assert( nodeunq == NODEUNQALCD ); } else { assert( nodeunq != NODEUNQALCD ); assert( nodeunq == NODEUNQFREE ); } #endif /* NODECHK */ /* unmap the window containing the node */ win_unmap( nh2segix( nh ), pp ); /* zeros *pp */ } /* ARGSUSED */ bool_t node_init( int fd, off64_t off, size_t usrnodesz, ix_t nodehkix, size_t nodealignsz, size64_t vmsz, size64_t dirs_nondirs_cnt ) { size_t nodesz; size64_t segsz; nh_t nodesperseg; size_t max_segments; size_t winmapmax; size_t segcount; int segixshift; /* sanity checks */ assert( sizeof( node_hdr_t ) <= NODE_HDRSZ ); assert( sizeof( nh_t ) < sizeof( off64_t )); assert( sizeof( nh_t ) <= sizeof( segix_t )); assert( sizeof( nh_t ) <= sizeof( relnix_t )); assert( nodehkix < usrnodesz ); assert( usrnodesz >= sizeof( char * ) + 1 ); /* so node is at least big enough to hold * the free list linkage and the housekeeping byte */ assert( nodehkix > sizeof( char * )); /* since beginning of each node is used to * link it in the free list. */ /* adjust the user's node size to meet user's alignment constraint */ nodesz = ( usrnodesz + nodealignsz - 1 ) & ~( nodealignsz - 1 ); /* Calculate the node table params based on the number of inodes in the * dump, since that's all we know. Ideally we'd base this on the number * of dirents in the dump instead as there's a node per dirent. * * Due to virtual memory constraints and the fact that we don't know * the final node table size, we can't guarantee that the entire node * table can be mapped at once. Instead segments will be mapped using a * window abstraction. Some operations require WINMAP_MIN nodes to be * referenced at a time, therefore we must ensure that this many * segments fit in virtual memory. * * nodesperseg must be a power of two. Earlier versions did not enforce * this, and profiling showed that nearly 50% of cpu time during the * node table construction was consumed doing division and modulo to * convert an nh_t to a segment index and node offset. By making * nodesperseg a power of two we can use shift and bitwise-and instead. * * Each segment must hold an integral number of nodes and be an integral * number of pages. #1 ensures this except when nodesperseg is small, so * the smallest allowed segsz is pgsz * nodesz (i.e., nodesperseg == * pgsz). However this is of no consequence as we enforce a larger * minimum nodesperseg (NODESPERSEG_MIN) anyway in order to place a * reasonable cap on the max number of segments. */ assert( NODESPERSEG_MIN >= pgsz ); if ( vmsz < WINMAP_MIN * NODESPERSEG_MIN * nodesz ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "not enough virtual memory for node abstraction: " "remaining-vsmz=%llu need=%llu\n"), vmsz, WINMAP_MIN * NODESPERSEG_MIN * nodesz ); return BOOL_FALSE; } /* This is checked as nodes are allocated as well (remember that * dirs_nondirs_cnt may be less than the number of nodes/dirents). * Checking this here prevents potential overflow in the logic below. */ if ( dirs_nondirs_cnt > NH_MAX ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "dump contains %llu inodes, restore can only handle %u\n"), dirs_nondirs_cnt, NH_MAX ); return BOOL_FALSE; } for ( winmapmax = 0, segcount = 1; winmapmax < WINMAP_MIN; segcount <<= 1 ) { nodesperseg = max( dirs_nondirs_cnt / segcount, NODESPERSEG_MIN ); /* nodesperseg must be a power of 2 */ for ( segixshift = 0; ( 1ULL << segixshift ) < nodesperseg; segixshift++ ); /* rounding up to a power of 2 may have caused overflow */ if ( ( 1ULL << segixshift ) > NH_MAX ) segixshift--; nodesperseg = 1UL << segixshift; max_segments = 1UL << ( NBBY * sizeof(nh_t) - segixshift ); segsz = nodesperseg * nodesz; /* max number of segments that will fit in virtual memory, * capped at the max possible number of segments */ winmapmax = min( vmsz / segsz, max_segments ); } /* map the abstraction header */ assert( ( NODE_HDRSZ & pgmask ) == 0 ); assert( ! ( NODE_HDRSZ % pgsz )); assert( off <= OFF64MAX ); assert( ! ( off % ( off64_t )pgsz )); node_hdrp = ( node_hdr_t * )mmap_autogrow( NODE_HDRSZ, fd, off ); if ( node_hdrp == (node_hdr_t *)-1 ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "unable to map node hdr of size %d: %s\n"), NODE_HDRSZ, strerror( errno )); return BOOL_FALSE; } /* initialize and save persistent context. */ node_hdrp->nh_nodesz = nodesz; node_hdrp->nh_nodehkix = nodehkix; node_hdrp->nh_segsz = segsz; node_hdrp->nh_winmapmax = winmapmax; node_hdrp->nh_nodesperseg = nodesperseg; node_hdrp->nh_nodealignsz = nodealignsz; node_hdrp->nh_freenh = NH_NULL; node_hdrp->nh_firstsegoff = off + ( off64_t )NODE_HDRSZ; node_hdrp->nh_virgnh = 0; node_hdrp->nh_segixshift = segixshift; node_hdrp->nh_relnixmask = nodesperseg - 1; /* save transient context */ node_fd = fd; /* initialize the window abstraction */ win_init( fd, node_hdrp->nh_firstsegoff, segsz, winmapmax ); /* announce the results */ mlog( MLOG_DEBUG | MLOG_TREE, "node_init:" " vmsz = %llu (0x%llx)" " segsz = %llu (0x%llx)" " nodesperseg = %u (0x%x)" " winmapmax = %lu (0x%lx)" "\n", vmsz, vmsz, segsz, segsz, nodesperseg, nodesperseg, winmapmax, winmapmax ); return BOOL_TRUE; } bool_t node_sync( int fd, off64_t off ) { /* sanity checks */ assert( sizeof( node_hdr_t ) <= NODE_HDRSZ ); /* map the abstraction header */ assert( ( NODE_HDRSZ & pgmask ) == 0 ); assert( off <= ( off64_t )OFF64MAX ); assert( ! ( off % ( off64_t )pgsz )); node_hdrp = ( node_hdr_t * )mmap_autogrow( NODE_HDRSZ, fd, off ); if ( node_hdrp == (node_hdr_t *)-1 ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "unable to map node hdr of size %d: %s\n"), NODE_HDRSZ, strerror( errno )); return BOOL_FALSE; } /* save transient context */ node_fd = fd; /* initialize the window abstraction */ win_init( fd, node_hdrp->nh_firstsegoff, node_hdrp->nh_segsz, node_hdrp->nh_winmapmax ); return BOOL_TRUE; } nh_t node_alloc( void ) { u_char_t *p; nh_t nh; #ifdef NODECHK u_char_t *hkpp; u_char_t gen = 0; u_char_t unq; #endif /* NODECHK */ /* if there's a node available on the free list, use it. * otherwise get the next one from the current virgin segment, * or allocate a new virgin segment if the current one is depleted. */ if ( node_hdrp->nh_freenh != NH_NULL ) { nh_t *linkagep; nh = node_hdrp->nh_freenh; node_map_internal( nh, ( void ** )&p ); if (p == NULL) return NH_NULL; #ifdef NODECHK hkpp = p + node_hdrp->nh_nodehkix; gen = ( u_char_t )( HKPGETGEN( *p ) + ( u_char_t )1 ); unq = HKPGETUNQ( *hkpp ); assert( unq != NODEUNQALCD ); assert( unq == NODEUNQFREE ); #endif /* NODECHK */ /* adjust the free list */ linkagep = ( nh_t * )p; node_hdrp->nh_freenh = *linkagep; node_unmap_internal( nh, ( void ** )&p, BOOL_TRUE ); } else { if ( nh2relnix( node_hdrp->nh_virgnh ) == 0 ) { /* need to start a new virgin segment */ int rval; off64_t new_seg_off = node_hdrp->nh_firstsegoff + ( off64_t )nh2segix( node_hdrp->nh_virgnh ) * ( off64_t )node_hdrp->nh_segsz; assert( new_seg_off <= OFF64MAX - ( off64_t )node_hdrp->nh_segsz ); mlog( MLOG_DEBUG, "pre-growing new node array segment at %lld " "size %lld\n", new_seg_off, ( off64_t )node_hdrp->nh_segsz ); rval = ftruncate64( node_fd, new_seg_off + ( off64_t )node_hdrp->nh_segsz ); if ( rval ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_TREE, _( "unable to autogrow node segment %u: " "%s (%d)\n"), nh2segix( node_hdrp->nh_virgnh ), strerror( errno ), errno ); } } nh = node_hdrp->nh_virgnh++; } /* build a handle for node */ if ( nh > NH_MAX ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "dump contains too many dirents, " "restore can only handle %llu\n"), NH_MAX ); return NH_NULL; } #ifdef NODECHK node_map_internal( nh , ( void ** )&p ); if (p == NULL) abort(); hkpp = p + ( int )node_hdrp->nh_nodehkix; nh = HDLMKHDL( gen, nh ); *hkpp = HKPMKHKP( gen, NODEUNQALCD ); node_unmap_internal( nh, ( void ** )&p, BOOL_FALSE ); #endif /* NODECHK */ return nh; } void * node_map( nh_t nh ) { u_char_t *p; #ifdef NODECHK register u_char_t hkp; register u_char_t hdlgen; register u_char_t nodegen; register u_char_t nodeunq; #endif /* NODECHK */ assert( nh != NH_NULL ); /* convert the handle into an index */ #ifdef NODECHK hdlgen = HDLGETGEN( nh ); nh = HDLGETNHDL( nh ); #endif /* NODECHK */ assert( nh <= NH_MAX ); /* map in */ p = 0; /* keep lint happy */ node_map_internal( nh, ( void ** )&p ); if (p == NULL) return NULL; #ifdef NODECHK hkp = *( p + node_hdrp->nh_nodehkix ); nodegen = HKPGETGEN( hkp ); nodeunq = HKPGETUNQ( hkp ); assert( nodegen == hdlgen ); assert( nodeunq != NODEUNQFREE ); assert( nodeunq == NODEUNQALCD ); #endif /* NODECHK */ return ( void * )p; } void node_unmap( nh_t nh, void **pp ) { node_unmap_internal( nh, pp, BOOL_FALSE ); } void node_free( nh_t *nhp ) { nh_t nh; u_char_t *p; register nh_t *linkagep; #ifdef NODECHK register u_char_t *hkpp; register u_char_t hdlgen; register u_char_t nodegen; register u_char_t nodeunq; #endif /* NODECHK */ assert( nhp ); nh = *nhp; assert( nh != NH_NULL ); /* convert the handle into an index */ #ifdef NODECHK hdlgen = HDLGETGEN( nh ); nh = HDLGETNHDL( nh ); #endif /* NODECHK */ assert( nh <= NH_MAX ); /* map in */ p = ( u_char_t * )node_map( nh ); if (p == NULL){ *nhp = NH_NULL; return; } #ifdef NODECHK /* fix up unique field */ hkpp = p + node_hdrp->nh_nodehkix; nodegen = HKPGETGEN( *hkpp ); nodeunq = HKPGETUNQ( *hkpp ); assert( nodegen == hdlgen ); assert( nodeunq != NODEUNQFREE ); assert( nodeunq == NODEUNQALCD ); *hkpp = HKPMKHKP( nodegen, NODEUNQFREE ); #endif /* NODECHK */ /* put node on free list */ linkagep = ( nh_t * )p; *linkagep = node_hdrp->nh_freenh; node_hdrp->nh_freenh = nh; /* map out */ node_unmap_internal( nh, ( void ** )&p, BOOL_TRUE ); /* invalidate caller's handle */ *nhp = NH_NULL; } xfsdump-3.1.6+nmu1/restore/tree.c0000644000000000000000000033407212620476160013554 0ustar /* * Copyright (c) 2000-2002 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "types.h" #include "exit.h" #include "cldmgr.h" #include "path.h" #include "openutil.h" #include "getopt.h" #include "stream.h" #include "mlog.h" #include "dlog.h" #include "global.h" #include "drive.h" #include "media.h" #include "content.h" #include "content_inode.h" #include "inomap.h" #include "namreg.h" #include "dirattr.h" #include "bag.h" #include "node.h" #include "tree.h" #include "libgen.h" #include "mmap.h" #include "exit.h" /* structure definitions used locally ****************************************/ /* name of persistent state file */ #define PERS_NAME "tree" /* orphanage specifics. ino must be otherwise unused in the dump source fs. * zero works. */ #define ORPH_INO 0 #define ORPH_NAME "orphanage" /* VM budgeting - give hash array one sixteenth, rest goes to node array */ #define HASHSZ_PERVM 16 /* reserve the first page for persistent state */ struct treePersStorage { xfs_ino_t p_rootino; /* ino of root */ nh_t p_rooth; /* handle of root node */ nh_t p_orphh; /* handle to orphanage node */ size64_t p_hashsz; /* size of hash array (private to hash abstraction) */ size_t p_hashmask; /* hash mask (private to hash abstraction) */ bool_t p_ownerpr; /* restore directory owner/group attributes */ bool_t p_fullpr; /* restoring a full level 0 non-resumed dump (can skip * some steps) */ bool_t p_ignoreorphpr; /* set if positive subtree or interactive */ bool_t p_restoredmpr; /* restore DMI event settings */ bool_t p_truncategenpr; /* truncate inode generation number (for compatibility * with xfsdump format 2 and earlier) */ }; typedef struct treePersStorage treepers_t; #define PERSSZ perssz /* interactive dialog transient state */ #define INTER_ARGMAX 10 /* max number of args to interactive cmds */ struct inter { size_t i_argc; char *i_argv[ INTER_ARGMAX ]; nh_t i_cwdh; char i_name[ NAME_MAX + 1 ]; }; typedef struct inter inter_t; /* transient state */ struct tran { bool_t t_toconlypr; /* just display table of contents; don't restore files */ char *t_hkdir; /* full absolute pathname of housekeeping directory */ char *t_dstdir; /* full absolute pathname of destination directory */ bool_t t_dstdirisxfspr; /* destination directory is an xfs filesystem; xfs-specific * calls can be made when needed. */ char *t_orphdir; /* full absolute pathname of orphanage directory */ char *t_hksubtree; /* if non-NULL, is path of hkdir relative to dstdir. * don't restore there. */ int t_persfd; /* file descriptor of the persistent state file */ nh_t *t_hashp; /* pointer to mapped hash array (private to hash abstraction) */ char t_namebuf[ NAME_MAX + 1 ]; /* to hold names temporarily retrieved from name registry */ inter_t t_inter; /* context for interactive subtree selection */ }; typedef struct tran tran_t; /* node structure. each node represents a directory entry */ #define NODESZ 56 struct node { xfs_ino_t n_ino; /* 8 8 ino */ nrh_t n_nrh; /* 8 16 handle to name in name registry */ dah_t n_dah; /* 4 20 handle to directory attributes */ nh_t n_hashh; /* 4 24 hash array */ nh_t n_parh; /* 4 28 parent */ nh_t n_sibh; /* 4 32 sibling list */ nh_t n_sibprevh; /* 4 36 prev sibling list - dbl link list */ nh_t n_cldh; /* 4 40 children list */ nh_t n_lnkh; /* 4 44 hard link list */ gen_t n_gen; /* 4 48 generation count mod 0x10000 */ u_char_t n_flags; /* 1 49 action and state flags */ u_char_t n_nodehkbyte; /* 1 50 given to node abstraction */ char n_pad[6]; /* 6 56 */ }; typedef struct node node_t; #define NF_REAL ( 1 << 0 ) /* set when the corresponding file/dir has been created in * the restore destination. */ #define NF_SUBTREE ( 1 << 1 ) /* marks nodes in the selected subtrees. */ #define NF_REFED ( 1 << 2 ) /* indicates node is still referenced according to incremental/resumed * dump. used to detect dirents no longer used. prior to restoring * a dump session, this flag is cleared in all nodes. during the dirent * restoral, it is set. it may also be set during the adjustment * for referenced but undumped directories. NOTE: nodes in the * orphanage NEVER have this flag set. */ #define NF_WRITTEN ( 1 << 3 ) /* set as soon as a non-dir node restore is begun. allows * overwrite inhibit options to work with segmented files */ #define NF_ISDIR ( 1 << 4 ) /* indicates this node is a directory. set when a directory is taken * from the dirdump. */ #define NF_DUMPEDDIR ( 1 << 5 ) /* indicates this node is a directory present in the current dirdump. * at beginning of session, this flag is cleared in all nodes. * then as each directory dump is read from media, the flag * is set from the corresponding node. this allows adjustments to * the NF_REFED flag: if a directory was not dumped, either it no * longer exists or it has not changed. if it is referenced, we assume * it exists, in which case if it is not dumped then all of its entries * are referenced as well. */ #define NF_NEWORPH ( 1 << 6 ) /* cleared from all nodes in the orphanage before a dump is applied. * set if a dir is seen in the dirdump but no node exists for it. * cleared if that dir is adopted subsequently during the dirdump. * set if a nondir is seen in the nondir dump but no node exists for * it. in either case a node is created and placed in the orphanage. * during rmdir/unlink processing, nodes so marked are left alone. * since the flag is cleared at the beginning of the next increment, * old orphans had better be adopted, otherwise they will be unlinked. */ /* link list iterator context */ struct link_iter_context { nh_t li_headh; /* head of hard link list */ nh_t li_prevh; /* next to last node returned by _next() */ nh_t li_lasth; /* last node returned by _next() */ bool_t li_donepr; /* set as soon as last.next null */ }; typedef struct link_iter_context link_iter_context_t; /* used for caching parent pathname from previous Node2path result */ struct path_cache { nh_t nh; int len; char buf[MAXPATHLEN]; }; typedef struct path_cache path_cache_t; /* declarations of externally defined global symbols *************************/ extern void usage( void ); extern size_t pgsz; extern size_t pgmask; extern bool_t restore_rootdir_permissions; /* forward declarations of locally defined static functions ******************/ static nh_t Node_alloc( xfs_ino_t ino, gen_t gen, nrh_t nrh, dah_t dah, size_t flags ); static void Node_free( nh_t *nhp ); static node_t * Node_map( nh_t nh ); static void Node_unmap( nh_t nh, node_t **npp ); static int Node2path_recurse( nh_t nh, char *buf, int bufsz, int level ); static void adopt( nh_t parh, nh_t cldh, nrh_t nrh ); static nrh_t disown( nh_t cldh ); static void selsubtree( nh_t nh, bool_t sensepr ); static void selsubtree_recurse_down( nh_t nh, bool_t sensepr ); static nh_t link_hardh( xfs_ino_t ino, gen_t gen ); static nh_t link_nexth( nh_t nh ); static nh_t link_matchh( nh_t hardh, nh_t parh, char *name ); static void link_in( nh_t nh ); static void link_out( nh_t nh ); static void link_headiter( bool_t ( * cbfp )( void *contextp, nh_t hardh ), void *contextp ); static void link_iter_init( link_iter_context_t *link_iter_contextp, nh_t hardheadh ); static nh_t link_iter_next( link_iter_context_t *link_iter_contextp ); void link_iter_unlink( link_iter_context_t *link_iter_contextp, nh_t nh ); static bool_t hash_init( size64_t vmsz, size64_t dircnt, size64_t nondircnt, char *perspath ); static bool_t hash_sync( char *perspath ); static inline size_t hash_val(xfs_ino_t ino, size_t hashmask); static void hash_in( nh_t nh ); static void hash_out( nh_t nh ); static nh_t hash_find( xfs_ino_t ino, gen_t gen ); static void hash_iter( bool_t ( * cbfp )( void *contextp, nh_t hashh ), void *contextp ); static void setdirattr( dah_t dah, char *path ); static bool_t tsi_walkpath( char *arg, nh_t rooth, nh_t cwdh, dlog_pcbp_t pcb, void *pctxp, nh_t *namedhp, nh_t *parhp, nh_t *cldhp, xfs_ino_t *inop, bool_t *isdirprp, bool_t *isselpr ); static bool_t Node2path( nh_t nh, char *path, char *errmsg ); static bool_t tree_setattr_recurse( nh_t parh, char *path ); static void tsi_cmd_pwd_recurse( void *ctxp, dlog_pcbp_t pcb, void *pctxp, nh_t nh ); static int mkdir_r(char *path); #ifdef TREE_CHK static bool_t Node_chk( nh_t nh, nh_t *nexthashhp, nh_t *nextlnkhp ); static bool_t tree_chk2( void ); #endif /* TREE_CHK */ /* definition of locally defined global variables ****************************/ /* definition of locally defined static variables *****************************/ static treepers_t *persp = 0; static tran_t *tranp = 0; static char *persname = PERS_NAME; static char *orphname = ORPH_NAME; static xfs_ino_t orphino = ORPH_INO; /* definition of locally defined global functions ****************************/ /* ARGSUSED */ bool_t tree_init( char *hkdir, char *dstdir, bool_t toconlypr, bool_t ownerpr, xfs_ino_t rootino, xfs_ino_t firstino, xfs_ino_t lastino, size64_t dircnt, size64_t nondircnt, size64_t vmsz, bool_t fullpr, bool_t restoredmpr, bool_t dstdirisxfspr, uint32_t dumpformat, bool_t truncategenpr ) { off64_t nodeoff; char *perspath; bool_t ok; int rval; /* sanity checks */ assert( ! ( PERSSZ % pgsz )); assert( sizeof( persp ) <= PERSSZ ); assert( sizeof( node_t ) <= NODESZ ); assert( ! persp ); assert( ! tranp ); /* allocate transient state */ tranp = ( tran_t * )calloc( 1, sizeof( tran_t )); assert( tranp ); tranp->t_toconlypr = toconlypr; tranp->t_hkdir = hkdir; tranp->t_dstdir = dstdir; tranp->t_dstdirisxfspr = dstdirisxfspr; /* allocate a char string buffer to hold the abs. pathname * of the orphanage directory file. load it with the pathname. */ tranp->t_orphdir = open_pathalloc( tranp->t_dstdir, orphname, 0 ); /* determine if housekeeping dir is within the destination. * generate a relative path containing the difference, * else null. will not restore into there. */ if ( strcmp( dstdir, "." )) { tranp->t_hksubtree = path_diff( hkdir, dstdir ); } else { tranp->t_hksubtree = 0; } /* create an orphanage, if it already exists, complain. * not needed if just a table-of-contents restore. */ if ( ! tranp->t_toconlypr ) { rval = mkdir( tranp->t_orphdir, S_IRWXU ); if ( rval ) { if ( errno == EEXIST ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_TREE, _( "%s already exists: " "rm -rf prior to initating restore\n"), tranp->t_orphdir ); } else { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_TREE, _( "unable to create %s: %s\n"), tranp->t_orphdir, strerror( errno )); } return BOOL_FALSE; } } /* build a full pathname to pers. state file */ perspath = open_pathalloc( tranp->t_hkdir, persname, 0 ); /* create the persistent state file */ ( void )unlink( perspath ); tranp->t_persfd = open( perspath, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR ); if ( tranp->t_persfd < 0 ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_TREE, _( "could not open %s: %s\n"), perspath, strerror( errno )); return BOOL_FALSE; } /* mmap the persistent state */ assert( ! ( PERSSZ % pgsz )); persp = ( treepers_t * ) mmap_autogrow( PERSSZ, tranp->t_persfd, ( off64_t )0 ); if ( persp == ( treepers_t * )-1 ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_TREE, _( "unable to map %s: %s\n"), perspath, strerror( errno )); return BOOL_FALSE; } /* create the hash abstraction. it will map more of the * persistent state file. */ ok = hash_init( vmsz / HASHSZ_PERVM, dircnt, nondircnt, perspath ); if ( ! ok ) { return BOOL_FALSE; } /* initialize the node abstraction. let it's use of backing store * begin immediately after the hash abstraction. give it the remainder * of vm. */ assert( persp->p_hashsz <= ( size64_t )( OFF64MAX - ( off64_t )PERSSZ)); nodeoff = ( off64_t )PERSSZ + ( off64_t )persp->p_hashsz; assert( vmsz > ( size64_t )nodeoff ); ok = node_init( tranp->t_persfd, nodeoff, NODESZ, ( ix_t )offsetofmember( node_t, n_nodehkbyte ), sizeof( size64_t ), /* node alignment */ vmsz - ( size64_t )nodeoff, dircnt + nondircnt ); if ( ! ok ) { return BOOL_FALSE; } /* extract the root ino and allocate a node for * the root and for the orphanage. place both nodes * in the hash list. make the orphanage a child of * root, and indicate he is real. * * Note that we assume that the root inode always * has a generation count of zero - which is true. */ persp->p_rootino = rootino; persp->p_rooth = Node_alloc( rootino, 0, /* gen cnt */ NRH_NULL, DAH_NULL, NF_ISDIR | NF_REAL ); if (persp->p_rooth == NH_NULL) return BOOL_FALSE; link_in( persp->p_rooth ); persp->p_orphh = Node_alloc( orphino, 0, /* gen cnt */ namreg_add( orphname, strlen( orphname )), DAH_NULL, NF_ISDIR | NF_REAL ); if (persp->p_orphh == NH_NULL) return BOOL_FALSE; link_in( persp->p_orphh ); adopt( persp->p_rooth, persp->p_orphh, NRH_NULL ); /* record if we should attempt to restore original owner/group */ persp->p_ownerpr = ownerpr; /* record if this is a full dump. can skip link processing if so */ persp->p_fullpr = fullpr; /* record if DMI event settings should be restored */ persp->p_restoredmpr = restoredmpr; /* record if truncated generation numbers are required */ if ( dumpformat < GLOBAL_HDR_VERSION_3 ) { persp->p_truncategenpr = BOOL_TRUE; mlog( MLOG_NORMAL | MLOG_DEBUG | MLOG_TREE, _( "dump format version %u used truncated inode generation numbers\n"), dumpformat ); } else if ( truncategenpr ) { persp->p_truncategenpr = BOOL_TRUE; mlog( MLOG_NORMAL | MLOG_DEBUG | MLOG_TREE, _( "forcing use of truncated inode generation numbers\n")); } else { persp->p_truncategenpr = BOOL_FALSE; } return BOOL_TRUE; } bool_t tree_sync( char *hkdir, char *dstdir, bool_t toconlypr, bool_t fullpr, bool_t dstdirisxfspr ) { off64_t nodeoff; char *perspath; bool_t ok; int rval; if ( persp ) { return BOOL_TRUE; } /* sanity checks */ assert( ! ( PERSSZ % pgsz )); assert( sizeof( persp ) <= PERSSZ ); assert( sizeof( node_t ) <= NODESZ ); assert( ! persp ); assert( ! tranp ); /* allocate transient state */ tranp = ( tran_t * )calloc( 1, sizeof( tran_t )); assert( tranp ); tranp->t_toconlypr = toconlypr; tranp->t_hkdir = hkdir; tranp->t_dstdir = dstdir; tranp->t_dstdirisxfspr = dstdirisxfspr; /* allocate a char string buffer to hold the abs. pathname * of the orphanage directory file. load it with the pathname. */ tranp->t_orphdir = open_pathalloc( tranp->t_dstdir, orphname, 0 ); /* determine if housekeeping dir is within the destination. * generate a relative path containing the difference, * else null. will not restore into there. */ if ( strcmp( dstdir, "." )) { tranp->t_hksubtree = path_diff( hkdir, dstdir ); } else { tranp->t_hksubtree = 0; } /* re-create the orphanage (in case someone rmdir'ed it) */ rval = mkdir( tranp->t_orphdir, S_IRWXU ); if ( rval && errno != EEXIST ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_TREE, _( "unable to recreate %s: %s\n"), tranp->t_orphdir, strerror( errno )); return BOOL_FALSE; } /* build a full pathname to pers. state file */ perspath = open_pathalloc( tranp->t_hkdir, persname, 0 ); /* re-open the persistent state file */ tranp->t_persfd = open( perspath, O_RDWR ); if ( tranp->t_persfd < 0 ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_TREE, _( "could not open %s: %s\n"), perspath, strerror( errno )); return BOOL_FALSE; } /* mmap the persistent state */ assert( ! ( PERSSZ % pgsz )); persp = ( treepers_t * ) mmap_autogrow( PERSSZ, tranp->t_persfd, ( off64_t )0 ); if ( persp == ( treepers_t * )-1 ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_TREE, _( "unable to map %s: %s\n"), perspath, strerror( errno )); return BOOL_FALSE; } /* update the fullpr field of the persistent state to match * the input of our caller. */ persp->p_fullpr = fullpr; /* regardless of the format of this dump, if the previously applied * dump used truncated generation numbers, then we need to as well. */ if ( persp->p_truncategenpr ) { mlog( MLOG_NORMAL | MLOG_DEBUG | MLOG_TREE, _( "using truncated inode generation numbers for " "compatibility with previously applied restore\n") ); } /* rsynchronize with the hash abstraction. it will map more of the * persistent state file. */ ok = hash_sync( perspath ); if ( ! ok ) { return BOOL_FALSE; } /* synchronize with the node abstraction. */ assert( persp->p_hashsz <= ( size64_t )( OFF64MAX - ( off64_t )PERSSZ)); nodeoff = ( off64_t )PERSSZ + ( off64_t )persp->p_hashsz; ok = node_sync( tranp->t_persfd, nodeoff ); if ( ! ok ) { return BOOL_FALSE; } /* extract the root ino and allocate a node for * the root and for the orphanage. place both nodes * in the hash list. make the orphanage a child of * root, and indicate he is real. */ return BOOL_TRUE; } bool_t tree_check_dump_format( uint32_t dumpformat ) { if ( dumpformat < GLOBAL_HDR_VERSION_3 && !persp->p_truncategenpr ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_TREE, _( "encountered dump format %d after a " "restore of format %d or newer\n"), dumpformat, GLOBAL_HDR_VERSION_3 ); mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_TREE, _( "to restore this series of dumps, use the -%c " "option on the first restore\n"), GETOPT_FMT2COMPAT ); return BOOL_FALSE; } return BOOL_TRUE; } /* recursively descend the tree clearing REFED and DIRDUMPED and NEWORPH * flags. force the orphanage to be refed and dumped, so we won't try * to orphan it, and so things added to it won't look like they are * referenced during ref adj. also null dirattr handles, since they are * not retained across dump session restores. */ static void tree_marknoref_recurse( nh_t parh ); void tree_marknoref( void ) { tree_marknoref_recurse( persp->p_rooth ); { node_t *orphp; orphp = Node_map( persp->p_orphh ); orphp->n_flags |= ( NF_REFED | NF_DUMPEDDIR ); assert( orphp->n_dah == DAH_NULL ); Node_unmap( persp->p_orphh, &orphp ); } } static void tree_marknoref_recurse( nh_t parh ) { nh_t cldh; { node_t *parp; parp = Node_map( parh ); parp->n_flags &= ~( NF_REFED | NF_DUMPEDDIR | NF_NEWORPH ); parp->n_dah = DAH_NULL; cldh = parp->n_cldh; Node_unmap( parh, &parp ); } while ( cldh != NH_NULL ) { node_t *cldp; nh_t nextcldh; tree_marknoref_recurse( cldh ); /* RECURSION */ cldp = Node_map( cldh ); nextcldh = cldp->n_sibh; Node_unmap( cldh, &cldp ); cldh = nextcldh; } } void tree_markallsubtree( bool_t sensepr ) { if ( ! sensepr ) { persp->p_ignoreorphpr = BOOL_TRUE; } selsubtree( persp->p_rooth, sensepr ); } nh_t tree_begindir( filehdr_t *fhdrp, dah_t *dahp ) { nh_t hardh; xfs_ino_t ino = fhdrp->fh_stat.bs_ino; gen_t gen = fhdrp->fh_stat.bs_gen; dah_t dah; if ( persp->p_truncategenpr ) { gen = BIGGEN2GEN( gen ); } /* sanity check - orphino is supposed to be an unused ino! */ assert( ino != orphino ); /* lookup head of hardlink list */ hardh = link_hardh( ino, gen ); assert( ino != persp->p_rootino || hardh == persp->p_rooth ); /* already present */ if ( hardh != NH_NULL ) { node_t *hardp; hardp = Node_map( hardh ); if ( ! ( hardp->n_flags & NF_ISDIR )) { /* case 1: previously seen as dirent, now know is dir */ mlog( MLOG_TRACE | MLOG_TREE, "directory %llu %u (%u): " "upgrading to dir\n", ino, gen, fhdrp->fh_stat.bs_gen ); if ( ! tranp->t_toconlypr ) { assert( hardp->n_dah == DAH_NULL ); hardp->n_dah = dirattr_add( fhdrp ); } } else if ( ! tranp->t_toconlypr && hardp->n_dah == DAH_NULL ) { /* case 2: node is a dir, but had thrown away dirattr */ mlog( MLOG_TRACE | MLOG_TREE, "directory %llu %u (%u): " "updating\n", ino, gen, fhdrp->fh_stat.bs_gen ); hardp->n_dah = dirattr_add( fhdrp ); } else { /* case 3: already has dirattr; must be restart */ mlog( MLOG_TRACE | MLOG_TREE, "directory %llu %u (%u): " "retaining\n", ino, gen, fhdrp->fh_stat.bs_gen ); } hardp->n_flags |= NF_ISDIR; hardp->n_flags |= NF_DUMPEDDIR; *dahp = hardp->n_dah; Node_unmap( hardh, &hardp ); } else { /* case 4: first time seen */ mlog( MLOG_TRACE | MLOG_TREE, "directory %llu %u (%u): " "new\n", ino, gen, fhdrp->fh_stat.bs_gen ); if ( ! tranp->t_toconlypr ) { dah = dirattr_add( fhdrp ); } else { dah = DAH_NULL; } hardh = Node_alloc( ino, gen, NRH_NULL, dah, NF_ISDIR | NF_NEWORPH ); if (hardh == NH_NULL) return NH_NULL; link_in( hardh ); adopt( persp->p_orphh, hardh, NRH_NULL ); *dahp = dah; } return hardh; } rv_t tree_addent( nh_t parh, xfs_ino_t ino, gen_t gen, char *name, size_t namelen ) { nh_t hardh; if ( persp->p_truncategenpr ) { gen = BIGGEN2GEN( gen ); } /* sanity check - orphino is supposed to be an unused ino! */ assert( ino != orphino ); /* don't allow entries named "orphanage" under root to be added */ if ( parh == persp->p_rooth && !strcmp( name, orphname )) { mlog( MLOG_DEBUG | MLOG_TREE, "dirent %s %llu %u: " "skipping (reserved)\n", name, ino, gen ); return RV_OK; } /* if the parent is null, just ignore */ if ( parh == NH_NULL ) { mlog( MLOG_DEBUG | MLOG_TREE, "dirent %s %llu %u: " "skipping (null parent)\n", name, ino, gen ); return RV_OK; } /* see if one or more links to this ino already exist. */ hardh = link_hardh( ino, gen ); if ( hardh != NH_NULL ) { node_t *hardp; hardp = Node_map( hardh ); if ( hardp->n_flags & NF_ISDIR ) { nh_t renameh; node_t *renamep; /* REFERENCED */ int namebuflen; hardp->n_flags |= NF_REFED; if ( hardp->n_parh == persp->p_orphh ) { /* dir now seen as entry * if in orph but REAL, must be pending rename */ if ( ( hardp->n_flags & NF_REAL ) && hardp->n_lnkh == NH_NULL ) { hardp->n_lnkh = Node_alloc( ino, gen, NRH_NULL, DAH_NULL, 0 ); if (hardp->n_lnkh == NH_NULL) return RV_ERROR; } if ( hardp->n_lnkh != NH_NULL ) { assert( hardp->n_flags & NF_REAL ); renameh = hardp->n_lnkh; renamep = Node_map( renameh ); if ( renamep->n_parh == NH_NULL ) { mlog( MLOG_DEBUG | MLOG_TREE, "dirent %s %llu %u: " "adopting (dir par)\n", name, ino, gen ); renamep->n_parh = parh; } if ( renamep->n_parh != parh ) { mlog( MLOG_DEBUG | MLOG_TREE, "dirent %s %llu %u: " "re-adopting (dir par)\n", name, ino, gen ); renamep->n_parh = parh; } if ( renamep->n_nrh != NRH_NULL ) { namebuflen = namreg_get( renamep->n_nrh, tranp->t_namebuf, sizeof( tranp->t_namebuf )); assert( namebuflen > 0 ); if ( strcmp( name, tranp->t_namebuf )) { mlog( MLOG_DEBUG | MLOG_TREE, "dirent %s " "%llu %u: " "re-adopting " "(dir name): " "was %s\n", name, ino, gen, tranp->t_namebuf ); namreg_del( renamep->n_nrh ); renamep->n_nrh = NRH_NULL; } } if ( renamep->n_nrh == NRH_NULL ) { renamep->n_nrh = namreg_add( name, namelen ); renamep->n_parh = parh; } Node_unmap( renameh, &renamep ); } else { nrh_t nrh; hardp->n_flags &= ~NF_NEWORPH; assert( hardp->n_nrh == NRH_NULL ); assert( hardp->n_parh != NH_NULL ); nrh = disown( hardh ); assert( nrh == NRH_NULL ); nrh = namreg_add( name, namelen ); adopt( parh, hardh, nrh ); mlog( MLOG_DEBUG | MLOG_TREE, "dirent %s %llu %u: " "updating (dir)\n", name, ino, gen ); } } else { assert( hardp->n_nrh != NRH_NULL ); namebuflen = namreg_get( hardp->n_nrh, tranp->t_namebuf, sizeof( tranp->t_namebuf )); assert( namebuflen > 0 ); if ( hardp->n_parh == parh && ! strcmp( tranp->t_namebuf, name )) { /* dir seen as entry again */ if ( hardp->n_lnkh != NH_NULL ) { /* rescind rename */ mlog( MLOG_DEBUG | MLOG_TREE, "dirent %s %llu %u: " "rescind rename (dir)\n", name, ino, gen ); Node_free( &hardp->n_lnkh ); } else { mlog( MLOG_DEBUG | MLOG_TREE, "dirent %s %llu %u: " "retaining (dir)\n", name, ino, gen ); } } else { /* dir rename */ nh_t renameh; node_t *renamep; if ( hardp->n_lnkh == NH_NULL ) { renameh = Node_alloc( ino, gen, NRH_NULL, DAH_NULL, 0 ); if (renameh == NH_NULL) return RV_ERROR; hardp->n_lnkh = renameh; } else { mlog( MLOG_DEBUG | MLOG_TREE, "dirent %s %llu %u: " "re-renaming\n", name, ino, gen ); renameh = hardp->n_lnkh; renamep = Node_map( renameh ); renamep->n_parh = NH_NULL; if ( renamep->n_nrh != NRH_NULL ) { namreg_del( renamep->n_nrh ); } renamep->n_nrh = NRH_NULL; Node_unmap( renameh, &renamep ); } renamep = Node_map( renameh ); assert( hardp->n_parh != NH_NULL ); if ( hardp->n_parh != parh ) { /* different parent */ renamep->n_parh = parh; mlog( MLOG_DEBUG | MLOG_TREE, "dirent %s %llu %u: " "renaming (parent)\n", name, ino, gen ); } if ( strcmp( tranp->t_namebuf, name )) { /* different name */ renamep->n_nrh = namreg_add( name, namelen ); mlog( MLOG_DEBUG | MLOG_TREE, "dirent %s %llu %u: " "renaming (name)\n", name, ino, gen ); } Node_unmap( renameh, &renamep ); } } } else { nh_t matchh; matchh = link_matchh( hardh, parh, name ); if ( matchh != NH_NULL ) { /* entry already exists */ node_t *matchp; matchp = Node_map( matchh ); matchp->n_flags |= NF_REFED; Node_unmap( matchh, &matchp ); mlog( MLOG_DEBUG | MLOG_TREE, "dirent %s %llu %u: " "retaining (nondir)\n", name, ino, gen ); } else { /* case 5: new hard link */ nrh_t nrh; nh_t linkh; nrh = namreg_add( name, namelen ); linkh = Node_alloc( ino, gen, NRH_NULL, DAH_NULL, NF_REFED ); if (linkh == NH_NULL) return RV_ERROR; link_in( linkh ); adopt( parh, linkh, nrh ); mlog( MLOG_DEBUG | MLOG_TREE, "dirent %s %llu %u: " "adding (link)\n", name, ino, gen ); } } Node_unmap( hardh, &hardp ); } else { /* case 6: new entry */ nrh_t nrh; nrh = namreg_add( name, namelen ); hardh = Node_alloc( ino, gen, NRH_NULL, DAH_NULL, NF_REFED ); if (hardh == NH_NULL) return RV_ERROR; link_in( hardh ); adopt( parh, hardh, nrh ); mlog( MLOG_DEBUG | MLOG_TREE, "dirent %s %llu %u: " "adding (new)\n", name, ino, gen ); } return RV_OK; } /* ARGSUSED */ void tree_enddir( nh_t dirh ) { } bool_t tree_subtree_parse( bool_t sensepr, char *path ) { nh_t namedh; nh_t parh; nh_t cldh; xfs_ino_t ino; bool_t isdirpr; bool_t isselpr; bool_t ok; /* walk the tree down this relative pathname from the root. */ ok = tsi_walkpath( path, NH_NULL, persp->p_rooth, 0, 0, &namedh, &parh, &cldh, &ino, &isdirpr, &isselpr ); if ( ! ok ) { return BOOL_FALSE; } /* set or clear flag in this node and all of its children, * and ajust parentage flags. */ selsubtree( namedh, sensepr ); return BOOL_TRUE; } /* tree_post - called after the dirdump has been applied. * first phase is to eliminate all unreferenced dirents. * done by recursive depth-wise descent of the tree. on the way * up, unlink or orphan unreferenced nondirs, unlink unreferenced * dirs, orphan dirs to be renamed. if a dir is unreferenced, but * contains referenced dirents, orphan those dirents. orphan unreferenced * nondirs if they are the last link to an inode referenced but not real * somewhere else in the tree. next, make new directories. then rename * directories. finally, create hardlinks from orphanage. */ static bool_t noref_elim_recurse( nh_t parh, nh_t cldh, bool_t parrefpr, char *path1, char *path2 ); static bool_t mkdirs_recurse( nh_t parh, nh_t cldh, char *path ); static bool_t rename_dirs( nh_t cldh, char *path1, char *path2 ); static bool_t proc_hardlinks( char *path1, char *path2 ); bool_t tree_post( char *path1, char *path2 ) { node_t *rootp; node_t *orphp; nh_t cldh; bool_t ok; /* eliminate unreferenced dirents */ if ( ! persp->p_fullpr ) { mlog( MLOG_DEBUG | MLOG_TREE, "eliminating unreferenced directory entries\n" ); rootp = Node_map( persp->p_rooth ); cldh = rootp->n_cldh; Node_unmap( persp->p_rooth, &rootp ); ok = noref_elim_recurse( persp->p_rooth, cldh, BOOL_TRUE, path1, path2 ); if ( ! ok ) { return BOOL_FALSE; } } /* make new directories */ mlog( MLOG_DEBUG | MLOG_TREE, "making new directories\n" ); rootp = Node_map( persp->p_rooth ); cldh = rootp->n_cldh; Node_unmap( persp->p_rooth, &rootp ); ok = mkdirs_recurse( persp->p_rooth, cldh, path1 ); if ( ! ok ) { return BOOL_FALSE; } #ifdef TREE_CHK assert( tree_chk( )); #endif /* TREE_CHK */ /* rename directories */ if ( ! persp->p_fullpr ) { mlog( MLOG_DEBUG | MLOG_TREE, "performing directory renames\n" ); orphp = Node_map( persp->p_orphh ); cldh = orphp->n_cldh; Node_unmap( persp->p_orphh, &orphp ); ok = rename_dirs( cldh, path1, path2 ); if ( ! ok ) { return BOOL_FALSE; } } #ifdef TREE_CHK assert( tree_chk( )); #endif /* TREE_CHK */ /* process hard links */ if ( ! persp->p_fullpr ) { mlog( MLOG_DEBUG | MLOG_TREE, "processing hard links\n" ); ok = proc_hardlinks( path1, path2 ); if ( ! ok ) { return BOOL_FALSE; } } return BOOL_TRUE; } /* ARGSUSED */ static bool_t noref_elim_recurse( nh_t parh, nh_t cldh, bool_t parrefpr, char *path1, char *path2 ) { while ( cldh != NH_NULL ) { node_t *cldp; xfs_ino_t ino; gen_t gen; bool_t inorphanagepr; bool_t isdirpr; bool_t isrealpr; bool_t isrefpr; bool_t isrenamepr; nh_t renameh; nh_t grandcldh; nh_t nextcldh; int rval; bool_t ok; cldp = Node_map( cldh ); ino = cldp->n_ino; gen = cldp->n_gen; inorphanagepr = cldp->n_parh == persp->p_orphh; isdirpr = ( cldp->n_flags & NF_ISDIR ); isrealpr = ( cldp->n_flags & NF_REAL ); isrefpr = ( cldp->n_flags & NF_REFED ); isrenamepr = ( isdirpr && cldp->n_lnkh != NH_NULL ); renameh = cldp->n_lnkh; grandcldh = cldp->n_cldh; nextcldh = cldp->n_sibh; #ifdef TREE_DEBUG ok = Node2path( cldh, path1, _("noref debug") ); mlog( MLOG_TRACE | MLOG_TREE, "noref: %s: isdir = %d, isreal = %d, isref = %d, " "isrenamedir = %d\n", path1, isdirpr, isrealpr, isrefpr, isrenamepr ); #endif Node_unmap( cldh, &cldp ); if ( isdirpr ) { bool_t ok; ok = noref_elim_recurse( cldh, grandcldh, isrefpr, path1, path2 ); /* RECURSION */ if ( ! ok ) { return BOOL_FALSE; } if ( inorphanagepr ) { cldh = nextcldh; continue; } if ( ! isrefpr ) { nrh_t nrh; assert( ! isrenamepr ); if ( isrealpr ) { ok = Node2path( cldh, path1, _("rmdir") ); if ( ! ok ) { cldh = nextcldh; continue; } mlog( MLOG_TRACE | MLOG_TREE, "rmdir %s\n", path1 ); rval = rmdir( path1 ); if ( rval ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_TREE, _( "unable to rmdir %s: %s\n"), path1, strerror( errno )); cldh = nextcldh; continue; } } nrh = disown( cldh ); assert( nrh != NRH_NULL ); namreg_del( nrh ); link_out( cldh ); Node_free( &cldh ); } if ( isrenamepr ) { nrh_t nrh; node_t *renamep; assert( isrefpr ); assert( isrealpr ); ok = Node2path( cldh, path1, _("tmp dir rename src") ); if ( ! ok ) { cldh = nextcldh; continue; } nrh = disown( cldh ); assert( nrh != NRH_NULL ); adopt( persp->p_orphh, cldh, NRH_NULL ); ok = Node2path( cldh, path2, _("tmp dir rename dst") ); if ( ! ok ) { /* REFERENCED */ nrh_t dummynrh; dummynrh = disown( cldh ); assert( dummynrh == NRH_NULL ); adopt( parh, cldh, nrh ); cldh = nextcldh; continue; } mlog( MLOG_TRACE | MLOG_TREE, "rename dir %s to %s\n", path1, path2 ); rval = rename( path1, path2 ); if ( rval ) { /* REFERENCED */ nrh_t dummynrh; mlog( MLOG_NORMAL | MLOG_WARNING, _( "unable to rename dir %s " "to dir %s: %s\n"), path1, path2, strerror( errno )); dummynrh = disown( cldh ); assert( dummynrh == NRH_NULL ); adopt( parh, cldh, nrh ); cldh = nextcldh; continue; } cldp = Node_map( cldh ); renamep = Node_map( renameh ); if ( renamep->n_nrh == NRH_NULL ) { renamep->n_nrh = nrh; } else { namreg_del( nrh ); } if ( renamep->n_parh == NH_NULL ) { renamep->n_parh = parh; } cldp->n_flags |= NF_NEWORPH; Node_unmap( renameh, &renamep ); Node_unmap( cldh, &cldp ); } } else { /* determine if we can unlink this node. * if its not real, and not refed, simple. * if real and not refed and there is at least * one unreal refed node and no other real * nodes around, must put this one in orphanage * rather than unlinking it. */ bool_t mustorphpr; bool_t canunlinkpr; if ( inorphanagepr ) { cldh = nextcldh; continue; } mustorphpr = BOOL_FALSE; canunlinkpr = ! isrefpr && ! isrealpr; if ( ! isrefpr && isrealpr ) { nh_t hardh; bool_t neededpr; hardh = link_hardh( ino, gen ); assert( hardh != NH_NULL ); canunlinkpr = BOOL_FALSE; neededpr = BOOL_FALSE; /* tes@sgi.com: * This loop seems to assume that * REAL files come before NON-REALs * so that we will break out first * if we find a REAL file. */ while ( hardh != NH_NULL ) { node_t *hardp; bool_t hardisrefpr; bool_t hardisrealpr; nh_t nexthardh; hardp = Node_map( hardh ); hardisrefpr = hardp->n_flags & NF_REFED; hardisrealpr = hardp->n_flags & NF_REAL; nexthardh = hardp->n_lnkh; Node_unmap( hardh, &hardp ); if ( hardh != cldh && hardisrealpr ) { break; } if ( hardisrefpr && ! hardisrealpr ) { neededpr = BOOL_TRUE; } hardh = nexthardh; } if ( neededpr ) { mustorphpr = BOOL_TRUE; } else { canunlinkpr = BOOL_TRUE; } } if ( mustorphpr ) { /* rename file to orphanage */ nrh_t nrh; assert( ! canunlinkpr ); ok = Node2path( cldh, path1, _("tmp nondir rename src") ); if ( ! ok ) { cldh = nextcldh; continue; } nrh = disown( cldh ); assert( nrh != NRH_NULL ); adopt( persp->p_orphh, cldh, NRH_NULL ); ok = Node2path( cldh, path2, _("tmp nondir rename dst") ); if ( ! ok ) { /* REFERENCED */ nrh_t dummynrh; dummynrh = disown( cldh ); assert( dummynrh == NRH_NULL ); adopt( parh, cldh, nrh ); cldh = nextcldh; continue; } mlog( MLOG_TRACE | MLOG_TREE, "rename nondir %s to %s\n", path1, path2 ); rval = rename( path1, path2 ); if ( rval ) { /* REFERENCED */ nrh_t dummynrh; mlog( MLOG_NORMAL | MLOG_WARNING, _( "unable to rename nondir %s " "to nondir %s: %s\n"), path1, path2, strerror( errno )); dummynrh = disown( cldh ); assert( dummynrh == NRH_NULL ); adopt( parh, cldh, nrh ); cldh = nextcldh; continue; } namreg_del( nrh ); cldp = Node_map( cldh ); cldp->n_flags |= NF_NEWORPH; Node_unmap( cldh, &cldp ); } if ( canunlinkpr ) { /* REFERENCED */ nrh_t nrh; assert( ! mustorphpr ); if ( isrealpr ) { ok = Node2path( cldh, path1, _("rmdir") ); if ( ! ok ) { cldh = nextcldh; continue; } mlog( MLOG_TRACE | MLOG_TREE, "unlink %s\n", path1 ); rval = unlink( path1 ); if ( rval ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_TREE, _( "unable to unlink nondir " "%s: %s\n"), path1, strerror( errno )); cldh = nextcldh; continue; } } nrh = disown( cldh ); assert( nrh != NRH_NULL ); link_out( cldh ); Node_free( &cldh ); } } /* next! */ cldh = nextcldh; } return BOOL_TRUE; } /* ARGSUSED */ static bool_t mkdirs_recurse( nh_t parh, nh_t cldh, char *path ) { while ( cldh != NH_NULL ) { node_t *cldp; bool_t isdirpr; bool_t isselpr; bool_t isrealpr; bool_t isrefpr; nh_t grandcldh; nh_t nextcldh; cldp = Node_map( cldh ); isdirpr = ( cldp->n_flags & NF_ISDIR ); isrealpr = ( cldp->n_flags & NF_REAL ); isrefpr = ( cldp->n_flags & NF_REFED ); isselpr = ( cldp->n_flags & NF_SUBTREE ); grandcldh = cldp->n_cldh; nextcldh = cldp->n_sibh; Node_unmap( cldh, &cldp ); /* if needed, create a directory and update real flag */ if ( isdirpr && ! isrealpr && isrefpr && isselpr ) { int rval; if ( ! Node2path( cldh, path, _("makedir") )) { cldh = nextcldh; continue; } if ( tranp->t_toconlypr ) { rval = 0; } else { mlog( MLOG_TRACE | MLOG_TREE, "mkdir %s\n", path ); rval = mkdir( path, S_IRWXU ); } if ( rval && errno != EEXIST ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_TREE, _( "mkdir %s failed: %s\n"), path, strerror( errno )); } else { cldp = Node_map( cldh ); cldp->n_flags |= NF_REAL; Node_unmap( cldh, &cldp ); isrealpr = BOOL_TRUE; } } /* if a real selected directory, recurse */ if ( isdirpr && isrealpr && isselpr ) { bool_t ok; ok = mkdirs_recurse( cldh, grandcldh, path ); /* RECURSION */ if ( ! ok ) { return BOOL_FALSE; } } /* next! */ cldh = nextcldh; } return BOOL_TRUE; } static bool_t rename_dirs( nh_t cldh, char *path1, char *path2 ) { while ( cldh != NH_NULL ) { node_t *cldp; /* REFERENCED */ nh_t parh; bool_t isdirpr; nh_t renameh; bool_t isrenamepr; nh_t nextcldh; nh_t newparh; nh_t newnrh; cldp = Node_map( cldh ); parh = cldp->n_parh; isdirpr = cldp->n_flags & NF_ISDIR; renameh = cldp->n_lnkh; isrenamepr = isdirpr && renameh != NH_NULL; nextcldh = cldp->n_sibh; Node_unmap( cldh, &cldp ); assert( parh == persp->p_orphh ); if ( isrenamepr ) { node_t *renamep; int rval; /* REFERENCED */ nrh_t dummynrh; bool_t ok; renamep = Node_map( renameh ); newparh = renamep->n_parh; newnrh = renamep->n_nrh; Node_unmap( renameh, &renamep ); ok = Node2path( cldh, path1, _("rename dir") ); if ( ! ok ) { cldh = nextcldh; continue; } dummynrh = disown( cldh ); assert( dummynrh == NRH_NULL ); adopt( newparh, cldh, newnrh ); ok = Node2path( cldh, path2, _("rename dir") ); if ( ! ok ) { dummynrh = disown( cldh ); assert( dummynrh == newnrh ); adopt( persp->p_orphh, cldh, NRH_NULL ); cldp = Node_map( cldh ); cldp->n_nrh = NRH_NULL; Node_unmap( cldh, &cldp ); cldh = nextcldh; continue; } mlog( MLOG_TRACE | MLOG_TREE, "rename dir %s to %s\n", path1, path2 ); rval = rename( path1, path2 ); if ( rval ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "unable to rename dir %s " "to dir %s: %s\n"), path1, path2, strerror( errno )); dummynrh = disown( cldh ); assert( dummynrh == newnrh ); adopt( persp->p_orphh, cldh, NRH_NULL ); cldh = nextcldh; continue; } cldp = Node_map( cldh ); cldp->n_flags &= ~NF_NEWORPH; cldp->n_lnkh = NH_NULL; Node_unmap( cldh, &cldp ); Node_free( &renameh ); } /* next! */ cldh = nextcldh; } return BOOL_TRUE; } /* will call funcp for all links to be created. will abort if funcp * ever returns FALSE; */ rv_t tree_cb_links( xfs_ino_t ino, gen_t gen, int32_t ctime, int32_t mtime, bool_t ( * funcp )( void *contextp, bool_t linkpr, char *path1, char *path2 ), void *contextp, char *path1, char *path2 ) { nh_t hardh; nh_t nh; char *path; bool_t ok; int rval; if ( persp->p_truncategenpr ) { gen = BIGGEN2GEN( gen ); } /* find the hardhead */ hardh = link_hardh( ino, gen ); /* loop through all hard links, attempting to restore/link */ path = path1; for ( nh = hardh ; nh != NH_NULL ; nh = link_nexth( nh )) { node_t *np; u_char_t flags; char *reasonstr; /* get the node flags */ np = Node_map( nh ); flags = np->n_flags; Node_unmap( nh, &np ); /* build a pathname */ ok = Node2path( nh, path, _("restore") ); if ( ! ok ) { continue; } /* skip if not in selected subtree */ if ( ! ( flags & NF_SUBTREE )) { mlog( (MLOG_NITTY + 1) | MLOG_TREE, "skipping %s (ino %llu gen %u): %s\n", path, ino, gen, "not in selected subtree" ); continue; } /* don't restore into the housekeeping directory */ if ( path_beginswith( path, tranp->t_hkdir )) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_TREE, _( "cannot restore %s (ino %llu gen %u): " "pathname contains %s\n"), path, ino, gen, tranp->t_hkdir ); continue; } /* check if ok to overwrite: don't check if we've already * been here and decided overwrite ok. if ok, set flag * so we won't check again. in fact, can't check again * since restore changes the answer. */ if ( ! ( flags & NF_WRITTEN )) { bool_t exists; if ( ! content_overwrite_ok( path, ctime, mtime, &reasonstr, &exists )) { mlog( MLOG_TRACE | MLOG_TREE, "skipping %s (ino %llu gen %u): %s\n", path, ino, gen, reasonstr ); continue; } else { np = Node_map( nh ); np->n_flags |= NF_WRITTEN; Node_unmap( nh, &np ); /* * We're the first stream to restore this file. * Unlink it first to remove extended attributes * that may have been set since the dump was * taken. */ if ( ! tranp->t_toconlypr && exists ) { rval = unlink( path ); if ( rval && errno != ENOENT ) { mlog( MLOG_NORMAL | MLOG_WARNING, _( "unable to unlink " "current file prior to " "restore: " "%s: %s: discarding\n"), path, strerror( errno )); continue; } } } } /* call callback to restore file / create hard link. * returns !ok if should abort. */ if ( path == path2 ) { mlog( MLOG_TRACE | MLOG_TREE, "link %s to %s (%llu %u)\n", path1, path2, ino, gen ); } else { mlog( MLOG_TRACE | MLOG_TREE, "restoring %s (%llu %u)\n", path1, ino, gen ); } ok = ( * funcp )( contextp, path == path2, path1, path2 ); if ( ! ok ) { return RV_NOTOK; } /* set flag, indicating node is now real */ np = Node_map( nh ); np->n_flags |= NF_REAL; Node_unmap( nh, &np ); /* switch to second path buffer, for link paths */ path = path2; } /* if not yet peeled from tape, do so: place in orphanage if * no references found (i.e., hard link list empty). */ if ( path == path1 ) { if ( hardh != NH_NULL || persp->p_ignoreorphpr ) { /* * The file is referenced so the path is * valid. This means that if path begins * with 'orphanage' the file is one of two * things: * 1) It's a file that really is an * orphanage file from a previous restore * that has now ended up on this dump tape. * We don't really want to restore this file * but, it's harmless to do so, it should * happen rarely, and the path name is * indistinguishable from ... * 2) A file whose name was never resolved * from root because of file corruption. * Some granparent dir (parent dir of it's * parent dir) was corrupted so the code that * walks the trees was thus never able to set * the NF_SUBTREE flag. It then ends up here * with a non-resolved name but a valid * hard reference. We really need to give * the admin the opportunity to get this * data since one corrupted dirnode would * make the whole tree of data * unreachable. pv698761 */ if ( persp->p_ignoreorphpr || (strncmp(ORPH_NAME, path, strlen(ORPH_NAME)) != 0)) { mlog( MLOG_DEBUG | MLOG_TREE, "discarding %llu %u\n", ino, gen ); ok = ( * funcp )( contextp, BOOL_FALSE, 0, 0 ); if ( ! ok ) { return RV_NOTOK; } } else { if ( ! tranp->t_toconlypr ) { char *dir; char tmp[PATH_MAX]; strcpy(tmp, path); dir = dirname(tmp); mkdir_r(dir); } mlog (MLOG_VERBOSE | MLOG_NOTE | MLOG_TREE, _( "ino %llu salvaging file," " placing in %s\n"), ino, path1); ok = ( * funcp )( contextp, path == path2, path1, path2 ); if ( ! ok ) { return RV_NOTOK; } } } else { mlog( MLOG_VERBOSE | MLOG_NOTE | MLOG_TREE, _( "ino %llu gen %u not referenced: " "placing in orphanage\n"), ino, gen ); nh = Node_alloc( ino, gen, NRH_NULL, DAH_NULL, NF_REAL | NF_NEWORPH ); if (nh == NH_NULL) { mlog( MLOG_ERROR | MLOG_TREE, _( "node allocation failed when placing ino %llu" " in orphanage\n"), ino); return RV_ERROR; /* allocation failed */ } link_in( nh ); adopt( persp->p_orphh, nh, NRH_NULL ); ok = Node2path( nh, path1, _("orphan") ); assert( ok ); ( void )( * funcp )( contextp, BOOL_FALSE, path1,path2); } } return RV_OK; } /* uses flags cleared during directory restore (NF_DUMPEDDIR and NF_REFED ) * to determine what directory entries are no longer needed. this can * be done because whenever a directory chenges, it and all of its current * entries are dumped. so if an entry is dumped which is a dir, but that * dir is not dumped, all of that directories entries are needed and so must * have their REFED flag cleared. * * does a recursive depth-wise descent of the tree, following this rule to * clear the REFED flags. */ static void tree_adjref_recurse( nh_t cldh, bool_t pardumpedpr, bool_t parrefedpr ); bool_t tree_adjref( void ) { tree_adjref_recurse( persp->p_rooth, BOOL_FALSE, BOOL_TRUE ); return BOOL_TRUE; } static void tree_adjref_recurse( nh_t cldh, bool_t pardumpedpr, bool_t parrefedpr ) { nh_t grandcldh; bool_t clddumpedpr; bool_t cldrefedpr; { node_t *cldp; cldp = Node_map( cldh ); if ( ! pardumpedpr && parrefedpr ) { cldp->n_flags |= NF_REFED; } clddumpedpr = ( int )cldp->n_flags & NF_DUMPEDDIR; cldrefedpr = ( int )cldp->n_flags & NF_REFED; grandcldh = cldp->n_cldh; Node_unmap( cldh, &cldp ); } while ( grandcldh != NH_NULL ) { node_t *grandcldp; nh_t nextgrandcldh; tree_adjref_recurse( grandcldh, clddumpedpr, cldrefedpr ); /* RECURSION */ grandcldp = Node_map( grandcldh ); nextgrandcldh = grandcldp->n_sibh; Node_unmap( grandcldh, &grandcldp ); grandcldh = nextgrandcldh; } } static bool_t tree_extattr_recurse( nh_t parh, nh_t cldh, bool_t ( * cbfunc )( char *path, dah_t dah ), char *path ); bool_t tree_extattr( bool_t ( * cbfunc )( char *path, dah_t dah ), char *path ) { node_t *rootp; nh_t cldh; bool_t ok; rootp = Node_map( persp->p_rooth ); cldh = rootp->n_cldh; Node_unmap( persp->p_rooth, &rootp ); ok = tree_extattr_recurse( persp->p_rooth, cldh, cbfunc, path ); return ok; } static bool_t tree_extattr_recurse( nh_t parh, nh_t cldh, bool_t ( * cbfunc )( char *path, dah_t dah ), char *path ) { node_t *parp; dah_t dah; bool_t ok; /* first update all children */ while ( cldh != NH_NULL ) { node_t *cldp; bool_t isdirpr; bool_t isselpr; bool_t isrealpr; nh_t grandcldh; nh_t nextcldh; cldp = Node_map( cldh ); isdirpr = ( cldp->n_flags & NF_ISDIR ); isrealpr = ( cldp->n_flags & NF_REAL ); isselpr = ( cldp->n_flags & NF_SUBTREE ); grandcldh = cldp->n_cldh; nextcldh = cldp->n_sibh; Node_unmap( cldh, &cldp ); /* if a real selected directory, recurse */ if ( isdirpr && isrealpr && isselpr ) { bool_t ok; ok = tree_extattr_recurse( cldh, grandcldh, cbfunc, path ); /* RECURSION */ if ( ! ok ) { return BOOL_FALSE; } } /* next! */ cldh = nextcldh; } /* now update self */ parp = Node_map( parh ); dah = parp->n_dah; Node_unmap( parh, &parp ); if ( ! Node2path( parh, path, _("set dir extattr") )) { mlog (MLOG_NORMAL | MLOG_WARNING | MLOG_TREE, _( "tree_extattr_recurse: Could not convert node to " "path for %s\n"), path); return BOOL_TRUE; } if ( dah != DAH_NULL ) { ok = ( * cbfunc )( path, dah ); } else { ok = BOOL_TRUE; } return ok; } struct phcb { char *path1; char *path2; bool_t ok; }; typedef struct phcb phcb_t; static bool_t proc_hardlinks_cb( void *contextp, nh_t hardheadh ); static bool_t proc_hardlinks( char *path1, char *path2 ) { phcb_t phcb; /* have callback invoked for all hardheads */ phcb.path1 = path1; phcb.path2 = path2; phcb.ok = BOOL_TRUE; link_headiter( proc_hardlinks_cb, ( void * )&phcb ); return phcb.ok; } /* called for every hard head * * tes@sgi.com: * This code processes the hardlinks, extracting out a * src_list - real & !ref * dest_list - !real & ref * The src_list are the entries to delete and the dst_list * are the new_entries to create. * 1. If we have a src and a dst then we can do a rename. * 2. If we have extra src nodes then we can unlink them. * 3. If we have extra dst nodes then we can link them. * HOWEVER, the linking in of the new nodes is actually handled * in the restore_file_cb() code which on restoral creates * the file and all its hardlinks. * ALSO, I can not see how the src_list can have more than * 1 node in it, since in noref_elim_recurse() it unlinks all * extra deleted entries (real & !ref). * Thus, steps 2 and 3 are handled in noref_elim_recurse(). */ static bool_t proc_hardlinks_cb( void *contextp, nh_t hardheadh ) { phcb_t *phcbp = ( phcb_t * )contextp; node_t *hardheadp; xfs_ino_t ino; gen_t gen; bool_t isdirpr; nh_t rnsrcheadh; nh_t rndstheadh; nh_t lnsrch; nh_t nh; link_iter_context_t link_iter_context; bool_t ok; int rval; /* skip directories */ hardheadp = Node_map( hardheadh ); ino = hardheadp->n_ino; gen = hardheadp->n_gen; isdirpr = hardheadp->n_flags & NF_ISDIR; Node_unmap( hardheadh, &hardheadp ); if ( isdirpr ) { return BOOL_TRUE; } mlog( MLOG_DEBUG | MLOG_TREE, "processing hardlinks to %llu %u\n", ino, gen ); /* first pass through hard link list: for each node, leave on * list, unlink and place on rename src list, unlink and place on * rename dst list, or unlink and discard. note a node available * to link from, in case we need it. */ rnsrcheadh = NH_NULL; rndstheadh = NH_NULL; lnsrch = NH_NULL; link_iter_init( &link_iter_context, hardheadh ); while ( ( nh = link_iter_next( &link_iter_context )) != NH_NULL ) { node_t *np = Node_map( nh ); bool_t isrealpr = np->n_flags & NF_REAL; bool_t isrefpr = np->n_flags & NF_REFED; bool_t isselpr = np->n_flags & NF_SUBTREE; /* if unrefed, unreal, free node etc. (sel doesn't matter) */ if ( ! isrealpr && ! isrefpr ) { mlog( MLOG_NITTY | MLOG_TREE, "freeing node %x: not real, not referenced\n", nh ); link_iter_unlink( &link_iter_context, nh ); Node_unmap( nh, &np ); ( void )disown( nh ); Node_free( &nh ); continue; } /* not real, refed, but not selected, can't help */ if ( ! isrealpr && isrefpr && ! isselpr ) { mlog( MLOG_NITTY | MLOG_TREE, "skipping node %x: not selected\n", nh ); Node_unmap( nh, &np ); continue; } /* if unreal, refed, sel, add to dst list, */ if ( ! isrealpr && isrefpr && isselpr ) { mlog( MLOG_NITTY | MLOG_TREE, "making node %x dst: " "not real, refed, sel\n", nh ); link_iter_unlink( &link_iter_context, nh ); np->n_lnkh = rndstheadh; rndstheadh = nh; Node_unmap( nh, &np ); continue; } /* if real, unrefed, sel, add to src list */ if ( isrealpr && ! isrefpr && isselpr ) { mlog( MLOG_NITTY | MLOG_TREE, "making node %x src: real, not refed, sel\n", nh ); link_iter_unlink( &link_iter_context, nh ); np->n_lnkh = rnsrcheadh; rnsrcheadh = nh; Node_unmap( nh, &np ); continue; } /* would like to get rid of but not selected, or * real and referenced, leave alone (sel doesn't matter). * consider as a lnk src, since real and not going away. */ if ( isrealpr && ( isrefpr || !isselpr ) ) { mlog( MLOG_NITTY | MLOG_TREE, "skipping node %x: %s\n", nh, isselpr ? "real and ref" : "real and not sel" ); Node_unmap( nh, &np ); if ( lnsrch == NH_NULL ) { mlog( MLOG_NITTY | MLOG_TREE, "node %x will be link src\n", nh ); lnsrch = nh; } continue; } assert( 0 ); } /* now pass through dst list, doing renames if src list not empty, * otherwise links if a lnk src available, otherwise put back in link * list */ while ( rndstheadh != NH_NULL ) { nh_t dsth; node_t *dstp; bool_t successpr; dsth = rndstheadh; dstp = Node_map( dsth ); rndstheadh = dstp->n_lnkh; dstp->n_lnkh = NH_NULL; Node_unmap( dsth, &dstp ); /* build pathname to dst */ ok = Node2path( dsth, phcbp->path2, _("rename to") ); if ( ! ok ) { link_in( dsth ); continue; } successpr = BOOL_FALSE; while ( ! successpr && rnsrcheadh != NH_NULL ) { nh_t srch; nrh_t nrh; node_t *srcp; srch = rnsrcheadh; srcp = Node_map( srch ); rnsrcheadh = srcp->n_lnkh; srcp->n_lnkh = NH_NULL; Node_unmap( srch, &srcp ); /* build a path to src */ ok = Node2path( srch, phcbp->path1, _("rename from") ); if ( ! ok ) { link_in( srch ); continue; } if ( tranp->t_toconlypr ) { rval = 0; } else { mlog( MLOG_TRACE | MLOG_TREE, "rename nondir %s to %s\n", phcbp->path1, phcbp->path2 ); rval = rename( phcbp->path1, phcbp->path2 ); } if ( rval ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_TREE, _( "unable to rename nondir " "%s to %s: %s\n"), phcbp->path1, phcbp->path2, strerror( errno )); link_in( srch ); continue; } nrh = disown( srch ); if ( nrh != NRH_NULL ) { namreg_del( nrh ); } Node_free( &srch ); successpr = BOOL_TRUE; } /* tes@sgi.com: note: loop of one iteration only */ while ( ! successpr && lnsrch != NH_NULL ) { ok = Node2path( lnsrch, phcbp->path1, _("link") ); if ( ! ok ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_TREE, _( "unable to use %s " "as a hard link source\n"), phcbp->path1 ); lnsrch = NH_NULL; continue; } if ( tranp->t_toconlypr ) { rval = 0; } else { mlog( MLOG_TRACE | MLOG_TREE, "link nondir %s to %s\n", phcbp->path1, phcbp->path2 ); rval = link( phcbp->path1, phcbp->path2 ); } if ( rval ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_TREE, "unable to link nondir " "%s to %s: %s\n", phcbp->path1, phcbp->path2, strerror( errno )); break; } successpr = BOOL_TRUE; } if ( ! successpr ) { mlog( MLOG_NITTY | MLOG_TREE, "no link src for node %x\n", dsth ); } else { dstp = Node_map( dsth ); dstp->n_flags |= NF_REAL; Node_unmap( dsth, &dstp ); } link_in( dsth ); } /* finally, pass through remaining src list, unlinking/disowning. * tes@sgi.com: don't believe this will happen as this step * should now be done in noref_elim_recurse(). */ while ( rnsrcheadh != NH_NULL ) { nh_t srch; node_t *srcp; bool_t ok; srch = rnsrcheadh; srcp = Node_map( srch ); rnsrcheadh = srcp->n_lnkh; srcp->n_lnkh = NH_NULL; Node_unmap( srch, &srcp ); ok = Node2path( srch, phcbp->path1, _("unlink") ); if ( ! ok ) { link_in( srch ); continue; } if ( tranp->t_toconlypr ) { rval = 0; } else { mlog( MLOG_TRACE | MLOG_TREE, "unlink nondir %s\n", phcbp->path1 ); rval = unlink( phcbp->path1 ); } if ( rval ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_TREE, _( "unable to unlink %s: %s\n"), phcbp->path1, strerror( errno )); link_in( srch ); } else { nrh_t nrh; nrh = disown( srch ); if ( nrh != NRH_NULL ) { namreg_del( nrh ); } Node_free( &srch ); } } return BOOL_TRUE; } /* traverse tree depth-wise bottom-up for dirs no longer referenced. * if non-empty, move children to orphanage */ bool_t tree_setattr( char *path ) { bool_t ok; node_t *rootp; ok = tree_setattr_recurse( persp->p_rooth, path ); if ( restore_rootdir_permissions && ok ) { rootp = Node_map( persp->p_rooth ); /* "." is cwd which is the destination dir */ setdirattr( rootp->n_dah, "." ); Node_unmap( persp->p_rooth, &rootp ); } return ok; } static bool_t tree_setattr_recurse( nh_t parh, char *path ) { node_t *parp = Node_map( parh ); nh_t cldh = parp->n_cldh; Node_unmap( parh, &parp ); while ( cldh != NH_NULL ) { nh_t nextcldh; /* get the node attributes */ node_t *cldp = Node_map( cldh ); bool_t isdirpr = ( cldp->n_flags & NF_ISDIR ); bool_t isselpr = ( cldp->n_flags & NF_SUBTREE ); bool_t isrealpr = ( cldp->n_flags & NF_REAL ); dah_t dah = cldp->n_dah; /* get next cld */ nextcldh = cldp->n_sibh; Node_unmap( cldh, &cldp ); /* if is a real selected dir, go ahead. */ if ( isdirpr && isselpr && isrealpr ) { bool_t ok; ok = tree_setattr_recurse( cldh, path ); /* RECURSION */ if ( ! ok ) { Node_unmap( cldh, &cldp ); return BOOL_FALSE; } if ( dah != DAH_NULL ) { bool_t ok; ok = Node2path( cldh, path, _("set dirattr") ); if ( ok ) { setdirattr( dah, path ); } } } cldh = nextcldh; } return BOOL_TRUE; } static void setdirattr( dah_t dah, char *path ) { mode_t mode; struct utimbuf utimbuf; struct fsxattr fsxattr; int rval; size_t hlen; void *hanp; int fd = -1; if ( dah == DAH_NULL ) return; if ( tranp->t_dstdirisxfspr ) { if (path_to_handle(path, &hanp, &hlen)) { mlog( MLOG_NORMAL | MLOG_WARNING, _("path_to_handle of %s failed:%s\n"), path, strerror( errno )); } else { fd = open_by_handle(hanp, hlen, O_RDONLY); if (fd < 0) { mlog( MLOG_NORMAL | MLOG_WARNING, _("open_by_handle of %s failed:%s\n"), path, strerror( errno )); } free_handle(hanp, hlen); } } if ( tranp->t_dstdirisxfspr && persp->p_restoredmpr ) { fsdmidata_t fssetdm; fssetdm.fsd_dmevmask = dirattr_get_dmevmask( dah ); fssetdm.fsd_padding = 0; /* not used */ fssetdm.fsd_dmstate = ( uint16_t )dirattr_get_dmstate( dah ); /* restore DMAPI event settings etc. */ rval = ioctl( fd, XFS_IOC_FSSETDM, ( void * )&fssetdm ); if ( rval ) { mlog( errno == EINVAL ? ( MLOG_NITTY + 1 ) | MLOG_TREE : MLOG_NITTY | MLOG_TREE, "set DMI attributes" " of %s failed: %s\n", path, strerror( errno )); } } utimbuf.actime = dirattr_get_atime( dah ); utimbuf.modtime = dirattr_get_mtime( dah ); rval = utime( path, &utimbuf ); if ( rval ) { mlog( MLOG_VERBOSE | MLOG_TREE, _( "could not set access and modification times" " of %s: %s\n"), path, strerror( errno )); } mode = dirattr_get_mode( dah ); if ( persp->p_ownerpr ) { rval = chown( path, dirattr_get_uid( dah ), dirattr_get_gid( dah )); if ( rval ) { mlog( MLOG_NORMAL | MLOG_TREE, _( "chown (uid=%d, gid=%d) %s failed: %s\n"), dirattr_get_uid( dah ), dirattr_get_gid( dah ), path, strerror( errno )); } } rval = chmod( path, mode ); if ( rval ) { mlog( MLOG_NORMAL | MLOG_TREE, _( "chmod %s failed: %s\n"), path, strerror( errno )); } /* set the extended inode flags */ if ( !tranp->t_dstdirisxfspr ) return; memset((void *)&fsxattr, 0, sizeof( fsxattr )); fsxattr.fsx_xflags = dirattr_get_xflags( dah ); fsxattr.fsx_extsize = dirattr_get_extsize( dah ); fsxattr.fsx_projid = dirattr_get_projid( dah ); rval = ioctl( fd, XFS_IOC_FSSETXATTR, (void *)&fsxattr); if ( rval < 0 ) { mlog(MLOG_NORMAL | MLOG_WARNING, _("attempt to set " "extended attributes " "(xflags 0x%x, " "extsize = 0x%x, " "projid = 0x%x) " "of %s failed: " "%s\n"), fsxattr.fsx_xflags, fsxattr.fsx_extsize, fsxattr.fsx_projid, path, strerror(errno)); } ( void )close( fd ); } /* deletes orphanage if empty, else warns */ bool_t tree_delorph( void ) { int rval; rval = rmdir( tranp->t_orphdir ); if ( rval ) { if ( errno == EEXIST ) { mlog(MLOG_NORMAL | MLOG_WARNING | MLOG_TREE, _( "unable to rmdir %s: not empty\n"), tranp->t_orphdir ); } else { mlog(MLOG_NORMAL | MLOG_WARNING | MLOG_TREE, _( "unable to rmdir %s: %s\n"), tranp->t_orphdir, strerror( errno )); } } return BOOL_TRUE; } /* definition of locally defined static functions ****************************/ /* interactive subtree abstraction *******************************************/ static void tsi_cmd_inst( void *, dlog_pcbp_t, void * ); static void tsi_cmd_pwd( void *, dlog_pcbp_t, void * ); static void tsi_cmd_ls( void *, dlog_pcbp_t, void * ); static void tsi_cmd_cd( void *, dlog_pcbp_t, void * ); static void tsi_cmd_add( void *, dlog_pcbp_t, void * ); static void tsi_cmd_delete( void *, dlog_pcbp_t, void * ); static void tsi_cmd_extract( void *, dlog_pcbp_t, void * ); static void tsi_cmd_quit( void *, dlog_pcbp_t, void * ); static void tsi_cmd_help( void *, dlog_pcbp_t, void * ); static void tsi_cmd_parse( char * ); static dlog_ucbp_t tsi_cmd_match( void ); #define PREAMBLEMAX 3 #define ACKMAX 3 #define POSTAMBLEMAX 3 bool_t tree_subtree_inter( void ) { fold_t fold; char *preamblestr[ PREAMBLEMAX ]; size_t preamblecnt; char *ackstr[ ACKMAX ]; size_t ackcnt; char *postamblestr[ POSTAMBLEMAX ]; size_t postamblecnt; dlog_ucbp_t cmdp; restart: /* make the current working directory the root of the fs */ tranp->t_inter.i_cwdh = persp->p_rooth; /* begin the dialog */ preamblecnt = 0; fold_init( fold, _("subtree selection dialog"), '=' ); preamblestr[ preamblecnt++ ] = "\n"; preamblestr[ preamblecnt++ ] = fold; preamblestr[ preamblecnt++ ] = "\n\n"; assert( preamblecnt <= PREAMBLEMAX ); dlog_begin( preamblestr, preamblecnt ); /* execute commands until time to extract or quit. always begin with * an implicit instructions command. if see SIGINT, give main thread * dialog a chance to decide if a session interrupt is wanted. */ cmdp = tsi_cmd_inst; do { char buf[ MAXPATHLEN ]; const ix_t abortix = 1; const ix_t sigintix = 2; const ix_t okix = 3; ix_t responseix; /* execute command and get response */ responseix = dlog_string_query( cmdp, 0, buf, sizeof( buf ), 0, IXMAX, /* timeout ix */ sigintix, /* sigint ix */ abortix, /* sighup ix */ abortix, /* sigquit ix */ okix ); /* ok ix */ /* ack the response */ ackcnt = 0; if ( responseix == sigintix ) { ackstr[ ackcnt++ ] = _("keyboard interrupt\n"); } else if ( responseix == abortix ) { ackstr[ ackcnt++ ] = _("abort\n"); } else { assert( responseix == okix ); } assert( ackcnt <= ACKMAX ); dlog_string_ack( ackstr, ackcnt ); /* exception handling */ if ( responseix != okix ) { /* if exception, end the dialog. may restart * if operator decidesd not to intr. */ postamblecnt = 0; fold_init( fold, _("end dialog"), '-' ); postamblestr[ postamblecnt++ ] = "\n"; postamblestr[ postamblecnt++ ] = fold; postamblestr[ postamblecnt++ ] = "\n\n"; assert( postamblecnt <= POSTAMBLEMAX ); dlog_end( postamblestr, postamblecnt ); /* if sighup or sigquit, immediately quit */ if ( responseix == abortix ) { return BOOL_FALSE; } /* if sigint, allow main thread to decide if * operator really wants to quit */ assert( responseix == sigintix ); if ( cldmgr_stop_requested( )) { return BOOL_FALSE; } sleep( 1 ); /* to allow main thread to begin dialog */ mlog( MLOG_NORMAL | MLOG_BARE | MLOG_TREE, "" ); /* block until main thread dialog done */ sleep( 1 ); /* let main thread ask children to die */ if ( cldmgr_stop_requested( )) { return BOOL_FALSE; } mlog( MLOG_DEBUG | MLOG_TREE, "retrying interactive subtree selection dialog\n" ); goto restart; } tsi_cmd_parse( buf ); cmdp = tsi_cmd_match( ); if ( ! cmdp ) { cmdp = tsi_cmd_help; } } while ( cmdp != tsi_cmd_quit && cmdp != tsi_cmd_extract ); postamblecnt = 0; fold_init( fold, _("end dialog"), '-' ); postamblestr[ postamblecnt++ ] = "\n"; postamblestr[ postamblecnt++ ] = fold; postamblestr[ postamblecnt++ ] = "\n\n"; assert( postamblecnt <= POSTAMBLEMAX ); dlog_end( postamblestr, postamblecnt ); /* pv 773569 - quit is not a reason to consider session * to be interrupted (we haven't started yet) so just unmark * any selected directories and return */ if ( cmdp == tsi_cmd_quit ) { mlog( MLOG_NORMAL, _("Unmark and quit\n") ); selsubtree( persp->p_rooth , BOOL_FALSE ); } return BOOL_TRUE; } static void tsi_cmd_inst( void *ctxp, dlog_pcbp_t pcb, void *pctxp ) { tsi_cmd_help( ctxp, pcb, pctxp ); } static void tsi_cmd_pwd( void *ctxp, dlog_pcbp_t pcb, void *pctxp ) { /* special case root */ if ( tranp->t_inter.i_cwdh == persp->p_rooth ) { ( * pcb )( pctxp, "cwd is fs root\n" ); return; } /* ascend tree recursively, print path on way back */ tsi_cmd_pwd_recurse( ctxp, pcb, pctxp, tranp->t_inter.i_cwdh ); ( * pcb )( pctxp, "\n" ); } static void tsi_cmd_pwd_recurse( void *ctxp, dlog_pcbp_t pcb, void *pctxp, nh_t nh ) { node_t *np; register nh_t parh; /* REFERENCED */ register int namelen; nrh_t nrh; assert( nh != NH_NULL ); np = Node_map( nh ); nrh = np->n_nrh; parh = np->n_parh; Node_unmap( nh, &np ); if ( parh != persp->p_rooth ) { tsi_cmd_pwd_recurse( ctxp, pcb, pctxp, parh ); /* RECURSION */ ( * pcb )( pctxp, "/" ); } assert( nrh != NRH_NULL ); namelen = namreg_get( nrh, tranp->t_inter.i_name, sizeof( tranp->t_inter.i_name )); assert( namelen > 0 ); ( * pcb )( pctxp, tranp->t_inter.i_name ); } /* ARGSUSED */ static void tsi_cmd_ls( void *ctxp, dlog_pcbp_t pcb, void *pctxp ) { size_t argc = tranp->t_inter.i_argc; char *arg = ( argc > 1 ) ? tranp->t_inter.i_argv[ 1 ] : 0; bool_t ok; nh_t cldh; nh_t parh; nh_t namedh; xfs_ino_t ino; bool_t isdirpr; bool_t isselpr; /* walk the tree according to the path argument, to get * the named node. */ ok = tsi_walkpath( arg, persp->p_rooth, tranp->t_inter.i_cwdh, pcb, pctxp, &namedh, &parh, &cldh, &ino, &isdirpr, &isselpr ); if ( ! ok ) { return; } /* if named is not a dir, just display named */ if ( ! isdirpr ) { ( * pcb )( pctxp, " %s %10llu %s%s\n", isselpr ? "*" : " ", ino, tranp->t_inter.i_name, isdirpr ? "/" : " " ); return; } /* iterate through the directory, printing all matching entries. * hide the orphanage. */ while ( cldh != NH_NULL ) { node_t *cldp; nrh_t nrh; nh_t nextcldh; cldp = Node_map( cldh ); nrh = cldp->n_nrh; nextcldh = cldp->n_sibh; isdirpr = ( cldp->n_flags & NF_ISDIR ); isselpr = ( cldp->n_flags & NF_SUBTREE ); ino = cldp->n_ino; Node_unmap( cldh, &cldp ); if ( cldh != persp->p_orphh ) { /* REFERENCED */ int namelen; namelen = namreg_get( nrh, tranp->t_inter.i_name, sizeof( tranp->t_inter.i_name )); assert( namelen > 0 ); ( * pcb )( pctxp, " %s %10llu %s%s\n", isselpr ? "*" : " ", ino, tranp->t_inter.i_name, isdirpr ? "/" : " " ); } cldh = nextcldh; } } /* ARGSUSED */ static void tsi_cmd_cd( void *ctxp, dlog_pcbp_t pcb, void *pctxp ) { size_t argc = tranp->t_inter.i_argc; char *arg = ( argc > 1 ) ? tranp->t_inter.i_argv[ 1 ] : 0; nh_t cldh; nh_t parh; nh_t namedh; xfs_ino_t ino; bool_t isdirpr; bool_t isselpr; bool_t ok; /* walk the tree according to the path argument, to get * the named node. */ ok = tsi_walkpath( arg, persp->p_rooth, tranp->t_inter.i_cwdh, pcb, pctxp, &namedh, &parh, &cldh, &ino, &isdirpr, &isselpr ); if ( ! ok ) { return; } /* if named is not a dir, complain */ if ( ! isdirpr ) { assert( arg ); ( * pcb )( pctxp, _("%s is not a directory\n"), arg ); return; } /* change the current working directory */ tranp->t_inter.i_cwdh = namedh; } /* ARGSUSED */ static void tsi_cmd_add( void *ctxp, dlog_pcbp_t pcb, void *pctxp ) { size_t argc = tranp->t_inter.i_argc; char *arg = ( argc > 1 ) ? tranp->t_inter.i_argv[ 1 ] : 0; nh_t cldh; nh_t parh; nh_t namedh; xfs_ino_t ino; bool_t isdirpr; bool_t isselpr; bool_t ok; /* walk the tree according to the path argument, to get * the named node. */ ok = tsi_walkpath( arg, persp->p_rooth, tranp->t_inter.i_cwdh, pcb, pctxp, &namedh, &parh, &cldh, &ino, &isdirpr, &isselpr ); if ( ! ok ) { return; } selsubtree( namedh, BOOL_TRUE ); } /* ARGSUSED */ static void tsi_cmd_delete( void *ctxp, dlog_pcbp_t pcb, void *pctxp ) { size_t argc = tranp->t_inter.i_argc; char *arg = ( argc > 1 ) ? tranp->t_inter.i_argv[ 1 ] : 0; nh_t cldh; nh_t parh; nh_t namedh; xfs_ino_t ino; bool_t isdirpr; bool_t isselpr; bool_t ok; /* walk the tree according to the path argument, to get * the named node. */ ok = tsi_walkpath( arg, persp->p_rooth, tranp->t_inter.i_cwdh, pcb, pctxp, &namedh, &parh, &cldh, &ino, &isdirpr, &isselpr ); if ( ! ok ) { return; } selsubtree( namedh, BOOL_FALSE ); } /* ARGSUSED */ static void tsi_cmd_extract( void *ctxp, dlog_pcbp_t pcb, void *pctxp ) { } /* ARGSUSED */ static void tsi_cmd_quit( void *ctxp, dlog_pcbp_t pcb, void *pctxp ) { } static int parse( int slotcnt, char **slotbuf, char *string ); static void tsi_cmd_parse( char *buf ) { int wordcnt; if ( ! buf ) { tranp->t_inter.i_argc = 0; return; } wordcnt = parse( INTER_ARGMAX, tranp->t_inter.i_argv, buf ); tranp->t_inter.i_argc = ( size_t )min( max( 0, wordcnt ), INTER_ARGMAX ); } struct tsi_cmd_tbl { char *tct_pattern; char *tct_help; dlog_ucbp_t tct_ucb; size_t tct_argcmin; size_t tct_argcmax; }; typedef struct tsi_cmd_tbl tsi_cmd_tbl_t; static tsi_cmd_tbl_t tsi_cmd_tbl[] = { { "pwd", "", tsi_cmd_pwd, 1, 1 }, { "ls", "[ ]", tsi_cmd_ls, 1, 2 }, { "cd", "[ ]", tsi_cmd_cd, 1, 2 }, { "add", "[ ]", tsi_cmd_add, 1, 2 }, { "delete", "[ ]", tsi_cmd_delete, 1, 2 }, { "extract", "", tsi_cmd_extract,1, 1 }, { "quit", "", tsi_cmd_quit, 1, 1 }, { "help", "", tsi_cmd_help, 1, 1 }, }; static dlog_ucbp_t tsi_cmd_match( void ) { tsi_cmd_tbl_t *tblp = tsi_cmd_tbl; tsi_cmd_tbl_t *tblendp = tsi_cmd_tbl + sizeof( tsi_cmd_tbl ) / sizeof( tsi_cmd_tbl[ 0 ] ); if ( tranp->t_inter.i_argc == 0 ) { return 0; } for ( ; tblp < tblendp ; tblp++ ) { if ( ! strncmp( tranp->t_inter.i_argv[ 0 ], tblp->tct_pattern, strlen( tranp->t_inter.i_argv[ 0 ] ))) { break; } } if ( tblp == tblendp ) { return 0; } assert( tblp->tct_argcmin != 0 ); if ( tranp->t_inter.i_argc < tblp->tct_argcmin ) { return 0; } if ( tranp->t_inter.i_argc > tblp->tct_argcmax ) { return 0; } return tblp->tct_ucb; } /* ARGSUSED */ static void tsi_cmd_help( void *ctxp, dlog_pcbp_t pcb, void *pctxp ) { tsi_cmd_tbl_t *tblp = tsi_cmd_tbl; tsi_cmd_tbl_t *tblendp = tsi_cmd_tbl + sizeof( tsi_cmd_tbl ) / sizeof( tsi_cmd_tbl[ 0 ] ); ( * pcb )( pctxp, _("the following commands are available:\n") ); for ( ; tblp < tblendp ; tblp++ ) { ( * pcb )( pctxp, "\t%s %s\n", tblp->tct_pattern, tblp->tct_help ); } } /* walks the tree following the given path. * returns FALSE if syntax error encountered. * returns by reference handles to the named node, its parent, * the first child in its cld list, its ino, if it is a directory, * and if it is selected. * optionally given a dlog print func and context, to be used for diag output. */ static bool_t tsi_walkpath( char *arg, nh_t rooth, nh_t cwdh, dlog_pcbp_t pcb, void *pctxp, nh_t *namedhp, nh_t *parhp, nh_t *cldhp, xfs_ino_t *inop, bool_t *isdirprp, bool_t *isselprp ) { nh_t namedh; nh_t parh; nh_t cldh; node_t *namedp; char *path; char nbuf[ NAME_MAX + 1 ]; xfs_ino_t ino; bool_t isdirpr; bool_t isselpr; /* correct arg if ends with slash (if arg is "/", ok) */ if ( arg && strlen( arg ) > 1 && arg[ strlen( arg ) - 1 ] == '/' ) { arg[ strlen( arg ) - 1 ] = 0; } /* use path to walk down the path argument */ path = arg; /* walk the tree beginning either at the root node * or at the current working directory */ if ( path && *path == '/' ) { assert( rooth != NH_NULL ); namedh = rooth; path++; } else { assert( cwdh != NH_NULL ); namedh = cwdh; } /* get the parent of the starting point, and its cld list */ namedp = Node_map( namedh ); parh = namedp->n_parh; cldh = namedp->n_cldh; ino = namedp->n_ino; isselpr = ( namedp->n_flags & NF_SUBTREE ); assert( namedp->n_flags & NF_ISDIR ); Node_unmap( namedh, &namedp ); isdirpr = BOOL_TRUE; /* walk the tree from the starting point following the path arg. * on leaving this loop, the following will be valid: * namedh - the handle of the node named by path arg; * parh - the parent of the named node; * isdirpr - TRUE if named node is a directory; * cldh - the first child in the named node's cld list. */ for ( ; ; ) { size_t namelen; char *strpatchp; nh_t sibh; /* if no path arg, break */ if ( ! path ) { break; } /* clean out leading slashes. these can occur if the * path arg is ".../////..." or "////..." */ while ( *path == '/' ) { path++; } /* if empty path arg, break */ if ( ! strlen( path )) { break; } /* copy the first name from the path, and advance * the path pointer. */ namelen = strcspn( path, "/" ); assert( namelen < sizeof( nbuf )); strncpy( nbuf, path, namelen ); nbuf[ namelen ] = 0; path += namelen; if ( *path ) { assert( *path == '/' ); strpatchp = path; *strpatchp = 0; path++; } else { strpatchp = 0; } /* be sure the named node is a dir */ if ( ! isdirpr ) { if ( pcb ) { ( * pcb )( pctxp, _( "parent of %s is not a directory\n"), arg ); } return BOOL_FALSE; } /* special case "." */ if ( ! strcmp( nbuf, "." )) { if ( strpatchp ) { *strpatchp = '/'; } continue; } /* special case ".." */ if ( ! strcmp( nbuf, ".." )) { if ( parh == NH_NULL ) { if ( pcb ) { ( * pcb )( pctxp, _( "%s above root\n"), arg ); } return BOOL_FALSE; } namedh = parh; namedp = Node_map( namedh ); parh = namedp->n_parh; cldh = namedp->n_cldh; ino = namedp->n_ino; isselpr = ( namedp->n_flags & NF_SUBTREE ); Node_unmap( namedh, &namedp ); if ( strpatchp ) { *strpatchp = '/'; } continue; } /* look for child with right name */ sibh = cldh; while ( sibh != NH_NULL ) { node_t *sibp; nh_t nextsibh; nrh_t nrh; /* REFERENCED */ int siblen; sibp = Node_map( sibh ); nrh = sibp->n_nrh; nextsibh = sibp->n_sibh; cldh = sibp->n_cldh; ino = sibp->n_ino; isselpr = ( sibp->n_flags & NF_SUBTREE ); isdirpr = ( sibp->n_flags & NF_ISDIR ); Node_unmap( sibh, &sibp ); assert( nrh != NRH_NULL || sibh == persp->p_orphh ); if ( nrh != NRH_NULL ) { siblen = namreg_get( nrh, tranp->t_inter.i_name, sizeof( tranp->t_inter.i_name )); assert( siblen > 0 ); if ( ! strcmp( nbuf, tranp->t_inter.i_name )) { break; } } sibh = nextsibh; } /* if no match, complain */ if ( sibh == NH_NULL ) { if ( pcb ) { ( * pcb )( pctxp, _( "%s not found\n"), arg ); } return BOOL_FALSE; } /* continue search. cldh, ino and isdirpr * set in inner loop above */ parh = namedh; namedh = sibh; if ( strpatchp ) { *strpatchp = '/'; } } *namedhp = namedh; *parhp = parh; *cldhp = cldh; *inop = ino; *isdirprp = isdirpr; *isselprp = isselpr; return BOOL_TRUE; } /* Node abstraction *********************************************************/ static nh_t Node_alloc( xfs_ino_t ino, gen_t gen, nrh_t nrh, dah_t dah, size_t flags ) { nh_t nh; node_t *np; nh = node_alloc( ); if (nh == NH_NULL) return NH_NULL; np = Node_map( nh ); np->n_ino = ino; np->n_nrh = nrh; np->n_dah = dah; np->n_hashh = NH_NULL; np->n_parh = NH_NULL; np->n_sibh = NH_NULL; np->n_sibprevh = NH_NULL; np->n_cldh = NH_NULL; np->n_lnkh = NH_NULL; np->n_gen = gen; np->n_flags = ( u_char_t )flags; memset(np->n_pad, 0, sizeof(np->n_pad)); Node_unmap( nh, &np ); return nh; } static void Node_free( nh_t *nhp ) { node_t *np; np = Node_map( *nhp ); np->n_ino = 0; np->n_gen = 0; if ( np->n_nrh != NRH_NULL ) { namreg_del( np->n_nrh ); np->n_nrh = NRH_NULL; } if ( np->n_dah != DAH_NULL ) { dirattr_del( np->n_dah ); np->n_dah = DAH_NULL; } np->n_flags = 0; np->n_parh = NH_NULL; np->n_sibh = NH_NULL; np->n_sibprevh = NH_NULL; np->n_cldh = NH_NULL; np->n_lnkh = NH_NULL; Node_unmap( *nhp, &np ); node_free( nhp ); } /* * NOTE: Does error handling here and exits. */ static node_t * Node_map( nh_t nh ) { node_t *n = ( node_t * )node_map( nh ); if ( n == NULL ) { mlog( MLOG_ERROR | MLOG_TREE, _( "failed to map in node (node handle: %u)\n"), nh); exit(EXIT_ERROR); } return n; } static void Node_unmap( nh_t nh, node_t **npp ) { node_unmap( nh, ( void ** )npp ); } /* builds a pathname for the specified node, relative to root * returns FALSE if pathname too long */ static bool_t Node2path( nh_t nh, char *path, char *errmsg ) { int remainingcnt; strcpy(path, "."); /* in case root node passed in */ remainingcnt = Node2path_recurse( nh, path, MAXPATHLEN, 0 ); if ( remainingcnt <= 0 ) { node_t *np = Node_map( nh ); xfs_ino_t ino = np->n_ino; gen_t gen = np->n_gen; Node_unmap( nh, &np ); mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_TREE, _( "unable %s ino %llu gen %u: " "relative pathname too long (partial %s)\n"), errmsg, ino, gen, path ); return BOOL_FALSE; } else { return BOOL_TRUE; } } /* returns how much of the buffer remains, assuming the buffer size is * MAXPATHLEN. always null-terminates, but null char not counted in return. * works because the buffer size is secretly 2 * MAXPATHLEN. */ static int Node2path_recurse( nh_t nh, char *buf, int bufsz, int level ) { static __thread path_cache_t cache = { NH_NULL, 0, "" }; node_t *np; nh_t parh; xfs_ino_t ino; gen_t gen; nrh_t nrh; char *oldbuf; int oldbufsz; int namelen; /* recursion termination */ if ( nh == persp->p_rooth ) { return bufsz; } /* if we have a cache hit, no need to recurse any further */ if ( nh == cache.nh ) { assert( bufsz > cache.len ); strcpy( buf, cache.buf ); return bufsz - cache.len; } /* extract useful node members */ np = Node_map( nh ); parh = np->n_parh; ino = np->n_ino; gen = np->n_gen; nrh = np->n_nrh; Node_unmap( nh, &np ); /* build path to parent */ oldbuf = buf; oldbufsz = bufsz; bufsz = Node2path_recurse( parh, buf, bufsz, level+1 ); /* RECURSION */ if ( bufsz <= 0 ) { return bufsz; } buf += oldbufsz - bufsz; /* insert slash if parent not root */ if ( parh != persp->p_rooth ) { assert( bufsz + MAXPATHLEN >= 2 ); *buf++ = '/'; *( buf + 1 ) = 0; bufsz--; if ( bufsz <= 0 ) { return bufsz; } } /* append entry name: special case if in orphanage */ if ( parh == persp->p_orphh ) { namelen = sprintf( buf, "%llu.%u", (unsigned long long)ino, gen ); } else if ( nh == persp->p_orphh ) { namelen = sprintf( buf, "%s", orphname ); } else { assert( nrh != NRH_NULL ); namelen = namreg_get( nrh, buf, ( size_t )bufsz + MAXPATHLEN ); assert( namelen > 0 ); } /* update remaining buffer size */ bufsz -= namelen; assert( bufsz + MAXPATHLEN > 0 ); /* update the cache if we're the target's parent * (and the pathname is not too long) */ if ( level == 1 && bufsz > 0 ) { cache.nh = nh; strcpy( cache.buf, oldbuf ); cache.len = oldbufsz - bufsz; } /* return remaining buffer size */ return bufsz; } /* family abstraction *********************************************************/ static void adopt( nh_t parh, nh_t cldh, nrh_t nrh ) { node_t *parp; node_t *cldp; node_t *sibp; #ifdef TREE_DEBUG mlog(MLOG_DEBUG | MLOG_TREE, "adopt(parent=%llu,child=%llu,node=%llu): \n", parh, cldh, nrh); #endif /* fix up our child - put at front of child list */ cldp = Node_map( cldh ); cldp->n_parh = parh; cldp->n_nrh = nrh; parp = Node_map( parh ); cldp->n_sibh = parp->n_cldh; cldp->n_sibprevh = NH_NULL; Node_unmap( cldh, &cldp ); /* fix up old first child i.e. child's new sibling */ if ( parp->n_cldh != NH_NULL ) { /* if parent has a child */ sibp = Node_map( parp->n_cldh ); sibp->n_sibprevh = cldh; Node_unmap( parp->n_cldh, &sibp ); } /* fix up parent */ parp->n_cldh = cldh; Node_unmap( parh, &parp ); } static nrh_t disown( nh_t cldh ) { node_t *cldp; nrh_t nrh; nh_t parh; node_t *parp; cldp = Node_map( cldh ); nrh = cldp->n_nrh; parh = cldp->n_parh; assert( parh != NH_NULL ); if ( parh == NH_NULL ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_TREE, _( "attempt to disown child " "which has no parent!\n") ); return nrh; } parp = Node_map( parh ); assert( parp->n_cldh != NH_NULL ); if ( parp->n_cldh == NH_NULL ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_TREE, _( "attempt to disown child " "when parent has no children!\n") ); return nrh; } if ( parp->n_cldh == cldh ) { /* child is the first one in the child list */ parp->n_cldh = cldp->n_sibh; if ( cldp->n_sibh != NH_NULL ) { node_t *sibp = Node_map( cldp->n_sibh ); sibp->n_sibprevh = NH_NULL; Node_unmap( cldp->n_sibh, &sibp ); } } else { /* child is further down the child list */ /* use double link list to find previous link */ nh_t prevcldh = cldp->n_sibprevh; node_t *prevcldp; assert(prevcldh != NH_NULL); /* must be a previous */ prevcldp = Node_map( prevcldh ); /* fix up previous */ prevcldp->n_sibh = cldp->n_sibh; Node_unmap( prevcldh, &prevcldp ); /* fix up next */ if ( cldp->n_sibh != NH_NULL ) { node_t *sibp = Node_map( cldp->n_sibh ); sibp->n_sibprevh = prevcldh; Node_unmap( cldp->n_sibh, &sibp ); } } Node_unmap( parh, &parp ); cldp->n_parh = NH_NULL; cldp->n_sibh = NH_NULL; cldp->n_sibprevh = NH_NULL; Node_unmap( cldh, &cldp ); return nrh; } /* recursively marks all nodes in subtree as selected or not selected * for subtree restoral. adjusts ancestors flags accordingly. also adjusts * inomap, which will be used by content.c to see if a media file contains * any nondirs which might need to be restored. */ static void selsubtree( nh_t nh, bool_t sensepr ) { node_t *np; nh_t parh; /* first mark the subtree */ selsubtree_recurse_down( nh, sensepr ); /* get parent */ np = Node_map( nh ); parh = np->n_parh; Node_unmap( nh, &np ); /* next adjust ancestory */ while ( parh != NH_NULL ) { node_t *parp; nh_t newparh; parp = Node_map( parh ); if ( sensepr ) { parp->n_flags |= NF_SUBTREE; } else { bool_t atleastonechildselpr = BOOL_FALSE; nh_t cldh = parp->n_cldh; while ( cldh != NH_NULL ) { node_t *cldp; nh_t nextcldh; bool_t cldsensepr; cldp = Node_map( cldh ); cldsensepr = ( cldp->n_flags & NF_SUBTREE ) ? BOOL_TRUE : BOOL_FALSE; nextcldh = cldp->n_sibh; Node_unmap( cldh, &cldp ); if ( cldsensepr ) { atleastonechildselpr = BOOL_TRUE; break; } cldh = nextcldh; } if ( ! atleastonechildselpr ) { parp->n_flags &= ~NF_SUBTREE; /* DBG could break out here (remember to unmap!) */ } } newparh = parp->n_parh; Node_unmap( parh, &parp ); parh = newparh; } } static void selsubtree_recurse_down( nh_t nh, bool_t sensepr ) { nh_t cldh; /* first mark the node indicated, and get head of cld list */ { node_t *np; bool_t isdirpr; xfs_ino_t ino; gen_t gen; np = Node_map( nh ); if ( sensepr ) { np->n_flags |= NF_SUBTREE; } else { np->n_flags &= ~NF_SUBTREE; } cldh = np->n_cldh; ino = np->n_ino; gen = np->n_gen; isdirpr = ( np->n_flags & NF_ISDIR ); Node_unmap( nh, &np ); if ( ! isdirpr ) { if ( sensepr ) { inomap_rst_add( ino ); } else { /* check hardlist: don't del unless none needed */ nh_t nh; bool_t neededpr = BOOL_FALSE; for ( nh = link_hardh( ino, gen ) ; nh != NH_NULL ; nh = link_nexth( nh )) { node_t *np; u_char_t flags; np = Node_map( nh ); flags = np->n_flags; Node_unmap( nh, &np ); if ( flags & NF_SUBTREE ) { neededpr = BOOL_TRUE; break; } } if ( ! neededpr ) { inomap_rst_del( ino ); } } } } /* then mark all of its children. be sure to skip the orphanage!!! */ while ( cldh != NH_NULL ) { node_t *cldp; nh_t nextcldh; if ( cldh != persp->p_orphh ) { selsubtree_recurse_down( cldh, sensepr ); } cldp = Node_map( cldh ); nextcldh = cldp->n_sibh; Node_unmap( cldh, &cldp ); cldh = nextcldh; } } /* link abstraction *********************************************************/ /* returns handle to head of hard link list */ static nh_t link_hardh( xfs_ino_t ino, gen_t gen ) { return hash_find( ino, gen ); } /* returns following node in hard link list */ static nh_t link_nexth( nh_t nh ) { node_t *np; nh_t nexth; np = Node_map( nh ); nexth = np->n_lnkh; Node_unmap( nh, &np ); return nexth; } /* searches hard link list for exact match. * returns hard link list head */ static nh_t link_matchh( nh_t hardh, nh_t parh, char *name ) { while ( hardh != NH_NULL ) { node_t *np; nh_t nexth; np = Node_map( hardh ); if ( np->n_parh == parh ) { /* REFERENCED */ int namelen; namelen = namreg_get( np->n_nrh, tranp->t_namebuf, sizeof( tranp->t_namebuf )); assert( namelen > 0 ); if ( ! strcmp( name, tranp->t_namebuf )) { Node_unmap( hardh, &np ); break; } } nexth = np->n_lnkh; Node_unmap( hardh, &np ); hardh = nexth; } return hardh; } static void link_in( nh_t nh ) { node_t *np; xfs_ino_t ino; gen_t gen; nh_t hardh; #ifdef TREE_DEBUG mlog(MLOG_DEBUG | MLOG_TREE, "link_in(%llu): map in node\n", nh); #endif /* map in the node to read ino and gen */ np = Node_map( nh ); ino = np->n_ino; gen = np->n_gen; /* see if one or more links already hashed. */ hardh = hash_find( ino, gen ); /* if not hashed, just hash it. otherwise put at end * of hard link (lnk) list. */ if ( hardh == NH_NULL ) { #ifdef TREE_DEBUG mlog(MLOG_DEBUG | MLOG_TREE, "link_in(): hash node in for ino %llu\n", ino); #endif hash_in( nh ); } else { nh_t prevh = hardh; node_t *prevp = Node_map( prevh ); #ifdef TREE_DEBUG mlog(MLOG_DEBUG | MLOG_TREE, "link_in(): put at end of hash list\n"); #endif while ( prevp->n_lnkh != NH_NULL ) { nh_t nexth = prevp->n_lnkh; Node_unmap( prevh, &prevp ); prevh = nexth; prevp = Node_map( prevh ); } prevp->n_lnkh = nh; Node_unmap( prevh, &prevp ); } /* since always put at end of hard link list, make node's * lnk member terminate list. */ np->n_lnkh = NH_NULL; Node_unmap( nh, &np ); #ifdef TREE_DEBUG mlog(MLOG_DEBUG | MLOG_TREE, "link_in(%llu): UNmap in node\n", nh); #endif } static void link_out( nh_t nh ) { node_t *np; xfs_ino_t ino; gen_t gen; nh_t hardh; /* map in the node to read ino and gen */ np = Node_map( nh ); ino = np->n_ino; gen = np->n_gen; /* get head of hard link list */ hardh = hash_find( ino, gen ); assert( hardh != NH_NULL ); /* if node is at head of hard link list, hash it out and * hash in the following node in link list, if there is one. * otherwise, unlink from hardlink list. */ if ( nh == hardh ) { hash_out( nh ); if ( np->n_lnkh != NH_NULL ) { hash_in( np->n_lnkh ); } } else { nh_t prevh = hardh; node_t *prevp = Node_map( prevh ); while ( prevp->n_lnkh != nh ) { nh_t nexth = prevp->n_lnkh; Node_unmap( prevh, &prevp ); prevh = nexth; assert( prevh != NH_NULL ); prevp = Node_map( prevh ); } prevp->n_lnkh = np->n_lnkh; Node_unmap( prevh, &prevp ); } np->n_lnkh = NH_NULL; /* release the mapping */ Node_unmap( nh, &np ); } /* invokes callback for all hardheads * iteration aborted if callback returns FALSE */ static void link_headiter( bool_t ( * cbfp )( void *contextp, nh_t hardh ), void *contextp ) { hash_iter( cbfp, contextp ); } /* iterator for a hard link list. allows deletion of the last node * returned. */ static void link_iter_init( link_iter_context_t *link_iter_contextp, nh_t hardheadh ) { link_iter_contextp->li_headh = hardheadh; link_iter_contextp->li_prevh = NH_NULL; link_iter_contextp->li_lasth = NH_NULL; link_iter_contextp->li_donepr = BOOL_FALSE; } static nh_t link_iter_next( link_iter_context_t *link_iter_contextp ) { node_t *lastp; nh_t tmplasth; /* if already done, return */ if ( link_iter_contextp->li_donepr == BOOL_TRUE ) { return NH_NULL; } /* if no hardhead, done */ if ( link_iter_contextp->li_headh == NH_NULL ) { link_iter_contextp->li_donepr = BOOL_TRUE; return NH_NULL; } /* make tmp copy of last */ tmplasth = link_iter_contextp->li_lasth; /* if no last, must be first call */ if ( tmplasth == NH_NULL ) { assert( link_iter_contextp->li_prevh == NH_NULL ); link_iter_contextp->li_lasth = link_iter_contextp->li_headh; return link_iter_contextp->li_lasth; } /* slide last into prev */ link_iter_contextp->li_prevh = tmplasth; lastp = Node_map( tmplasth ); link_iter_contextp->li_lasth = lastp->n_lnkh; Node_unmap( tmplasth, &lastp ); /* if NULL, flag done */ if ( link_iter_contextp->li_lasth == NH_NULL ) { link_iter_contextp->li_donepr = BOOL_TRUE; } /* return the last handle */ return link_iter_contextp->li_lasth; } /* ARGSUSED */ void link_iter_unlink( link_iter_context_t *link_iter_contextp, nh_t nh ) { node_t *lastp; nh_t nexth; /* sanity checks */ assert( link_iter_contextp->li_lasth != NH_NULL ); assert( nh == link_iter_contextp->li_lasth ); /* get the next node in list */ lastp = Node_map( link_iter_contextp->li_lasth ); nexth = lastp->n_lnkh; lastp->n_lnkh = NH_NULL; Node_unmap( link_iter_contextp->li_lasth, &lastp ); if ( link_iter_contextp->li_lasth == link_iter_contextp->li_headh ) { assert( link_iter_contextp->li_prevh == NH_NULL ); hash_out( link_iter_contextp->li_headh ); link_iter_contextp->li_headh = nexth; if ( nexth != NH_NULL ) { hash_in( nexth ); } } else { node_t *prevp; assert( link_iter_contextp->li_prevh != NH_NULL ); prevp = Node_map( link_iter_contextp->li_prevh ); prevp->n_lnkh = nexth; Node_unmap( link_iter_contextp->li_prevh, &prevp ); } link_iter_contextp->li_lasth = link_iter_contextp->li_prevh; link_iter_contextp->li_prevh = NH_NULL; } /* hash abstraction *********************************************************/ #define HASHLEN_MIN ( pgsz / sizeof( nh_t )) static bool_t hash_init( size64_t vmsz, size64_t dircnt, size64_t nondircnt, char *perspath ) { size64_t hashlen; size64_t loghashlen; size64_t vmlen; size64_t hashlenmax; ix_t hix; /* sanity checks */ assert( pgsz % sizeof( nh_t ) == 0 ); /* calculate the size of the hash array. must be a power of two, * and a multiple of the page size. don't use more than the available * vm. but enforce a minimum. */ vmlen = vmsz / sizeof( nh_t ); hashlenmax = min( vmlen, SIZEMAX ); hashlen = ( dircnt + nondircnt ); hashlen = max( hashlen, ( size64_t )HASHLEN_MIN ); hashlen = min( hashlen, hashlenmax ); for ( loghashlen = 0 ; ( ( size64_t )1 << loghashlen ) <= hashlen ; loghashlen++ ) ; assert( loghashlen > 0 ); hashlen = ( size64_t )1 << loghashlen; if (hashlen > hashlenmax) hashlen >>= 1; assert( hashlen <= hashlenmax ); /* record hash size in persistent state */ persp->p_hashsz = hashlen * sizeof( nh_t ); /* map the hash array just after the persistent state header */ assert( persp->p_hashsz <= SIZEMAX ); assert( ! ( persp->p_hashsz % ( size64_t )pgsz )); assert( ! ( PERSSZ % pgsz )); tranp->t_hashp = ( nh_t * ) mmap_autogrow( ( size_t )persp->p_hashsz, tranp->t_persfd, ( off64_t )PERSSZ ); if ( tranp->t_hashp == ( nh_t * )-1 ) { mlog( MLOG_NORMAL | MLOG_TREE, _( "unable to mmap hash array into %s: %s\n"), perspath, strerror( errno )); return BOOL_FALSE; } /* initialize the hash array to all NULL node handles */ for ( hix = 0 ; hix < ( ix_t )hashlen ; hix++ ) { tranp->t_hashp[ hix ] = NH_NULL; } /* build a hash mask. this works because hashlen is a power of two. * record in persistent state. */ assert( hashlen - 1 <= SIZEMAX ); persp->p_hashmask = ( size_t )( hashlen - 1 ); return BOOL_TRUE; } static bool_t hash_sync( char *perspath ) { size64_t hashsz; /* sanity checks */ assert( pgsz % sizeof( nh_t ) == 0 ); /* retrieve the hash size from the persistent state */ hashsz = persp->p_hashsz; assert( ! ( hashsz % sizeof( nh_t ))); /* map the hash array just after the persistent state header */ assert( hashsz <= SIZEMAX ); assert( ! ( hashsz % ( size64_t )pgsz )); assert( ! ( PERSSZ % pgsz )); tranp->t_hashp = ( nh_t * ) mmap_autogrow( ( size_t )hashsz, tranp->t_persfd, ( off64_t )PERSSZ ); if ( tranp->t_hashp == ( nh_t * )-1 ) { mlog( MLOG_NORMAL | MLOG_TREE, _( "unable to mmap hash array into %s: %s\n"), perspath, strerror( errno )); return BOOL_FALSE; } return BOOL_TRUE; } static inline size_t hash_val(xfs_ino_t ino, size_t hashmask) { ino += ~(ino << 15); ino ^= (ino >> 10); ino += (ino << 3); ino ^= (ino >> 6); ino += ~(ino << 11); ino ^= (ino >> 16); return (size_t)ino & hashmask; } static void hash_in( nh_t nh ) { node_t *np; xfs_ino_t ino; size_t hix; nh_t *entryp; /* get a mapping to the node */ np = Node_map( nh ); /* get ino from node */ ino = np->n_ino; /* assert not already in */ assert( hash_find( np->n_ino, np->n_gen ) == NH_NULL ); /* calculate the hash index */ hix = hash_val(ino, persp->p_hashmask); /* get a pointer to the indexed hash array entry */ entryp = &tranp->t_hashp[ hix ]; /* insert into the list, at the head */ assert( np->n_hashh == NH_NULL ); np->n_hashh = *entryp; *entryp = nh; /* release the mapping */ Node_unmap( nh, &np ); } static void hash_out( nh_t nh ) { node_t *np; xfs_ino_t ino; nh_t hashheadh; size_t hix; nh_t *entryp; /* get a mapping to the node */ np = Node_map( nh ); /* get the ino */ ino = np->n_ino; /* get a pointer to the hash array entry */ hix = hash_val(ino, persp->p_hashmask); entryp = &tranp->t_hashp[ hix ]; /* get the handle of the first node in the appropriate hash array */ hashheadh = *entryp; assert( hashheadh != NH_NULL ); /* if node is first in list, replace entry with following node. * otherwise, walk the list until found. */ if ( hashheadh == nh ) { *entryp = np->n_hashh; } else { nh_t prevh = hashheadh; node_t *prevp = Node_map( prevh ); while ( prevp->n_hashh != nh ) { nh_t nexth = prevp->n_hashh; Node_unmap( prevh, &prevp ); prevh = nexth; assert( prevh != NH_NULL ); prevp = Node_map( prevh ); } prevp->n_hashh = np->n_hashh; Node_unmap( prevh, &prevp ); } np->n_hashh = NH_NULL; /* release the mapping */ Node_unmap( nh, &np ); } static nh_t hash_find( xfs_ino_t ino, gen_t gen ) { nh_t nh; node_t *np; size_t hix; /* get handle to first node in appropriate hash array */ hix = hash_val(ino, persp->p_hashmask); nh = tranp->t_hashp[ hix ]; /* if list empty, return null handle */ if ( nh == NH_NULL ) { return NH_NULL; } #ifdef TREE_DEBUG mlog(MLOG_DEBUG | MLOG_TREE, "hash_find(%llu,%u): traversing hash link list\n", ino, gen); #endif /* walk the list until found. */ np = Node_map( nh ); while ( np->n_ino != ino || np->n_gen != gen ) { nh_t nextnh = np->n_hashh; Node_unmap( nh, &np ); nh = nextnh; if ( nh == NH_NULL ) { return NH_NULL; } np = Node_map( nh ); } Node_unmap( nh, &np ); #ifdef TREE_DEBUG mlog(MLOG_DEBUG | MLOG_TREE, "hash_find(): return nh = %llu\n", nh); #endif return nh; } /* invokes callback for all hashed nodes * iteration aborted if callback returns FALSE * call back may hash out and free the node, so * must figure next node prior to calling callback. */ static void hash_iter( bool_t ( * cbfp )( void *contextp, nh_t hashh ), void *contextp ) { ix_t hix; size64_t hashlen = persp->p_hashsz / sizeof( nh_t ); for ( hix = 0 ; hix < ( ix_t )hashlen ; hix++ ) { nh_t nh = tranp->t_hashp[ hix ]; while ( nh != NH_NULL ) { node_t *np; nh_t nexth; bool_t ok; np = Node_map( nh ); nexth = np->n_hashh; Node_unmap( nh, &np ); ok = ( * cbfp )( contextp, nh ); if ( ! ok ) { return; } nh = nexth; } } } /* misc static functions *****************************************************/ #ifdef TREE_CHK /* use hash array to iterate through all nodes. check * each node's hash, hardlink, namreg, dirattr, parent, * and sibling handles. */ static bool_t Node_chk( nh_t nh, nh_t *nexthashhp, nh_t *nextlnkhp ) { node_t *np; node_t n; char nambuf[ NAME_MAX + 1 ]; bool_t okaccum; mlog( MLOG_NITTY + 1 | MLOG_TREE, "checking node nh == 0x%x\n", nh ); okaccum = BOOL_TRUE; if ( nexthashhp ) { *nexthashhp = NH_NULL; } assert( nextlnkhp ); *nextlnkhp = NH_NULL; np = Node_map( nh ); assert( np ); n = *np; Node_unmap( nh, &np ); if ( ! nexthashhp && n.n_hashh != NH_NULL ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_TREE, _( "nh 0x%x np 0x%x hash link not null\n"), nh, np ); okaccum = BOOL_FALSE; } if ( n.n_hashh != NH_NULL ) { np = Node_map( n.n_hashh ); Node_unmap( n.n_hashh, &np ); } if ( n.n_lnkh != NH_NULL ) { np = Node_map( n.n_lnkh ); Node_unmap( n.n_lnkh, &np ); } if ( n.n_parh != NH_NULL ) { np = Node_map( n.n_parh ); Node_unmap( n.n_parh, &np ); } if ( n.n_cldh != NH_NULL ) { np = Node_map( n.n_cldh ); Node_unmap( n.n_cldh, &np ); } if ( n.n_sibh != NH_NULL ) { np = Node_map( n.n_sibh ); Node_unmap( n.n_sibh, &np ); } if ( n.n_nrh != NRH_NULL ) { int rval; rval = namreg_get( n.n_nrh, nambuf, sizeof( nambuf )); assert( rval >= 0 ); } if ( n.n_dah != DAH_NULL ) { ( void )dirattr_get_mode( n.n_dah ); } if ( nexthashhp ) { *nexthashhp = n.n_hashh; } *nextlnkhp = n.n_lnkh; return okaccum; } bool_t tree_chk( void ) { ix_t hix; size64_t hashlen = persp->p_hashsz / sizeof( nh_t ); bool_t ok; bool_t okaccum; okaccum = BOOL_TRUE; for ( hix = 0 ; hix < ( ix_t )hashlen ; hix++ ) { nh_t hashh = tranp->t_hashp[ hix ]; mlog( MLOG_NITTY + 1 | MLOG_TREE, "checking hix %u\n", hix ); while ( hashh != NH_NULL ) { nh_t lnkh; ok = Node_chk( hashh, &hashh, &lnkh ); if ( ! ok ) { okaccum = BOOL_FALSE; } while ( lnkh != NH_NULL ) { ok = Node_chk( lnkh, 0, &lnkh ); if ( ! ok ) { okaccum = BOOL_FALSE; } } } } ok = tree_chk2( ); if ( ! ok ) { okaccum = BOOL_FALSE; } return okaccum; } static bool_t tree_chk2_recurse( nh_t cldh, nh_t parh ); static bool_t tree_chk2( void ) { node_t *rootp; nh_t cldh; bool_t ok; mlog( MLOG_DEBUG | MLOG_TREE, "tree hierarchy check\n" ); rootp = Node_map( persp->p_rooth ); cldh = rootp->n_cldh; Node_unmap( persp->p_rooth, &rootp ); ok = tree_chk2_recurse( cldh, persp->p_rooth ); return ok; } static bool_t tree_chk2_recurse( nh_t cldh, nh_t parh ) { bool_t okaccum = BOOL_TRUE; assert( parh != NH_NULL ); while ( cldh != NH_NULL ) { node_t *cldp; xfs_ino_t ino; gen_t gen; nh_t nodeparh; nrh_t nrh; nh_t grandcldh; nh_t nextcldh; bool_t ok; cldp = Node_map( cldh ); ino = cldp->n_ino; gen = cldp->n_gen; nodeparh = cldp->n_parh; nrh = cldp->n_nrh; grandcldh = cldp->n_cldh; nextcldh = cldp->n_sibh; Node_unmap( cldh, &cldp ); if ( parh == persp->p_orphh ) { sprintf( tranp->t_namebuf, "%llu.%u", ino, gen ); } else if ( cldh == persp->p_orphh ) { sprintf( tranp->t_namebuf, "%llu.%u", ino, gen ); } else { int namelen; namelen = namreg_get( nrh, tranp->t_namebuf, sizeof( tranp->t_namebuf )); assert( namelen >= 0 ); } if ( nodeparh == NH_NULL ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_TREE, _( "node %x %s %llu %u parent NULL\n"), cldh, tranp->t_namebuf, ino, gen ); return BOOL_FALSE; } else if ( nodeparh != parh ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_TREE, _( "node %x %s %llu %u parent mismatch: " "nodepar %x par %x\n"), cldh, tranp->t_namebuf, ino, gen, nodeparh, parh ); return BOOL_FALSE; } else { mlog( MLOG_DEBUG | MLOG_TREE, "node %x %s %llu %u parent %x\n", cldh, tranp->t_namebuf, ino, gen, parh ); } ok = tree_chk2_recurse( grandcldh, cldh ); if ( ! ok ) { okaccum = BOOL_FALSE; } cldh = nextcldh; } return okaccum; } #endif /* TREE_CHK */ static char *whites = " \t\r\n\v\f"; static int is_white( char c ); static void fix_escape( char *string, char *liter ); static void fix_quoted_span( char *string, char *liter ); static void collapse_white( char *string, char *liter ); static size_t distance_to_space( char *s, char *l ); static int parse( int slotcnt, char **slotbuf, char *string ) { char *liter; char *s; char *l; size_t wordcnt; /* sanity checkcs */ assert( slotcnt >= 0 ); /* allocate a companion to the input string for identifying * characters which are to be interpreted literally. */ liter = ( char * )calloc( 1, strlen( string ) + 1 ); if ( ! liter ) { return -1; } /* pass 1: collapse escape sequences, identifying characters which * are to be interpreted literally */ for ( s = string, l = liter ; *s ; s++, l++ ) { if ( *s == '\\' && ! *l ) { fix_escape( s, l ); } } /* pass 2: collapse quoted spans, identifying characters which * are to be interpreted literally */ for ( s = string, l = liter ; *s ; s++, l++ ) { if ( *s == '\"' && ! *l ) { fix_quoted_span( s, l ); } } /* pass 3: collapse white space spans into a single space */ for ( s = string, l = liter ; *s ; s++, l++ ) { if ( is_white( *s ) && ! *l ) { collapse_white( s, l ); } } /* pass 4: identify and null-terminate words */ wordcnt = 0; s = string; l = liter; while ( *s ) { size_t d; if ( wordcnt < ( size_t )slotcnt ) { slotbuf[ wordcnt ] = s; } wordcnt++; d = distance_to_space( s, l ); s += d; l += d; if ( *s ) { *s = 0; s++; l++; } } free( ( void * )liter ); return ( int )wordcnt; } struct escape_table { char sequence; char substitute; }; typedef struct escape_table escape_table_t; static escape_table_t escape_table[ ] = { { 'n', '\n' }, { 't', '\t' }, { 'v', '\v' }, { 'b', '\b' }, { 'r', '\r' }, { 'f', '\f' }, { 'f', '\f' }, { 'a', '\a' }, { '\\', '\\' } }; static void shrink( char *s, size_t cnt ); static int is_hex( char c ); static size_t hex_to_size( char c ); static int is_octal( char c ); static size_t octal_to_size( char c ); static void fix_escape( char *string, char *liter ) { escape_table_t *ep; escape_table_t *endep; /* first look for special escapes described in table */ ep = escape_table; endep = escape_table + ( sizeof( escape_table ) / sizeof( escape_table[ 0 ] )); for ( ; ep < endep ; ep++ ) { if ( string[ 1 ] == ep->sequence ) { string[ 0 ] = ep->substitute; liter[ 0 ] = ( char )1; shrink( &string[ 1 ], 1 ); shrink( &liter[ 1 ], 1 ); return; } } /* detect white space escapes */ if ( is_white( string[ 1 ] )) { liter[ 0 ] = ( char )1; shrink( &string[ 0 ], 1 ); shrink( &liter[ 1 ], 1 ); return; } /* detect hex escapes (don't allow null) */ if ( string[ 1 ] == 'x' ) { size_t hexlen; size_t accum; accum = 0; for ( hexlen = 0 ; hexlen < 2 && is_hex( string[ 2 + hexlen ] ) ; hexlen++ ) { accum *= 16; accum += hex_to_size( string[ 2 + hexlen ] ); } if ( hexlen && accum ) { string[ 0 ] = ( char )accum; liter[ 0 ] = ( char )1; shrink( &string[ 1 ], 1 + hexlen ); shrink( &liter[ 1 ], 1 + hexlen ); return; } } /* detect octal escapes (don't allow null) */ if ( is_octal( string[ 1 ] )) { size_t octallen; size_t accum; accum = octal_to_size( string[ 1 ] ); for ( octallen = 1 ; octallen < 3 && is_octal( string[ 1 + octallen ] ) ; octallen++ ) { accum *= 8; accum += octal_to_size( string[ 1 + octallen ] ); } if ( accum ) { string[ 0 ] = ( char )accum; liter[ 0 ] = ( char )1; shrink( &string[ 1 ], octallen ); shrink( &liter[ 1 ], octallen ); return; } } /* didn't match any escape sequences, so assume literal */ liter[ 0 ] = ( char )1; } static void fix_quoted_span( char *string, char *liter ) { char *s; char *l; /* first cover the leading quote */ shrink( string, 1 ); shrink( liter, 1 ); /* scan for the next non-literal quote, marking all * characters in between as literal */ for ( s = string, l = liter ; *s && ( *s != '\"' || *l ) ; s++, l++ ) { *l = ( char )1; } if ( *s ) { shrink( s, 1 ); shrink( l, 1 ); } } static void collapse_white( char *string, char *liter ) { char *s; char *l; size_t cnt; cnt = 0; for ( s = string, l = liter ; is_white( *s ) && ! *l ; s++, l++ ) { cnt++; } string[ 0 ] = ' '; if ( cnt > 1 ) { shrink( &string[ 1 ], cnt - 1 ); shrink( &liter[ 1 ], cnt - 1 ); } } static size_t distance_to_space( char *s, char *l ) { size_t cnt; for ( cnt = 0 ; *s && ( ! is_white( *s ) || *l ) ; s++, l++ ) { cnt++; } return cnt; } static void shrink( char *s, size_t cnt ) { strcpy( s, s + cnt ); } static int is_white( char c ) { if ( c && strchr( whites, ( int )c )) { return 1; } else { return 0; } } static int is_hex( char c ) { if ( c >= '0' && c <= '9' ) { return 1; } if ( c >= 'a' && c <= 'f' ) { return 1; } if ( c >= 'A' && c <= 'F' ) { return 1; } return 0; } static size_t hex_to_size( char c ) { if ( c >= '0' && c <= '9' ) { return ( size_t )( c - '0' ); } if ( c >= 'a' && c <= 'f' ) { return ( size_t )( c - 'a' ) + ( size_t )0xa; } if ( c >= 'A' && c <= 'F' ) { return ( size_t )( c - 'A' ) + ( size_t )0xa; } return 0; } static int is_octal( char c ) { if ( c >= '0' && c <= '7' ) { return 1; } return 0; } static size_t octal_to_size( char c ) { if ( c >= '0' && c <= '7' ) { return ( size_t )( c - '0' ); } return 0; } static int mkdir_r(char *path) { struct stat sbuf; if (stat(path, &sbuf) < 0) { if (mkdir_r(dirname(strdup(path))) < 0) return -1; return mkdir(path, 0755); } else if ((sbuf.st_mode & S_IFDIR) == 0) { mlog( MLOG_TRACE | MLOG_ERROR | MLOG_TREE, _( "%s is not a directory\n"), path); mlog_exit(EXIT_ERROR, RV_EXISTS); exit(1); } return 0; } xfsdump-3.1.6+nmu1/restore/mmap.c0000644000000000000000000000251212620476160013536 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include /* * our custom mmap b/c Linux doesn't have MAP_AUTOGROW * and for an empty file we need to write to last byte * to ensure it can be accessed */ void * mmap_autogrow(size_t len, int fd, off_t offset) { struct stat buf; char nul_buffer[] = ""; /* prealloc file if it is an empty file */ if (fstat(fd, &buf) == -1) {; return (void*)MAP_FAILED; } if (buf.st_size < offset+len) { (void)lseek(fd, offset+len-1, SEEK_SET); (void)write(fd, nul_buffer, 1); } return mmap( 0, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset ); } xfsdump-3.1.6+nmu1/restore/dirattr.h0000644000000000000000000000573212620476160014271 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef DIRATTR_H #define DIRATTR_H /* dah_t - handle to registered directory attributes * a special handle is reserved for the caller's convenience, * to indicate no directory attributes have been registered. */ typedef size32_t dah_t; #define DAH_NULL SIZE32MAX /* dirattr_init - creates the directory attributes registry. * resync indicates if an existing context should be re-opened. * returns FALSE if an error encountered. if NOT resync, * dircnt hints at number of directories to expect. */ extern bool_t dirattr_init( char *housekeepingdir, bool_t resync, uint64_t dircnt ); /* dirattr_cleanup - removes all traces */ extern void dirattr_cleanup( void ); /* dirattr_add - registers a directory's attributes. knows how to interpret * the filehdr. returns handle for use with dirattr_get_...(). */ extern dah_t dirattr_add( filehdr_t *fhdrp ); /* dirattr_update - modifies existing registered attributes */ extern void dirattr_update( dah_t dah, filehdr_t *fhdrp ); /* dirattr_del - frees dirattr no longer needed */ extern void dirattr_del( dah_t dah ); /* dirattr_get_... - retrieve various attributes */ mode_t dirattr_get_mode( dah_t dah ); uid_t dirattr_get_uid( dah_t dah ); gid_t dirattr_get_gid( dah_t dah ); time32_t dirattr_get_atime( dah_t dah ); time32_t dirattr_get_mtime( dah_t dah ); time32_t dirattr_get_ctime( dah_t dah ); uint32_t dirattr_get_xflags( dah_t dah ); uint32_t dirattr_get_extsize( dah_t dah ); uint32_t dirattr_get_projid( dah_t dah ); uint32_t dirattr_get_dmevmask( dah_t dah ); uint32_t dirattr_get_dmstate( dah_t dah ); /* dirattr_flush - flush dirattr I/O buffer. Returns 0 if successful. */ extern rv_t dirattr_flush( void ); /* dirattr_addextattr - record an extended attribute. second argument is * ptr to extattrhdr_t, with extattr name and value appended as * described by hdr. */ extern void dirattr_addextattr( dah_t dah, extattrhdr_t *ahdrp ); /* dirattr_cb_extattr - calls back for every extended attribute associated with * the given dah. stops iteration and returnd FALSE if cbfunc returns FALSE, * else returns TRUE. */ extern bool_t dirattr_cb_extattr( dah_t dah, bool_t ( * cbfunc )( extattrhdr_t *ahdrp, void *ctxp ), extattrhdr_t *ahdrp, void *ctxp ); #endif /* DIRATTR_H */ xfsdump-3.1.6+nmu1/restore/node.h0000644000000000000000000000413712620476160013543 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef NODE_H #define NODE_H /* node.[ch] - abstract pool of nodes * * operators alloc, free, map, and unmap nodes. */ typedef size32_t nh_t; #define NH_NULL SIZE32MAX /* node_init - creates a new node abstraction. * user reserves one byte per node for use by the node abstraction */ extern bool_t node_init( int fd, /* backing store */ off64_t off, /* offset into backing store */ size_t nodesz, /* node size */ ix_t nodehkix, /* my housekeeping byte */ size_t alignsz, /* node alignment requirement */ size64_t vmsz, /* abstractions's share of VM */ size64_t dir_nondir); /* num of dirs + nondirs */ /* node_sync - syncs up with existing node abstraction persistent state */ extern bool_t node_sync( int fd, off64_t off ); /* node_alloc - allocates a node, returning a handle. * returns NULL handle if no space left. */ extern nh_t node_alloc( void ); /* node_map - returns a pointer to the node identified by the node handle. * pointer remains valid until node_unmap called. */ extern void *node_map( nh_t node_handle ); /* node_unmap - unmaps the node. * SIDE-EFFECT: sets *nodepp to 0. */ extern void node_unmap( nh_t node_handle, void **nodepp ); /* node_free - frees a previously allocated node. * SIDE-EFFECT: sets *node_handlep to NODE_HANDLE_NULL. */ extern void node_free( nh_t *node_handlep ); #endif /* NODE_H */ xfsdump-3.1.6+nmu1/restore/inomap.c0000644000000000000000000003526312620476160014100 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "types.h" #include "util.h" #include "openutil.h" #include "mlog.h" #include "global.h" #include "drive.h" #include "media.h" #include "content.h" #include "content_inode.h" #include "inomap.h" #include "mmap.h" #include "arch_xlate.h" /* structure definitions used locally ****************************************/ /* restores the inomap into a file */ #define PERS_NAME "inomap" /* reserve the first page for persistent state */ struct pers { size64_t hnkcnt; /* number of hunks in map */ size64_t segcnt; /* number of segments */ xfs_ino_t last_ino_added; }; typedef struct pers pers_t; #define PERSSZ perssz /* declarations of externally defined global symbols *************************/ extern size_t pgsz; /* forward declarations of locally defined static functions ******************/ /* inomap primitives */ static int map_getset( xfs_ino_t, int, bool_t ); static int map_set( xfs_ino_t ino, int ); static seg_t * map_getsegment( xfs_ino_t ino ); /* definition of locally defined global variables ****************************/ /* definition of locally defined static variables *****************************/ static int pers_fd = -1; /* file descriptor for persistent inomap backing store */ /* context for inomap construction - initialized by inomap_restore_pers */ static uint64_t hnkcnt; static uint64_t segcnt; static hnk_t *roothnkp = 0; static hnk_t *tailhnkp; static seg_t *lastsegp; static xfs_ino_t last_ino_added; /* map context and operators */ static inline void SEG_SET_BITS( seg_t *segp, xfs_ino_t ino, int state ) { register xfs_ino_t relino; register uint64_t mask; register uint64_t clrmask; relino = ino - segp->base; mask = ( uint64_t )1 << relino; clrmask = ~mask; switch( state ) { case 0: segp->lobits &= clrmask; segp->mebits &= clrmask; segp->hibits &= clrmask; break; case 1: segp->lobits |= mask; segp->mebits &= clrmask; segp->hibits &= clrmask; break; case 2: segp->lobits &= clrmask; segp->mebits |= mask; segp->hibits &= clrmask; break; case 3: segp->lobits |= mask; segp->mebits |= mask; segp->hibits &= clrmask; break; case 4: segp->lobits &= clrmask; segp->mebits &= clrmask; segp->hibits |= mask; break; case 5: segp->lobits |= mask; segp->mebits &= clrmask; segp->hibits |= mask; break; case 6: segp->lobits &= clrmask; segp->mebits |= mask; segp->hibits |= mask; break; case 7: segp->lobits |= mask; segp->mebits |= mask; segp->hibits |= mask; break; } } static inline int SEG_GET_BITS( seg_t *segp, xfs_ino_t ino ) { int state; register xfs_ino_t relino; register uint64_t mask; relino = ino - segp->base; mask = ( uint64_t )1 << relino; if ( segp->lobits & mask ) { state = 1; } else { state = 0; } if ( segp->mebits & mask ) { state |= 2; } if ( segp->hibits & mask ) { state |= 4; } return state; } /* definition of locally defined global functions ****************************/ rv_t inomap_restore_pers( drive_t *drivep, content_inode_hdr_t *scrhdrp, char *hkdir ) { drive_ops_t *dop = drivep->d_opsp; char *perspath; pers_t *persp; hnk_t *pershnkp; hnk_t *tmphnkp; int fd; /* REFERENCED */ int nread; int rval; /* REFERENCED */ int rval1; int i; bool_t ok; /* sanity checks */ assert( INOPERSEG == ( sizeof( (( seg_t * )0 )->lobits ) * NBBY )); assert( sizeof( hnk_t ) == HNKSZ ); assert( sizeof( pers_t ) <= PERSSZ ); /* get inomap info from media hdr */ hnkcnt = scrhdrp->cih_inomap_hnkcnt; segcnt = scrhdrp->cih_inomap_segcnt; last_ino_added = scrhdrp->cih_inomap_lastino; /* truncate and open the backing store */ perspath = open_pathalloc( hkdir, PERS_NAME, 0 ); ( void )unlink( perspath ); fd = open( perspath, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR ); if ( fd < 0 ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "could not open %s: %s\n"), perspath, strerror( errno )); return RV_ERROR; } /* mmap the persistent hdr and space for the map */ persp = ( pers_t * ) mmap_autogrow( PERSSZ + sizeof( hnk_t ) * ( size_t )hnkcnt, fd, ( off64_t )0 ); if ( persp == ( pers_t * )-1 ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "unable to map %s: %s\n"), perspath, strerror( errno )); return RV_ERROR; } /* load the pers hdr */ persp->hnkcnt = hnkcnt; persp->segcnt = segcnt; persp->last_ino_added = last_ino_added; tmphnkp = ( hnk_t * )calloc( ( size_t )hnkcnt, sizeof( hnk_t )); assert( tmphnkp ); /* read the map in from media */ nread = read_buf( ( char * )tmphnkp, sizeof( hnk_t ) * ( size_t )hnkcnt, ( void * )drivep, ( rfp_t )dop->do_read, ( rrbfp_t )dop->do_return_read_buf, &rval ); pershnkp = (hnk_t *)((char *)persp + PERSSZ); for(i = 0; i < hnkcnt; i++) { xlate_hnk(&tmphnkp[i], &pershnkp[i], 1); } free(tmphnkp); mlog(MLOG_NITTY, "inomap_restore_pers: pre-munmap\n"); /* close up */ rval1 = munmap( ( void * )persp, PERSSZ + sizeof( hnk_t ) * ( size_t )hnkcnt ); assert( ! rval1 ); ( void )close( fd ); free( ( void * )perspath ); mlog(MLOG_NITTY, "inomap_restore_pers: post-munmap\n"); /* check the return code from read */ switch( rval ) { case 0: assert( ( size_t )nread == sizeof( hnk_t ) * ( size_t )hnkcnt ); ok = inomap_sync_pers( hkdir ); if ( ! ok ) { return RV_ERROR; } return RV_OK; case DRIVE_ERROR_EOD: case DRIVE_ERROR_EOF: case DRIVE_ERROR_EOM: case DRIVE_ERROR_MEDIA: case DRIVE_ERROR_CORRUPTION: return RV_CORRUPT; case DRIVE_ERROR_DEVICE: return RV_DRIVE; case DRIVE_ERROR_CORE: default: return RV_CORE; } } /* peels inomap from media */ rv_t inomap_discard( drive_t *drivep, content_inode_hdr_t *scrhdrp ) { drive_ops_t *dop = drivep->d_opsp; uint64_t tmphnkcnt; /* REFERENCED */ int nread; int rval; /* get inomap info from media hdr */ tmphnkcnt = scrhdrp->cih_inomap_hnkcnt; /* read the map in from media */ nread = read_buf( 0, sizeof( hnk_t ) * ( size_t )tmphnkcnt, ( void * )drivep, ( rfp_t )dop->do_read, ( rrbfp_t )dop->do_return_read_buf, &rval ); /* check the return code from read */ switch( rval ) { case 0: assert( ( size_t )nread == sizeof( hnk_t ) * ( size_t )hnkcnt ); return RV_OK; case DRIVE_ERROR_EOD: case DRIVE_ERROR_EOF: case DRIVE_ERROR_EOM: case DRIVE_ERROR_MEDIA: case DRIVE_ERROR_CORRUPTION: return RV_CORRUPT; case DRIVE_ERROR_DEVICE: return RV_DRIVE; case DRIVE_ERROR_CORE: default: return RV_CORE; } } bool_t inomap_sync_pers( char *hkdir ) { char *perspath; pers_t *persp; hnk_t *hnkp; /* sanity checks */ assert( sizeof( hnk_t ) == HNKSZ ); /* only needed once per session */ if ( pers_fd >= 0 ) { return BOOL_TRUE; } /* open the backing store. if not present, ok, hasn't been created yet */ perspath = open_pathalloc( hkdir, PERS_NAME, 0 ); pers_fd = open( perspath, O_RDWR ); if ( pers_fd < 0 ) { return BOOL_TRUE; } /* mmap the persistent hdr */ persp = ( pers_t * ) mmap_autogrow( PERSSZ, pers_fd, ( off64_t )0 ); if ( persp == ( pers_t * )-1 ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "unable to map %s hdr: %s\n"), perspath, strerror( errno )); return BOOL_FALSE; } /* read the pers hdr */ hnkcnt = persp->hnkcnt; segcnt = persp->segcnt; last_ino_added = persp->last_ino_added; /* mmap the pers inomap */ assert( hnkcnt * sizeof( hnk_t ) <= ( size64_t )INT32MAX ); roothnkp = ( hnk_t * ) mmap_autogrow( sizeof( hnk_t ) * ( size_t )hnkcnt, pers_fd, ( off64_t )PERSSZ ); if ( roothnkp == ( hnk_t * )-1 ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "unable to map %s: %s\n"), perspath, strerror( errno )); return BOOL_FALSE; } /* correct the next pointers */ for ( hnkp = roothnkp ; hnkp < roothnkp + ( int )hnkcnt - 1 ; hnkp++ ) { hnkp->nextp = hnkp + 1; } hnkp->nextp = 0; /* calculate the tail pointers */ tailhnkp = hnkp; assert( hnkcnt > 0 ); lastsegp = &tailhnkp->seg[ ( int )( segcnt - SEGPERHNK * ( hnkcnt - 1 ) - 1 ) ]; /* now all inomap operators will work */ return BOOL_TRUE; } /* de-allocate the persistent inomap */ void inomap_del_pers( char *hkdir ) { char *perspath = open_pathalloc( hkdir, PERS_NAME, 0 ); ( void )unlink( perspath ); free( ( void * )perspath ); } /* mark all included non-dirs as MAP_NDR_NOREST */ void inomap_sanitize( void ) { hnk_t *hnkp; seg_t *segp; /* step through all hunks, segs, and inos */ for ( hnkp = roothnkp ; hnkp != 0 ; hnkp = hnkp->nextp ) { for ( segp = hnkp->seg ; segp < hnkp->seg + SEGPERHNK ; segp++ ) { xfs_ino_t ino; if ( hnkp == tailhnkp && segp > lastsegp ) { return; } for ( ino = segp->base ; ino < segp->base + INOPERSEG ; ino++ ) { int state; if ( ino > last_ino_added ) { return; } state = SEG_GET_BITS( segp, ino ); if ( state == MAP_NDR_CHANGE ) { state = MAP_NDR_NOREST; SEG_SET_BITS( segp, ino, state ); } } } } } /* called to mark a non-dir ino as TO be restored */ void inomap_rst_add( xfs_ino_t ino ) { assert( pers_fd >= 0 ); ( void )map_set( ino, MAP_NDR_CHANGE ); } /* called to mark a non-dir ino as NOT to be restored */ void inomap_rst_del( xfs_ino_t ino ) { assert( pers_fd >= 0 ); ( void )map_set( ino, MAP_NDR_NOREST ); } /* called to ask if any inos in the given range need to be restored. * range is inclusive */ bool_t inomap_rst_needed( xfs_ino_t firstino, xfs_ino_t lastino ) { hnk_t *hnkp; seg_t *segp; /* if inomap not restored/resynced, just say yes */ if ( ! roothnkp ) { return BOOL_TRUE; } /* may be completely out of range */ if ( firstino > last_ino_added ) { return BOOL_FALSE; } /* find the hunk/seg containing first ino or any ino beyond */ for ( hnkp = roothnkp ; hnkp != 0 ; hnkp = hnkp->nextp ) { if ( firstino > hnkp->maxino ) { continue; } for ( segp = hnkp->seg; segp < hnkp->seg + SEGPERHNK ; segp++ ){ if ( hnkp == tailhnkp && segp > lastsegp ) { return BOOL_FALSE; } if ( firstino < segp->base + INOPERSEG ) { goto begin; } } } return BOOL_FALSE; begin: /* search until at least one ino is needed or until beyond last ino */ for ( ; ; ) { xfs_ino_t ino; if ( segp->base > lastino ) { return BOOL_FALSE; } for ( ino = segp->base ; ino < segp->base + INOPERSEG ; ino++ ){ int state; if ( ino < firstino ) { continue; } if ( ino > lastino ) { return BOOL_FALSE; } state = SEG_GET_BITS( segp, ino ); if ( state == MAP_NDR_CHANGE ) { return BOOL_TRUE; } } segp++; if ( hnkp == tailhnkp && segp > lastsegp ) { return BOOL_FALSE; } if ( segp >= hnkp->seg + SEGPERHNK ) { hnkp = hnkp->nextp; if ( ! hnkp ) { return BOOL_FALSE; } segp = hnkp->seg; } } /* NOTREACHED */ } /* calls the callback for all inos with an inomap state included * in the state mask. stops iteration when inos exhaused or cb * returns FALSE. */ void inomap_cbiter( int statemask, bool_t ( * cbfunc )( void *ctxp, xfs_ino_t ino ), void *ctxp ) { hnk_t *hnkp; seg_t *segp; /* step through all hunks, segs, and inos */ for ( hnkp = roothnkp ; hnkp != 0 ; hnkp = hnkp->nextp ) { for ( segp = hnkp->seg ; segp < hnkp->seg + SEGPERHNK ; segp++ ) { xfs_ino_t ino; if ( hnkp == tailhnkp && segp > lastsegp ) { return; } for ( ino = segp->base ; ino < segp->base + INOPERSEG ; ino++ ) { int state; if ( ino > last_ino_added ) { return; } state = SEG_GET_BITS( segp, ino ); if ( statemask & ( 1 << state )) { bool_t ok; ok = ( cbfunc )( ctxp, ino ); if ( ! ok ) { return; } } } } } } /* definition of locally defined static functions ****************************/ /* map_getset - locates and gets the state of the specified ino, * and optionally sets the state to a new value. */ static int map_getset( xfs_ino_t ino, int newstate, bool_t setflag ) { int state; seg_t *segp; if ((segp = map_getsegment( ino )) == NULL) { return MAP_INO_UNUSED; } state = SEG_GET_BITS( segp, ino ); if ( setflag ) { SEG_SET_BITS( segp, ino, newstate ); } return state; } static seg_t * map_getsegment( xfs_ino_t ino ) { uint64_t min; uint64_t max; uint64_t hnk; uint64_t seg; /* Use binary search to find the hunk that contains the inode number, * if any. This counts on the fact that all the hunks are contiguous * in memory and therefore can be treated as an array instead of a * list. */ min = 0; max = hnkcnt - 1; while (max >= min) { hnk = min + ((max - min) / 2); if (roothnkp[hnk].seg[0].base > ino) { max = hnk - 1; /* in a lower hunk */ } else if (roothnkp[hnk].maxino < ino) { min = hnk + 1; /* in a higher hunk */ } else { break; /* we have a winner! */ } } if (max < min) { return NULL; /* inode number fell between hunks */ } /* Use binary search to find the segment within the hunk that contains * the inode number, if any. */ min = 0; if (hnk == hnkcnt - 1) { max = segcnt - SEGPERHNK * ( hnkcnt - 1 ) - 1; } else { max = SEGPERHNK - 1; } while (max >= min) { seg = min + ((max - min) / 2); if (roothnkp[hnk].seg[seg].base > ino) { max = seg - 1; /* in a lower segment */ } else if (roothnkp[hnk].seg[seg].base + INOPERSEG <= ino) { min = seg + 1; /* in a higher segment */ } else { return &roothnkp[hnk].seg[seg]; /* we have a winner! */ } } return NULL; } static int map_set( xfs_ino_t ino, int state ) { int oldstate; oldstate = map_getset( ino, state, BOOL_TRUE ); return oldstate; } xfsdump-3.1.6+nmu1/m4/0000755000000000000000000000000012620476226011300 5ustar xfsdump-3.1.6+nmu1/m4/package_globals.m40000644000000000000000000000246612607344125014645 0ustar # # Generic macro, sets up all of the global packaging variables. # The following environment variables may be set to override defaults: # DEBUG OPTIMIZER MALLOCLIB PLATFORM DISTRIBUTION INSTALL_USER INSTALL_GROUP # BUILD_VERSION # AC_DEFUN([AC_PACKAGE_GLOBALS], [ pkg_name="$1" AC_SUBST(pkg_name) AC_PROG_CC . ./VERSION pkg_version=${PKG_MAJOR}.${PKG_MINOR}.${PKG_REVISION} AC_SUBST(pkg_version) pkg_release=$PKG_BUILD test -z "$BUILD_VERSION" || pkg_release="$BUILD_VERSION" AC_SUBST(pkg_release) DEBUG=${DEBUG:-'-DDEBUG'} dnl -DNDEBUG debug_build="$DEBUG" AC_SUBST(debug_build) OPTIMIZER=${OPTIMIZER:-'-g -O2'} opt_build="$OPTIMIZER" AC_SUBST(opt_build) MALLOCLIB=${MALLOCLIB:-''} dnl /usr/lib/libefence.a malloc_lib="$MALLOCLIB" AC_SUBST(malloc_lib) pkg_user=`id -u -n` test -z "$INSTALL_USER" || pkg_user="$INSTALL_USER" AC_SUBST(pkg_user) pkg_group=`id -g -n` test -z "$INSTALL_GROUP" || pkg_group="$INSTALL_GROUP" AC_SUBST(pkg_group) pkg_distribution=`uname -s` test -z "$DISTRIBUTION" || pkg_distribution="$DISTRIBUTION" AC_SUBST(pkg_distribution) pkg_platform=`uname -s | tr 'A-Z' 'a-z' | sed -e 's/irix64/irix/'` test -z "$PLATFORM" || pkg_platform="$PLATFORM" AC_SUBST(pkg_platform) ]) xfsdump-3.1.6+nmu1/m4/ltversion.m40000644000000000000000000000126212607344146013570 0ustar # ltversion.m4 -- version numbers -*- Autoconf -*- # # Copyright (C) 2004 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # @configure_input@ # serial 3337 ltversion.m4 # This file is part of GNU Libtool m4_define([LT_PACKAGE_VERSION], [2.4.2]) m4_define([LT_PACKAGE_REVISION], [1.3337]) AC_DEFUN([LTVERSION_VERSION], [macro_version='2.4.2' macro_revision='1.3337' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) xfsdump-3.1.6+nmu1/m4/libtool.m40000644000000000000000000106011112607344146013206 0ustar # libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. m4_define([_LT_COPYING], [dnl # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. # # GNU Libtool 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. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool 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 GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, or # obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ]) # serial 57 LT_INIT # LT_PREREQ(VERSION) # ------------------ # Complain and exit if this libtool version is less that VERSION. m4_defun([LT_PREREQ], [m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, [m4_default([$3], [m4_fatal([Libtool version $1 or higher is required], 63)])], [$2])]) # _LT_CHECK_BUILDDIR # ------------------ # Complain if the absolute build directory name contains unusual characters m4_defun([_LT_CHECK_BUILDDIR], [case `pwd` in *\ * | *\ *) AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; esac ]) # LT_INIT([OPTIONS]) # ------------------ AC_DEFUN([LT_INIT], [AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl AC_BEFORE([$0], [LTDL_INIT])dnl m4_require([_LT_CHECK_BUILDDIR])dnl dnl Autoconf doesn't catch unexpanded LT_ macros by default: m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 dnl unless we require an AC_DEFUNed macro: AC_REQUIRE([LTOPTIONS_VERSION])dnl AC_REQUIRE([LTSUGAR_VERSION])dnl AC_REQUIRE([LTVERSION_VERSION])dnl AC_REQUIRE([LTOBSOLETE_VERSION])dnl m4_require([_LT_PROG_LTMAIN])dnl _LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) dnl Parse OPTIONS _LT_SET_OPTIONS([$0], [$1]) # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ltmain" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' AC_SUBST(LIBTOOL)dnl _LT_SETUP # Only expand once: m4_define([LT_INIT]) ])# LT_INIT # Old names: AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PROG_LIBTOOL], []) dnl AC_DEFUN([AM_PROG_LIBTOOL], []) # _LT_CC_BASENAME(CC) # ------------------- # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. m4_defun([_LT_CC_BASENAME], [for cc_temp in $1""; do case $cc_temp in compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` ]) # _LT_FILEUTILS_DEFAULTS # ---------------------- # It is okay to use these file commands and assume they have been set # sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'. m4_defun([_LT_FILEUTILS_DEFAULTS], [: ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} ])# _LT_FILEUTILS_DEFAULTS # _LT_SETUP # --------- m4_defun([_LT_SETUP], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl _LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl dnl _LT_DECL([], [host_alias], [0], [The host system])dnl _LT_DECL([], [host], [0])dnl _LT_DECL([], [host_os], [0])dnl dnl _LT_DECL([], [build_alias], [0], [The build system])dnl _LT_DECL([], [build], [0])dnl _LT_DECL([], [build_os], [0])dnl dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl dnl AC_REQUIRE([AC_PROG_LN_S])dnl test -z "$LN_S" && LN_S="ln -s" _LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl dnl AC_REQUIRE([LT_CMD_MAX_LEN])dnl _LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl _LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl m4_require([_LT_CMD_RELOAD])dnl m4_require([_LT_CHECK_MAGIC_METHOD])dnl m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl m4_require([_LT_CMD_OLD_ARCHIVE])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_WITH_SYSROOT])dnl _LT_CONFIG_LIBTOOL_INIT([ # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi ]) if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi _LT_CHECK_OBJDIR m4_require([_LT_TAG_COMPILER])dnl case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld="$lt_cv_prog_gnu_ld" old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o _LT_CC_BASENAME([$compiler]) # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then _LT_PATH_MAGIC fi ;; esac # Use C for the default configuration in the libtool script LT_SUPPORTED_TAG([CC]) _LT_LANG_C_CONFIG _LT_LANG_DEFAULT_CONFIG _LT_CONFIG_COMMANDS ])# _LT_SETUP # _LT_PREPARE_SED_QUOTE_VARS # -------------------------- # Define a few sed substitution that help us do robust quoting. m4_defun([_LT_PREPARE_SED_QUOTE_VARS], [# Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([["`\\]]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ]) # _LT_PROG_LTMAIN # --------------- # Note that this code is called both from `configure', and `config.status' # now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, # `config.status' has no value for ac_aux_dir unless we are using Automake, # so we pass a copy along to make sure it has a sensible value anyway. m4_defun([_LT_PROG_LTMAIN], [m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl _LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) ltmain="$ac_aux_dir/ltmain.sh" ])# _LT_PROG_LTMAIN ## ------------------------------------- ## ## Accumulate code for creating libtool. ## ## ------------------------------------- ## # So that we can recreate a full libtool script including additional # tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS # in macros and then make a single call at the end using the `libtool' # label. # _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) # ---------------------------------------- # Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL_INIT], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_INIT], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_INIT]) # _LT_CONFIG_LIBTOOL([COMMANDS]) # ------------------------------ # Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) # _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) # ----------------------------------------------------- m4_defun([_LT_CONFIG_SAVE_COMMANDS], [_LT_CONFIG_LIBTOOL([$1]) _LT_CONFIG_LIBTOOL_INIT([$2]) ]) # _LT_FORMAT_COMMENT([COMMENT]) # ----------------------------- # Add leading comment marks to the start of each line, and a trailing # full-stop to the whole comment if one is not present already. m4_define([_LT_FORMAT_COMMENT], [m4_ifval([$1], [ m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) )]) ## ------------------------ ## ## FIXME: Eliminate VARNAME ## ## ------------------------ ## # _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) # ------------------------------------------------------------------- # CONFIGNAME is the name given to the value in the libtool script. # VARNAME is the (base) name used in the configure script. # VALUE may be 0, 1 or 2 for a computed quote escaped value based on # VARNAME. Any other value will be used directly. m4_define([_LT_DECL], [lt_if_append_uniq([lt_decl_varnames], [$2], [, ], [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], [m4_ifval([$1], [$1], [$2])]) lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) m4_ifval([$4], [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) lt_dict_add_subkey([lt_decl_dict], [$2], [tagged?], [m4_ifval([$5], [yes], [no])])]) ]) # _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) # -------------------------------------------------------- m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) # lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_tag_varnames], [_lt_decl_filter([tagged?], [yes], $@)]) # _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) # --------------------------------------------------------- m4_define([_lt_decl_filter], [m4_case([$#], [0], [m4_fatal([$0: too few arguments: $#])], [1], [m4_fatal([$0: too few arguments: $#: $1])], [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], [lt_dict_filter([lt_decl_dict], $@)])[]dnl ]) # lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) # -------------------------------------------------- m4_define([lt_decl_quote_varnames], [_lt_decl_filter([value], [1], $@)]) # lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_dquote_varnames], [_lt_decl_filter([value], [2], $@)]) # lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_varnames_tagged], [m4_assert([$# <= 2])dnl _$0(m4_quote(m4_default([$1], [[, ]])), m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) m4_define([_lt_decl_varnames_tagged], [m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) # lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_all_varnames], [_$0(m4_quote(m4_default([$1], [[, ]])), m4_if([$2], [], m4_quote(lt_decl_varnames), m4_quote(m4_shift($@))))[]dnl ]) m4_define([_lt_decl_all_varnames], [lt_join($@, lt_decl_varnames_tagged([$1], lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl ]) # _LT_CONFIG_STATUS_DECLARE([VARNAME]) # ------------------------------------ # Quote a variable value, and forward it to `config.status' so that its # declaration there will have the same value as in `configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], [$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) # _LT_CONFIG_STATUS_DECLARATIONS # ------------------------------ # We delimit libtool config variables with single quotes, so when # we write them to config.status, we have to be sure to quote all # embedded single quotes properly. In configure, this macro expands # each variable declared with _LT_DECL (and _LT_TAGDECL) into: # # ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], [m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAGS # ---------------- # Output comment and list of tags supported by the script m4_defun([_LT_LIBTOOL_TAGS], [_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl available_tags="_LT_TAGS"dnl ]) # _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) # ----------------------------------- # Extract the dictionary values for VARNAME (optionally with TAG) and # expand to a commented shell variable setting: # # # Some comment about what VAR is for. # visible_name=$lt_internal_name m4_define([_LT_LIBTOOL_DECLARE], [_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [description])))[]dnl m4_pushdef([_libtool_name], m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), [0], [_libtool_name=[$]$1], [1], [_libtool_name=$lt_[]$1], [2], [_libtool_name=$lt_[]$1], [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl ]) # _LT_LIBTOOL_CONFIG_VARS # ----------------------- # Produce commented declarations of non-tagged libtool config variables # suitable for insertion in the LIBTOOL CONFIG section of the `libtool' # script. Tagged libtool config variables (even for the LIBTOOL CONFIG # section) are produced by _LT_LIBTOOL_TAG_VARS. m4_defun([_LT_LIBTOOL_CONFIG_VARS], [m4_foreach([_lt_var], m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAG_VARS(TAG) # ------------------------- m4_define([_LT_LIBTOOL_TAG_VARS], [m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) # _LT_TAGVAR(VARNAME, [TAGNAME]) # ------------------------------ m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) # _LT_CONFIG_COMMANDS # ------------------- # Send accumulated output to $CONFIG_STATUS. Thanks to the lists of # variables for single and double quote escaping we saved from calls # to _LT_DECL, we can put quote escaped variables declarations # into `config.status', and then the shell code to quote escape them in # for loops in `config.status'. Finally, any additional code accumulated # from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. m4_defun([_LT_CONFIG_COMMANDS], [AC_PROVIDE_IFELSE([LT_OUTPUT], dnl If the libtool generation code has been placed in $CONFIG_LT, dnl instead of duplicating it all over again into config.status, dnl then we will have config.status run $CONFIG_LT later, so it dnl needs to know what name is stored there: [AC_CONFIG_COMMANDS([libtool], [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], dnl If the libtool generation code is destined for config.status, dnl expand the accumulated commands and init code now: [AC_CONFIG_COMMANDS([libtool], [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) ])#_LT_CONFIG_COMMANDS # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], [ # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' _LT_CONFIG_STATUS_DECLARATIONS LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$[]1 _LTECHO_EOF' } # Quote evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_quote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_dquote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done _LT_OUTPUT_LIBTOOL_INIT ]) # _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) # ------------------------------------ # Generate a child script FILE with all initialization necessary to # reuse the environment learned by the parent script, and make the # file executable. If COMMENT is supplied, it is inserted after the # `#!' sequence but before initialization text begins. After this # macro, additional text can be appended to FILE to form the body of # the child script. The macro ends with non-zero status if the # file could not be fully written (such as if the disk is full). m4_ifdef([AS_INIT_GENERATED], [m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], [m4_defun([_LT_GENERATED_FILE_INIT], [m4_require([AS_PREPARE])]dnl [m4_pushdef([AS_MESSAGE_LOG_FD])]dnl [lt_write_fail=0 cat >$1 <<_ASEOF || lt_write_fail=1 #! $SHELL # Generated by $as_me. $2 SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$1 <<\_ASEOF || lt_write_fail=1 AS_SHELL_SANITIZE _AS_PREPARE exec AS_MESSAGE_FD>&1 _ASEOF test $lt_write_fail = 0 && chmod +x $1[]dnl m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT # LT_OUTPUT # --------- # This macro allows early generation of the libtool script (before # AC_OUTPUT is called), incase it is used in configure for compilation # tests. AC_DEFUN([LT_OUTPUT], [: ${CONFIG_LT=./config.lt} AC_MSG_NOTICE([creating $CONFIG_LT]) _LT_GENERATED_FILE_INIT(["$CONFIG_LT"], [# Run this file to recreate a libtool stub with the current configuration.]) cat >>"$CONFIG_LT" <<\_LTEOF lt_cl_silent=false exec AS_MESSAGE_LOG_FD>>config.log { echo AS_BOX([Running $as_me.]) } >&AS_MESSAGE_LOG_FD lt_cl_help="\ \`$as_me' creates a local libtool stub from the current configuration, for use in further configure time tests before the real libtool is generated. Usage: $[0] [[OPTIONS]] -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files Report bugs to ." lt_cl_version="\ m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) configured by $[0], generated by m4_PACKAGE_STRING. Copyright (C) 2011 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." while test $[#] != 0 do case $[1] in --version | --v* | -V ) echo "$lt_cl_version"; exit 0 ;; --help | --h* | -h ) echo "$lt_cl_help"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --quiet | --q* | --silent | --s* | -q ) lt_cl_silent=: ;; -*) AC_MSG_ERROR([unrecognized option: $[1] Try \`$[0] --help' for more information.]) ;; *) AC_MSG_ERROR([unrecognized argument: $[1] Try \`$[0] --help' for more information.]) ;; esac shift done if $lt_cl_silent; then exec AS_MESSAGE_FD>/dev/null fi _LTEOF cat >>"$CONFIG_LT" <<_LTEOF _LT_OUTPUT_LIBTOOL_COMMANDS_INIT _LTEOF cat >>"$CONFIG_LT" <<\_LTEOF AC_MSG_NOTICE([creating $ofile]) _LT_OUTPUT_LIBTOOL_COMMANDS AS_EXIT(0) _LTEOF chmod +x "$CONFIG_LT" # configure is writing to config.log, but config.lt does its own redirection, # appending to config.log, which fails on DOS, as config.log is still kept # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. lt_cl_success=: test "$silent" = yes && lt_config_lt_args="$lt_config_lt_args --quiet" exec AS_MESSAGE_LOG_FD>/dev/null $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false exec AS_MESSAGE_LOG_FD>>config.log $lt_cl_success || AS_EXIT(1) ])# LT_OUTPUT # _LT_CONFIG(TAG) # --------------- # If TAG is the built-in tag, create an initial libtool script with a # default configuration from the untagged config vars. Otherwise add code # to config.status for appending the configuration named by TAG from the # matching tagged config vars. m4_defun([_LT_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_CONFIG_SAVE_COMMANDS([ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl m4_if(_LT_TAG, [C], [ # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi cfgfile="${ofile}T" trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # _LT_COPYING _LT_LIBTOOL_TAGS # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS # ### END LIBTOOL CONFIG _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac _LT_PROG_LTMAIN # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) _LT_PROG_REPLACE_SHELLFNS mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ], [cat <<_LT_EOF >> "$ofile" dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded dnl in a comment (ie after a #). # ### BEGIN LIBTOOL TAG CONFIG: $1 _LT_LIBTOOL_TAG_VARS(_LT_TAG) # ### END LIBTOOL TAG CONFIG: $1 _LT_EOF ])dnl /m4_if ], [m4_if([$1], [], [ PACKAGE='$PACKAGE' VERSION='$VERSION' TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile'], []) ])dnl /_LT_CONFIG_SAVE_COMMANDS ])# _LT_CONFIG # LT_SUPPORTED_TAG(TAG) # --------------------- # Trace this macro to discover what tags are supported by the libtool # --tag option, using: # autoconf --trace 'LT_SUPPORTED_TAG:$1' AC_DEFUN([LT_SUPPORTED_TAG], []) # C support is built-in for now m4_define([_LT_LANG_C_enabled], []) m4_define([_LT_TAGS], []) # LT_LANG(LANG) # ------------- # Enable libtool support for the given language if not already enabled. AC_DEFUN([LT_LANG], [AC_BEFORE([$0], [LT_OUTPUT])dnl m4_case([$1], [C], [_LT_LANG(C)], [C++], [_LT_LANG(CXX)], [Go], [_LT_LANG(GO)], [Java], [_LT_LANG(GCJ)], [Fortran 77], [_LT_LANG(F77)], [Fortran], [_LT_LANG(FC)], [Windows Resource], [_LT_LANG(RC)], [m4_ifdef([_LT_LANG_]$1[_CONFIG], [_LT_LANG($1)], [m4_fatal([$0: unsupported language: "$1"])])])dnl ])# LT_LANG # _LT_LANG(LANGNAME) # ------------------ m4_defun([_LT_LANG], [m4_ifdef([_LT_LANG_]$1[_enabled], [], [LT_SUPPORTED_TAG([$1])dnl m4_append([_LT_TAGS], [$1 ])dnl m4_define([_LT_LANG_]$1[_enabled], [])dnl _LT_LANG_$1_CONFIG($1)])dnl ])# _LT_LANG m4_ifndef([AC_PROG_GO], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_GO. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_GO], [AC_LANG_PUSH(Go)dnl AC_ARG_VAR([GOC], [Go compiler command])dnl AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl _AC_ARG_VAR_LDFLAGS()dnl AC_CHECK_TOOL(GOC, gccgo) if test -z "$GOC"; then if test -n "$ac_tool_prefix"; then AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) fi fi if test -z "$GOC"; then AC_CHECK_PROG(GOC, gccgo, gccgo, false) fi ])#m4_defun ])#m4_ifndef # _LT_LANG_DEFAULT_CONFIG # ----------------------- m4_defun([_LT_LANG_DEFAULT_CONFIG], [AC_PROVIDE_IFELSE([AC_PROG_CXX], [LT_LANG(CXX)], [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) AC_PROVIDE_IFELSE([AC_PROG_F77], [LT_LANG(F77)], [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) AC_PROVIDE_IFELSE([AC_PROG_FC], [LT_LANG(FC)], [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal dnl pulling things in needlessly. AC_PROVIDE_IFELSE([AC_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([LT_PROG_GCJ], [LT_LANG(GCJ)], [m4_ifdef([AC_PROG_GCJ], [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([A][M_PROG_GCJ], [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([LT_PROG_GCJ], [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) AC_PROVIDE_IFELSE([AC_PROG_GO], [LT_LANG(GO)], [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) AC_PROVIDE_IFELSE([LT_PROG_RC], [LT_LANG(RC)], [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) ])# _LT_LANG_DEFAULT_CONFIG # Obsolete macros: AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_CXX], []) dnl AC_DEFUN([AC_LIBTOOL_F77], []) dnl AC_DEFUN([AC_LIBTOOL_FC], []) dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) dnl AC_DEFUN([AC_LIBTOOL_RC], []) # _LT_TAG_COMPILER # ---------------- m4_defun([_LT_TAG_COMPILER], [AC_REQUIRE([AC_PROG_CC])dnl _LT_DECL([LTCC], [CC], [1], [A C compiler])dnl _LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl _LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl _LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC ])# _LT_TAG_COMPILER # _LT_COMPILER_BOILERPLATE # ------------------------ # Check for compiler boilerplate output or warnings with # the simple compiler test code. m4_defun([_LT_COMPILER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ])# _LT_COMPILER_BOILERPLATE # _LT_LINKER_BOILERPLATE # ---------------------- # Check for linker boilerplate output or warnings with # the simple link test code. m4_defun([_LT_LINKER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ])# _LT_LINKER_BOILERPLATE # _LT_REQUIRED_DARWIN_CHECKS # ------------------------- m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ case $host_os in rhapsody* | darwin*) AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) AC_CHECK_TOOL([LIPO], [lipo], [:]) AC_CHECK_TOOL([OTOOL], [otool], [:]) AC_CHECK_TOOL([OTOOL64], [otool64], [:]) _LT_DECL([], [DSYMUTIL], [1], [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) _LT_DECL([], [NMEDIT], [1], [Tool to change global to local symbols on Mac OS X]) _LT_DECL([], [LIPO], [1], [Tool to manipulate fat objects and archives on Mac OS X]) _LT_DECL([], [OTOOL], [1], [ldd/readelf like tool for Mach-O binaries on Mac OS X]) _LT_DECL([], [OTOOL64], [1], [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], [lt_cv_apple_cc_single_mod=no if test -z "${LT_MULTI_MODULE}"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test $_lt_result -eq 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -rf libconftest.dylib* rm -f conftest.* fi]) AC_CACHE_CHECK([for -exported_symbols_list linker flag], [lt_cv_ld_exported_symbols_list], [lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [lt_cv_ld_exported_symbols_list=yes], [lt_cv_ld_exported_symbols_list=no]) LDFLAGS="$save_LDFLAGS" ]) AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], [lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then lt_cv_ld_force_load=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM ]) case $host_os in rhapsody* | darwin1.[[012]]) _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; 10.[[012]]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; then _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ]) # _LT_DARWIN_LINKER_FEATURES([TAG]) # --------------------------------- # Checks for linker and compiler features on darwin m4_defun([_LT_DARWIN_LINKER_FEATURES], [ m4_require([_LT_REQUIRED_DARWIN_CHECKS]) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported if test "$lt_cv_ld_force_load" = "yes"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) else _LT_TAGVAR(whole_archive_flag_spec, $1)='' fi _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" case $cc_basename in ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=func_echo_all _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" m4_if([$1], [CXX], [ if test "$lt_cv_apple_cc_single_mod" != "yes"; then _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" fi ],[]) else _LT_TAGVAR(ld_shlibs, $1)=no fi ]) # _LT_SYS_MODULE_PATH_AIX([TAGNAME]) # ---------------------------------- # Links a minimal program and checks the executable # for the system default hardcoded library path. In most cases, # this is /usr/lib:/lib, but when the MPI compilers are used # the location of the communication and MPI libs are included too. # If we don't find anything, use the default library path according # to the aix ld manual. # Store the results from the different compilers for each TAGNAME. # Allow to override them for all tags through lt_cv_aix_libpath. m4_defun([_LT_SYS_MODULE_PATH_AIX], [m4_require([_LT_DECL_SED])dnl if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ lt_aix_libpath_sed='[ /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }]' _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi],[]) if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])="/usr/lib:/lib" fi ]) aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) fi ])# _LT_SYS_MODULE_PATH_AIX # _LT_SHELL_INIT(ARG) # ------------------- m4_define([_LT_SHELL_INIT], [m4_divert_text([M4SH-INIT], [$1 ])])# _LT_SHELL_INIT # _LT_PROG_ECHO_BACKSLASH # ----------------------- # Find how we can fake an echo command that does not interpret backslash. # In particular, with Autoconf 2.60 or later we add some code to the start # of the generated configure script which will find a shell with a builtin # printf (which we can use as an echo command). m4_defun([_LT_PROG_ECHO_BACKSLASH], [ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO AC_MSG_CHECKING([how to print strings]) # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $[]1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } case "$ECHO" in printf*) AC_MSG_RESULT([printf]) ;; print*) AC_MSG_RESULT([print -r]) ;; *) AC_MSG_RESULT([cat]) ;; esac m4_ifdef([_AS_DETECT_SUGGESTED], [_AS_DETECT_SUGGESTED([ test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test "X`printf %s $ECHO`" = "X$ECHO" \ || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) _LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) _LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) ])# _LT_PROG_ECHO_BACKSLASH # _LT_WITH_SYSROOT # ---------------- AC_DEFUN([_LT_WITH_SYSROOT], [AC_MSG_CHECKING([for sysroot]) AC_ARG_WITH([sysroot], [ --with-sysroot[=DIR] Search for dependent libraries within DIR (or the compiler's sysroot if not specified).], [], [with_sysroot=no]) dnl lt_sysroot will always be passed unquoted. We quote it here dnl in case the user passed a directory name. lt_sysroot= case ${with_sysroot} in #( yes) if test "$GCC" = yes; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) AC_MSG_RESULT([${with_sysroot}]) AC_MSG_ERROR([The sysroot must be an absolute path.]) ;; esac AC_MSG_RESULT([${lt_sysroot:-no}]) _LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl [dependent libraries, and in which our libraries should be installed.])]) # _LT_ENABLE_LOCK # --------------- m4_defun([_LT_ENABLE_LOCK], [AC_ARG_ENABLE([libtool-lock], [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `/usr/bin/file conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; *-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD="${LD-ld}_sol2" fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks="$enable_libtool_lock" ])# _LT_ENABLE_LOCK # _LT_PROG_AR # ----------- m4_defun([_LT_PROG_AR], [AC_CHECK_TOOLS(AR, [ar], false) : ${AR=ar} : ${AR_FLAGS=cru} _LT_DECL([], [AR], [1], [The archiver]) _LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], [lt_cv_ar_at_file=no AC_COMPILE_IFELSE([AC_LANG_PROGRAM], [echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([lt_ar_try]) if test "$ac_status" -eq 0; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a AC_TRY_EVAL([lt_ar_try]) if test "$ac_status" -ne 0; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a ]) ]) if test "x$lt_cv_ar_at_file" = xno; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi _LT_DECL([], [archiver_list_spec], [1], [How to feed a file listing to the archiver]) ])# _LT_PROG_AR # _LT_CMD_OLD_ARCHIVE # ------------------- m4_defun([_LT_CMD_OLD_ARCHIVE], [_LT_PROG_AR AC_CHECK_TOOL(STRIP, strip, :) test -z "$STRIP" && STRIP=: _LT_DECL([], [STRIP], [1], [A symbol stripping program]) AC_CHECK_TOOL(RANLIB, ranlib, :) test -z "$RANLIB" && RANLIB=: _LT_DECL([], [RANLIB], [1], [Commands used to install an old-style archive]) # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac _LT_DECL([], [old_postinstall_cmds], [2]) _LT_DECL([], [old_postuninstall_cmds], [2]) _LT_TAGDECL([], [old_archive_cmds], [2], [Commands used to build an old-style archive]) _LT_DECL([], [lock_old_archive_extraction], [0], [Whether to use a lock for old archive extraction]) ])# _LT_CMD_OLD_ARCHIVE # _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------------------- # Check whether the given compiler option works AC_DEFUN([_LT_COMPILER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$3" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi fi $RM conftest* ]) if test x"[$]$2" = xyes; then m4_if([$5], , :, [$5]) else m4_if([$6], , :, [$6]) fi ])# _LT_COMPILER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) # _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------- # Check whether the given linker option works AC_DEFUN([_LT_LINKER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $3" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&AS_MESSAGE_LOG_FD $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi else $2=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" ]) if test x"[$]$2" = xyes; then m4_if([$4], , :, [$4]) else m4_if([$5], , :, [$5]) fi ])# _LT_LINKER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) # LT_CMD_MAX_LEN #--------------- AC_DEFUN([LT_CMD_MAX_LEN], [AC_REQUIRE([AC_CANONICAL_HOST])dnl # find the maximum length of command line arguments AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl i=0 teststring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8 ; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac ]) if test -n $lt_cv_sys_max_cmd_len ; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) fi max_cmd_len=$lt_cv_sys_max_cmd_len _LT_DECL([], [max_cmd_len], [0], [What is the maximum length of a command?]) ])# LT_CMD_MAX_LEN # Old name: AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) # _LT_HEADER_DLFCN # ---------------- m4_defun([_LT_HEADER_DLFCN], [AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl ])# _LT_HEADER_DLFCN # _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) # ---------------------------------------------------------------- m4_defun([_LT_TRY_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test "$cross_compiling" = yes; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF [#line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; }] _LT_EOF if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; x$lt_dlneed_uscore) $2 ;; x$lt_dlunknown|x*) $3 ;; esac else : # compilation failed $3 fi fi rm -fr conftest* ])# _LT_TRY_DLOPEN_SELF # LT_SYS_DLOPEN_SELF # ------------------ AC_DEFUN([LT_SYS_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; *) AC_CHECK_FUNC([shl_load], [lt_cv_dlopen="shl_load"], [AC_CHECK_LIB([dld], [shl_load], [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], [AC_CHECK_FUNC([dlopen], [lt_cv_dlopen="dlopen"], [AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], [AC_CHECK_LIB([svld], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], [AC_CHECK_LIB([dld], [dld_link], [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) ]) ]) ]) ]) ]) ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], lt_cv_dlopen_self, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) ]) fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi _LT_DECL([dlopen_support], [enable_dlopen], [0], [Whether dlopen is supported]) _LT_DECL([dlopen_self], [enable_dlopen_self], [0], [Whether dlopen of programs is supported]) _LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], [Whether dlopen of statically linked programs is supported]) ])# LT_SYS_DLOPEN_SELF # Old name: AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) # _LT_COMPILER_C_O([TAGNAME]) # --------------------------- # Check to see if options -c and -o are simultaneously supported by compiler. # This macro does not hard code the compiler like AC_PROG_CC_C_O. m4_defun([_LT_COMPILER_C_O], [m4_require([_LT_DECL_SED])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes fi fi chmod u+w . 2>&AS_MESSAGE_LOG_FD $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* ]) _LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], [Does compiler simultaneously support -c and -o options?]) ])# _LT_COMPILER_C_O # _LT_COMPILER_FILE_LOCKS([TAGNAME]) # ---------------------------------- # Check to see if we can do hard links to lock some files if needed m4_defun([_LT_COMPILER_FILE_LOCKS], [m4_require([_LT_ENABLE_LOCK])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_COMPILER_C_O([$1]) hard_links="nottested" if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) if test "$hard_links" = no; then AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) need_locks=warn fi else need_locks=no fi _LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) ])# _LT_COMPILER_FILE_LOCKS # _LT_CHECK_OBJDIR # ---------------- m4_defun([_LT_CHECK_OBJDIR], [AC_CACHE_CHECK([for objdir], [lt_cv_objdir], [rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null]) objdir=$lt_cv_objdir _LT_DECL([], [objdir], [0], [The name of the directory that contains temporary libtool files])dnl m4_pattern_allow([LT_OBJDIR])dnl AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/", [Define to the sub-directory in which libtool stores uninstalled libraries.]) ])# _LT_CHECK_OBJDIR # _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) # -------------------------------------- # Check hardcoding attributes. m4_defun([_LT_LINKER_HARDCODE_LIBPATH], [AC_MSG_CHECKING([how to hardcode library paths into programs]) _LT_TAGVAR(hardcode_action, $1)= if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || test -n "$_LT_TAGVAR(runpath_var, $1)" || test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then # We can hardcode non-existent directories. if test "$_LT_TAGVAR(hardcode_direct, $1)" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no && test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then # Linking always hardcodes the temporary library directory. _LT_TAGVAR(hardcode_action, $1)=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. _LT_TAGVAR(hardcode_action, $1)=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. _LT_TAGVAR(hardcode_action, $1)=unsupported fi AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) if test "$_LT_TAGVAR(hardcode_action, $1)" = relink || test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi _LT_TAGDECL([], [hardcode_action], [0], [How to hardcode a shared library path into an executable]) ])# _LT_LINKER_HARDCODE_LIBPATH # _LT_CMD_STRIPLIB # ---------------- m4_defun([_LT_CMD_STRIPLIB], [m4_require([_LT_DECL_EGREP]) striplib= old_striplib= AC_MSG_CHECKING([whether stripping libraries is possible]) if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ;; *) AC_MSG_RESULT([no]) ;; esac fi _LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) _LT_DECL([], [striplib], [1]) ])# _LT_CMD_STRIPLIB # _LT_SYS_DYNAMIC_LINKER([TAG]) # ----------------------------- # PORTME Fill in your ld.so characteristics m4_defun([_LT_SYS_DYNAMIC_LINKER], [AC_REQUIRE([AC_CANONICAL_HOST])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ if test "$GCC" = yes; then case $host_os in darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq="s,=\([[A-Za-z]]:\),\1,g" ;; *) lt_sed_strip_eq="s,=/,/,g" ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path/$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" else test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo="/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[[lt_foo]]++; } if (lt_freq[[lt_foo]] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's,/\([[A-Za-z]]:\),\1,g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi]) library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[[4-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[[45]]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' library_names_spec='${libname}.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec="$LIB" if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[[23]].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[[01]]* | freebsdelf3.[[01]]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=yes sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[[3-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], [lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], [lt_cv_shlibpath_overrides_runpath=yes])]) LDFLAGS=$save_LDFLAGS libdir=$save_libdir ]) shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[[89]] | openbsd2.[[89]].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac AC_MSG_RESULT([$dynamic_linker]) test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi _LT_DECL([], [variables_saved_for_relink], [1], [Variables whose values should be saved in libtool wrapper scripts and restored at link time]) _LT_DECL([], [need_lib_prefix], [0], [Do we need the "lib" prefix for modules?]) _LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) _LT_DECL([], [version_type], [0], [Library versioning type]) _LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) _LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) _LT_DECL([], [shlibpath_overrides_runpath], [0], [Is shlibpath searched before the hard-coded library search path?]) _LT_DECL([], [libname_spec], [1], [Format of library name prefix]) _LT_DECL([], [library_names_spec], [1], [[List of archive names. First name is the real one, the rest are links. The last name is the one that the linker finds with -lNAME]]) _LT_DECL([], [soname_spec], [1], [[The coded name of the library, if different from the real name]]) _LT_DECL([], [install_override_mode], [1], [Permission mode override for installation of shared libraries]) _LT_DECL([], [postinstall_cmds], [2], [Command to use after installation of a shared archive]) _LT_DECL([], [postuninstall_cmds], [2], [Command to use after uninstallation of a shared archive]) _LT_DECL([], [finish_cmds], [2], [Commands used to finish a libtool library installation in a directory]) _LT_DECL([], [finish_eval], [1], [[As "finish_cmds", except a single script fragment to be evaled but not shown]]) _LT_DECL([], [hardcode_into_libs], [0], [Whether we should hardcode library paths into libraries]) _LT_DECL([], [sys_lib_search_path_spec], [2], [Compile-time system search path for libraries]) _LT_DECL([], [sys_lib_dlsearch_path_spec], [2], [Run-time system search path for libraries]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- # find a file program which can recognize shared library AC_DEFUN([_LT_PATH_TOOL_PREFIX], [m4_require([_LT_DECL_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in [[\\/*] | ?:[\\/]*]) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="m4_if([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$1; then lt_cv_path_MAGIC_CMD="$ac_dir/$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac]) MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else AC_MSG_RESULT(no) fi _LT_DECL([], [MAGIC_CMD], [0], [Used to examine libraries when file_magic_cmd begins with "file"])dnl ])# _LT_PATH_TOOL_PREFIX # Old name: AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) # _LT_PATH_MAGIC # -------------- # find a file program which can recognize a shared library m4_defun([_LT_PATH_MAGIC], [_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) else MAGIC_CMD=: fi fi ])# _LT_PATH_MAGIC # LT_PATH_LD # ---------- # find the pathname to the GNU or non-GNU linker AC_DEFUN([LT_PATH_LD], [AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PROG_ECHO_BACKSLASH])dnl AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], [test "$withval" = no || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]]* | ?:[[\\/]]*) re_direlt='/[[^/]][[^/]]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[[3-9]]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; esac ]) file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown _LT_DECL([], [deplibs_check_method], [1], [Method to check whether dependent libraries are shared objects]) _LT_DECL([], [file_magic_cmd], [1], [Command to use when deplibs_check_method = "file_magic"]) _LT_DECL([], [file_magic_glob], [1], [How to find potential files when deplibs_check_method = "file_magic"]) _LT_DECL([], [want_nocaseglob], [1], [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) ])# _LT_CHECK_MAGIC_METHOD # LT_PATH_NM # ---------- # find the pathname to a BSD- or MS-compatible name lister AC_DEFUN([LT_PATH_NM], [AC_REQUIRE([AC_PROG_CC])dnl AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/$lt_tmp_nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS="$lt_save_ifs" done : ${lt_cv_path_NM=no} fi]) if test "$lt_cv_path_NM" != "no"; then NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols" ;; *) DUMPBIN=: ;; esac fi AC_SUBST([DUMPBIN]) if test "$DUMPBIN" != ":"; then NM="$DUMPBIN" fi fi test -z "$NM" && NM=nm AC_SUBST([NM]) _LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], [lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) cat conftest.out >&AS_MESSAGE_LOG_FD if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest*]) ])# LT_PATH_NM # Old names: AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_PROG_NM], []) dnl AC_DEFUN([AC_PROG_NM], []) # _LT_CHECK_SHAREDLIB_FROM_LINKLIB # -------------------------------- # how to determine the name of the shared library # associated with a specific link library. # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) m4_require([_LT_DECL_DLLTOOL]) AC_CACHE_CHECK([how to associate runtime and link libraries], lt_cv_sharedlib_from_linklib_cmd, [lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh # decide which to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd="$ECHO" ;; esac ]) sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO _LT_DECL([], [sharedlib_from_linklib_cmd], [1], [Command to associate shared and link libraries]) ])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB # _LT_PATH_MANIFEST_TOOL # ---------------------- # locate the manifest tool m4_defun([_LT_PATH_MANIFEST_TOOL], [AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], [lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&AS_MESSAGE_LOG_FD if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest*]) if test "x$lt_cv_path_mainfest_tool" != xyes; then MANIFEST_TOOL=: fi _LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl ])# _LT_PATH_MANIFEST_TOOL # LT_LIB_M # -------- # check for math library AC_DEFUN([LT_LIB_M], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) AC_CHECK_LIB(m, cos, LIBM="-lm") ;; esac AC_SUBST([LIBM]) ])# LT_LIB_M # Old name: AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_CHECK_LIBM], []) # _LT_COMPILER_NO_RTTI([TAGNAME]) # ------------------------------- m4_defun([_LT_COMPILER_NO_RTTI], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test "$GCC" = yes; then case $cc_basename in nvcc*) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; *) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; esac _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, [-fno-rtti -fno-exceptions], [], [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) fi _LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], [Compiler flag to turn off builtin functions]) ])# _LT_COMPILER_NO_RTTI # _LT_CMD_GLOBAL_SYMBOLS # ---------------------- m4_defun([_LT_CMD_GLOBAL_SYMBOLS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([LT_PATH_NM])dnl AC_REQUIRE([LT_PATH_LD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_TAG_COMPILER])dnl # Check for command to grab the raw symbol name followed by C symbol from nm. AC_MSG_CHECKING([command to parse $NM output from $compiler object]) AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [ # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[[BCDEGRST]]' # Regexp to match symbols that can be accessed directly from C. sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[[BCDT]]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[[ABCDGISTW]]' ;; hpux*) if test "$host_cpu" = ia64; then symcode='[[ABCDEGRST]]' fi ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' ;; osf*) symcode='[[BCDEGQRST]]' ;; solaris*) symcode='[[BDRT]]' ;; sco3.2v5*) symcode='[[DT]]' ;; sysv4.2uw2*) symcode='[[DT]]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[[ABDT]]' ;; sysv4) symcode='[[DFNSTU]]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[[ABCDGIRSTW]]' ;; esac # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK ['"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ " {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ " s[1]~/^[@?]/{print s[1], s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx]" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if AC_TRY_EVAL(ac_compile); then # Now try to grab the symbols. nlist=conftest.nm if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT@&t@_DLSYM_CONST #elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT@&t@_DLSYM_CONST #else # define LT@&t@_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT@&t@_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[[]] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD fi else echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done ]) if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then AC_MSG_RESULT(failed) else AC_MSG_RESULT(ok) fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then nm_file_list_spec='@' fi _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], [Take the output of nm and produce a listing of raw symbols and C names]) _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], [Transform the output of nm in a proper C declaration]) _LT_DECL([global_symbol_to_c_name_address], [lt_cv_sys_global_symbol_to_c_name_address], [1], [Transform the output of nm in a C name address pair]) _LT_DECL([global_symbol_to_c_name_address_lib_prefix], [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], [Transform the output of nm in a C name address pair when lib prefix is needed]) _LT_DECL([], [nm_file_list_spec], [1], [Specify filename containing input files for $NM]) ]) # _LT_CMD_GLOBAL_SYMBOLS # _LT_COMPILER_PIC([TAGNAME]) # --------------------------- m4_defun([_LT_COMPILER_PIC], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_wl, $1)= _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)= m4_if([$1], [CXX], [ # C++ specific cases for pic, static, wl, etc. if test "$GXX" = yes; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else case $host_os in aix[[4-9]]*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; dgux*) case $cc_basename in ec++*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; ghcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' if test "$host_cpu" != ia64; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # KAI C++ Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64 which still supported -KPIC. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL 8.0, 9.0 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' ;; *) ;; esac ;; netbsd* | netbsdelf*-gnu) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; cxx*) # Digital/Compaq C++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; lcc*) # Lucid _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ], [ if test "$GCC" = yes; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; hpux9* | hpux10* | hpux11*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC (with -KPIC) is the default. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # Lahey Fortran 8.1. lf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' ;; nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; ccc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All Alpha code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='' ;; *Sun\ F* | *Sun*Fortran*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; *Intel*\ [[CF]]*Compiler*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; *Portland\ Group*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; esac ;; newsos6) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All OSF/1 code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; rdos*) _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; solaris*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; *) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; esac ;; sunos4*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; unicos*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; uts4*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ]) case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" ;; esac AC_CACHE_CHECK([for $compiler option to produce PIC], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) _LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) # # Check to make sure the PIC flag actually works. # if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in "" | " "*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; esac], [_LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) fi _LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], [Additional compiler flags for building library objects]) _LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], [How to pass a linker flag through the compiler]) # # Check to make sure the static flag actually works. # wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" _LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), $lt_tmp_static_flag, [], [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) _LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], [Compiler flag to prevent dynamic linking]) ])# _LT_COMPILER_PIC # _LT_LINKER_SHLIBS([TAGNAME]) # ---------------------------- # See if the linker supports building shared libraries. m4_defun([_LT_LINKER_SHLIBS], [AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) m4_if([$1], [CXX], [ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global defined # symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl*) _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] ;; esac ;; linux* | k*bsd*-gnu | gnu*) _LT_TAGVAR(link_all_deplibs, $1)=no ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac ], [ runpath_var= _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_cmds, $1)= _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(old_archive_from_new_cmds, $1)= _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= _LT_TAGVAR(thread_safe_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list _LT_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. dnl Note also adjust exclude_expsyms for C++ above. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; linux* | k*bsd*-gnu | gnu*) _LT_TAGVAR(link_all_deplibs, $1)=no ;; esac _LT_TAGVAR(ld_shlibs, $1)=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test "$with_gnu_ld" = yes; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test "$lt_use_gnu_ld_interface" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi supports_anon_versioning=no case `$LD -v 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[[3-9]]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test "$host_os" = linux-dietlibc; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test "$tmp_diet" = no then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 _LT_TAGVAR(whole_archive_flag_spec, $1)= tmp_sharedflag='--shared' ;; xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi case $cc_basename in xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; sunos4*) _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then runpath_var= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_TAGVAR(hardcode_minus_L, $1)=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_TAGVAR(hardcode_direct, $1)=unsupported fi ;; aix[[4-9]]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global # defined symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' if test "$GCC" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi _LT_TAGVAR(link_all_deplibs, $1)=no else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; bsdi[[45]]*) _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; hpux9*) if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; hpux10*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes fi ;; hpux11*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) m4_if($1, [], [ # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) _LT_LINKER_OPTION([if $CC understands -b], _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) ;; esac fi if test "$with_gnu_ld" = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], [lt_cv_irix_exported_symbol], [save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" AC_LINK_IFELSE( [AC_LANG_SOURCE( [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], [C++], [[int foo (void) { return 0; }]], [Fortran 77], [[ subroutine foo end]], [Fortran], [[ subroutine foo end]])])], [lt_cv_irix_exported_symbol=yes], [lt_cv_irix_exported_symbol=no]) LDFLAGS="$save_LDFLAGS"]) if test "$lt_cv_irix_exported_symbol" = yes; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' fi else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes _LT_TAGVAR(link_all_deplibs, $1)=yes ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; newsos6) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *nto* | *qnx*) ;; openbsd*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' else case $host_os in openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' ;; esac fi else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; solaris*) _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' if test "$GCC" = yes; then wlarc='${wl}' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='${wl}' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test "$GCC" = yes; then _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' fi ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4) case $host_vendor in sni) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' _LT_TAGVAR(hardcode_direct, $1)=no ;; motorola) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4.3*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes _LT_TAGVAR(ld_shlibs, $1)=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(ld_shlibs, $1)=no ;; esac if test x$host_vendor = xsni; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym' ;; esac fi fi ]) AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld _LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl _LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl _LT_DECL([], [extract_expsyms_cmds], [2], [The commands to extract the exported symbol list from a shared archive]) # # Do we need to explicitly link libc? # case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in x|xyes) # Assume -lc should be added _LT_TAGVAR(archive_cmds_need_lc, $1)=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $_LT_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. AC_CACHE_CHECK([whether -lc should be explicitly linked in], [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), [$RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if AC_TRY_EVAL(ac_compile) 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) _LT_TAGVAR(allow_undefined_flag, $1)= if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) then lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no else lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes fi _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* ]) _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) ;; esac fi ;; esac _LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], [Whether or not to add -lc for building shared libraries]) _LT_TAGDECL([allow_libtool_libs_with_static_runtimes], [enable_shared_with_static_runtimes], [0], [Whether or not to disallow shared libs when runtime libs are static]) _LT_TAGDECL([], [export_dynamic_flag_spec], [1], [Compiler flag to allow reflexive dlopens]) _LT_TAGDECL([], [whole_archive_flag_spec], [1], [Compiler flag to generate shared objects directly from archives]) _LT_TAGDECL([], [compiler_needs_object], [1], [Whether the compiler copes with passing no objects directly]) _LT_TAGDECL([], [old_archive_from_new_cmds], [2], [Create an old-style archive from a shared archive]) _LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], [Create a temporary old-style archive to link instead of a shared archive]) _LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) _LT_TAGDECL([], [archive_expsym_cmds], [2]) _LT_TAGDECL([], [module_cmds], [2], [Commands used to build a loadable module if different from building a shared archive.]) _LT_TAGDECL([], [module_expsym_cmds], [2]) _LT_TAGDECL([], [with_gnu_ld], [1], [Whether we are building with GNU ld or not]) _LT_TAGDECL([], [allow_undefined_flag], [1], [Flag that allows shared libraries with undefined symbols to be built]) _LT_TAGDECL([], [no_undefined_flag], [1], [Flag that enforces no undefined symbols]) _LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], [Flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]) _LT_TAGDECL([], [hardcode_libdir_separator], [1], [Whether we need a single "-rpath" flag with a separated argument]) _LT_TAGDECL([], [hardcode_direct], [0], [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_direct_absolute], [0], [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the resulting binary and the resulting library dependency is "absolute", i.e impossible to change by setting ${shlibpath_var} if the library is relocated]) _LT_TAGDECL([], [hardcode_minus_L], [0], [Set to "yes" if using the -LDIR flag during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_shlibpath_var], [0], [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_automatic], [0], [Set to "yes" if building a shared library automatically hardcodes DIR into the library and all subsequent libraries and executables linked against it]) _LT_TAGDECL([], [inherit_rpath], [0], [Set to yes if linker adds runtime paths of dependent libraries to runtime path list]) _LT_TAGDECL([], [link_all_deplibs], [0], [Whether libtool must link a program against all its dependency libraries]) _LT_TAGDECL([], [always_export_symbols], [0], [Set to "yes" if exported symbols are required]) _LT_TAGDECL([], [export_symbols_cmds], [2], [The commands to list exported symbols]) _LT_TAGDECL([], [exclude_expsyms], [1], [Symbols that should not be listed in the preloaded symbols]) _LT_TAGDECL([], [include_expsyms], [1], [Symbols that must always be exported]) _LT_TAGDECL([], [prelink_cmds], [2], [Commands necessary for linking programs (against libraries) with templates]) _LT_TAGDECL([], [postlink_cmds], [2], [Commands necessary for finishing linking programs]) _LT_TAGDECL([], [file_list_spec], [1], [Specify filename containing input files]) dnl FIXME: Not yet implemented dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], dnl [Compiler flag to generate thread safe objects]) ])# _LT_LINKER_SHLIBS # _LT_LANG_C_CONFIG([TAG]) # ------------------------ # Ensure that the configuration variables for a C compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to `libtool'. m4_defun([_LT_LANG_C_CONFIG], [m4_require([_LT_DECL_EGREP])dnl lt_save_CC="$CC" AC_LANG_PUSH(C) # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' _LT_TAG_COMPILER # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) LT_SYS_DLOPEN_SELF _LT_CMD_STRIPLIB # Report which library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_CONFIG($1) fi AC_LANG_POP CC="$lt_save_CC" ])# _LT_LANG_C_CONFIG # _LT_LANG_CXX_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to `libtool'. m4_defun([_LT_LANG_CXX_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl if test -n "$CXX" && ( test "X$CXX" != "Xno" && ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || (test "X$CXX" != "Xg++"))) ; then AC_PROG_CXXCPP else _lt_caught_CXX_error=yes fi AC_LANG_PUSH(C++) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_caught_CXX_error" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} CFLAGS=$CXXFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test "$GXX" = yes; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi if test "$GXX" = yes; then # Set up default GNU C++ configuration LT_PATH_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test "$with_gnu_ld" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='${wl}' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) _LT_TAGVAR(ld_shlibs, $1)=yes case $host_os in aix3*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aix[[4-9]]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' if test "$GXX" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. _LT_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an empty # executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared # libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl*) # Native MSVC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ func_to_tool_file "$lt_outputfile"~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF _LT_TAGVAR(ld_shlibs, $1)=no ;; freebsd-elf*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_TAGVAR(ld_shlibs, $1)=yes ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; hpux9*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; hpux10*|hpux11*) if test $with_gnu_ld = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) ;; *) _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes; then if test $with_gnu_ld = no; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test "$GXX" = yes; then if test "$with_gnu_ld" = no; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' fi fi _LT_TAGVAR(link_all_deplibs, $1)=yes ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' ;; cxx*) # Compaq C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; m88k*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) _LT_TAGVAR(ld_shlibs, $1)=yes ;; openbsd2*) # C++ shared libraries are fairly broken _LT_TAGVAR(ld_shlibs, $1)=no ;; openbsd*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; cxx*) case $host in osf3*) _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ $RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; esac _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' case $host in osf3*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # g++ 2.7 appears to require `-G' NOT `-shared' on this # platform. _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ '"$_LT_TAGVAR(old_archive_cmds, $1)" _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ '"$_LT_TAGVAR(reload_cmds, $1)" ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_TAGVAR(GCC, $1)="$GXX" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test "$_lt_caught_CXX_error" != yes AC_LANG_POP ])# _LT_LANG_CXX_CONFIG # _LT_FUNC_STRIPNAME_CNF # ---------------------- # func_stripname_cnf prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # # This function is identical to the (non-XSI) version of func_stripname, # except this one can be used by m4 code that may be executed by configure, # rather than the libtool script. m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl AC_REQUIRE([_LT_DECL_SED]) AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) func_stripname_cnf () { case ${2} in .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; esac } # func_stripname_cnf ])# _LT_FUNC_STRIPNAME_CNF # _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) # --------------------------------- # Figure out "hidden" library dependencies from verbose # compiler output when linking a shared library. # Parse the compiler output and extract the necessary # objects, libraries and library flags. m4_defun([_LT_SYS_HIDDEN_LIBDEPS], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl # Dependencies to place before and after the object being linked: _LT_TAGVAR(predep_objects, $1)= _LT_TAGVAR(postdep_objects, $1)= _LT_TAGVAR(predeps, $1)= _LT_TAGVAR(postdeps, $1)= _LT_TAGVAR(compiler_lib_search_path, $1)= dnl we can't use the lt_simple_compile_test_code here, dnl because it contains code intended for an executable, dnl not a library. It's possible we should let each dnl tag define a new lt_????_link_test_code variable, dnl but it's only used here... m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF int a; void foo (void) { a = 0; } _LT_EOF ], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF ], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer*4 a a=0 return end _LT_EOF ], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer a a=0 return end _LT_EOF ], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF public class foo { private int a; public void bar (void) { a = 0; } }; _LT_EOF ], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF package foo func foo() { } _LT_EOF ]) _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; *\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; esac dnl Parse the compiler output and extract the necessary dnl objects, libraries and library flags. if AC_TRY_EVAL(ac_compile); then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case ${prev}${p} in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test $p = "-L" || test $p = "-R"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test "$pre_test_object_deps_done" = no; then case ${prev} in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" else _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$_LT_TAGVAR(postdeps, $1)"; then _LT_TAGVAR(postdeps, $1)="${prev}${p}" else _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test "$pre_test_object_deps_done" = no; then if test -z "$_LT_TAGVAR(predep_objects, $1)"; then _LT_TAGVAR(predep_objects, $1)="$p" else _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" fi else if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then _LT_TAGVAR(postdep_objects, $1)="$p" else _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling $1 test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken m4_if([$1], [CXX], [case $host_os in interix[[3-9]]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. _LT_TAGVAR(predep_objects,$1)= _LT_TAGVAR(postdep_objects,$1)= _LT_TAGVAR(postdeps,$1)= ;; linux*) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac if test "$solaris_use_stlport4" != yes; then _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' fi ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac # Adding this requires a known-good setup of shared libraries for # Sun compiler versions before 5.6, else PIC objects from an old # archive will be linked into the output, leading to subtle bugs. if test "$solaris_use_stlport4" != yes; then _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' fi ;; esac ;; esac ]) case " $_LT_TAGVAR(postdeps, $1) " in *" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; esac _LT_TAGVAR(compiler_lib_search_dirs, $1)= if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` fi _LT_TAGDECL([], [compiler_lib_search_dirs], [1], [The directories searched by this compiler when creating a shared library]) _LT_TAGDECL([], [predep_objects], [1], [Dependencies to place before and after the objects being linked to create a shared library]) _LT_TAGDECL([], [postdep_objects], [1]) _LT_TAGDECL([], [predeps], [1]) _LT_TAGDECL([], [postdeps], [1]) _LT_TAGDECL([], [compiler_lib_search_path], [1], [The library search path used internally by the compiler when linking a shared library]) ])# _LT_SYS_HIDDEN_LIBDEPS # _LT_LANG_F77_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_F77_CONFIG], [AC_LANG_PUSH(Fortran 77) if test -z "$F77" || test "X$F77" = "Xno"; then _lt_disable_F77=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the F77 compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_disable_F77" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${F77-"f77"} CFLAGS=$FFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) GCC=$G77 if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)="$G77" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC="$lt_save_CC" CFLAGS="$lt_save_CFLAGS" fi # test "$_lt_disable_F77" != yes AC_LANG_POP ])# _LT_LANG_F77_CONFIG # _LT_LANG_FC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_FC_CONFIG], [AC_LANG_PUSH(Fortran) if test -z "$FC" || test "X$FC" = "Xno"; then _lt_disable_FC=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for fc test sources. ac_ext=${ac_fc_srcext-f} # Object file extension for compiled fc test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the FC compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_disable_FC" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${FC-"f95"} CFLAGS=$FCFLAGS compiler=$CC GCC=$ac_cv_fc_compiler_gnu _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test "$_lt_disable_FC" != yes AC_LANG_POP ])# _LT_LANG_FC_CONFIG # _LT_LANG_GCJ_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Java Compiler compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_GCJ_CONFIG], [AC_REQUIRE([LT_PROG_GCJ])dnl AC_LANG_SAVE # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GCJ-"gcj"} CFLAGS=$GCJFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)="$LD" _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GCJ_CONFIG # _LT_LANG_GO_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Go compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_GO_CONFIG], [AC_REQUIRE([LT_PROG_GO])dnl AC_LANG_SAVE # Source file extension for Go test sources. ac_ext=go # Object file extension for compiled Go test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="package main; func main() { }" # Code to be used in simple link tests lt_simple_link_test_code='package main; func main() { }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GOC-"gccgo"} CFLAGS=$GOFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)="$LD" _LT_CC_BASENAME([$compiler]) # Go did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GO_CONFIG # _LT_LANG_RC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for the Windows resource compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_RC_CONFIG], [AC_REQUIRE([LT_PROG_RC])dnl AC_LANG_SAVE # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests lt_simple_link_test_code="$lt_simple_compile_test_code" # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC= CC=${RC-"windres"} CFLAGS= compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes if test -n "$compiler"; then : _LT_CONFIG($1) fi GCC=$lt_save_GCC AC_LANG_RESTORE CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_RC_CONFIG # LT_PROG_GCJ # ----------- AC_DEFUN([LT_PROG_GCJ], [m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj,) test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS)])])[]dnl ]) # Old name: AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_GCJ], []) # LT_PROG_GO # ---------- AC_DEFUN([LT_PROG_GO], [AC_CHECK_TOOL(GOC, gccgo,) ]) # LT_PROG_RC # ---------- AC_DEFUN([LT_PROG_RC], [AC_CHECK_TOOL(RC, windres,) ]) # Old name: AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_RC], []) # _LT_DECL_EGREP # -------------- # If we don't have a new enough Autoconf to choose the best grep # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_EGREP], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_REQUIRE([AC_PROG_FGREP])dnl test -z "$GREP" && GREP=grep _LT_DECL([], [GREP], [1], [A grep program that handles long lines]) _LT_DECL([], [EGREP], [1], [An ERE matcher]) _LT_DECL([], [FGREP], [1], [A literal string matcher]) dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too AC_SUBST([GREP]) ]) # _LT_DECL_OBJDUMP # -------------- # If we don't have a new enough Autoconf to choose the best objdump # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_OBJDUMP], [AC_CHECK_TOOL(OBJDUMP, objdump, false) test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) AC_SUBST([OBJDUMP]) ]) # _LT_DECL_DLLTOOL # ---------------- # Ensure DLLTOOL variable is set. m4_defun([_LT_DECL_DLLTOOL], [AC_CHECK_TOOL(DLLTOOL, dlltool, false) test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program]) AC_SUBST([DLLTOOL]) ]) # _LT_DECL_SED # ------------ # Check for a fully-functional sed program, that truncates # as few characters as possible. Prefer GNU sed if found. m4_defun([_LT_DECL_SED], [AC_PROG_SED test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" _LT_DECL([], [SED], [1], [A sed program that does not truncate output]) _LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], [Sed that helps us avoid accidentally triggering echo(1) options like -n]) ])# _LT_DECL_SED m4_ifndef([AC_PROG_SED], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_SED. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_SED], [AC_MSG_CHECKING([for a sed that does not truncate output]) AC_CACHE_VAL(lt_cv_path_SED, [# Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done IFS=$as_save_IFS lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f $lt_ac_sed && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test $lt_ac_count -gt 10 && break lt_ac_count=`expr $lt_ac_count + 1` if test $lt_ac_count -gt $lt_ac_max; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done ]) SED=$lt_cv_path_SED AC_SUBST([SED]) AC_MSG_RESULT([$SED]) ])#AC_PROG_SED ])#m4_ifndef # Old name: AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_SED], []) # _LT_CHECK_SHELL_FEATURES # ------------------------ # Find out whether the shell is Bourne or XSI compatible, # or has some other useful features. m4_defun([_LT_CHECK_SHELL_FEATURES], [AC_MSG_CHECKING([whether the shell understands some XSI constructs]) # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ = c,a/b,b/c, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes AC_MSG_RESULT([$xsi_shell]) _LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell']) AC_MSG_CHECKING([whether the shell understands "+="]) lt_shell_append=no ( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \ >/dev/null 2>&1 \ && lt_shell_append=yes AC_MSG_RESULT([$lt_shell_append]) _LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append']) if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi _LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac _LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl _LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl ])# _LT_CHECK_SHELL_FEATURES # _LT_PROG_FUNCTION_REPLACE (FUNCNAME, REPLACEMENT-BODY) # ------------------------------------------------------ # In `$cfgfile', look for function FUNCNAME delimited by `^FUNCNAME ()$' and # '^} FUNCNAME ', and replace its body with REPLACEMENT-BODY. m4_defun([_LT_PROG_FUNCTION_REPLACE], [dnl { sed -e '/^$1 ()$/,/^} # $1 /c\ $1 ()\ {\ m4_bpatsubsts([$2], [$], [\\], [^\([ ]\)], [\\\1]) } # Extended-shell $1 implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: ]) # _LT_PROG_REPLACE_SHELLFNS # ------------------------- # Replace existing portable implementations of several shell functions with # equivalent extended shell implementations where those features are available.. m4_defun([_LT_PROG_REPLACE_SHELLFNS], [if test x"$xsi_shell" = xyes; then _LT_PROG_FUNCTION_REPLACE([func_dirname], [dnl case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac]) _LT_PROG_FUNCTION_REPLACE([func_basename], [dnl func_basename_result="${1##*/}"]) _LT_PROG_FUNCTION_REPLACE([func_dirname_and_basename], [dnl case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac func_basename_result="${1##*/}"]) _LT_PROG_FUNCTION_REPLACE([func_stripname], [dnl # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are # positional parameters, so assign one to ordinary parameter first. func_stripname_result=${3} func_stripname_result=${func_stripname_result#"${1}"} func_stripname_result=${func_stripname_result%"${2}"}]) _LT_PROG_FUNCTION_REPLACE([func_split_long_opt], [dnl func_split_long_opt_name=${1%%=*} func_split_long_opt_arg=${1#*=}]) _LT_PROG_FUNCTION_REPLACE([func_split_short_opt], [dnl func_split_short_opt_arg=${1#??} func_split_short_opt_name=${1%"$func_split_short_opt_arg"}]) _LT_PROG_FUNCTION_REPLACE([func_lo2o], [dnl case ${1} in *.lo) func_lo2o_result=${1%.lo}.${objext} ;; *) func_lo2o_result=${1} ;; esac]) _LT_PROG_FUNCTION_REPLACE([func_xform], [ func_xform_result=${1%.*}.lo]) _LT_PROG_FUNCTION_REPLACE([func_arith], [ func_arith_result=$(( $[*] ))]) _LT_PROG_FUNCTION_REPLACE([func_len], [ func_len_result=${#1}]) fi if test x"$lt_shell_append" = xyes; then _LT_PROG_FUNCTION_REPLACE([func_append], [ eval "${1}+=\\${2}"]) _LT_PROG_FUNCTION_REPLACE([func_append_quoted], [dnl func_quote_for_eval "${2}" dnl m4 expansion turns \\\\ into \\, and then the shell eval turns that into \ eval "${1}+=\\\\ \\$func_quote_for_eval_result"]) # Save a `func_append' function call where possible by direct use of '+=' sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: else # Save a `func_append' function call even when '+=' is not available sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$_lt_function_replace_fail" = x":"; then AC_MSG_WARN([Unable to substitute extended shell functions in $ofile]) fi ]) # _LT_PATH_CONVERSION_FUNCTIONS # ----------------------------- # Determine which file name conversion functions should be used by # func_to_host_file (and, implicitly, by func_to_host_path). These are needed # for certain cross-compile configurations and native mingw. m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_MSG_CHECKING([how to convert $build file names to $host format]) AC_CACHE_VAL(lt_cv_to_host_file_cmd, [case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac ]) to_host_file_cmd=$lt_cv_to_host_file_cmd AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) _LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], [0], [convert $build file names to $host format])dnl AC_MSG_CHECKING([how to convert $build file names to toolchain format]) AC_CACHE_VAL(lt_cv_to_tool_file_cmd, [#assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac ]) to_tool_file_cmd=$lt_cv_to_tool_file_cmd AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) _LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], [0], [convert $build files to toolchain format])dnl ])# _LT_PATH_CONVERSION_FUNCTIONS xfsdump-3.1.6+nmu1/m4/manual_format.m40000644000000000000000000000075112607344125014367 0ustar # # Find format of installed man pages. # Always gzipped on Debian, but not Redhat pre-7.0. # We don't deal with bzip2'd man pages, which Mandrake uses, # someone will send us a patch sometime hopefully. :-) # AC_DEFUN([AC_MANUAL_FORMAT], [ have_zipped_manpages=false for d in ${prefix}/share/man ${prefix}/man ; do if test -f $d/man1/man.1.gz then have_zipped_manpages=true break fi done AC_SUBST(have_zipped_manpages) ]) xfsdump-3.1.6+nmu1/m4/package_ncurses.m40000644000000000000000000000167012607344125014700 0ustar AC_DEFUN([AC_PACKAGE_NEED_NCURSES_H], [ AC_CHECK_HEADERS([ncurses.h]) if test "$ac_cv_header_ncurses_h" != yes; then echo echo 'FATAL ERROR: could not find a valid ncurses header.' echo 'Install the ncurses development package.' exit 1 fi ]) AC_DEFUN([AC_PACKAGE_WANT_WORKING_LIBNCURSES], [ AC_CHECK_LIB(ncurses, initscr,, [ echo echo 'FATAL ERROR: could not find a valid ncurses library.' echo 'Install the ncurses library package.' exit 1 ]) AC_MSG_CHECKING([for bad glibc/ncurses header interaction]) libcurses="-lncurses" LIBS="$LIBS $libcurses" CFLAGS="$CFLAGS -D_GNU_SOURCE" AC_TRY_LINK([ #include #include ], [wgetch(stdscr);], [enable_curses=yes; AC_MSG_RESULT([ok])], [enable_curses=no; libcurses=""; AC_MSG_RESULT([disabling curses])]) AC_SUBST(enable_curses) AC_SUBST(libcurses) ]) xfsdump-3.1.6+nmu1/m4/ltsugar.m40000644000000000000000000001042412607344146013224 0ustar # ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 6 ltsugar.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) # lt_join(SEP, ARG1, [ARG2...]) # ----------------------------- # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their # associated separator. # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier # versions in m4sugar had bugs. m4_define([lt_join], [m4_if([$#], [1], [], [$#], [2], [[$2]], [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) m4_define([_lt_join], [m4_if([$#$2], [2], [], [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) # lt_car(LIST) # lt_cdr(LIST) # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support # Autoconf-2.59 which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], [$#], 1, [], [m4_dquote(m4_shift($@))])]) m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ # Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different # than defined and empty). # # This macro is needed until we can rely on Autoconf 2.62, since earlier # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. m4_define([lt_append], [m4_define([$1], m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) # ---------------------------------------------------------- # Produce a SEP delimited list of all paired combinations of elements of # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list # has the form PREFIXmINFIXSUFFIXn. # Needed until we can rely on m4_combine added in Autoconf 2.62. m4_define([lt_combine], [m4_if(m4_eval([$# > 3]), [1], [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl [[m4_foreach([_Lt_prefix], [$2], [m4_foreach([_Lt_suffix], ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) # ----------------------------------------------------------------------- # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. m4_define([lt_if_append_uniq], [m4_ifdef([$1], [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], [lt_append([$1], [$2], [$3])$4], [$5])], [lt_append([$1], [$2], [$3])$4])]) # lt_dict_add(DICT, KEY, VALUE) # ----------------------------- m4_define([lt_dict_add], [m4_define([$1($2)], [$3])]) # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) # -------------------------------------------- m4_define([lt_dict_add_subkey], [m4_define([$1($2:$3)], [$4])]) # lt_dict_fetch(DICT, KEY, [SUBKEY]) # ---------------------------------- m4_define([lt_dict_fetch], [m4_ifval([$3], m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) # ----------------------------------------------------------------- m4_define([lt_if_dict_fetch], [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], [$5], [$6])]) # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) # -------------------------------------------------------------- m4_define([lt_dict_filter], [m4_if([$5], [], [], [lt_join(m4_quote(m4_default([$4], [[, ]])), lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl ]) xfsdump-3.1.6+nmu1/m4/package_uuiddev.m40000644000000000000000000000137012607344125014660 0ustar AC_DEFUN([AC_PACKAGE_NEED_UUID_H], [ AC_CHECK_HEADERS([uuid.h sys/uuid.h uuid/uuid.h]) if test $ac_cv_header_uuid_h = no -a \ $ac_cv_header_sys_uuid_h = no -a \ $ac_cv_header_uuid_uuid_h = no; then echo echo 'FATAL ERROR: could not find a valid UUID header.' echo 'Install the Universally Unique Identifiers development package.' exit 1 fi ]) AC_DEFUN([AC_PACKAGE_NEED_UUIDCOMPARE], [ AC_CHECK_FUNCS(uuid_compare) if test $ac_cv_func_uuid_compare = yes; then libuuid="" else AC_CHECK_LIB(uuid, uuid_compare,, [ echo echo 'FATAL ERROR: could not find a valid UUID library.' echo 'Install the Universally Unique Identifiers library package.' exit 1]) libuuid="-luuid" fi AC_SUBST(libuuid) ]) xfsdump-3.1.6+nmu1/m4/Makefile0000644000000000000000000000104612607344125012736 0ustar # # Copyright (c) 2003-2006 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = .. include $(TOPDIR)/include/builddefs CONFIGURE = \ libtool.m4 \ ltoptions.m4 \ ltsugar.m4 \ ltversion.m4 \ lt~obsolete.m4 LSRCFILES = \ manual_format.m4 \ package_attrdev.m4 \ package_globals.m4 \ package_ncurses.m4 \ package_pthread.m4 \ package_utilies.m4 \ package_uuiddev.m4 \ package_xfslibs.m4 \ multilib.m4 \ $(CONFIGURE) default: include $(BUILDRULES) install install-dev install-lib: default realclean: distclean rm -f $(CONFIGURE) xfsdump-3.1.6+nmu1/m4/package_attrdev.m40000644000000000000000000000546112607344125014671 0ustar AC_DEFUN([AC_PACKAGE_NEED_ATTR_XATTR_H], [ AC_CHECK_HEADERS([attr/xattr.h]) if test "$ac_cv_header_attr_xattr_h" != "yes"; then echo echo 'FATAL ERROR: attr/xattr.h does not exist.' echo 'Install the extended attributes (attr) development package.' echo 'Alternatively, run "make install-dev" from the attr source.' exit 1 fi ]) AC_DEFUN([AC_PACKAGE_NEED_ATTR_ERROR_H], [ AC_CHECK_HEADERS([attr/error_context.h]) if test "$ac_cv_header_attr_error_context_h" != "yes"; then echo echo 'FATAL ERROR: attr/error_context.h does not exist.' echo 'Install the extended attributes (attr) development package.' echo 'Alternatively, run "make install-dev" from the attr source.' exit 1 fi ]) AC_DEFUN([AC_PACKAGE_NEED_ATTRIBUTES_H], [ have_attributes_h=false AC_CHECK_HEADERS([attr/attributes.h sys/attributes.h], [have_attributes_h=true], ) if test "$have_attributes_h" = "false"; then echo echo 'FATAL ERROR: attributes.h does not exist.' echo 'Install the extended attributes (attr) development package.' echo 'Alternatively, run "make install-dev" from the attr source.' exit 1 fi ]) AC_DEFUN([AC_PACKAGE_WANT_ATTRLIST_LIBATTR], [ AC_CHECK_LIB(attr, attr_list, [have_attr_list=true], [have_attr_list=false]) AC_SUBST(have_attr_list) ]) AC_DEFUN([AC_PACKAGE_NEED_GETXATTR_LIBATTR], [ AC_CHECK_LIB(attr, getxattr,, [ echo echo 'FATAL ERROR: could not find a valid Extended Attributes library.' echo 'Install the extended attributes (attr) development package.' echo 'Alternatively, run "make install-lib" from the attr source.' exit 1 ]) libattr="-lattr" test -f ${libexecdir}${libdirsuffix}/libattr.la && \ libattr="${libexecdir}${libdirsuffix}/libattr.la" AC_SUBST(libattr) ]) AC_DEFUN([AC_PACKAGE_NEED_ATTRGET_LIBATTR], [ AC_CHECK_LIB(attr, attr_get,, [ echo echo 'FATAL ERROR: could not find a valid Extended Attributes library.' echo 'Install the extended attributes (attr) development package.' echo 'Alternatively, run "make install-lib" from the attr source.' exit 1 ]) libattr="-lattr" test -f ${libexecdir}${libdirsuffix}/libattr.la && \ libattr="${libexecdir}${libdirsuffix}/libattr.la" AC_SUBST(libattr) ]) AC_DEFUN([AC_PACKAGE_NEED_ATTRIBUTES_MACROS], [ AC_MSG_CHECKING([macros in attr/attributes.h]) AC_TRY_LINK([ #include #include ], [ int x = ATTR_SECURE; ], [ echo ok ], [ echo echo 'FATAL ERROR: could not find a current attributes header.' echo 'Upgrade the extended attributes (attr) development package.' echo 'Alternatively, run "make install-dev" from the attr source.' exit 1 ]) ]) xfsdump-3.1.6+nmu1/m4/ltoptions.m40000644000000000000000000003007312607344146013600 0ustar # Helper functions for option handling. -*- Autoconf -*- # # Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, # Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 7 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) # ------------------------------------------ m4_define([_LT_MANGLE_OPTION], [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) # --------------------------------------- # Set option OPTION-NAME for macro MACRO-NAME, and if there is a # matching handler defined, dispatch to it. Other OPTION-NAMEs are # saved as a flag. m4_define([_LT_SET_OPTION], [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), [m4_warning([Unknown $1 option `$2'])])[]dnl ]) # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) # ------------------------------------------------------------ # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. m4_define([_LT_IF_OPTION], [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) # ------------------------------------------------------- # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME # are set. m4_define([_LT_UNLESS_OPTIONS], [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), [m4_define([$0_found])])])[]dnl m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 ])[]dnl ]) # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) # ---------------------------------------- # OPTION-LIST is a space-separated list of Libtool options associated # with MACRO-NAME. If any OPTION has a matching handler declared with # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about # the unknown option and exit. m4_defun([_LT_SET_OPTIONS], [# Set options m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [_LT_SET_OPTION([$1], _LT_Option)]) m4_if([$1],[LT_INIT],[ dnl dnl Simply set some default values (i.e off) if boolean options were not dnl specified: _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no ]) _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no ]) dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither dnl `shared' nor `disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], [_LT_ENABLE_FAST_INSTALL]) ]) ])# _LT_SET_OPTIONS ## --------------------------------- ## ## Macros to handle LT_INIT options. ## ## --------------------------------- ## # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) # ----------------------------------------- m4_define([_LT_MANGLE_DEFUN], [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) # ----------------------------------------------- m4_define([LT_OPTION_DEFINE], [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl ])# LT_OPTION_DEFINE # dlopen # ------ LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes ]) AU_DEFUN([AC_LIBTOOL_DLOPEN], [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) # win32-dll # --------- # Declare package support for building win32 dll's. LT_OPTION_DEFINE([LT_INIT], [win32-dll], [enable_win32_dll=yes case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) ;; esac test -z "$AS" && AS=as _LT_DECL([], [AS], [1], [Assembler program])dnl test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl ])# win32-dll AU_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_REQUIRE([AC_CANONICAL_HOST])dnl _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- # implement the --enable-shared flag, and supports the `shared' and # `disable-shared' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) _LT_DECL([build_libtool_libs], [enable_shared], [0], [Whether or not to build shared libraries]) ])# _LT_ENABLE_SHARED LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) # Old names: AC_DEFUN([AC_ENABLE_SHARED], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) ]) AC_DEFUN([AC_DISABLE_SHARED], [_LT_SET_OPTION([LT_INIT], [disable-shared]) ]) AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_SHARED], []) dnl AC_DEFUN([AM_DISABLE_SHARED], []) # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- # implement the --enable-static flag, and support the `static' and # `disable-static' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_static=]_LT_ENABLE_STATIC_DEFAULT) _LT_DECL([build_old_libs], [enable_static], [0], [Whether or not to build static libraries]) ])# _LT_ENABLE_STATIC LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) # Old names: AC_DEFUN([AC_ENABLE_STATIC], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) ]) AC_DEFUN([AC_DISABLE_STATIC], [_LT_SET_OPTION([LT_INIT], [disable-static]) ]) AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_STATIC], []) dnl AC_DEFUN([AM_DISABLE_STATIC], []) # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- # implement the --enable-fast-install flag, and support the `fast-install' # and `disable-fast-install' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) _LT_DECL([fast_install], [enable_fast_install], [0], [Whether or not to optimize for fast installation])dnl ])# _LT_ENABLE_FAST_INSTALL LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) # Old names: AU_DEFUN([AC_ENABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) # _LT_WITH_PIC([MODE]) # -------------------- # implement the --with-pic flag, and support the `pic-only' and `no-pic' # LT_INIT options. # MODE is either `yes' or `no'. If omitted, it defaults to `both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for lt_pkg in $withval; do IFS="$lt_save_ifs" if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS="$lt_save_ifs" ;; esac], [pic_mode=default]) test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) # Old name: AU_DEFUN([AC_LIBTOOL_PICMODE], [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) ## ----------------- ## ## LTDL_INIT Options ## ## ----------------- ## m4_define([_LTDL_MODE], []) LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], [m4_define([_LTDL_MODE], [nonrecursive])]) LT_OPTION_DEFINE([LTDL_INIT], [recursive], [m4_define([_LTDL_MODE], [recursive])]) LT_OPTION_DEFINE([LTDL_INIT], [subproject], [m4_define([_LTDL_MODE], [subproject])]) m4_define([_LTDL_TYPE], []) LT_OPTION_DEFINE([LTDL_INIT], [installable], [m4_define([_LTDL_TYPE], [installable])]) LT_OPTION_DEFINE([LTDL_INIT], [convenience], [m4_define([_LTDL_TYPE], [convenience])]) xfsdump-3.1.6+nmu1/m4/package_utilies.m40000644000000000000000000000757712607344125014710 0ustar # # Check for specified utility (env var) - if unset, fail. # AC_DEFUN([AC_PACKAGE_NEED_UTILITY], [ if test -z "$2"; then echo echo FATAL ERROR: $3 does not seem to be installed. echo $1 cannot be built without a working $4 installation. exit 1 fi ]) # #check compiler can generate dependencies # AC_DEFUN([AC_PACKAGE_GCC_DEPS], [AC_CACHE_CHECK(whether gcc -MM is supported, ac_cv_gcc_nodeps, [cat > conftest.c < int main() { exit(0); } EOF ac_cv_gcc_nodeps=no if ${CC} -MM conftest.c >/dev/null 2>&1; then ac_cv_gcc_nodeps=yes fi rm -f conftest.c a.out ]) ]) # # Generic macro, sets up all of the global build variables. # The following environment variables may be set to override defaults: # CC MAKE LIBTOOL TAR ZIP MAKEDEPEND AWK SED ECHO SORT # MSGFMT MSGMERGE XGETTEXT RPM # AC_DEFUN([AC_PACKAGE_UTILITIES], [ AC_PROG_CC cc="$CC" AC_SUBST(cc) AC_PACKAGE_NEED_UTILITY($1, "$cc", cc, [C compiler]) if test -z "$MAKE"; then AC_PATH_PROG(MAKE, gmake,, /usr/bin:/usr/local/bin:/usr/freeware/bin) fi if test -z "$MAKE"; then AC_PATH_PROG(MAKE, make,, /usr/bin) fi make=$MAKE AC_SUBST(make) AC_PACKAGE_NEED_UTILITY($1, "$make", make, [GNU make]) if test -z "$TAR"; then AC_PATH_PROG(TAR, tar,, /usr/freeware/bin:/bin:/usr/local/bin:/usr/bin) fi tar=$TAR AC_SUBST(tar) if test -z "$ZIP"; then AC_PATH_PROG(ZIP, gzip,, /bin:/usr/bin:/usr/local/bin:/usr/freeware/bin) fi zip=$ZIP AC_SUBST(zip) AC_PACKAGE_GCC_DEPS() makedepend="$cc -MM" if test $ac_cv_gcc_nodeps = no; then makedepend=/bin/true fi AC_SUBST(makedepend) if test -z "$AWK"; then AC_PATH_PROG(AWK, awk,, /bin:/usr/bin) fi awk=$AWK AC_SUBST(awk) if test -z "$SED"; then AC_PATH_PROG(SED, sed,, /bin:/usr/bin) fi sed=$SED AC_SUBST(sed) if test -z "$ECHO"; then AC_PATH_PROG(ECHO, echo,, /bin:/usr/bin) fi echo=$ECHO AC_SUBST(echo) if test -z "$SORT"; then AC_PATH_PROG(SORT, sort,, /bin:/usr/bin) fi sort=$SORT AC_SUBST(sort) dnl check if symbolic links are supported AC_PROG_LN_S if test "$enable_gettext" = yes; then if test -z "$MSGFMT"; then AC_PATH_PROG(MSGFMT, msgfmt,, /usr/bin:/usr/local/bin:/usr/freeware/bin) fi msgfmt=$MSGFMT AC_SUBST(msgfmt) AC_PACKAGE_NEED_UTILITY($1, "$msgfmt", msgfmt, gettext) if test -z "$MSGMERGE"; then AC_PATH_PROG(MSGMERGE, msgmerge,, /usr/bin:/usr/local/bin:/usr/freeware/bin) fi msgmerge=$MSGMERGE AC_SUBST(msgmerge) AC_PACKAGE_NEED_UTILITY($1, "$msgmerge", msgmerge, gettext) if test -z "$XGETTEXT"; then AC_PATH_PROG(XGETTEXT, xgettext,, /usr/bin:/usr/local/bin:/usr/freeware/bin) fi xgettext=$XGETTEXT AC_SUBST(xgettext) AC_PACKAGE_NEED_UTILITY($1, "$xgettext", xgettext, gettext) fi if test -z "$RPM"; then AC_PATH_PROG(RPM, rpm,, /bin:/usr/bin:/usr/freeware/bin) fi rpm=$RPM AC_SUBST(rpm) dnl .. and what version is rpm rpm_version=0 test -n "$RPM" && test -x "$RPM" && rpm_version=`$RPM --version \ | awk '{print $NF}' | awk -F. '{V=1; print $V}'` AC_SUBST(rpm_version) dnl At some point in rpm 4.0, rpm can no longer build rpms, and dnl rpmbuild is needed (rpmbuild may go way back; not sure) dnl So, if rpm version >= 4.0, look for rpmbuild. Otherwise build w/ rpm if test $rpm_version -ge 4; then AC_PATH_PROG(RPMBUILD, rpmbuild) rpmbuild=$RPMBUILD else rpmbuild=$RPM fi AC_SUBST(rpmbuild) ]) xfsdump-3.1.6+nmu1/m4/multilib.m40000644000000000000000000000345412607344125013366 0ustar # The AC_MULTILIB macro was extracted and modified from # gettext-0.15's AC_LIB_PREPARE_MULTILIB macro in the lib-prefix.m4 file # so that the correct paths can be used for 64-bit libraries. # dnl Copyright (C) 2001-2005 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. dnl AC_MULTILIB creates a variable libdirsuffix, containing dnl the suffix of the libdir, either "" or "64". dnl Only do this if the given enable parameter is "yes". AC_DEFUN([AC_MULTILIB], [ dnl There is no formal standard regarding lib and lib64. The current dnl practice is that on a system supporting 32-bit and 64-bit instruction dnl sets or ABIs, 64-bit libraries go under $prefix/lib64 and 32-bit dnl libraries go under $prefix/lib. We determine the compiler's default dnl mode by looking at the compiler's library search path. If at least dnl of its elements ends in /lib64 or points to a directory whose absolute dnl pathname ends in /lib64, we assume a 64-bit ABI. Otherwise we use the dnl default, namely "lib". enable_lib64="$1" libdirsuffix="" searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'` if test "$enable_lib64" = "yes" -a -n "$searchpath"; then save_IFS="${IFS= }"; IFS=":" for searchdir in $searchpath; do if test -d "$searchdir"; then case "$searchdir" in */lib64/ | */lib64 ) libdirsuffix=64 ;; *) searchdir=`cd "$searchdir" && pwd` case "$searchdir" in */lib64 ) libdirsuffix=64 ;; esac ;; esac fi done IFS="$save_IFS" fi AC_SUBST(libdirsuffix) ]) xfsdump-3.1.6+nmu1/m4/package_pthread.m40000644000000000000000000000072512607344125014645 0ustar AC_DEFUN([AC_PACKAGE_NEED_PTHREAD_H], [ AC_CHECK_HEADERS(pthread.h) if test $ac_cv_header_pthread_h = no; then AC_CHECK_HEADERS(pthread.h,, [ echo echo 'FATAL ERROR: could not find a valid pthread header.' exit 1]) fi ]) AC_DEFUN([AC_PACKAGE_NEED_PTHREADMUTEXINIT], [ AC_CHECK_LIB(pthread, pthread_mutex_init,, [ echo echo 'FATAL ERROR: could not find a valid pthread library.' exit 1 ]) libpthread=-lpthread AC_SUBST(libpthread) ]) xfsdump-3.1.6+nmu1/m4/lt~obsolete.m40000644000000000000000000001375612607344146014130 0ustar # lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 5 lt~obsolete.m4 # These exist entirely to fool aclocal when bootstrapping libtool. # # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us # using a macro with the same name in our local m4/libtool.m4 it'll # pull the old libtool.m4 in (it doesn't see our shiny new m4_define # and doesn't know about Autoconf macros at all.) # # So we provide this file, which has a silly filename so it's always # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until # we give up compatibility with versions before 1.7, at which point # we need to keep only those names which we still refer to. # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) xfsdump-3.1.6+nmu1/m4/package_xfslibs.m40000644000000000000000000000723012607344125014666 0ustar AC_DEFUN([AC_PACKAGE_NEED_XFS_XFS_H], [ AC_CHECK_HEADERS([xfs/xfs.h]) if test "$ac_cv_header_xfs_xfs_h" != "yes"; then echo echo 'FATAL ERROR: cannot find a valid header file.' echo 'Install or upgrade the XFS development package.' echo 'Alternatively, run "make install-dev" from the xfsprogs source.' exit 1 fi ]) AC_DEFUN([AC_PACKAGE_NEED_XFS_XQM_H], [ AC_CHECK_HEADERS([xfs/xqm.h]) if test "$ac_cv_header_xfs_xqm_h" != "yes"; then echo echo 'FATAL ERROR: cannot find a valid header file.' echo 'Install or upgrade the XFS development package.' echo 'Alternatively, run "make install-dev" from the xfsprogs source.' exit 1 fi ]) AC_DEFUN([AC_PACKAGE_NEED_XFS_HANDLE_H], [ AC_CHECK_HEADERS([xfs/handle.h]) if test "$ac_cv_header_xfs_handle_h" != "yes"; then echo echo 'FATAL ERROR: cannot find a valid header file.' echo 'Install or upgrade the XFS development package.' echo 'Alternatively, run "make install-dev" from the xfsprogs source.' exit 1 fi ]) AC_DEFUN([AC_PACKAGE_NEED_LIBXFSINIT_LIBXFS], [ AC_CHECK_LIB(xfs, libxfs_init,, [ echo echo 'FATAL ERROR: could not find a valid XFS base library.' echo 'Install or upgrade the XFS library package.' echo 'Alternatively, run "make install-dev" from the xfsprogs source.' exit 1 ]) libxfs="-lxfs" test -f `pwd`/../xfsprogs/libxfs/libxfs.la && \ libxfs="`pwd`/../xfsprogs/libxfs/libxfs.la" test -f ${libexecdir}${libdirsuffix}/libxfs.la && \ libxfs="${libexecdir}${libdirsuffix}/libxfs.la" AC_SUBST(libxfs) ]) AC_DEFUN([AC_PACKAGE_NEED_OPEN_BY_FSHANDLE], [ AC_CHECK_LIB(handle, open_by_fshandle,, [ echo echo 'FATAL ERROR: could not find a current XFS handle library.' echo 'Install or upgrade the XFS library package.' echo 'Alternatively, run "make install-dev" from the xfsprogs source.' exit 1 ]) libhdl="-lhandle" test -f `pwd`/../xfsprogs/libhandle/libhandle.la && \ libhdl="`pwd`/../xfsprogs/libhandle/libhandle.la" test -f ${libexecdir}${libdirsuffix}/libhandle.la && \ libhdl="${libexecdir}${libdirsuffix}/libhandle.la" AC_SUBST(libhdl) ]) AC_DEFUN([AC_PACKAGE_NEED_ATTRLIST_LIBHANDLE], [ AC_CHECK_LIB(handle, attr_list_by_handle,, [ echo echo 'FATAL ERROR: could not find a current XFS handle library.' echo 'Install or upgrade the XFS library package.' echo 'Alternatively, run "make install-lib" from the xfsprogs source.' exit 1 ]) libhdl="-lhandle" test -f `pwd`/../xfsprogs/libhandle/libhandle.la && \ libhdl="`pwd`/../xfsprogs/libhandle/libhandle.la" test -f ${libexecdir}${libdirsuffix}/libhandle.la && \ libhdl="${libexecdir}${libdirsuffix}/libhandle.la" AC_SUBST(libhdl) ]) AC_DEFUN([AC_PACKAGE_NEED_IRIX_LIBHANDLE], [ AC_MSG_CHECKING([libhandle.a for IRIX]) libhdl="`pwd`/../irix/libhandle/libhandle.a" if ! test -f $libhdl; then echo 'no' echo 'FATAL ERROR: could not find IRIX XFS handle library.' exit 1 fi echo 'yes' AC_SUBST(libhdl) ]) AC_DEFUN([AC_PACKAGE_NEED_XFSCTL_MACRO], [ AC_MSG_CHECKING([xfsctl from xfs/libxfs.h]) AC_TRY_LINK([#include ], [ int x = xfsctl(0, 0, 0, 0); ], [ echo ok ], [ echo echo 'FATAL ERROR: cannot find required macros in the XFS headers.' echo 'Upgrade your XFS programs (xfsprogs) development package.' echo 'Alternatively, run "make install-dev" from the xfsprogs source.' exit 1 ]) ]) xfsdump-3.1.6+nmu1/invutil/0000755000000000000000000000000012643557274012462 5ustar xfsdump-3.1.6+nmu1/invutil/list.h0000644000000000000000000000370412607344125013577 0ustar /* * Copyright (c) 2002 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef LIST_H #define LIST_H struct menu_ops_s; typedef struct node_s { void *data; struct node_s *next; struct node_s *prev; } node_t; typedef struct { int level; /* indentation level in menu */ int hidden; /* flag: displayed in menu */ int expanded; /* flag: children displayed in menu */ int deleted; /* flag: marked as deleted in menu */ int imported; /* flag: marked as imported in menu */ int commited; /* flag: record already commited */ int file_idx; /* index into file table */ char *text; /* text displayed in menu */ struct menu_ops_s *ops; /* table of applicable operations */ node_t *parent; /* parent node */ node_t **children; /* child nodes */ int nbr_children; /* number of children nodes */ int data_idx; /* real data in mmap file */ } data_t; void node_free(node_t *node); node_t *node_create(int hidden, int expanded, int level, int deleted, int file_idx, char *text, struct menu_ops_s *ops, node_t *parent, node_t **children, int nbr_children, int data_idx); node_t *list_add(node_t *prevnode, node_t *newnode); node_t *list_del(node_t *node); node_t *free_all_children(node_t *node); node_t *mark_all_children_commited(node_t *node); #endif /* LIST_H */ xfsdump-3.1.6+nmu1/invutil/invidx.c0000644000000000000000000007051312620476160014122 0ustar /* * Copyright (c) 2002 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include "types.h" #include "mlog.h" #include "inv_priv.h" #include "getopt.h" #include "invutil.h" #include "cmenu.h" #include "list.h" #include "invidx.h" #include "stobj.h" #include "timeutil.h" invidx_fileinfo_t *invidx_file; int invidx_numfiles; extern stobj_fileinfo_t *stobj_file; extern int stobj_numfiles; static void stobj_makefname_len( char *fname, int fname_len ); menu_ops_t invidx_ops = { NULL, invidx_undelete, NULL, invidx_select, NULL, NULL, NULL, NULL, invidx_highlight, menu_unhighlight, invidx_commit, invidx_prune, }; /*ARGSUSED*/ int invidx_commit(WINDOW *win, node_t *current, node_t *list) { int i; int idx; int fidx; node_t *n; data_t *d; invt_entry_t *inv_entry; n = current; if(n == NULL || n->data == NULL) return 0; d = ((data_t *)(n->data)); fidx = d->file_idx; inv_entry = invidx_file[fidx].data[d->data_idx]; idx = (int)(((long)inv_entry - (long)invidx_file[fidx].mapaddr - sizeof(invt_counter_t)) / sizeof(invt_entry_t)); if(d->deleted == BOOL_TRUE && d->imported == BOOL_FALSE) { /* shortcut - just close and unlink stobj files */ for(i = 0; i < d->nbr_children; i++) { close_stobj_file(((data_t *)(d->children[i]->data))->file_idx, BOOL_TRUE); } mark_all_children_commited(current); if ( invidx_file[fidx].counter->ic_curnum > 1 ) { memmove(&inv_entry[idx], &inv_entry[idx + 1], (sizeof(invt_entry_t) * (invidx_file[fidx].counter->ic_curnum - idx - 1))); invidx_file[fidx].data[idx]=NULL; for(i = idx + 1; i < invidx_file[fidx].numrecords; i++) { if(invidx_file[fidx].data[i] != NULL) invidx_file[fidx].data[i]--; } } invidx_file[fidx].counter->ic_curnum--; } else if(d->imported == BOOL_TRUE) { int dst_fileidx; int dst_invpos; int dst_invidx; char dst_idxfile[MAXPATHLEN]; struct stat s; char dst_stobjfile[MAXPATHLEN]; char *stobjfile; char cmd[1024]; snprintf(dst_idxfile, sizeof(dst_idxfile), "%s/%s", inventory_path, basename(invidx_file[fidx].name)); /* append if we have the target open already, else write to a possibly new file */ if((dst_fileidx = find_matching_invidxfile(dst_idxfile)) >= 0) { invt_entry_t *dest = NULL; if((dst_invidx = find_overlapping_invidx(dst_fileidx, inv_entry)) >= 0) { char *stobj_filename = NULL; int stobj_fd = -1; int stobj_fileidx; int last_dst_invidx; node_t *tmp_parent; data_t *tmp_d; node_t *dst_n; data_t *dst_d; invt_seshdr_t *hdr; invt_session_t *ses; invt_stream_t *strms; invt_mediafile_t *mfiles; last_dst_invidx = -1; i = d->nbr_children - 1; do { if(dst_invidx != last_dst_invidx) { stobj_fileidx = find_matching_stobjfile(invidx_file[dst_fileidx].data[dst_invidx]->ie_filename); stobj_filename = stobj_file[stobj_fileidx].name; stobj_fd = stobj_file[stobj_fileidx].fd; last_dst_invidx = dst_invidx; } /* for each child of inv_entry, insert into invidx & stobj files */ tmp_d = d->children[i]->data; read_stobj_info(stobj_file[tmp_d->file_idx].fd, i, &hdr, &ses, &strms, &mfiles); insert_stobj_into_stobjfile(dst_fileidx, stobj_filename, stobj_fd, hdr, ses, strms, mfiles); free(hdr); free(ses); free(strms); free(mfiles); if(--i < 0) break; } while((dst_invidx = find_overlapping_invidx(dst_fileidx, inv_entry)) >= 0); mark_all_children_commited(current); /* Clean up the mess we just created */ /* find node for dst_fileidx */ dst_n = find_invidx_node(list, dst_fileidx); tmp_parent = ((data_t *)(dst_n->data))->parent; while(dst_n != NULL) { node_t *tmp_n1; dst_d = dst_n->data; /* close affected invidx file and stobj files */ for(i = 0; i < dst_d->nbr_children; i++) { close_stobj_file(((data_t *)(dst_d->children[i]->data))->file_idx, BOOL_FALSE); } /* free_all_children on that node */ free_all_children(dst_n); tmp_n1 = find_invidx_node(dst_n->next, dst_fileidx); node_free(list_del(dst_n)); dst_n = tmp_n1; } close_invidx(dst_fileidx); /* generate invidx menu for the parent node */ dst_n = generate_invidx_menu(inventory_path, tmp_parent, 1, dst_idxfile); if(dst_n != tmp_parent) { /* mark all its children commited */ mark_all_children_commited(dst_n); } return 0; } else { /* insert new invidx entry, and copy over stobj file */ if(invidx_file[dst_fileidx].counter->ic_curnum >= invidx_file[dst_fileidx].nEntries) { dest = remmap_invidx(dst_fileidx, 1); } dst_invpos = find_invidx_insert_pos(dst_fileidx, inv_entry); if(dst_invpos >= 0) { memmove(invidx_file[dst_fileidx].data[dst_invpos + 1], invidx_file[dst_fileidx].data[dst_invpos], sizeof(*inv_entry) * (invidx_file[dst_fileidx].counter->ic_curnum - dst_invpos)); } else { dest = invidx_file[dst_fileidx].data[invidx_file[dst_fileidx].counter->ic_curnum - 1] + 1; } /* copy new data to mmap */ memmove(dest, inv_entry, sizeof(*inv_entry)); /* increment counter */ invidx_file[dst_fileidx].counter->ic_curnum++; mark_all_children_commited(current); /* shortcut - just copy stobj file over */ stobjfile = get_inventry_stobjfile(d); if(stobjfile == NULL) { put_error("Error: unable to work out stobj filename"); return 0; } snprintf(dst_stobjfile, sizeof(dst_stobjfile), "%s/%s", inventory_path, basename(stobjfile)); if(stat(dst_stobjfile, &s) < 0) { if(errno != ENOENT) { put_error("Error: unable to copy stobj file: stat error"); return 0; } } else { put_error("Error: unable to copy stobj file: file exists"); return 0; } snprintf(cmd, sizeof(cmd), "cp %s %s", stobjfile, dst_stobjfile); if(system(cmd) != 0) { put_error("Error: unable to copy stobj file: cp failed"); return 0; } open_stobj(dst_stobjfile); return 0; } } else { /* no matching inventory index file - just copy entry to a new file */ invt_counter_t cnt; int new_fd; memset(&cnt, 0, sizeof(cnt)); cnt.ic_maxnum = INVT_MAX_INVINDICES; cnt.ic_curnum = 0; cnt.ic_vernum = INV_VERSION; mark_all_children_commited(current); if(stat(dst_idxfile, &s) < 0) { if(errno != ENOENT) { put_error("Error: unable to stat inventory index file"); return 0; } } else { put_error("Error: unable to copy inventory index file: file exists"); return 0; } new_fd = open(dst_idxfile, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR); if(new_fd < 0) { put_error("Error: unable to open inventory index file"); return 0; } INVLOCK(new_fd, LOCK_EX); cnt.ic_curnum++; write_n_bytes(new_fd, (char *)&cnt, sizeof(cnt), dst_idxfile); write_n_bytes(new_fd, (char *)inv_entry, sizeof(*inv_entry), dst_idxfile); INVLOCK(new_fd, LOCK_UN); close(new_fd); open_invidx(dst_idxfile); /* shortcut - just copy stobj file over */ stobjfile = get_inventry_stobjfile(d); if(stobjfile == NULL) { put_error("Error: unable to work out stobj filename"); return 0; } snprintf(dst_stobjfile, sizeof(dst_stobjfile), "%s/%s", inventory_path, basename(stobjfile)); if(stat(dst_stobjfile, &s) < 0) { if(errno != ENOENT) { put_error("Error: unable to copy stobj file: stat error"); return 0; } } else { put_error("Error: unable to copy stobj file: file exists"); return 0; } snprintf(cmd, sizeof(cmd), "cp %s %s", stobjfile, dst_stobjfile); if(system(cmd) != 0) { put_error("Error: unable to copy stobj file: cp failed"); return 0; } open_stobj(dst_stobjfile); return 0; } } return 0; } int create_stobjfile(int invidx_fileidx, char *filename, int fname_len, invt_seshdr_t *hdr, invt_session_t *ses, invt_stream_t *strms, invt_mediafile_t *mfiles) { int fd; stobj_makefname_len(filename, fname_len); fd = stobj_create(filename); insert_stobj_into_stobjfile(invidx_fileidx, filename, fd, hdr, ses, strms, mfiles); return fd; } int read_stobj_info(int fd, int idx, invt_seshdr_t **out_hdr, invt_session_t **out_ses, invt_stream_t **out_strms, invt_mediafile_t **out_mfiles) { int i; int nmfiles; invt_seshdr_t *hdr; invt_session_t *ses; invt_stream_t *strms; invt_mediafile_t *mfiles; lseek(fd, STOBJ_OFFSET(idx, 0), SEEK_SET); hdr = malloc(sizeof(*hdr)); read_n_bytes(fd, (char *)hdr, sizeof(*hdr), "stobj file"); lseek(fd, hdr->sh_sess_off, SEEK_SET); ses = malloc(sizeof(*ses)); read_n_bytes(fd, (char *)ses, sizeof(*ses), "stobj file"); if(ses->s_cur_nstreams > 0) { lseek(fd, hdr->sh_streams_off, SEEK_SET); strms = malloc(sizeof(*strms) * ses->s_cur_nstreams); read_n_bytes(fd, (char *)strms, sizeof(*strms) * ses->s_cur_nstreams, "stobj file"); nmfiles = 0; for(i = 0; i < ses->s_cur_nstreams; i++) { nmfiles += strms[i].st_nmediafiles; } if(nmfiles > 0) { mfiles = malloc(sizeof(*mfiles) * nmfiles); read_n_bytes(fd, (char *)mfiles, sizeof(*mfiles) * nmfiles, "stobj file"); } else { mfiles = NULL; } } else { strms = NULL; mfiles = NULL; } *out_hdr = hdr; *out_ses = ses; *out_strms = strms; *out_mfiles = mfiles; return fd; } int delete_stobj_entries(int fd, int deletepos) { invt_sescounter_t sescnt; invt_seshdr_t *hdr; invt_session_t *ses; invt_stream_t *strms; invt_mediafile_t *mfiles; lseek(fd, 0, SEEK_SET); read_n_bytes(fd, (char *)&sescnt, sizeof(sescnt), "stobj file"); read_stobj_info(fd, deletepos, &hdr, &ses, &strms, &mfiles); sescnt.ic_eof = hdr->sh_streams_off; free(hdr); free(ses); free(strms); free(mfiles); sescnt.ic_curnum -= deletepos; lseek(fd, 0, SEEK_SET); write_n_bytes(fd, (char *)&sescnt, sizeof(sescnt), "stobj file"); return 0; } int find_stobj_insert_point(int fd, invt_seshdr_t *hdr) { int i; invt_sescounter_t sescnt; invt_seshdr_t tmphdr; lseek(fd, 0, SEEK_SET); read_n_bytes(fd, (char *)&sescnt, sizeof(sescnt), "stobj file"); for(i = 0; i < sescnt.ic_curnum; i++) { read_n_bytes(fd, (char *)&tmphdr, sizeof(tmphdr), "stobj file"); if(hdr->sh_time <= tmphdr.sh_time) { break; } } return i; } int update_invidx_entry(int fd, char *filename, int stobj_fd) { int i; time32_t start_time; time32_t end_time; invt_counter_t cnt; invt_seshdr_t hdr; invt_sescounter_t sescnt; invt_entry_t entry; off_t first_offset; off_t last_offset; /* find the start and stop in stobj file */ lseek(stobj_fd, 0, SEEK_SET); read_n_bytes(stobj_fd, &sescnt, sizeof(sescnt), "stobj file"); memset(&hdr, 0, sizeof(hdr)); first_offset = STOBJ_OFFSET(0,0); lseek(stobj_fd, first_offset, SEEK_SET); read_n_bytes(stobj_fd, &hdr, sizeof(hdr), "stobj file"); start_time = hdr.sh_time; memset(&hdr, 0, sizeof(hdr)); last_offset = STOBJ_OFFSET((sescnt.ic_curnum - 1), 0); lseek(stobj_fd, last_offset, SEEK_SET); read_n_bytes(stobj_fd, &hdr, sizeof(hdr), "stobj file"); end_time = hdr.sh_time; lseek(fd, 0, SEEK_SET); read_n_bytes(fd, &cnt, sizeof(cnt), "invidx file"); for(i = 0; i < cnt.ic_curnum; i++) { lseek(fd, IDX_HDR_OFFSET(i), SEEK_SET); read_n_bytes(fd, &entry, sizeof(entry), "invidx file"); if(strcmp(entry.ie_filename, filename) == 0) { entry.ie_timeperiod.tp_start = start_time; entry.ie_timeperiod.tp_end = end_time; lseek(fd, IDX_HDR_OFFSET(i), SEEK_SET); write_n_bytes(fd, &entry, sizeof(entry), "invidx file"); return i; } } entry.ie_timeperiod.tp_start = start_time; entry.ie_timeperiod.tp_end = end_time; strcpy(entry.ie_filename, filename); lseek(fd, 0, SEEK_END); write_n_bytes(fd, &entry, sizeof(entry), "invidx file"); cnt.ic_curnum++; lseek(fd, 0, SEEK_SET); write_n_bytes(fd, &cnt, sizeof(cnt), "invidx file"); return i; } int insert_stobj_into_stobjfile(int invidx_fileidx, char *filename, int fd, invt_seshdr_t *hdr, invt_session_t *ses, invt_stream_t *strms, invt_mediafile_t *mfiles) { int i; invt_sescounter_t sescnt; int pos; char *buf; int invidx_fd = invidx_file[invidx_fileidx].fd; if(hdr == NULL || ses == NULL || strms == NULL || mfiles == NULL) return 0; lseek(fd, 0, SEEK_SET); read_n_bytes(fd, (char *)&sescnt, sizeof(sescnt), "stobj file"); pos = find_stobj_insert_point(fd, hdr); /* if stobj file is full, we need to split it */ if(sescnt.ic_curnum >= sescnt.ic_maxnum) { int new_fd; char new_filename[INV_STRLEN]; invt_seshdr_t *s_hdr; invt_session_t *s_ses; invt_stream_t *s_strms; invt_mediafile_t *s_mfiles; new_fd = create_stobjfile(invidx_fileidx, new_filename, sizeof(new_filename), hdr, ses, strms, mfiles); for(i = pos; i < sescnt.ic_curnum; i++) { read_stobj_info(fd, i, &s_hdr, &s_ses, &s_strms, &s_mfiles); insert_stobj_into_stobjfile(invidx_fileidx, new_filename, new_fd, s_hdr, s_ses, s_strms, s_mfiles); free(s_hdr); free(s_ses); free(s_strms); free(s_mfiles); } delete_stobj_entries(fd, pos); update_invidx_entry(invidx_fd, new_filename, new_fd); update_invidx_entry(invidx_fd, filename, fd); return 0; } /* stobj file not full, just insert the entry */ hdr->sh_sess_off = STOBJ_OFFSET( sescnt.ic_maxnum, pos); hdr->sh_streams_off = sescnt.ic_eof; /* for seshdr: malloc buffer, copy new entry into buffer, read file entries into buffer, write the lot out */ buf = malloc(((sescnt.ic_curnum - pos) + 1) * sizeof(invt_seshdr_t)); memmove(buf, hdr, sizeof(invt_seshdr_t)); lseek(fd, STOBJ_OFFSET(pos, 0), SEEK_SET); read_n_bytes(fd, buf + sizeof(invt_seshdr_t), (sescnt.ic_curnum - pos) * sizeof(invt_seshdr_t), "stobj file"); lseek(fd, STOBJ_OFFSET(pos, 0), SEEK_SET); write_n_bytes(fd, buf, ((sescnt.ic_curnum - pos) + 1) * sizeof(invt_seshdr_t), "stobj file"); free(buf); /* for session: malloc buffer, copy new entry into buffer, read file entries into buffer, write the lot out */ buf = malloc(((sescnt.ic_curnum - pos) + 1) * sizeof(invt_session_t)); memmove(buf, ses, sizeof(invt_session_t)); lseek(fd, STOBJ_OFFSET(sescnt.ic_maxnum, pos), SEEK_SET); read_n_bytes(fd, buf + sizeof(invt_session_t), (sescnt.ic_curnum - pos) * sizeof(invt_session_t), "stobj file"); lseek(fd, STOBJ_OFFSET(sescnt.ic_maxnum, pos), SEEK_SET); write_n_bytes(fd, buf, ((sescnt.ic_curnum - pos) + 1) * sizeof(invt_session_t), "stobj file"); free(buf); /* write the streams and mediafile info at the end of the stobj file */ stobj_put_streams(fd, hdr, ses, strms, mfiles); /* update counter */ sescnt.ic_curnum++; sescnt.ic_eof = lseek(fd, 0, SEEK_END); lseek(fd, 0, SEEK_SET); write_n_bytes(fd, (char *)&sescnt, sizeof(sescnt), "stobj file"); /* update the inventory index entry */ update_invidx_entry(invidx_fd, filename, fd); return 0; } static void stobj_makefname_len( char *fname, int fname_len ) { /* come up with a new unique name */ uuid_t fn; char str[UUID_STR_LEN + 1]; uuid_generate( fn ); uuid_unparse( fn, str ); snprintf(fname, fname_len, "%s/%s.StObj", inventory_path, str); } int stobj_create( char *fname ) { int fd; invt_sescounter_t sescnt; /* create the new storage object */ if (( fd = open( fname, O_RDWR | O_EXCL | O_CREAT, S_IRUSR|S_IWUSR )) < 0 ) { return -1; } INVLOCK( fd, LOCK_EX ); fchmod( fd, INV_PERMS ); memset(&sescnt, 0, sizeof(sescnt)); sescnt.ic_vernum = INV_VERSION; sescnt.ic_curnum = 0; /* there are no sessions as yet */ sescnt.ic_maxnum = INVT_STOBJ_MAXSESSIONS; sescnt.ic_eof = SC_EOF_INITIAL_POS; lseek(fd, 0, SEEK_SET); write_n_bytes ( fd, (char *)&sescnt, sizeof(sescnt), "new stobj file" ); INVLOCK( fd, LOCK_UN ); return fd; } int stobj_put_streams( int fd, invt_seshdr_t *hdr, invt_session_t *ses, invt_stream_t *strms, invt_mediafile_t *mfiles ) { uint nstm = ses->s_cur_nstreams; off64_t off = hdr->sh_streams_off; off64_t mfileoff= off + (off64_t)( nstm * sizeof( invt_stream_t ) ); uint nmfiles = 0; uint i,j; /* fix the offsets in streams */ for ( i = 0; i < nstm; i++ ) { strms[i].st_firstmfile = mfileoff + (off64_t) ((size_t) nmfiles * sizeof( invt_mediafile_t ) ); /* now fix the offsets in mediafiles */ for ( j = 0; j < strms[i].st_nmediafiles; j++ ) { /* no need to fix the last element's next ptr */ if ( j < strms[i].st_nmediafiles - 1 ) mfiles[ nmfiles + j ].mf_nextmf = strms[i].st_firstmfile + (off64_t) ((j+1) * sizeof( invt_mediafile_t )); /* no need to fix the first element's prev ptr */ if ( j ) mfiles[ nmfiles + j ].mf_prevmf = strms[i].st_firstmfile + (off64_t) ((j-1) * sizeof( invt_mediafile_t )); } /* adjust the offsets of the first and the last elements in the mediafile chain */ mfiles[ nmfiles ].mf_prevmf = 0; nmfiles += strms[i].st_nmediafiles; mfiles[ nmfiles - 1 ].mf_nextmf = 0; } /* first put the streams. hdr already points at the right place */ lseek(fd, off, SEEK_SET); write_n_bytes( fd, strms, nstm * sizeof( invt_stream_t ), "stobj file" ); lseek(fd, mfileoff, SEEK_SET); write_n_bytes( fd, mfiles, nmfiles * sizeof( invt_mediafile_t ), "stobj file" ); return 1; } /*ARGSUSED*/ int invidx_select(WINDOW *win, node_t *current, node_t *list) { data_t *d; if(current == NULL || current->data == NULL) { return 0; } d = (data_t *)(current->data); if(d->expanded == TRUE) { return menu_collapse(win, current, list); } return menu_expand(win, current, list); } /*ARGSUSED*/ int invidx_highlight(WINDOW *win, node_t *current, node_t *list) { static char txt[256]; data_t *d; invt_entry_t *invtentry; if(current == NULL || current->data == NULL) { return 0; } d = (data_t *)(current->data); invtentry = invidx_file[d->file_idx].data[d->data_idx]; wclear(infowin); put_info_header("inventory index entry"); snprintf(txt, sizeof(txt), "path: %s", invtentry->ie_filename); put_info_line(1, txt); snprintf(txt, sizeof(txt), "start: %s", ctime32(&invtentry->ie_timeperiod.tp_start)); txt[strlen(txt) - 1] = '\0'; put_info_line(2, txt); snprintf(txt, sizeof(txt), "end: %s", ctime32(&invtentry->ie_timeperiod.tp_end)); txt[strlen(txt) - 1] = '\0'; put_info_line(3, txt); return FALSE; } /*ARGSUSED*/ int invidx_undelete(WINDOW *win, node_t *current, node_t *list) { node_t *n; data_t *d; if(current == NULL || current->data == NULL) { return BOOL_FALSE; } list_undelete(current, list); d = ((data_t *)(current->data)); n = current->next; while(n != NULL && n->data != NULL && ((data_t *)(n->data))->level > d->level) { ((data_t *)(n->data))->deleted = BOOL_FALSE; ((data_t *)(n->data))->text[0] = ' '; n = n->next; } redraw_screen = BOOL_TRUE; return BOOL_FALSE; } /*ARGSUSED*/ int invidx_prune(char *mountpt, uuid_t *uuidp, time32_t prunetime, node_t *node, node_t *list) { data_t *d; invt_entry_t *invidx_entry; if(node == NULL || node->data == NULL) { return BOOL_FALSE; } d = ((data_t *)(node->data)); invidx_entry = invidx_file[d->file_idx].data[d->data_idx]; if(invidx_entry == NULL) { return BOOL_FALSE; } if(invidx_entry->ie_timeperiod.tp_start < prunetime) { return BOOL_TRUE; } return BOOL_FALSE; } node_t * find_invidx_node(node_t *list, int inv_fileidx) { node_t *n; data_t *d; n = list; while(n != NULL && n->data != NULL) { d = n->data; /* is this an invidx entry we're looking at? */ if(d->ops == &invidx_ops) { if(d->file_idx == inv_fileidx) { return n; } } n = n->next; } return NULL; } char * get_inventry_stobjfile(data_t *d) { data_t *child_data; if(d->nbr_children <= 0) { return NULL; } /* all the children will be from the same stobj file, so we can just get the name for the first */ child_data = d->children[0]->data; return stobj_file[child_data->file_idx].name; } int find_overlapping_invidx(int fidx, invt_entry_t *inv_entry) { int i = 0; invt_entry_t *entry; for(i = 0; i < invidx_file[fidx].numrecords; i++) { entry = invidx_file[fidx].data[i]; if(entry->ie_timeperiod.tp_end < inv_entry->ie_timeperiod.tp_start || entry->ie_timeperiod.tp_start > inv_entry->ie_timeperiod.tp_end) { continue; } return i; } return -1; } int find_invidx_insert_pos(int fidx, invt_entry_t *inv_entry) { int i = 0; invt_entry_t *entry; invt_entry_t *next_entry; for(i = 0; i < invidx_file[fidx].numrecords - 1; i++) { entry = invidx_file[fidx].data[i]; next_entry = invidx_file[fidx].data[i+1]; if(inv_entry->ie_timeperiod.tp_start > entry->ie_timeperiod.tp_end && inv_entry->ie_timeperiod.tp_end < next_entry->ie_timeperiod.tp_start ) { return i; } } return -1; } int find_matching_stobjfile(char *filename) { int i = 0; for(i = 0; i < stobj_numfiles; i++) { if(stobj_file[i].name == NULL) continue; if(strcmp(stobj_file[i].name, filename) == 0) { return i; } } return -1; } int find_matching_invidxfile(char *filename) { int i = 0; for(i = 0; i < invidx_numfiles; i++) { if(invidx_file[i].name == NULL) continue; if(strcmp(invidx_file[i].name, filename) == 0) { return i; } } return -1; } int add_invidx_data(int fidx, invt_entry_t *data) { if(invidx_file[fidx].numrecords == 0) { invidx_file[fidx].data = malloc(sizeof(*invidx_file[fidx].data)); if(invidx_file[fidx].data == NULL) { fprintf(stderr, "%s: internal memory error: invidx data allocation\n", g_programName); exit(1); } } else { invidx_file[fidx].data = realloc(invidx_file[fidx].data, sizeof(*invidx_file[fidx].data) * (invidx_file[fidx].numrecords + 1)); if(invidx_file[fidx].data == NULL) { fprintf(stderr, "%s: internal memory error: invidx data reallocation\n", g_programName); exit(1); } } invidx_file[fidx].data[invidx_file[fidx].numrecords] = data; invidx_file[fidx].numrecords++; return 0; } node_t * generate_invidx_menu(char * inv_path, node_t *startnode, int level, char *idxFileName) { int i; int idx; int len; char *txt; node_t *n; invt_entry_t *invidx_entry; char *stobjname; if((idx = open_invidx(idxFileName)) < 0) { return startnode; } invidx_entry = (invt_entry_t *)( invidx_file[idx].mapaddr + sizeof(invt_counter_t)); n = startnode; for (i=0; i < invidx_file[idx].counter->ic_curnum; i++) { len = strlen(invidx_entry[i].ie_filename) + 54; txt = malloc(len); if(txt == NULL) { fprintf(stderr, "%s: internal memory error: invidx_text\n", g_programName); exit(1); } snprintf(txt, len, " inv file: %s ", basename(invidx_entry[i].ie_filename)); n = list_add(n, node_create(BOOL_TRUE, /* hidden */ BOOL_FALSE, /* expanded */ level, /* level */ BOOL_FALSE, /* deleted */ idx, /* file_idx */ txt, /* text */ &(invidx_ops), /* menu ops */ startnode, /* parent */ NULL, /* children */ 0, /* nbr_children */ i)); /* data_idx */ if(n == NULL) { fprintf(stderr, "%s: internal memory error: list_add: node_create: invidx\n", g_programName); exit(1); } add_invidx_data(idx, &(invidx_entry[i])); stobjname = GetNameOfStobj(inv_path, invidx_entry[i].ie_filename); n = generate_stobj_menu( n, level + 1, stobjname ); free(stobjname); } return n; } int add_invidx(char *name, int fd, int nEntries, char *mapaddr, invt_counter_t *counter) { static int highwatermark = 10; if(invidx_numfiles == 0) { invidx_file = malloc(sizeof(*invidx_file) * highwatermark); if(invidx_file == NULL) { fprintf(stderr, "%s: internal memory error: malloc invidx_file\n", g_programName); exit(1); } } else { if(invidx_numfiles >= highwatermark - 1) { highwatermark += highwatermark; invidx_file = realloc(invidx_file, sizeof(*invidx_file) * highwatermark); if(invidx_file == NULL) { fprintf(stderr, "%s: internal memory error: realloc invidx\n", g_programName); exit(1); } } } invidx_file[invidx_numfiles].nEntries = nEntries; invidx_file[invidx_numfiles].mapaddr = mapaddr; invidx_file[invidx_numfiles].fd = fd; invidx_file[invidx_numfiles].name = name; invidx_file[invidx_numfiles].counter = counter; invidx_file[invidx_numfiles].data = NULL; invidx_file[invidx_numfiles].numrecords = 0; invidx_numfiles++; return invidx_numfiles - 1; } void * remmap_invidx(int fidx, int num) { int i; int nEntries; char *mapaddr; invt_entry_t *inv_entry; nEntries = invidx_file[fidx].counter->ic_curnum; munmap( invidx_file[fidx].mapaddr, (nEntries * sizeof(invt_entry_t)) + sizeof(invt_counter_t)); /* need to lseek on the file to grow it to the right size - no autogrow on linux */ lseek(invidx_file[fidx].fd, (num * sizeof(invt_entry_t)) - 1, SEEK_END); write_n_bytes(invidx_file[fidx].fd, "", 1, invidx_file[fidx].name); mapaddr = mmap_n_bytes(invidx_file[fidx].fd, (nEntries + 1) * (num * sizeof(invt_entry_t)) + sizeof(invt_counter_t), BOOL_FALSE, invidx_file[fidx].name); invidx_file[fidx].nEntries += num; invidx_file[fidx].mapaddr = mapaddr; invidx_file[fidx].counter = (invt_counter_t *)mapaddr; /* regenerate the data index for the file given the new mapping */ inv_entry = (invt_entry_t *)(invidx_file[fidx].mapaddr + sizeof(invt_counter_t)); for(i=0; i < nEntries; i++) { if(i >= invidx_file[fidx].numrecords) { add_invidx_data(fidx, &(inv_entry[i])); } else { invidx_file[fidx].data[i] = &(inv_entry[i]); } } return &(inv_entry[i]); } int open_invidx(char *idxFileName) { int fd; int nEntries; char *mapaddr; char *name; invt_counter_t header; errno=0; fd = open_and_lock( idxFileName, FILE_WRITE, wait_for_locks ); if (fd < 0) { return fd; } name = strdup(idxFileName); if(name == NULL) { fprintf(stderr, "%s: internal memory error: strdup idxFileName\n", g_programName); exit(1); } read_n_bytes( fd, &header, sizeof(invt_counter_t), idxFileName); nEntries = header.ic_curnum; mapaddr = mmap_n_bytes(fd, nEntries*sizeof(invt_entry_t) + sizeof(invt_counter_t), BOOL_FALSE, idxFileName); return add_invidx(name, fd, nEntries, mapaddr, (invt_counter_t *)mapaddr); } int close_invidx(int idx) { int nEntries; if(idx >= invidx_numfiles || invidx_file[idx].fd < 0) return 0; nEntries = invidx_file[idx].counter->ic_curnum; munmap( invidx_file[idx].mapaddr, (invidx_file[idx].nEntries*sizeof(invt_entry_t)) + sizeof(invt_counter_t) ); if(nEntries != 0 && nEntries != invidx_file[idx].nEntries) { ftruncate(invidx_file[idx].fd, sizeof(invt_counter_t) + (nEntries * sizeof(invt_entry_t)) ); } close( invidx_file[idx].fd ); if(nEntries == 0) { unlink(invidx_file[idx].name); } free( invidx_file[idx].name ); free( invidx_file[idx].data ); invidx_file[idx].fd = -1; invidx_file[idx].name = NULL; invidx_file[idx].data = NULL; return 0; } int close_all_invidx() { int i; for(i = 0; i < invidx_numfiles; i++) { if(invidx_file[i].fd < 0) continue; close_invidx(i); } free(invidx_file); invidx_file = NULL; return 0; } xfsdump-3.1.6+nmu1/invutil/menu.c0000644000000000000000000001465512620476160013572 0ustar /* * Copyright (c) 2002 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include "types.h" #include "cmenu.h" #include "list.h" #include "invutil.h" int put_all_options(WINDOW *win, node_t *list, node_t *current) { int i; int attr; data_t *d; node_t *node; i = 0; node = list; while(node != NULL) { d = ((data_t *)(node->data)); if(d->hidden == BOOL_TRUE) { node = node->next; continue; } if(node == current) { attr = A_REVERSE; } else { attr = 0; } put_option(win, i, d->text, attr); node = node->next; i++; } return 0; } void put_helpscreen(int keyc, menukey_t *keyv) { int k; int l; int winline; WINDOW *helpscreen; winline = LINES - (keyc + 5); if(winline < 0) winline = 0; helpscreen = newwin(keyc + 4, 29, winline, COLS - 30); keypad(helpscreen, TRUE); wattron(helpscreen, A_REVERSE); wmove(helpscreen, 0, 0); waddstr(helpscreen, " --------------------------- "); wmove(helpscreen, 1, 0); waddstr(helpscreen, "| Menu Help |"); wmove(helpscreen, 2, 0); waddstr(helpscreen, "| |"); l = 3; for(k = 0; k < keyc + 1; k++) { if(keyv[k].text == NULL) continue; wmove(helpscreen, l, 0); waddstr(helpscreen, keyv[k].text); l++; } wmove(helpscreen, l, 0); waddstr(helpscreen, " --------------------------- "); wrefresh(helpscreen); wattroff(helpscreen, A_REVERSE); hitanykey(); wclear(helpscreen); wrefresh(helpscreen); delwin(helpscreen); } int menu(WINDOW *win, int line, int col, node_t *list, int keyc, menukey_t *keyv) { int c; int k; int quit; char txt[256]; node_t *current; node_t *last; data_t *d; int current_line; int last_line; int size; current = list; last = current; current_line = 0; last_line = current_line; redraw_screen = BOOL_TRUE; quit = BOOL_FALSE; while(quit != BOOL_TRUE) { if(current == NULL && current->data == NULL) { current = list; } d = (data_t *)(current->data); if(redraw_screen == BOOL_TRUE) { wclear(win); snprintf(txt, sizeof(txt), "%s: %s", g_programName, g_programVersion); put_header(txt, ALIGN_LEFT); if(d->hidden == BOOL_TRUE) { current = list; current_line = 0; d = (data_t *)(current->data); } put_all_options(win, list, current); redraw_screen = BOOL_FALSE; if(d->ops != NULL && d->ops->op_highlight != NULL) { quit = d->ops->op_highlight(win, current, list); } } else if (last != current || redraw_options) { put_option(win, last_line, ((data_t *)(last->data))->text, 0); put_option(win, current_line, d->text, A_REVERSE); redraw_options = BOOL_FALSE; if(((data_t *)(last->data))->ops != NULL && ((data_t *)(last->data))->ops->op_unhighlight != NULL) { quit = ((data_t *)(last->data))->ops->op_unhighlight(win, current, list); } if(d->ops != NULL && d->ops->op_highlight != NULL) { quit = d->ops->op_highlight(win, current, list); } } last = current; last_line = current_line; wrefresh(stdscr); wrefresh(infowin); size = (LINES - 2) - INFO_SIZE; prefresh(win, current_line - (size - 1), 0, line, col, size, COLS - 1); if(quit == BOOL_TRUE) continue; c=wgetch(win); switch(c) { case '?': case KEY_F(1): /* online help */ put_helpscreen(keyc, keyv); redraw_screen = BOOL_TRUE; break; case KEY_UP: case 'k': /* go to previous option */ { data_t *d; node_t *n = current->prev; while(n != NULL) { d = ((data_t *)(n->data)); if(d == NULL) { n = n->prev; continue; } if(d->hidden == BOOL_FALSE) { break; } n = n->prev; } if(n != NULL) { current = n; current_line--; } } break; case KEY_DOWN: case 'j': /* go to next option */ { data_t *d; node_t *n = current->next; while(n != NULL) { d = ((data_t *)(n->data)); if(d == NULL) { n = n->next; continue; } if(d->hidden == BOOL_FALSE) { break; } n = n->next; } if(n != NULL) { current = n; current_line++; } } break; case KEY_RIGHT: case 'l': /* go to next child */ { node_t *n = current->next; int l; if(current != NULL && ((data_t *)(current->data)) == NULL) { break; } l = ((data_t *)(current->data))->level; if(n != NULL && ((data_t *)(n->data)) != NULL && ((data_t *)(n->data))->level > l) { if(((data_t *)(n->data))->hidden == BOOL_TRUE) { menu_expand(win, current, list); } current = n; current_line++; } } break; case KEY_LEFT: case 'h': /* go to parent */ { data_t *d; node_t *n = current->prev; int l = 0; int i; if(current != NULL && ((data_t *)(current->data)) != NULL) { l = ((data_t *)(current->data))->level; } i = current_line - 1; while(n != NULL) { d = ((data_t *)(n->data)); if(d == NULL) { n = n->prev; continue; } if(d->hidden == BOOL_TRUE) { n = n->prev; continue; } if(d->level < l) { break; } n = n->prev; i--; } if(n != NULL) { current = n; current_line = i;; } } break; case ERR: if(errno == EINTR) { /* mainmenu window has been recreated - use new one */ win = mainmenu; } break; default: for(k = 0; k < keyc; k++) { if(c == keyv[k].key || tolower(c) == keyv[k].key) { if (keyv[k].fn != NULL) { quit = keyv[k].fn(win, current, list); break; } else { put_footer("internal error: can't execute function", ALIGN_CENTRE); break; } } } break; } } return 0; } xfsdump-3.1.6+nmu1/invutil/invutil.h0000644000000000000000000000407612607344125014321 0ustar /* * Copyright (c) 2002 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef INVUTIL_H #define INVUTIL_H #define STR_LEN INV_STRLEN+32 #define GEN_STRLEN 32 /* open_and_lock() return codes */ #define SYSCALL_FAILED (-1) #define LOCK_BUSY (-2) typedef enum { FILE_READ, FILE_WRITE, FILE_UNSAFE, DIRECTORY_READ, DIRECTORY_WRITE, DIRECTORY_UNSAFE } Open_t; extern char * g_programName; extern char * g_programVersion; extern char * inventory_path; extern bool_t debug; extern bool_t force; extern bool_t wait_for_locks; char * GetFstabFullPath(char *); char * GetNameOfInvIndex (char *, uuid_t); char * GetNameOfStobj (char *inv_path, char *filename); void CheckAndPruneFstab( char *, bool_t, char *, uuid_t *, uuid_t *, time32_t, char *); int CheckAndPruneInvIndexFile( bool_t, char *, uuid_t *, time32_t, char *); int CheckAndPruneStObjFile( bool_t, char *, uuid_t *, time32_t, char *); int uses_specified_mf_label( invt_seshdr_t *, invt_session_t *, char *, char *); time32_t ParseDate(char *); void usage (void); int open_and_lock(char *, Open_t, uint); void read_n_bytes(int, void *, size_t, char *); void write_n_bytes(int, void *, size_t, char *); void * mmap_n_bytes(int, size_t, bool_t, char *); void ListFstab(void); int ListInvIndexFile( char *); int ListStObjFile(char *); int invutil_interactive(char *, char *, uuid_t *, time32_t timeSecs); int mntpnt_equal(char *s1, char *s2); #endif /* INVUTIL_H */ xfsdump-3.1.6+nmu1/invutil/stobj.h0000644000000000000000000000342712607344125013747 0ustar /* * Copyright (c) 2002 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef STOBJ_H #define STOBJ_H #include "types.h" #include "mlog.h" #include "inv_priv.h" #include "list.h" #include "cmenu.h" node_t *generate_stobj_menu(node_t *startnode, int level, char *StObjFileName); int open_stobj(char *StObjFileName); int close_stobj_file(int fidx, int unlink_ok); int close_all_stobj(void); int stobjsess_highlight(WINDOW *win, node_t *current, node_t *list); int stobjstrm_highlight(WINDOW *win, node_t *current, node_t *list); int stobjmed_highlight(WINDOW *win, node_t *current, node_t *list); int stobj_select(WINDOW *win, node_t *current, node_t *list); int stobjsess_commit(WINDOW *win, node_t *current, node_t *list); int stobj_prune(char *mountpt, uuid_t *uuidp, time32_t prunetime, node_t *node, node_t *list); int stobj_undelete(WINDOW *win, node_t *current, node_t *list); int stobjmed_commit(WINDOW *win, node_t *current, node_t *list); int stobjstrm_commit(WINDOW *win, node_t *current, node_t *list); int stobjstrm_delete(WINDOW *win, node_t *current, node_t *list); int stobjmed_delete(WINDOW *win, node_t *current, node_t *list); #endif /* STOBJ_H */ xfsdump-3.1.6+nmu1/invutil/Makefile0000644000000000000000000000241712607344125014113 0ustar # # Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = .. include $(TOPDIR)/include/builddefs COMMINCL = \ global.h \ mlog.h \ timeutil.h \ types.h INVINCL = \ inventory.h \ inv_priv.h INVCOMMON = \ inv_files.c COMMON = \ timeutil.c CURSESCOMMON = \ cmenu.c \ fstab.c \ invidx.c \ list.c \ menu.c \ screen.c \ stobj.c CURSESINCL = \ cmenu.h \ fstab.h \ getopt.h \ invidx.h \ invutil.h \ list.h \ stobj.h LOCALS = invutil.c LTCOMMAND = xfsinvutil CFILES = $(LOCALS) LCFILES = $(COMMON) $(INVCOMMON) LHFILES = $(COMMINCL) $(INVINCL) LINKS = $(COMMINCL) $(COMMON) $(INVINCL) $(INVCOMMON) LDIRT = $(LINKS) LLDLIBS = $(LIBUUID) $(LIBCURSES) LCFLAGS = -DDUMP ifeq ($(ENABLE_CURSES), yes) CFILES += $(CURSESCOMMON) HFILES += $(CURSESINCL) LCFLAGS += -DHAVE_CURSES else LSRCFILES += $(CURSESCOMMON) $(CURSESINCL) endif default: depend $(LTCOMMAND) include $(BUILDRULES) install: default $(INSTALL) -m 755 -d $(PKG_SBIN_DIR) $(LTINSTALL) -m 755 $(LTCOMMAND) $(PKG_SBIN_DIR) install-dev: .dep: $(COMMINCL) $(COMMON) $(INVINCL) $(INVCOMMON) $(COMMINCL) $(COMMON): @echo " [LN] $@" $(Q)$(RM) $@; $(LN_S) ../common/$@ $@ $(INVINCL) $(INVCOMMON): @echo " [LN] $@" $(Q)$(RM) $@; $(LN_S) ../inventory/$@ $@ -include .dep xfsdump-3.1.6+nmu1/invutil/invutil.c0000644000000000000000000007216712620476160014322 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include "types.h" #include "mlog.h" #include "inv_priv.h" #include "getopt.h" #include "timeutil.h" #include "invutil.h" char *g_programName; char *g_programVersion; char *inventory_path; bool_t debug = BOOL_FALSE; bool_t force = BOOL_FALSE; bool_t wait_for_locks = BOOL_FALSE; bool_t resize_screen = BOOL_FALSE; bool_t redraw_screen = BOOL_FALSE; bool_t redraw_options = BOOL_FALSE; #ifndef HAVE_CURSES int invutil_interactive(char *path, char *mountpt, uuid_t *uuidp, time32_t timeSecs) { fprintf(stderr, "%s: libcurses support not compiled in, " "interactive mode is unavailable.\n", g_programName); exit(1); } #endif int main(int argc, char *argv[]) { int c = 0; bool_t check_option = BOOL_FALSE; bool_t mntpnt_option = BOOL_FALSE; bool_t uuid_option = BOOL_FALSE; bool_t interactive_option = BOOL_FALSE; bool_t session_option = BOOL_FALSE; static char version[32]; char *mntPoint = NULL; char *r_mf_label = NULL; uuid_t uuid; uuid_t session; snprintf(version, sizeof(version), "version %s", VERSION); g_programName = basename(argv[0]); g_programVersion = version; uuid_clear(uuid); uuid_clear(session); while((c = getopt( argc, argv, GETOPT_CMDSTRING)) != EOF) { switch(c) { case GETOPT_DEBUG: debug = BOOL_TRUE; break; case GETOPT_INTERACTIVE: if (force) { fprintf( stderr, "%s: may not specify both -%c and -%c\n", g_programName, GETOPT_FORCE, c ); usage(); } if (session_option) { fprintf( stderr, "%s: may not specify both -%c and -%c\n", g_programName, GETOPT_PRUNESESSION, c ); usage(); } interactive_option = BOOL_TRUE; break; case GETOPT_NONINTERACTIVE: /* obsoleted by -F */ if (interactive_option) { fprintf( stderr, "%s: may not specify both -%c and -%c\n", g_programName, GETOPT_INTERACTIVE, c ); usage(); } force = BOOL_TRUE; break; case GETOPT_UUID: if (check_option) { fprintf( stderr, "%s: may not specify both -%c and -%c\n", g_programName, GETOPT_CHECKPRUNEFSTAB, c ); usage(); } if (mntpnt_option || session_option) { fprintf( stderr, "%s: may not specify both -%c and -%c\n", g_programName, mntpnt_option ? GETOPT_PRUNEMNT : GETOPT_PRUNESESSION, c ); usage(); } uuid_option = BOOL_TRUE; uuid_parse(optarg, uuid); break; case GETOPT_WAITFORLOCKS: wait_for_locks = BOOL_TRUE; break; case GETOPT_CHECKPRUNEFSTAB: if (mntpnt_option) { fprintf( stderr, "%s: may not specify both -%c and -%c\n", g_programName, GETOPT_PRUNEMNT, c ); usage(); } if (uuid_option) { fprintf( stderr, "%s: may not specify both -%c and -%c\n", g_programName, GETOPT_UUID, c ); usage(); } if (session_option) { fprintf( stderr, "%s: may not specify both -%c and -%c\n", g_programName, GETOPT_PRUNESESSION, c ); usage(); } check_option = BOOL_TRUE; break; case GETOPT_FORCE: if (interactive_option) { fprintf( stderr, "%s: may not specify both -%c and -%c\n", g_programName, GETOPT_INTERACTIVE, c ); usage(); } force = BOOL_TRUE; break; case GETOPT_PRUNEMNT: if (check_option) { fprintf( stderr, "%s: may not specify both -%c and -%c\n", g_programName, GETOPT_CHECKPRUNEFSTAB, c ); usage(); } if (uuid_option || session_option) { fprintf( stderr, "%s: may not specify both -%c and -%c\n", g_programName, uuid_option ? GETOPT_UUID : GETOPT_PRUNESESSION, c ); usage(); } mntpnt_option = BOOL_TRUE; mntPoint = optarg; break; case GETOPT_PRUNEMEDIALABEL: r_mf_label = optarg; break; case GETOPT_PRUNESESSION: if (check_option) { fprintf( stderr, "%s: may not specify both -%c and -%c\n", g_programName, GETOPT_CHECKPRUNEFSTAB, c ); usage(); } if (interactive_option) { fprintf( stderr, "%s: may not specify both -%c and -%c\n", g_programName, GETOPT_INTERACTIVE, c ); usage(); } if (mntpnt_option || uuid_option) { fprintf( stderr, "%s: may not specify both -%c and -%c\n", g_programName, mntpnt_option ? GETOPT_PRUNEMNT : GETOPT_UUID, c ); usage(); } session_option = BOOL_TRUE; uuid_parse(optarg, session); break; default: usage(); break; } } if (r_mf_label != NULL && !(mntpnt_option || uuid_option)) { fprintf( stderr, "%s: -%c requires either -%c or -%c\n", g_programName, GETOPT_PRUNEMEDIALABEL, GETOPT_PRUNEMNT, GETOPT_UUID ); usage(); } /* date string only passed for -u and -M */ if (uuid_option || mntpnt_option) { if (optind != (argc - 1)) { fprintf(stderr, "%s: Date missing for -%c option\n", g_programName, uuid_option ? GETOPT_UUID : GETOPT_PRUNEMNT); usage(); } } else { if (optind != argc) { fprintf(stderr, "%s: Extra arguments specified\n", g_programName); usage(); } } /* sanity check the inventory database directory, setup global paths */ if (!inv_setup_base()) { fprintf( stderr, "%s: both /var/lib/xfsdump and /var/xfsdump exist - fatal\n", g_programName ); exit(1); } inventory_path = INV_DIRPATH; if (check_option) { char *tempstr = "test"; time32_t temptime = 0; CheckAndPruneFstab(inventory_path, BOOL_TRUE, tempstr, &uuid, &session, temptime, NULL); } else if (session_option) { CheckAndPruneFstab( inventory_path, BOOL_FALSE , mntPoint, &uuid, &session, (time32_t)0, r_mf_label); } else if (uuid_option || mntpnt_option) { time32_t timeSecs = ParseDate(argv[optind]); if (interactive_option) { invutil_interactive(inventory_path, mntPoint, &uuid, timeSecs); printf("\n"); } else { CheckAndPruneFstab( inventory_path, BOOL_FALSE , mntPoint, &uuid, &session, timeSecs, r_mf_label); } } else if ( interactive_option ) { invutil_interactive(inventory_path, mntPoint, &uuid, 0); printf("\n"); } else { usage(); } return 0; } /* get_mntpnt & mntpnt_equal are used to allow matching of mountpoints if * no hostname is supplied */ static char * get_mntpnt(char *txt) { char *p; p = strchr(txt, ':'); if(p == NULL) return txt; return p+1; } int mntpnt_equal(char *s1, char *s2) { if(strchr(s1, ':') == NULL || strchr(s2, ':') == NULL) { s1 = get_mntpnt(s1); s2 = get_mntpnt(s2); } return STREQL(s1, s2); } time32_t ParseDate(char *strDate) { struct tm tm; time_t date = 0; time32_t date32; char **fmt; char *templateStr[] = { "%m/%d/%Y %I:%M:%S %p", "%m/%d/%Y %H:%M:%S", "%m/%d/%Y %I:%M %p", "%m/%d/%Y %H:%M", "%m/%d/%Y %I %p", "%m/%d/%Y %H", "%m/%d/%Y", "%m/%d/%y %I:%M:%S %p", "%m/%d/%y %H:%M:%S", "%m/%d/%y %I:%M %p", "%m/%d/%y %H:%M", "%m/%d/%y %I %p", "%m/%d/%y %H", "%m/%d/%y", "%m/%d", "%b %d, %Y %H:%M:%S %p", "%b %d, %Y %I:%M:%S", "%B %d, %Y %H:%M:%S %p", "%B %d, %Y %I:%M:%S", "%b %d, %Y %H:%M %p", "%b %d, %Y %I:%M", "%B %d, %Y %H:%M %p", "%B %d, %Y %I:%M", "%b %d, %Y %H %p", "%b %d, %Y %I", "%B %d, %Y %H %p", "%B %d, %Y %I", "%b %d, %Y", "%B %d, %Y", "%b %d", "%B %d", "%m%d%H", "%m%d", 0}; for (fmt = &templateStr[0]; *fmt != NULL; fmt++) { memset (&tm, 0, sizeof (struct tm)); /* ensure fields init'ed */ if (strptime(strDate, *fmt, &tm) != NULL) break; } #ifdef INV_DEBUG printf("INV_DEBUG: the date entered is %s\n", strDate); printf("INV_DEBUG: the hour parsed from string is %d\n", tm.tm_hour); #endif if (*fmt == NULL || (date = mktime(&tm)) < 0) { fprintf(stderr, "%s: bad date, \"%s\"\n", g_programName, strDate ); usage(); } /* HACK to ensure tm_isdst is set BEFORE calling mktime(3) */ if (tm.tm_isdst) { int dst = tm.tm_isdst; memset (&tm, 0, sizeof (struct tm)); tm.tm_isdst = dst; (void)strptime(strDate, *fmt, &tm); tm.tm_isdst = dst; date = mktime(&tm); } /* xfsdump inventory uses time32_t for portability. * make sure the given date did not overflow... */ date32 = date; if (date32 != date) { fprintf(stderr, "%s: date out of range: \"%s\"\n", g_programName, strDate); usage(); } #ifdef INV_DEBUG printf("INV_DEBUG: the date entered is %s\n", strDate); printf("INV_DEBUG: the hour parsed from string is %d\n", tm.tm_hour); printf("INV_DEBUG: the date entered in secs is %d\n", date32); #endif /* INV_DEBUG */ return date32; } char * GetNameOfStobj (char *inv_path, char *filename) { char *str; char *name; str = basename(filename); name = (char *) malloc( strlen( inv_path ) + 1 + strlen( str ) + 1); strcpy( name, inv_path ); strcat( name, "/" ); strcat( name, str ); return(name); } char * GetNameOfInvIndex (char *inv_path, uuid_t uuid) { char str[UUID_STR_LEN + 1]; char *name; uuid_unparse( uuid, str ); name = (char *) malloc( strlen( inv_path ) + 1 + strlen( str ) + strlen( INV_INVINDEX_PREFIX ) + 1); strcpy( name, inv_path ); strcat( name, "/" ); strcat( name, str ); strcat( name, INV_INVINDEX_PREFIX ); return(name); } char * GetFstabFullPath(char *inv_path) { char *fstabname; fstabname = (char *) malloc( strlen(inv_path) + 1 /* one for the "/" */ + strlen("fstab") + 1 ); strcpy( fstabname, inv_path ); strcat( fstabname, "/" ); strcat( fstabname, "fstab" ); return(fstabname); } void CheckAndPruneFstab(char *inv_path, bool_t checkonly, char *mountPt, uuid_t *uuidp, uuid_t *sessionp, time32_t prunetime, char *r_mf_label) { char *fstabname; char *mapaddr; char *invname; int fstabEntries; int nEntries; int fd; int i; int j; bool_t removeflag; invt_fstab_t *fstabentry; invt_counter_t *counter,cnt; if (mountPt == NULL && uuid_is_null(*uuidp) && uuid_is_null(*sessionp)) { fprintf( stderr, "%s: mountpoint, uuid or session " "must be specified\n", g_programName ); fprintf( stderr, "%s: abnormal termination\n", g_programName ); exit(1); } fstabname = GetFstabFullPath(inv_path); fd = open_and_lock( fstabname, FILE_WRITE, wait_for_locks ); if (fd < 0) { fprintf( stderr, "%s: abnormal termination\n", g_programName ); exit(1); } read_n_bytes(fd, &cnt, sizeof(invt_counter_t), fstabname); nEntries = cnt.ic_curnum; mapaddr = mmap_n_bytes(fd, nEntries*sizeof(invt_fstab_t) + sizeof(invt_counter_t), BOOL_FALSE, fstabname); counter = (invt_counter_t *)mapaddr; fstabentry = (invt_fstab_t *)(mapaddr + sizeof(invt_counter_t)); printf("Processing file %s\n", fstabname); /* check each entry in fstab for mount pt or uuid match */ for (i = 0; i < counter->ic_curnum; ) { removeflag = BOOL_FALSE; printf(" Found entry for %s\n" , fstabentry[i].ft_mountpt); for (j = i +1 ; j < counter->ic_curnum ; j++ ) { if (uuid_compare(fstabentry[i].ft_uuid, fstabentry[j].ft_uuid) == 0) { printf(" duplicate fstab entry\n"); removeflag = BOOL_TRUE; break; } } if (!removeflag) { bool_t IdxCheckOnly = BOOL_TRUE; invname = GetNameOfInvIndex(inv_path, fstabentry[i].ft_uuid); #ifdef INV_DEBUG printf("INV_DEBUG: ft_mountpt = %s, mountPt = %s, r_mf_label = %s\n", fstabentry[i].ft_mountpt, mountPt, (r_mf_label ? r_mf_label : "(NULL)")); #endif if ( checkonly == BOOL_FALSE ) { if(mountPt != NULL && strcmp(mountPt, fstabentry[i].ft_mountpt) == 0) { printf(" Match on hostname and path\n"); IdxCheckOnly = BOOL_FALSE; } else if((!uuid_is_null(*uuidp)) && (uuid_compare(*uuidp, fstabentry[i].ft_uuid) == 0)) { printf(" Match on UUID only\n"); IdxCheckOnly = BOOL_FALSE; } else if(mountPt != NULL && mntpnt_equal(mountPt, fstabentry[i].ft_mountpt)) { printf(" Match on directory name only: %s\n", mountPt); IdxCheckOnly = BOOL_FALSE; } else if (!uuid_is_null(*sessionp)) { // no session id to match against yet, defer deciding if this is // a check-only run until we have a session IdxCheckOnly = BOOL_FALSE; } } if (CheckAndPruneInvIndexFile( IdxCheckOnly, invname, sessionp, prunetime, r_mf_label) == -1 ) { removeflag = BOOL_TRUE; } free( invname ); } if (removeflag == BOOL_TRUE) { printf(" removing fstab entry %s\n", fstabentry[i].ft_mountpt); if ( counter->ic_curnum > 1 ) { bcopy((void *)&fstabentry[i + 1], (void *)&fstabentry[i], (sizeof(invt_fstab_t) * (counter->ic_curnum - i - 1))); } counter->ic_curnum--; } else i++; /* next entry if this entry not removed */ } fstabEntries = counter->ic_curnum; munmap( mapaddr, (nEntries*sizeof(invt_fstab_t)) + sizeof(invt_counter_t)); if ((fstabEntries != 0) && (fstabEntries != nEntries)) { if(debug) { printf("ftruncate fstab from %d to %d (%ld bytes)\n", nEntries, fstabEntries, (long) sizeof(invt_counter_t) + (sizeof(invt_fstab_t) * fstabEntries)); printf("ftruncate %s\n", fstabname); } ftruncate(fd, sizeof(invt_counter_t) + (sizeof(invt_fstab_t) * fstabEntries)); } close(fd); if (fstabEntries == 0) { if(debug) { printf("unlink fstab file %s\n", fstabname); } unlink( fstabname ); } free( fstabname ); } int CheckAndPruneInvIndexFile( bool_t checkonly, char *idxFileName, uuid_t *sessionp, time32_t prunetime, char *r_mf_label) { char *temp; int fd; int i; int validEntries; int nEntries; bool_t removeflag; invt_entry_t *invIndexEntry; invt_counter_t *counter; invt_counter_t header; printf(" processing index file \n" " %s\n",idxFileName); fd = open_and_lock( idxFileName, FILE_WRITE, wait_for_locks ); if (fd < 0) { return -1; } read_n_bytes( fd, &header, sizeof(invt_counter_t), idxFileName); nEntries = header.ic_curnum; temp = mmap_n_bytes(fd, nEntries*sizeof(invt_entry_t) + sizeof(invt_counter_t), BOOL_FALSE, idxFileName); counter = (invt_counter_t *)temp; invIndexEntry = (invt_entry_t *)( temp + sizeof(invt_counter_t)); for (i=0; i < counter->ic_curnum; ) { removeflag = BOOL_FALSE; printf(" Checking access for\n" " %s\n", invIndexEntry[i].ie_filename); if (debug) { printf(" Time:\tbegin %s", ctime32(&(invIndexEntry[i].ie_timeperiod.tp_start))); printf("\t\tend %s", ctime32(&(invIndexEntry[i].ie_timeperiod.tp_end))); } if (( access( invIndexEntry[i].ie_filename, R_OK | W_OK ) == -1) && (errno == ENOENT)) { printf(" Unable to access %s referred in %s\n", invIndexEntry[i].ie_filename, idxFileName); printf(" removing index entry \n"); removeflag = BOOL_TRUE; } if (CheckAndPruneStObjFile(checkonly, invIndexEntry[i].ie_filename, sessionp, prunetime, r_mf_label) == -1) { removeflag = BOOL_TRUE; /* The StObj is gone */ } if (removeflag == BOOL_TRUE) { if ( counter->ic_curnum > 1 ) { bcopy((void *)&invIndexEntry[i + 1], (void *)&invIndexEntry[i], (sizeof(invt_entry_t) * (counter->ic_curnum - i - 1))); } counter->ic_curnum--; } else i++; /* next entry if this entry not removed */ } validEntries = counter->ic_curnum; munmap( temp, (nEntries*sizeof(invt_entry_t)) + sizeof(invt_counter_t) ); if ((validEntries != 0) && (validEntries != nEntries)) { if(debug) { printf("ftruncate idx from %d to %d (%ld bytes)\n", nEntries, validEntries, (long) sizeof(invt_counter_t) + (validEntries * sizeof(invt_entry_t)) ); printf("- truncate %s\n", idxFileName); } ftruncate( fd, sizeof(invt_counter_t) + (validEntries * sizeof(invt_entry_t)) ); } if (debug) { printf(" pruned %d entries from this index file, %d remaining\n", (nEntries - validEntries), validEntries); } close( fd ); if (validEntries == 0) { if(debug) { printf("unlink idx file %s\n", idxFileName); } unlink( idxFileName ); return(-1); } return(0); } int CheckAndPruneStObjFile( bool_t checkonly, char *StObjFileName, uuid_t *sessionp, time32_t prunetime, char *r_mf_label) { char response[GEN_STRLEN]; char *temp; int fd; int i; int validEntries; bool_t removeflag; int prunedcount = 0; int removedcount = 0; bool_t session_match; struct stat sb; char str[UUID_STR_LEN + 1]; int sescount; invt_seshdr_t *StObjhdr; invt_session_t *StObjses; invt_sescounter_t *counter; invt_sescounter_t header; fd = open_and_lock( StObjFileName, FILE_WRITE, wait_for_locks ); if (fd < 0) { return -1; } read_n_bytes(fd, &header, sizeof(invt_sescounter_t), StObjFileName); if (fstat(fd, &sb) < 0) { fprintf(stderr, "Could not get stat info on %s\n", StObjFileName); perror("fstat"); exit(1); } temp = mmap_n_bytes(fd, sb.st_size, BOOL_FALSE, StObjFileName); counter = (invt_sescounter_t *)temp; StObjhdr = (invt_seshdr_t *)( temp + sizeof(invt_sescounter_t)); StObjses = (invt_session_t *)(temp + StObjhdr->sh_sess_off); sescount = 0; for (i=0; i < counter->ic_curnum; ) { removeflag = BOOL_FALSE; if (StObjhdr->sh_pruned) prunedcount++; if (! StObjhdr->sh_pruned) { printf(" Session %d: %s %s", sescount++, StObjses->s_mountpt, ctime32(&StObjhdr->sh_time)); } if (debug) { /* Note that the DMF people use some of this debug * output for their interface to the inventory. * They care about the following fields: * media label: * interrupted: * session label: * level: * Do not change these fields w/out talking to * them first. */ int i; int j; invt_stream_t *StObjstrm; invt_mediafile_t *StObjmed; if (StObjhdr->sh_pruned) printf(" Pruned Session: %s %s", StObjses->s_mountpt, ctime32(&StObjhdr->sh_time)); printf("\t\tdevice:\t\t%s\n", StObjses->s_devpath); printf("\t\tsession label:\t\"%s\"\n", StObjses->s_label); uuid_unparse( StObjses->s_sesid, str ); printf("\t\tsession id:\t%s\n", str); printf("\t\tlevel:\t\t%d\n", StObjhdr->sh_level); printf("\t\tstreams:\t%d\n", StObjses->s_cur_nstreams ); for ( i = 0; i < (int) StObjses->s_cur_nstreams; i++ ) { printf( "\t\tstream %d:\n", i); StObjstrm = (invt_stream_t *)(temp + StObjhdr->sh_streams_off + (i * sizeof(invt_stream_t))); printf( "\t\t\tpathname:\t%s\n", StObjstrm->st_cmdarg); printf( "\t\t\tinode start:\t%llu\n", (unsigned long long) StObjstrm->st_startino.ino); printf( "\t\t\tinode end:\t%llu\n", (unsigned long long) StObjstrm->st_endino.ino); printf( "\t\t\tinterrupted:\t%s\n", StObjstrm->st_interrupted ? "YES" : "NO" ); printf( "\t\t\tmedia files:\t%d\n", StObjstrm->st_nmediafiles); for ( j = 0; j < StObjstrm->st_nmediafiles; j++) { StObjmed = (invt_mediafile_t *)(temp + StObjstrm->st_firstmfile + (j * sizeof(invt_mediafile_t))); printf( "\t\t\tmfile file %d:\n", j); printf( "\t\t\t\tmfile size:\t%lld\n", (long long) StObjmed->mf_size); printf( "\t\t\t\tmfile start:\t%llu\n", (unsigned long long) StObjmed->mf_startino.ino); printf( "\t\t\t\tmfile end:\t%llu\n", (unsigned long long) StObjmed->mf_endino.ino); printf( "\t\t\t\tmedia label:\t\"%s\"\n", StObjmed->mf_label); } } } #ifdef INV_DEBUG printf("INV_DEBUG: sh_time = %d, prunetime = %d\n", StObjhdr->sh_time, prunetime); printf("INV_DEBUG: checkonly = %d, sh_pruned = %d\n", checkonly, StObjhdr->sh_pruned); #endif session_match = !uuid_compare(*sessionp, StObjses->s_sesid); if (session_match) { printf("\t\tMatch on session id\n"); } if ((checkonly == BOOL_FALSE) && (! StObjhdr->sh_pruned) && ((StObjhdr->sh_time < prunetime) || session_match) && (uses_specified_mf_label(StObjhdr, StObjses, temp, r_mf_label))){ bool_t GotResponse = BOOL_FALSE; uuid_unparse( StObjses->s_sesid, str ); if(force) { printf("-------------------------------------------------\n"); printf("Pruning this matching entry:\n"); printf( "UUID\t\t:\t%s\nMOUNT POINT\t:\t%s\n" "DEV PATH\t:\t%s\n" "LABEL\t\t:\t%s\n" "TIME OF DUMP\t:\t%s", str, StObjses->s_mountpt, StObjses->s_devpath, StObjses->s_label, ctime32(&StObjhdr->sh_time)); removeflag = BOOL_TRUE; } else { printf("-------------------------------------------------\n"); printf("An entry matching the mount point/time is :\n"); printf("UUID\t\t:\t%s\nMOUNT POINT\t:\t%s\n" "DEV PATH\t:\t%s\nTIME OF DUMP\t:\t%s", str, StObjses->s_mountpt, StObjses->s_devpath, ctime32(&StObjhdr->sh_time)); while ( GotResponse == BOOL_FALSE ) { char *chp; printf("\nDo you want to prune this entry: [y/n] "); fgets( response, GEN_STRLEN, stdin ); chp = strchr( response, '\n'); if (chp) *chp = '\0'; if (strcasecmp( response, "Y" ) == 0) { removeflag = BOOL_TRUE; GotResponse = BOOL_TRUE; } else if (strcasecmp( response, "N" ) == 0) { GotResponse = BOOL_TRUE; } } } printf("-------------------------------------------------\n\n"); } if (removeflag == BOOL_TRUE) { /* Mark this entry as pruned */ StObjhdr->sh_pruned = 1; removedcount++; } i++; StObjhdr = (invt_seshdr_t *)( temp + sizeof(invt_sescounter_t) + (i * sizeof(invt_seshdr_t)) ); StObjses = (invt_session_t *)(temp + StObjhdr->sh_sess_off); } validEntries = counter->ic_curnum - prunedcount - removedcount; munmap( temp, sb.st_size); if (debug && removedcount) printf(" pruned %d entries from this StObj file," " %d remaining\n", removedcount, validEntries); close( fd ); if (validEntries == 0) { if (debug) printf("Removing: %s\n", StObjFileName); unlink( StObjFileName ); return(-1); } return(0); } /* If any of the media objects have a label which matches the one supplied * by the user, or if none is supplied, or if the session has no media * objects, say the session is prunable. * Otherwise, say it should be bypassed. */ int uses_specified_mf_label( invt_seshdr_t *StObjhdr, invt_session_t *StObjses, char *temp, char *r_mf_label) { int s, m; int num_media_objects = 0; invt_stream_t *StObjstrm; invt_mediafile_t *StObjmed; if (!r_mf_label) { return 1; /* prune */ } for ( s = 0; s < (int) StObjses->s_cur_nstreams; s++ ) { StObjstrm = (invt_stream_t *) (temp + StObjhdr->sh_streams_off + (s * sizeof(invt_stream_t))); for ( m = 0; m < StObjstrm->st_nmediafiles; m++, num_media_objects++) { StObjmed = (invt_mediafile_t *) (temp + StObjstrm->st_firstmfile + (m * sizeof(invt_mediafile_t))); if (!strncmp(StObjmed->mf_label, r_mf_label, sizeof(StObjmed->mf_label))) { printf("\t\tSpecified media label \"%s\" found - " "pruning session \"%s\"\n", r_mf_label, StObjses->s_label); return 1; /* prune */ } } } if (!num_media_objects) return 1; /* prune */ return 0; /* don't prune */ } /* copied from inv_api.c */ char * inv_DEBUG_lock_str( int c ) { #ifdef USE_LOCKF static char *lockstr[] = { "F_ULOCK", "F_LOCK", "F_TLOCK", "F_TEST", }; if (c < 0 || c >= (sizeof(lockstr) / sizeof(char *))) { return "unknown lockf"; } return lockstr[c]; #else #ifdef USE_FLOCK int i; static struct { int cmd; char *str; } lockinfo[] = { { LOCK_UN, "LOCK_UN" }, { LOCK_SH, "LOCK_SH" }, { LOCK_EX, "LOCK_EX" }, { LOCK_NB, "LOCK_NB" }, { NULL, NULL } }; for (i = 0; lockinfo[i].str; i++) { if(lockinfo[i].cmd == c) { return lockinfo[i].str; } } return "unknown flock"; #else return "unknown lock mechanism"; #endif /* USE_FLOCK */ #endif /* USE_LOCKF */ } /* * returns file descriptor >= 0 if open and lock successful. * * returns LOCK_BUSY if lock busy. * returns SYSCALL_FAILED for other failures. */ int open_and_lock(char * path, Open_t open_type, uint lock_wait_flag) { int fd; int rc; int open_mode, lock_mode; switch (open_type) { case FILE_READ: open_mode = O_RDONLY; lock_mode = 0; break; case FILE_WRITE: open_mode = O_RDWR; lock_mode = LOCK_EX; break; case FILE_UNSAFE: open_mode = O_RDWR; lock_mode = 0; break; case DIRECTORY_READ: open_mode = O_RDONLY; lock_mode = 0; break; case DIRECTORY_WRITE: open_mode = O_RDWR; lock_mode = LOCK_EX; break; case DIRECTORY_UNSAFE: open_mode = O_RDONLY; lock_mode = 0; break; default: abort(); } fd = open(path, open_mode); if (fd < 0) { fprintf( stderr, "%s: open of %s failed.\n", g_programName, path); perror( "open" ); return SYSCALL_FAILED; } if (lock_mode != 0) { int local_mode = lock_mode; if (lock_wait_flag == 0) local_mode &= ~LOCK_NB; rc = INVLOCK(fd, local_mode); if (rc < 0) { if (errno == EACCES || errno == EWOULDBLOCK) { fprintf(stderr,"%s: Unable to get lock on " "file %s\n", g_programName, path); fprintf(stderr,"Conflict with other instances of" " xfsinvutil, xfsdump or xfsrestore.\n"); rc = LOCK_BUSY; } else { fprintf(stderr,"%s: lock on %s (fd == %d) failed.\n", g_programName, path, fd); perror("file lock"); rc = SYSCALL_FAILED; } close(fd); return rc; } } if (debug) { char *lstr; switch(lock_mode) { case LOCK_EX: lstr = inv_DEBUG_lock_str(lock_mode); break; default: lstr = "NO_LOCK"; } fprintf(stderr, "open_and_lock: DEBUG open_mode %s" " lock_mode %s file %s\n", open_mode == O_RDONLY ? "O_RDONLY" : "O_RDWR", lstr, path); } return fd; } void read_n_bytes(int fd, void * buf, size_t count, char *path) { int rc; rc = read(fd, buf, count); if (rc < 0) { fprintf(stderr, "%s: read of %ld bytes on %s failed.\n", g_programName, (long) count, path); perror(path); exit (2); } else if (rc != count) { fprintf(stderr, "%s: read of %ld bytes on %s failed.\n", g_programName, (long) count, path); fprintf(stderr, "Tried to read %ld bytes, got %d.\n", (long) count, rc); exit (2); } } void write_n_bytes(int fd, void * buf, size_t count, char *path) { int rc; rc = write(fd, buf, count); if (rc < 0) { fprintf(stderr, "%s: write of %ld bytes on %s failed.\n", g_programName, (long) count, path); perror(path); exit (2); } else if (rc != count) { fprintf(stderr, "%s: write of %ld bytes on %s failed.\n", g_programName, (long) count, path); fprintf(stderr, "Tried to write %ld bytes, wrote %d.\n", (long) count, rc); exit (2); } } void * mmap_n_bytes(int fd, size_t count, bool_t checkonly, char *path) { void * temp; lseek( fd, 0, SEEK_SET ); temp = mmap( NULL, count, (checkonly == BOOL_TRUE) ? PROT_READ : PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0 ); if (temp == (void *)-1) { fprintf( stderr, "%s: error in mmap of %ld bytes for file %s\n", g_programName, (long) count, path); perror("mmap"); fprintf( stderr, "%s: abnormal termination\n", g_programName ); exit(1); } return temp; } void usage (void) { int pfxsz; fprintf(stderr, "%s: %s\n", g_programName, g_programVersion); pfxsz = fprintf(stderr, "Usage: \n"); fprintf(stderr, "%*s%s [-F|-i] [-m media_label] -M mount_point mm/dd/yyyy\n", pfxsz, "", g_programName); fprintf(stderr, "%*s%s [-F|-i] [-m media_label] -u UUID mm/dd/yyyy\n", pfxsz, "", g_programName); fprintf(stderr, "%*s%s [-F] -s SESSION_ID\n", pfxsz, "", g_programName); fprintf(stderr, "%*s%s -i\n", pfxsz, "", g_programName); fprintf(stderr, "%*s%s -C\n", pfxsz, "", g_programName); exit(1); } xfsdump-3.1.6+nmu1/invutil/getopt.h0000644000000000000000000000255412607344125014130 0ustar /* * Copyright (c) 2000-2002 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GETOPT_H #define GETOPT_H #define GETOPT_CMDSTRING "dilnu:wCFM:m:s:" #define GETOPT_DEBUG 'd' /* debug */ #define GETOPT_INTERACTIVE 'i' /* interactive mode */ #define GETOPT_NONINTERACTIVE 'n' /* non interactive mode - obsoleted by -F */ #define GETOPT_UUID 'u' /* prune uuid */ #define GETOPT_WAITFORLOCKS 'w' /* wait for locks */ #define GETOPT_CHECKPRUNEFSTAB 'C' /* check and prune fstab */ #define GETOPT_FORCE 'F' /* force - do not ask for confirmation */ #define GETOPT_PRUNEMNT 'M' /* prune mount point */ #define GETOPT_PRUNEMEDIALABEL 'm' /* prune media label */ #define GETOPT_PRUNESESSION 's' /* prune session id */ #endif /* GETOPT_H */ xfsdump-3.1.6+nmu1/invutil/list.c0000644000000000000000000000740512620476160013574 0ustar /* * Copyright (c) 2002 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include "list.h" #include "cmenu.h" node_t * parent_add_child(node_t *parent, node_t *child) { data_t *d; if(parent == NULL || child == NULL) return parent; d = parent->data; d->nbr_children++; d->children = realloc(d->children, d->nbr_children * sizeof(*child)); d->children[d->nbr_children - 1] = child; return parent; } node_t * node_create(int hidden, int expanded, int level, int deleted, int file_idx, char *text, menu_ops_t *ops, node_t *parent, node_t **children, int nbr_children, int data_idx) { node_t *newnode; data_t *newdata; newnode = malloc(sizeof(*newnode)); if(newnode == NULL) return NULL; newdata = malloc(sizeof(*newdata)); if(newdata == NULL) return NULL; newdata->hidden = hidden; newdata->expanded = expanded; newdata->level = level; newdata->deleted = deleted; newdata->file_idx = file_idx; newdata->text = text; newdata->ops = ops; newdata->parent = parent; newdata->children = children; newdata->nbr_children = nbr_children; newdata->data_idx = data_idx; newdata->commited = BOOL_FALSE; newdata->imported = BOOL_FALSE; if(deleted == BOOL_TRUE) { newdata->text[0] = 'D'; } newnode->data = newdata; newnode->next = NULL; newnode->prev = NULL; return newnode; } void node_free(node_t *node) { if(node != NULL) { if(node->data != NULL) { if(((data_t *)(node->data))->text != NULL) { free(((data_t *)(node->data))->text); free(((data_t *)(node->data))->children); } free(node->data); } free(node); } } node_t * list_add(node_t *prevnode, node_t *newnode) { if(newnode == NULL) return NULL; if(prevnode != NULL) { newnode->next = prevnode->next; prevnode->next = newnode; newnode->prev = prevnode; if(newnode->next != NULL) { newnode->next->prev = newnode; } } else { newnode->next = NULL; newnode->prev = NULL; } if(((data_t *)(newnode->data))->parent != NULL) { parent_add_child(((data_t *)(newnode->data))->parent, newnode); } return newnode; } node_t * list_del(node_t *node) { if(node->prev != NULL) { node->prev->next = node->next; } if(node->next != NULL) { node->next->prev = node->prev; } node->next = NULL; node->prev = NULL; return node; } node_t * free_all_children(node_t *node) { int i; data_t *d; if(node == NULL || node->data == NULL) return NULL; d = (data_t *)(node->data); for(i = 0; i < d->nbr_children; i++) { node_free(list_del(free_all_children(d->children[i]))); } d->children = NULL; d->nbr_children = 0; return node; } /* Used when a parent controls the commit for child nodes */ node_t * mark_all_children_commited(node_t *node) { int i; data_t *d; if(node == NULL || node->data == NULL) return NULL; d = (data_t *)(node->data); for(i = 0; i < d->nbr_children; i++) { mark_all_children_commited(d->children[i]); } d->commited = BOOL_TRUE; return node; } xfsdump-3.1.6+nmu1/invutil/fstab.h0000644000000000000000000000261312607344125013721 0ustar /* * Copyright (c) 2002 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef FSTAB_H #define FSTAB_H #include "types.h" #include "mlog.h" #include "inv_priv.h" #include "list.h" #include "cmenu.h" /* fstab.c */ node_t *generate_fstab_menu(char *inv_path, node_t *startnode, int level, char *fstabname); int open_fstab(char *fstabname); int close_all_fstab(void); void *remmap_fstab(int fidx, int num); int find_matching_fstab(int fidx, invt_fstab_t *fstabentry); int fstab_select(WINDOW *win, node_t *current, node_t *list); int fstab_highlight(WINDOW *win, node_t *current, node_t *list); int fstab_commit(WINDOW *win, node_t *current, node_t *list); int fstab_prune(char *mountpt, uuid_t *uuidp, time32_t prunetime, node_t *node, node_t *list); #endif /* FSTAB_H */ xfsdump-3.1.6+nmu1/invutil/screen.c0000644000000000000000000000365112620476160014077 0ustar /* * Copyright (c) 2002 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include "cmenu.h" int put_line(WINDOW *win, int line, char *msg, int attr, alignment_t alignment) { int c; int cols; int msglen; static char text[256]; cols = getmaxx(win); cols--; if(cols > 255) { cols = 255; } msglen = strlen(msg); if(msglen > cols) msglen = cols; switch(alignment) { case ALIGN_CENTRE: c = (cols - msglen) / 2; break; case ALIGN_RIGHT: c = (cols - msglen); break; case ALIGN_LEFT: default: c = 0; break; } snprintf(text, sizeof(text), "%*s%.*s%*s", c, "", msglen, msg, cols - msglen - c, ""); wmove(win, line, 0); wattron(win, attr); waddstr(win, text); wattroff(win, attr); return 0; } void hitanykey() { put_footer("Hit any key to continue...", ALIGN_CENTRE); wgetch(stdscr); clear_line(stdscr, LINES - 1); } /*ARGSUSED*/ int get_string(WINDOW *win, char *prompt, char *response, int len) { put_line(stdscr, LINES - 1, prompt, 0, ALIGN_LEFT); wmove(stdscr, LINES - 1, strlen(prompt)); echo(); wgetnstr(stdscr, response, len); noecho(); return 0; } xfsdump-3.1.6+nmu1/invutil/invidx.h0000644000000000000000000000415112607344125014122 0ustar /* * Copyright (c) 2002 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef INVIDX_H #define INVIDX_H #include "types.h" #include "mlog.h" #include "inv_priv.h" #include "list.h" #include "cmenu.h" /* invidx.c */ node_t *generate_invidx_menu(char *inv_path, node_t *startnode, int level, char *idxFileName); int open_invidx(char *idxFileName); int close_invidx(int idx); int close_all_invidx(void); void *remmap_invidx(int fidx, int num); int find_matching_stobjfile(char *filename); int find_matching_invidxfile(char *filename); int find_overlapping_invidx(int fidx, invt_entry_t *inv_entry); int find_invidx_insert_pos(int fidx, invt_entry_t *inv_entry); char *get_inventry_stobjfile(data_t *d); node_t *find_invidx_node(node_t *list, int inv_fileidx); int read_stobj_info(int fd, int idx, invt_seshdr_t **hdr, invt_session_t **ses, invt_stream_t **strms, invt_mediafile_t **mfiles); int insert_stobj_into_stobjfile(int invidx_fileidx, char *filename, int fd, invt_seshdr_t *hdr, invt_session_t *ses, invt_stream_t *strms, invt_mediafile_t *mfiles); int insert_stobj_into_inventory(int invidx_fileidx, node_t *node); int invidx_undelete(WINDOW *win, node_t *current, node_t *list); int invidx_select(WINDOW *win, node_t *current, node_t *list); int invidx_highlight(WINDOW *win, node_t *current, node_t *list); int invidx_commit(WINDOW *win, node_t *current, node_t *list); int invidx_prune(char *mountpt, uuid_t *uuidp, time32_t prunetime, node_t *node, node_t *list); #endif /* INVIDX_H */ xfsdump-3.1.6+nmu1/invutil/cmenu.h0000644000000000000000000001067212607344125013735 0ustar /* * Copyright (c) 2002 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef CMENU_H #define CMENU_H #include "types.h" #include "mlog.h" #include "inv_priv.h" #include "list.h" /* number of lines for info window */ #define INFO_SIZE 4 #define put_header(m,a) put_line(stdscr, 0, m, A_REVERSE | A_BOLD, a) #define put_footer(m,a) put_line(stdscr, LINES - 1, m, A_REVERSE | A_BOLD, a) #define put_error(m) put_line(stdscr, LINES - 1, m, A_REVERSE | A_BOLD, ALIGN_LEFT);\ beep();\ wrefresh(stdscr);\ sleep(2) #define put_info_header(m) put_line(infowin, 0, m, A_REVERSE|A_BOLD, ALIGN_LEFT) #define put_info_line(l,m) put_line(infowin, l, m, 0, ALIGN_LEFT) #define put_option(w,l,t,a) put_line(w, l, t, a, ALIGN_LEFT) #define clear_line(w,l) wmove(w, l, 0); wclrtoeol(w); typedef enum { ALIGN_LEFT, ALIGN_CENTRE, ALIGN_RIGHT } alignment_t; typedef struct menu_ops_s { int (* op_delete ) (WINDOW *win, node_t *current, node_t *list); int (* op_undelete ) (WINDOW *win, node_t *current, node_t *list); int (* op_saveexit ) (WINDOW *win, node_t *current, node_t *list); int (* op_select ) (WINDOW *win, node_t *current, node_t *list); int (* op_collapse ) (WINDOW *win, node_t *current, node_t *list); int (* op_expand ) (WINDOW *win, node_t *current, node_t *list); int (* op_collapseall ) (WINDOW *win, node_t *current, node_t *list); int (* op_expandall ) (WINDOW *win, node_t *current, node_t *list); int (* op_highlight ) (WINDOW *win, node_t *current, node_t *list); int (* op_unhighlight ) (WINDOW *win, node_t *current, node_t *list); int (* op_commit ) (WINDOW *win, node_t *current, node_t *list); int (* op_prune ) (char *mountpt, uuid_t *uuidp, time32_t prunetime, node_t *node, node_t *list); } menu_ops_t; typedef struct { int key; char *text; int (*fn)(WINDOW *win, node_t *current, node_t *list); } menukey_t; typedef struct { invt_seshdr_t *header; invt_session_t *session; } stobjsess_t; typedef struct { char *name; int fd; int nEntries; char *mapaddr; invt_counter_t *counter; invt_entry_t **data; int numrecords; } invidx_fileinfo_t; typedef struct { char *name; int fd; off_t size; char *mapaddr; invt_sescounter_t *counter; void **data; int numrecords; } stobj_fileinfo_t; typedef struct { char *name; int fd; int nEntries; char *mapaddr; invt_counter_t *counter; invt_fstab_t **data; int numrecords; } fstab_fileinfo_t; extern int redraw_screen; extern int redraw_options; extern WINDOW *mainmenu; extern WINDOW *infowin; /* cmenu.c */ void hitanykey(void); int put_line(WINDOW *win, int line, char *msg, int attr, alignment_t alignment); int create_windows(void); int get_string(WINDOW *win, char *prompt, char *response, int len); void list_undelete(node_t *current, node_t *list); int list_delete(node_t *current, node_t *list); int menu_import(WINDOW *win, node_t *current, node_t *list); int menu_unhighlight(WINDOW *win, node_t *current, node_t *list); int menu_expand(WINDOW *win, node_t *current, node_t *list); int menu_expandall(WINDOW *win, node_t *current, node_t *list); int menu_collapse(WINDOW *win, node_t *current, node_t *list); int menu_collapseall(WINDOW *win, node_t *current, node_t *list); int menu_select(WINDOW *win, node_t *current, node_t *list); int menu_delete(WINDOW *win, node_t *current, node_t *list); int menu_undelete(WINDOW *win, node_t *current, node_t *list); int menu_saveexit(WINDOW *win, node_t *current, node_t *list); int menu_commit(WINDOW *win, node_t *current, node_t *list); int menu_quit(WINDOW *win, node_t *current, node_t *list); /* menu.c */ int menu(WINDOW *win, int line, int col, node_t *list, int keyc, menukey_t *keyv); node_t *generate_menu(char *inv_path); #endif /* CMENU_H */ xfsdump-3.1.6+nmu1/invutil/cmenu.c0000644000000000000000000002604512620476160013731 0ustar /* * Copyright (c) 2002 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include "types.h" #include "mlog.h" #include "inv_priv.h" #include "getopt.h" #include "invutil.h" #include "cmenu.h" #include "list.h" #include "fstab.h" #include "invidx.h" #include "stobj.h" WINDOW *mainmenu; WINDOW *infowin; menukey_t keyv[] = { {'+', "| +: Expand |", menu_expand }, {'-', "| -: Collapse |", menu_collapse }, {'*', "| *: Expand Tree |", menu_expandall }, {'%', "| %: Collapse Tree |", menu_collapseall}, {'d', "| d: Delete |", menu_delete }, {'u', "| u: Undelete |", menu_undelete }, {'i', "| i: Import Inventory |", menu_import }, {'x', "| x: Commit & Exit |", menu_commit }, {'q', "| q: Quit |", menu_quit }, {' ', "| : Select |", menu_select }, {KEY_ENTER, NULL, menu_select }, }; /*ARGSUSED*/ void signal_handler(int s) { switch(s) { case SIGWINCH: signal(SIGWINCH, signal_handler); delwin(mainmenu); delwin(infowin); endwin(); create_windows(); redraw_screen = BOOL_TRUE; break; } } /*ARGSUSED*/ int menu_quit(WINDOW *win, node_t *current, node_t *list) { return BOOL_TRUE; } /*ARGSUSED*/ int menu_commit(WINDOW *win, node_t *current, node_t *list) { node_t *n; node_t *next; data_t *d; n = list; while(n != NULL && n->data != NULL) { d = n->data; if(d->ops != NULL && d->ops->op_commit != NULL && d->commited == BOOL_FALSE) { d->ops->op_commit(win, n, list); d->commited = BOOL_TRUE; } n = n->next; } n = list; while(n != NULL) { next = n->next; node_free(list_del(n)); n = next; } return BOOL_TRUE; } node_t * get_lastnode(node_t *node) { while(node->next != NULL) { node = node->next; } return node; } /*ARGSUSED*/ int menu_import(WINDOW *win, node_t *current, node_t *list) { char inv_path[MAXPATHLEN]; struct stat s; char *fstabname; data_t *d; for(;;) { inv_path[0] = '\0'; if(get_string(win, "Path to inventory to be imported: ", inv_path, MAXPATHLEN) == ERR) { put_error("Error: invalid input"); continue; } if(strlen(inv_path) == 0) { clear_line(stdscr, LINES - 1); return BOOL_FALSE; } if(stat(inv_path, &s) < 0 || !S_ISDIR(s.st_mode)) { put_error("Error: invalid path"); continue; } clear_line(stdscr, LINES - 1); fstabname = GetFstabFullPath(inv_path); if(fstabname == NULL) { put_footer("internal memory error: import inventory", ALIGN_LEFT); exit(1); } while(current->next != NULL) { current = current->next; } generate_fstab_menu(inv_path, current, 0, fstabname); free(fstabname); while(current->next != NULL) { current = current->next; d = current->data; d->text[1] = 'I'; d->imported = BOOL_TRUE; } redraw_screen = BOOL_TRUE; break; } return BOOL_FALSE; } /*ARGSUSED*/ int menu_unhighlight(WINDOW *win, node_t *current, node_t *list) { wclear(infowin); put_info_header(""); return BOOL_FALSE; } int menu_select(WINDOW *win, node_t *current, node_t *list) { data_t *d; if(current == NULL || current->data == NULL) { return BOOL_FALSE; } d = (data_t *)(current->data); if(d->ops != NULL && d->ops->op_select != NULL) { return d->ops->op_select(win, current, list); } return BOOL_FALSE; } node_t * expand_node(node_t *node) { int i; data_t *d; if(node == NULL || node->data == NULL) { return NULL; } d = node->data; d->expanded = BOOL_TRUE; for(i = 0; i < d->nbr_children; i++) { ((data_t *)(d->children[i]->data))->hidden = BOOL_FALSE; } return node; } int menu_expand(WINDOW *win, node_t *current, node_t *list) { data_t *d; if(current == NULL || current->data == NULL) { return BOOL_FALSE; } d = current->data; if(d->ops != NULL && d->ops->op_expand != NULL) { return d->ops->op_expand(win, current, list); } expand_node(current); redraw_screen = BOOL_TRUE; return BOOL_FALSE; } node_t * expand_tree(node_t *node) { int i; data_t *d; if(node == NULL || node->data == NULL) { return NULL; } d = node->data; d->hidden = BOOL_FALSE; d->expanded = BOOL_TRUE; for(i = 0; i < d->nbr_children; i++) { expand_tree(d->children[i]); } return node; } int menu_expandall(WINDOW *win, node_t *current, node_t *list) { data_t *d; if(current == NULL || current->data == NULL) { return BOOL_FALSE; } d = (data_t *)(current->data); if(d->ops != NULL && d->ops->op_expandall != NULL) { return d->ops->op_expandall(win, current, list); } expand_tree(current); redraw_screen = BOOL_TRUE; return BOOL_FALSE; } node_t * collapse_node(node_t *node) { int i; data_t *d; if(node == NULL || node->data == NULL) { return NULL; } d = node->data; if(d->expanded == BOOL_FALSE) return node; d->expanded = BOOL_FALSE; for(i = 0; i < d->nbr_children; i++) { ((data_t *)(d->children[i]->data))->hidden = BOOL_TRUE; collapse_node(d->children[i]); } return node; } int menu_collapse(WINDOW *win, node_t *current, node_t *list) { data_t *d; if(current == NULL || current->data == NULL) { return BOOL_FALSE; } d = current->data; if(d->ops != NULL && d->ops->op_collapse != NULL) { return d->ops->op_collapse(win, current, list); } collapse_node(current); redraw_screen = BOOL_TRUE; return BOOL_FALSE; } int menu_collapseall(WINDOW *win, node_t *current, node_t *list) { data_t *d; node_t *n; if(current == NULL || current->data == NULL) { return BOOL_FALSE; } d = current->data; if(d->ops != NULL && d->ops->op_collapseall != NULL) { return d->ops->op_collapseall(win, current, list); } n = current; while(d->parent != NULL) { n = d->parent; d = n->data; } collapse_node(n); redraw_screen = BOOL_TRUE; return BOOL_FALSE; } int menu_delete(WINDOW *win, node_t *current, node_t *list) { data_t *d; if(current == NULL || current->data == NULL) { return BOOL_FALSE; } d = (data_t *)(current->data); if(d->ops != NULL && d->ops->op_delete != NULL) { return d->ops->op_delete(win, current, list); } list_delete(current, list); redraw_screen = BOOL_TRUE; return BOOL_FALSE; } int menu_undelete(WINDOW *win, node_t *current, node_t *list) { data_t *d; if(current == NULL || current->data == NULL) { return BOOL_FALSE; } d = (data_t *)(current->data); if(d->ops != NULL && d->ops->op_undelete != NULL) { return d->ops->op_undelete(win, current, list); } list_undelete(current, list); redraw_screen = BOOL_TRUE; return BOOL_FALSE; } int menu_saveexit(WINDOW *win, node_t *current, node_t *list) { data_t *d; if(current == NULL || current->data == NULL) { return BOOL_TRUE; } d = (data_t *)(current->data); if(d->ops != NULL && d->ops->op_saveexit != NULL) { return d->ops->op_saveexit(win, current, list); } return BOOL_TRUE; } node_t * delete_node(node_t *node) { int i; data_t *d; if(node == NULL || node->data == NULL) { return NULL; } d = node->data; d->deleted = BOOL_TRUE; d->text[0] = 'D'; for(i = 0; i < d->nbr_children; i++) { delete_node(d->children[i]); } return node; } /*ARGSUSED*/ int list_delete(node_t *current, node_t *list) { if(current == NULL && current->data == NULL) { return 0; } delete_node(current); return 0; } node_t * undelete_node(node_t *node) { data_t *d; if(node == NULL || node->data == NULL) { return NULL; } d = node->data; d->deleted = BOOL_FALSE; d->text[0] = ' '; if(d->parent != NULL) { undelete_node(d->parent); } return node; } /*ARGSUSED*/ void list_undelete(node_t *current, node_t *list) { if(current == NULL || current->data == NULL) { return; } undelete_node(current); } int list_prune(node_t *menulist, char *mountpt, uuid_t *uuidp, time32_t prunetime) { node_t *n; data_t *d; n = menulist; while(n != NULL) { d = (data_t *)(n->data); if(d != NULL && d->ops != NULL && d->ops->op_prune != NULL) { if(d->ops->op_prune(mountpt, uuidp, prunetime, n, menulist) == BOOL_TRUE) { if(d->ops->op_delete == NULL) { list_delete(n, menulist); } else { d->ops->op_delete(NULL, n, menulist); } } else { if(d->ops->op_undelete == NULL) { list_undelete(n, menulist); } else { d->ops->op_undelete(NULL, n, menulist); } } } n = n->next; } return 0; } node_t * generate_menu(char *inv_path) { char *fstabname; node_t *list; fstabname = GetFstabFullPath(inv_path); if(fstabname == NULL) { fprintf(stderr, "%s: internal memory error: general_menu\n", g_programName); exit(1); } list = generate_fstab_menu(inv_path, NULL, 0, fstabname); free(fstabname); return list; } int create_windows() { int menusize; int infosize; initscr(); cbreak(); noecho(); keypad(stdscr, TRUE); signal(SIGWINCH, signal_handler); if(LINES < 7) { endwin(); fprintf(stderr, "%s: window too small for curses interactive mode: LINES = %d\n", g_programName, LINES); exit(1); } mainmenu = newpad(100, COLS); keypad(mainmenu, TRUE); notimeout(mainmenu, TRUE); menusize = (LINES - 2) - INFO_SIZE; if(menusize <= 0) menusize = 1; prefresh(mainmenu, 0, 0, 1, 0, menusize, COLS - 1); infosize = INFO_SIZE; if(infosize <= 0) infosize = 1; infowin = newwin(infosize, COLS, menusize + 1, 0); keypad(infowin, TRUE); wrefresh(infowin); return menusize; } int invutil_interactive(char *inv_path, char *mountpt, uuid_t *uuidp, time32_t timeSecs) { int keyc; node_t *menulist; menulist = generate_menu(inv_path); if(menulist == NULL) { fprintf(stderr, "%s: abnormal termination\n", g_programName); exit(1); } if(timeSecs > 0) { list_prune(menulist, mountpt, uuidp, timeSecs); } keyc = sizeof(keyv) / sizeof(keyv[0]); create_windows(); menu(mainmenu, 1, 0, menulist, keyc, keyv); endwin(); close_all_stobj(); close_all_invidx(); close_all_fstab(); return 0; } xfsdump-3.1.6+nmu1/invutil/fstab.c0000644000000000000000000002574112620476160013723 0ustar /* * Copyright (c) 2002 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include "types.h" #include "mlog.h" #include "inv_priv.h" #include "getopt.h" #include "invutil.h" #include "cmenu.h" #include "list.h" #include "invidx.h" #include "fstab.h" fstab_fileinfo_t *fstab_file; int fstab_numfiles; menu_ops_t fstab_ops = { NULL, NULL, NULL, /*fstab_saveall,*/ fstab_select, NULL, NULL, NULL, NULL, fstab_highlight, menu_unhighlight, fstab_commit, fstab_prune, }; /*ARGSUSED*/ int fstab_commit(WINDOW *win, node_t *current, node_t *list) { int i; int fidx; node_t *n; data_t *d; invt_fstab_t *fstabentry; int fstabentry_idx; n = current; if(n == NULL || n->data == NULL) return 0; d = ((data_t *)(n->data)); fidx = d->file_idx; fstabentry = fstab_file[fidx].data[d->data_idx]; if(d->deleted == BOOL_TRUE && d->imported == BOOL_FALSE) { for(i = 0; i < d->nbr_children; i++) { invidx_commit(win, d->children[i], list); } mark_all_children_commited(current); fstabentry_idx = (int)(((long)fstabentry - (long)fstab_file[fidx].mapaddr - sizeof(invt_counter_t)) / sizeof(invt_fstab_t)); if ( fstab_file[fidx].counter->ic_curnum > 1 ) { memmove(fstabentry, fstabentry + 1, (sizeof(invt_fstab_t) * (fstab_file[fidx].counter->ic_curnum - fstabentry_idx - 1))); fstab_file[fidx].data[d->data_idx] = NULL; for(i = d->data_idx + 1; i < fstab_file[fidx].numrecords; i++) { if(fstab_file[fidx].data[i] != NULL) fstab_file[fidx].data[i]--; } } fstab_file[fidx].counter->ic_curnum--; } else if(d->imported == BOOL_TRUE) { invt_fstab_t *dest; for(i = 0; i < d->nbr_children; i++) { invidx_commit(win, d->children[i], list); } mark_all_children_commited(current); if(find_matching_fstab(0, fstabentry) >= 0) { return 0; } if(fstab_file[0].counter->ic_curnum < fstab_file[0].nEntries) { dest = fstab_file[0].data[fstab_file[0].counter->ic_curnum - 1] + 1; } else { /* expand mmap by one */ dest = remmap_fstab(0, 1); } /* copy new data to mmap */ memmove(dest, fstabentry, sizeof(*fstabentry)); /* increment counter */ fstab_file[0].counter->ic_curnum++; } return 0; } /*ARGSUSED*/ int fstab_select(WINDOW *win, node_t *current, node_t *list) { data_t *d; if(current == NULL || current->data == NULL) { return 0; } d = (data_t *)(current->data); if(d->expanded == TRUE) { return menu_collapse(win, current, list); } return menu_expand(win, current, list); } /*ARGSUSED*/ int fstab_highlight(WINDOW *win, node_t *current, node_t *list) { static char txt[256]; char uuidstr[UUID_STR_LEN + 1]; data_t *d; invt_fstab_t *fstabentry; if(current == NULL || current->data == NULL) { return 0; } d = (data_t *)(current->data); fstabentry = fstab_file[d->file_idx].data[d->data_idx]; wclear(infowin); put_info_header("fstab entry"); snprintf(txt, sizeof(txt), "device: %s", fstabentry->ft_devpath); put_info_line(1, txt); uuid_unparse(fstabentry->ft_uuid, uuidstr); snprintf(txt, sizeof(txt), "uuid: %s", uuidstr); put_info_line(2, txt); return FALSE; } /*ARGSUSED*/ int fstab_prune(char *mountpt, uuid_t *uuidp, time32_t prunetime, node_t *node, node_t *list) { data_t *d; invt_fstab_t *fstabentry; if(node == NULL || node->data == NULL) { return BOOL_FALSE; } d = (data_t *)(node->data); fstabentry = fstab_file[d->file_idx].data[d->data_idx]; if(mountpt != NULL && mntpnt_equal(mountpt, fstabentry->ft_mountpt)) { return BOOL_TRUE; } if((!uuid_is_null(*uuidp)) && (uuid_compare(*uuidp, fstabentry->ft_uuid) == 0)) { return BOOL_TRUE; } return BOOL_FALSE; } int add_fstab_data(int fidx, invt_fstab_t *data) { if(fstab_file[fidx].numrecords == 0) { fstab_file[fidx].data = malloc(sizeof(*fstab_file[fidx].data)); if(fstab_file[fidx].data == NULL) { fprintf(stderr, "%s: internal memory error: fstab data allocation\n", g_programName); exit(1); } } else { fstab_file[fidx].data = realloc(fstab_file[fidx].data, sizeof(*fstab_file[fidx].data) * (fstab_file[fidx].numrecords + 1)); if(fstab_file[fidx].data == NULL) { fprintf(stderr, "%s: internal memory error: fstab data reallocation\n", g_programName); exit(1); } } fstab_file[fidx].data[fstab_file[fidx].numrecords] = data; fstab_file[fidx].numrecords++; return fstab_file[fidx].numrecords - 1; } node_t * generate_fstab_menu(char * inv_path, node_t *startnode, int level, char *fstabname) { int i; char *invname; char *txt; int idx; int len; node_t *list = NULL; node_t *n; invt_fstab_t *fstab_entry; if((idx = open_fstab(fstabname)) < 0) { return NULL; } fstab_entry = (invt_fstab_t *)(fstab_file[idx].mapaddr + sizeof(invt_counter_t)); n = startnode; for(i=0; i < fstab_file[idx].counter->ic_curnum; i++) { len = strlen(fstab_entry[i].ft_mountpt) + strlen(fstab_entry[i].ft_devpath) + 40; txt = malloc(len); if(txt == NULL) { fprintf(stderr, "%s: internal memory error: fstab_text\n", g_programName); exit(1); } snprintf(txt, len, " fs: %s", fstab_entry[i].ft_mountpt); n = list_add(n, node_create(BOOL_FALSE, /* hidden */ BOOL_FALSE, /* expanded */ level, /* level */ BOOL_FALSE, /* deleted */ idx, /* file_idx */ txt, /* text */ &(fstab_ops), /* menu ops */ NULL, /* parent */ NULL, /* children */ 0, /* nbr_children */ i)); /* data_idx */ if(i == 0) { list = n; } if(n == NULL) { fprintf(stderr, "%s: internal memory error: list_add: node_create: fstab\n", g_programName); exit(1); } add_fstab_data(idx, &(fstab_entry[i])); invname = GetNameOfInvIndex(inv_path, fstab_entry[i].ft_uuid); n = generate_invidx_menu(inv_path, n, level + 1, invname); free(invname); } return list; } int add_fstab(char *name, int fd, int nEntries, char *mapaddr, invt_counter_t *counter) { static int highwatermark = 10; if(fstab_numfiles == 0) { fstab_file = malloc(sizeof(*fstab_file) * highwatermark); if(fstab_file == NULL) { fprintf(stderr, "%s: internal memory error: malloc fstab_file\n", g_programName); exit(1); } } else { if(fstab_numfiles >= highwatermark - 1) { highwatermark += highwatermark; fstab_file = realloc(fstab_file, sizeof(*fstab_file) * highwatermark); if(fstab_file == NULL) { fprintf(stderr, "%s: internal memory error: realloc fstab\n", g_programName); exit(1); } } } fstab_file[fstab_numfiles].fd = fd; fstab_file[fstab_numfiles].name = name; fstab_file[fstab_numfiles].nEntries = nEntries; fstab_file[fstab_numfiles].mapaddr = mapaddr; fstab_file[fstab_numfiles].counter = counter; fstab_file[fstab_numfiles].data = NULL; fstab_file[fstab_numfiles].numrecords = 0; fstab_numfiles++; return fstab_numfiles - 1; } int fstab_equal(invt_fstab_t *f1, invt_fstab_t *f2) { if(strcmp(f1->ft_mountpt, f2->ft_mountpt) != 0) return BOOL_FALSE; if(strcmp(f1->ft_devpath, f2->ft_devpath) != 0) return BOOL_FALSE; if(uuid_compare(f1->ft_uuid, f2->ft_uuid) != 0) return BOOL_FALSE; return BOOL_TRUE; } int find_matching_fstab(int fidx, invt_fstab_t *fstabentry) { int i; for(i = 0; i < fstab_file[fidx].numrecords; i++) { if(fstab_equal(fstab_file[fidx].data[i], fstabentry) == BOOL_TRUE) { return i; } } return -1; } void * remmap_fstab(int fidx, int num) { int i; int nEntries; char *mapaddr; invt_fstab_t *fstab_entry; nEntries = fstab_file[fidx].counter->ic_curnum; munmap( fstab_file[fidx].mapaddr, (nEntries * sizeof(invt_fstab_t)) + sizeof(invt_counter_t)); /* need to lseek on the file to grow it to the right size - no autogrow on linux */ lseek(fstab_file[fidx].fd, (num * sizeof(invt_fstab_t)) - 1, SEEK_END); write_n_bytes(fstab_file[fidx].fd, "", 1, fstab_file[fidx].name); mapaddr = mmap_n_bytes(fstab_file[fidx].fd, (nEntries + 1) * (num * sizeof(invt_fstab_t)) + sizeof(invt_counter_t), BOOL_FALSE, fstab_file[fidx].name); fstab_file[fidx].nEntries += num; fstab_file[fidx].mapaddr = mapaddr; fstab_file[fidx].counter = (invt_counter_t *)mapaddr; /* regenerate the data index for the file given the new mapping */ fstab_entry = (invt_fstab_t *)(fstab_file[fidx].mapaddr + sizeof(invt_counter_t)); for(i=0; i < nEntries; i++) { if(i >= fstab_file[fidx].numrecords) { add_fstab_data(fidx, &(fstab_entry[i])); } else { fstab_file[fidx].data[i] = &(fstab_entry[i]); } } return &(fstab_entry[i]); } int open_fstab(char *fstabname) { int fd; int nEntries; char *mapaddr; char *name; invt_counter_t cnt; fd = open_and_lock( fstabname, FILE_WRITE, wait_for_locks ); if (fd < 0) { fprintf( stderr, "%s: abnormal termination\n", g_programName ); exit(1); } name = strdup(fstabname); if(name == NULL) { fprintf(stderr, "%s: internal memory error: strdup fstabname\n", g_programName); exit(1); } read_n_bytes(fd, &cnt, sizeof(invt_counter_t), fstabname); nEntries = cnt.ic_curnum; mapaddr = mmap_n_bytes(fd, nEntries * sizeof(invt_fstab_t) + sizeof(invt_counter_t), BOOL_FALSE, fstabname); return add_fstab(name, fd, nEntries, mapaddr, (invt_counter_t *)mapaddr); } int close_fstab(int fidx) { int fstabentries; fstabentries = fstab_file[fidx].counter->ic_curnum; munmap( fstab_file[fidx].mapaddr, (fstab_file[fidx].counter->ic_curnum * sizeof(invt_fstab_t)) + sizeof(invt_counter_t)); if ((fstabentries != 0) && (fstabentries < fstab_file[fidx].nEntries)) { ftruncate(fstab_file[fidx].fd, sizeof(invt_counter_t) + (sizeof(invt_fstab_t) * fstabentries)); } close(fstab_file[fidx].fd); if (fstabentries == 0) { unlink( fstab_file[fidx].name ); } free(fstab_file[fidx].name); free(fstab_file[fidx].data); return 0; } int close_all_fstab() { int i; for(i = 0; i < fstab_numfiles; i++) { close_fstab(i); } free(fstab_file); fstab_file = NULL; return 0; } xfsdump-3.1.6+nmu1/invutil/stobj.c0000644000000000000000000003731012620476160013740 0ustar /* * Copyright (c) 2002 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include "types.h" #include "mlog.h" #include "inv_priv.h" #include "getopt.h" #include "invutil.h" #include "timeutil.h" #include "cmenu.h" #include "list.h" #include "stobj.h" stobj_fileinfo_t *stobj_file; int stobj_numfiles; menu_ops_t stobjsess_ops = { NULL, stobj_undelete, NULL, stobj_select, NULL, NULL, NULL, NULL, stobjsess_highlight, menu_unhighlight, stobjsess_commit, stobj_prune, }; menu_ops_t stobjstrm_ops = { stobjstrm_delete, stobj_undelete, NULL, stobj_select, NULL, NULL, NULL, NULL, stobjstrm_highlight, menu_unhighlight, stobjstrm_commit, NULL, }; menu_ops_t stobjmed_ops = { stobjmed_delete, NULL, NULL, stobj_select, NULL, NULL, NULL, NULL, stobjmed_highlight, menu_unhighlight, stobjmed_commit, NULL, }; /*ARGSUSED*/ int stobjmed_commit(WINDOW *win, node_t *current, node_t *list) { data_t *d; if(current == NULL || current->data == NULL) { return 0; } d = (data_t *)(current->data); return stobjstrm_commit(win, d->parent, list); } /*ARGSUSED*/ int stobjstrm_commit(WINDOW *win, node_t *current, node_t *list) { data_t *d; if(current == NULL || current->data == NULL) { return 0; } d = (data_t *)(current->data); return stobjsess_commit(win, d->parent, list); } /*ARGSUSED*/ int stobjmed_delete(WINDOW *win, node_t *current, node_t *list) { data_t *d; if(current == NULL || current->data == NULL) { return 0; } d = (data_t *)(current->data); return stobjstrm_delete(win, d->parent, list); } /*ARGSUSED*/ int stobjstrm_delete(WINDOW *win, node_t *current, node_t *list) { data_t *d; if(current == NULL || current->data == NULL) { return 0; } d = (data_t *)(current->data); return menu_delete(win, d->parent, list); } /*ARGSUSED*/ int stobjsess_commit(WINDOW *win, node_t *current, node_t *list) { data_t *d; invt_seshdr_t *stobjhdr; if(current == NULL || current->data == NULL) { return 0; } d = (data_t *)(current->data); stobjhdr = ((stobjsess_t *)(stobj_file[d->file_idx].data[d->data_idx]))->header; mark_all_children_commited(current); if(d->deleted == BOOL_TRUE) { stobjhdr->sh_pruned = 1; } else { stobjhdr->sh_pruned = 0; } return 0; } /*ARGSUSED*/ int stobjsess_highlight(WINDOW *win, node_t *current, node_t *list) { static char txt[256]; char uuidstr[UUID_STR_LEN + 1]; data_t *d; invt_seshdr_t *stobjhdr; invt_session_t *stobjses; if(current == NULL || current->data == NULL) { return 0; } d = (data_t *)(current->data); stobjhdr = ((stobjsess_t *)(stobj_file[d->file_idx].data[d->data_idx]))->header; stobjses = ((stobjsess_t *)(stobj_file[d->file_idx].data[d->data_idx]))->session; wclear(infowin); put_info_header("session entry"); snprintf(txt, sizeof(txt), "pruned: %s, flags: %#x, time: %s", (stobjhdr->sh_pruned == BOOL_TRUE) ? "yes" : "no", stobjhdr->sh_flag, ctime32(&(stobjhdr->sh_time))); txt[strlen(txt)-1] = '\0'; put_info_line(1, txt); uuid_unparse(stobjses->s_fsid, uuidstr); snprintf(txt, sizeof(txt), "mountpt: %s, fsid: %s", stobjses->s_mountpt, uuidstr); put_info_line(2, txt); uuid_unparse(stobjses->s_sesid, uuidstr); snprintf(txt, sizeof(txt), "device: %s, sesid: %s", stobjses->s_devpath, uuidstr); put_info_line(3, txt); return FALSE; } /*ARGSUSED*/ int stobjstrm_highlight(WINDOW *win, node_t *current, node_t *list) { static char txt[256]; data_t *d; invt_stream_t *stobjstrm; if(current == NULL || current->data == NULL) { return 0; } d = (data_t *)(current->data); stobjstrm = (invt_stream_t *)(stobj_file[d->file_idx].data[d->data_idx]); wclear(infowin); put_info_header("session stream"); snprintf(txt, sizeof(txt), "interrupted: %s, cmdarg: %s", (stobjstrm->st_interrupted == BOOL_TRUE) ? "yes" : "no", stobjstrm->st_cmdarg); put_info_line(1, txt); snprintf(txt, sizeof(txt), "start ino: %llu, offset %lld", (unsigned long long) stobjstrm->st_startino.ino, (long long) stobjstrm->st_startino.offset); put_info_line(2, txt); snprintf(txt, sizeof(txt), " end ino: %llu, offset %lld", (unsigned long long) stobjstrm->st_endino.ino, (long long) stobjstrm->st_endino.offset); put_info_line(3, txt); return FALSE; } /*ARGSUSED*/ int stobjmed_highlight(WINDOW *win, node_t *current, node_t *list) { static char txt[256]; char uuidstr[UUID_STR_LEN + 1]; data_t *d; invt_mediafile_t *stobjmed; if(current == NULL || current->data == NULL) { return 0; } d = (data_t *)(current->data); stobjmed = (invt_mediafile_t *)(stobj_file[d->file_idx].data[d->data_idx]); wclear(infowin); put_info_header("session media file"); uuid_unparse(stobjmed->mf_moid, uuidstr); snprintf(txt, sizeof(txt), "flags: %#x, id: %s", stobjmed->mf_flag, uuidstr); put_info_line(1, txt); snprintf(txt, sizeof(txt), "start ino: %llu, offset %lld", (unsigned long long) stobjmed->mf_startino.ino, (long long) stobjmed->mf_startino.offset); put_info_line(2, txt); snprintf(txt, sizeof(txt), " end ino: %llu, offset %lld", (unsigned long long) stobjmed->mf_endino.ino, (long long) stobjmed->mf_endino.offset); put_info_line(3, txt); return FALSE; } /*ARGSUSED*/ int stobj_select(WINDOW *win, node_t *current, node_t *list) { data_t *d; if(current == NULL || current->data == NULL) { return 0; } d = (data_t *)(current->data); if(d->expanded == TRUE) { return menu_collapse(win, current, list); } return menu_expand(win, current, list); } /*ARGSUSED*/ int stobj_prune(char *mountpt, uuid_t *uuidp, time32_t prunetime, node_t *node, node_t *list) { data_t *d; stobjsess_t *stobj; invt_seshdr_t *stobj_header; invt_session_t *stobj_session; if(node == NULL || node->data == NULL) { return BOOL_FALSE; } d = (data_t *)(node->data); stobj = stobj_file[d->file_idx].data[d->data_idx]; stobj_header = stobj->header; stobj_session = stobj->session; if(stobj_header == NULL || stobj_session == NULL) { return BOOL_FALSE; } if(stobj_header->sh_pruned) { return BOOL_TRUE; } if(stobj_header->sh_time < prunetime) { if(mountpt != NULL && mntpnt_equal(mountpt, stobj_session->s_mountpt)) { return BOOL_TRUE; } if((!uuid_is_null(*uuidp)) && (uuid_compare(*uuidp, stobj_session->s_fsid) == 0)) { return BOOL_TRUE; } } return BOOL_FALSE; } /*ARGSUSED*/ int stobj_undelete(WINDOW *win, node_t *current, node_t *list) { node_t *n; data_t *d; if(current == NULL || current->data == NULL) { return BOOL_FALSE; } list_undelete(current, list); d = ((data_t *)(current->data)); n = current->next; while(n != NULL && n->data != NULL && ((data_t *)(n->data))->level > d->level) { ((data_t *)(n->data))->deleted = BOOL_FALSE; ((data_t *)(n->data))->text[0] = ' '; n = n->next; } redraw_screen = BOOL_TRUE; return BOOL_FALSE; } int add_stobj_data(int fidx, void *data) { if(stobj_file[fidx].numrecords == 0) { stobj_file[fidx].data = malloc(sizeof(*stobj_file[fidx].data)); if(stobj_file[fidx].data == NULL) { fprintf(stderr, "%s: internal memory error: stobj data allocation\n", g_programName); exit(1); } } else { stobj_file[fidx].data = realloc(stobj_file[fidx].data, sizeof(*stobj_file[fidx].data) * (stobj_file[fidx].numrecords + 1)); if(stobj_file[fidx].data == NULL) { fprintf(stderr, "%s: internal memory error: stobj data reallocation\n", g_programName); exit(1); } } stobj_file[fidx].data[stobj_file[fidx].numrecords] = data; stobj_file[fidx].numrecords++; return 0; } node_t * generate_stobj_menu(node_t *startnode, int level, char *StObjFileName) { int i; int j; int k; int idx; int data_idx; int len; char *txt; node_t *n; node_t *parent_stream; node_t *parent_session; stobjsess_t *session; invt_seshdr_t *StObjhdr; invt_session_t *StObjses; invt_stream_t *StObjstrm; invt_mediafile_t *StObjmed; if((idx = open_stobj(StObjFileName)) < 0) { return startnode; } StObjhdr = (invt_seshdr_t *)( stobj_file[idx].mapaddr + sizeof(invt_sescounter_t)); StObjses = (invt_session_t *)(stobj_file[idx].mapaddr + StObjhdr->sh_sess_off); data_idx = 0; n = startnode; for (i=0; i < stobj_file[idx].counter->ic_curnum; ) { session = malloc(sizeof(*session)); if(session == NULL) { fprintf(stderr, "%s: internal memory error: session malloc\n", g_programName); exit(1); } session->header = StObjhdr; session->session = StObjses; len = 60+strlen(session->session->s_label); txt = malloc(len); if(txt == NULL) { fprintf(stderr, "%s: internal memory error: invidx_text\n", g_programName); exit(1); } snprintf(txt, len, " session level: %d label: %s", session->header->sh_level, session->session->s_label); n = list_add(n, node_create(BOOL_TRUE, /* hidden */ BOOL_FALSE, /* expanded */ level, /* level */ session->header->sh_pruned, /* deleted */ idx, /* file_idx */ txt, /* text */ &(stobjsess_ops), /* menu ops */ startnode, /* parent */ NULL, /* children */ 0, /* nbr_children */ data_idx)); if(n == NULL) { fprintf(stderr, "%s: internal memory error: list_add: node_create: session\n", g_programName); exit(1); } data_idx++; add_stobj_data(idx, session); parent_session = n; for ( j = 0; j < (int) StObjses->s_cur_nstreams; j++ ) { StObjstrm = (invt_stream_t *)(stobj_file[idx].mapaddr + StObjhdr->sh_streams_off + (j * sizeof(invt_stream_t))); len = strlen(StObjstrm->st_cmdarg) + 33; txt = malloc(len); if(txt == NULL) { fprintf(stderr, "%s: internal memory error: invidx_text\n", g_programName); exit(1); } snprintf(txt, len, " stream: drive path: %s", StObjstrm->st_cmdarg); n = list_add(n, node_create(BOOL_TRUE, /* hidden */ BOOL_FALSE, /* expanded */ level + 1, /* level */ session->header->sh_pruned, /* deleted */ idx, /* file_idx */ txt, /* text */ &(stobjstrm_ops), /* menu ops */ parent_session, /* parent */ NULL, /* children */ 0, /* nbr_children */ data_idx)); if(n == NULL) { fprintf(stderr, "%s: internal memory error: list_add: node_create: StObjstrm\n", g_programName); exit(1); } data_idx++; add_stobj_data(idx, StObjstrm); parent_stream = n; for ( k = 0; k < StObjstrm->st_nmediafiles; k++) { StObjmed = (invt_mediafile_t *)(stobj_file[idx].mapaddr + StObjstrm->st_firstmfile + (k * sizeof(invt_mediafile_t))); len = strlen(StObjmed->mf_label) + 26; txt = malloc(len); if(txt == NULL) { fprintf(stderr, "%s: internal memory error: invidx_text\n", g_programName); exit(1); } snprintf(txt, len, " media file: %s", StObjmed->mf_label); n = list_add(n, node_create(BOOL_TRUE, /* hidden */ BOOL_FALSE, /* expanded */ level + 2, /* level */ session->header->sh_pruned, /* deleted */ idx, /* file_idx */ txt, /* text */ &(stobjmed_ops), /* menu ops */ parent_stream, /* parent */ NULL, /* children */ 0, /* nbr_children */ data_idx)); if(n == NULL) { fprintf(stderr, "%s: internal memory error: list_add: node_create: StObjmed\n", g_programName); exit(1); } data_idx++; add_stobj_data(idx, StObjmed); } } i++; StObjhdr = (invt_seshdr_t *)( stobj_file[idx].mapaddr + sizeof(invt_sescounter_t) + (i * sizeof(invt_seshdr_t)) ); StObjses = (invt_session_t *)(stobj_file[idx].mapaddr + StObjhdr->sh_sess_off); } return n; } int add_stobj(char *name, int fd, off_t size, char *mapaddr, invt_sescounter_t *counter) { static int highwatermark = 20; if(stobj_numfiles == 0) { stobj_file = malloc(sizeof(*stobj_file) * highwatermark); if(stobj_file == NULL) { fprintf(stderr, "%s: internal memory error: malloc stobj_file\n", g_programName); exit(1); } } else { if(stobj_numfiles >= highwatermark - 1) { highwatermark += highwatermark; stobj_file = realloc(stobj_file, sizeof(*stobj_file) * highwatermark); if(stobj_file == NULL) { fprintf(stderr, "%s: internal memory error: realloc stobj_file\n", g_programName); exit(1); } } } stobj_file[stobj_numfiles].size = size; stobj_file[stobj_numfiles].mapaddr = mapaddr; stobj_file[stobj_numfiles].fd = fd; stobj_file[stobj_numfiles].counter = counter; stobj_file[stobj_numfiles].name = name; stobj_file[stobj_numfiles].data = NULL; stobj_file[stobj_numfiles].numrecords = 0; stobj_numfiles++; return stobj_numfiles - 1; } int open_stobj(char *StObjFileName) { int fd; struct stat sb; off_t size; char *mapaddr; invt_sescounter_t cnt; char *name; errno=0; fd = open_and_lock( StObjFileName, FILE_WRITE, wait_for_locks ); if (fd < 0) { return fd; } read_n_bytes(fd, &cnt, sizeof(invt_sescounter_t), StObjFileName); lseek( fd, 0, SEEK_SET ); errno = 0; if (fstat(fd, &sb) < 0) { fprintf(stderr, "Could not get stat info on %s\n", StObjFileName); perror("fstat"); close(fd); return -1; } size = sb.st_size; mapaddr = mmap_n_bytes(fd, size, BOOL_FALSE, StObjFileName); name = strdup(StObjFileName); if(name == NULL) { fprintf(stderr, "%s: internal memory error: strdup stobj_name\n", g_programName); exit(1); } return add_stobj(name, fd, size, mapaddr, (invt_sescounter_t *)mapaddr); } int close_stobj_file(int fidx, int unlink_ok) { if(fidx >= stobj_numfiles || stobj_file[fidx].fd < 0) return 0; munmap( stobj_file[fidx].mapaddr, stobj_file[fidx].size); close( stobj_file[fidx].fd ); stobj_file[fidx].fd = -1; if(unlink_ok == BOOL_TRUE) { unlink(stobj_file[fidx].name); } free( stobj_file[fidx].name ); free( stobj_file[fidx].data ); stobj_file[fidx].name = NULL; stobj_file[fidx].data = NULL; return 0; } int close_all_stobj() { int i; int j; invt_seshdr_t *StObjhdr; int unlink_ok; for(i = 0; i < stobj_numfiles; i++) { if(stobj_file[i].fd < 0) continue; unlink_ok = BOOL_TRUE; StObjhdr = (invt_seshdr_t *)( stobj_file[i].mapaddr + sizeof(invt_sescounter_t)); for(j = 0; j < stobj_file[i].counter->ic_curnum; ) { if(StObjhdr->sh_pruned != 1) { unlink_ok = BOOL_FALSE; break; } j++; StObjhdr = (invt_seshdr_t *)( stobj_file[i].mapaddr + sizeof(invt_sescounter_t) + (j * sizeof(invt_seshdr_t)) ); } close_stobj_file(i, unlink_ok); } free(stobj_file); stobj_file = NULL; return 0; } xfsdump-3.1.6+nmu1/config.guess0000755000000000000000000012355012607344145013305 0ustar #! /bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2014 Free Software Foundation, Inc. timestamp='2014-03-23' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # # Originally written by Per Bothner. # # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD # # Please send patches with a ChangeLog entry to config-patches@gnu.org. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright 1992-2014 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case "${UNAME_SYSTEM}" in Linux|GNU|GNU/*) # If the system lacks a compiler, then just pick glibc. # We could probably try harder. LIBC=gnu eval $set_cc_for_build cat <<-EOF > $dummy.c #include #if defined(__UCLIBC__) LIBC=uclibc #elif defined(__dietlibc__) LIBC=dietlibc #else LIBC=gnu #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` ;; esac # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; *:SolidBSD:*:*) echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE="alpha" ;; "EV4.5 (21064)") UNAME_MACHINE="alpha" ;; "LCA4 (21066/21068)") UNAME_MACHINE="alpha" ;; "EV5 (21164)") UNAME_MACHINE="alphaev5" ;; "EV5.6 (21164A)") UNAME_MACHINE="alphaev56" ;; "EV5.6 (21164PC)") UNAME_MACHINE="alphapca56" ;; "EV5.7 (21164PC)") UNAME_MACHINE="alphapca57" ;; "EV6 (21264)") UNAME_MACHINE="alphaev6" ;; "EV6.7 (21264A)") UNAME_MACHINE="alphaev67" ;; "EV6.8CB (21264C)") UNAME_MACHINE="alphaev68" ;; "EV6.8AL (21264B)") UNAME_MACHINE="alphaev68" ;; "EV6.8CX (21264D)") UNAME_MACHINE="alphaev68" ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE="alphaev69" ;; "EV7 (21364)") UNAME_MACHINE="alphaev7" ;; "EV7.9 (21364A)") UNAME_MACHINE="alphaev79" ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) echo i386-pc-auroraux${UNAME_RELEASE} exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) eval $set_cc_for_build SUN_ARCH="i386" # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH="x86_64" fi fi echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`$dummy $dummyarg` && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = "hppa2.0w" ] then eval $set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH="hppa2.0w" else HP_ARCH="hppa64" fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case ${UNAME_PROCESSOR} in amd64) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; *:MINGW64*:*) echo ${UNAME_MACHINE}-pc-mingw64 exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; *:MSYS*:*) echo ${UNAME_MACHINE}-pc-msys exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; *:Interix*:*) case ${UNAME_MACHINE} in x86) echo i586-pc-interix${UNAME_RELEASE} exit ;; authenticamd | genuineintel | EM64T) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; IA64) echo ia64-unknown-interix${UNAME_RELEASE} exit ;; esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; 8664:Windows_NT:*) echo x86_64-pc-mks exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; aarch64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC="gnulibc1" ; fi echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arc:Linux:*:* | arceb:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arm*:Linux:*:*) eval $set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then echo ${UNAME_MACHINE}-unknown-linux-${LIBC} else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi else echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf fi fi exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; cris:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; crisv32:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; frv:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; hexagon:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:Linux:*:*) echo ${UNAME_MACHINE}-pc-linux-${LIBC} exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; mips:Linux:*:* | mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=${UNAME_MACHINE}el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=${UNAME_MACHINE} #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } ;; openrisc*:Linux:*:*) echo or1k-unknown-linux-${LIBC} exit ;; or32:Linux:*:* | or1k*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; padre:Linux:*:*) echo sparc-unknown-linux-${LIBC} exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-${LIBC} exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; *) echo hppa-unknown-linux-${LIBC} ;; esac exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-${LIBC} exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-${LIBC} exit ;; ppc64le:Linux:*:*) echo powerpc64le-unknown-linux-${LIBC} exit ;; ppcle:Linux:*:*) echo powerpcle-unknown-linux-${LIBC} exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux-${LIBC} exit ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; tile*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-${LIBC} exit ;; x86_64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configury will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo ${UNAME_MACHINE}-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; x86_64:Haiku:*:*) echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux${UNAME_RELEASE} exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux${UNAME_RELEASE} exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown eval $set_cc_for_build if test "$UNAME_PROCESSOR" = unknown ; then UNAME_PROCESSOR=powerpc fi if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in i386) UNAME_PROCESSOR=x86_64 ;; powerpc) UNAME_PROCESSOR=powerpc64 ;; esac fi fi elif test "$UNAME_PROCESSOR" = i386 ; then # Avoid executing cc on OS X 10.9, as it ships with a stub # that puts up a graphical alert prompting to install # developer tools. Any system running Mac OS X 10.7 or # later (Darwin 11 and later) is required to have a 64-bit # processor. This is not true of the ARM version of Darwin # that Apple uses in portable devices. UNAME_PROCESSOR=x86_64 fi echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NEO-?:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk${UNAME_RELEASE} exit ;; NSE-*:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; i*86:AROS:*:*) echo ${UNAME_MACHINE}-pc-aros exit ;; x86_64:VMkernel:*:*) echo ${UNAME_MACHINE}-unknown-esx exit ;; esac cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: xfsdump-3.1.6+nmu1/common/0000755000000000000000000000000012620476226012250 5ustar xfsdump-3.1.6+nmu1/common/media.c0000644000000000000000000001665612620476160013506 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include "config.h" #include "types.h" #include "util.h" #include "mlog.h" #include "getopt.h" #include "stream.h" #include "global.h" #include "drive.h" #include "media.h" /* media.c - selects and initializes a media strategy */ /* declarations of externally defined global symbols *************************/ extern void usage( void ); /* declare all media strategies here */ extern media_strategy_t media_strategy_simple; extern media_strategy_t media_strategy_rmvtape; /* forward declarations of locally defined static functions ******************/ static media_t *media_alloc( drive_t *, char * ); /* definition of locally defined global variables ****************************/ /* definition of locally defined static variables *****************************/ /* media strategy array - ordered by precedence */ static media_strategy_t *strategyp[] = { &media_strategy_simple, &media_strategy_rmvtape, }; /* definition of locally defined global functions ****************************/ /* media_create - select and initialize a media strategy. * and create and initialize media managers for each stream. */ media_strategy_t * media_create( int argc, char *argv[ ], drive_strategy_t *dsp ) { int c; size_t mediaix; size_t mediacnt; media_t **mediapp; char *medialabel; media_strategy_t **spp = strategyp; media_strategy_t **epp = strategyp + sizeof( strategyp ) / sizeof( strategyp[ 0 ] ); media_strategy_t *chosen_sp; int id; bool_t ok; /* sanity check asserts */ assert( sizeof( media_hdr_t ) == MEDIA_HDR_SZ ); assert( MEDIA_MARKLOG_SZ == sizeof( media_marklog_t )); /* scan the command line for a media label */ medialabel = 0; optind = 1; opterr = 0; while ( ( c = getopt( argc, argv, GETOPT_CMDSTRING )) != EOF ) { switch ( c ) { #ifdef DUMP case GETOPT_MEDIALABEL: if ( medialabel ) { mlog( MLOG_NORMAL, _("too many -%c arguments: " "\"-%c %s\" already given\n"), c, c, medialabel ); usage( ); return 0; } if ( ! optarg || optarg[ 0 ] == '-' ) { mlog( MLOG_NORMAL, _("-%c argument missing\n"), c ); usage( ); return 0; } medialabel = optarg; break; #endif /* DUMP */ } } /* if no media label specified, synthesize one */ if ( ! medialabel ) { /* not useful mlog( MLOG_VERBOSE, _("WARNING: no media label specified\n") ); */ medialabel = ""; } /* create a media_t array, and a media_ts for each drive. * Initialize each media_t's generic portions. these will * be lended to each media strategy during the strategy * match phase, and given to the winning strategy. */ mediacnt = dsp->ds_drivecnt; mediapp = ( media_t ** )calloc( mediacnt, sizeof( media_t * )); assert( mediapp ); for ( mediaix = 0 ; mediaix < mediacnt ; mediaix++ ) { mediapp[ mediaix ] = media_alloc( dsp->ds_drivep[ mediaix ], medialabel ); } /* choose the first strategy which claims appropriateness. * if none match, return null. Also, initialize the strategy ID * and pointer to the drive strategy. the ID is simply the index * of the strategy in the strategy array. it is placed in the * media_strategy_t as well as the write headers. */ chosen_sp = 0; for ( id = 0 ; spp < epp ; spp++, id++ ) { (*spp)->ms_id = id; if ( ! chosen_sp ) { /* lend the media_t array to the strategy */ (*spp)->ms_mediap = mediapp; (*spp)->ms_dsp = dsp; (*spp)->ms_mediacnt = mediacnt; for ( mediaix = 0 ; mediaix < mediacnt ; mediaix++ ) { media_t *mediap = mediapp[ mediaix ]; mediap->m_strategyp = *spp; mediap->m_writehdrp->mh_strategyid = id; } if ( ( * (*spp)->ms_match )( argc, argv, dsp )) { chosen_sp = *spp; } } } if ( ! chosen_sp ) { mlog( MLOG_NORMAL, #ifdef DUMP _("no media strategy available for selected " "dump destination(s)\n") #endif /* DUMP */ #ifdef RESTORE _("no media strategy available for selected " "restore source(s)\n") #endif /* RESTORE */ ); usage( ); return 0; } /* give the media_t array to the chosen strategy */ for ( mediaix = 0 ; mediaix < mediacnt ; mediaix++ ) { media_t *mediap = mediapp[ mediaix ]; mediap->m_strategyp = chosen_sp; mediap->m_writehdrp->mh_strategyid = chosen_sp->ms_id; } /* initialize the strategy. this will cause each of the managers * to be initialized as well. if error, return 0. */ ok = ( * chosen_sp->ms_create )( chosen_sp, argc, argv ); if ( ! ok ) { return 0; } /* return the selected strategy */ return chosen_sp; } bool_t media_init( media_strategy_t *msp, int argc, char *argv[] ) { bool_t ok; ok = ( * msp->ms_init )( msp, argc, argv ); return ok; } void media_complete( media_strategy_t *msp ) { ( * msp->ms_complete )( msp ); } /* media_get_upper_hdrs - supply pointers to portion of media file headers * set aside for upper software layers, as well as to the global hdrs */ void media_get_upper_hdrs( media_t *mediap, global_hdr_t **grhdrpp, char **rhdrpp, size_t *rhdrszp, global_hdr_t **gwhdrpp, char **whdrpp, size_t *whdrszp ) { *grhdrpp = mediap->m_greadhdrp; *rhdrpp = mediap->m_readhdrp->mh_upper; *rhdrszp = sizeof( mediap->m_readhdrp->mh_upper ); *gwhdrpp = mediap->m_gwritehdrp; *whdrpp = mediap->m_writehdrp->mh_upper; *whdrszp = sizeof( mediap->m_writehdrp->mh_upper ); } /* definition of locally defined static functions ****************************/ /* media_alloc - allocate and initialize the generic portions of a media * descriptor and read and write media headers */ static media_t * media_alloc( drive_t *drivep, char *medialabel ) { media_t *mediap; global_hdr_t *grhdrp; global_hdr_t *gwhdrp; media_hdr_t *mrhdrp; media_hdr_t *mwhdrp; size_t mrhdrsz; size_t mwhdrsz; mediap = ( media_t * )calloc( 1, sizeof( media_t )); assert( mediap ); grhdrp = 0; gwhdrp = 0; mrhdrp = 0; mwhdrp = 0; drive_get_upper_hdrs( drivep, &grhdrp, ( char ** )&mrhdrp, &mrhdrsz, &gwhdrp, ( char ** )&mwhdrp, &mwhdrsz ); assert( grhdrp ); assert( gwhdrp ); assert( mrhdrp ); assert( mwhdrp ); assert( mrhdrsz == MEDIA_HDR_SZ ); assert( mwhdrsz == MEDIA_HDR_SZ ); mediap->m_greadhdrp = grhdrp; mediap->m_gwritehdrp = gwhdrp; mediap->m_readhdrp = mrhdrp; mediap->m_writehdrp = mwhdrp; mediap->m_drivep = drivep; strncpyterm( mwhdrp->mh_medialabel, medialabel, sizeof( mwhdrp->mh_medialabel )); #ifdef DUMP uuid_create( mwhdrp->mh_mediaid ); #else /* DUMP */ uuid_clear( mwhdrp->mh_mediaid ); #endif /* DUMP */ return mediap; } xfsdump-3.1.6+nmu1/common/drive.h0000644000000000000000000006436212620476160013542 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef DRIVE_H #define DRIVE_H /* drive.[hc] - drive abstraction * * drive_t provides a framework for device-independent drive abstraction, * as well as initialization of appropriate drive handlers. * * A drive_t is a drive manager providing capabilities for reading, writing, * and manipulating media objects (e.g., tape cartridges). * * All writing and reading is done within the scope of a media file. Writes * may be cut short due to media events (e.g., EOM). The mark * mechanism allows the caller to determine what portion of the write data * stream is guaranteed to have been committed to media. * * Marks may be placed in the stream during writes. During subsequent * reads of the data stream, the media object may be positioned at a * specific mark, or to the next mark in the stream. * * To accomodate end-of-media uncertainty, the marks are set in two steps. * First the caller asks to set a mark at a position within the write stream, * providing a callback function. The callback will be invoked when the data * prior to that mark has been committed to media. * * The caller must re-position the media (e.g., change media objects or * begin a new media file) and re-write any portion of the data written * after the last committed mark. It is entirely possible for part of that * data to have made it onto the previous media file, due to the uncertainty * of end-of-media handling of some drives. Thus the caller must be prepared * for portions of data read from the end of one media file to be duplicated * at the beginning of the next media file. * * To allow repositioning the stream in the above scenarios, * drive_t supplies forward-space-file, backward-space-file, rewind, * seek_mark, and get_mark operators. * * A call to the end_read or end_write operator virtually positions the * media at the beginning of the next media file. Thus if a caller calls * begin read, looks at the header and decides to overwrite the media * file, a call to the bsf operator must be made prior to the call to * begin_write. However, if the media is positioned at EOD and the caller calls * begin_read, EOD will be returned and no repositioning is needed. A call * to begin_write will append a new media file after the last media file. * * Drive_init1 selects and instantiates a drive manager for each drive * identified on the command line. This is done by showing the drive * successively to each drive strategy module. The drive strategies * supply a match score. The strategy with the highest score gets to * instantiate a drive manager for that drive. * * Drive_init2 allocates and initializes read and write header buffers for * each drive, and calls each drive manager's init operator, which begins async * initialization of the drive. This includes determining if a media object * is currently mounted in that drive. * * Drive_init3 synchronizes with the async initializations kicked off by * drive_init2. * * Each drive strategy is defined by a drive_strategy_t. This supplies * a match function, and an instantiate function. * * The match function lets the given strategy determine if it is the correct * strategy to choose. The instantiate function creates a driver manager. * * The I/O write model presents the user with a function to get a write buffer, * or get a page-aligned write buffer, and a function to take back the buffer * and commit part or all of that buffer to media. The read model is similar; * the caller may ask for a buffer filled with read data, and gives the buffer * back after the data is used. These models facilitate high-performance * operation, since the buffers can be used in direct I/O. */ /* drive_hdr_t - drive media file header * * A drive media file header is imbedded in the global media file header * structure, which is in turn placed at the beginning of each media file. The * drive hdr has three parts: generally useful drive-related info, info * specific to the selected drive strategy, and upper layer info. Each drive * handler contains two drive header images; a read hdr and a write hdr. * * CAUTION! the various components of the media file header are carefully * crafted to fit in DRIVE_HDR_SZ bytes. */ #define DRIVE_HDR_SZ sizeofmember( global_hdr_t, gh_upper ) struct drive_hdr { uint32_t dh_drivecnt; /* 4 4 */ /* number of drives used to dump the fs */ uint32_t dh_driveix; /* 4 8 */ /* 0-based index of the drive used to dump this stream */ int32_t dh_strategyid; /* 4 c */ /* ID of the drive strategy used to produce this dump */ char dh_pad1[ 0x1f4 ]; /* 1f4 200 */ /* padding */ char dh_specific[ 0x200 ]; /* 200 400 */ /* drive strategy-specific info */ char dh_upper[ DRIVE_HDR_SZ - 0x400 ]; /* 800 c00 */ /* header info private to upper software layers */ }; typedef struct drive_hdr drive_hdr_t; /* drive_strategy_t - drive strategy * * The drive strategy has two operators, ds_match() and ds_instantiate(). * ds_match() returns an integer indicating the degree of match of the * strategy to the drives indicated on the command line. ds_init() * initializes the drive strategy, creates and initializes a drive manager * for each drive, and if possible positions each drive at the beginning of * the current file and reads the file header into d_readhdr. ds_drivep * points to an array of drive managers, and ds_drivecnt indicates * the length of that array. */ struct drive; /* forward declaration */ struct drive_strategy { int ds_id; /* strategy ID */ char *ds_description; /* a short char string describing strategy */ int ( * ds_match )( int argc, char *argv[ ], struct drive *drivep ); /* returns degree of match. drivep has been pre-allocated * and initialized with generic info. */ bool_t ( * ds_instantiate )( int argc, char *argv[ ], struct drive *drivep ); /* creates a drive manager instance, by filling in the * blanks of the pre-allocated drive descriptor * returns FALSE on failure. */ off64_t ds_recmarksep; /* recommended maximum separation (in bytes) * between marks. can be observed when sending * long data streams to the drive. this field is * transfered to d_recmarksep during instantiation. */ off64_t ds_recmfilesz; /* recommended maximum length of media files. * transfered to d_recmarksep during instantiation. */ }; typedef struct drive_strategy drive_strategy_t; /* definitions of strategy ids */ #define DRIVE_STRATEGY_SCSITAPE 0 #define DRIVE_STRATEGY_SIMPLE 1 #define DRIVE_STRATEGY_RMT 0 /* same as SCSITAPE for now */ /* drive_mark_t - token identifying a mark within a media object file * * 64 bit cookie, the structure of which is known only to the drive manager * which generated it. generated by do_get_mark, given to do_seek_mark. */ typedef off64_t drive_mark_t; /* drive mark callback function * invoked for each mark registered with do_set_mark, in the same order. * committed is TRUE if the data up to the mark was committed to media. * committed is FALSE if it is POSSIBLE that some data prior to the mark * was NOT committed. */ struct drive_markrec; /* forward decl */ typedef void ( * drive_mcbfp_t )( void *context_t, struct drive_markrec *markrecp, bool_t committed ); /* drive_markrec_t - context for set mark callback function * * caller allocates and passes ptr to do_set_mark, along with a callback func. * callback returns the record, which must be freed by the original caller. * */ struct drive_markrec { drive_mark_t dm_log; /* identifies position within mfile */ drive_mcbfp_t dm_cbfuncp; /* caller's callback function */ void *dm_cbcontextp; /* caller's context */ struct drive_markrec *dm_nextp; /* for linked list */ }; typedef struct drive_markrec drive_markrec_t; /* drive_t - drive manager * * A drive manager is described by a set of generic parameters * and operators. */ struct drive_ops; /* forward declaration */ struct drive { drive_strategy_t *d_strategyp; /* back ptr to strategy */ struct drive_ops *d_opsp; /* pointer to drive operations */ void *d_contextp; /* manager-specific data */ void *d_strmcontextp; /* stream-specific data */ global_hdr_t *d_greadhdrp; /* global portion of media file header of * media file drive currently positioned. */ drive_hdr_t *d_readhdrp; /* drive portion of media file header of * media file drive currently positioned. */ global_hdr_t *d_gwritehdrp; /* global portion of media file header to * be written by the next begin_write op. */ drive_hdr_t *d_writehdrp; /* drive portion of media file header to * be written by the next begin_write op. */ char *d_pathname; /* e.g., /dev/tape */ ix_t d_index; /* e.g., 0, 1, 2, ... */ bool_t d_isnamedpipepr; /* is a named pipe */ bool_t d_isunnamedpipepr;/* is an unnamed pipe */ int d_capabilities;/* see DRIVE_CAP_xxx below */ off64_t d_cap_est; /* capacity estimate in bytes; -1 if unknown */ int d_rate_est; /* bytes per second; -1 if unknown */ drive_markrec_t *d_markrecheadp; /* linked list of mark records */ drive_markrec_t *d_markrectailp; /* yet to be committed */ off64_t d_recmarksep; /* transfered from strategy on instantiation */ off64_t d_recmfilesz; /* transfered from strategy on instantiation */ }; typedef struct drive drive_t; struct drive_ops { bool_t ( * do_init )( drive_t *drivep ); /* initializes drive, and begins async * determination of media object presence * returns FALSE if session should be aborted. */ bool_t ( * do_sync )( drive_t *drivep ); /* synchronizes with the activity kicked off * by do_init. returns FALSE if session should * be aborted. */ int ( * do_begin_read )( drive_t *drivep ); /* prepares the drive manager for reading. * if the media is positioned at BOM or just * after a file mark, current media file is * begun. Otherwise, the drive will advance * media to just after the next file mark first. * loads the read header buffer with the * header at the beginning of the media file. * return value will be set non zero: * BLANK - blank tape, positioned * at BOT and ready for a * do_begin_write; * FOREIGN - unrecognized data at * BOT, positioned * at BOT and ready for a * do_begin_write; * EOD - tried to read past end of * recorded data; * EOM - tried to read past end of media * object; * MEDIA - no media object in drive; * FORMAT - unrecognized media file header; * VERSION - unsupported media file header; * CORRUPTION - encountered corrupt data * at beginning of media file; * DEVICE - drive hardware error, other * than missing media; * INVAL - operator error; * CORE - driver wants core dump; * STOP - upper level asked lengthy * drive op to give up. * OVERWRITE - overwrite option to dump * specified by user. Assume tape * positioned and ready for write. * if not successful (non-zero return), caller * must NOT call end_read prior to next * begin_read. if successful, caller MUST call * end_read prior to next begin_read. */ char * ( * do_read )( drive_t *drivep, size_t wanted_bufsz, size_t *actual_bufszp, int *statp ); /* asks the drive manager for a buffered filled * with the next read stream data. * the actual buffer size supplied may * be shorter than requested; it will never * be longer than requested. the buffer * should be returned to the drive manager as * soon as possible, to facilitate drive * streaming. the actual buffer size may * be short due to the internal buffering * mechanism, or due to media events; in * the latter case, *statp will explain why: * EOD - tried to read past end of * recorded data; this is semant- * ically equiv. to EOF, but * occurs on last media file only. * EOF - hit end of media file prior * to completing read; probably * due to a write fail during dump, * or were near end of tape (e.g., * early warning). * EOM - tried to read past end of media * object; * MEDIA - no media object in drive; * CORRUPTION - encountered corrupt data; * DEVICE - drive hardware error, other * than missing media; * CORE - driver wants core dump; * in all cases, the buffer returned contains * valid data (although the buffer size may * be zero!). */ void ( * do_return_read_buf )( drive_t *drivep, char *bufp, size_t bufsz ); /* returns the buffer obtained * from the previous do_read() call. * the entire buffer must be returned * in one shot. */ void ( * do_get_mark )( drive_t *drivep, drive_mark_t *drivemarkp ); /* returns (by reference) a mark corresponding * to the next byte which will be read by a * call to do_read(). will be used in a later * session to seek to that position. */ int ( * do_seek_mark )( drive_t *drivep, drive_mark_t *drivemarkp ); /* searches for the specified mark within the * current file. returns zero if the mark * was found, or an error explaining why not: * EOF - end of file was encountered; * EOD - end of recorded date encountered; * EOM - end of media encountered; * CORRUPTION - encountered corrupt data; * DEVICE - device error; */ int ( * do_next_mark )( drive_t *drivep ); /* if d_capabilities has DRIVE_CAP_NEXTMARK set, * drive has the capability to * seek forward to the next mark. returns * zero if a mark was found, or an error code: * EOF - end of file was encountered; * EOD - end of recorded date encountered; * EOM - end of media encountered; * DEVICE - device error; * if currently at a mark, will go to the next. */ void ( *do_end_read )( drive_t *drivep ); /* ends the file read. must be called prior * to beginning another read or write session. * ensures that the next call to begin_read * will position the media at the next media * file. */ int ( * do_begin_write )( drive_t *drivep ); /* begins a write media file for writing. * asserts the media is positioned at BOM or * just after a file mark. write header will * be placed at the head of the file. * same return codes as do_write(): * EOM - end of media object encountered; * MEDIA - media object missing or broken; * DEVICE - device error; * CORE - driver error */ void ( * do_set_mark )( drive_t *drivep, drive_mcbfp_t cbfuncp, void *cbcontextp, drive_markrec_t *markrecp ); /* marks the position in the write stream * where the next write will occur. * At the time the data written * prior to the mark is committed to media, * the callback will be invoked, with * the context and markrec pointers. The caller * append his mark context to the drive markrec * buffer pointed to by markrecp. the drive * manager will use the drive_markrec_t * to track the progress of the mark. * If EOM is encountered before the * mark is committed to media, the mark * callback for all uncommitted marks will * be called, but with the committed flag * set to FALSE. it is up to the * caller to free the mark buffers he previously * allocated. note the drive strategy member * d_recmarksep, the recommended maximum * separation between marks. This is a hint * based on underlying drive characteristics. * the caller should record the committed * marks; when do_write() fails due to * EOM, the caller can resume writing after * last committed marked point in the write * stream. */ char * ( * do_get_write_buf )( drive_t *drivep, size_t wanted_bufsz, size_t *actual_bufszp ); /* asks the drive manager for a buffer. * returns a pointer to a buffer, and its * size. must call do_write() before * calling do_get_write_buf() again. By asking * the drive manager for a buffer, buffer * copying can be avoided. This facilitates * achieving streaming performance on tape * media. Also, the drive manager can implement * a double-buffering scheme, causing source * reads and drive writes to occur * simultaneously. note that the buffer can * be larger or smaller than the wanted bufsz, * but will be at least 1 byte in length. */ int ( * do_write )( drive_t *drivep, char *bufp, size_t bufsz ); /* asks the drive manager to write bufsz * bytes from the buffer, which was acquired * from a previous call to do_get_write_buf(). * returns the following status values: * EOM - end of media object encountered; * MEDIA - media object missing or broken; * DEVICE - device error; * CORE - driver error; * in the case of a non-zero return status, * the caller must refer to the last mark * callback received, to know the last data * guaranteed to have been committed to media. * any writes subsequent to the placement of * that mark may or may not be on media. * the caller should therefore be prepared * to see the same data twice when crossing * a media file boundary while reading. * note that no indication of the actual * number of bytes written is returned. * even if only part of the buffer * obtained from do_get_write_buf() * is used, the do_write() call returns the * entire buffer to the drive manager; it * is not available for subsequent writes. * instead, the caller must get another buffer * using do_get_write_buf(). */ size_t ( * do_get_align_cnt )( drive_t *drivep ); /* used during writing. returns the number * of bytes which should be written to * page-align the next do_get_write_buf() * call. NOTE: the caller can assume that * alignment will be maintained after the * initial alignment done using this info. */ int ( * do_end_write )( drive_t *drivep, off64_t *ncommittedp ); /* terminates a media file write sequence. * flushes any buffered data not yet committed * to media, and calls callbacks for all marks * not yet returned. just like do_write(), can * encounter EOM, in which case the * last affirmative mark callback received will * indicate what portion of the write data * stream may have not been committed to media. * EOM - end of media object encountered; * MEDIA - media object missing or broken; * DEVICE - device error; * returns by reference number of bytes * committed to media for the media file. * this is the number of bytes written to * media, which may be greater than what the * client wrote due to record padding. * NOTE: if last call to do_write returned * an error, do_end_write will not do any * I/O, and will return 0. */ int ( * do_fsf )( drive_t *drivep, int count, int *statp ); /* if d_capabilities has DRIVE_CAP_FSF set, * drive has the capability to * forward space count files. returns the * number of actual files forwarded to. for * example, if count is one, and there is a * file after the current file, positions to * the beginning of that file and returns 1. * if the current file is the last one on the * medium, returns 0, and leaves position at * the end of recorded data, after the file * mark. if there is a following file, * positions such that the next read will * retrieve the first data in that file. * furthermore, *statp will be set in the * following cases: * EOD - encountered end of recorded data * EOM - encountered end of media * DEVICE - device error; * NOTE: if media is positioned anywhere other * than at the beginning of a media file, * behaves as if position is at most recent * file mark or BOT. */ int ( * do_bsf )( drive_t *drivep, int count, int *statp ); /* if d_capabilities has DRIVE_CAP_BSF set, * drive has the capability to backward space * count files. returns the number of actual * files backed to. * can only be invoked when not reading or * writing (i.e., only after calling end_read * or end_write, or prior to calling begin_read * or begin_write). if count is zero, backs * up to the beginning of the last media file * read or written. if count is 1, backs up to * the media file preceeding that one. returns * the number of media files skipped. if * the current file is the first one on the * medium, returns 0, and leaves position * at the beginning of recorded data. if count * is one and there is a preceeding file, * positions such that the next read will * retrieve the first data in that file. * furthermore, *statp will be set in the * following cases: * BOM - hit beginning of recorded data; * DEVICE - device error; */ int ( * do_rewind )( drive_t *drivep ); /* if d_capabilities has DRIVE_CAP_REWIND set, * drive has the capability to * position at beginning of recorded data * DEVICE - device error; */ int ( * do_erase )( drive_t *drivep ); /* if d_capabilities has DRIVE_CAP_ERASE set, * drive has the capability to * erase: all content of media object is * eradicated. * DEVICE - device error; */ int ( * do_eject_media )( drive_t *drivep ); /* if d_capabilities has DRIVE_CAP_EJECT set, * drive has capability * to eject media, and will do so when called. * DEVICE - device error; */ int ( * do_get_device_class )( drive_t *drivep ); /* returns the media class of the device * (see below). */ void ( * do_display_metrics )( drive_t *drivep ); /* use BARE mlog to print useful throughput * and performance info. set to NULL if * nothing to say. */ void ( * do_quit )( drive_t * drivep ); /* tells the drive manager to de-allocate * resources, INCLUDING the slave process. */ }; typedef struct drive_ops drive_ops_t; /* the drive managers are visible globally, but should be accessed sparingly. * valid after drive_init1() returns successfully */ extern drive_t **drivepp; extern size_t drivecnt; extern size_t partialmax; /* drive capabilities - bit positions in the capabilities mask * DO NOT CHANGE: used in dh_capabilities field of scsi drive hdr. */ #define DRIVE_CAP_BSF ( 1 << 0 ) /* can backspace files */ #define DRIVE_CAP_FSF ( 1 << 1 ) /* can forwardspace files */ #define DRIVE_CAP_REWIND ( 1 << 2 ) /* can rewind */ #define DRIVE_CAP_FILES ( 1 << 4 ) /* supports multiple files */ #define DRIVE_CAP_APPEND ( 1 << 5 ) /* can append to end of rec. data */ #define DRIVE_CAP_OVERWRITE ( 1 << 6 ) /* can overwrite recorded data */ #define DRIVE_CAP_ERASE ( 1 << 6 ) /* can erase media */ #define DRIVE_CAP_NEXTMARK ( 1 << 8 ) /* can seek to a next good mark */ #define DRIVE_CAP_EJECT ( 1 << 12 ) /* can eject media */ #define DRIVE_CAP_AUTOREWIND ( 1 << 13 ) /* rewinds on media insertion */ #define DRIVE_CAP_READ ( 1 << 14 ) /* can read media */ #define DRIVE_CAP_REMOVABLE ( 1 << 15 ) /* can change media */ /* drive manager error codes - interpretation specific to and described * in context of use. */ #define DRIVE_ERROR_CORRUPTION 1 #define DRIVE_ERROR_EOF 2 #define DRIVE_ERROR_EOD 3 #define DRIVE_ERROR_EOM 4 #define DRIVE_ERROR_BOM 5 #define DRIVE_ERROR_DEVICE 6 #define DRIVE_ERROR_FORMAT 7 #define DRIVE_ERROR_MEDIA 8 #define DRIVE_ERROR_VERSION 9 #define DRIVE_ERROR_CORE 10 #define DRIVE_ERROR_TIMEOUT 11 #define DRIVE_ERROR_STOP 12 #define DRIVE_ERROR_INVAL 13 #define DRIVE_ERROR_BLANK 14 #define DRIVE_ERROR_FOREIGN 15 #define DRIVE_ERROR_OVERWRITE 16 /* drive_init1 - select and instantiate a drive manager for each drive * specified on the command line. * * Highly heuristic, using all avalable sources of information, including * the command line (command name and parameters), experimentation, and * drive-specific media functions, but excluding time-consuming operations * such as tape motion. * * sets globals drivepp and drivecnt. * * Returns FALSE if utility should be aborted. */ extern bool_t drive_init1( int argc, char *argv[] ); /* drive_init2 - allocate and initialize read and write hdr buffers, * and cause each drive manager to asynchronously determine if * drive has media object mounted. * * Returns FALSE if the session should be aborted. */ extern bool_t drive_init2( int argc, char *argv[], global_hdr_t *gwhdrtemplatep ); /* drive_init3 - synchronize with async activity kicked off by drive_init3. * * Returns FALSE if the session should be aborted. */ extern bool_t drive_init3( void ); /* drive_mark_commit - invokes callback for all drive marks committed * to media. ncommitted is the number of bytes actually committed to * media so far. mark records with a mark offset less than or equal to * ncommitted will have their callbacks invoked. */ extern void drive_mark_commit( drive_t *drivep, off64_t ncommitted ); /* drive_mark_discard - invokes callback of all uncommitted marks, * indicating the commit did not occur. */ extern void drive_mark_discard( drive_t *drivep ); /* drive_display_metrics - display drive throughput and streaming metrics * for all drives */ extern void drive_display_metrics( void ); /* device classes * used for determining which media driver to employ */ #define DEVICE_NONREMOVABLE 1 #define DEVICE_TAPE_REMOVABLE 2 #define DEVICE_DISK_REMOVABLE 3 #endif /* DRIVE_H */ xfsdump-3.1.6+nmu1/common/fs.h0000644000000000000000000000402512620476160013027 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef FS_H #define FS_H /* fs - utilities for examining and manipulating file systems */ /* default maximum path and name lengths */ #define FS_MAXNAMELEN_DEFAULT 256 #define FS_MAXPATHLEN_DEFAULT 1024 /* fs_info - decides if a source name describes a file system, and if * so returns useful information about that file system. * * returns BOOL_FALSE if srcname does not describe a file system. */ extern bool_t fs_info( char *fstype, /* out: fs type (fsid.h) */ int fstypesz, /* in: buffer size */ char *fstypedef, /* in: default fs type */ char *fsdevice, /* out: blk spec. dev. file */ int fsdevicesz, /* in: buffer size */ char *mntpt, /* out: where fs mounted */ int mntptsz, /* in: buffer size */ uuid_t *fsid, /* out: fs uuid */ char *srcname ); /* in: how user named the fs */ /* fs_mounted - checks if a file system is mounted at its mount point */ extern bool_t fs_mounted( char *fstype, char *fsdevice, char *mntpt, uuid_t *fsid ); /* fs_getid - retrieves the uuid of the file system containing the named * file. returns -1 with errno set on error. */ extern int fs_getid( char *fullpathname, uuid_t *fsidp ); /* tells how many inos in use */ extern size_t fs_getinocnt( char *mnts ); #endif /* FS_H */ xfsdump-3.1.6+nmu1/common/drive_scsitape.c0000644000000000000000000042061012620476160015420 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "types.h" #include "qlock.h" #include "cldmgr.h" #include "mlog.h" #include "dlog.h" #include "global.h" #include "drive.h" #include "media.h" #include "getopt.h" #include "stream.h" #include "ring.h" #include "rec_hdr.h" #include "arch_xlate.h" #include "ts_mtio.h" /* drive_scsitape.c - drive strategy for all scsi tape devices */ /* structure definitions used locally ****************************************/ /* remote tape protocol debug */ #ifdef RMTDBG #define open(p,f) dbgrmtopen(p,f) #define close(fd) dbgrmtclose(fd) #define ioctl(fd,op,arg) dbgrmtioctl(fd,op,arg) #define read(fd,p,sz) dbgrmtread(fd,p,sz) #define write(fd,p,sz) dbgrmtwrite(fd,p,sz) #else /* RMTDBG */ #define open rmtopen #define close rmtclose #define ioctl rmtioctl #define read rmtread #define write rmtwrite #endif /* RMTDBG */ /* if the media file header structure changes, this number must be * bumped, and STAPE_VERSION_1 must be defined and recognized. */ #define STAPE_VERSION 1 /* a bizarre number to help reduce the odds of mistaking random data * for a media file or record header */ #define STAPE_MAGIC 0x13579bdf02468acell /* this much of each record is reserved for header info: the user * data always begins at this offset from the beginning of each * record. be sure global_hdr_t fits. */ #define STAPE_HDR_SZ PGSZ /* maximum tape record size. this is the max size of I/O buffers sent to drive. * note that for variable block devices this determines the block size as well. */ #define STAPE_MAX_RECSZ 0x200000 /* 2Mb */ /* this is the smallest maximum block size for any tape device * supported by xfsdump/xfsrestore. we use this when it is not possible * to ask the driver for block size info. * i.e. we use this in the remote case. */ #define STAPE_MIN_MAX_BLKSZ 0x3c000 /* 240K, 245760 */ /* On linux, not all kernels can handle block sizes of 2Mb * so we use a reduced amount. */ #define STAPE_MAX_LINUX_RECSZ 0x100000 /* QIC tapes always use 512 byte blocks */ #define QIC_BLKSZ 512 /* number of record buffers in the I/O ring */ #define RINGLEN_MIN 1 #define RINGLEN_MAX 10 #define RINGLEN_DEFAULT 3 /* tape i/o request retry limit */ #define MTOP_TRIES_MAX 10 /* operational mode. can be reading or writing, but not both */ typedef enum { OM_NONE, OM_READ, OM_WRITE } om_t; /* drive_context - control state * * NOTE: ring used only if not singlethreaded */ struct drive_context { om_t dc_mode; /* current mode of operation (READ or WRITE) */ size_t dc_ringlen; /* number of tape_recsz buffers in ring. only used * for displaying ring info */ bool_t dc_ringpinnedpr; /* are the ring buffers pinned down */ ring_t *dc_ringp; /* handle to ring */ ring_msg_t *dc_msgp; /* currently held ring message */ char *dc_bufp; /* pre-allocated record buffer (only if ring not used) */ char *dc_recp; /* pointer to current record buffer. once the current * record is completely read or written by client, * set to NULL. */ char *dc_recendp; /* always set to point to just off the end of the * current record buffer pointed to by dc_recp. valid * only when dc_recp non-NULL. */ char *dc_dataendp; /* same as dc_recendp, except for first and last * records in media file. the first record is all * pads after the header page. the last record may * have been padded (as indicated by the rec_used * field of the record header). in either case * dc_dataendp points to first padding byte. */ char *dc_ownedp; /* first byte in current buffer owned by caller. * given to caller by do_read or do_get_write_buf * set to null by do_return_read_buf or do_write. */ char *dc_nextp; /* next byte available in current buffer to give * to do_get_write_buf for writing or do_read for * reading. */ off64_t dc_reccnt; /* count of the number of records completely read or * written by client, and therefore not represented * by current dc_recp. valid initially and after * each call to do_return_read_buf or do_write. * NOT valid after a call to do_read or * do_get_write_buf. always bumped regardless of * read or write error status. */ off64_t dc_iocnt; /* count of the number of records read or written * to media without error. includes media file header * record. this is incremented when the actual I/O is * done. dc_reccnt is different, indicating what has * been seen by client. slave may have read ahead / * written behind. */ int dc_fd; /* drive file descriptor. -1 when not open */ bool_t dc_isrmtpr; /* TRUE if drive being accessed via RMT */ bool_t dc_isvarpr; /* TRUE if variable block size device */ bool_t dc_cangetblkszpr; /* TRUE if can get blksz info from driver */ bool_t dc_cansetblkszpr; /* TRUE if can set blksz info to driver */ size_t dc_maxblksz; /* maximum block size. */ size_t dc_origcurblksz; /* Save original curblksz to restore on quit. */ bool_t dc_isQICpr; /* fixed 512 byte block size device. */ bool_t dc_canfsrpr; /* can seek forward records at a time */ size_t dc_blksz; /* actual tape blksize selected */ size_t dc_recsz; /* actual tape record size selected */ off64_t dc_lostrecmax; /* maximum number of records written without error * which may be lost due to a near end-of-tape * experience. a function of drive type and * compression */ bool_t dc_singlethreadedpr; /* single-threaded operation (no slave) */ bool_t dc_errorpr; /* TRUE if error encountered during reading or writing. * used to detect attempts to read or write after * error reported. */ bool_t dc_recchksumpr; /* TRUE if records should be checksumed */ bool_t dc_unloadokpr; /* ok to issue unload command when do_eject invoked. */ bool_t dc_overwritepr; /* overwrite tape without checking whats on it */ off64_t dc_filesz; /* file size given as argument */ }; typedef struct drive_context drive_context_t; /* macros for shortcut references to context. assumes a local variable named * 'contextp'. */ #define tape_recsz ( contextp->dc_recsz ) #define tape_blksz ( contextp->dc_blksz ) /* macros to interpret tape status information returned by reference from * mt_get_status( ). */ /* tape is positioned at end-of-tape */ #define IS_EOT(mtstat) GMT_EOT(mtstat) /* tape is positioned at beginning-of-tape */ #define IS_BOT(mtstat) GMT_BOT(mtstat) /* the tape is write protected */ #define IS_WPROT(mtstat) GMT_WR_PROT(mtstat) /* the tape drive is online */ #define IS_ONL(mtstat) GMT_ONLINE(mtstat) /* the tape is positioned at the end of user data */ #define IS_EOD(mtstat) GMT_EOD(mtstat) /* the tape is positioned at at file mark */ #define IS_FMK(mtstat) GMT_EOF(mtstat) /* tape is positioned at early warning */ /* not supported by linux tape drivers */ #define IS_EW(mtstat) (0) typedef long mtstat_t; /* declarations of externally defined global variables ***********************/ extern void usage( void ); #ifdef DUMP extern uint64_t hdr_mfilesz; #endif /* DUMP */ /* remote tape protocol declarations (should be a system header file) */ extern int rmtopen( char *, int, ... ); extern int rmtclose( int ); extern int rmtfstat( int, struct stat * ); extern int rmtioctl( int, int, ... ); extern int rmtread( int, void*, uint); extern int rmtwrite( int, const void *, uint); /* forward declarations of locally defined static functions ******************/ /* strategy functions */ static int ds_match( int, char *[], drive_t * ); static int ds_instantiate( int, char *[], drive_t * ); /* manager operations */ static bool_t do_init( drive_t * ); static bool_t do_sync( drive_t * ); static int do_begin_read( drive_t * ); static char *do_read( drive_t *, size_t , size_t *, int * ); static void do_return_read_buf( drive_t *, char *, size_t ); static void do_get_mark( drive_t *, drive_mark_t * ); static int do_seek_mark( drive_t *, drive_mark_t * ); static int do_next_mark( drive_t * ); static void do_get_mark( drive_t *, drive_mark_t * ); static void do_end_read( drive_t * ); static int do_begin_write( drive_t * ); static void do_set_mark( drive_t *, drive_mcbfp_t, void *, drive_markrec_t * ); static char * do_get_write_buf( drive_t *, size_t , size_t * ); static int do_write( drive_t *, char *, size_t ); static size_t do_get_align_cnt( drive_t * ); static int do_end_write( drive_t *, off64_t * ); static int do_fsf( drive_t *, int , int *); static int do_bsf( drive_t *, int , int *); static int do_rewind( drive_t * ); static int do_erase( drive_t * ); static int do_eject_media( drive_t * ); static int do_get_device_class( drive_t * ); static void do_display_metrics( drive_t *drivep ); static void do_quit( drive_t * ); /* misc. local utility funcs */ static int mt_op(int , int , int ); static int mt_blkinfo(int , struct mtblkinfo * ); static bool_t mt_get_fileno( drive_t *, long *); static bool_t mt_get_status( drive_t *, mtstat_t *); static int determine_write_error( drive_t *, int, int ); static int read_label( drive_t *); static bool_t tape_rec_checksum_check( drive_context_t *, char * ); static void set_recommended_sizes( drive_t * ); static void display_access_failed_message( drive_t *); static void status_failed_message( drive_t *); static bool_t get_tpcaps( drive_t * ); static bool_t set_fixed_blksz( drive_t *, size_t ); static int prepare_drive( drive_t *drivep ); static bool_t Open( drive_t *drivep ); static void Close( drive_t *drivep ); static int Read( drive_t *drivep, char *bufp, size_t cnt, int *errnop ); static int Write( drive_t *drivep, char *bufp, size_t cnt, int *saved_errnop ); static int quick_backup( drive_t *drivep, drive_context_t *contextp, ix_t skipcnt ); static int record_hdr_validate( drive_t *drivep, char *bufp, bool_t chkoffpr ); static int ring_read( void *clientctxp, char *bufp ); static int ring_write( void *clientctxp, char *bufp ); static double percent64( off64_t num, off64_t denom ); static int getrec( drive_t *drivep ); static int write_record( drive_t *drivep, char *bufp, bool_t chksumpr, bool_t xlatepr ); static ring_msg_t * Ring_get( ring_t *ringp ); static void Ring_reset( ring_t *ringp, ring_msg_t *msgp ); static void Ring_put( ring_t *ringp, ring_msg_t *msgp ); static int validate_media_file_hdr( drive_t *drivep ); static void calc_max_lost( drive_t *drivep ); static void display_ring_metrics( drive_t *drivep, int mlog_flags ); static mtstat_t rewind_and_verify( drive_t *drivep ); static mtstat_t erase_and_verify( drive_t *drivep ); static mtstat_t bsf_and_verify( drive_t *drivep ); static mtstat_t fsf_and_verify( drive_t *drivep ); static void calc_best_blk_and_rec_sz( drive_t *drivep ); static bool_t set_best_blk_and_rec_sz( drive_t *drivep ); static bool_t isefsdump( drive_t *drivep ); static int get_driver_character_major( const char * ); static void map_ts_status( struct mtget *, struct mtget_sgi ); /* RMT trace stubs */ #ifdef RMTDBG static int dbgrmtopen( char *, int ); static int dbgrmtclose( int ); static int dbgrmtioctl( int, int, void *); static int dbgrmtread( int, void*, uint); static int dbgrmtwrite( int, void *, uint); #endif /* RMTDBG */ /* definition of locally defined global variables ****************************/ /* tape driver */ int TS_ISDRIVER=0; /* scsitape drive strategy. referenced by drive.c */ drive_strategy_t drive_strategy_scsitape = { DRIVE_STRATEGY_SCSITAPE, /* ds_id */ "scsi tape (drive_scsitape)", /* ds_description */ ds_match, /* ds_match */ ds_instantiate, /* ds_instantiate */ 0x1000000ll, /* ds_recmarksep 16 MB */ OFF64MAX, /* ds_recmfilesz */ }; /* definition of locally defined static variables *****************************/ /* drive operators */ static drive_ops_t drive_ops = { do_init, /* do_init */ do_sync, /* do_sync */ do_begin_read, /* do_begin_read */ do_read, /* do_read */ do_return_read_buf, /* do_return_read_buf */ do_get_mark, /* do_get_mark */ do_seek_mark, /* do_seek_mark */ do_next_mark, /* do_next_mark */ do_end_read, /* do_end_read */ do_begin_write, /* do_begin_write */ do_set_mark, /* do_set_mark */ do_get_write_buf, /* do_get_write_buf */ do_write, /* do_write */ do_get_align_cnt, /* do_get_align_cnt */ do_end_write, /* do_end_write */ do_fsf, /* do_fsf */ do_bsf, /* do_bsf */ do_rewind, /* do_rewind */ do_erase, /* do_erase */ do_eject_media, /* do_eject_media */ do_get_device_class, /* do_get_device_class */ do_display_metrics, /* do_display_metrics */ do_quit, /* do_quit */ }; static uint32_t cmdlineblksize = 0; /* definition of locally defined global functions ****************************/ /* definition of locally defined static functions ****************************/ static bool_t is_scsi_driver(char *pathname) { char rp[PATH_MAX]; struct stat64 statbuf; int dev_major; if (realpath(pathname, rp) == NULL) { return BOOL_FALSE; } if ( stat64( pathname, &statbuf ) == -1) { return BOOL_FALSE; } if ( !S_ISCHR( statbuf.st_mode )) { return BOOL_FALSE; } /* In the past, this routine would look at the pathname of the * file to determine if we had a tape device or not. That method * worked fine for tape devices residing in one of the directories * in the list of 'valid' pathnames. However, that method did not * work for tape applications like TMF and OpenVault, which allow * the user the flexibility of creating tape deivces with pathnames * of their choice. * * In order to provide support for such applications, this routine * will now look at the major number of the character device to * determine whether we have a tape device or not. Major number * 9 is reserved for ST, while major numbers for TS and TMF are not * officially registered on Linux (and may be subject to change). * For this reason, we will call the get_driver_character_major() * routine to get the major numbers for TS and TMF (providing the * drivers are loaded). We will also look up the major number for * ST, for sanity and consistency. We can compare the major number * of the target device to the major number of each of the tape * drivers to determine 1) if we have a tape device, and 2) which * tape driver the device is using. */ dev_major = major(statbuf.st_rdev); if (dev_major == get_driver_character_major("st")) { return BOOL_TRUE; } else if (dev_major == get_driver_character_major("ts") || dev_major == get_driver_character_major("tmf")) { TS_ISDRIVER = 1; return BOOL_TRUE; } else { return BOOL_FALSE; } } /* strategy match - determines if this is the right strategy */ /* ARGSUSED */ static int ds_match( int argc, char *argv[], drive_t *drivep ) { struct mtget mt_stat; int fd; /* heuristics to determine if this is a drive. */ if ( ! strcmp( drivep->d_pathname, "stdio" )) { return -10; } if ( strchr( drivep->d_pathname, ':')) { errno = 0; fd = open( drivep->d_pathname, O_RDONLY ); if ( fd < 0 ) { return -10; } if ( ioctl( fd, MTIOCGET, &mt_stat ) < 0 ) { close( fd ); return -10; } close( fd ); return 10; } else { if (is_scsi_driver(drivep->d_pathname)) { return 10; } else { return -10; } } } /* strategy instantiate - initializes the pre-allocated drive descriptor */ /*ARGSUSED*/ static bool_t ds_instantiate( int argc, char *argv[], drive_t *drivep ) { drive_context_t *contextp; int c; /* opportunity for sanity checking */ assert( sizeof( global_hdr_t ) <= STAPE_HDR_SZ ); assert( sizeof( rec_hdr_t ) == sizeofmember( drive_hdr_t, dh_specific )); assert( ! ( STAPE_MAX_RECSZ % PGSZ )); /* hook up the drive ops */ drivep->d_opsp = &drive_ops; /* allocate context for the drive manager */ contextp = ( drive_context_t * )calloc( 1, sizeof( drive_context_t )); assert( contextp ); memset( ( void * )contextp, 0, sizeof( *contextp )); /* do not enable a separate I/O thread, * more testing to be done first... */ contextp->dc_singlethreadedpr = BOOL_TRUE; /* scan the command line for the I/O buffer ring length * and record checksum request */ contextp->dc_ringlen = RINGLEN_DEFAULT; contextp->dc_ringpinnedpr = BOOL_FALSE; contextp->dc_recchksumpr = BOOL_FALSE; contextp->dc_filesz = 0; contextp->dc_isQICpr = BOOL_FALSE; #ifdef DUMP contextp->dc_filesz = 0; #endif optind = 1; opterr = 0; while ( ( c = getopt( argc, argv, GETOPT_CMDSTRING )) != EOF ) { switch ( c ) { case GETOPT_RINGLEN: if ( ! optarg || optarg[ 0 ] == '-' ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("-%c argument missing\n"), c ); return BOOL_FALSE; } contextp->dc_ringlen = ( size_t )atoi( optarg ); if ( contextp->dc_ringlen < RINGLEN_MIN || contextp->dc_ringlen > RINGLEN_MAX ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_DRIVE, _("-%c argument must be " "between %u and %u: ignoring %u\n"), c, RINGLEN_MIN, RINGLEN_MAX, contextp->dc_ringlen ); return BOOL_FALSE; } break; case GETOPT_RINGPIN: contextp->dc_ringpinnedpr = BOOL_TRUE; break; case GETOPT_RECCHKSUM: contextp->dc_recchksumpr = BOOL_TRUE; break; case GETOPT_UNLOAD: contextp->dc_unloadokpr = BOOL_TRUE; break; case GETOPT_QIC: contextp->dc_isQICpr = BOOL_TRUE; break; case GETOPT_BLOCKSIZE: if ( ! optarg || optarg[ 0 ] == '-' ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("-%c argument missing\n"), c ); return -10; } cmdlineblksize = ( uint32_t )atoi( optarg ); break; #ifdef DUMP case GETOPT_OVERWRITE: contextp->dc_overwritepr = BOOL_TRUE; break; case GETOPT_FILESZ: if ( ! optarg || optarg[ 0 ] == '-' ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("-%c argument missing\n"), c ); return BOOL_FALSE; } /* given in Mb */ contextp->dc_filesz = (off64_t)atoi( optarg ) * 1024 * 1024; if (contextp->dc_filesz <= 0) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_DRIVE, _("-%c argument must be a " "positive number (Mb): ignoring %u\n"), c, contextp->dc_filesz ); return BOOL_FALSE; } break; #endif } } /* set drive file descriptor to null value */ contextp->dc_fd = -1; /* record location of context descriptor in drive descriptor */ drivep->d_contextp = (void *)contextp; /* indicate neither capacity nor rate estimates available */ drivep->d_cap_est = -1; drivep->d_rate_est = -1; /* if threads not allowed, allocate a record buffer. otherwise * create a ring, from which buffers will be taken. */ if ( contextp->dc_singlethreadedpr ) { contextp->dc_bufp = ( char * )memalign( PGSZ, STAPE_MAX_RECSZ ); assert( contextp->dc_bufp ); } else { int rval; mlog( (MLOG_NITTY + 1) | MLOG_DRIVE, "ring op: create: ringlen == %u\n", contextp->dc_ringlen ); contextp->dc_ringp = ring_create( contextp->dc_ringlen, STAPE_MAX_RECSZ, contextp->dc_ringpinnedpr, drivep->d_index, ring_read, ring_write, ( void * )drivep, &rval ); if ( ! contextp->dc_ringp ) { if ( rval == ENOMEM ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_DRIVE, _("unable to allocate memory " "for I/O buffer ring\n") ); } else if ( rval == E2BIG ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_DRIVE, _("not enough physical memory " "to pin down I/O buffer ring\n") ); } else if ( rval == EPERM ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_DRIVE, _("not allowed " "to pin down I/O buffer ring\n") ); } else { assert( 0 ); } return BOOL_FALSE; } } /* scan drive device pathname to see if remote tape */ if ( strchr( drivep->d_pathname, ':') ) { contextp->dc_isrmtpr = BOOL_TRUE; } else { contextp->dc_isrmtpr = BOOL_FALSE; } /* several of contextp predicates cannot yet be determined. * mark them as unknown for now. however, if this is an RMT * access, we know immediately some capabilities are missing. */ if ( contextp->dc_isrmtpr ) { contextp->dc_cangetblkszpr = BOOL_FALSE; contextp->dc_cansetblkszpr = BOOL_FALSE; contextp->dc_isvarpr = BOOL_TRUE; contextp->dc_isQICpr = BOOL_FALSE; } else { contextp->dc_cangetblkszpr = BOOL_UNKNOWN; contextp->dc_cansetblkszpr = BOOL_UNKNOWN; contextp->dc_isvarpr = BOOL_UNKNOWN; } /* specify that we are currently neither reading nor writing */ contextp->dc_mode = OM_NONE; /* set the capabilities flags advertised in the drive_t d_capabilities * field that we know a priori to be true. later additional flags * may be set */ drivep->d_capabilities = 0 | DRIVE_CAP_BSF | DRIVE_CAP_FSF | DRIVE_CAP_REWIND | DRIVE_CAP_FILES | DRIVE_CAP_APPEND | DRIVE_CAP_NEXTMARK | DRIVE_CAP_EJECT | DRIVE_CAP_READ | DRIVE_CAP_REMOVABLE | DRIVE_CAP_ERASE ; /* initialize origcurblksz so we only save it once */ contextp->dc_origcurblksz = 0; return BOOL_TRUE; } /* drive op init - do more time-consuming init/checking here. read and * write headers are available now. * * NOTE: * When using a RMT device, the MTIOCGETBLKINFO, MTCAPABILITY and * MTSPECOP ioctl calls are not supported. This means that we have * to assume that the drive does not support the MTCAN_APPEND capability. */ /* ARGSUSED */ static bool_t do_init( drive_t *drivep ) { #ifdef DUMP drive_hdr_t *dwhdrp = drivep->d_writehdrp; media_hdr_t *mwhdrp = ( media_hdr_t * )dwhdrp->dh_upper; #endif /* DUMP */ mlog( MLOG_DEBUG | MLOG_DRIVE, "drive op: init\n" ); #ifdef DUMP /* fill in media strategy id: artifact of first version of xfsdump */ mwhdrp->mh_strategyid = MEDIA_STRATEGY_RMVTAPE; #endif /* DUMP */ return BOOL_TRUE; } /* wait here for slave to complete initialization. * set drive capabilities flags. NOTE: currently don't make use of this * feature: drive initialization done whenever block/record sizes unknown. */ /* ARGSUSED */ static bool_t do_sync( drive_t *drivep ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "drive op: sync\n" ); return BOOL_TRUE; } /* begin_read * Set up the tape device and read the media file header. * if allowed, begin read-ahead. * * RETURNS: * 0 on success * DRIVE_ERROR_* on failure * */ static int do_begin_read( drive_t *drivep ) { drive_context_t *contextp; int rval; mlog( MLOG_DEBUG | MLOG_DRIVE, "drive op: begin read\n" ); /* get drive context */ contextp = ( drive_context_t * )drivep->d_contextp; /* verify protocol being followed */ assert( drivep->d_capabilities & DRIVE_CAP_READ ); assert( contextp->dc_mode == OM_NONE ); assert( ! contextp->dc_recp ); /* get a record buffer to use during initialization. */ if ( contextp->dc_singlethreadedpr ) { contextp->dc_recp = contextp->dc_bufp; } else { assert( contextp->dc_ringp ); contextp->dc_msgp = Ring_get( contextp->dc_ringp ); assert( contextp->dc_msgp->rm_stat == RING_STAT_INIT ); contextp->dc_recp = contextp->dc_msgp->rm_bufp; } /* if the tape is not open, open, determine the record size, and * read the first record. otherwise read a record using the record * size previously determined. */ contextp->dc_iocnt = 0; if ( contextp->dc_fd < 0 ) { assert( contextp->dc_fd == -1 ); rval = prepare_drive( drivep ); if ( rval ) { if ( ! contextp->dc_singlethreadedpr ) { Ring_reset( contextp->dc_ringp, contextp->dc_msgp ); } contextp->dc_msgp = 0; contextp->dc_recp = 0; return rval; } } else { rval = read_label( drivep ); if ( rval ) { if ( ! contextp->dc_singlethreadedpr ) { Ring_reset( contextp->dc_ringp, contextp->dc_msgp ); } contextp->dc_msgp = 0; contextp->dc_recp = 0; return rval; } } assert( contextp->dc_iocnt == 1 ); /* set by prepare_drive or read_label */ /* all is well. adjust context. don't kick off read-aheads just yet; * the client may not want this media file. */ if ( ! contextp->dc_singlethreadedpr ) { contextp->dc_msgp->rm_op = RING_OP_NOP; contextp->dc_msgp->rm_user = 0; /* do diff. use in do_seek */ Ring_put( contextp->dc_ringp, contextp->dc_msgp ); contextp->dc_msgp = 0; } contextp->dc_recp = 0; contextp->dc_recendp = 0; contextp->dc_dataendp = 0; contextp->dc_ownedp = 0; contextp->dc_nextp = 0; contextp->dc_reccnt = 1; /* used to detect attempt to read after an error was reported */ contextp->dc_errorpr = BOOL_FALSE; /* successfully entered read mode. must do end_read to get out. */ contextp->dc_mode = OM_READ; return 0; } /* do_read * Supply the caller with all or a portion of the current buffer, * filled with data from a record. * * RETURNS: * a pointer to a buffer containing "*actual_bufszp" bytes of data * or 0 on failure with "*rvalp" containing the error (DRIVE_ERROR_...) * */ static char * do_read( drive_t *drivep, size_t wantedcnt, size_t *actualcntp, int *rvalp ) { drive_context_t *contextp; size_t availcnt; size_t actualcnt; int rval; mlog( MLOG_DEBUG | MLOG_DRIVE, "drive op: read: wanted %u (0x%x)\n", wantedcnt, wantedcnt ); /* get context ptrs */ contextp = ( drive_context_t * )drivep->d_contextp; /* assert protocol being followed */ assert( contextp->dc_mode == OM_READ ); assert( ! contextp->dc_errorpr ); assert( ! contextp->dc_ownedp ); assert( wantedcnt > 0 ); /* clear the return status field */ *rvalp = 0; /* read a new record if necessary */ rval = getrec( drivep ); if ( rval ) { mlog( MLOG_NITTY | MLOG_DRIVE, "drive op read returning error rval=%d\n", rval ); *rvalp = rval; return 0; } /* figure how much data is available, and how much should be supplied */ availcnt = ( size_t )( contextp->dc_dataendp - contextp->dc_nextp ); actualcnt = min( wantedcnt, availcnt ); /* adjust the context */ contextp->dc_ownedp = contextp->dc_nextp; contextp->dc_nextp += actualcnt; assert( contextp->dc_nextp <= contextp->dc_dataendp ); mlog( MLOG_NITTY | MLOG_DRIVE, "drive op read actual == %d (0x%x)\n", actualcnt, actualcnt ); *actualcntp = actualcnt; return contextp->dc_ownedp; } /* do_return_read_buf - * Lets the caller give back the buffer portion obtained from the preceding * call to do_read(). * * RETURNS: * void */ /* ARGSUSED */ static void do_return_read_buf( drive_t *drivep, char *bufp, size_t retcnt ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; /* REFERENCED */ size_t ownedcnt; mlog( MLOG_DEBUG | MLOG_DRIVE, "drive op: return read buf: sz %d (0x%x)\n", retcnt, retcnt ); /* assert protocol being followed */ assert( contextp->dc_mode == OM_READ ); assert( ! contextp->dc_errorpr ); assert( contextp->dc_ownedp ); assert( bufp == contextp->dc_ownedp ); /* calculate how much the caller owns */ assert( contextp->dc_nextp >= contextp->dc_ownedp ); ownedcnt = ( size_t )( contextp->dc_nextp - contextp->dc_ownedp ); assert( ownedcnt == retcnt ); /* take possession of buffer portion */ contextp->dc_ownedp = 0; /* if caller is done with this record, take the buffer back * and (if ring in use) give buffer to ring for read-ahead. */ if ( contextp->dc_nextp >= contextp->dc_dataendp ) { assert( contextp->dc_nextp == contextp->dc_dataendp ); if ( ! contextp->dc_singlethreadedpr ) { contextp->dc_msgp->rm_op = RING_OP_READ; Ring_put( contextp->dc_ringp, contextp->dc_msgp ); contextp->dc_msgp = 0; } contextp->dc_recp = 0; contextp->dc_recendp = 0; contextp->dc_dataendp = 0; contextp->dc_nextp = 0; contextp->dc_reccnt++; } } /* do_get_mark * Get the current read tape location. * * RETURNS: * void */ static void do_get_mark( drive_t *drivep, drive_mark_t *markp ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; off64_t offset; mlog( MLOG_DEBUG | MLOG_DRIVE, "drive op: get mark\n" ); /* assert protocol being followed */ assert( contextp->dc_mode == OM_READ ); assert( ! contextp->dc_errorpr ); assert( ! contextp->dc_ownedp ); /* the mark is simply the offset into the media file of the * next byte to be read. */ offset = contextp->dc_reccnt * ( off64_t )tape_recsz; if ( contextp->dc_recp ) { offset += ( off64_t )( contextp->dc_nextp - contextp->dc_recp ); } *markp = ( drive_mark_t )offset; return; } typedef enum { SEEKMODE_BUF, SEEKMODE_RAW } seekmode_t; /* do_seek_mark * Advance the tape to the given mark. does dummy reads to * advance tape, as well as FSR if supported. * * RETURNS: * 0 on success * DRIVE_ERROR_* on failure * */ static int do_seek_mark( drive_t *drivep, drive_mark_t *markp ) { drive_context_t *contextp; off64_t wantedoffset; off64_t currentoffset; /* get the drive context */ contextp = (drive_context_t *)drivep->d_contextp; /* assert protocol being followed */ assert( contextp->dc_mode == OM_READ ); assert( ! contextp->dc_errorpr ); assert( ! contextp->dc_ownedp ); /* the desired mark is passed by reference, and is really just an * offset into the raw (incl rec hdrs) read stream */ wantedoffset = *( off64_t * )markp; mlog( MLOG_DEBUG | MLOG_DRIVE, "drive op: seek mark: %lld (0x%llx)\n", wantedoffset, wantedoffset ); /* determine the current offset. assert that the wanted offset is * not less than the current offset. */ currentoffset = contextp->dc_reccnt * ( off64_t )tape_recsz; if ( contextp->dc_recp ) { uint32_t recoff; #ifdef DEBUG rec_hdr_t *rechdrp = ( rec_hdr_t * )contextp->dc_recp; #endif assert( contextp->dc_nextp >= contextp->dc_recp ); recoff = ( uint32_t )( contextp->dc_nextp - contextp->dc_recp ); assert( recoff <= tape_recsz ); assert( rechdrp->rec_used <= tape_recsz ); assert( recoff >= STAPE_HDR_SZ ); assert( rechdrp->rec_used >= STAPE_HDR_SZ ); assert( recoff <= rechdrp->rec_used ); currentoffset += ( off64_t )recoff; } assert( wantedoffset >= currentoffset ); /* if we are currently holding a record and the desired offset * is not within the current record, eat the current record. */ if ( contextp->dc_recp ) { off64_t nextrecoffset; rec_hdr_t *rechdrp = ( rec_hdr_t * )contextp->dc_recp; nextrecoffset = contextp->dc_reccnt * ( off64_t )tape_recsz + ( off64_t )rechdrp->rec_used; if ( wantedoffset >= nextrecoffset ) { uint32_t recoff; size_t wantedcnt; char *dummybufp; size_t actualcnt; int rval; /* if this is the last record, the wanted offset * must be just after it. */ if ( rechdrp->rec_used < tape_recsz ) { assert( wantedoffset == nextrecoffset ); } /* figure how much to ask for */ assert( contextp->dc_nextp >= contextp->dc_recp ); recoff = ( uint32_t )( contextp->dc_nextp - contextp->dc_recp ); wantedcnt = ( size_t )( rechdrp->rec_used - recoff ); /* eat that much tape */ rval = 0; dummybufp = do_read( drivep, wantedcnt, &actualcnt, &rval ); if ( rval ) { return rval; } assert( actualcnt == wantedcnt ); do_return_read_buf( drivep, dummybufp, actualcnt ); currentoffset += ( off64_t )actualcnt; assert( currentoffset == nextrecoffset ); assert( wantedoffset >= currentoffset ); assert( ! contextp->dc_recp ); assert( currentoffset == contextp->dc_reccnt * ( off64_t )tape_recsz ); } } /* if FSR is supported, while the desired offset is more than a record * away, eat records. this is tricky. if read-ahead has already read * to the desired point, no need to FSR: fall through to next code block * where we get there by eating excess records. if read-ahead has not * made it there, suspend read-ahead, eat those readahead records, * FSR the remaining, and resume readahead. */ if ( contextp->dc_canfsrpr && wantedoffset - currentoffset >= ( off64_t )tape_recsz ) { off64_t wantedreccnt; seekmode_t seekmode; assert( ! contextp->dc_recp ); wantedreccnt = wantedoffset / ( off64_t )tape_recsz; if ( contextp->dc_singlethreadedpr ) { seekmode = SEEKMODE_RAW; } else { seekmode = SEEKMODE_BUF; } assert( wantedreccnt != 0 ); /* so NOP below can be * distinguished from use * in do_begin_read */ while ( contextp->dc_reccnt < wantedreccnt ) { off64_t recskipcnt64; off64_t recskipcnt64remaining; if ( seekmode == SEEKMODE_BUF ) { ring_stat_t rs; assert( ! contextp->dc_msgp ); contextp->dc_msgp = Ring_get( contextp->dc_ringp ); rs = contextp->dc_msgp->rm_stat; if ( rs == RING_STAT_ERROR ) { contextp->dc_errorpr = BOOL_TRUE; return contextp->dc_msgp->rm_rval; } if ( rs != RING_STAT_OK && rs != RING_STAT_INIT && rs != RING_STAT_NOPACK ) { assert( 0 ); contextp->dc_errorpr = BOOL_TRUE; return DRIVE_ERROR_CORE; } if ( rs == RING_STAT_OK ) { contextp->dc_reccnt++; } if ( rs == RING_STAT_NOPACK && contextp->dc_msgp->rm_user == wantedreccnt ) { seekmode = SEEKMODE_RAW; } contextp->dc_msgp->rm_op = RING_OP_NOP; contextp->dc_msgp->rm_user = wantedreccnt; Ring_put( contextp->dc_ringp, contextp->dc_msgp ); contextp->dc_msgp = 0; continue; } assert( contextp->dc_reccnt == contextp->dc_iocnt ); assert( wantedreccnt > contextp->dc_reccnt ); recskipcnt64 = wantedreccnt - contextp->dc_reccnt; recskipcnt64remaining = recskipcnt64; while ( recskipcnt64remaining ) { int recskipcnt; int saved_errno; int rval; assert( recskipcnt64remaining > 0 ); if ( recskipcnt64remaining > INTGENMAX ) { recskipcnt = INTGENMAX; } else { recskipcnt = ( int ) recskipcnt64remaining; } assert( recskipcnt > 0 ); rval = mt_op( contextp->dc_fd, MTFSR, recskipcnt ); saved_errno = errno; if ( rval ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("could not forward space %d " "tape blocks: " "rval == %d, errno == %d (%s)\n"), rval, saved_errno, strerror( saved_errno )); return DRIVE_ERROR_MEDIA; } recskipcnt64remaining -= ( off64_t )recskipcnt; } contextp->dc_reccnt += recskipcnt64; contextp->dc_iocnt += recskipcnt64; currentoffset = contextp->dc_reccnt * ( off64_t )tape_recsz; assert( wantedoffset >= currentoffset ); assert( wantedoffset - currentoffset < ( off64_t )tape_recsz ); } } /* remove excess records by eating them. won't be any if * FSR supported */ while ( wantedoffset - currentoffset >= ( off64_t )tape_recsz ) { size_t wantedcnt; char *dummybufp; size_t actualcnt; int rval; assert( ! contextp->dc_recp ); /* figure how much to ask for. to eat an entire record, * ask for a record sans the header. do_read will eat * the header, we eat the rest. */ wantedcnt = ( size_t )( tape_recsz - STAPE_HDR_SZ ); /* eat that much tape */ rval = 0; dummybufp = do_read( drivep, wantedcnt, &actualcnt, &rval ); if ( rval ) { return rval; } assert( actualcnt == wantedcnt ); do_return_read_buf( drivep, dummybufp, actualcnt ); assert( ! contextp->dc_recp ); currentoffset += ( off64_t )tape_recsz; assert( currentoffset == contextp->dc_reccnt * ( off64_t )tape_recsz ); } /* eat that portion of the next record leading up to the * desired offset. */ if ( wantedoffset != currentoffset ) { size_t wantedcnt; char *dummybufp; size_t actualcnt; assert( wantedoffset > currentoffset ); assert( wantedoffset - currentoffset < ( off64_t )tape_recsz ); wantedcnt = ( size_t )( wantedoffset - currentoffset ); if ( contextp->dc_recp ) { uint32_t recoff; #ifdef DEBUG rec_hdr_t *rechdrp = ( rec_hdr_t * )contextp->dc_recp; #endif recoff = ( uint32_t )( contextp->dc_nextp - contextp->dc_recp ); assert( recoff <= tape_recsz ); assert( rechdrp->rec_used <= tape_recsz ); assert( recoff >= STAPE_HDR_SZ ); assert( rechdrp->rec_used >= STAPE_HDR_SZ ); assert( recoff <= rechdrp->rec_used ); assert( recoff + wantedcnt <= rechdrp->rec_used ); } else { assert( wantedcnt >= STAPE_HDR_SZ ); wantedcnt -= STAPE_HDR_SZ; } /* eat that much tape */ if ( wantedcnt > 0 ) { int rval; rval = 0; dummybufp = do_read( drivep, wantedcnt, &actualcnt, &rval ); if ( rval ) { return rval; } assert( actualcnt == wantedcnt ); do_return_read_buf( drivep, dummybufp, actualcnt ); } } /* as a sanity check, refigure the current offset and make sure * it is equal to the wanted offset */ currentoffset = contextp->dc_reccnt * ( off64_t )tape_recsz; if ( contextp->dc_recp ) { uint32_t recoff; #ifdef DEBUG rec_hdr_t *rechdrp = ( rec_hdr_t * )contextp->dc_recp; #endif assert( contextp->dc_nextp >= contextp->dc_recp ); recoff = ( uint32_t )( contextp->dc_nextp - contextp->dc_recp ); assert( recoff <= tape_recsz ); assert( rechdrp->rec_used <= tape_recsz ); assert( recoff >= STAPE_HDR_SZ ); assert( rechdrp->rec_used >= STAPE_HDR_SZ ); assert( recoff <= rechdrp->rec_used ); currentoffset += ( off64_t )recoff; } assert( wantedoffset == currentoffset ); return 0; } /* do_next_mark * Advance the tape position to the next valid mark. if in * error mode, first attempt to move past error by re-reading. if * that fails, try to FSR. also deals with QIC possibility of * reading a block not at a record boundary. * * RETURNS: * 0 on success * DRIVE_ERROR_* on failure */ static int do_next_mark( drive_t *drivep ) { drive_context_t *contextp = (drive_context_t *)drivep->d_contextp; rec_hdr_t *rechdrp; char *p; ix_t trycnt; const ix_t maxtrycnt = 5; int nread; off64_t markoff; int saved_errno; mtstat_t mtstat; size_t tailsz; int rval; bool_t ok; /* assert protocol being followed. */ assert( contextp->dc_mode == OM_READ ); assert( ! contextp->dc_errorpr ); assert( ! contextp->dc_ownedp ); mlog( MLOG_DEBUG | MLOG_DRIVE, "drive op: next mark\n" ); trycnt = 0; if ( contextp->dc_errorpr ) { goto resetring; } else { goto noerrorsearch; } noerrorsearch: for ( ; ; ) { rval = getrec( drivep ); if ( rval == DRIVE_ERROR_CORRUPTION ) { goto resetring; } else if ( rval ) { return rval; } rechdrp = ( rec_hdr_t * )contextp->dc_recp; assert( rechdrp->first_mark_offset != 0 ); if ( rechdrp->first_mark_offset > 0 ) { off64_t markoff = rechdrp->first_mark_offset - rechdrp->file_offset; off64_t curoff = ( off64_t )( contextp->dc_nextp - contextp->dc_recp ); assert( markoff > 0 ); assert( curoff > 0 ); if ( markoff >= curoff ) { break; } } if ( ! contextp->dc_singlethreadedpr ) { Ring_put( contextp->dc_ringp, contextp->dc_msgp ); contextp->dc_msgp = 0; } contextp->dc_recp = 0; contextp->dc_reccnt++; } assert( rechdrp->first_mark_offset - rechdrp->file_offset <= ( off64_t )tape_recsz ); contextp->dc_nextp = contextp->dc_recp + ( size_t )( rechdrp->first_mark_offset - rechdrp->file_offset ); assert( contextp->dc_nextp <= contextp->dc_dataendp ); assert( contextp->dc_nextp >= contextp->dc_recp + STAPE_HDR_SZ ); if ( contextp->dc_nextp == contextp->dc_dataendp ) { if ( ! contextp->dc_singlethreadedpr ) { Ring_put( contextp->dc_ringp, contextp->dc_msgp ); contextp->dc_msgp = 0; } contextp->dc_recp = 0; contextp->dc_reccnt++; } return 0; resetring: if ( ! contextp->dc_singlethreadedpr ) { Ring_reset( contextp->dc_ringp, contextp->dc_msgp ); contextp->dc_msgp = 0; } contextp->dc_recp = 0; /* get a record buffer and cast a record header pointer */ if ( contextp->dc_singlethreadedpr ) { contextp->dc_recp = contextp->dc_bufp; } else { contextp->dc_msgp = Ring_get( contextp->dc_ringp ); assert( contextp->dc_msgp->rm_stat == RING_STAT_INIT ); contextp->dc_recp = contextp->dc_msgp->rm_bufp; } rechdrp = ( rec_hdr_t * )contextp->dc_recp; goto readrecord; readrecord: trycnt++; if ( trycnt > maxtrycnt ) { mlog( MLOG_NORMAL | MLOG_DRIVE, _("unable to locate next mark in media file\n") ); return DRIVE_ERROR_MEDIA; } nread = Read( drivep, contextp->dc_recp, tape_recsz, &saved_errno ); goto validateread; validateread: if ( nread == ( int )tape_recsz ) { goto validatehdr; } ok = mt_get_status( drivep, &mtstat ); if ( ! ok ) { status_failed_message( drivep ); return DRIVE_ERROR_DEVICE; } if ( IS_FMK( mtstat )) { mlog( MLOG_DEBUG | MLOG_DRIVE, "encountered EOF attempting to read record\n" ); return DRIVE_ERROR_EOF; } if ( IS_EOD( mtstat )) { mlog( MLOG_DEBUG | MLOG_DRIVE, "encountered EOD attempting to read record\n" ); return DRIVE_ERROR_EOD; } if ( IS_EOT( mtstat )) { mlog( MLOG_DEBUG | MLOG_DRIVE, "encountered EOM attempting to read record\n" ); return DRIVE_ERROR_EOM; } if ( IS_EW( mtstat )) { mlog( MLOG_DEBUG | MLOG_DRIVE, "encountered EW attempting to read record\n" ); return DRIVE_ERROR_EOM; } if ( nread >= 0 ) { assert( ( size_t )nread <= tape_recsz ); mlog( MLOG_DEBUG | MLOG_DRIVE, "short read (nread == %d, record size == %d)\n", nread, tape_recsz ); goto getbeyonderror; } /* some other error */ mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_DRIVE, _( "unexpected error attempting to read record: " "read returns %d, errno %d (%s)\n"), nread, errno, strerror( errno )); goto getbeyonderror; validatehdr: rval = record_hdr_validate( drivep, contextp->dc_recp, BOOL_FALSE ); if ( rval && ( contextp->dc_isQICpr == BOOL_TRUE || contextp->dc_isQICpr == BOOL_UNKNOWN )) { goto huntQIC; } if ( rval ) { goto readrecord; } contextp->dc_reccnt = rechdrp->file_offset / ( off64_t )tape_recsz; contextp->dc_iocnt = contextp->dc_reccnt + 1; if ( rechdrp->first_mark_offset < 0 ) { mlog( MLOG_NORMAL | MLOG_DRIVE, _("valid record %lld but no mark\n"), contextp->dc_iocnt - 1 ); goto readrecord; } assert( ! ( rechdrp->file_offset % ( off64_t )tape_recsz )); markoff = rechdrp->first_mark_offset - rechdrp->file_offset; assert( markoff >= ( off64_t )STAPE_HDR_SZ ); assert( markoff < ( off64_t )tape_recsz ); assert( rechdrp->rec_used > STAPE_HDR_SZ ); assert( rechdrp->rec_used < tape_recsz ); goto alliswell; alliswell: contextp->dc_nextp = contextp->dc_recp + ( size_t )markoff; assert( ! ( rechdrp->file_offset % ( off64_t )tape_recsz )); contextp->dc_reccnt = rechdrp->file_offset / ( off64_t )tape_recsz; contextp->dc_iocnt = contextp->dc_reccnt + 1; contextp->dc_recendp = contextp->dc_recp + tape_recsz; contextp->dc_dataendp = contextp->dc_recp + rechdrp->rec_used; assert( contextp->dc_dataendp <= contextp->dc_recendp ); assert( contextp->dc_nextp < contextp->dc_dataendp ); contextp->dc_errorpr = BOOL_FALSE; mlog( MLOG_NORMAL | MLOG_DRIVE, _("resynchronized at record %lld offset %u\n"), contextp->dc_iocnt - 1, contextp->dc_nextp - contextp->dc_recp ); return 0; getbeyonderror: rval = mt_op( contextp->dc_fd, MTFSR, 1 ); saved_errno = errno; if ( rval ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("could not forward space one tape block beyond " "read error: rval == %d, errno == %d (%s)\n"), rval, saved_errno, strerror( saved_errno )); return DRIVE_ERROR_MEDIA; } goto readrecord; huntQIC: /* we have a full tape_recsz record. look for the magic number at the * beginning of each 512 byte block. If we find one, shift that and * the following blocks to the head of the record buffer, and try * to read the remaining blocks in the record. */ for ( p = contextp->dc_recp + QIC_BLKSZ ; p < contextp->dc_recendp ; p += QIC_BLKSZ ) { if ( *( uint64_t * )p == STAPE_MAGIC ) { goto adjustQIC; } } goto readrecord; adjustQIC: tailsz = ( size_t )( contextp->dc_recendp - p ); memcpy( ( void * )contextp->dc_recp, ( void * )p, tailsz ); nread = Read( drivep, contextp->dc_recp + tailsz, tape_recsz - tailsz, &saved_errno ); goto validateread; } /* do_end_read * Discard any buffered reads. * Tell the reader/writer process to wait. * * RETURNS: * void */ static void do_end_read( drive_t *drivep ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; mlog( MLOG_DEBUG | MLOG_DRIVE, "drive op: end read\n" ); /* assert protocol being followed */ assert( contextp->dc_mode == OM_READ ); assert( ! contextp->dc_ownedp ); if ( ! contextp->dc_singlethreadedpr ) { Ring_reset( contextp->dc_ringp, contextp->dc_msgp ); contextp->dc_msgp = 0; } contextp->dc_recp = 0; contextp->dc_mode = OM_NONE; } /* do_begin_write * prepare drive for writing. set up drive context. write a header record. * * RETURNS: * 0 on success * DRIVE_ERROR_... on failure */ static int do_begin_write( drive_t *drivep ) { drive_context_t *contextp; drive_hdr_t *dwhdrp; global_hdr_t *gwhdrp; rec_hdr_t *tpwhdrp; rec_hdr_t *rechdrp; mtstat_t mtstat; int rval; media_hdr_t *mwhdrp; content_hdr_t *ch; content_inode_hdr_t *cih; global_hdr_t *tmpgh; drive_hdr_t *tmpdh; media_hdr_t *tmpmh; rec_hdr_t *tmprh; content_hdr_t *tmpch; content_inode_hdr_t *tmpcih; /* get drive context */ contextp = ( drive_context_t * )drivep->d_contextp; mlog( MLOG_DEBUG | MLOG_DRIVE, "drive op: begin write\n" ); /* verify protocol being followed */ assert( contextp->dc_mode == OM_NONE ); assert( ! drivep->d_markrecheadp ); assert( ! contextp->dc_recp ); /* get pointers into global write header */ gwhdrp = drivep->d_gwritehdrp; dwhdrp = drivep->d_writehdrp; tpwhdrp = ( rec_hdr_t * )dwhdrp->dh_specific; /* must already be open. The only way to open is to do a begin_read. * so all interaction with scsi tape requires reading first. */ assert( contextp->dc_fd != -1 ); /* get tape device status. verify tape is positioned */ if ( ! mt_get_status( drivep, &mtstat )) { status_failed_message( drivep ); return DRIVE_ERROR_DEVICE; } if ( IS_EOT( mtstat )) { return DRIVE_ERROR_EOM; } if ( IS_EW( mtstat ) && !(IS_BOT(mtstat)) ) { return DRIVE_ERROR_EOM; } /* fill in write header's drive specific info */ tpwhdrp->magic = STAPE_MAGIC; tpwhdrp->version = STAPE_VERSION; tpwhdrp->blksize = ( int32_t )tape_blksz; tpwhdrp->recsize = ( int32_t )tape_recsz; tpwhdrp->rec_used = 0; tpwhdrp->file_offset = 0; tpwhdrp->first_mark_offset= 0; tpwhdrp->capability = drivep->d_capabilities; /* get a record buffer. will be used for the media file header, * and is needed to "prime the pump" for first call to do_write. */ assert( ! contextp->dc_recp ); if ( contextp->dc_singlethreadedpr ) { assert( contextp->dc_bufp ); contextp->dc_recp = contextp->dc_bufp; } else { assert( contextp->dc_ringp ); assert( ! contextp->dc_msgp ); contextp->dc_msgp = Ring_get( contextp->dc_ringp ); assert( contextp->dc_msgp->rm_stat == RING_STAT_INIT ); contextp->dc_recp = contextp->dc_msgp->rm_bufp; } /* write the record. be sure to prevent a record checksum from * being produced! */ contextp->dc_iocnt = 0; memset( ( void * )contextp->dc_recp, 0, tape_recsz ); tmpgh = (global_hdr_t *)contextp->dc_recp; tmpdh = (drive_hdr_t *)tmpgh->gh_upper; tmpmh = (media_hdr_t *)tmpdh->dh_upper; tmprh = (rec_hdr_t *)tmpdh->dh_specific; tmpch = (content_hdr_t *)tmpmh->mh_upper; tmpcih = (content_inode_hdr_t *)tmpch->ch_specific; mwhdrp = (media_hdr_t *)dwhdrp->dh_upper; ch = (content_hdr_t *)mwhdrp->mh_upper; cih = (content_inode_hdr_t *)ch->ch_specific; xlate_global_hdr(gwhdrp, tmpgh, 1); xlate_drive_hdr(dwhdrp, tmpdh, 1); xlate_media_hdr(mwhdrp, tmpmh, 1); xlate_content_hdr(ch, tmpch, 1); xlate_content_inode_hdr(cih, tmpcih, 1); xlate_rec_hdr(tpwhdrp, tmprh, 1); /* checksum the global header */ global_hdr_checksum_set( tmpgh ); rval = write_record( drivep, contextp->dc_recp, BOOL_TRUE, BOOL_FALSE ); if ( rval ) { if ( ! contextp->dc_singlethreadedpr ) { Ring_reset( contextp->dc_ringp, contextp->dc_msgp ); contextp->dc_msgp = 0; } contextp->dc_recp = 0; return rval; } /* prepare the drive context. must have a record buffer ready to * go, header initialized. */ assert( ! contextp->dc_ownedp ); contextp->dc_reccnt = 1; /* count the header record */ contextp->dc_recendp = contextp->dc_recp + tape_recsz; contextp->dc_nextp = contextp->dc_recp + STAPE_HDR_SZ; /* intialize header in new record */ rechdrp = (rec_hdr_t*)contextp->dc_recp; rechdrp->magic = STAPE_MAGIC; rechdrp->version = STAPE_VERSION; rechdrp->file_offset = contextp->dc_reccnt * ( off64_t )tape_recsz; rechdrp->blksize = ( int32_t )tape_blksz; rechdrp->recsize = ( int32_t )tape_recsz; rechdrp->capability = drivep->d_capabilities; rechdrp->first_mark_offset = -1LL; uuid_copy( rechdrp->dump_uuid, gwhdrp->gh_dumpid ); /* set mode now so operators will work */ contextp->dc_mode = OM_WRITE; contextp->dc_errorpr = BOOL_FALSE; return 0; } /* do_set_mark - queue a mark request. if first mark set in record, record * in record. */ static void do_set_mark( drive_t *drivep, drive_mcbfp_t cbfuncp, void *cbcontextp, drive_markrec_t *markrecp ) { drive_context_t *contextp; off64_t nextoff; rec_hdr_t *rechdrp; /* get drive context */ contextp = ( drive_context_t * )drivep->d_contextp; /* verify protocol being followed */ assert( contextp->dc_mode == OM_WRITE ); assert( ! contextp->dc_errorpr ); assert( ! contextp->dc_ownedp ); assert( contextp->dc_recp ); assert( contextp->dc_nextp ); /* calculate and fill in the mark record offset */ assert( contextp->dc_recp ); nextoff = contextp->dc_reccnt * ( off64_t )tape_recsz + ( off64_t )( contextp->dc_nextp - contextp->dc_recp ); markrecp->dm_log = ( drive_mark_t )nextoff; mlog( MLOG_DEBUG | MLOG_DRIVE, "drive op: set mark: %lld (0x%llx)\n", nextoff, nextoff ); /* note the location of the first mark in this tape record. */ rechdrp = ( rec_hdr_t * )contextp->dc_recp; if ( rechdrp->first_mark_offset == -1LL ) { assert( nextoff != -1LL ); rechdrp->first_mark_offset = nextoff; } /* put the mark on the tail of the queue. */ markrecp->dm_cbfuncp = cbfuncp; markrecp->dm_cbcontextp = cbcontextp; markrecp->dm_nextp = 0; if ( drivep->d_markrecheadp == 0 ) { drivep->d_markrecheadp = markrecp; drivep->d_markrectailp = markrecp; } else { assert( drivep->d_markrectailp ); drivep->d_markrectailp->dm_nextp = markrecp; drivep->d_markrectailp = markrecp; } } /* do_get_write_buf - supply the caller with some or all of the current record * buffer. the supplied buffer must be fully returned (via a single call to * do_write) prior to the next call to do_get_write_buf. * * RETURNS: * the address of a buffer * "actual_bufszp" points to the size of the buffer */ static char * do_get_write_buf( drive_t *drivep, size_t wantedcnt, size_t *actualcntp ) { drive_context_t *contextp; size_t remainingcnt; size_t actualcnt; /* get drive context */ contextp = ( drive_context_t * )drivep->d_contextp; /* verify protocol being followed */ assert( contextp->dc_mode == OM_WRITE ); assert( ! contextp->dc_errorpr ); assert( ! contextp->dc_ownedp ); assert( contextp->dc_recp ); assert( contextp->dc_nextp ); assert( contextp->dc_nextp < contextp->dc_recendp ); /* figure how much is available; supply the min of what is * available and what is wanted. */ remainingcnt = ( size_t )( contextp->dc_recendp - contextp->dc_nextp ); actualcnt = min( remainingcnt, wantedcnt ); *actualcntp = actualcnt; contextp->dc_ownedp = contextp->dc_nextp; contextp->dc_nextp += actualcnt; mlog( MLOG_DEBUG | MLOG_DRIVE, "drive op: get write buf: wanted %u (0x%x) actual %u (0x%x)\n", wantedcnt, wantedcnt, actualcnt, actualcnt ); return contextp->dc_ownedp; } /* do_write - accept ownership of the portion of the current record buffer * being returned by the caller. if returned portion includes end of record * buffer, write the buffer and get and prepare a new one in anticipation of * the next call to do_get_write_buf. also, process any queued marks which * are guaranteed to be committed to media. NOTE: the caller must return * everything obtained with the preceeding call to do_get_write_buf. * * RETURNS: * 0 on success * non 0 on error */ /* ARGSUSED */ static int do_write( drive_t *drivep, char *bufp, size_t retcnt ) { drive_context_t *contextp; rec_hdr_t *rechdrp; global_hdr_t *gwhdrp; size_t heldcnt; off64_t last_rec_wrtn_wo_err; /* zero-based index */ int rval; /* get drive context and pointer to global write hdr */ contextp = ( drive_context_t * )drivep->d_contextp; gwhdrp = drivep->d_gwritehdrp; /* calculate how many bytes we believe caller is holding */ heldcnt = ( size_t )( contextp->dc_nextp - contextp->dc_ownedp ); mlog( MLOG_DEBUG | MLOG_DRIVE, "drive op: write: retcnt %u (0x%x) heldcnt %u (0x%x)\n", retcnt, retcnt, heldcnt, heldcnt ); /* verify protocol being followed */ assert( contextp->dc_mode == OM_WRITE ); assert( ! contextp->dc_errorpr ); assert( contextp->dc_ownedp ); assert( contextp->dc_recp ); assert( contextp->dc_nextp ); assert( contextp->dc_nextp <= contextp->dc_recendp ); /* verify the caller is returning exactly what is held */ assert( bufp == contextp->dc_ownedp ); assert( retcnt == heldcnt ); /* take it back */ contextp->dc_ownedp = 0; /* if some portion of the record buffer has not yet been * held by the client, just return. */ if ( contextp->dc_nextp < contextp->dc_recendp ) { return 0; } /* record in record header that entire record is used */ rechdrp = ( rec_hdr_t * )contextp->dc_recp; rechdrp->rec_used = tape_recsz; /* write out the record buffer and get a new one. */ if ( contextp->dc_singlethreadedpr ) { rval = write_record( drivep, contextp->dc_recp, BOOL_TRUE, BOOL_TRUE ); last_rec_wrtn_wo_err = contextp->dc_reccnt; /* conv cnt to ix */ } else { contextp->dc_msgp->rm_op = RING_OP_WRITE; contextp->dc_msgp->rm_user = contextp->dc_reccnt; Ring_put( contextp->dc_ringp, contextp->dc_msgp ); contextp->dc_msgp = 0; contextp->dc_msgp = Ring_get( contextp->dc_ringp ); contextp->dc_recp = contextp->dc_msgp->rm_bufp; last_rec_wrtn_wo_err = contextp->dc_msgp->rm_user; switch( contextp->dc_msgp->rm_stat ) { case RING_STAT_OK: case RING_STAT_INIT: rval = 0; break; case RING_STAT_ERROR: rval = contextp->dc_msgp->rm_rval; break; default: assert( 0 ); return DRIVE_ERROR_CORE; } } /* check for errors. if none, commit all marks before a safety margin * before the no error offset. */ if ( rval ) { contextp->dc_errorpr = BOOL_TRUE; } else { off64_t recs_wrtn_wo_err; off64_t recs_committed; off64_t bytes_committed; recs_wrtn_wo_err = last_rec_wrtn_wo_err + 1; recs_committed = recs_wrtn_wo_err - contextp->dc_lostrecmax; bytes_committed = recs_committed * ( off64_t )tape_recsz; drive_mark_commit( drivep, bytes_committed ); } /* adjust context */ contextp->dc_reccnt++; contextp->dc_recendp = contextp->dc_recp + tape_recsz; contextp->dc_nextp = contextp->dc_recp + STAPE_HDR_SZ; /* intialize header in new record */ rechdrp = ( rec_hdr_t * )contextp->dc_recp; rechdrp->magic = STAPE_MAGIC; rechdrp->version = STAPE_VERSION; rechdrp->file_offset = contextp->dc_reccnt * ( off64_t )tape_recsz; rechdrp->blksize = ( int32_t )tape_blksz; rechdrp->recsize = ( int32_t )tape_recsz; rechdrp->capability = drivep->d_capabilities; rechdrp->first_mark_offset = -1LL; uuid_copy( rechdrp->dump_uuid, gwhdrp->gh_dumpid ); return rval; } /* do_get_align_cnt - * Returns the number of bytes which must be written to * cause the next call to get_write_buf() to be page-aligned. * * RETURNS: * the number of bytes to next alignment */ static size_t do_get_align_cnt( drive_t * drivep ) { char *next_alignment_point; intptr_t next_alignment_off; drive_context_t *contextp; contextp = ( drive_context_t * )drivep->d_contextp; mlog( MLOG_DEBUG | MLOG_DRIVE, "drive op: get align cnt\n" ); /* verify protocol being followed */ assert( contextp->dc_mode == OM_WRITE ); assert( ! contextp->dc_errorpr ); assert( ! contextp->dc_ownedp ); assert( contextp->dc_recp ); assert( contextp->dc_nextp ); assert( contextp->dc_nextp < contextp->dc_recendp ); /* calculate the next alignment point at or beyond the current nextp. * the following algorithm works because all buffers are page-aligned * and a multiple of PGSZ. */ next_alignment_off = ( intptr_t )contextp->dc_nextp; next_alignment_off += PGMASK; next_alignment_off &= ~PGMASK; next_alignment_point = ( char * )next_alignment_off; assert( next_alignment_point <= contextp->dc_recendp ); /* return the number of bytes to the next alignment offset */ assert( next_alignment_point >= contextp->dc_nextp ); return ( size_t )( next_alignment_point - contextp->dc_nextp ); } /* do_end_write - pad and write pending record if any client data in it. * flush all pending writes. write a file mark. figure how many records are * guaranteed to be on media, and commit/discard marks accordingly. * RETURNS: * 0 on success * DRIVE_ERROR_* on failure */ static int do_end_write( drive_t *drivep, off64_t *ncommittedp ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; off64_t first_rec_w_err; /* zero-based index */ off64_t recs_wtn_wo_err; off64_t recs_guaranteed; off64_t bytes_committed; int rval; mlog( MLOG_DEBUG | MLOG_DRIVE, "drive op: end write\n" ); /* verify protocol being followed */ assert( contextp->dc_mode == OM_WRITE ); assert( ! contextp->dc_ownedp ); assert( contextp->dc_recp ); assert( contextp->dc_nextp ); assert( contextp->dc_nextp >= contextp->dc_recp + STAPE_HDR_SZ ); assert( contextp->dc_nextp < contextp->dc_recendp ); /* pre-initialize return of count of bytes committed to media */ *ncommittedp = 0; /* if in error mode, a write error occured earlier. don't bother * to do anymore writes, just cleanup and return 0. don't need to * do commits, already done when error occured. */ if ( contextp->dc_errorpr ) { if ( ! contextp->dc_singlethreadedpr ) { Ring_reset( contextp->dc_ringp, contextp->dc_msgp ); contextp->dc_msgp = 0; } contextp->dc_mode = OM_NONE; drive_mark_discard( drivep ); *ncommittedp = ( contextp->dc_iocnt - contextp->dc_lostrecmax ) * ( off64_t )tape_recsz; contextp->dc_recp = 0; return 0; } /* if any user data in current record buffer, send it out. */ if ( contextp->dc_nextp > contextp->dc_recp + STAPE_HDR_SZ ) { rec_hdr_t *rechdrp; size_t bufusedcnt; rechdrp = ( rec_hdr_t * )contextp->dc_recp; bufusedcnt = ( size_t )( contextp->dc_nextp - contextp->dc_recp ); rechdrp->rec_used = bufusedcnt; mlog( MLOG_DEBUG | MLOG_DRIVE, "writing padded last record\n" ); if ( contextp->dc_singlethreadedpr ) { rval = write_record( drivep, contextp->dc_recp, BOOL_TRUE, BOOL_TRUE ); } else { assert( contextp->dc_msgp ); contextp->dc_msgp->rm_op = RING_OP_WRITE; contextp->dc_msgp->rm_user = contextp->dc_reccnt; Ring_put( contextp->dc_ringp, contextp->dc_msgp ); contextp->dc_msgp = 0; contextp->dc_msgp = Ring_get( contextp->dc_ringp ); switch( contextp->dc_msgp->rm_stat ) { case RING_STAT_OK: case RING_STAT_INIT: rval = 0; break; case RING_STAT_ERROR: rval = contextp->dc_msgp->rm_rval; break; default: assert( 0 ); contextp->dc_recp = 0; return DRIVE_ERROR_CORE; } } contextp->dc_reccnt++; } else { rval = 0; } /* now flush the ring until error or tracer bullet seen. * note the record index in the first msg received with * an error indication. this will be used to calculate * the number of records guaranteed to have made it onto * media, and that will be used to select which marks * to commit and which to discard. */ if ( rval ) { first_rec_w_err = contextp->dc_iocnt; /* because dc_iocnt bumped by write_record * only if no error */ } else { first_rec_w_err = -1L; } if ( ! contextp->dc_singlethreadedpr ) { while ( ! rval ) { assert( contextp->dc_msgp ); contextp->dc_msgp->rm_op = RING_OP_TRACE; Ring_put( contextp->dc_ringp, contextp->dc_msgp ); contextp->dc_msgp = 0; contextp->dc_msgp = Ring_get( contextp->dc_ringp ); if ( contextp->dc_msgp->rm_op == RING_OP_TRACE ) { break; } switch( contextp->dc_msgp->rm_stat ) { case RING_STAT_OK: case RING_STAT_INIT: assert( rval == 0 ); break; case RING_STAT_ERROR: rval = contextp->dc_msgp->rm_rval; first_rec_w_err = contextp->dc_msgp->rm_user; break; default: assert( 0 ); contextp->dc_recp = 0; return DRIVE_ERROR_CORE; } } } /* the ring is now flushed. reset */ if ( ! contextp->dc_singlethreadedpr ) { Ring_reset( contextp->dc_ringp, contextp->dc_msgp ); contextp->dc_msgp = 0; } contextp->dc_recp = 0; /* if no error so far, write a file mark. this will have the * side-effect of flushing the driver/drive of pending writes, * exposing any write errors. */ if ( ! rval ) { int weofrval; mtstat_t mtstat; bool_t ok; weofrval = mt_op( contextp->dc_fd, MTWEOF, 1 ); if ( ! weofrval ) { ok = mt_get_status( drivep, &mtstat ); if ( ! ok ) { status_failed_message( drivep ); mtstat = 0; rval = DRIVE_ERROR_DEVICE; } } else { mtstat = 0; mlog( MLOG_DEBUG | MLOG_DRIVE, "MTWEOF returned %d: errno == %d (%s)\n", weofrval, errno, strerror( errno )); } if ( weofrval || IS_EW( mtstat ) || IS_EOT( mtstat )) { mlog( MLOG_DEBUG | MLOG_DRIVE, "hit EOM trying to write file mark\n" ); rval = DRIVE_ERROR_EOM; } } /* if an error occured, first_rec_w_err now contains * the count of records written without error, all of which * were full records. subtract from this dc_lostrecmax, * and we have the number of records guaranteed to have made * it to media. * * if no errors have occured, all I/O has been committed. * we can use dc_iocnt, which is the count of records actually * written without error. * * commit marks contained in committed records, discard the rest, * and return rval. return by reference the number of bytes committed * to tape. */ if ( rval ) { assert( first_rec_w_err >= 0 ); recs_wtn_wo_err = first_rec_w_err; recs_guaranteed = recs_wtn_wo_err - contextp->dc_lostrecmax; } else { assert( first_rec_w_err == -1 ); recs_wtn_wo_err = contextp->dc_iocnt; recs_guaranteed = recs_wtn_wo_err; } bytes_committed = recs_guaranteed * ( off64_t )tape_recsz; drive_mark_commit( drivep, bytes_committed ); drive_mark_discard( drivep ); contextp->dc_mode = OM_NONE; *ncommittedp = bytes_committed; return rval; } /* do_fsf * Advance the tape by count files. * * RETURNS: * number of media files skipped * *statp set to zero or DRIVE_ERROR_... */ static int do_fsf( drive_t *drivep, int count, int *statp ) { int i, done, op_failed, opcount; mtstat_t mtstat; drive_context_t *contextp; /* get drive context */ contextp = ( drive_context_t * )drivep->d_contextp; /* verify protocol being followed */ assert( contextp->dc_mode == OM_NONE ); mlog( MLOG_DEBUG | MLOG_DRIVE, "drive op: fsf: count %d\n", count ); assert( count ); assert( contextp->dc_mode == OM_NONE ); /* get tape status */ if ( ! mt_get_status( drivep, &mtstat) ) { status_failed_message( drivep ); *statp = DRIVE_ERROR_DEVICE; return 0; } for ( i = 0 ; i < count; i++ ) { done = 0; opcount = 2; /* the tape may encounter errors will trying to * reach the next file. */ while ( !done ) { /* check for end-of-data and end-of-tape conditions */ if ( IS_EOT( mtstat ) ) { *statp = DRIVE_ERROR_EOM; return i; } else if ( IS_EOD( mtstat ) ) { *statp = DRIVE_ERROR_EOD; return i; } /* advance the tape to the next file mark * NOTE: * ignore return code */ mlog( MLOG_VERBOSE | MLOG_DRIVE, _("advancing tape to next media file\n") ); op_failed = 0; assert( contextp->dc_fd >= 0 ); if ( mt_op( contextp->dc_fd, MTFSF, 1 ) ) { op_failed = 1; } if ( ! mt_get_status( drivep, &mtstat) ) { status_failed_message( drivep ); *statp = DRIVE_ERROR_DEVICE; return i; } /* Check for a file mark to * determine if the fsf command worked. */ if ( (!op_failed) && (IS_FMK(mtstat)) ) { done = 1; } /* If the FSF command has been issued multiple * times, and a file mark has not been reached, * return an error. */ if ( --opcount < 0 ) { mlog( MLOG_VERBOSE | MLOG_DRIVE, _("FSF tape command failed\n") ); *statp = DRIVE_ERROR_DEVICE; return i; } } } return count; } /* do_bsf * Backup the tape by count files. zero means just back up to the beginning * of the last media file read or written. * * RETURNS: * number of media files skipped * *statp set to zero or DRIVE_ERROR_... */ static int do_bsf( drive_t *drivep, int count, int *statp ) { #ifdef DEBUG drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; #endif int skipped; mtstat_t mtstat; mlog( MLOG_DEBUG | MLOG_DRIVE, "drive op: bsf: count %d\n", count ); assert( contextp->dc_mode == OM_NONE ); *statp = 0; /* first move to the left of the last file mark. * if BOT encountered, return 0. also check for * being at BOT or file mark and count == 0: no motion needed */ /* get tape status */ if ( ! mt_get_status( drivep, &mtstat )) { status_failed_message( drivep ); *statp = DRIVE_ERROR_DEVICE; return 0; } /* check for beginning-of-tape condition. close/reopen hack here */ if ( IS_BOT( mtstat )) { mlog( MLOG_DEBUG | MLOG_DRIVE, "reopening drive while at BOT\n" ); Close( drivep ); if ( ! Open( drivep )) { display_access_failed_message( drivep ); *statp = DRIVE_ERROR_DEVICE; return 0; } if ( ! mt_get_status( drivep, &mtstat )) { status_failed_message( drivep ); *statp = DRIVE_ERROR_DEVICE; return 0; } assert( IS_BOT(mtstat )); *statp = DRIVE_ERROR_BOM; return 0; } /* check if already at (and to right of) file mark and * count is zero. */ if ( IS_FMK( mtstat ) && count == 0 ) { return 0; } /* back space - places us to left of previous file mark */ assert( drivep->d_capabilities & DRIVE_CAP_BSF ); mtstat = bsf_and_verify( drivep ); /* check again for beginning-of-tape condition */ if ( IS_BOT( mtstat )) { *statp = DRIVE_ERROR_BOM; return 0; } /* should be to the left of a file mark. drive status * indicates file mark whether to left or right - for * TS devices !!! LINUX ST tape driver only reports * GMT_EOF to the right of the filemark !! */ if ( TS_ISDRIVER ) { if ( ! IS_FMK( mtstat )) { *statp = DRIVE_ERROR_DEVICE; return 0; } } /* now loop, skipping media files */ for ( skipped = 0 ; skipped < count ; skipped++ ) { /* move to the left of the next file mark on the left. * check for BOT. */ mtstat = bsf_and_verify( drivep ); if ( IS_BOT( mtstat )) { *statp = DRIVE_ERROR_BOM; return skipped + 1; } if ( TS_ISDRIVER ) { if ( ! IS_FMK( mtstat )) { *statp = DRIVE_ERROR_DEVICE; return 0; } } } /* finally, move to the right side of the file mark */ mtstat = fsf_and_verify( drivep ); if( IS_EOT( mtstat )) { *statp = DRIVE_ERROR_EOM; } if ( ! IS_FMK( mtstat )) { *statp = DRIVE_ERROR_DEVICE; } /* indicate the number of media files skipped */ return skipped; } /* do_rewind * Position the tape at the beginning of the recorded media. * * RETURNS: * 0 on success * DRIVE_ERROR_* on failure */ static int do_rewind( drive_t *drivep ) { #ifdef DEBUG drive_context_t *contextp = (drive_context_t *)drivep->d_contextp; #endif mtstat_t mtstat; mlog( MLOG_DEBUG | MLOG_DRIVE, "drive op: rewind\n" ); assert( contextp->dc_mode == OM_NONE ); assert( contextp->dc_fd >= 0 ); /* use validating tape rewind util func */ mtstat = rewind_and_verify( drivep ); if ( ! IS_BOT( mtstat )) { return DRIVE_ERROR_DEVICE; } else { return 0; } } /* do_erase * erase media from beginning * * RETURNS: * 0 on success * DRIVE_ERROR_* on failure */ static int do_erase( drive_t *drivep ) { #ifdef DEBUG drive_context_t *contextp = (drive_context_t *)drivep->d_contextp; #endif mtstat_t mtstat; mlog( MLOG_DEBUG | MLOG_DRIVE, "drive op: erase\n" ); assert( contextp->dc_mode == OM_NONE ); assert( contextp->dc_fd >= 0 ); /* use validating tape rewind util func */ mtstat = rewind_and_verify( drivep ); if ( ! IS_BOT( mtstat )) { return DRIVE_ERROR_DEVICE; } /* use validating tape erase util func */ ( void )erase_and_verify( drivep ); /* rewind again */ mtstat = rewind_and_verify( drivep ); if ( ! IS_BOT( mtstat )) { return DRIVE_ERROR_DEVICE; } /* close the drive so we start from scratch */ Close( drivep ); return 0; } /* do_eject * pop the tape out - may be a nop on some drives * * RETURNS: * 0 on success * DRIVE_ERROR_DEVICE on failure */ static int do_eject_media( drive_t *drivep ) { drive_context_t *contextp = (drive_context_t *)drivep->d_contextp; mlog( MLOG_DEBUG | MLOG_DRIVE, "drive op: eject media\n" ); /* drive must be open */ assert( contextp->dc_fd >= 0 ); assert( contextp->dc_mode == OM_NONE ); /* issue tape unload */ if ( contextp->dc_unloadokpr ) { ( void )mt_op( contextp->dc_fd, MTUNLOAD, 0 ); } /* close the device driver */ Close( drivep ); return 0; } /* do_get_device_class * Return the device class * * RETURNS: * always returns DEVICE_TAPE_REMOVABLE */ /* ARGSUSED */ static int do_get_device_class( drive_t *drivep) { mlog( MLOG_DEBUG | MLOG_DRIVE, "drive op: get device class\n" ); return DEVICE_TAPE_REMOVABLE; } /* do_display_metrics - print ring stats if using I/O ring */ static void do_display_metrics( drive_t *drivep ) { drive_context_t *contextp = (drive_context_t *)drivep->d_contextp; ring_t *ringp = contextp->dc_ringp; if ( ringp ) { if ( drivecnt > 1 ) { mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK | MLOG_DRIVE, _("drive %u "), drivep->d_index ); } display_ring_metrics( drivep, MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK ); } } /* do_quit */ static void do_quit( drive_t *drivep ) { drive_context_t *contextp = (drive_context_t *)drivep->d_contextp; ring_t *ringp = contextp->dc_ringp; mlog( MLOG_DEBUG | MLOG_DRIVE, "drive op: quit\n" ); /* print the ring metrics and kill the ring */ if ( ringp ) { display_ring_metrics( drivep, MLOG_VERBOSE ); /* tell slave to die */ mlog( (MLOG_NITTY + 1) | MLOG_DRIVE, "ring op: destroy\n" ); ring_destroy( ringp ); } if ( ! contextp->dc_isvarpr && ! contextp->dc_isQICpr && contextp->dc_cansetblkszpr && ( contextp->dc_origcurblksz != 0 ) ) { ( void )set_fixed_blksz( drivep, contextp->dc_origcurblksz ); } /* issue tape unload */ if ( contextp->dc_unloadokpr ) { ( void )mt_op( contextp->dc_fd, MTUNLOAD, 0 ); } mlog( MLOG_DEBUG | MLOG_DRIVE, "drive op quit complete\n" ); } static double percent64( off64_t num, off64_t denom ) { return ( double )( num * 100 ) / ( double )denom; } /* read_label * responsible for reading and validating the first record from a * media file. can assume that prepare_drive has already been run * on this tape. if read fails due to an encounter with a file mark, * end of media, or end of data, position the media to allow an * append. * * RETURNS: * 0 on success * DRIVE_ERROR_* on failure */ /* * Notes for restoring in Linux/IRIX. * These are the assumption being made about the scsi tape drivers * in IRIX and Linux. * The 1st read() below is made prior to calling read_label(). * The 2nd read() is the one made inside read_label(). * Extraneous status flags, such as online, are not mentioned. * * ----------------------------------------- * Full tape (incomplete dump - over >1 tapes) * * Linux * read->0 * read->0 <<<**** caused my problem * * IRIX * read->0 * read->-1 (ENOSPC) * ----------------------------------------- * Partial tape (complete dump - just 1 tape) * * Linux * read->0 * read->0 * * IRIX * read->0 * read->-1 (ENOSPC) * ----------------------------------------- */ static int read_label( drive_t *drivep ) { drive_context_t *contextp; int nread; int saved_errno; mtstat_t mtstat; bool_t wasatbotpr; int rval; bool_t ok; /* initialize context ptr */ contextp = ( drive_context_t * )drivep->d_contextp; /* if not at BOT or a file mark, advance to right of next file mark */ ok = mt_get_status( drivep, &mtstat ); if ( ! ok ) { status_failed_message( drivep ); return DRIVE_ERROR_DEVICE; } if ( ! IS_BOT( mtstat ) && ! IS_FMK( mtstat )) { mtstat = fsf_and_verify( drivep ); } /* if we hit EOM or early warning, just return */ if ( IS_EOT( mtstat ) || IS_EW( mtstat )) { mlog( MLOG_DEBUG | MLOG_DRIVE, "begin read hit EOM/EW\n" ); return DRIVE_ERROR_EOM; } /* if we hit EOD, a file mark is missing */ if ( IS_EOD( mtstat )) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("file mark missing from tape (hit EOD)\n") ); #ifdef DUMP mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("writing file mark at EOD\n") ); rval = mt_op( contextp->dc_fd, MTWEOF, 1 ); if ( rval ) { mlog( MLOG_NORMAL | MLOG_WARNING, _("unable to write file mark at eod: %s (%d)\n"), strerror( errno ), errno ); return DRIVE_ERROR_MEDIA; } ok = mt_get_status( drivep, &mtstat ); if ( ! ok ) { status_failed_message( drivep ); return DRIVE_ERROR_DEVICE; } #endif /* DUMP */ } /* verify we are either at BOT or a file mark */ if ( ! IS_BOT( mtstat ) && ! IS_FMK( mtstat )) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("file mark missing from tape\n") ); #ifdef DUMP return DRIVE_ERROR_MEDIA; #endif } /* remember if we were at BOT, so we know how to reposition if EOD * encountered */ if ( IS_BOT( mtstat )) { wasatbotpr = BOOL_TRUE; } else { wasatbotpr = BOOL_FALSE; } /* read the first record of the media file directly */ nread = Read( drivep, contextp->dc_recp, tape_recsz, &saved_errno ); /* if a read error, get status */ if ( nread != ( int )tape_recsz ) { assert( nread < ( int )tape_recsz ); ok = mt_get_status( drivep, &mtstat ); if ( ! ok ) { status_failed_message( drivep ); return DRIVE_ERROR_DEVICE; } } else { mtstat = 0; } /* check for an unexpected errno */ if ( nread < 0 && saved_errno != ENOSPC ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("could not read from drive: %s (%d)\n"), strerror( errno ), errno ); return DRIVE_ERROR_DEVICE; } /* check for a blank tape. NOTE: shouldn't get here! */ if ( nread == 0 && wasatbotpr ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("unexpectedly encountered EOD at BOT: " "assuming corrupted media\n") ); ( void )rewind_and_verify( drivep ); return DRIVE_ERROR_MEDIA; } /* if we hit end of tape or early warning, indicate EOM */ if ( IS_EOT( mtstat ) || IS_EW( mtstat )) { mlog( MLOG_DEBUG | MLOG_DRIVE, "hit EOM\n" ); return DRIVE_ERROR_EOM; } #ifdef DUMP /* if we hit EOD, re-position in anticipation of appending. */ if ( IS_EOD( mtstat )) { mlog( MLOG_DEBUG | MLOG_DRIVE, "hit EOD: repositioning for append\n" ); if ( drivep->d_capabilities & DRIVE_CAP_BSF ) { ( void )bsf_and_verify( drivep ); } ( void )fsf_and_verify( drivep ); return DRIVE_ERROR_EOD; } #endif /* DUMP */ #ifdef RESTORE /* Linux case */ if ( IS_EOD( mtstat ) && IS_FMK( mtstat ) ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "hit EOM\n" ); return DRIVE_ERROR_EOM; } if ( IS_EOD( mtstat )) { mlog( MLOG_DEBUG | MLOG_DRIVE, "hit EOD\n" ); return DRIVE_ERROR_EOD; } #endif /* RESTORE */ /* if we hit a file mark, this is very bad. * indicates the media has been corrupted */ if ( IS_FMK( mtstat )) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("unexpectedly encountered a file mark: " "assuming corrupted media\n") ); ( void )rewind_and_verify( drivep ); return DRIVE_ERROR_MEDIA; } /* dc_iocnt is count of number of records read without error */ contextp->dc_iocnt = 1; rval = validate_media_file_hdr( drivep ); return rval; } static int validate_media_file_hdr( drive_t *drivep ) { global_hdr_t *grhdrp = drivep->d_greadhdrp; drive_hdr_t *drhdrp = drivep->d_readhdrp; rec_hdr_t *tprhdrp = (rec_hdr_t *)drhdrp->dh_specific; media_hdr_t *mrhdrp = (media_hdr_t *)drhdrp->dh_upper; content_hdr_t *ch = (content_hdr_t *)mrhdrp->mh_upper; content_inode_hdr_t *cih = (content_inode_hdr_t *)ch->ch_specific; drive_context_t *contextp = (drive_context_t *)drivep->d_contextp; char tmpbuf[GLOBAL_HDR_SZ]; global_hdr_t *tmpgh = (global_hdr_t *)&tmpbuf[0]; drive_hdr_t *tmpdh = (drive_hdr_t *)tmpgh->gh_upper; media_hdr_t *tmpmh = (media_hdr_t *)tmpdh->dh_upper; rec_hdr_t *tmprh = (rec_hdr_t *)tmpdh->dh_specific; content_hdr_t *tmpch = (content_hdr_t *)tmpmh->mh_upper; content_inode_hdr_t *tmpcih = (content_inode_hdr_t *)tmpch->ch_specific; mlog( MLOG_DEBUG | MLOG_DRIVE, "validating media file header\n" ); memcpy( tmpbuf, contextp->dc_recp, GLOBAL_HDR_SZ ); mlog(MLOG_NITTY, "validate_media_file_hdr\n" "\tgh_magic %.100s\n" "\tgh_version %u\n" "\tgh_checksum %u\n" "\tgh_timestamp %u\n" "\tgh_ipaddr %llu\n" "\tgh_hostname %.100s\n" "\tgh_dumplabel %.100s\n", tmpgh->gh_magic, tmpgh->gh_version, tmpgh->gh_checksum, tmpgh->gh_timestamp, tmpgh->gh_ipaddr, tmpgh->gh_hostname, tmpgh->gh_dumplabel); /* check the checksum */ if ( ! global_hdr_checksum_check( tmpgh )) { mlog( MLOG_DEBUG | MLOG_DRIVE, "bad media file header checksum\n"); return DRIVE_ERROR_CORRUPTION; } if ( ! tape_rec_checksum_check( contextp, contextp->dc_recp )) { mlog( MLOG_DEBUG | MLOG_DRIVE, "tape record checksum error\n"); return DRIVE_ERROR_CORRUPTION; } xlate_global_hdr(tmpgh, grhdrp, 1); xlate_drive_hdr(tmpdh, drhdrp, 1); xlate_media_hdr(tmpmh, mrhdrp, 1); xlate_content_hdr(tmpch, ch, 1); xlate_content_inode_hdr(tmpcih, cih, 1); xlate_rec_hdr(tmprh, tprhdrp, 1); memcpy( contextp->dc_recp, grhdrp, GLOBAL_HDR_SZ ); /* check the magic number */ if ( strncmp( grhdrp->gh_magic, GLOBAL_HDR_MAGIC,GLOBAL_HDR_MAGIC_SZ)) { mlog( MLOG_DEBUG | MLOG_DRIVE, "missing magic number in tape label\n"); return DRIVE_ERROR_FORMAT; } /* check the version */ if ( global_version_check( grhdrp->gh_version ) != BOOL_TRUE ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "invalid version number (%d) in tape label\n", grhdrp->gh_version ); return DRIVE_ERROR_VERSION; } /* check the strategy id */ if ( drhdrp->dh_strategyid != drivep->d_strategyp->ds_id ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "unrecognized drive strategy ID (%d)\n", drivep->d_readhdrp->dh_strategyid ); return DRIVE_ERROR_FORMAT; } /* check the record magic number */ if ( tprhdrp->magic != STAPE_MAGIC ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "invalid record magic number in tape label\n"); return DRIVE_ERROR_FORMAT; } /* check the record version number */ if ( tprhdrp->version != STAPE_VERSION ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "invalid record version number in tape label\n"); return DRIVE_ERROR_VERSION; } mlog( MLOG_DEBUG | MLOG_DRIVE, "media file header valid: " "media file ix %d\n", mrhdrp->mh_mediafileix ); return 0; } /* set_fixed_blksz() * Issue the MTSETBLK ioctl to set the tape block size. * Before issuing the call, close/reopen the device. * if fails, rewind and try again. This is done to set the tape to BOT * and to turn the CT_MOTION flag off so that the MTSETBLK call will * succeed. If the call still fails, print an error but keep running. * * RETURNS: * TRUE on success * FALSE on failure */ static bool_t set_fixed_blksz( drive_t *drivep, size_t blksz ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; ix_t try; /* sanity checks */ assert( blksz ); assert( contextp->dc_isvarpr == BOOL_FALSE ); assert( contextp->dc_cansetblkszpr ); assert( contextp->dc_fd >= 0 ); /* give it two tries: first without rewinding, second with rewinding */ for ( try = 1 ; try <= 2 ; try++ ) { struct mtblkinfo mtinfo; /* set the tape block size. requires re-open */ mlog( MLOG_DEBUG | MLOG_DRIVE, "setting fixed block size to %d\n", blksz ); /* close and re-open */ Close( drivep ); if ( ! Open( drivep )) { display_access_failed_message( drivep ); return BOOL_FALSE; } /* issue call to set block size */ if ( mt_op( contextp->dc_fd, MTSETBLK, ( int )blksz ) ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "MTSETBLK %u failed: %s (%d)\n", blksz, strerror( errno ), errno); } /* see if we were successful (can't look if RMT, so assume * it worked) */ if ( ! contextp->dc_isrmtpr ) { bool_t ok; ok = mt_blkinfo( contextp->dc_fd, &mtinfo ); if ( ! ok ) { return BOOL_FALSE; } if ( mtinfo.curblksz == blksz ) { return BOOL_TRUE; } } else { return BOOL_TRUE; } /* so rewind and try again */ ( void )rewind_and_verify( drivep ); } mlog( MLOG_NORMAL | MLOG_DRIVE, _("unable to set block size to %d\n"), blksz ); return BOOL_FALSE; } /* get_tpcaps * Get the specific tape drive capabilities. Set the * d_capabilities field of the driver structure. * set the blksz limits and tape type in the context structure. * * RETURNS: * TRUE on success * FALSE on error */ static bool_t get_tpcaps( drive_t *drivep ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; assert( contextp->dc_fd >= 0 ); if ( contextp->dc_isrmtpr ) { /* can't ask about blksz, can't set blksz, can't ask about * drive types/caps. assume a drive which can overwrite. * assume NOT QIC, since fixed blksz devices not supported * via RMT. */ contextp->dc_maxblksz = 0; contextp->dc_isQICpr = BOOL_FALSE; contextp->dc_cangetblkszpr = BOOL_FALSE; contextp->dc_cansetblkszpr = BOOL_FALSE; drivep->d_capabilities |= DRIVE_CAP_OVERWRITE; drivep->d_capabilities |= DRIVE_CAP_BSF; } else { /* not remote, so we can ask the driver */ struct mtblkinfo mtinfo; bool_t ok; ok = mt_blkinfo( contextp->dc_fd, &mtinfo ); if ( ! ok ) { return BOOL_FALSE; } contextp->dc_canfsrpr = BOOL_FALSE; if (contextp->dc_isQICpr) { contextp->dc_cangetblkszpr = BOOL_FALSE; contextp->dc_cansetblkszpr = BOOL_FALSE; contextp->dc_maxblksz = QIC_BLKSZ; drivep->d_capabilities &= ~DRIVE_CAP_OVERWRITE; drivep->d_capabilities &= ~DRIVE_CAP_BSF; } else { contextp->dc_cangetblkszpr = BOOL_TRUE; contextp->dc_cansetblkszpr = BOOL_TRUE; contextp->dc_maxblksz = mtinfo.maxblksz; if ( contextp->dc_origcurblksz == 0 ) contextp->dc_origcurblksz = mtinfo.curblksz; drivep->d_capabilities |= DRIVE_CAP_OVERWRITE; drivep->d_capabilities |= DRIVE_CAP_BSF; #ifdef HIDDEN Need to find equivalent in Linux. if ( mtcapablity & MTCAN_SEEK ) { contextp->dc_canfsrpr = BOOL_TRUE; } #endif } } set_recommended_sizes( drivep ); return BOOL_TRUE; } /* set_recommended_sizes * Determine the recommended tape file size and mark separation * based on tape device type. * * RETURNS: * void */ static void set_recommended_sizes( drive_t *drivep ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; off64_t fsize = drive_strategy_scsitape.ds_recmfilesz; off64_t marksep = drive_strategy_scsitape.ds_recmarksep; if (contextp->dc_filesz > 0) { fsize = contextp->dc_filesz; #ifdef DUMP if ( hdr_mfilesz > fsize ) { mlog( MLOG_WARNING, _( "recommended media file size of %llu Mb less than" " estimated file header size %llu Mb for %s\n"), fsize / ( 1024 * 1024 ), hdr_mfilesz / ( 1024 * 1024 ), drivep->d_pathname ); } #endif /* DUMP */ } mlog( MLOG_DEBUG | MLOG_DRIVE, "recommended tape media file size set to 0x%llx bytes\n", fsize ); mlog( MLOG_DEBUG | MLOG_DRIVE, "recommended tape media mark separation set to 0x%llx bytes\n", marksep ); drivep->d_recmfilesz = fsize; drivep->d_recmarksep = marksep; return; } /* mt_blkinfo * In IRIX, issue MTIOGETBLKINFO ioctl operation to the tape device. * There is no equivalent call in Linux at the moment. * However, the minblks and maxblks are stored internally in * the scsi/st.c driver and may be exported in the future. * The current blk size comes from the mt_dsreg field. * * RETURNS: * TRUE on success * FALSE on failure */ static bool_t mt_blkinfo( int fd, struct mtblkinfo *minfo ) { struct mtget mt_stat; mlog( MLOG_DEBUG | MLOG_DRIVE, "tape op: get block size info\n" ); if (TS_ISDRIVER) { /* Use TS ioctl MTIOCGETBLKINFO so we don't * have to hard code the max block size */ struct mtblkinfo ts_blkinfo; if ( ioctl(fd, MTIOCGETBLKINFO, &ts_blkinfo) < 0 ) { /* failure */ mlog(MLOG_DEBUG, "tape command MTIOCGETBLKINFO failed : %d (%s)\n", errno, strerror( errno )); return BOOL_FALSE; } minfo->curblksz = ts_blkinfo.curblksz; minfo->maxblksz = ts_blkinfo.maxblksz; } else { if ( ioctl(fd, MTIOCGET, &mt_stat) < 0 ) { /* failure */ mlog(MLOG_DEBUG, "tape command MTIOCGET failed : %d (%s)\n", errno, strerror( errno )); return BOOL_FALSE; } minfo->curblksz = (mt_stat.mt_dsreg >> MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK; minfo->maxblksz = STAPE_MAX_LINUX_RECSZ; } mlog( MLOG_NITTY | MLOG_DRIVE, "max=%u cur=%u\n", minfo->maxblksz, minfo->curblksz); /* success */ return BOOL_TRUE; } /* mt_op * Issue MTIOCTOP ioctl operation to the tape device. * * RETURNS: * 0 on success * -1 on failure */ static int mt_op(int fd, int sub_op, int param ) { struct mtop mop; char *printstr; int rval; mop.mt_op = (short )sub_op; mop.mt_count = param; assert( fd >= 0 ); switch ( sub_op ) { case MTSEEK: printstr = "seek"; break; case MTBSF: printstr = "back space file"; break; case MTWEOF: printstr = "write file mark"; break; case MTFSF: printstr = "forward space file"; break; case MTREW: printstr = "rewind"; break; case MTUNLOAD: printstr = "unload"; break; case MTEOM: printstr = "advance to EOD"; break; case MTFSR: printstr = "forward space block"; break; case MTERASE: printstr = "erase"; break; case MTSETBLK: printstr = "set block size"; break; default: printstr = "???"; break; } mlog( MLOG_DEBUG | MLOG_DRIVE, "tape op: %s %d\n", printstr, param ); rval = ioctl( fd, MTIOCTOP, &mop ); if ( rval < 0 ) { /* failure */ mlog( MLOG_DEBUG | MLOG_DRIVE, "tape op %s %d returns %d: errno == %d (%s)\n", printstr, param, rval, errno, strerror( errno )); return -1; } /* success */ return 0; } static bool_t mt_get_fileno( drive_t *drivep, long *fileno) { struct mtget mt_stat; drive_context_t *contextp; contextp = ( drive_context_t * )drivep->d_contextp; mlog( MLOG_DEBUG | MLOG_DRIVE, "tape op: get fileno\n" ); assert( contextp->dc_fd >= 0 ); if ( ioctl(contextp->dc_fd, MTIOCGET, &mt_stat) < 0 ) { /* failure */ mlog(MLOG_DEBUG, "tape command MTIOCGET failed : %d (%s)\n", errno, strerror( errno )); return BOOL_FALSE; } *fileno = mt_stat.mt_fileno; return BOOL_TRUE; } /* mt_get_status * Get the current status of the tape device. * * RETURNS: * TRUE if status was obtained * FALSE if not */ static bool_t mt_get_status( drive_t *drivep, long *status) { struct mtget mt_stat; drive_context_t *contextp; contextp = ( drive_context_t * )drivep->d_contextp; mlog( MLOG_DEBUG | MLOG_DRIVE, "tape op: get status\n" ); assert( contextp->dc_fd >= 0 ); if (TS_ISDRIVER) { /* * Call the MTIOCGET_SGI ioctl for TS devices, then * map the results into ST format (mtget) using the * TS workaround routine called map_ts_status(). * See comments in map_ts_status() for more detail. */ struct mtget_sgi mt_stat_sgi; if ( ioctl(contextp->dc_fd, MTIOCGET_SGI, &mt_stat_sgi) < 0 ) { /* failure */ mlog(MLOG_DEBUG, "tape command MTIOCGET_SGI failed : %d (%s)\n", errno, strerror( errno )); return BOOL_FALSE; } map_ts_status( &mt_stat, mt_stat_sgi ); } else { if ( ioctl(contextp->dc_fd, MTIOCGET, &mt_stat) < 0 ) { /* failure */ mlog(MLOG_DEBUG, "tape command MTIOCGET failed : %d (%s)\n", errno, strerror( errno )); return BOOL_FALSE; } } /* success */ *status = mt_stat.mt_gstat; /* print out symbolic form of tape status */ mlog( MLOG_DEBUG | MLOG_DRIVE, "tape status = %s%s%s%s%s%s%s\n", IS_BOT(*status)? "bot ":"", IS_FMK(*status)? "fmk ":"", IS_EOD(*status)? "eod ":"", IS_EOT(*status)? "eot ":"", IS_EW(*status)? "ew ":"", IS_WPROT(*status)? "wprot ":"", IS_ONL(*status)? "onl ":""); return BOOL_TRUE; } /* determine_write_error() * Using the errno and the tape status information, determine the * type of tape write error that has occured. * * RETURNS: * DRIVE_ERROR_* */ static int determine_write_error( drive_t *drivep, int nwritten, int saved_errno ) { mtstat_t mtstat; int ret; drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; /* get tape device status */ if ( ! mt_get_status( drivep, &mtstat) ) { status_failed_message( drivep ); ret = DRIVE_ERROR_DEVICE; } else if ( IS_WPROT(mtstat) && (saved_errno == EROFS)) { mlog(MLOG_NORMAL, _("tape is write protected\n")); ret = DRIVE_ERROR_DEVICE; } else if ( (!IS_BOT(mtstat)) && (IS_EOT( mtstat ) || IS_EW( mtstat) || (saved_errno == ENOSPC))) { ret = DRIVE_ERROR_EOM; } else if (saved_errno == EIO ) { mlog(MLOG_NORMAL, _("tape media error on write operation\n")); mlog(MLOG_NORMAL, _("no more data can be written to this tape\n")); ret = DRIVE_ERROR_EOM; } else if ( (saved_errno == 0) && (nwritten > 0) && contextp->dc_isQICpr ) { /* short write on one of this devices indicates * early warning for end-of-media. */ ret = DRIVE_ERROR_EOM; } else { ret = DRIVE_ERROR_CORE; mlog( MLOG_DEBUG | MLOG_DRIVE, "tape unknown error on write operation: " "0x%x, %d, %d\n", mtstat, nwritten, saved_errno); } mlog( MLOG_NITTY | MLOG_DRIVE, "tape write operation status 0x%x, nwritten %d, errno %d\n", mtstat, nwritten, saved_errno); return ( ret ); } static void tape_rec_checksum_set( drive_context_t *contextp, char *bufp ) { rec_hdr_t *rechdrp = ( rec_hdr_t * )bufp; uint32_t *beginp = ( uint32_t * )bufp; uint32_t *endp = ( uint32_t * )( bufp + tape_recsz ); uint32_t *p; uint32_t accum; if ( ! contextp->dc_recchksumpr ) { return; } INT_SET(rechdrp->ischecksum, ARCH_CONVERT, 1); rechdrp->checksum = 0; accum = 0; for ( p = beginp ; p < endp ; p++ ) { accum += INT_GET(*p, ARCH_CONVERT); } INT_SET(rechdrp->checksum, ARCH_CONVERT, ( int32_t )( ~accum + 1 )); } static bool_t tape_rec_checksum_check( drive_context_t *contextp, char *bufp ) { rec_hdr_t *rechdrp = ( rec_hdr_t * )bufp; uint32_t *beginp = ( uint32_t * )bufp; uint32_t *endp = ( uint32_t * )( bufp + tape_recsz ); uint32_t *p; uint32_t accum; if ( contextp->dc_recchksumpr && INT_GET(rechdrp->ischecksum, ARCH_CONVERT)) { accum = 0; for ( p = beginp ; p < endp ; p++ ) { accum += INT_GET(*p, ARCH_CONVERT); } return accum == 0 ? BOOL_TRUE : BOOL_FALSE; } else { return BOOL_TRUE; } } /* to trace rmt operations */ #ifdef RMTDBG static int dbgrmtopen( char *path, int flags ) { int rval; rval = rmtopen( path, flags ); mlog( MLOG_NORMAL | MLOG_DRIVE, _("RMTOPEN( %s, %d ) returns %d: errno=%d (%s)\n"), path, flags, rval, errno, strerror( errno )); return rval; } static int dbgrmtclose( int fd ) { int rval; rval = rmtclose( fd ); mlog( MLOG_NORMAL | MLOG_DRIVE, _("RMTCLOSE( %d ) returns %d: errno=%d (%s)\n"), fd, rval, errno, strerror( errno )); return rval; } static int dbgrmtioctl( int fd, int op, void *arg ) { int rval; rval = rmtioctl( fd, op, arg ); mlog( MLOG_NORMAL | MLOG_DRIVE, _("RMTIOCTL( %d, %d, 0x%x ) returns %d: errno=%d (%s)\n"), fd, op, arg, rval, errno, strerror( errno )); return rval; } static int dbgrmtread( int fd, void *p, uint sz ) { int rval; rval = rmtread( fd, p, sz ); mlog( MLOG_NORMAL | MLOG_DRIVE, _("RMTREAD( %d, 0x%x, %u ) returns %d: errno=%d (%s)\n"), fd, p, sz, rval, errno, strerror( errno )); return rval; } static int dbgrmtwrite( int fd, void *p, uint sz ) { int rval; rval = rmtwrite( fd, p, sz ); mlog( MLOG_NORMAL | MLOG_DRIVE, _("RMTWRITE( %d, 0x%x, %u ) returns %d: errno=%d (%s)\n"), fd, p, sz, rval, errno, strerror( errno )); return rval; } #endif /* RMTDBG */ /* display_access_failed_message() * Print tape device open/access failed message. * * RETURNS: * void */ static void display_access_failed_message( drive_t *drivep ) { drive_context_t *contextp; /* get pointer to drive context */ contextp = ( drive_context_t * )drivep->d_contextp; if ( contextp->dc_isrmtpr ) { mlog( MLOG_NORMAL | MLOG_DRIVE, _("attempt to access/open remote " "tape drive %s failed: %d (%s)\n"), drivep->d_pathname, errno, strerror( errno )); } else { mlog( MLOG_NORMAL | MLOG_DRIVE, _("attempt to access/open device %s failed: %d (%s)\n"), drivep->d_pathname, errno, strerror( errno )); } return; } /* status_failed_message() * Print tape status device failed message. * * RETURNS: * one */ static void status_failed_message( drive_t *drivep ) { drive_context_t *contextp; /* get pointer to drive context */ contextp = ( drive_context_t * )drivep->d_contextp; /* the get status call could have failed due to the * tape device being closed by a CTLR-\ from the operator. */ if ( contextp->dc_fd != -1 ) { if ( contextp->dc_isrmtpr ) { mlog( MLOG_NORMAL | MLOG_DRIVE, _("attempt to get status of remote " "tape drive %s failed: %d (%s)\n"), drivep->d_pathname, errno, strerror( errno )); } else { mlog( MLOG_NORMAL | MLOG_DRIVE, _("attempt to get status of " "tape drive %s failed: %d (%s)\n"), drivep->d_pathname, errno, strerror( errno )); } } return; } static bool_t is_variable( drive_t *drivep, bool_t *varblk ) { drive_context_t *contextp; contextp = ( drive_context_t * )drivep->d_contextp; if (TS_ISDRIVER) { char value[MT_ATTR_MAX_VALLEN+1]; struct mt_attr mtattr; value[0] = '\0'; mtattr.ma_value = value; mtattr.ma_name = MT_ATTR_NAME_VARIABLE; mtattr.ma_vlen = sizeof(value); ioctl(contextp->dc_fd, MTGETATTR, &mtattr); if (strcmp(value, MT_ATTR_VALUE_TRUE) == 0) *varblk = BOOL_TRUE; else if (strcmp(value, MT_ATTR_VALUE_FALSE) == 0) *varblk = BOOL_FALSE; else return BOOL_FALSE; /* failure */ } else { bool_t ok; struct mtblkinfo minfo; ok = mt_blkinfo(contextp->dc_fd, &minfo); if (!ok ) return BOOL_FALSE; /* failure */ /* for Linux scsi driver the blksize == 0 if variable */ if (minfo.curblksz == 0) *varblk = BOOL_TRUE; else *varblk = BOOL_FALSE; } return BOOL_TRUE; } /* prepare_drive - called by begin_read if drive device not open. * determines record size and sets block size if fixed block device. * determines other drive attributes. determines if any previous * xfsdumps on media. */ static int prepare_drive( drive_t *drivep ) { drive_context_t *contextp; mtstat_t mtstat; bool_t ok; ix_t try; ix_t maxtries; bool_t changedblkszpr; int rval; int varblk; /* get pointer to drive context */ contextp = ( drive_context_t * )drivep->d_contextp; retry: if ( cldmgr_stop_requested( )) { return DRIVE_ERROR_STOP; } /* shouldn't be here if drive is open */ assert( contextp->dc_fd == -1 ); mlog( MLOG_VERBOSE | MLOG_DRIVE, _("preparing drive\n") ); /* determine if tape is present or write protected. try several times. * if not present or write-protected during dump, return. */ maxtries = 15; for ( try = 1 ; ; sleep( 10 ), try++ ) { if ( cldmgr_stop_requested( )) { return DRIVE_ERROR_STOP; } /* open the drive */ ok = Open( drivep ); if ( ! ok ) { if ( errno != EBUSY ) { display_access_failed_message( drivep ); return DRIVE_ERROR_DEVICE; } else { mlog( MLOG_DEBUG | MLOG_DRIVE, "open drive returns EBUSY\n" ); if ( try >= maxtries ) { mlog( MLOG_TRACE | MLOG_DRIVE, "giving up waiting for drive " "to indicate online\n" ); return DRIVE_ERROR_MEDIA; } continue; } } /* read device status (uses an ioctl) */ mtstat = 0; ok = mt_get_status( drivep, &mtstat ); if ( ! ok ) { status_failed_message( drivep ); return DRIVE_ERROR_DEVICE; } /* look at status to check if the device is online. * also check if write-protected (DUMP only), and give up * after a few tries. */ if ( IS_ONL( mtstat )) { #ifdef DUMP if ( IS_WPROT( mtstat )) { mlog(MLOG_NORMAL, _("tape is write protected\n") ); return DRIVE_ERROR_MEDIA; } #endif /* DUMP */ /* populate a struct stat. NOTE: this may do a temporary open/close * NOTE: may do this only on local drives: rmt does not support! */ if ( contextp->dc_isrmtpr ) { contextp->dc_isvarpr = BOOL_FALSE; } else { /* check for special device dev_t for fixed or variable type * of device. set context and drive flags accordingly. */ if (is_variable(drivep, &varblk) == BOOL_FALSE) return DRIVE_ERROR_DEVICE; if (varblk) { contextp->dc_isvarpr = BOOL_TRUE; mlog( MLOG_TRACE | MLOG_DRIVE, "variable block size " "tape drive at %s\n", drivep->d_pathname ); } else { contextp->dc_isvarpr = BOOL_FALSE; mlog( MLOG_TRACE | MLOG_DRIVE, "fixed block size tape " "drive at %s\n", drivep->d_pathname ); } } break; } else if ( try >= maxtries ) { mlog( MLOG_VERBOSE | MLOG_DRIVE, _("giving up waiting for drive " "to indicate online\n") ); return DRIVE_ERROR_MEDIA; } /* drive is not ready. sleep for a while and try again */ mlog( MLOG_VERBOSE | MLOG_DRIVE, _("tape drive %s is not ready (0x%x): " "retrying ...\n"), drivep->d_pathname, mtstat ); Close( drivep ); } assert( IS_ONL( mtstat )); /* determine tape capabilities. this will set the drivep->d_capabilities * and contextp->dc_{...}blksz and dc_isQICpr, as well as recommended * mark separation and media file size. */ ok = get_tpcaps( drivep ); if ( ! ok ) { return DRIVE_ERROR_DEVICE; } /* disallow access of QIC via variable */ if ( contextp->dc_isvarpr && contextp->dc_isQICpr ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_DRIVE, _( "use of QIC drives via variable blocksize device nodes " "is not supported\n") ); return DRIVE_ERROR_INVAL; } /* if the overwrite option was specified , set the best blocksize * we can and return. */ if ( contextp->dc_overwritepr ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "Overwrite option specified. " "Trying best blocksize\n" ); ok = set_best_blk_and_rec_sz( drivep ); if ( ! ok ) { return DRIVE_ERROR_DEVICE; } return DRIVE_ERROR_OVERWRITE; } /* establish the initial block and record sizes we will try. * if unable to ask drive about fixed block sizes, we will * guess. */ calc_best_blk_and_rec_sz(drivep); /* if the drive status says we are at a file mark, there is * an ambiguity: we could be positioned just before or just * after the file mark. we want to always be positioned just after * file marks. To disambiguate and force positioning after, * we will use tape motion. back up two file marks, because * typically we will be positioned after last file mark at EOD. */ if ( ! IS_BOT( mtstat ) && IS_FMK( mtstat )) { mlog( MLOG_DEBUG | MLOG_DRIVE, "tape positioned at file mark, " "but do not know if before or after: " "forcing tape motion to disambiguate\n" ); #ifdef RESTORE ( void )fsf_and_verify( drivep ); #endif /* RESTORE */ rval = quick_backup( drivep, contextp, 0 ); if ( rval ) { return rval; } } /* loop trying to read a record. begin with the record size * calculated above. if it appears we have selected the wrong * block size and if we are able to alter the fixed block size, * and the record size we tried initially was not less than * the minmax block size, change the block size to minmax and * try to read a one block record again. * * ************** * LINUX WARNING: * ************** * This code has a lot of conditionals on the current status * and error result from the read. * Under Linux using the scsi tape driver, as opposed to IRIX, * the semantics may well be different for some error codes. * For example, it seems on Linux if we use an erased tape * then the first read returns an EIO, whereas on IRIX we would * get an ENOSPC. */ maxtries = 5; changedblkszpr = BOOL_FALSE; for ( try = 1 ; ; try++ ) { bool_t wasatbotpr; int nread; int saved_errno; if ( cldmgr_stop_requested( )) { return DRIVE_ERROR_STOP; } /* bail out if we've tried too many times */ if ( try > maxtries ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _( "giving up attempt to determining " "tape record size\n") ); return DRIVE_ERROR_MEDIA; } mlog( MLOG_DEBUG | MLOG_DRIVE, "determining tape record size: trying %d (0x%x) bytes\n", tape_recsz, tape_recsz ); /* if a fixed device, but not QIC, and possible to set the block * size, do so. */ if ( ! contextp->dc_isvarpr && ! contextp->dc_isQICpr && contextp->dc_cansetblkszpr ) { ok = set_fixed_blksz( drivep, tape_blksz ); if ( ! ok ) { return DRIVE_ERROR_DEVICE; } } /* refresh the tape status */ mtstat = 0; ok = mt_get_status( drivep, &mtstat ); if ( ! ok ) { status_failed_message( drivep ); return DRIVE_ERROR_DEVICE; } /* first ensure we are positioned at BOT or just after * a file mark. if the drive says we are at a file mark, we * don't know if we are just before or just after the file mark. * so we must either bsf or rewind to eliminate the uncertainty. * if BSF is not supported, must rewind. */ if ( ! IS_BOT( mtstat ) && ! IS_FMK( mtstat )) { mlog( MLOG_DEBUG | MLOG_DRIVE, "tape position unknown: searching backward " "for file mark or BOT\n" ); rval = quick_backup( drivep, contextp, 0 ); if ( rval ) { return rval; } mtstat = 0; ok = mt_get_status( drivep, &mtstat ); if ( ! ok ) { status_failed_message( drivep ); return DRIVE_ERROR_DEVICE; } } /* if we can't position the tape, call it a media error */ if ( ! IS_BOT( mtstat ) && ! IS_FMK( mtstat )) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("unable to backspace/rewind media\n") ); return DRIVE_ERROR_MEDIA; } if ( IS_BOT( mtstat )) { mlog( MLOG_DEBUG | MLOG_DRIVE, "tape positioned at BOT: " "doing redundant rewind\n" ); mtstat = rewind_and_verify( drivep ); if ( ! IS_BOT( mtstat )) { return DRIVE_ERROR_DEVICE; } } if ( IS_FMK( mtstat )) { mlog( MLOG_DEBUG | MLOG_DRIVE, "tape positioned at file mark\n" ); } /* determine if we are at BOT. remember, so if read fails * we can make a better decision on what to do next. */ if ( IS_BOT( mtstat )) { wasatbotpr = BOOL_TRUE; } else if ( IS_FMK( mtstat )) { wasatbotpr = BOOL_FALSE; } else { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("unable to backspace/rewind media\n") ); return DRIVE_ERROR_MEDIA; } /* read a record. use the first ring buffer */ saved_errno = 0; nread = Read( drivep, contextp->dc_recp, tape_recsz, &saved_errno ); assert( saved_errno == 0 || nread < 0 ); /* RMT can require a retry */ if ( saved_errno == EAGAIN ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "read returned EAGAIN: retrying\n" ); continue; } /* block size is bigger than buffer; should never happen */ if ( saved_errno == EINVAL ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "read returned EINVAL: " "trying new record size\n" ); goto largersize; } /* block size is bigger than buffer; should never happen */ if ( saved_errno == ENOMEM ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "read returned ENOMEM: " "trying new record size\n" ); goto largersize; } /* tried to read past EOD and was at BOT */ if ( saved_errno == ENOSPC && wasatbotpr ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "errno ENOSPC while at BOT " "indicates blank tape: returning\n" ); ( void )rewind_and_verify( drivep ); ok = set_best_blk_and_rec_sz( drivep ); if ( ! ok ) { return DRIVE_ERROR_DEVICE; } return DRIVE_ERROR_BLANK; } /* was at BOT and got EIO on read * On Linux, using the scsi tape driver this * seems to happen with an erased/blank tape */ if ( saved_errno == EIO && wasatbotpr ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "errno EIO while at BOT " "indicates blank tape: returning\n" ); ( void )rewind_and_verify( drivep ); ok = set_best_blk_and_rec_sz( drivep ); if ( ! ok ) { return DRIVE_ERROR_DEVICE; } return DRIVE_ERROR_BLANK; } /* tried to read past EOD and NOT at BOT */ if ( saved_errno == ENOSPC && ! wasatbotpr ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "errno ENOSPC while not at BOT " "indicates EOD: retrying\n" ); rval = quick_backup( drivep, contextp, 1 ); if ( rval ) { return rval; } continue; } /* I/O error */ if ( saved_errno == EIO ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "read returned EIO: will reopen, rewind, " "and try again\n" ); Close( drivep ); ok = Open( drivep ); if ( ! ok ) { display_access_failed_message( drivep ); return DRIVE_ERROR_DEVICE; } ( void )rewind_and_verify( drivep ); continue; } /* freshen up the tape status. useful in decision-making * done below. */ mtstat = 0; ok = mt_get_status( drivep, &mtstat ); if ( ! ok ) { status_failed_message( drivep ); return DRIVE_ERROR_DEVICE; } if ( nread == 0 && ! contextp->dc_isvarpr && IS_EOD( mtstat ) && wasatbotpr ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "nread == 0 and EOD while at BOT on " "fixed blocksize drive " "indicates blank tape: returning\n" ); ( void )rewind_and_verify( drivep ); ok = set_best_blk_and_rec_sz( drivep ); if ( ! ok ) { return DRIVE_ERROR_DEVICE; } return DRIVE_ERROR_BLANK; } if ( nread == 0 && ! contextp->dc_isvarpr && IS_EOD( mtstat ) && ! wasatbotpr ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "nread == 0 and EOD while not at BOT on " "fixed blocksize drive " "indicates EOD: backing up and retrying\n" ); rval = quick_backup( drivep, contextp, 1 ); if ( rval ) { return rval; } continue; } if ( nread == 0 && ! contextp->dc_isvarpr && IS_EOT( mtstat ) && ! wasatbotpr ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "nread == 0 and EOT while not at BOT on " "fixed blocksize drive " "indicates EOD: backing up and retrying\n" ); rval = quick_backup( drivep, contextp, 1 ); if ( rval ) { return rval; } continue; } if ( nread == 0 && ! contextp->dc_isvarpr && ! IS_EOD( mtstat ) && ! IS_FMK( mtstat ) && ! IS_EOT( mtstat )) { mlog( MLOG_DEBUG | MLOG_DRIVE, "nread == 0 and not EOD, not EOT, " "and not at a file mark on fixed blocksize drive " "indicates wrong blocksize\n" ); goto newsize; } if ( nread == 0 && contextp->dc_isvarpr && IS_EOD( mtstat ) && wasatbotpr ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "nread == 0 and EOD indication at BOT " "on variable tape " "indicates blank tape: returning\n" ); ( void )rewind_and_verify( drivep ); ok = set_best_blk_and_rec_sz( drivep ); if ( ! ok ) { return DRIVE_ERROR_DEVICE; } return DRIVE_ERROR_BLANK; } if ( nread == 0 && contextp->dc_isvarpr && IS_EOD( mtstat ) && ! wasatbotpr ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "nread == 0 and EOD while not at BOT on " "variable blocksize drive " "indicates EOD: backing up and retrying\n" ); rval = quick_backup( drivep, contextp, 1 ); if ( rval ) { return rval; } continue; } if ( nread == 0 && contextp->dc_isvarpr && IS_EOT( mtstat ) && ! wasatbotpr ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "nread == 0 and EOT while not at BOT on " "variable blocksize drive " "indicates EOT: backing up and retrying\n" ); rval = quick_backup( drivep, contextp, 1 ); if ( rval ) { return rval; } continue; } if ( nread == 0 && contextp->dc_isvarpr && IS_FMK( mtstat ) && wasatbotpr ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "nread == 0 at BOT and at a file mark " "on variable blocksize drive " "indicates foreign tape: returning\n" ); ( void )rewind_and_verify( drivep ); ok = set_best_blk_and_rec_sz( drivep ); if ( ! ok ) { return DRIVE_ERROR_DEVICE; } return DRIVE_ERROR_FOREIGN; } if ( nread > 0 && contextp->dc_isvarpr && ! IS_EOD( mtstat ) && ! IS_FMK( mtstat ) && ! IS_EOT( mtstat )) { mlog( MLOG_DEBUG | MLOG_DRIVE, "nread > 0 and not EOD, not EOT, " "and not at a file mark on variable blocksize drive " "indicates correct blocksize found\n" ); goto checkhdr; } if ( nread < ( int )tape_recsz && ! contextp->dc_isvarpr ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "nread less than selected record size on " "fixed blocksize drive " "indicates wrong blocksize\n" ); goto newsize; } if ( nread == ( int )tape_recsz && ! contextp->dc_isvarpr ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "nread == selected blocksize " "on fixed blocksize drive " "indicates correct blocksize found\n" ); goto checkhdr; } /* if we fell through the seive, code is wrong. * display useful info and abort */ mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_DRIVE, _( "unexpected tape error: " "errno %d " "nread %d " "blksz %d " "recsz %d " "isvar %d " "wasatbot %d " "eod %d " "fmk %d " "eot %d " "onl %d " "wprot %d " "ew %d " "\n"), saved_errno, nread, tape_blksz, tape_recsz, !! contextp->dc_isvarpr, wasatbotpr, IS_EOD( mtstat ) > 0, IS_FMK( mtstat ) > 0, IS_EOT( mtstat ) > 0, IS_ONL( mtstat ) > 0, IS_WPROT( mtstat ) > 0, IS_EW( mtstat ) > 0, 0 ); /* Common Linux Problem */ if (errno == EOVERFLOW) { mlog( MLOG_NORMAL | MLOG_NOTE | MLOG_DRIVE, _("likely problem is that the block size, %d, " "is too large for Linux\n"), tape_blksz); mlog( MLOG_NORMAL | MLOG_NOTE | MLOG_DRIVE, _("either try using a smaller block size with " "the -b option, or increase max_sg_segs for " "the scsi tape driver\n")); } return DRIVE_ERROR_CORE; checkhdr: rval = validate_media_file_hdr( drivep ); if ( rval ) { if ( rval == DRIVE_ERROR_VERSION ) { global_hdr_t *grhdrp = drivep->d_greadhdrp; mlog( MLOG_NORMAL | MLOG_DRIVE, _("media file header version (%d) " "invalid: advancing\n"), grhdrp->gh_version ); continue; } else if ( wasatbotpr ) { if ( isefsdump( drivep )) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("may be an EFS dump at BOT\n")); } else { mlog( MLOG_NORMAL | MLOG_DRIVE, _("bad media file header at BOT " "indicates foreign or " "corrupted tape\n")); } ( void )rewind_and_verify( drivep ); ok = set_best_blk_and_rec_sz( drivep ); if ( ! ok ) { return DRIVE_ERROR_DEVICE; } return DRIVE_ERROR_FOREIGN; } else { /* back up and try again. */ mlog( MLOG_DEBUG | MLOG_DRIVE, "media file header invalid: " "backing up " "to try a previous media file\n" ); rval = quick_backup( drivep, contextp, 1 ); if ( rval ) { return rval; } continue; } } else { drive_hdr_t *drhdrp; rec_hdr_t *tprhdrp; drhdrp = drivep->d_readhdrp; tprhdrp = ( rec_hdr_t * )drhdrp->dh_specific; assert( tprhdrp->recsize >= 0 ); tape_recsz = ( size_t )tprhdrp->recsize; mlog( MLOG_DEBUG | MLOG_DRIVE, "tape record size set to header's " "record size = %d\n", tape_recsz); break; } newsize: /* we end up here if we want to try a new record size. * only do this once. */ if ( changedblkszpr ) { mlog( MLOG_NORMAL | MLOG_DRIVE, _("cannot determine tape block size " "after two tries\n") ); if ( ! wasatbotpr ) { mlog( MLOG_NORMAL | MLOG_DRIVE, _("will rewind and try again\n") ); ( void )rewind_and_verify( drivep ); Close( drivep ); goto retry; } else { mlog( MLOG_NORMAL | MLOG_DRIVE, _("assuming media is corrupt " "or contains non-xfsdump data\n") ); ( void )rewind_and_verify( drivep ); ok = set_best_blk_and_rec_sz( drivep ); if ( ! ok ) { return DRIVE_ERROR_DEVICE; } return DRIVE_ERROR_FOREIGN; } } if ( tape_recsz > STAPE_MIN_MAX_BLKSZ ) { tape_recsz = STAPE_MIN_MAX_BLKSZ; if ( ! contextp->dc_isQICpr ) { tape_blksz = tape_recsz;; } changedblkszpr = BOOL_TRUE; } else { mlog( MLOG_NORMAL | MLOG_DRIVE, _("cannot determine tape block size\n") ); return DRIVE_ERROR_MEDIA; } continue; largersize: /* we end up here if we want to try a new larger record size * because the last one was not big enough for the tape block */ if ( changedblkszpr ) { mlog( MLOG_NORMAL | MLOG_DRIVE, _("cannot determine tape block size " "after two tries\n") ); if ( ! wasatbotpr ) { mlog( MLOG_NORMAL | MLOG_DRIVE, _("will rewind and try again\n") ); ( void )rewind_and_verify( drivep ); Close( drivep ); goto retry; } else { mlog( MLOG_NORMAL | MLOG_DRIVE, _("assuming media is corrupt " "or contains non-xfsdump data\n") ); ( void )rewind_and_verify( drivep ); ok = set_best_blk_and_rec_sz( drivep ); if ( ! ok ) { return DRIVE_ERROR_DEVICE; } return DRIVE_ERROR_FOREIGN; } } /* Make it as large as we can go */ if ( tape_recsz != STAPE_MAX_RECSZ ) { tape_recsz = STAPE_MAX_RECSZ; if ( ! contextp->dc_isQICpr ) { tape_blksz = tape_recsz;; } changedblkszpr = BOOL_TRUE; } else { mlog( MLOG_NORMAL | MLOG_DRIVE, _("cannot determine tape block size\n") ); return DRIVE_ERROR_MEDIA; } continue; } /* loop reading 1st record 'til get correct blksz */ mlog( MLOG_DEBUG | MLOG_DRIVE, "read first record of first media file encountered on media: " "recsz == %u\n", tape_recsz ); /* calculate maximum bytes lost without error at end of tape */ calc_max_lost( drivep ); contextp->dc_iocnt = 1; return 0; } /* if BOOL_FALSE returned, errno is valid */ static bool_t Open( drive_t *drivep ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; int oflags; #ifdef DUMP oflags = O_RDWR; #endif /* DUMP */ #ifdef RESTORE oflags = O_RDONLY; #endif /* RESTORE */ mlog( MLOG_DEBUG | MLOG_DRIVE, "tape op: opening drive\n" ); assert( contextp->dc_fd == -1 ); errno = 0; contextp->dc_fd = open( drivep->d_pathname, oflags ); if ( contextp->dc_fd <= 0 ) { return BOOL_FALSE; } return BOOL_TRUE; } static void Close( drive_t *drivep ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; mlog( MLOG_DEBUG | MLOG_DRIVE, "tape op: closing drive\n" ); assert( contextp->dc_fd >= 0 ); ( void )close( contextp->dc_fd ); contextp->dc_fd = -1; } static int Read( drive_t *drivep, char *bufp, size_t cnt, int *errnop ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; int nread; mlog( MLOG_DEBUG | MLOG_DRIVE, "tape op: reading %u bytes\n", cnt ); assert( contextp->dc_fd >= 0 ); assert( bufp ); *errnop = 0; errno = 0; nread = read( contextp->dc_fd, ( void * )bufp, cnt ); if ( nread < 0 ) { *errnop = errno; mlog( MLOG_NITTY | MLOG_DRIVE, "tape op read of %u bytes failed: errno == %d (%s)\n", cnt, errno, strerror( errno )); } else if ( nread != ( int )cnt ) { mlog( MLOG_NITTY | MLOG_DRIVE, "tape op read of %u bytes short: nread == %d\n", cnt, nread ); } else { mlog( MLOG_NITTY | MLOG_DRIVE, "tape op read of %u bytes successful\n", cnt ); } return nread; } static int Write( drive_t *drivep, char *bufp, size_t cnt, int *errnop ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; int nwritten; mlog( MLOG_DEBUG | MLOG_DRIVE, "tape op: writing %u bytes\n", cnt ); assert( contextp->dc_fd >= 0 ); assert( bufp ); *errnop = 0; errno = 0; nwritten = write( contextp->dc_fd, ( void * )bufp, cnt ); if ( nwritten < 0 ) { *errnop = errno; mlog( MLOG_NITTY | MLOG_DRIVE, "tape op write of %u bytes failed: errno == %d (%s)\n", cnt, errno, strerror( errno )); } else if ( nwritten != ( int )cnt ) { mlog( MLOG_NITTY | MLOG_DRIVE, "tape op write of %u bytes short: nwritten == %d\n", cnt, nwritten ); } else { mlog( MLOG_NITTY | MLOG_DRIVE, "tape op write of %u bytes successful\n", cnt ); } return nwritten; } /* probably should use do_bsf instead. * backs up and positions tape after previous file mark. * skips skipcnt media files. */ /* ARGSUSED */ static int quick_backup( drive_t *drivep, drive_context_t *contextp, ix_t skipcnt ) { if ( drivep->d_capabilities & DRIVE_CAP_BSF ) { do { mtstat_t mtstat; mtstat = bsf_and_verify( drivep ); if ( IS_BOT( mtstat )) { return 0; } if ( TS_ISDRIVER ) { if ( ! IS_FMK( mtstat )) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("unable to backspace tape: " "assuming media error\n") ); return DRIVE_ERROR_MEDIA; } } } while ( skipcnt-- ); ( void )fsf_and_verify( drivep ); } else { ( void )rewind_and_verify( drivep ); } return 0; } /* validate a record header, log any anomolies, and return appropriate * indication. */ static int record_hdr_validate( drive_t *drivep, char *bufp, bool_t chkoffpr ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; global_hdr_t *grhdrp = drivep->d_greadhdrp; rec_hdr_t rechdr; rec_hdr_t *rechdrp = &rechdr; rec_hdr_t *tmprh = ( rec_hdr_t * )bufp; if ( ! tape_rec_checksum_check( contextp, bufp )) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("record %lld corrupt: bad record checksum\n"), contextp->dc_iocnt - 1 ); return DRIVE_ERROR_CORRUPTION; } xlate_rec_hdr(tmprh, rechdrp, 1); if ( rechdrp->magic != STAPE_MAGIC ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("record %lld corrupt: bad magic number\n"), contextp->dc_iocnt - 1 ); return DRIVE_ERROR_CORRUPTION; } if ( uuid_is_null( rechdrp->dump_uuid )) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("record %lld corrupt: null dump id\n"), contextp->dc_iocnt - 1 ); return DRIVE_ERROR_CORRUPTION; } if ( uuid_compare( grhdrp->gh_dumpid, rechdrp->dump_uuid ) != 0) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("record %lld corrupt: dump id mismatch\n"), contextp->dc_iocnt - 1 ); return DRIVE_ERROR_CORRUPTION; } if ( ( size_t )rechdrp->recsize != tape_recsz ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _( "record %lld corrupt: incorrect record size in header\n"), contextp->dc_iocnt - 1 ); return DRIVE_ERROR_CORRUPTION; } if ( rechdrp->file_offset % ( off64_t )tape_recsz ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("record %lld corrupt: record offset in header " "not a multiple of record size\n"), contextp->dc_iocnt - 1 ); return DRIVE_ERROR_CORRUPTION; } if ( chkoffpr && rechdrp->file_offset != ( contextp->dc_iocnt - 1 ) * ( off64_t )tape_recsz ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("record %lld corrupt: " "incorrect record offset in header (0x%llx)\n"), contextp->dc_iocnt - 1, rechdrp->file_offset ); return DRIVE_ERROR_CORRUPTION; } if ( rechdrp->rec_used > tape_recsz || rechdrp->rec_used < STAPE_HDR_SZ ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("record %lld corrupt: " "incorrect record padding offset in header\n"), contextp->dc_iocnt - 1 ); return DRIVE_ERROR_CORRUPTION; } memcpy(tmprh, rechdrp, sizeof(*rechdrp)); return 0; } /* do a read, determine DRIVE_ERROR_... if failure, and return failure code. * return 0 on success. */ static int read_record( drive_t *drivep, char *bufp ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; int nread; int saved_errno; mtstat_t mtstat; int rval; bool_t ok; nread = Read( drivep, bufp, tape_recsz, &saved_errno ); if ( nread == ( int )tape_recsz ) { contextp->dc_iocnt++; rval = record_hdr_validate( drivep, bufp, BOOL_TRUE ); return rval; } /* get drive status */ ok = mt_get_status( drivep, &mtstat ); if ( ! ok ) { status_failed_message( drivep ); return DRIVE_ERROR_DEVICE; } /* encountered a file mark */ if ( IS_FMK( mtstat )) { mlog( MLOG_DEBUG | MLOG_DRIVE, "encountered EOF attempting to read record %lld\n", contextp->dc_iocnt ); return DRIVE_ERROR_EOF; } /* encountered a end of recorded data */ if ( IS_EOD( mtstat )) { mlog( MLOG_DEBUG | MLOG_DRIVE, "encountered EOD attempting to read record %lld\n", contextp->dc_iocnt ); return DRIVE_ERROR_EOD; } /* encountered a end of media */ if ( IS_EOT( mtstat )) { mlog( MLOG_DEBUG | MLOG_DRIVE, "encountered EOM attempting to read record %lld\n", contextp->dc_iocnt ); return DRIVE_ERROR_EOM; } /* encountered a end of media (early warning indicated) */ if ( IS_EW( mtstat )) { mlog( MLOG_DEBUG | MLOG_DRIVE, "encountered EW attempting to read record %lld\n", contextp->dc_iocnt ); return DRIVE_ERROR_EOM; } /* short read */ if ( nread >= 0 ) { assert( nread <= ( int )tape_recsz ); mlog( MLOG_DEBUG | MLOG_DRIVE, "short read record %lld (nread == %d)\n", contextp->dc_iocnt, nread ); return DRIVE_ERROR_CORRUPTION; } /* some other error */ mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_DRIVE, _( "unexpected error attempting to read record %lld: " "read returns %d, errno %d (%s)\n"), contextp->dc_iocnt, nread, errno, strerror( errno )); return DRIVE_ERROR_CORRUPTION; } static int ring_read( void *clientctxp, char *bufp ) { return read_record( ( drive_t * )clientctxp, bufp ); } /* gets another record IF dc_recp is NULL */ static int getrec( drive_t *drivep ) { drive_context_t *contextp; contextp = ( drive_context_t * )drivep->d_contextp; while ( ! contextp->dc_recp ) { rec_hdr_t *rechdrp; if ( contextp->dc_singlethreadedpr ) { int rval; contextp->dc_recp = contextp->dc_bufp; rval = read_record( drivep, contextp->dc_recp ); if ( rval ) { contextp->dc_errorpr = BOOL_TRUE; return rval; } } else { contextp->dc_msgp = Ring_get( contextp->dc_ringp ); switch( contextp->dc_msgp->rm_stat ) { case RING_STAT_OK: contextp->dc_recp = contextp->dc_msgp->rm_bufp; break; case RING_STAT_INIT: case RING_STAT_NOPACK: case RING_STAT_IGNORE: contextp->dc_msgp->rm_op = RING_OP_READ; Ring_put( contextp->dc_ringp, contextp->dc_msgp ); contextp->dc_msgp = 0; continue; case RING_STAT_ERROR: contextp->dc_errorpr = BOOL_TRUE; return contextp->dc_msgp->rm_rval; default: assert( 0 ); contextp->dc_errorpr = BOOL_TRUE; return DRIVE_ERROR_CORE; } } rechdrp = ( rec_hdr_t * )contextp->dc_recp; contextp->dc_recendp = contextp->dc_recp + tape_recsz; contextp->dc_dataendp = contextp->dc_recp + rechdrp->rec_used; contextp->dc_nextp = contextp->dc_recp + STAPE_HDR_SZ; assert( contextp->dc_nextp <= contextp->dc_dataendp ); } return 0; } /* do a write, determine DRIVE_ERROR_... if failure, and return failure code. * return 0 on success. */ /*ARGSUSED*/ static int write_record( drive_t *drivep, char *bufp, bool_t chksumpr, bool_t xlatepr ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; int nwritten; int saved_errno; int rval; if ( xlatepr ) { rec_hdr_t rechdr; memcpy( &rechdr, bufp, sizeof(rechdr) ); xlate_rec_hdr( &rechdr, ( rec_hdr_t * )bufp, 1 ); } if ( chksumpr ) { tape_rec_checksum_set( contextp, bufp ); } nwritten = Write( drivep, bufp, tape_recsz, &saved_errno ); if ( nwritten == ( int )tape_recsz ) { contextp->dc_iocnt++; return 0; } rval = determine_write_error( drivep, nwritten, saved_errno ); assert( rval ); return rval; } static int ring_write( void *clientctxp, char *bufp ) { return write_record( ( drive_t * )clientctxp, bufp, BOOL_TRUE, BOOL_TRUE ); } static ring_msg_t * Ring_get( ring_t *ringp ) { ring_msg_t *msgp; mlog( (MLOG_NITTY + 1) | MLOG_DRIVE, "ring op: get\n" ); msgp = ring_get( ringp ); return msgp; } static void Ring_put( ring_t *ringp, ring_msg_t *msgp ) { mlog( (MLOG_NITTY + 1) | MLOG_DRIVE, "ring op: put %d\n", msgp->rm_op ); ring_put( ringp, msgp ); } static void Ring_reset( ring_t *ringp, ring_msg_t *msgp ) { mlog( (MLOG_NITTY + 1) | MLOG_DRIVE, "ring op: reset\n" ); assert( ringp ); ring_reset( ringp, msgp ); } /* a simple heuristic to calculate the maximum uncertainty * of how much data actually was written prior to encountering * end of media. */ static void calc_max_lost( drive_t *drivep ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; if ( contextp->dc_isQICpr ) { contextp->dc_lostrecmax = 1; } else { contextp->dc_lostrecmax = 2; } } static void display_ring_metrics( drive_t *drivep, int mlog_flags ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; ring_t *ringp = contextp->dc_ringp; char bufszbuf[ 16 ]; char *bufszsfxp; if ( tape_recsz == STAPE_MIN_MAX_BLKSZ ) { assert( ! ( STAPE_MIN_MAX_BLKSZ % 0x400 )); sprintf( bufszbuf, "%u", STAPE_MIN_MAX_BLKSZ / 0x400 ); assert( strlen( bufszbuf ) < sizeof( bufszbuf )); bufszsfxp = "KB"; } else if ( tape_recsz == STAPE_MAX_RECSZ ) { assert( ! ( STAPE_MAX_RECSZ % 0x100000 )); sprintf( bufszbuf, "%u", STAPE_MAX_RECSZ / 0x100000 ); assert( strlen( bufszbuf ) < sizeof( bufszbuf )); bufszsfxp = "MB"; } else if ( tape_recsz == STAPE_MAX_LINUX_RECSZ ) { assert( ! ( STAPE_MAX_LINUX_RECSZ % 0x100000 )); sprintf( bufszbuf, "%u", STAPE_MAX_LINUX_RECSZ / 0x100000 ); assert( strlen( bufszbuf ) < sizeof( bufszbuf )); bufszsfxp = "MB"; } else { bufszsfxp = ""; } mlog( mlog_flags, _( "I/O metrics: " "%u by %s%s %sring; " "%lld/%lld (%.0lf%%) records streamed; " "%.0lfB/s\n"), contextp->dc_ringlen, bufszbuf, bufszsfxp, contextp->dc_ringpinnedpr ? _("pinned ") : "", ringp->r_slave_msgcnt - ringp->r_slave_blkcnt, ringp->r_slave_msgcnt, percent64( ringp->r_slave_msgcnt - ringp->r_slave_blkcnt, ringp->r_slave_msgcnt ), ( double )( ringp->r_all_io_cnt ) * ( double )tape_recsz / ( double )( time( 0 ) - ringp->r_first_io_time )); } static mtstat_t rewind_and_verify( drive_t *drivep ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; ix_t try; int rval; rval = mt_op( contextp->dc_fd, MTREW, 0 ); for ( try = 1 ; ; try++ ) { mtstat_t mtstat; bool_t ok; if ( rval ) { sleep( 1 ); rval = mt_op( contextp->dc_fd, MTREW, 0 ); } ok = mt_get_status( drivep, &mtstat ); if ( ! ok ) { mtstat = 0; status_failed_message( drivep ); if ( try > 1 ) { return 0; } } if ( IS_BOT( mtstat )) { return mtstat; } if ( try >= MTOP_TRIES_MAX ) { return mtstat; } if ( rval ) { return mtstat; } sleep( 1 ); } /* NOTREACHED */ } static mtstat_t erase_and_verify( drive_t *drivep ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; mtstat_t mtstat; bool_t ok; ( void )mt_op( contextp->dc_fd, MTERASE, 0 ); ok = mt_get_status( drivep, &mtstat ); if ( ! ok ) { mtstat = 0; status_failed_message( drivep ); } return mtstat; } static mtstat_t bsf_and_verify( drive_t *drivep ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; ix_t try; bool_t ok; /* Can't do with LINUX ST driver, as GMT_EOF never set for left of fmk */ if ( TS_ISDRIVER ) { ( void )mt_op( contextp->dc_fd, MTBSF, 1 ); for ( try = 1 ; ; try++ ) { mtstat_t mtstat; ok = mt_get_status( drivep, &mtstat ); if ( ! ok ) { mtstat = 0; status_failed_message( drivep ); if ( try > 1 ) { return 0; } } if ( IS_FMK( mtstat )) { return mtstat; } if ( IS_BOT( mtstat )) { return mtstat; } if ( try >= MTOP_TRIES_MAX ) { return mtstat; } sleep( 1 ); } } else { long fileno; mtstat_t mtstat; bool_t ok; /* * Workaround for linux st driver bug. * Don't do a bsf if still in the first file. * Do a rewind instead because the status won't be * set correctly otherwise. [TS:Oct/2000] */ ok = mt_get_fileno( drivep, &fileno ); if ( ! ok ) { status_failed_message( drivep ); return 0; } if (fileno == 0) { mlog( MLOG_DEBUG | MLOG_DRIVE, "In first file, do a rewind to achieve bsf\n"); return rewind_and_verify( drivep ); } ( void )mt_op( contextp->dc_fd, MTBSF, 1 ); try = 1; status: ok = mt_get_status( drivep, &mtstat ); if ( ! ok ) { mtstat = 0; status_failed_message( drivep ); if ( try > 1 ) { return 0; } try++; sleep( 1 ); goto status; } return mtstat; } /* NOTREACHED */ } static mtstat_t fsf_and_verify( drive_t *drivep ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; ix_t try; ( void )mt_op( contextp->dc_fd, MTFSF, 1 ); for ( try = 1 ; ; try++ ) { mtstat_t mtstat; bool_t ok; ok = mt_get_status( drivep, &mtstat ); if ( ! ok ) { mtstat = 0; status_failed_message( drivep ); if ( try > 1 ) { return 0; } } if ( IS_FMK( mtstat )) { return mtstat; } if ( IS_EOD( mtstat )) { return mtstat; } if ( IS_EOT( mtstat )) { return mtstat; } if ( try >= MTOP_TRIES_MAX ) { return mtstat; } sleep( 1 ); } /* NOTREACHED */ } static void calc_best_blk_and_rec_sz( drive_t *drivep ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; if ( ! contextp->dc_isrmtpr ) { if ( cmdlineblksize > 0 ) { tape_blksz = cmdlineblksize; } else { tape_blksz = contextp->dc_maxblksz; } if ( tape_blksz > STAPE_MAX_RECSZ ) { tape_blksz = STAPE_MAX_RECSZ; } if ( contextp->dc_isQICpr ) { tape_recsz = STAPE_MAX_RECSZ; } else { tape_recsz = tape_blksz; } } else { tape_recsz = STAPE_MIN_MAX_BLKSZ; } } static bool_t set_best_blk_and_rec_sz( drive_t *drivep ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; calc_best_blk_and_rec_sz(drivep); if ( ! contextp->dc_isvarpr && ! contextp->dc_isQICpr && contextp->dc_cansetblkszpr ) { bool_t ok; ok = set_fixed_blksz( drivep, tape_blksz ); if ( ! ok ) { return BOOL_FALSE; } } return BOOL_TRUE; } static bool_t isefsdump( drive_t *drivep ) { int32_t *efshdrp = ( int32_t * )drivep->d_greadhdrp; int32_t efsmagic = efshdrp[ 6 ]; if ( efsmagic == 60011 || efsmagic == 60012 ) { return BOOL_TRUE; } else { return BOOL_FALSE; } } /* * General purpose routine which dredges through procfs trying to * match up device driver names with the associated major numbers * being used in the running kernel. (This routine is based on * the get_driver_block_major() routine in the libdisk library.) */ static int get_driver_character_major( const char *driver ) { FILE *f; char buf[64], puf[64]; int major = -1; #define PROC_DEVICES "/proc/devices" if ((f = fopen(PROC_DEVICES, "r")) == NULL) return major; while (fgets(buf, sizeof(buf), f)) /* skip to character dev section */ if (strncmp("Character devices:\n", buf, sizeof(buf)) == 0) break; while (fgets(buf, sizeof(buf), f)) if ((sscanf(buf, "%u %s\n", &major, puf) == 2) && (strncmp(puf, driver, sizeof(puf)) == 0)) goto found; major = -1; found: fclose(f); return major; } static void map_ts_status( struct mtget *mtstat, struct mtget_sgi mtstat_sgi) { /* * This routine has been added as a workaround for a TS/APD * bug which sets the BOT flag incorrectly when positioned * at a filemark. The BOT bug has been fixed in APD 2.8, * however the fix won't be released until spring 2004 (well * after xfsdump 2.2.15). This xfsdump workaround begins * in mt_get_status(), where we call the MTIOCGET_SGI ioctl * rather than the ST-emulated MTIOCGET ioctl for TS devices. * This routine is called following the MTIOCGET_SGI ioctl * to map the TS mtget_sgi.mt_dposn bits back to an ST value * for the mt_gstat status field. NOTE that this routine does * NOT map the entire mtget struct, ONLY the mt_gstat field, * as required by mt_get_status()!!! The ST mtget structure * is returned to mt_get_status() with ONLY the correct mt_gstat * flags set. This workaround can be removed once APD 2.8 has * been released for at least 6 months (Oct-Dec 2004). */ mtstat->mt_gstat = 0; if (mtstat_sgi.mt_dposn & MT_BOT) { mtstat->mt_gstat |= GMT_BOT(0xffffffff); } if (mtstat_sgi.mt_dposn & MT_EOT) { mtstat->mt_gstat |= GMT_EOT(0xffffffff); } if (mtstat_sgi.mt_dposn & MT_WPROT) { mtstat->mt_gstat |= GMT_WR_PROT(0xffffffff); } if (mtstat_sgi.mt_dposn & MT_ONL) { mtstat->mt_gstat |= GMT_ONLINE(0xffffffff); } if (mtstat_sgi.mt_dposn & MT_EOD) { mtstat->mt_gstat |= GMT_EOD(0xffffffff); } if (mtstat_sgi.mt_dposn & MT_FMK) { mtstat->mt_gstat |= GMT_EOF(0xffffffff); } return; } xfsdump-3.1.6+nmu1/common/hsmapi.h0000644000000000000000000003061412620476160013703 0ustar /* * Copyright (c) 2000-2004 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef HSMAPI_H #define HSMAPI_H #include "types.h" #include "global.h" #include "content.h" #include "content_inode.h" struct xfs_bstat; #define HSM_API_VERSION_1 1 /* only version supported so far */ typedef void hsm_fs_ctxt_t; /* opaque HSM filesystem context */ typedef void hsm_f_ctxt_t; /* opaque HSM file context */ /****************************************************************************** * Name * HsmInitFsysContext - allocate and initialize an HSM filesystem context * * Description * HsmInitFsysContext allocates and initializes an HSM filesystem * context to hold all filesystem information that might later be needed * by the other HSM routines. The context is read-only, and can be shared * by multiple xfsdump dump streams. It should eventually be freed by * calling HsmDeleteFsysContext(). The caller must provide the mount * point of the filesystem to be dumped and the HSM API version that * xfsdump was compiled with. * * Note: The restore routines do not require an HSM filesystem context. * * Returns * != NULL, then a pointer to the filesystem context that was allocated. * == NULL, either the HSM libary is not compatible with xfsdump, or * the filesystem is not under HSM management. ******************************************************************************/ extern hsm_fs_ctxt_t * HsmInitFsysContext( const char *mountpoint, int dumpversion); /****************************************************************************** * Name * HsmDeleteFsysContext - delete an HSM filesystem context * * Description * HsmDeleteFsysContext releases all storage previously allocated to a * HSM filesystem context via HsmInitFsysContext. * * Returns * None. ******************************************************************************/ extern void HsmDeleteFsysContext( hsm_fs_ctxt_t *contextp); /****************************************************************************** * Name * HsmEstimateFileSpace - return estimated offline file size * * Description * HsmEstimateFileSpace is called from within estimate_dump_space() only * if -a is selected. It estimates the number of bytes needed to dump * the file assuming that all dual-residency data will be dumped as holes. * * Returns * != 0, then *bytes contains the estimated size of the file in bytes. * == 0, then no estimate made. Caller should use his default estimator. ******************************************************************************/ extern int HsmEstimateFileSpace( hsm_fs_ctxt_t *fscontextp, hsm_f_ctxt_t *fcontextp, const struct xfs_bstat *statp, off64_t *bytes, int accurate); /****************************************************************************** * Name * HsmEstimateFileOffset - return estimated file offset * * Description * HsmEstimateFileOffset is called from within quantity2offset() only * if -a is selected. It estimates the offset within the file that has * 'bytecount' bytes of physical data preceding it assuming that all * dual-residency data in the file will be dumped as holes. * * Returns * != 0, then *byteoffset contains the estimated offset within the file. * == 0, then no estimate made. Caller should use his default estimator. ******************************************************************************/ extern int HsmEstimateFileOffset( hsm_fs_ctxt_t *contextp, const struct xfs_bstat *statp, off64_t bytecount, off64_t *byteoffset); /****************************************************************************** * Name * HsmAllocateFileContext - allocate an HSM file context * * Description * HsmAllocateFileContext mallocs the maximum-sized file context that * might later be needed by HsmInitFileContext(). The context is * read-write. Each xfsdump stream must have its own file context. This * context should eventually be freed by calling HsmDeleteFileContext(). * The caller must provide the HSM filesystem context for the filesystem * being dumped. * * Note: The restore routines do not require an HSM file context. * * Returns * != NULL, then a pointer to the file context that was allocated. ******************************************************************************/ extern hsm_f_ctxt_t * HsmAllocateFileContext( hsm_fs_ctxt_t *contextp); /****************************************************************************** * Name * HsmDeleteFileContext - delete a previously created HSM file context * * Description * HsmDeleteFileContext releases all storage previously allocated to a * HSM file context via HsmAllocateFileContext. * * Returns * None. ******************************************************************************/ extern void HsmDeleteFileContext( hsm_f_ctxt_t *contextp); /****************************************************************************** * Name * HsmInitFileContext - initialize the HSM context for a particular file * * Description * HsmInitFileContext initializes an existing HSM file context for * subsequent operations on a particular regular file. Other HSM routines * use the context to access information collected by HsmInitFileContext * about the file rather than having to recollect the file's information * on each call. * * Returns * != 0, context was created. * == 0, if something is wrong with the file and it should not be dumped. ******************************************************************************/ extern int HsmInitFileContext( hsm_f_ctxt_t *contextp, const struct xfs_bstat *statp); /****************************************************************************** * Name * HsmModifyInode - modify a xfs_bstat_t to make a file appear offline * * Description * HsmModifyInode uses the context provided by a previous * HsmInitFileContext call to determine how to modify a xfs_bstat_t * structure to make a dual-residency HSM file appear to be offline. * * Returns * != 0, xfs_bstat_t structure was modified. * == 0, if something is wrong with the file and it should not be dumped. ******************************************************************************/ extern int HsmModifyInode( hsm_f_ctxt_t *contextp, struct xfs_bstat *statp); /****************************************************************************** * Name * HsmModifyExtentMap - modify getbmapx array to make file appear offline * * Description * HsmModifyExtentMap uses the context provided by a previous * HsmInitFileContext call to determine how to modify a contiguous array * of getbmapx structures to make a dual-residency HSM file appear to * be offline. * * Returns * != 0, getbmapx array was successfully modified. * == 0, if something is wrong with the file and it should not be dumped. ******************************************************************************/ extern int HsmModifyExtentMap( hsm_f_ctxt_t *contextp, struct getbmapx *bmap); /****************************************************************************** * Name * HsmFilterExistingAttribute - filter out unwanted extended attributes * * Description * HsmFilterExistingAttribute uses the context provided by a previous * HsmInitFileContext call to determine whether or not the extended * attribute with name 'namep' should be included in a file's dump image. * (An extended attribute can be modified within the dump by filtering * it out with this routine, then adding the new version of the attribute * back with HsmAddNewAttribute.) * * Note: this routine must be idempotent. It is possible that xfsdump * will call this routine a second time for the same attribute if after * the first call it discovers that there isn't room in its buffer to * hold the attribute value. * * Returns * != 0, the attribute was successfully examined. If '*skip_entry' is * non-zero, xfsdump will not add this attribute to the dump. * == 0, if something is wrong with the file and it should not be dumped. ******************************************************************************/ extern int HsmFilterExistingAttribute( hsm_f_ctxt_t *hsm_f_ctxtp, const char *namep, /* name of attribute to filter */ uint32_t valuesz, /* attribute's current value size */ int flag, /* ext attr flags */ int *skip_entry); /****************************************************************************** * Name * HsmAddNewAttribute - add zero or more HSM attributes to a file's dump * * Description * HsmAddNewAttribute uses the context provided by a previous * HsmInitFileContext call to determine whether or not additional HSM * extended attributes need to be added to a file's dump image. On the * first call for a file, 'cursor' will be zero. xfsdump will increment * 'cursor' by one each time it asks for a new attribute. When no more * attributes are to be added, '*namepp' should be set to NULL. * * Note: this routine must be idempotent. It is possible that xfsdump * will call this routine a second time using the same cursor value if * it discovers that there isn't room in its buffer to hold the attribute * value it was given in the first call. * * Returns * != 0, call was successful. If '*namepp' is non-NULL, then it is the * name of an attribute to be added to the file's dump. '*valuep' * points the the value of the attribute, and '*valueszp' is the * value's size. If '*namep* is NULL, then there are no more * attributes to be added. * == 0, if something is wrong with the file and it should not be dumped. ******************************************************************************/ extern int HsmAddNewAttribute( hsm_f_ctxt_t *hsm_f_ctxtp, int cursor, int flag, /* ext attr flags */ char **namepp, /* pointer to new attribute name */ char **valuepp, /* pointer to its value */ uint32_t *valueszp); /* pointer to the value size */ /****************************************************************************** * Name * HsmBeginRestoreFile * * Description * HsmBeginRestoreFile is called after a file is created but before any * data has been restored to it. The hsm_flagp param can be used to * keep track of limited state between calls to the HSM restore routines. * * Note that this does not require a filesystem or file context like the * HSM calls for xfsdump. This is currently a crude interface to satisfy * a specific need. It can be generalized at a later time, if necessary. * * Returns * None. ******************************************************************************/ extern void HsmBeginRestoreFile( bstat_t *statp, int fd, int *hsm_flagp); /****************************************************************************** * Name * HsmRestoreAttribute * * Description ** HsmRestoreAttribute is called when restoring an extended attribute. * The hsm_flagp param can be used to keep track of limited state * between calls to the HSM restore routines. * * Note that this does not require a filesystem or file context like the * HSM calls for xfsdump. This is currently a crude interface to satisfy * a specific need. It can be generalized at a later time, if necessary. * * Returns * None. ******************************************************************************/ extern void HsmRestoreAttribute( int flag, /* ext attr flags */ char *namep, /* pointer to new attribute name */ int *hsm_flagp); /****************************************************************************** * Name * HsmEndRestoreFile * * Description * HsmEndRestoreFile is called when all data and extended attributes * have been restored. The hsm_flagsp param can be used to keep track * of limited state between calls to the HSM restore routines. * * Note that this does not require a filesystem or file context like the * HSM calls for xfsdump. This is currently a crude interface to satisfy * a specific need. It can be generalized at a later time, if necessary. * * Returns * None. ******************************************************************************/ extern void HsmEndRestoreFile( char *path, int fd, int *hsm_flagp); #endif /* HSMAPI_H */ xfsdump-3.1.6+nmu1/common/inventory.c0000644000000000000000000004306712620476160014460 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "types.h" #include "inventory_priv.h" int sesslock_fd = -1; /*----------------------------------------------------------------------*/ /* inventory_open */ /* */ /* INV_BY_MOUNTPT, INV_BY_UUID or INV_BY_DEVPATH */ /*----------------------------------------------------------------------*/ inv_idbtoken_t inv_open( inv_predicate_t bywhat, void *pred ) { int fd, stobjfd, num; char uuname[ INV_STRLEN ]; inv_idbtoken_t tok = INV_TOKEN_NULL; invt_sescounter_t *sescnt = 0; int index = 0; assert ( pred ); if ((fd = init_idb ( pred, bywhat, uuname, &tok )) < 0 ) return tok; /* XXX also, see if it is too full. if so, make another and leave a reference to the new file in the old one */ stobjfd = get_storageobj( fd, &index ); if ( stobjfd < 0 ) { close( fd ); close( sesslock_fd ); sesslock_fd = -1; return INV_TOKEN_NULL; } assert ( index > 0 ); /* Now we need to make sure that this has enough space */ num = GET_SESCOUNTERS( stobjfd, &sescnt ); if ( num < 0 ) { close( fd ); close( stobjfd ); close( sesslock_fd ); sesslock_fd = -1; return INV_TOKEN_NULL; } /* create another storage object ( and, an inv_index entry for it too ) if we've filled this one up */ if ( (uint) num >= sescnt->ic_maxnum ) { #ifdef INVT_DEBUG printf("$ creating a new storage obj & index entry. \n" ); #endif close (stobjfd); stobjfd = create_invindex_entry( &tok, fd, uuname, BOOL_FALSE ); free ( sescnt ); if ( stobjfd < 0 ) { close( fd ); close( sesslock_fd ); sesslock_fd = -1; return INV_TOKEN_NULL; } return tok; } free ( sescnt ); tok = get_token( fd, stobjfd ); tok->d_invindex_off = INVINDEX_HDR_OFFSET( index - 1 ); return tok; } /*----------------------------------------------------------------------*/ /* */ /* */ /* */ /*----------------------------------------------------------------------*/ bool_t inv_close( inv_idbtoken_t tok ) { close ( tok->d_invindex_fd ); close ( tok->d_stobj_fd ); destroy_token( tok ); close( sesslock_fd ); sesslock_fd = -1; return BOOL_TRUE; } /*----------------------------------------------------------------------*/ /* inventory_lasttime_level_lessthan */ /* */ /* Given a token that refers to a file system, and a level, this returns*/ /* the last time when a session of a lesser level was done. */ /* */ /* returns -1 on error. */ /*----------------------------------------------------------------------*/ bool_t inv_lasttime_level_lessthan( inv_idbtoken_t tok, u_char level, time32_t **tm ) { int rval; assert ( tok != INV_TOKEN_NULL ); rval = search_invt( tok, level, (void **) tm, (search_callback_t) tm_level_lessthan ); return ( rval < 0) ? BOOL_FALSE: BOOL_TRUE; } /*----------------------------------------------------------------------*/ /* */ /* */ /* */ /*----------------------------------------------------------------------*/ bool_t inv_lastsession_level_lessthan( inv_idbtoken_t tok, u_char level, inv_session_t **ses ) { int rval; assert ( tok != INV_TOKEN_NULL ); rval = search_invt( tok, level, (void **) ses, (search_callback_t) lastsess_level_lessthan ); return ( rval < 0) ? BOOL_FALSE: BOOL_TRUE; } /*----------------------------------------------------------------------*/ /* */ /* */ /* Return FALSE on an error, TRUE if not. If (*ses) is NULL, then the */ /* search failed. */ /*----------------------------------------------------------------------*/ bool_t inv_lastsession_level_equalto( inv_idbtoken_t tok, u_char level, inv_session_t **ses ) { int rval; assert ( tok != INV_TOKEN_NULL ); rval = search_invt( tok, level, (void **) ses, (search_callback_t) lastsess_level_equalto ); return ( rval < 0) ? BOOL_FALSE: BOOL_TRUE; } /*----------------------------------------------------------------------*/ /* */ /* */ /* */ /*----------------------------------------------------------------------*/ inv_sestoken_t inv_writesession_open( inv_idbtoken_t tok, /* token obtained by inventory_open() */ uuid_t *fsid, uuid_t *sesid, char *label, u_char level, uint nstreams, time32_t time, char *mntpt, char *devpath ) { invt_session_t *ses; int fd; int rval; invt_sescounter_t *sescnt = NULL; invt_seshdr_t hdr; inv_sestoken_t sestok; assert ( tok != INV_TOKEN_NULL ); assert ( sesid && fsid && mntpt && devpath ); if ( ! ( tok->d_update_flag & FSTAB_UPDATED ) ) { if ( put_fstab_entry( fsid, mntpt, devpath ) < 0 ) { printf ("put_fstab_entry :(\n"); return INV_TOKEN_NULL; } tok->d_update_flag |= FSTAB_UPDATED; } ses = (invt_session_t *) calloc( 1, sizeof( invt_session_t ) ); /* copy the session information to store */ memcpy( &ses->s_sesid, sesid, sizeof( uuid_t ) ); memcpy( &ses->s_fsid, fsid, sizeof( uuid_t ) ); strcpy( ses->s_label, label ); strcpy( ses->s_mountpt, mntpt ); strcpy( ses->s_devpath, devpath ); ses->s_max_nstreams = nstreams; /* s_curstream_off will be set in create_session() */ fd = tok->d_stobj_fd; assert ( fd > 0 ); hdr.sh_time = time; hdr.sh_level = level; /* sh_streams_off and sh_sess_off will be set in create_session() */ sestok = get_sesstoken( tok ); /* we need to put the new session in the appropriate place in storage object. So first find out howmany sessions are there */ INVLOCK( fd, LOCK_EX ); if ( GET_SESCOUNTERS( fd, &sescnt) < 0 ) { free ( ses ); free ( sestok ); INVLOCK( fd, LOCK_UN ); return INV_TOKEN_NULL; } /* create the writesession, and get ready for the streams to come afterwards */ rval = create_session( sestok, fd, sescnt, ses, &hdr ); assert (rval > 0); INVLOCK( fd, LOCK_UN ); sestok->sd_sesstime = time; if ( tok->d_update_flag & NEW_INVINDEX ) { if ( put_sesstime( sestok, INVT_STARTTIME ) < 0 ) { printf ("put_starttime :(\n"); return INV_TOKEN_NULL; } tok->d_update_flag &= ~(NEW_INVINDEX); } free ( ses ); free ( sescnt ); return ( rval < 0 )? INV_TOKEN_NULL: sestok; } /*----------------------------------------------------------------------*/ /* */ /* */ /* */ /*----------------------------------------------------------------------*/ bool_t inv_writesession_close( inv_sestoken_t tok ) { int rval; assert ( tok != INV_TOKEN_NULL ); /* now update end_time in the inv index header */ rval = put_sesstime( tok, INVT_ENDTIME ); memset( tok, 0, sizeof( invt_sesdesc_entry_t ) ); free ( tok ); return ( rval < 0 ) ? BOOL_FALSE: BOOL_TRUE; } /*----------------------------------------------------------------------*/ /* inventory_stream_open */ /* */ /* Opens a stream for mediafiles to be put in. */ /*----------------------------------------------------------------------*/ inv_stmtoken_t inv_stream_open( inv_sestoken_t tok ) { inv_stmtoken_t stok; invt_stream_t stream; invt_session_t ses; invt_seshdr_t seshdr; int fd; assert ( tok != INV_TOKEN_NULL ); stream.st_nmediafiles = 0; stream.st_interrupted = BOOL_FALSE; /* XXX yukk... make the token descriptors not pointers */ stok = ( inv_stmtoken_t ) malloc( sizeof( invt_strdesc_entry_t ) ); stok->md_sesstok = tok; stok->md_lastmfile = 0; /* get the session to find out where the stream is going to go */ fd = tok->sd_invtok->d_stobj_fd; sess_lock(); INVLOCK( fd, LOCK_SH ); /* get the session header first */ if ( GET_REC_NOLOCK( fd, &seshdr, sizeof( invt_seshdr_t ), tok->sd_sesshdr_off ) <= 0 ) { free ( stok ); INVLOCK( fd, LOCK_UN ); sess_unlock(); return INV_TOKEN_NULL; } /* XXX Have one func that gives both seshdr and session */ if ( GET_REC_NOLOCK( fd, &ses, sizeof( invt_session_t ), tok->sd_session_off ) <= 0 ) { free ( stok ); INVLOCK( fd, LOCK_UN ); sess_unlock(); return INV_TOKEN_NULL; } INVLOCK( fd, LOCK_UN ); if ( ses.s_cur_nstreams < ses.s_max_nstreams ) { /* this is where this stream header will be written to */ stok->md_stream_off = (off64_t) (sizeof( invt_stream_t ) * ses.s_cur_nstreams ) + seshdr.sh_streams_off; ses.s_cur_nstreams++; /* write it back. this locks and unlocks fd EXclusively */ if ( PUT_REC( fd, &ses, sizeof( ses ), tok->sd_session_off ) < 0 ) { free ( stok ); sess_unlock(); return INV_TOKEN_NULL; } } else { fprintf(stderr, "Cant create more than %d streams. Max'd out..\n", ses.s_cur_nstreams ); free ( stok ); sess_unlock(); return INV_TOKEN_NULL; } sess_unlock(); stream.st_firstmfile = stream.st_lastmfile = stok->md_stream_off; /* now put the stream header on to the disk */ if ( PUT_REC( fd, &stream, sizeof( invt_stream_t ), stok->md_stream_off ) < 0 ) { free ( stok ); return INV_TOKEN_NULL; } return stok; } /*----------------------------------------------------------------------*/ /* */ /* */ /* */ /*----------------------------------------------------------------------*/ bool_t inv_stream_close( inv_stmtoken_t tok, bool_t wasinterrupted ) { invt_stream_t strm; int fd = tok->md_sesstok->sd_invtok->d_stobj_fd; int rval; bool_t dowrite = BOOL_FALSE; INVLOCK( fd, LOCK_EX ); if ((rval = GET_REC_NOLOCK( fd, &strm, sizeof( invt_stream_t ), tok->md_stream_off )) < 0 ) goto end; /* eek :-) */ if ( strm.st_interrupted != wasinterrupted ) { strm.st_interrupted = wasinterrupted; dowrite = BOOL_TRUE; } /* get the last media file to figure out what our last ino was. we have a pointer to that in the stream token */ if ( tok->md_lastmfile ){ if ( strm.st_endino.ino != tok->md_lastmfile->mf_endino.ino || strm.st_endino.offset != tok->md_lastmfile->mf_endino.offset){ printf("Warning: endinos dont match ! \n"); dowrite = BOOL_TRUE; strm.st_endino = tok->md_lastmfile->mf_endino; } } if (dowrite) { rval = PUT_REC_NOLOCK_SEEKCUR( fd, &strm, sizeof( invt_stream_t ), (off64_t) -(sizeof( invt_stream_t )) ); } end: INVLOCK( fd, LOCK_UN ); free ( tok->md_lastmfile ); memset( tok, 0, sizeof( invt_strdesc_entry_t ) ); free ( tok ); return ( rval < 0 ) ? BOOL_FALSE: BOOL_TRUE; } /*----------------------------------------------------------------------*/ /* */ /* */ /* */ /*----------------------------------------------------------------------*/ bool_t inv_put_mediafile( inv_stmtoken_t tok, uuid_t *moid, char *label, xfs_ino_t startino, off64_t startino_offset, xfs_ino_t endino, off64_t endino_offset ) { invt_mediafile_t *mf; int rval; assert ( tok != INV_TOKEN_NULL ); assert ( tok->md_sesstok->sd_invtok->d_update_flag & FSTAB_UPDATED ); assert ( tok->md_sesstok->sd_invtok->d_stobj_fd >= 0 ); mf = (invt_mediafile_t *) calloc( 1, sizeof( invt_mediafile_t ) ); /* copy the media file information */ memcpy( &mf->mf_moid, moid, sizeof( uuid_t ) ); strcpy( mf->mf_label, label ); mf->mf_startino.ino = startino; mf->mf_startino.offset = startino_offset; mf->mf_endino.ino = endino; mf->mf_endino.offset = endino_offset; INVLOCK( tok->md_sesstok->sd_invtok->d_stobj_fd, LOCK_EX ); rval = put_mediafile( tok, mf ); INVLOCK( tok->md_sesstok->sd_invtok->d_stobj_fd, LOCK_UN ); /* we dont free the mfile here. we always keep the last mfile around, inside the inv_stmtoken, and when we add a new mfile, we free the previous one. The last one is freed in stream_close() */ return ( rval < 0 ) ? BOOL_FALSE: BOOL_TRUE; } /*----------------------------------------------------------------------*/ /* inv_get_inolist */ /* */ /* This returns all the database files that belong to the inventory, so */ /* that the client (dump) knows that these shouldn't be dumped alongwith*/ /* regular files. */ /* */ /* foreach ( fs in fstab ) */ /* foreach ( index in InvIndex ) */ /* get */ /*----------------------------------------------------------------------*/ int inv_get_inolist( inv_inolist_t **inolist ) { invt_entry_t *iarr = NULL; invt_counter_t *icnt = NULL; int nindices, i; struct stat64 statbuf; inv_inolist_t *curitem; #ifdef NOTDEF *inolist = NULL; curitem = malloc( sizeof( inv_inolist_t ) ); /* get the array of all indices in the invindex */ if ( ( nindices = GET_ALLHDRS_N_CNTS( invfd, (void **)&iarr, (void **)&icnt, sizeof( invt_entry_t ), sizeof( invt_counter_t )) ) <= 0 ) { return -1; } free( icnt ); /* attach all the StObjs */ for (i = nindices - 1; i >= 0; i--) { if ( stat64( iarr[i].ie_filename, &statbuf ) < 0 ) { perror( iarr[i].ie_filename ); return -1; } create_inolist_item( curitem, statbuf.st_ino ); } /* The inventory index */ if ( fstat64( invfd, &statbuf ) ){ perror( "InvIndex file" ); return -1; } create_inolist_item( curitem, statbuf.st_ino ); /* fstab */ if ( stat64( INV_FSTAB, &statbuf ) < 0 ) { perror( INV_FSTAB ); return -1; } create_inolist_item( curitem, statbuf.st_ino ); /* sesslock file */ if ( stat64( SESSLOCK_FILE, &statbuf ) < 0 ) { perror( SESSLOCK_FILE ); return -1; } create_inolist_item( curitem, statbuf.st_ino ); #endif return 1; } /*----------------------------------------------------------------------*/ /* inv_get_session */ /* */ /* This is to be called after a write-session is complete, but before it*/ /* is closed. ie. the token must still be valid, and all the streams */ /* and their mediafiles put in the inventory. */ /* */ /* On return, the buffer will be filled with all the data pertinent to */ /* the session referred to by the session token. The application of this*/ /* is to dump the inventory of a session to a media object. */ /*----------------------------------------------------------------------*/ bool_t inv_get_session( inv_sestoken_t tok, void **bufpp, /* buf to fill */ size_t *bufszp )/* size of that buffer */ { assert( tok != INV_TOKEN_NULL ); assert( tok->sd_invtok ); /* First get the session header, and the session information. Then we can figure out how much space to allocate */ } #ifdef DEBUG /* This prints out all the sessions of a filesystem that are in the inventory */ bool_t inv_DEBUG_printallsessions( inv_idbtoken_t tok, inv_session_t **ses ) { int rval; rval = search_invt( tok, 0, (void **) ses, (search_callback_t) DEBUG_displayallsessions ); return ( rval < 0) ? BOOL_FALSE: BOOL_TRUE; } #endif xfsdump-3.1.6+nmu1/common/main.c0000644000000000000000000016534412620476160013352 0ustar /* * Copyright (c) 2000-2002 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "exit.h" #include "types.h" #include "stream.h" #include "cldmgr.h" #include "getopt.h" #include "mlog.h" #include "qlock.h" #include "lock.h" #include "dlog.h" #include "global.h" #include "drive.h" #include "media.h" #include "content.h" #include "inventory.h" #ifdef DUMP /* main.c - main for dump */ #endif /* DUMP */ #ifdef RESTORE /* main.c - main for restore */ #endif /* RESTORE */ /* structure definitions used locally ****************************************/ #ifdef RESTORE #define VMSZ_PER 4 /* proportion of available vm to use in tree */ #endif /* RESTORE */ #define DLOG_TIMEOUT 60 /* time out operator dialog */ #define STOP_TIMEOUT 600 /* seconds after stop req. before abort */ #define ABORT_TIMEOUT 10 /* seconds after abort req. before abort */ #define MINSTACKSZ 0x02000000 #define MAXSTACKSZ 0x08000000 /* declarations of externally defined global symbols *************************/ extern void rmt_turnonmsgs(int); /* forward declarations of locally defined global functions ******************/ void usage( void ); bool_t preemptchk( int ); /* forward declarations of locally defined static functions ******************/ static bool_t loadoptfile( int *argcp, char ***argvp ); static char * stripquotes( char *p ); static void shiftleftby1( char *p, char *endp ); static void sighandler( int ); static int childmain( void * ); static bool_t sigint_dialog( void ); static char *sigintstr( void ); #ifdef DUMP static bool_t set_rlimits( void ); #endif /* DUMP */ #ifdef RESTORE static bool_t set_rlimits( size64_t * ); #endif /* RESTORE */ static char *sig_numstring( int num ); static char *strpbrkquotes( char *p, const char *sep ); /* definition of locally defined global variables ****************************/ char *progname = 0; /* used in all error output */ char *homedir = 0; /* directory invoked from */ bool_t pipeline = BOOL_FALSE; bool_t stdoutpiped = BOOL_FALSE; pthread_t parenttid; char *sistr; size_t pgsz; size_t pgmask; /* definition of locally defined static variables *****************************/ static rlim64_t minstacksz; static rlim64_t maxstacksz; #ifdef RESTORE static size64_t vmsz; #endif /* RESTORE */ static time32_t stop_deadline; static bool_t stop_in_progress; static bool_t sighup_received; static bool_t sigterm_received; static bool_t sigquit_received; static bool_t sigint_received; /* REFERENCED */ static int sigstray_received; static bool_t progrpt_enabledpr; static time32_t progrpt_interval; static time32_t progrpt_deadline; /* definition of locally defined global functions ****************************/ int main( int argc, char *argv[] ) { int c; #ifdef DUMP uid_t euid; #endif /* DUMP */ ix_t stix; /* stream index */ bool_t infoonly; #ifdef DUMP global_hdr_t *gwhdrtemplatep; #endif /* DUMP */ bool_t init_error; bool_t coredump_requested = BOOL_FALSE; int exitcode; rlim64_t tmpstacksz; struct sigaction sa; int prbcld_xc = EXIT_NORMAL; int xc; bool_t ok; /* REFERENCED */ int rval; /* sanity checks */ assert( sizeof( char_t ) == 1 ); assert( sizeof( u_char_t ) == 1 ); assert( sizeof( int32_t ) == 4 ); assert( sizeof( uint32_t ) == 4 ); assert( sizeof( size32_t ) == 4 ); assert( sizeof( int64_t ) == 8 ); assert( sizeof( uint64_t ) == 8 ); assert( sizeof( size64_t ) == 8 ); /* record the command name used to invoke */ progname = argv[ 0 ]; /* setup I18N support */ setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); /* bootstrap message logging (stage 0) */ mlog_init0(); /* Get the parent's pthread id. will be used * to differentiate parent from children. */ parenttid = pthread_self( ); rval = atexit(mlog_exit_flush); assert(rval == 0); /* pre-scan the command line for the option file option. * if found, create a new argv. */ ok = loadoptfile( &argc, &argv ); if ( ! ok ) { return mlog_exit(EXIT_ERROR, RV_OPT); } /* initialize message logging (stage 1) */ ok = mlog_init1( argc, argv ); if ( ! ok ) { return mlog_exit(EXIT_ERROR, RV_INIT); } /* scan the command line for the info, progress * report options, and stacksz. */ minstacksz = MINSTACKSZ; maxstacksz = MAXSTACKSZ; infoonly = BOOL_FALSE; progrpt_enabledpr = BOOL_FALSE; optind = 1; opterr = 0; while ( ( c = getopt( argc, argv, GETOPT_CMDSTRING )) != EOF ) { switch ( c ) { case GETOPT_MINSTACKSZ: if ( ! optarg || optarg[ 0 ] == '-' ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_NOLOCK, _("-%c argument missing\n"), c ); usage( ); return mlog_exit(EXIT_ERROR, RV_OPT); } errno = 0; tmpstacksz = strtoull( optarg, 0, 0 ); if ( tmpstacksz == UINT64_MAX || errno == ERANGE ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_NOLOCK, _("-%c argument (%s) invalid\n"), c, optarg ); usage( ); return mlog_exit(EXIT_ERROR, RV_OPT); } minstacksz = tmpstacksz; break; case GETOPT_MAXSTACKSZ: if ( ! optarg || optarg[ 0 ] == '-' ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_NOLOCK, _("-%c argument missing\n"), c ); usage( ); return mlog_exit(EXIT_ERROR, RV_OPT); } errno = 0; tmpstacksz = strtoull( optarg, 0, 0 ); if ( tmpstacksz == UINT64_MAX || errno == ERANGE ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_NOLOCK, _("-%c argument (%s) invalid\n"), c, optarg ); usage( ); return mlog_exit(EXIT_ERROR, RV_OPT); } maxstacksz = tmpstacksz; break; case GETOPT_HELP: infoonly = BOOL_TRUE; mlog_exit_hint(RV_USAGE); break; case GETOPT_PROGRESS: if ( ! optarg || optarg[ 0 ] == '-' ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_NOLOCK, _("-%c argument missing\n"), c ); usage( ); return mlog_exit(EXIT_ERROR, RV_OPT); } progrpt_interval = ( time32_t )atoi( optarg ); if ( progrpt_interval > 0 ) { progrpt_enabledpr = BOOL_TRUE; } else { progrpt_enabledpr = BOOL_FALSE; } break; } } /* sanity check resultant stack size limits */ if ( minstacksz > maxstacksz ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_NOLOCK | MLOG_PROC, _("specified minimum stack size is larger than maximum: " "min is 0x%llx, max is 0x%llx\n"), minstacksz, maxstacksz ); return mlog_exit(EXIT_ERROR, RV_INIT); } if ( argc == 1 ) { infoonly = BOOL_TRUE; } /* set a progress report deadline to allow preemptchk() to * report */ if ( progrpt_enabledpr ) { progrpt_deadline = time( 0 ) + progrpt_interval; } /* intitialize the stream manager */ stream_init( ); #ifdef DUMP /* set the memory limits to their appropriate values. */ ok = set_rlimits( ); #endif /* DUMP */ #ifdef RESTORE /* set the memory limits to their appropriate values. this is necessary * to accomodate the tree abstraction and some recursive functions. * also determines maximum vm, which will be budgeted among the * various abstractions. */ ok = set_rlimits( &vmsz ); #endif /* RESTORE */ if ( ! ok ) { return mlog_exit(EXIT_ERROR, RV_INIT); } /* initialize message logging (stage 2) - allocate the message lock */ ok = mlog_init2( ); if ( ! ok ) { return mlog_exit(EXIT_ERROR, RV_INIT); } /* initialize the critical region lock */ lock_init( ); rmt_turnonmsgs(1); /* turn on WARNING msgs for librmt */ mlog( MLOG_NITTY + 1, "INTGENMAX == %ld (0x%lx)\n", INTGENMAX, INTGENMAX ); mlog( MLOG_NITTY + 1, "UINTGENMAX == %lu (0x%lx)\n", UINTGENMAX, UINTGENMAX ); mlog( MLOG_NITTY + 1, "OFF64MAX == %lld (0x%llx)\n", OFF64MAX, OFF64MAX ); mlog( MLOG_NITTY + 1, "OFFMAX == %ld (0x%lx)\n", OFFMAX, OFFMAX ); mlog( MLOG_NITTY + 1, "SIZEMAX == %lu (0x%lx)\n", SIZEMAX, SIZEMAX ); mlog( MLOG_NITTY + 1, "INOMAX == %lu (0x%lx)\n", INOMAX, INOMAX ); mlog( MLOG_NITTY + 1, "TIMEMAX == %ld (0x%lx)\n", TIMEMAX, TIMEMAX ); mlog( MLOG_NITTY + 1, "SIZE64MAX == %llu (0x%llx)\n", SIZE64MAX, SIZE64MAX ); mlog( MLOG_NITTY + 1, "INO64MAX == %llu (0x%llx)\n", INO64MAX, INO64MAX ); mlog( MLOG_NITTY + 1, "UINT64MAX == %llu (0x%llx)\n", UINT64MAX, UINT64MAX ); mlog( MLOG_NITTY + 1, "INT64MAX == %lld (0x%llx)\n", INT64MAX, INT64MAX ); mlog( MLOG_NITTY + 1, "UINT32MAX == %u (0x%x)\n", UINT32MAX, UINT32MAX ); mlog( MLOG_NITTY + 1, "INT32MAX == %d (0x%x)\n", INT32MAX, INT32MAX ); mlog( MLOG_NITTY + 1, "INT16MAX == %d (0x%x)\n", INT16MAX, INT16MAX ); mlog( MLOG_NITTY + 1, "UINT16MAX == %u (0x%x)\n", UINT16MAX, UINT16MAX ); /* ask the system for the true vm page size, which must be used * in all mmap calls */ pgsz = ( size_t )getpagesize( ); mlog( MLOG_DEBUG | MLOG_PROC, "getpagesize( ) returns %u\n", pgsz ); assert( ( int )pgsz > 0 ); pgmask = pgsz - 1; /* report parent tid */ mlog( MLOG_DEBUG | MLOG_PROC, "parent tid is %lu\n", parenttid ); /* get the current working directory: this is where we will dump * core, if necessary. some tmp files may be placed here as well. */ homedir = getcwd( 0, MAXPATHLEN ); if ( ! homedir ) { mlog( MLOG_NORMAL | MLOG_ERROR, _("unable to determine current directory: %s\n"), strerror( errno )); return mlog_exit(EXIT_ERROR, RV_INIT); } /* sanity check the inventory database directory, setup global paths */ ok = inv_setup_base( ); if ( ! ok ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_NOLOCK, _("both /var/lib/xfsdump and /var/xfsdump exist - fatal\n")); return mlog_exit(EXIT_ERROR, RV_INIT); } /* if just looking for info, oblige */ if ( infoonly ) { mlog( MLOG_NORMAL, _("version %s (dump format %d.0)\n"), VERSION, GLOBAL_HDR_VERSION ); usage( ); return mlog_exit(EXIT_NORMAL, RV_OK); /* normal termination */ } /* if an inventory display is requested, do it and exit */ if ( ! inv_DEBUG_print( argc, argv )) { return mlog_exit(EXIT_NORMAL, RV_OK); /* normal termination */ } #ifdef DUMP /* insist that the effective user id is root. * this must appear after inv_DEBUG_print(), * so it may be done without root privilege. */ euid = geteuid( ); mlog( MLOG_DEBUG | MLOG_PROC, "effective user id is %d\n", euid ); if ( euid != 0 ) { mlog( MLOG_NORMAL, _("effective user ID must be root\n") ); return mlog_exit(EXIT_ERROR, RV_PERM); } #endif /* DUMP */ /* initialize operator dialog capability */ ok = dlog_init( argc, argv ); if ( ! ok ) { return mlog_exit(EXIT_ERROR, RV_INIT); } /* initialize the child process manager */ ok = cldmgr_init( ); if ( ! ok ) { return mlog_exit(EXIT_ERROR, RV_INIT); } /* select and instantiate a drive manager for each stream. this * is the first pass at initialization, so don't do anything * terribly time-consuming here. A second initialization pass * will be done shortly. */ ok = drive_init1( argc, argv ); if ( ! ok ) { return mlog_exit(EXIT_ERROR, RV_INIT); } /* check the drives to see if we're in a pipeline. * if not, check stdout anyway, in case someone is trying to pipe * the log messages into more, tee, ... */ if ( drivepp[ 0 ]->d_isunnamedpipepr ) { mlog( MLOG_DEBUG | MLOG_NOTE, "pipeline detected\n" ); pipeline = BOOL_TRUE; } else { struct stat64 statbuf; if ( fstat64( 1, &statbuf ) == 0 && ( statbuf.st_mode & S_IFMT ) == S_IFIFO ) { stdoutpiped = BOOL_TRUE; } } /* announce version and instructions */ sistr = sigintstr( ); mlog( MLOG_VERBOSE, _("version %s (dump format %d.0)"), VERSION, GLOBAL_HDR_VERSION ); if ( ! pipeline && ! stdoutpiped && sistr && dlog_allowed( )) { mlog( MLOG_VERBOSE | MLOG_BARE, _( " - " "type %s for status and control\n"), sistr ); } else { mlog( MLOG_VERBOSE | MLOG_BARE, "\n" ); } #ifdef DUMP /* build a global write header template */ gwhdrtemplatep = global_hdr_alloc( argc, argv ); if ( ! gwhdrtemplatep ) { return mlog_exit(EXIT_ERROR, RV_INIT); } #endif /* DUMP */ /* tell mlog how many streams there are. the format of log messages * depends on whether there are one or many. */ mlog_tell_streamcnt( drivecnt ); /* initialize the state of signal processing. if in a pipeline, just * want to exit when a signal is received. otherwise, hold signals so * they don't interfere with sys calls; they will be released at * pre-emption points and upon pausing in the main loop. * * note that since we're multi-threaded, handling SIGCHLD causes * problems with system()'s ability to obtain a child's exit status * (because the main thread may process SIGCHLD before the thread * running system() calls waitpid()). likewise explicitly ignoring * SIGCHLD also prevents system() from getting an exit status. * therefore we don't do anything with SIGCHLD. */ sigfillset(&sa.sa_mask); sa.sa_flags = 0; /* always ignore SIGPIPE, instead handle EPIPE as part * of normal sys call error handling. */ sa.sa_handler = SIG_IGN; sigaction( SIGPIPE, &sa, NULL ); if ( ! pipeline ) { sigset_t blocked_set; stop_in_progress = BOOL_FALSE; coredump_requested = BOOL_FALSE; sighup_received = BOOL_FALSE; sigterm_received = BOOL_FALSE; sigint_received = BOOL_FALSE; sigquit_received = BOOL_FALSE; sigstray_received = BOOL_FALSE; alarm( 0 ); sigemptyset( &blocked_set ); sigaddset( &blocked_set, SIGINT ); sigaddset( &blocked_set, SIGHUP ); sigaddset( &blocked_set, SIGTERM ); sigaddset( &blocked_set, SIGQUIT ); sigaddset( &blocked_set, SIGALRM ); sigaddset( &blocked_set, SIGUSR1 ); pthread_sigmask( SIG_SETMASK, &blocked_set, NULL ); sa.sa_handler = sighandler; sigaction( SIGINT, &sa, NULL ); sigaction( SIGHUP, &sa, NULL ); sigaction( SIGTERM, &sa, NULL ); sigaction( SIGQUIT, &sa, NULL ); sigaction( SIGALRM, &sa, NULL ); sigaction( SIGUSR1, &sa, NULL ); } /* do content initialization. */ #ifdef DUMP ok = content_init( argc, argv, gwhdrtemplatep ); #endif /* DUMP */ #ifdef RESTORE ok = content_init( argc, argv, vmsz / VMSZ_PER ); #endif /* RESTORE */ if ( ! ok ) { return mlog_exit(EXIT_ERROR, RV_INIT); } /* if in a pipeline, go single-threaded with just one stream. */ if ( pipeline ) { int exitcode; sa.sa_handler = sighandler; sigaction( SIGINT, &sa, NULL ); sigaction( SIGHUP, &sa, NULL ); sigaction( SIGTERM, &sa, NULL ); sigaction( SIGQUIT, &sa, NULL ); ok = drive_init2( argc, argv, #ifdef DUMP gwhdrtemplatep ); #endif /* DUMP */ #ifdef RESTORE ( global_hdr_t * )0 ); #endif /* RESTORE */ if ( ! ok ) { return mlog_exit(EXIT_ERROR, RV_INIT); } ok = drive_init3( ); if ( ! ok ) { return mlog_exit(EXIT_ERROR, RV_INIT); } #ifdef DUMP exitcode = content_stream_dump( 0 ); #endif /* DUMP */ #ifdef RESTORE exitcode = content_stream_restore( 0 ); #endif /* RESTORE */ if ( exitcode != EXIT_NORMAL ) { ( void )content_complete( ); /* for cleanup side-effect */ return mlog_exit(exitcode, RV_UNKNOWN); } else if ( content_complete( )) { return mlog_exit(EXIT_NORMAL, RV_OK); } else { return mlog_exit(EXIT_INTERRUPT, RV_UNKNOWN); } } /* used to skip to end if errors occur during any * stage of initialization. */ init_error = BOOL_FALSE; /* now do the second and third passes of drive initialization. * allocate per-stream write and read headers. if a drive * manager uses a slave process, it should be created now, * using cldmgr_create( ). each drive manager may use the slave to * asynchronously read the media file header, typically a very * time-consuming chore. drive_init3 will synchronize with each slave. */ if ( ! init_error ) { ok = drive_init2( argc, argv, #ifdef DUMP gwhdrtemplatep ); #endif /* DUMP */ #ifdef RESTORE ( global_hdr_t * )0 ); #endif /* RESTORE */ if ( ! ok ) { init_error = BOOL_TRUE; } } if ( ! init_error ) { ok = drive_init3( ); if ( ! ok ) { init_error = BOOL_TRUE; } } /* create a child thread for each stream. drivecnt global from * drive.h, initialized by drive_init[12] */ if ( ! init_error ) { for ( stix = 0 ; stix < drivecnt ; stix++ ) { ok = cldmgr_create( childmain, stix, "child", ( void * )stix ); if ( ! ok ) { init_error = BOOL_TRUE; } } } /* loop here, waiting for children to die, processing operator * signals. */ if ( progrpt_enabledpr ) { ( void )alarm( ( uint )progrpt_interval ); } for ( ; ; ) { time32_t now; bool_t stop_requested = BOOL_FALSE; int stop_timeout = -1; sigset_t empty_set; /* if there was an initialization error, * immediately stop all children. */ if ( init_error ) { stop_timeout = STOP_TIMEOUT; stop_requested = BOOL_TRUE; } /* if one or more children died abnormally, request a * stop. furthermore, note that core should be dumped if * the child explicitly exited with EXIT_FAULT. */ xc = cldmgr_join( ); if ( xc ) { if ( xc == EXIT_FAULT ) { coredump_requested = BOOL_TRUE; stop_timeout = ABORT_TIMEOUT; } else { stop_timeout = STOP_TIMEOUT; } prbcld_xc = xc; stop_requested = BOOL_TRUE; } /* all children died normally. break out. */ if ( cldmgr_remainingcnt( ) == 0 ) { mlog( MLOG_DEBUG, "all children have exited\n" ); break; } /* get the current time */ now = time( 0 ); /* check for stop timeout. request a core dump and bail */ if ( stop_in_progress && now >= stop_deadline ) { mlog( MLOG_NORMAL | MLOG_ERROR, _("session interrupt timeout\n") ); coredump_requested = BOOL_TRUE; break; } /* operator sent SIGINT. if dialog allowed, enter dialog. * otherwise treat as a hangup and request a stop. */ if ( sigint_received ) { mlog( MLOG_DEBUG | MLOG_PROC, "SIGINT received\n" ); if ( stop_in_progress ) { if ( dlog_allowed( )) { ( void )sigint_dialog( ); } /* mlog( MLOG_NORMAL, _("session interrupt in progress: " "please wait\n") ); */ } else { if ( dlog_allowed( )) { stop_requested = sigint_dialog( ); } else { stop_requested = BOOL_TRUE; } stop_timeout = STOP_TIMEOUT; } /* important that this appear after dialog. * allows dialog to be terminated with SIGINT, * without infinite loop. */ sigint_received = BOOL_FALSE; } /* refresh the current time in case in dialog for a while */ now = time( 0 ); /* request a stop on hangup */ if ( sighup_received ) { mlog( MLOG_DEBUG | MLOG_PROC, "SIGHUP received\n" ); stop_requested = BOOL_TRUE; stop_timeout = STOP_TIMEOUT; sighup_received = BOOL_FALSE; } /* request a stop on termination request */ if ( sigterm_received ) { mlog( MLOG_DEBUG | MLOG_PROC, "SIGTERM received\n" ); stop_requested = BOOL_TRUE; stop_timeout = STOP_TIMEOUT; sigterm_received = BOOL_FALSE; } /* operator send SIGQUIT. treat like an interrupt, * but force a core dump */ if ( sigquit_received ) { mlog( MLOG_NORMAL | MLOG_PROC, "SIGQUIT received\n" ); if ( stop_in_progress ) { mlog( MLOG_NORMAL, _("session interrupt in progress: " "please wait\n") ); stop_deadline = now; } else { stop_requested = BOOL_TRUE; stop_timeout = ABORT_TIMEOUT; sigquit_received = BOOL_FALSE; coredump_requested = BOOL_TRUE; } } /* see if need to initiate a stop */ if ( stop_requested && ! stop_in_progress ) { mlog( MLOG_NORMAL, _("initiating session interrupt (timeout in %d sec)\n"), stop_timeout); mlog_exit_hint(RV_INTR); stop_in_progress = BOOL_TRUE; cldmgr_stop( ); assert( stop_timeout >= 0 ); stop_deadline = now + ( time32_t )stop_timeout; } /* set alarm if needed (note time stands still during dialog) */ if ( stop_in_progress ) { int timeout = ( int )( stop_deadline - now ); if ( timeout < 0 ) { timeout = 0; } mlog( MLOG_DEBUG | MLOG_PROC, "setting alarm for %d second%s\n", timeout, timeout == 1 ? "" : "s" ); ( void )alarm( ( uint )timeout ); if ( timeout == 0 ) { continue; } } if ( progrpt_enabledpr && ! stop_in_progress ) { bool_t need_progrptpr = BOOL_FALSE; while ( now >= progrpt_deadline ) { need_progrptpr = BOOL_TRUE; progrpt_deadline += progrpt_interval; } if ( need_progrptpr ) { size_t statlinecnt; char **statline; ix_t i; statlinecnt = content_statline( &statline ); for ( i = 0 ; i < statlinecnt ; i++ ) { mlog( MLOG_NORMAL, statline[ i ] ); } } ( void )alarm( ( uint )( progrpt_deadline - now )); } /* sleep until next signal */ sigemptyset( &empty_set ); sigsuspend( &empty_set ); ( void )alarm( 0 ); } /* check if core dump requested */ if ( coredump_requested ) { mlog( MLOG_DEBUG | MLOG_PROC, "core dump requested, aborting (pid %d)\n", getpid() ); abort(); } /* determine if dump or restore was interrupted * or an initialization error occurred. */ if ( init_error ) { ( void )content_complete( ); exitcode = EXIT_ERROR; } else { if ( content_complete( ) ) { if (prbcld_xc != EXIT_NORMAL) exitcode = EXIT_ERROR; else exitcode = EXIT_NORMAL; } else { exitcode = EXIT_INTERRUPT; if ( mlog_get_hint() == RV_NONE ) mlog_exit_hint(RV_INCOMPLETE); } } return mlog_exit(exitcode, RV_UNKNOWN); } #define ULO( f, o ) fprintf( stderr, \ "%*s[ -%c %s ]\n", \ ps, \ ns, \ o, \ f ), \ ps = pfxsz #define ULN( f ) fprintf( stderr, \ "%*s[ %s ]\n", \ ps, \ ns, \ f ), \ ps = pfxsz void usage( void ) { int pfxsz; int ps = 0; char *ns = ""; pfxsz = fprintf(stderr, _("%s: usage: %s "), progname, basename(progname)); #ifdef DUMP ULO(_("(dump DMF dualstate files as offline)"), GETOPT_DUMPASOFFLINE ); ULO(_(""), GETOPT_BLOCKSIZE ); ULO(_(" "), GETOPT_ALERTPROG ); ULO(_(" "), GETOPT_FILESZ ); ULO(_("(allow files to be excluded)"), GETOPT_EXCLUDEFILES ); ULO(_(" ..."), GETOPT_DUMPDEST ); ULO(_("(help)"), GETOPT_HELP ); ULO(_(""), GETOPT_LEVEL ); ULO(_("(force usage of minimal rmt)"), GETOPT_MINRMT ); ULO(_("(overwrite tape)"), GETOPT_OVERWRITE ); ULO(_(""), GETOPT_PROGRESS ); ULO(_(""), GETOPT_QIC ); ULO(_(" ..."), GETOPT_SUBTREE ); ULO(_(" (use file mtime for dump time"), GETOPT_DUMPTIME ); ULO(_(""), GETOPT_VERBOSITY ); ULO(_(""), GETOPT_MAXDUMPFILESIZE ); ULO(_("(don't dump extended file attributes)"), GETOPT_NOEXTATTR ); ULO(_(""), GETOPT_BASED ); #ifdef REVEAL ULO(_("(generate tape record checksums)"), GETOPT_RECCHKSUM ); #endif /* REVEAL */ ULO(_("(skip unchanged directories)"), GETOPT_NOUNCHANGEDDIRS ); ULO(_("(pre-erase media)"), GETOPT_ERASE ); ULO(_("(don't prompt)"), GETOPT_FORCE ); #ifdef REVEAL ULO(_(""), GETOPT_MINSTACKSZ ); ULO(_(""), GETOPT_MAXSTACKSZ ); #endif /* REVEAL */ ULO(_("(display dump inventory)"), GETOPT_INVPRINT ); ULO(_("(inhibit inventory update)"), GETOPT_NOINVUPDATE ); ULO(_("(generate format 2 dump)"), GETOPT_FMT2COMPAT ); ULO(_(""), GETOPT_DUMPLABEL ); ULO(_(" ..."), GETOPT_MEDIALABEL ); #ifdef REVEAL ULO(_("(timestamp messages)"), GETOPT_TIMESTAMP ); #endif /* REVEAL */ ULO(_(""), GETOPT_OPTFILE ); #ifdef REVEAL ULO(_("(pin down I/O buffers)"), GETOPT_RINGPIN ); #endif /* REVEAL */ ULO(_("(resume)"), GETOPT_RESUME ); ULO(_("(don't timeout dialogs)"), GETOPT_NOTIMEOUTS ); #ifdef REVEAL ULO(_("(unload media when change needed)"), GETOPT_UNLOAD ); ULO(_("(show subsystem in messages)"), GETOPT_SHOWLOGSS ); ULO(_("(show verbosity in messages)"), GETOPT_SHOWLOGLEVEL ); #endif /* REVEAL */ ULO(_(""), GETOPT_RINGLEN ); ULN(_("- (stdout)") ); ULN(_("") ); #endif /* DUMP */ #ifdef RESTORE ULO(_(" ..."), GETOPT_WORKSPACE ); ULO(_(""), GETOPT_BLOCKSIZE ); ULO(_(" "), GETOPT_ALERTPROG ); ULO(_("(don't overwrite existing files)"), GETOPT_EXISTING ); ULO(_(" ..."), GETOPT_DUMPDEST ); ULO(_("(help)"), GETOPT_HELP ); ULO(_("(interactive)"), GETOPT_INTERACTIVE ); ULO(_("(force usage of minimal rmt)"), GETOPT_MINRMT ); ULO(_(" (restore only if newer than)"), GETOPT_NEWER ); ULO(_("(restore owner/group even if not root)"),GETOPT_OWNER ); ULO(_(""), GETOPT_PROGRESS ); ULO(_(""), GETOPT_QIC ); ULO(_("(cumulative restore)"), GETOPT_CUMULATIVE ); ULO(_(" ..."), GETOPT_SUBTREE ); ULO(_("(contents only)"), GETOPT_TOC ); ULO(_(""), GETOPT_VERBOSITY ); ULO(_("(use small tree window)"), GETOPT_SMALLWINDOW ); ULO(_("(don't restore extended file attributes)"),GETOPT_NOEXTATTR ); ULO(_("(restore root dir owner/permissions)"), GETOPT_ROOTPERM ); ULO(_("(restore DMAPI event settings)"), GETOPT_SETDM ); #ifdef REVEAL ULO(_("(check tape record checksums)"), GETOPT_RECCHKSUM ); #endif /* REVEAL */ ULO(_("(don't overwrite if changed)"), GETOPT_CHANGED ); ULO(_("(don't prompt)"), GETOPT_FORCE ); ULO(_("(display dump inventory)"), GETOPT_INVPRINT ); ULO(_("(inhibit inventory update)"), GETOPT_NOINVUPDATE ); ULO(_("(force use of format 2 generation numbers)"),GETOPT_FMT2COMPAT ); ULO(_(""), GETOPT_DUMPLABEL ); #ifdef REVEAL ULO(_("(timestamp messages)"), GETOPT_TIMESTAMP ); #endif /* REVEAL */ ULO(_(""), GETOPT_OPTFILE ); #ifdef REVEAL ULO(_("(pin down I/O buffers)"), GETOPT_RINGPIN ); #endif /* REVEAL */ ULO(_("(force interrupted session completion)"),GETOPT_SESSCPLT ); ULO(_("(resume)"), GETOPT_RESUME ); ULO(_(""), GETOPT_SESSIONID ); ULO(_("(don't timeout dialogs)"), GETOPT_NOTIMEOUTS ); #ifdef REVEAL ULO(_("(unload media when change needed)"), GETOPT_UNLOAD ); ULO(_("(show subsystem in messages)"), GETOPT_SHOWLOGSS ); ULO(_("(show verbosity in messages)"), GETOPT_SHOWLOGLEVEL ); #endif /* REVEAL */ ULO(_(" ..."), GETOPT_NOSUBTREE ); ULO(_(""), GETOPT_RINGLEN ); ULN(_("- (stdin)") ); ULN(_("") ); #endif /* RESTORE */ /* anywhere usage is called we will exit shortly after... * catch all of those cases below */ (void) mlog_exit(EXIT_ERROR, RV_OPT); } /* returns TRUE if preemption */ bool_t preemptchk( int flg ) { bool_t preempt_requested; int i; int sigs[] = { SIGINT, SIGHUP, SIGTERM, SIGQUIT }; int num_sigs = sizeof(sigs) / sizeof(sigs[0]); sigset_t pending_set, handle_set; /* see if a progress report needed */ if ( progrpt_enabledpr ) { time32_t now = time( 0 ); bool_t need_progrptpr = BOOL_FALSE; while ( now >= progrpt_deadline ) { need_progrptpr = BOOL_TRUE; progrpt_deadline += progrpt_interval; } if ( need_progrptpr ) { size_t statlinecnt; char **statline; ix_t i; statlinecnt = content_statline( &statline ); for ( i = 0 ; i < statlinecnt ; i++ ) { mlog( MLOG_NORMAL, statline[ i ] ); } } } /* Progress report only */ if (flg == PREEMPT_PROGRESSONLY) { return BOOL_FALSE; } /* signals not caught if in a pipeline */ if ( pipeline ) { return BOOL_FALSE; } /* release signals momentarily to let any pending ones * invoke signal handler and set flags */ sigpending( &pending_set ); for ( i = 0; i < num_sigs; i++ ) { if ( sigismember( &pending_set, sigs[i] ) == 1 ) { sigfillset( &handle_set ); sigdelset( &handle_set, sigs[i] ); sigsuspend( &handle_set ); } } preempt_requested = BOOL_FALSE; if ( sigint_received ) { mlog( MLOG_DEBUG | MLOG_PROC, "SIGINT received (preempt)\n" ); if ( dlog_allowed( )) { preempt_requested = sigint_dialog( ); } else { preempt_requested = BOOL_TRUE; } /* important that this appear after dialog. * allows dialog to be terminated with SIGINT, * without infinite loop. */ sigint_received = BOOL_FALSE; } if ( sighup_received ) { mlog( MLOG_DEBUG | MLOG_PROC, "SIGHUP received (prempt)\n" ); preempt_requested = BOOL_TRUE; sighup_received = BOOL_FALSE; } if ( sigterm_received ) { mlog( MLOG_DEBUG | MLOG_PROC, "SIGTERM received (prempt)\n" ); preempt_requested = BOOL_TRUE; sigterm_received = BOOL_FALSE; } if ( sigquit_received ) { mlog( MLOG_DEBUG | MLOG_PROC, "SIGQUIT received (preempt)\n" ); preempt_requested = BOOL_TRUE; sigquit_received = BOOL_FALSE; } return preempt_requested; } /* definition of locally defined static functions ****************************/ static bool_t loadoptfile( int *argcp, char ***argvp ) { char *optfilename; ix_t optfileix = 0; int fd; size_t sz; int i; struct stat64 stat; char *argbuf; char *p; size_t tokencnt; int nread; const char *sep = " \t\n\r"; char **newargv; int c; int rval; /* see if option specified */ optind = 1; opterr = 0; optfilename = 0; while ( ( c = getopt( *argcp, *argvp, GETOPT_CMDSTRING )) != EOF ) { switch ( c ) { case GETOPT_OPTFILE: if ( ! optarg || optarg[ 0 ] == '-' ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_NOLOCK, _("-%c argument missing\n"), c ); usage( ); return BOOL_FALSE; } if ( optfilename ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_NOLOCK, _("-%c allowed only once\n"), c ); usage( ); return BOOL_FALSE; } optfilename = optarg; assert( optind > 2 ); optfileix = ( ix_t )optind - 2; break; } } if ( ! optfilename ) { return BOOL_TRUE; } /* attempt to open the option file */ errno = 0; fd = open( optfilename, O_RDONLY ); if ( fd < 0 ) { mlog( MLOG_ERROR | MLOG_NOLOCK, _("cannot open option file %s: %s (%d)\n"), optfilename, strerror( errno ), errno ); return BOOL_FALSE; } /* get file status */ rval = fstat64( fd, &stat ); if ( rval ) { mlog( MLOG_ERROR | MLOG_NOLOCK, _("cannot stat option file %s: %s (%d)\n"), optfilename, strerror( errno ), errno ); close( fd ); return BOOL_FALSE; } /* ensure the file is ordinary */ if ( ( stat.st_mode & S_IFMT ) != S_IFREG ) { mlog( MLOG_ERROR | MLOG_NOLOCK, _("given option file %s is not ordinary file\n"), optfilename ); close( fd ); return BOOL_FALSE; } /* calculate the space required for the cmd line options. * skip the GETOPT_OPTFILE option which put us here! */ sz = 0; for ( i = 0 ; i < *argcp ; i++ ) { if ( i == ( int )optfileix ) { i++; /* to skip option argument */ continue; } sz += strlen( ( * argvp )[ i ] ) + 1; } /* add in the size of the option file (plus one byte in case * option file ends without newline, and one NULL for safety) */ sz += ( size_t )stat.st_size + 2; /* allocate an argument buffer */ argbuf = ( char * )malloc( sz ); assert( argbuf ); /* copy arg0 (the executable's name ) in first */ p = argbuf; i = 0; sprintf( p, "%s ", ( * argvp )[ i ] ); p += strlen( ( * argvp )[ i ] ) + 1; i++; /* copy the options file into the buffer after the given args */ nread = read( fd, ( void * )p, ( size_t )stat.st_size ); if ( nread < 0 ) { mlog( MLOG_ERROR | MLOG_NOLOCK, _("read of option file %s failed: %s (%d)\n"), optfilename, strerror( errno ), errno ); close( fd ); return BOOL_FALSE; } assert( ( off64_t )nread == stat.st_size ); p += ( size_t )stat.st_size; *p++ = ' '; /* copy the remaining command line args into the buffer */ for ( ; i < *argcp ; i++ ) { if ( i == ( int )optfileix ) { i++; /* to skip option argument */ continue; } sprintf( p, "%s ", ( * argvp )[ i ] ); p += strlen( ( * argvp )[ i ] ) + 1; } /* null-terminate the entire buffer */ *p++ = 0; assert( ( size_t )( p - argbuf ) <= sz ); /* change newlines and carriage returns into spaces */ for ( p = argbuf ; *p ; p++ ) { if ( strchr( "\n\r", ( int )( *p ))) { *p = ' '; } } /* count the tokens in the buffer */ tokencnt = 0; p = argbuf; for ( ; ; ) { /* start at the first non-separator character */ while ( *p && strchr( sep, ( int )( *p ))) { p++; } /* done when NULL encountered */ if ( ! *p ) { break; } /* we have a token */ tokencnt++; /* find the end of the first token */ p = strpbrkquotes( p, sep ); /* if no more separators, all tokens seen */ if ( ! p ) { break; } } /* if no arguments, can return now */ if ( ! tokencnt ) { close( fd ); return BOOL_TRUE; } /* allocate a new argv array to hold the tokens */ newargv = ( char ** )calloc( tokencnt, sizeof( char * )); assert( newargv ); /* null-terminate tokens and place in new argv, after * extracting quotes and escapes */ p = argbuf; for ( i = 0 ; ; i++ ) { char *endp = 0; /* start at the first non-separator character */ while ( *p && strchr( sep, ( int )*p )) { p++; } /* done when NULL encountered */ if ( ! *p ) { break; } /* better not disagree with counting scan! */ assert( i < ( int )tokencnt ); /* find the end of the first token */ endp = strpbrkquotes( p, sep ); /* null-terminate if needed */ if ( endp ) { *endp = 0; } /* strip quotes and escapes */ p = stripquotes( p ); /* stick result in new argv array */ newargv[ i ] = p; /* if no more separators, all tokens seen */ if ( ! endp ) { break; } p = endp + 1; } /* return new argc anr argv */ close( fd ); *argcp = ( int )tokencnt; *argvp = newargv; return BOOL_TRUE; } /* parent and children share this handler. */ static void sighandler( int signo ) { /* dialog gets first crack at the signal */ if ( dlog_sighandler( signo ) ) return; /* if in pipeline, don't do anything risky. just quit. */ if ( pipeline ) { int rval; mlog( MLOG_TRACE | MLOG_NOTE | MLOG_NOLOCK | MLOG_PROC, _("received signal %d (%s): cleanup and exit\n"), signo, sig_numstring( signo )); if ( content_complete( )) { rval = EXIT_NORMAL; } else { rval = EXIT_INTERRUPT; } mlog_exit(rval, RV_NONE); exit( rval ); } switch ( signo ) { case SIGHUP: /* immediately disable further dialogs */ dlog_desist( ); sighup_received = BOOL_TRUE; break; case SIGTERM: /* immediately disable further dialogs */ dlog_desist( ); sigterm_received = BOOL_TRUE; break; case SIGINT: sigint_received = BOOL_TRUE; break; case SIGQUIT: /* immediately disable further dialogs */ dlog_desist( ); sigquit_received = BOOL_TRUE; break; case SIGALRM: case SIGUSR1: break; default: sigstray_received = signo; break; } } static int childmain( void *arg1 ) { ix_t stix; int exitcode; drive_t *drivep; /* Determine which stream I am. */ stix = ( ix_t )arg1; /* tell the content manager to begin. */ #ifdef DUMP exitcode = content_stream_dump( stix ); #endif /* DUMP */ #ifdef RESTORE exitcode = content_stream_restore( stix ); #endif /* RESTORE */ /* let the drive manager shut down its slave thread */ drivep = drivepp[ stix ]; ( * drivep->d_opsp->do_quit )( drivep ); return exitcode; } /* ARGSUSED */ static void prompt_prog_cb( void *uctxp, dlog_pcbp_t pcb, void *pctxp ) { /* query: ask for a dump label */ ( * pcb )( pctxp, progrpt_enabledpr ? _("please enter seconds between progress reports, " "or 0 to disable") : _("please enter seconds between progress reports") ); } /* SIGINTR dialog * * side affect is to change verbosity level. * return code of BOOL_TRUE indicates a stop was requested. */ #define PREAMBLEMAX ( 7 + 2 * STREAM_SIMMAX ) #define QUERYMAX 3 #define CHOICEMAX 9 #define ACKMAX 7 #define POSTAMBLEMAX 3 static bool_t sigint_dialog( void ) { fold_t fold; char **statline; ix_t i; size_t statlinecnt; char *preamblestr[ PREAMBLEMAX ]; size_t preamblecnt; char *querystr[ QUERYMAX ]; size_t querycnt; char *choicestr[ CHOICEMAX ]; size_t choicecnt; char *ackstr[ ACKMAX ]; size_t ackcnt; char *postamblestr[ POSTAMBLEMAX ]; size_t postamblecnt; size_t interruptix; size_t verbosityix; size_t metricsix; size_t controlix; size_t ioix; size_t mediachangeix; #ifdef RESTORE size_t piix; size_t roix; #endif /* RESTORE */ size_t progix; size_t mllevix; size_t mlssix; size_t mltsix; size_t continueix; size_t allix; size_t nochangeix; size_t responseix; int ssselected = 0; bool_t stop_requested = BOOL_FALSE; /* preamble: the content status line, indicate if interrupt happening */ fold_init( fold, _("status and control dialog"), '=' ); statlinecnt = content_statline( &statline ); preamblecnt = 0; preamblestr[ preamblecnt++ ] = "\n"; preamblestr[ preamblecnt++ ] = fold; preamblestr[ preamblecnt++ ] = "\n"; preamblestr[ preamblecnt++ ] = "\n"; for ( i = 0 ; i < statlinecnt ; i++ ) { preamblestr[ preamblecnt++ ] = statline[ i ]; } if ( stop_in_progress ) { preamblestr[ preamblecnt++ ] = _("\nsession interrupt in progress\n"); } preamblestr[ preamblecnt++ ] = "\n"; assert( preamblecnt <= PREAMBLEMAX ); dlog_begin( preamblestr, preamblecnt ); /* top-level query: a function of session interrupt status */ querycnt = 0; querystr[ querycnt++ ] = _("please select one of " "the following operations\n"); assert( querycnt <= QUERYMAX ); choicecnt = 0; if ( ! stop_in_progress ) { interruptix = choicecnt; choicestr[ choicecnt++ ] = _("interrupt this session"); } else { interruptix = SIZEMAX; /* never happen */ } verbosityix = choicecnt; choicestr[ choicecnt++ ] = _("change verbosity"); metricsix = choicecnt; choicestr[ choicecnt++ ] = _("display metrics"); if ( content_media_change_needed ) { mediachangeix = choicecnt; choicestr[ choicecnt++ ] = _("confirm media change"); } else { mediachangeix = SIZEMAX; /* never happen */ } controlix = choicecnt; choicestr[ choicecnt++ ] = _("other controls"); continueix = choicecnt; choicestr[ choicecnt++ ] = _("continue"); assert( choicecnt <= CHOICEMAX ); responseix = dlog_multi_query( querystr, querycnt, choicestr, choicecnt, 0, /* hilitestr */ IXMAX, /* hiliteix */ 0, /* defaultstr */ continueix, /* defaultix */ DLOG_TIMEOUT, /* timeout */ continueix, /* timeout ix */ continueix, /* sigint ix */ continueix, /* sighup ix */ continueix ); /* sigquit ix */ if ( responseix == interruptix ) { ackcnt = 0; ackstr[ ackcnt++ ] = "\n"; dlog_multi_ack( ackstr, ackcnt ); querycnt = 0; querystr[ querycnt++ ] = _("please confirm\n"); assert( querycnt <= QUERYMAX ); choicecnt = 0; interruptix = choicecnt; choicestr[ choicecnt++ ] = _("interrupt this session"); nochangeix = choicecnt; choicestr[ choicecnt++ ] = _("continue"); assert( choicecnt <= CHOICEMAX ); responseix = dlog_multi_query( querystr, querycnt, choicestr, choicecnt, 0, /* hilitestr */ IXMAX, /* hiliteix */ 0, /* defaultstr */ nochangeix, /* defaultix */ DLOG_TIMEOUT,/* timeout */ nochangeix, /* timeout ix */ nochangeix, /* sigint ix */ nochangeix, /* sighup ix */ nochangeix);/* sigquit ix */ ackcnt = 0; if ( responseix == nochangeix ) { ackstr[ ackcnt++ ] = _("continuing\n"); } else { ackstr[ ackcnt++ ] = _("interrupt request accepted\n"); stop_requested = BOOL_TRUE; } dlog_multi_ack( ackstr, ackcnt ); } else if ( responseix == verbosityix ) { ackcnt = 0; ackstr[ ackcnt++ ] = "\n"; dlog_multi_ack( ackstr, ackcnt ); querycnt = 0; querystr[ querycnt++ ] = _("please select one of " "the following subsystems\n"); assert( querycnt <= QUERYMAX ); choicecnt = 0; /* number of lines must match number of subsystems */ for ( choicecnt = 0 ; choicecnt < MLOG_SS_CNT ; choicecnt++ ) { choicestr[ choicecnt ] = mlog_ss_names[ choicecnt ]; } allix = choicecnt; choicestr[ choicecnt++ ] = _("all of the above"); nochangeix = choicecnt; choicestr[ choicecnt++ ] = _("no change"); assert( choicecnt <= CHOICEMAX ); responseix = dlog_multi_query( querystr, querycnt, choicestr, choicecnt, 0, /* hilitestr */ IXMAX, /* hiliteix */ 0, /* defaultstr */ allix, /* defaultix */ DLOG_TIMEOUT,/* timeout */ nochangeix, /* timeout ix */ nochangeix, /* sigint ix */ nochangeix, /* sighup ix */ nochangeix);/* sigquit ix */ ackcnt = 0; if ( responseix == nochangeix ) { ackstr[ ackcnt++ ] = _("no change\n"); } else if ( responseix == allix ) { ssselected = -1; ackstr[ ackcnt++ ] = _("all subsystems selected\n\n"); } else { ssselected = ( int )responseix; ackstr[ ackcnt++ ] = "\n"; } dlog_multi_ack( ackstr, ackcnt ); if ( responseix != nochangeix ) { querycnt = 0; querystr[ querycnt++ ] = ("please select one of the " "following verbosity levels\n"); assert( querycnt <= QUERYMAX ); choicecnt = 0; choicestr[ choicecnt++ ] = _("silent"); choicestr[ choicecnt++ ] = _("verbose"); choicestr[ choicecnt++ ] = _("trace"); choicestr[ choicecnt++ ] = _("debug"); choicestr[ choicecnt++ ] = _("nitty"); choicestr[ choicecnt++ ] = _("nitty + 1"); nochangeix = choicecnt; choicestr[ choicecnt++ ] = _("no change"); assert( choicecnt <= CHOICEMAX ); responseix = dlog_multi_query( querystr, querycnt, choicestr, choicecnt, ssselected == -1 ? 0 : _(" (current)"),/* hilitestr */ ssselected == -1 ? IXMAX : ( ix_t )mlog_level_ss[ ssselected ], /* hiliteix */ 0, /* defaultstr */ nochangeix,/* defaultix */ DLOG_TIMEOUT,/* timeout */ nochangeix, /* timeout ix */ nochangeix, /* sigint ix */ nochangeix, /* sighup ix */ nochangeix);/* sigquit ix */ ackcnt = 0; if ( responseix == nochangeix || ( ssselected >= 0 && responseix == ( ix_t )mlog_level_ss[ ssselected ] )) { ackstr[ ackcnt++ ] = _("no change\n"); } else { if ( ssselected < 0 ) { ix_t ssix; assert( ssselected == -1 ); for ( ssix = 0 ; ssix < MLOG_SS_CNT ; ssix++ ) { mlog_level_ss[ ssix ] = ( int )responseix; } } else { mlog_level_ss[ ssselected ] = ( int )responseix; } ackstr[ ackcnt++ ] = _("level changed\n"); } dlog_multi_ack( ackstr, ackcnt ); } } else if ( responseix == metricsix ) { ackcnt = 0; ackstr[ ackcnt++ ] = "\n"; dlog_multi_ack( ackstr, ackcnt ); querycnt = 0; querystr[ querycnt++ ] = _("please select one of " "the following metrics\n"); assert( querycnt <= QUERYMAX ); choicecnt = 0; ioix = choicecnt; choicestr[ choicecnt++ ] = _("I/O"); #ifdef RESTORE piix = choicecnt; choicestr[ choicecnt++ ] = _("media inventory status"); roix = choicecnt; choicestr[ choicecnt++ ] = _("needed media objects"); #endif /* RESTORE */ nochangeix = choicecnt; choicestr[ choicecnt++ ] = _("continue"); assert( choicecnt <= CHOICEMAX ); responseix = dlog_multi_query( querystr, querycnt, choicestr, choicecnt, 0, /* hilitestr */ IXMAX, /* hiliteix */ 0, /* defaultstr */ nochangeix, /* defaultix */ DLOG_TIMEOUT, nochangeix, /* timeout ix */ nochangeix, /* sigint ix */ nochangeix, /* sighup ix */ nochangeix);/* sigquit ix */ if ( responseix != nochangeix ) { ackcnt = 0; ackstr[ ackcnt++ ] = "\n"; dlog_multi_ack( ackstr, ackcnt ); } if ( responseix == ioix ) { drive_display_metrics( ); #ifdef RESTORE } else if ( responseix == piix ) { content_showinv( ); } else if ( responseix == roix ) { content_showremainingobjects( ); #endif /* RESTORE */ } if ( responseix != nochangeix ) { querycnt = 0; querystr[ querycnt++ ] = "\n"; assert( querycnt <= QUERYMAX ); choicecnt = 0; nochangeix = choicecnt; choicestr[ choicecnt++ ] = _("continue"); assert( choicecnt <= CHOICEMAX ); responseix = dlog_multi_query( querystr, querycnt, choicestr, choicecnt, 0, /* hilitestr */ IXMAX, /* hiliteix */ 0, /* defaultstr */ nochangeix,/* defaultix*/ DLOG_TIMEOUT, nochangeix,/*timeout ix*/ nochangeix,/* sigint ix*/ nochangeix,/* sighup ix*/ nochangeix);/*sigquitix*/ } ackcnt = 0; ackstr[ ackcnt++ ] = _("continuing\n"); dlog_multi_ack( ackstr, ackcnt ); } else if ( responseix == mediachangeix ) { ackcnt = 0; dlog_multi_ack( ackstr, ackcnt ); ackcnt = 0; ackstr[ ackcnt++ ] = content_mediachange_query( ); dlog_multi_ack( ackstr, ackcnt ); } else if ( responseix == controlix ) { ackcnt = 0; ackstr[ ackcnt++ ] = "\n"; dlog_multi_ack( ackstr, ackcnt ); querycnt = 0; querystr[ querycnt++ ] = _("please select one of " "the following controls\n"); assert( querycnt <= QUERYMAX ); choicecnt = 0; progix = choicecnt; if ( progrpt_enabledpr ) { choicestr[ choicecnt++ ] = _("change interval of " "or disable progress reports"); } else { choicestr[ choicecnt++ ] = _("enable progress reports"); } mllevix = choicecnt; if ( mlog_showlevel ) { choicestr[ choicecnt++ ] = _("hide log message levels"); } else { choicestr[ choicecnt++ ] = _("show log message levels"); } mlssix = choicecnt; if ( mlog_showss ) { choicestr[ choicecnt++ ] = _("hide log message subsystems"); } else { choicestr[ choicecnt++ ] = _("show log message subsystems"); } mltsix = choicecnt; if ( mlog_timestamp ) { choicestr[ choicecnt++ ] = _("hide log message timestamps"); } else { choicestr[ choicecnt++ ] = _("show log message timestamps"); } nochangeix = choicecnt; choicestr[ choicecnt++ ] = _("continue"); assert( choicecnt <= CHOICEMAX ); responseix = dlog_multi_query( querystr, querycnt, choicestr, choicecnt, 0, /* hilitestr */ IXMAX, /* hiliteix */ 0, /* defaultstr */ nochangeix, /* defaultix */ DLOG_TIMEOUT, nochangeix, /* timeout ix */ nochangeix, /* sigint ix */ nochangeix, /* sighup ix */ nochangeix);/* sigquit ix */ ackcnt = 0; if ( responseix == progix ) { char buf[ 10 ]; const size_t ncix = 1; const size_t okix = 2; ackstr[ ackcnt++ ] = "\n"; dlog_multi_ack( ackstr, ackcnt ); ackcnt = 0; responseix = dlog_string_query( prompt_prog_cb, 0, buf, sizeof( buf ), DLOG_TIMEOUT, ncix,/* timeout ix */ ncix, /* sigint ix */ ncix, /* sighup ix */ ncix, /* sigquit ix */ okix ); if ( responseix == okix ) { int newinterval; newinterval = atoi( buf ); if ( ! strlen( buf )) { ackstr[ ackcnt++ ] = _("no change\n"); } else if ( newinterval > 0 ) { time32_t newdeadline; char intervalbuf[ 64 ]; newdeadline = time( 0 ) + ( time32_t )newinterval; if ( progrpt_enabledpr ) { if ( ( time32_t )newinterval == progrpt_interval ) { ackstr[ ackcnt++ ] = _("no change\n"); } else { ackstr[ ackcnt++ ] = _("changing progress report interval to "); sprintf( intervalbuf, _("%d seconds\n"), newinterval ); assert( strlen( intervalbuf ) < sizeof( intervalbuf )); ackstr[ ackcnt++ ] = intervalbuf; if ( progrpt_deadline > newdeadline ) { progrpt_deadline = newdeadline; } } } else { ackstr[ ackcnt++ ] = _("enabling progress reports at "); sprintf( intervalbuf, _("%d second intervals\n"), newinterval ); assert( strlen( intervalbuf ) < sizeof( intervalbuf )); ackstr[ ackcnt++ ] = intervalbuf; progrpt_enabledpr = BOOL_TRUE; progrpt_deadline = newdeadline; } progrpt_interval = ( time32_t )newinterval; } else { if ( progrpt_enabledpr ) { ackstr[ ackcnt++ ] = _("disabling progress reports\n"); } else { ackstr[ ackcnt++ ] = _("no change\n"); } progrpt_enabledpr = BOOL_FALSE; } } else { ackstr[ ackcnt++ ] = _("no change\n"); } } else if ( responseix == mllevix ) { mlog_showlevel = ! mlog_showlevel; if ( mlog_showlevel ) { ackstr[ ackcnt++ ] = _("showing log message levels\n"); } else { ackstr[ ackcnt++ ] = _("hiding log message levels\n"); } } else if ( responseix == mlssix ) { mlog_showss = ! mlog_showss; if ( mlog_showss ) { ackstr[ ackcnt++ ] = _("showing log message subsystems\n"); } else { ackstr[ ackcnt++ ] = _("hiding log message subsystems\n"); } } else if ( responseix == mltsix ) { mlog_timestamp = ! mlog_timestamp; if ( mlog_timestamp ) { ackstr[ ackcnt++ ] = _("showing log message timestamps\n"); } else { ackstr[ ackcnt++ ] = _("hiding log message timestamps\n"); } } dlog_multi_ack( ackstr, ackcnt ); } else { ackcnt = 0; ackstr[ ackcnt++ ] = _("continuing\n"); dlog_multi_ack( ackstr, ackcnt ); } fold_init( fold, _("end dialog"), '-' ); postamblecnt = 0; postamblestr[ postamblecnt++ ] = "\n"; postamblestr[ postamblecnt++ ] = fold; postamblestr[ postamblecnt++ ] = "\n\n"; assert( postamblecnt <= POSTAMBLEMAX ); dlog_end( postamblestr, postamblecnt ); return stop_requested; } static char * sigintstr( void ) { int ttyfd; static char buf[ 20 ]; struct termios termios; cc_t intchr; int rval; ttyfd = dlog_fd( ); if ( ttyfd == -1 ) { return 0; } rval = tcgetattr( ttyfd, &termios ); if ( rval ) { mlog( MLOG_NITTY | MLOG_PROC, "could not get controlling terminal information: %s\n", strerror( errno )); return 0; } intchr = termios.c_cc[ VINTR ]; mlog( MLOG_NITTY | MLOG_PROC, "tty fd: %d; terminal interrupt character: %c (0%o)\n", ttyfd, intchr, intchr ); if ( intchr < ' ' ) { sprintf( buf, "^%c", intchr + '@' ); } else if ( intchr == 0177 ) { sprintf( buf, "DEL" ); } else { sprintf( buf, "%c", intchr ); } assert( strlen( buf ) < sizeof( buf )); return buf; } #ifdef DUMP static bool_t set_rlimits( void ) #endif /* DUMP */ #ifdef RESTORE static bool_t set_rlimits( size64_t *vmszp ) #endif /* RESTORE */ { struct rlimit64 rlimit64; #ifdef RESTORE size64_t vmsz; #endif /* RESTORE */ /* REFERENCED */ int rval; assert( minstacksz <= maxstacksz ); rval = getrlimit64( RLIMIT_AS, &rlimit64 ); assert( ! rval ); mlog( MLOG_NITTY | MLOG_NOLOCK | MLOG_PROC, "RLIMIT_AS org cur 0x%llx max 0x%llx\n", rlimit64.rlim_cur, rlimit64.rlim_max ); #ifdef RESTORE if (rlimit64.rlim_cur != RLIM64_INFINITY) { rlimit64.rlim_cur = rlimit64.rlim_max; ( void )setrlimit64( RLIMIT_AS, &rlimit64 ); rval = getrlimit64( RLIMIT_AS, &rlimit64 ); assert( ! rval ); mlog( MLOG_NITTY | MLOG_NOLOCK | MLOG_PROC, "RLIMIT_VMEM now cur 0x%llx max 0x%llx\n", rlimit64.rlim_cur, rlimit64.rlim_max ); } vmsz = ( size64_t )rlimit64.rlim_cur; #endif /* RESTORE */ assert( minstacksz <= maxstacksz ); rval = getrlimit64( RLIMIT_STACK, &rlimit64 ); assert( ! rval ); mlog( MLOG_NITTY | MLOG_NOLOCK | MLOG_PROC, "RLIMIT_STACK org cur 0x%llx max 0x%llx\n", rlimit64.rlim_cur, rlimit64.rlim_max ); if ( rlimit64.rlim_cur < minstacksz ) { if ( rlimit64.rlim_max < minstacksz ) { mlog( MLOG_DEBUG | MLOG_NOLOCK | MLOG_PROC, "raising stack size hard limit " "from 0x%llx to 0x%llx\n", rlimit64.rlim_max, minstacksz ); rlimit64.rlim_cur = minstacksz; rlimit64.rlim_max = minstacksz; ( void )setrlimit64( RLIMIT_STACK, &rlimit64 ); rval = getrlimit64( RLIMIT_STACK, &rlimit64 ); assert( ! rval ); if ( rlimit64.rlim_cur < minstacksz ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_NOLOCK | MLOG_PROC, _("unable to raise stack size hard limit " "from 0x%llx to 0x%llx\n"), rlimit64.rlim_max, minstacksz ); } } else { mlog( MLOG_DEBUG | MLOG_NOLOCK | MLOG_PROC, "raising stack size soft limit " "from 0x%llx to 0x%llx\n", rlimit64.rlim_cur, minstacksz ); rlimit64.rlim_cur = minstacksz; ( void )setrlimit64( RLIMIT_STACK, &rlimit64 ); rval = getrlimit64( RLIMIT_STACK, &rlimit64 ); assert( ! rval ); if ( rlimit64.rlim_cur < minstacksz ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_NOLOCK | MLOG_PROC, _("unable to raise stack size soft limit " "from 0x%llx to 0x%llx\n"), rlimit64.rlim_cur, minstacksz ); } } } else if ( rlimit64.rlim_cur > maxstacksz ) { mlog( MLOG_DEBUG | MLOG_NOLOCK | MLOG_PROC, "lowering stack size soft limit " "from 0x%llx to 0x%llx\n", rlimit64.rlim_cur, maxstacksz ); rlimit64.rlim_cur = maxstacksz; ( void )setrlimit64( RLIMIT_STACK, &rlimit64 ); rval = getrlimit64( RLIMIT_STACK, &rlimit64 ); assert( ! rval ); if ( rlimit64.rlim_cur > maxstacksz ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_NOLOCK | MLOG_PROC, _("unable to lower stack size soft limit " "from 0x%llx to 0x%llx\n"), rlimit64.rlim_cur, maxstacksz ); } } mlog( MLOG_NITTY | MLOG_NOLOCK | MLOG_PROC, "RLIMIT_STACK new cur 0x%llx max 0x%llx\n", rlimit64.rlim_cur, rlimit64.rlim_max ); rval = getrlimit64( RLIMIT_DATA, &rlimit64 ); assert( ! rval ); mlog( MLOG_NITTY | MLOG_NOLOCK | MLOG_PROC, "RLIMIT_DATA org cur 0x%llx max 0x%llx\n", rlimit64.rlim_cur, rlimit64.rlim_max ); rval = getrlimit64( RLIMIT_FSIZE, &rlimit64 ); assert( ! rval ); mlog( MLOG_NITTY | MLOG_NOLOCK | MLOG_PROC, "RLIMIT_FSIZE org cur 0x%llx max 0x%llx\n", rlimit64.rlim_cur, rlimit64.rlim_max ); rlimit64.rlim_cur = rlimit64.rlim_max; ( void )setrlimit64( RLIMIT_FSIZE, &rlimit64 ); rlimit64.rlim_cur = RLIM64_INFINITY; ( void )setrlimit64( RLIMIT_FSIZE, &rlimit64 ); rval = getrlimit64( RLIMIT_FSIZE, &rlimit64 ); assert( ! rval ); mlog( MLOG_NITTY | MLOG_NOLOCK | MLOG_PROC, "RLIMIT_FSIZE now cur 0x%llx max 0x%llx\n", rlimit64.rlim_cur, rlimit64.rlim_max ); rval = getrlimit64( RLIMIT_CPU, &rlimit64 ); assert( ! rval ); mlog( MLOG_NITTY | MLOG_NOLOCK | MLOG_PROC, "RLIMIT_CPU cur 0x%llx max 0x%llx\n", rlimit64.rlim_cur, rlimit64.rlim_max ); rlimit64.rlim_cur = rlimit64.rlim_max; ( void )setrlimit64( RLIMIT_CPU, &rlimit64 ); rval = getrlimit64( RLIMIT_CPU, &rlimit64 ); assert( ! rval ); mlog( MLOG_NITTY | MLOG_NOLOCK | MLOG_PROC, "RLIMIT_CPU now cur 0x%llx max 0x%llx\n", rlimit64.rlim_cur, rlimit64.rlim_max ); #ifdef RESTORE *vmszp = vmsz; #endif /* RESTORE */ return BOOL_TRUE; } struct sig_printmap { int num; char *string; }; typedef struct sig_printmap sig_printmap_t; static sig_printmap_t sig_printmap[ ] = { {SIGHUP, "SIGHUP"}, {SIGINT, "SIGINT"}, {SIGQUIT, "SIGQUIT"}, {SIGILL, "SIGILL"}, {SIGABRT, "SIGABRT"}, {SIGFPE, "SIGFPE"}, {SIGBUS, "SIGBUS"}, {SIGSEGV, "SIGSEGV"}, #ifdef SIGSYS {SIGSYS, "SIGSYS"}, #endif {SIGPIPE, "SIGPIPE"}, {SIGALRM, "SIGALRM"}, {SIGTERM, "SIGTERM"}, {SIGUSR1, "SIGUSR1"}, {SIGUSR2, "SIGUSR2"}, {SIGCLD, "SIGCLD"}, {SIGPWR, "SIGPWR"}, {SIGURG, "SIGURG"}, {SIGPOLL, "SIGPOLL"}, {SIGXCPU, "SIGXCPU"}, {SIGXFSZ, "SIGXFSZ"}, #if HIDDEN {SIGRTMIN, "SIGRTMIN"}, {SIGRTMAX, "SIGRTMAX"}, #endif {0, "???"} }; static char * sig_numstring( int num ) { sig_printmap_t *p = sig_printmap; sig_printmap_t *endp = sig_printmap + ( sizeof( sig_printmap ) / sizeof( sig_printmap[ 0 ] )); for ( ; p < endp ; p++ ) { if ( p->num == num ) { return p->string; } } return "???"; } static char * strpbrkquotes( char *p, const char *sep ) { bool_t prevcharwasbackslash = BOOL_FALSE; bool_t inquotes = BOOL_FALSE; for ( ; ; p++ ) { if ( *p == 0 ) { return 0; } if ( *p == '\\' ) { if ( ! prevcharwasbackslash ) { prevcharwasbackslash = BOOL_TRUE; } else { prevcharwasbackslash = BOOL_FALSE; } continue; } if ( *p == '"' ) { if ( prevcharwasbackslash ) { prevcharwasbackslash = BOOL_FALSE; continue; } if ( inquotes ) { inquotes = BOOL_FALSE; } else { inquotes = BOOL_TRUE; } continue; } if ( ! inquotes ) { if ( strchr( sep, ( int )( *p ))) { return p; } } prevcharwasbackslash = BOOL_FALSE; } /* NOTREACHED */ } static char * stripquotes( char *p ) { size_t len = strlen( p ); char *endp; char *nextp; bool_t justremovedbackslash; if ( len > 2 && p[ 0 ] == '"' ) { p++; len--; if ( len && p[ len - 1 ] == '"' ) { p[ len - 1 ] = 0; len--; } } endp = p + len; justremovedbackslash = BOOL_FALSE; for ( nextp = p ; nextp < endp ; ) { if ( *nextp == '\\' && ! justremovedbackslash ) { shiftleftby1( nextp, endp ); endp--; justremovedbackslash = BOOL_TRUE; } else { justremovedbackslash = BOOL_FALSE; nextp++; } } return p; } static void shiftleftby1( char *p, char *endp ) { for ( ; p < endp ; p++ ) { *p = p[ 1 ]; } } xfsdump-3.1.6+nmu1/common/ring.h0000644000000000000000000001666612620476160013374 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef RING_H #define RING_H /* ring - readahead/writeahead abstraction * * the ring is conceptually an ordered set of messages circulating between the * client thread and the I/O slave thread. a message can be in one of four * places: on the ready queue, held by the client, on the active queue, or held * by the slave. The client and slave can each hold at most one message at a * time. all others must be on one of the two queues. the messages must * circulate in that order: ready, client, active, slave, ready, ... * initially all messages are on the ready queue, with status set to * INIT. The client uses ring_get to remove a message from the ready queue. * the client can then use the message to read or write. to read, the client * sets the op field to READ, and places the message on the active queue. the * slave will remove messages from the active queue, invoke the client-supplied * read function with the message's buffer, record the read function's return * value in the message, set the message status to OK (read function returned 0) * or ERROR (read returned non-zero), and place the message on the ready queue. * the client will see the message after removing all messages ahead of it on * the ready queue. to write, the client follows almost the same procedure, * except the client fills the buffer and sets the op to WRITE prior to placing * the message on the active queue. * * if the client-supplied read or write function returns an error, the slave * will set the message status to ERROR. the slave will pass all subsequent * messages appearing on the active queue directly to the ready queue with * no I/O done and the message status set to IGNORE. the slave will remain * in this state until a reset is performed (see below). * * The client may at anytime place a NOP msg on the ring. the slave does * nothing with this mmessage other than to place it back on the ready queue * with NOPACK status. This is useful for inhibiting read-ahead. * * To flush the ring, the client must repetatively place TRACE messages on the * active queue until it sees an IGNORE msg on the ready queue. the slave will * simply transfer TRACErs from active to ready with no other action taken * (other than to set the message status to IGNORE). * * the client may at any time reset the ring. the reset will return to the * client when the current I/O being executed by the slave completes, and * all messages have been wiped clean and placed on the ready queue with * status set to INIT. the ring_reset function accomplishes this internally by * placing a RESET message on the active QUEUE, and continuing to remove * messages from the ready queue (without placing them on the active queue) * until the RESET message is seen the slave responds to a reset message by * setting the status to RESETACK, queueing the message on the ready queue, and * waiting for a message from the active queue. ring_reset will then re- * initialize the ring and return. note that the client may be holding one * message at the time the reset is called. if so, it must pass a pointer to * that message into the reset call. otherwise it must pass in NULL. * * the ring_destroy function may be invoked to shut down the ring and kill the * slave thread. it simply places a DIE message on the active queue, and waits * for a DIEACK response. it then de-allocates all semaphores memory allocated * by ring_create. * * the message structure includes a 64 bit field for the convenience * of the client. it is not perturbed during any ring operations. * * the ring maintains four performance metering values: the number of times * the slave and client attempted to get a message, and the number of times * those attempts resulting in blocking. */ /* ring_msg - structure of messages managed by ring */ enum ring_op { RING_OP_NONE, RING_OP_READ, RING_OP_WRITE, RING_OP_NOP, RING_OP_TRACE, RING_OP_RESET, RING_OP_DIE }; typedef enum ring_op ring_op_t; enum ring_stat { RING_STAT_INIT, RING_STAT_OK, RING_STAT_ERROR, RING_STAT_NOPACK, RING_STAT_IGNORE, RING_STAT_RESETACK, RING_STAT_DIEACK }; typedef enum ring_stat ring_stat_t; enum ring_loc { RING_LOC_READY, RING_LOC_ACTIVE, RING_LOC_CLIENT, RING_LOC_SLAVE }; typedef enum ring_loc ring_loc_t; struct ring_msg { ring_op_t rm_op; ring_stat_t rm_stat; int rm_rval; off64_t rm_user; char *rm_bufp; /* ALL BELOW PRIVATE!!! */ size_t rm_mix; ring_loc_t rm_loc; }; typedef struct ring_msg ring_msg_t; /* ring - instantiation of a ring */ struct ring { off64_t r_client_msgcnt; off64_t r_slave_msgcnt; off64_t r_client_blkcnt; off64_t r_slave_blkcnt; time32_t r_first_io_time; off64_t r_all_io_cnt; /* ALL BELOW PRIVATE!!! */ size_t r_len; ring_msg_t *r_msgp; size_t r_ready_in_ix; size_t r_ready_out_ix; qsemh_t r_ready_qsemh; size_t r_active_in_ix; size_t r_active_out_ix; qsemh_t r_active_qsemh; size_t r_client_cnt; size_t r_slave_cnt; int ( *r_readfunc )( void *contextp, char *bufp ); int ( *r_writefunc )( void *contextp, char *bufp ); void *r_clientctxp; }; typedef struct ring ring_t; /* ring_create - creates a ring. parameters supply the length of the ring, * the read/write buffer size, the drive index, a function for reading, a * function for writing, and a pointer to client context for the read and * write functions. returns a pointer to a ring if successful, a NULL * pointer if not. the read and write functions should return 0 on success, * or an error code on failure which will be recorded in the rm_rval field * of the message invoking the failed operation. if null pointer returned, * the location pointed to by rvalp will contain one of the following: * ENOMEM - could not allocate some portion of the ring memory; * E2BIG - insufficient physical memory available for pinning; * EPERM - exceeds allowed amount of pinned down memory. */ extern ring_t *ring_create( size_t ringlen, size_t bufsz, bool_t pinpr, ix_t drive_index, int ( * readfunc )( void *clientctxp, char *bufp ), int ( * writefunc )( void *clientctxp, char *bufp ), void *clientctxp, int *rvalp ); /* ring_get - get a message off the ready queue */ extern ring_msg_t *ring_get( ring_t *ringp ); /* ring_put - put a message on the active queue */ extern void ring_put( ring_t *ringp, ring_msg_t *msgp ); /* ring_reset - re-initialize the ring, after the current I/O completes. * msgp must be NULL if the client is not currently holding a ring message. * otherwise it must point to that message. */ extern void ring_reset( ring_t *ringp, ring_msg_t *msgp ); /* ring_destroy - de-allocates ring */ extern void ring_destroy( ring_t *ringp ); #endif /* RING_H */ xfsdump-3.1.6+nmu1/common/lock.h0000644000000000000000000000153712607344125013354 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef LOCK_H #define LOCK_H extern bool_t lock_init( void ); extern void lock( void ); extern void unlock( void ); #endif /* LOCK_H */ xfsdump-3.1.6+nmu1/common/cleanup.c0000644000000000000000000000552212620476160014044 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include "cleanup.h" struct cu { void ( * cu_funcp )( void *arg1, void *arg2 ); void *cu_arg1; void *cu_arg2; int cu_flags; struct cu *cu_nextp; }; /* Cleanup structure flags */ #define CU_EARLY 0x00000001 /* call cleanup routine before calling killall */ typedef struct cu cu_t; static cu_t *cu_rootp; void cleanup_init( void ) { cu_rootp = 0; } static cleanup_t * cleanup_register_base( void ( * funcp )( void *arg1, void *arg2 ), void *arg1, void *arg2 ) { cu_t *p; p = ( cu_t * )calloc( 1, sizeof( cu_t )); assert( p ); p->cu_funcp = funcp; p->cu_arg1 = arg1; p->cu_arg2 = arg2; p->cu_flags = 0; p->cu_nextp = cu_rootp; cu_rootp = p; return ( cleanup_t *)p; } cleanup_t * cleanup_register( void ( * funcp )( void *arg1, void *arg2 ), void *arg1, void *arg2 ) { cu_t *p; p = cleanup_register_base( funcp, arg1, arg2 ); return ( cleanup_t *)p; } cleanup_t * cleanup_register_early( void ( * funcp )( void *arg1, void *arg2 ), void *arg1, void *arg2 ) { cu_t *p; p = cleanup_register_base( funcp, arg1, arg2 ); p->cu_flags = CU_EARLY; return ( cleanup_t *)p; } void cleanup_cancel( cleanup_t *cleanupp ) { cu_t *p = ( cu_t *)cleanupp; cu_t *nextp; cu_t *prevp; assert( cu_rootp ); for ( prevp = 0, nextp = cu_rootp ; nextp && nextp != p ; prevp = nextp, nextp = nextp->cu_nextp ) ; assert( nextp ); if ( prevp ) { prevp->cu_nextp = p->cu_nextp; } else { cu_rootp = p->cu_nextp; } free( ( void * )p ); } void cleanup( void ) { while ( cu_rootp ) { cu_t *p = cu_rootp; ( * p->cu_funcp )( p->cu_arg1, p->cu_arg2 ); cu_rootp = p->cu_nextp; free( ( void * )p ); } } void cleanup_early( void ) { cu_t *cuptr, *cuprevp; cuptr = cu_rootp; cuprevp = NULL; while ( cuptr ) { cu_t *cunextp = cuptr->cu_nextp; if ( cuptr->cu_flags & CU_EARLY) { ( * cuptr->cu_funcp )( cuptr->cu_arg1, cuptr->cu_arg2 ); free( ( void * )cuptr ); if ( cuprevp ) { cuprevp->cu_nextp = cunextp; } else { cu_rootp = cunextp; } cuptr = cunextp; } else { cuprevp = cuptr; cuptr = cunextp; } } } xfsdump-3.1.6+nmu1/common/content_inode.h0000644000000000000000000003113012620476160015244 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef CONTENT_INODE_H #define CONTENT_INODE_H /* content_inode.h - inode-style content strategy-specific header structure */ /* dump startpoint: identifies dump stream boundaries * NOTE: sp_offset is not a position within a file; it is a quantity of * bytes to skip. holes do not count. */ struct startpt { xfs_ino_t sp_ino; /* first inode to dump */ off64_t sp_offset; /* bytes to skip in file data fork */ int32_t sp_flags; int32_t sp_pad1; }; typedef struct startpt startpt_t; #define STARTPT_FLAGS_END ( 1 << 0 ) /* this startpt indicates that all extents of all files in * the stream were completely dumped. the other fields * are meaningless. this will appear only once per dump * stream, even if the stream spans multiple media files. * * also used in the strategy-specific portion of the * content header to qualify the ending point. */ #define STARTPT_FLAGS_NULL ( 1 << 1 ) /* used to detect if the null file header makes it onto * media. only necessary after the last file in the stream, * to allow the end-of-stream flag in the null header to * be seen. */ /* drange_t - describes a range of ino/offset values */ struct drange { startpt_t dr_begin; startpt_t dr_end; }; typedef struct drange drange_t; /* inode-style specific media file header section */ #define CONTENT_INODE_HDR_SZ sizeofmember( content_hdr_t, ch_specific ) struct content_inode_hdr { int32_t cih_mediafiletype; /* 4 4 */ /* dump media file type: see #defines below */ int32_t cih_dumpattr; /* 4 8 */ /* dump attributes: see #defines below */ int32_t cih_level; /* 4 c */ /* dump level */ char pad1[ 4 ]; /* 4 10 */ /* alignment */ time32_t cih_last_time; /* 4 14 */ /* if an incremental,time of previous dump at a lesser level */ time32_t cih_resume_time; /* 4 18 */ /* if a resumed dump, time of interrupted dump */ xfs_ino_t cih_rootino; /* 8 20 */ /* root inode number */ uuid_t cih_last_id; /* 10 30 */ /* if an incremental, uuid of prev dump */ uuid_t cih_resume_id; /* 10 40 */ /* if a resumed dump, uuid of interrupted dump */ startpt_t cih_startpt; /* 18 58 */ /* starting point of media file contents */ startpt_t cih_endpt; /* 18 70 */ /* starting point of next stream */ uint64_t cih_inomap_hnkcnt; /* 8 78 */ uint64_t cih_inomap_segcnt; /* 8 80 */ uint64_t cih_inomap_dircnt; /* 8 88 */ uint64_t cih_inomap_nondircnt; /* 8 90 */ xfs_ino_t cih_inomap_firstino; /* 8 98 */ xfs_ino_t cih_inomap_lastino; /* 8 a0 */ uint64_t cih_inomap_datasz; /* 8 a8 */ /* bytes of non-metadata dumped */ char cih_pad2[ CONTENT_INODE_HDR_SZ - 0xa8 ]; /* 18 c0 */ /* padding */ }; typedef struct content_inode_hdr content_inode_hdr_t; /* media file types */ #define CIH_MEDIAFILETYPE_DATA 0 #define CIH_MEDIAFILETYPE_INVENTORY 1 #define CIH_MEDIAFILETYPE_INDEX 2 /* dump attributes */ #define CIH_DUMPATTR_SUBTREE ( 1 << 0 ) #define CIH_DUMPATTR_INDEX ( 1 << 1 ) #define CIH_DUMPATTR_INVENTORY ( 1 << 2 ) #define CIH_DUMPATTR_INCREMENTAL ( 1 << 3 ) #define CIH_DUMPATTR_RETRY ( 1 << 4 ) #define CIH_DUMPATTR_RESUME ( 1 << 5 ) #define CIH_DUMPATTR_INOMAP ( 1 << 6 ) #define CIH_DUMPATTR_DIRDUMP ( 1 << 7 ) #define CIH_DUMPATTR_FILEHDR_CHECKSUM ( 1 << 8 ) #define CIH_DUMPATTR_EXTENTHDR_CHECKSUM ( 1 << 9 ) #define CIH_DUMPATTR_DIRENTHDR_CHECKSUM ( 1 << 10 ) #define CIH_DUMPATTR_DIRENTHDR_GEN ( 1 << 11 ) #define CIH_DUMPATTR_EXTATTR ( 1 << 12 ) #define CIH_DUMPATTR_EXTATTRHDR_CHECKSUM ( 1 << 13 ) #define CIH_DUMPATTR_NOTSELFCONTAINED ( 1 << 14 ) /* timestruct_t - time structure * * used in bstat_t below. derived from timestruc_t, to achieve independence * from changes to timestruc_t. */ #define TIMESTRUCT_SZ 8 struct timestruct { /* bytes accum */ int32_t tv_sec; /* seconds 4 4 */ int32_t tv_nsec; /* and nanoseconds 4 8 */ }; typedef struct timestruct timestruct_t; /* bstat_t - bulk stat structure * * used in filehdr_t below. derived from xfs_bstat_t, to achieve independence * from changes to xfs_bstat_t. */ #define BSTAT_SZ 128 #define MODE_SZ 4 struct bstat { /* bytes accum */ xfs_ino_t bs_ino; /* inode number 8 8 */ uint32_t bs_mode; /* type and mode 4 c */ uint32_t bs_nlink; /* number of links 4 10 */ int32_t bs_uid; /* user id 4 14 */ int32_t bs_gid; /* group id 4 18 */ uint32_t bs_rdev; /* device value 4 1c */ int32_t bs_blksize; /* block size 4 20 */ off64_t bs_size; /* file size 8 28 */ timestruct_t bs_atime; /* access time 8 30 */ timestruct_t bs_mtime; /* modify time 8 38 */ timestruct_t bs_ctime; /* inode change time 8 40 */ int64_t bs_blocks; /* number of blocks 8 48 */ uint32_t bs_xflags; /* extended flags 4 4c */ int32_t bs_extsize; /* extent size 4 50 */ int32_t bs_extents; /* number of extents 4 54 */ uint32_t bs_gen; /* generation count 4 58 */ uint16_t bs_projid_lo; /* low 16 of project id 2 5a */ uint16_t bs_forkoff; /* inode fork offset 2 5c */ uint16_t bs_projid_hi; /* hi 16 of project id 2 5e */ char bs_pad[ 10 ]; /* for expansion e 68 */ uint32_t bs_dmevmask; /* DMI event mask 4 6c */ uint16_t bs_dmstate; /* DMI state info 2 6e */ char bs_pad1[ 18 ]; /* for expansion 12 80 */ /* NOTE: old dumps didn't always * zero first 2 bytes of bs_pad1 */ }; typedef struct bstat bstat_t; /* * Project quota id helpers (previously projid was 16bit only * and using two 16bit values to hold new 32bit projid was choosen * to retain compatibility with "old" filesystems). */ static inline __uint32_t bstat_projid(struct bstat *bs) { return (__uint32_t)bs->bs_projid_hi << 16 | bs->bs_projid_lo; } /* extended inode flags that can only be set after all data * has been restored to a file. */ #define POST_DATA_XFLAGS ( XFS_XFLAG_IMMUTABLE | \ XFS_XFLAG_APPEND | \ XFS_XFLAG_SYNC ) /* filehdr_t - header placed at the beginning of every dumped file. * * each fs file placed on dump media begins with a FILEHDR_SZ-byte header. * following that are one or more variable-length content extents. * the content extents contain the actual data associated with the fs file. */ #define FILEHDR_SZ 256 struct filehdr { int64_t fh_offset; int32_t fh_flags; uint32_t fh_checksum; bstat_t fh_stat; char fh_pad2[ FILEHDR_SZ - sizeof( int64_t ) - sizeof( int32_t ) - sizeof( uint32_t ) - sizeof( bstat_t ) ]; }; typedef struct filehdr filehdr_t; #define FILEHDR_FLAGS_NULL ( 1 << 0 ) /* identifies a dummy file header. every media file * is terminated with a dummy file header, unless * terminated by end of media. */ #define FILEHDR_FLAGS_CHECKSUM ( 1 << 1 ) /* indicates the header checksum is valid */ #define FILEHDR_FLAGS_END ( 1 << 2 ) /* the last media file in the stream is always terminated by * a dummy file header, with this flag set. */ #define FILEHDR_FLAGS_EXTATTR ( 1 << 3 ) /* special file header followed by one file's (dir or nondir) * extended attributes. */ /* extenthdr_t - a header placed at the beginning of every dumped * content extent. * * a dumped file consists of a filehdr_t followed by zero or more * extents. for regular files the last extent is always of type LAST. * for symbolic link files, only one extent is dumped, and it contains the * symlink path. */ #define EXTENTHDR_SZ 32 struct extenthdr { off64_t eh_sz; /* length of extent, NOT including header, in bytes */ off64_t eh_offset; int32_t eh_type; int32_t eh_flags; uint32_t eh_checksum; char eh_pad[ 4 ]; }; typedef struct extenthdr extenthdr_t; #define EXTENTHDR_TYPE_LAST 0 /* always the last extent. sz is always 0 */ #define EXTENTHDR_TYPE_ALIGN 1 /* used for alignment. sz is the number of bytes to skip, * in addition to the hdr */ #define EXTENTHDR_TYPE_DATA 4 /* heads an extent of ordinary file data. sz is the data * extent length in bytes, NOT including the hdr. offset * indicates the byte position of the extent within the file. * also heads the path in a symlink dump. */ #define EXTENTHDR_TYPE_HOLE 8 /* used to encode a hole extent. Offset indicates the byte * position of the hole within the file and sz is the * hole extent length. */ #define EXTENTHDR_FLAGS_CHECKSUM ( 1 << 0 ) /* direnthdr_t - placed at the beginning of every dumped directory entry. * a directory entry consists of the fixed size header followed by a variable * length NULL-terminated name string, followed by enough padding to make the * overall record size a multiple of 8 bytes. the name string begins * at the dh_name field. the total number of bytes occupied by * each directory entry on media is dh_sz. * * a sequence of directory entries is always terminated with a null direnthdr_t. * this is detected by looking for a zero ino. */ typedef uint32_t gen_t; #define DIRENTHDR_ALIGN 8 #define DIRENTHDR_SZ 24 struct direnthdr { xfs_ino_t dh_ino; gen_t dh_gen; uint32_t dh_checksum; uint16_t dh_sz; /* overall size of record */ char dh_name[ 6 ]; }; typedef struct direnthdr direnthdr_t; /* the old direnthdr truncated the inode generation number * to the low 12 bits. */ struct direnthdr_v1 { xfs_ino_t dh_ino; uint16_t dh_gen; /* generation count & DENTGENMASK of ref'ed inode */ uint16_t dh_sz; /* overall size of record */ uint32_t dh_checksum; char dh_name[ 8 ]; }; typedef struct direnthdr_v1 direnthdr_v1_t; /* truncated generation count */ #define DENTGENSZ 12 /* leave 4 bits for future flags */ #define DENTGENMASK (( 1 << DENTGENSZ ) - 1 ) #define BIGGEN2GEN( bg ) ( ( gen_t )( bg & DENTGENMASK )) /* symbolic links will be dumped using an extent header. the extent * will always be a multiple of SYMLINK_ALIGN bytes. the symlink character * string will always be null-terminated. */ #define SYMLINK_ALIGN 8 /* extattr_hdr_t - hdr for an extended attribute. the first byte of the * attribute name immediately follows the header. the name is terminated * with a NULL byte. Each extattr record will be aligned; there may * be padding at the end of each record to achieve this. NOTE: ah_sz * includes the hdr sz; adding ah_sz to the offset of one extattr * gives the offset of the next. */ #define EXTATTRHDR_SZ 16 #define EXTATTRHDR_ALIGN 8 struct extattrhdr { uint32_t ah_sz; /* overall size of extended attribute record */ uint16_t ah_valoff; /* byte offset within record of value */ uint16_t ah_flags; /* see EXTATTRHDR_FLAGS_... below */ uint32_t ah_valsz; /* size of value */ uint32_t ah_checksum; /* hdr checksum */ }; typedef struct extattrhdr extattrhdr_t; #define EXTATTRHDR_FLAGS_ROOT ( 1 << 0 ) /* a "root" mode attribute */ #define EXTATTRHDR_FLAGS_NULL ( 1 << 1 ) /* marks the end of the attributes associated with the leading filehdr_t */ #define EXTATTRHDR_FLAGS_OLD_CHECKSUM ( 1 << 2 ) /* old xfsdumps used this flag to indicate a checksum is present, * but the checksum was not calculated properly. the presence of * this flag now indicates a checksum that cannot be verified. */ #define EXTATTRHDR_FLAGS_SECURE ( 1 << 3 ) /* a linux "secure" mode attribute */ #define EXTATTRHDR_FLAGS_CHECKSUM ( 1 << 4 ) /* checksum is present. */ /* Routines for calculating and validating checksums on xfsdump headers. * The header length must be an integral number of uint32_t's. */ static inline uint32_t calc_checksum(void *bufp, size_t len) { uint32_t sum = 0; uint32_t *sump = bufp; uint32_t *endp = sump + len / sizeof(uint32_t); assert(len % sizeof(uint32_t) == 0); while (sump < endp) sum += *sump++; return ~sum + 1; } static inline bool_t is_checksum_valid(void *bufp, size_t len) { uint32_t sum = 0; uint32_t *sump = bufp; uint32_t *endp = sump + len / sizeof(uint32_t); assert(len % sizeof(uint32_t) == 0); while (sump < endp) sum += *sump++; return sum == 0 ? BOOL_TRUE : BOOL_FALSE; } #endif /* CONTENT_INODE_H */ xfsdump-3.1.6+nmu1/common/exit.h0000644000000000000000000000244012620476160013367 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef EXIT_H #define EXIT_H /* exit codes for main and child processes */ #define EXIT_NORMAL 0 /* normal completion / don't exit */ #define EXIT_ERROR 1 /* resource error or resource exhaustion */ #define EXIT_INTERRUPT 2 /* interrupted (operator or device error) */ #define EXIT_FAULT 4 /* code fault */ static inline const char * exit_codestring( int code ) { switch ( code ) { case EXIT_NORMAL: return "SUCCESS"; case EXIT_ERROR: return "ERROR"; case EXIT_INTERRUPT: return "INTERRUPT"; case EXIT_FAULT: return "FAULT"; } return "UNKNOWN"; } #endif /* EXIT_H */ xfsdump-3.1.6+nmu1/common/getdents.c0000644000000000000000000000763712607344125014243 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* * Copyright (C) 1993, 95, 96, 97, 98, 99,2000,2001 Free Software Foundation, Inc. * This file is based almost entirely on getdents.c in the GNU C Library. */ #include #include #include #include #include #include #include #include #include #include #include #include struct kernel_dirent64 { uint64_t d_ino; int64_t d_off; unsigned short int d_reclen; unsigned char d_type; char d_name[256]; }; /* The problem here is that we cannot simply read the next NBYTES bytes. We need to take the additional field into account. We use some heuristic. Assuming the directory contains names with 14 characters on average we can compute an estimated number of entries which fit in the buffer. Taking this number allows us to specify a reasonable number of bytes to read. If we should be wrong, we can reset the file descriptor. In practice the kernel is limiting the amount of data returned much more then the reduced buffer size. */ int getdents_wrap(int fd, char *buf, size_t nbytes) { struct dirent *dp; struct kernel_dirent64 *kdp; off64_t last_offset = -1; ssize_t retval; char *kbuf = buf; size_t kbytes = nbytes; const size_t size_diff = (offsetof(struct kernel_dirent64, d_name) - offsetof(struct dirent, d_name)); if (offsetof(struct dirent, d_name) < offsetof(struct kernel_dirent64, d_name) && nbytes <= sizeof(struct dirent)) { kbytes = nbytes + size_diff; kbuf = alloca(kbytes); } retval = syscall(SYS_getdents64, fd, kbuf, kbytes); if (retval != -1) return retval; /* If the structure returned by the kernel is identical to what we need, don't do any conversions. */ if (offsetof(struct dirent, d_name) == offsetof(struct kernel_dirent64, d_name) && sizeof(dp->d_ino) == sizeof(kdp->d_ino) && sizeof(dp->d_off) == sizeof(kdp->d_off)) return retval; dp = (struct dirent *)buf; kdp = (struct kernel_dirent64 *)kbuf; while ((char *)kdp < kbuf + retval) { const size_t alignment = __alignof__(struct dirent); /* Since kdp->d_reclen is already aligned for the kernel structure this may compute a value that is bigger than necessary. */ size_t old_reclen = kdp->d_reclen; size_t new_reclen = ((old_reclen - size_diff + alignment - 1) & ~(alignment - 1)); uint64_t d_ino = kdp->d_ino; int64_t d_off = kdp->d_off; unsigned char d_type = kdp->d_type; dp->d_ino = d_ino; dp->d_off = d_off; if ((sizeof(dp->d_ino) != sizeof(kdp->d_ino)) || (sizeof(dp->d_off) != sizeof(kdp->d_off))) { /* Overflow. If there was at least one entry before this one, return them without error, otherwise signal overflow. */ if (last_offset != -1) { lseek64(fd, last_offset, SEEK_SET); return (char *)dp - buf; } errno = EOVERFLOW; return -1; } last_offset = d_off; dp->d_reclen = new_reclen; dp->d_type = d_type; memmove(dp->d_name, kdp->d_name, old_reclen - offsetof(struct kernel_dirent64, d_name)); dp = (struct dirent *)((char *)dp + new_reclen); kdp = (struct kernel_dirent64 *)((char *)kdp + old_reclen); } return (char *)dp - buf; } xfsdump-3.1.6+nmu1/common/inventory.h0000644000000000000000000001720312620476160014456 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef INVENTORY_H #define INVENTORY_H /* abstract interface to the inventory sub system of xfsdump * * the inventory contains a description of every xfsdump ever * done, unless explicitly deleted. It provides simple and specific * storage and query facilities. * * This was not an attempt to write a generic database. The inventory does have * knowledge of the functionalities, some abstractions, and even typical queries * of dump() and restore() and uses this knowledge in formulating its storage * structure on disk. All these things, of course, are completely abstract with * respect to the clients of the inventory. * */ #define INV_DIRPATH inv_dirpath() #define INV_TOKEN_NULL NULL #define INV_FSTAB inv_fstab() #define INV_INVINDEX_PREFIX ".InvIndex" #define INV_STOBJ_PREFIX ".StObj" #define INV_STRLEN 128 /* length of labels, mntpts, etc */ /*----------------------------------------------------------------------*/ /* */ /* */ /* Users are first supposed to call inventory_open() specifying what */ /* type of handle s/he would like to supply. This can be BY_MOUNTPT, */ /* BY_DEVPATH, or BY_UUID. The inventory maintains its own table of file*/ /* systems and their uuids, mountpts, and device paths. (XXX host). */ /* The current implementation requires that a uuid be present for all */ /* its fs table entries. However, once the entry is there, caller can */ /* query by any of the other handles. */ /* */ /* For a read-session, ie. just querying, like in restore(), the token */ /* from inventory_open() must always be passed. */ /* */ /* This inventory has a hierarchical token scheme. */ /* For write-sessions, the caller should obtain a session_token */ /* by calling inventory_session_open() with the original token. */ /* In order to start writing media files, the caller must */ /* then obtain a stream_token via inventory_stream_open() using that */ /* session_token. */ /* */ /* Once, done, stream_close(), session_close() and inventory_close() */ /* must be called in that order. */ /* */ /*----------------------------------------------------------------------*/ /* Caller can open the inventory by any of these handles */ typedef enum { INV_BY_UUID, INV_BY_MOUNTPT, INV_BY_DEVPATH } inv_predicate_t; typedef struct inv_stream { bool_t st_interrupted; /* was this stream interrupted ? */ /* duplicate info from mediafiles for speed */ xfs_ino_t st_startino; /* the starting pt */ off64_t st_startino_off; xfs_ino_t st_endino; /* where we actually ended up. this means we've written upto but not including this breakpoint. */ off64_t st_endino_off; int st_nmediafiles; /* number of mediafiles */ } inv_stream_t; /* * inventory_session_t * all the information that is kept on a single dump session of a single * file system in the inventory. * */ typedef struct inv_session { uuid_t s_fsid; /* file system */ uuid_t s_sesid; /* this dump session's id: 16 bytes*/ uint s_nstreams; /* number of media streams recorded */ inv_stream_t *s_streams; /* array of streams */ time32_t s_time; /* time of the dump */ u_char s_level; /* dump level */ char s_label[INV_STRLEN]; /* session label, assigned by the operator */ char s_mountpt[INV_STRLEN];/* path to the mount point */ char s_devpath[INV_STRLEN];/* path to the device */ } inv_session_t; /* Is there anything else that you need here, Chuck? */ typedef struct inv_mediafile { uuid_t m_moid; /* media object id */ xfs_ino_t m_startino; /* file that we started out with */ off64_t m_startino_off; xfs_ino_t m_endino; /* the dump file we ended this .. */ off64_t m_endino_off; /* .. media file with. */ char m_label[INV_STRLEN]; /* media file label */ } inv_mediafile_t; /* the list of inos returned by inv_get_inolist() */ typedef struct inolist { xfs_ino_t i_ino; struct inolist *i_next; /* NULL if last element */ } inv_inolist_t; struct invt_desc_entry; struct invt_sesdesc_entry; struct invt_strdesc_entry; /* The three kinds of access tokens for the inventory */ typedef struct invt_desc_entry *inv_idbtoken_t; typedef struct invt_sesdesc_entry *inv_sestoken_t; typedef struct invt_strdesc_entry *inv_stmtoken_t; /* inventory_open - initializes access to the inventory */ extern inv_idbtoken_t inv_open( inv_predicate_t bywhat, /* BY_UUID, BY_MOUNTPT, BY_DEVPATH */ void *pred );/* uuid_t *,char * mntpt, or char *dev */ extern bool_t inv_close( inv_idbtoken_t tok ); extern inv_sestoken_t inv_writesession_open( inv_idbtoken_t tok, /* token obtained by inventory_init() */ uuid_t *fsid, uuid_t *sesid, char *label, u_char level, uint nstreams, time32_t time, char *mntpt, char *devpath ); extern bool_t inv_writesession_close( inv_sestoken_t tok ); extern inv_stmtoken_t inv_stream_open( inv_sestoken_t tok ); extern bool_t inv_stream_close( inv_stmtoken_t tok, bool_t wasinterrupted ); extern bool_t inv_put_mediafile( inv_stmtoken_t tok, uuid_t *moid, char *label, xfs_ino_t startino, off64_t startino_offset, xfs_ino_t endino, off64_t endino_offset ); /* lasttime_level_lessthan - finds the time of the last dump of the * specified file system at a level less than the specified level. * if never dumped below the current level, *time is set to NULL. * */ extern bool_t inv_lasttime_level_lessthan( inv_idbtoken_t tok, u_char level, time32_t **time );/* out */ extern bool_t inv_lastsession_level_lessthan( inv_idbtoken_t tok, u_char level, inv_session_t **ses );/* out */ extern bool_t inv_lastsession_level_equalto( inv_idbtoken_t tok, u_char level, inv_session_t **ses );/* out */ extern bool_t inv_get_inolist( inv_inolist_t **inolist ); /* For dumping the inventory once a dump is done. */ extern bool_t inv_get_session( inv_sestoken_t tok, void **bufpp, /* out */ size_t *bufszp ); /* out */ /* To reconstruct a compelete inventory from dumped inventories */ extern bool_t inv_put_session( inv_idbtoken_t tok, void *bufp, size_t bufsz ); #ifdef DEBUG bool_t inv_DEBUG_printallsessions( inv_idbtoken_t tok, inv_session_t **ses ); #endif /* ifdef DEBUG */ extern int inv_setup_base( void ); extern char * inv_dirpath( void ); extern char * inv_fstab( void ); extern char * inv_lockfile( void ); #endif /* INVENTORY_H */ xfsdump-3.1.6+nmu1/common/drive.c0000644000000000000000000002510312620476160013523 0ustar /* * Copyright (c) 2000-2002 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include "config.h" #include "types.h" #include "mlog.h" #include "dlog.h" #include "path.h" #include "getopt.h" #include "global.h" #include "drive.h" /* drive.c - selects and initializes a drive strategy */ /* structure definitions used locally ****************************************/ /* declarations of externally defined global symbols *************************/ extern void usage( void ); extern char *homedir; /* declare all drive strategies here */ extern drive_strategy_t drive_strategy_simple; extern drive_strategy_t drive_strategy_scsitape; extern drive_strategy_t drive_strategy_rmt; /* forward declarations of locally defined static functions ******************/ static drive_t *drive_alloc( char *, size_t ); static void drive_allochdrs( drive_t *drivep, global_hdr_t *gwhdrtemplatep, ix_t driveix ); /* definition of locally defined global variables ****************************/ drive_t **drivepp; size_t drivecnt; size_t partialmax; /* definition of locally defined static variables *****************************/ /* drive strategy array - ordered by precedence */ static drive_strategy_t *strategypp[] = { &drive_strategy_simple, &drive_strategy_scsitape, &drive_strategy_rmt, }; /* definition of locally defined global functions ****************************/ /* drive_init1 - select and instantiate a drive manager for each drive * specified on the command line. */ bool_t drive_init1( int argc, char *argv[ ] ) { int c; ix_t driveix; /* sanity check asserts */ assert( sizeof( drive_hdr_t ) == DRIVE_HDR_SZ ); /* count drive arguments */ optind = 1; opterr = 0; drivecnt = 0; while ( ( c = getopt( argc, argv, GETOPT_CMDSTRING )) != EOF ) { switch ( c ) { case GETOPT_DUMPDEST: drivecnt++; break; } } /* allocate an array to hold ptrs to drive descriptors */ if (drivecnt > 0) { drivepp = ( drive_t ** )calloc( drivecnt, sizeof( drive_t * )); assert( drivepp ); } /* initialize the partialmax value. Each drive can be completing a file * started in another drive (except for drive 0) and leave one file to * be completed by another drive. This value is used to limit the * search in the list of partially completed files shared between all * restore streams. Note, if drivecnt is one, then partialmax is zero * to indicate no partial files can span streams. */ partialmax = (drivecnt <= 1 ? 0 : (drivecnt * 2) - 1); /* initialize drive descriptors from command line arguments */ optind = 1; opterr = 0; driveix = 0; while ( ( c = getopt( argc, argv, GETOPT_CMDSTRING )) != EOF ) { switch ( c ) { case GETOPT_DUMPDEST: if ( ! optarg || optarg[ 0 ] == '-' ) { mlog( MLOG_NORMAL, _("-%c argument missing\n"), c ); usage( ); return BOOL_FALSE; } /* allocate a drive descriptor */ drivepp[ driveix ] = drive_alloc( optarg, driveix ); driveix++; break; } } assert( driveix == drivecnt ); /* the user may specify stdin as the source, by * a single dash ('-') with no option letter. This must appear * between all lettered arguments and the file system pathname. */ if ( optind < argc && ! strcmp( argv[ optind ], "-" )) { if ( driveix > 0 ) { mlog( MLOG_NORMAL, #ifdef DUMP _("cannot specify source files and stdout together\n") #endif /* DUMP */ #ifdef RESTORE _("cannot specify source files and stdin together\n") #endif /* RESTORE */ ); usage( ); return BOOL_FALSE; } drivecnt = 1; /* Adding this alloc to fix malloc corruption. * Bug #393618 - prasadb 04/16/97 * allocate an array to hold ptrs to drive descriptors */ drivepp = ( drive_t ** )calloc( drivecnt, sizeof( drive_t * )); assert( drivepp ); drivepp[ 0 ] = drive_alloc( "stdio", 0 ); #ifdef DUMP /* ifdef added around dlog_desist() by prasadb to fix 435626 */ dlog_desist( ); #endif } /* verify that some dump destination(s) / restore source(s) specified */ if ( drivecnt == 0 ) { mlog( MLOG_NORMAL | MLOG_ERROR, #ifdef DUMP _("no destination file(s) specified\n") #endif /* DUMP */ #ifdef RESTORE _("no source file(s) specified\n") #endif /* RESTORE */ ); usage( ); return BOOL_FALSE; } /* run each drive past each strategy, pick the best match * and instantiate a drive manager. */ for ( driveix = 0 ; driveix < drivecnt ; driveix++ ) { drive_t *drivep = drivepp[ driveix ]; int bestscore = 0 - INTGENMAX; ix_t six; ix_t scnt = sizeof( strategypp ) / sizeof( strategypp[ 0 ] ); drive_strategy_t *bestsp = 0; bool_t ok; for ( six = 0 ; six < scnt ; six++ ) { drive_strategy_t *sp = strategypp[ six ]; int score; score = ( * sp->ds_match )( argc, argv, drivep ); if ( ! bestsp || score > bestscore ) { bestsp = sp; bestscore = score; } } assert( bestsp ); drivep->d_strategyp = bestsp; drivep->d_recmarksep = bestsp->ds_recmarksep; drivep->d_recmfilesz = bestsp->ds_recmfilesz; mlog( MLOG_VERBOSE, _("using %s strategy\n"), bestsp->ds_description ); ok = ( * bestsp->ds_instantiate )( argc, argv, drivep ); if ( ! ok ) { return BOOL_FALSE; } } return BOOL_TRUE; } /* drive_init2 - second phase strategy initialization. * allocates global read and write hdrs, copying global hdr template * into the write hdrs (DUMP only). kicks off async init for each drive, * which will be synchronized with drive_init3. */ /* ARGSUSED */ bool_t drive_init2( int argc, char *argv[ ], global_hdr_t *gwhdrtemplatep ) { ix_t driveix; for ( driveix = 0 ; driveix < drivecnt ; driveix++ ) { drive_t *drivep = drivepp[ driveix ]; bool_t ok; drive_allochdrs( drivep, gwhdrtemplatep, driveix ); ok = ( * drivep->d_opsp->do_init )( drivep ); if ( ! ok ) { return BOOL_FALSE; } } return BOOL_TRUE; } /* drive_init3 - third phase strategy initialization. * synchronizes with async operations begun by drive_init2. */ bool_t drive_init3( void ) { ix_t driveix; for ( driveix = 0 ; driveix < drivecnt ; driveix++ ) { drive_t *drivep = drivepp[ driveix ]; bool_t ok; ok = ( * drivep->d_opsp->do_sync )( drivep ); if ( ! ok ) { return BOOL_FALSE; } } return BOOL_TRUE; } /* drive_mark_commit - commits and unlinks all accumulated marks with * offsets less than or equal to the offset of the next (as yet unwritten) * byte in the media file. * utility function for use by drive-specific strategies. */ void drive_mark_commit( drive_t *drivep, off64_t ncommitted ) { drive_markrec_t *dmp; for ( dmp = drivep->d_markrecheadp ; dmp && dmp->dm_log <= ( drive_mark_t )ncommitted ; ) { drivep->d_markrecheadp = dmp->dm_nextp; ( * dmp->dm_cbfuncp )( dmp->dm_cbcontextp, dmp, BOOL_TRUE ); dmp = drivep->d_markrecheadp; } } /* drive_mark_discard - unlinks all accumulated marks, calling their callbacks * indicating the mark was NOT committed. * utility function for use by drive-specific strategies. */ void drive_mark_discard( drive_t *drivep ) { drive_markrec_t *dmp; for ( dmp = drivep->d_markrecheadp ; dmp ; drivep->d_markrecheadp = dmp->dm_nextp, dmp = dmp->dm_nextp ) { ( * dmp->dm_cbfuncp )( dmp->dm_cbcontextp, dmp, BOOL_FALSE ); } } /* drive_display_metrics - called by main thread during interactive dialog * to print drive throughput and streaming metrics. */ void drive_display_metrics( void ) { ix_t driveix; for ( driveix = 0 ; driveix < drivecnt ; driveix++ ) { drive_t *drivep = drivepp[ driveix ]; drive_ops_t *dop = drivep->d_opsp; if ( dop->do_display_metrics ) { ( * dop->do_display_metrics )( drivep ); } } } /* definition of locally defined static functions ****************************/ /* drive_alloc - allocate and initialize the generic portions of a drive * descriptor. do NOT allocate hdr buffers. */ static drive_t * drive_alloc( char *pathname, ix_t driveix ) { drive_t *drivep; struct stat64 statbuf; /* allocate the descriptor */ drivep = ( drive_t * )calloc( 1, sizeof( drive_t )); assert( drivep ); /* convert the pathname to an absolute pathname * NOTE: string "stdio" is reserved to mean send to standard out */ if ( strcmp( pathname, "stdio" )) { pathname = path_reltoabs( pathname, homedir ); } /* set pipe flags */ if ( ! strcmp( pathname, "stdio" )) { drivep->d_isunnamedpipepr = BOOL_TRUE; } else if ( ! stat64( pathname, &statbuf ) && ( statbuf.st_mode & S_IFMT ) == S_IFIFO ) { drivep->d_isnamedpipepr = BOOL_TRUE; } /* complete the drive manager */ drivep->d_pathname = pathname; drivep->d_index = driveix; return drivep; } /* drive_allochdrs - allocate and initialize the drive read and write * hdrs, and ptrs into the hdrs. */ static void drive_allochdrs( drive_t *drivep, global_hdr_t *gwhdrtemplatep, ix_t driveix ) { global_hdr_t *grhdrp; drive_hdr_t *drhdrp; global_hdr_t *gwhdrp; drive_hdr_t *dwhdrp; /* allocate the read header */ grhdrp = ( global_hdr_t * )calloc( 1, sizeof( global_hdr_t )); assert( grhdrp ); gwhdrp = NULL; dwhdrp = NULL; /* calculate pointer to the drive portion of the read header */ drhdrp = ( drive_hdr_t * )grhdrp->gh_upper; /* global write hdr used only for dumps. will be NULL for restore */ if ( gwhdrtemplatep ) { /* allocate the write header */ gwhdrp = ( global_hdr_t * )calloc( 1, sizeof( global_hdr_t )); assert( gwhdrp ); /* copy the template */ *gwhdrp = *gwhdrtemplatep; /* calculate pointer to the drive portion of the read header */ dwhdrp = ( drive_hdr_t * )gwhdrp->gh_upper; /* fill in generic drive fields of write hdr */ dwhdrp->dh_strategyid = drivep->d_strategyp->ds_id; dwhdrp->dh_driveix = driveix; dwhdrp->dh_drivecnt = drivecnt; } /* complete the drive manager */ drivep->d_greadhdrp = grhdrp; drivep->d_readhdrp = drhdrp; drivep->d_gwritehdrp = gwhdrp; drivep->d_writehdrp = dwhdrp; } xfsdump-3.1.6+nmu1/common/timeutil.c0000644000000000000000000000222712607344125014250 0ustar /* * Copyright (c) 2009 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include "types.h" #include "timeutil.h" char * ctime32(const time32_t *timep) { time_t t = (time_t) *timep; return ctime(&t); } char * ctime32_r(const time32_t *timep, char *buf) { time_t t = (time_t) *timep; return ctime_r(&t, buf); } char * ctimennl( const time32_t *clockp ) { char *p = ctime32( clockp ); if ( p && strlen( p ) > 0 ) { p[ strlen( p ) - 1 ] = 0; } return p; } xfsdump-3.1.6+nmu1/common/global.h0000644000000000000000000000653612620476160013670 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GLOBAL_H #define GLOBAL_H /* global_hdr_t - first page of every media file */ #define GLOBAL_HDR_SZ PGSZ #define GLOBAL_HDR_MAGIC "xFSdump0" #define GLOBAL_HDR_MAGIC_SZ 8 #define GLOBAL_HDR_VERSION_0 0 #define GLOBAL_HDR_VERSION_1 1 #define GLOBAL_HDR_VERSION_2 2 #define GLOBAL_HDR_VERSION_3 3 /* version 3 uses the full 32-bit inode generation number in direnthdr_t. * version 2 adds encoding of holes and a change to on-tape inventory format. * version 1 adds extended file attribute dumping. * version 0 xfsrestore can't handle media produced * by version 1 xfsdump. */ #define GLOBAL_HDR_VERSION GLOBAL_HDR_VERSION_3 #define GLOBAL_HDR_STRING_SZ 0x100 #define GLOBAL_HDR_TIME_SZ 4 #define GLOBAL_HDR_UUID_SZ 0x10 struct global_hdr { char gh_magic[ GLOBAL_HDR_MAGIC_SZ ]; /* 8 8 */ /* unique signature of xfsdump */ uint32_t gh_version; /* 4 c */ /* header version */ uint32_t gh_checksum; /* 4 10 */ /* 32-bit unsigned additive inverse of entire header */ time32_t gh_timestamp; /* 4 14 */ /* time32_t of dump */ char gh_pad1[ 4 ]; /* 4 18 */ /* alignment */ uint64_t gh_ipaddr; /* 8 20 */ /* from gethostid(2), room for expansion */ uuid_t gh_dumpid; /* 10 30 */ /* ID of dump session */ char gh_pad2[ 0xd0 ]; /* d0 100 */ /* alignment */ char gh_hostname[ GLOBAL_HDR_STRING_SZ ]; /* 100 200 */ /* from gethostname(2) */ char gh_dumplabel[ GLOBAL_HDR_STRING_SZ ]; /* 100 300 */ /* label of dump session */ char gh_pad3[ 0x100 ]; /* 100 400 */ /* padding */ char gh_upper[ GLOBAL_HDR_SZ - 0x400 ]; /* c00 1000 */ /* header info private to upper software layers */ }; typedef struct global_hdr global_hdr_t; /* used by main( ) to allocate and populate a global header template. * drive managers will copy this into the write header. */ extern global_hdr_t * global_hdr_alloc( int argc, char *argv[ ] ); /* used by main( ) to free the global header template after drive ini. */ extern void global_hdr_free( global_hdr_t *ghdrp ); /* global_hdr_checksum_set - fill in the global media file header checksum. * utility function for use by drive-specific strategies. */ extern void global_hdr_checksum_set( global_hdr_t *hdrp ); /* global_hdr_checksum_check - check the global media file header checksum. * utility function for use by drive-specific strategies. * returns BOOL_TRUE if ok, BOOL_FALSE if bad */ extern bool_t global_hdr_checksum_check( global_hdr_t *hdrp ); /* global_version_check - if we know this version number, return BOOL_TRUE * else return BOOL_FALSE */ extern bool_t global_version_check( uint32_t version ); #endif /* GLOBAL_H */ xfsdump-3.1.6+nmu1/common/hsmapi.c0000644000000000000000000006355712620476160013712 0ustar /* * Copyright (c) 2000-2004 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "types.h" #include "hsmapi.h" #include "mlog.h" /* This version of the HSM API supports the DMF attribute used in the initial * DMF release, as well as the attribute used in the pseudo multiple managed * region DMF release. */ /* DMF attribute name, size, and format as stored within XFS. (Stolen directly from "dmfsapi/dmf_dmattr.H". */ #define DMF_ATTR_NAME "SGI_DMI_DMFATTR" /* name of DMF's attr */ typedef struct { u_char fsys; /* filesystem type */ u_char version; /* attribute format version */ u_char state[2]; /* dm_state in MSB form */ u_char flags[2]; /* dm_flags in MSB form */ u_char bfid[16]; /* Bitfile ID in MSB form */ } XFSattrvalue0_t; typedef struct { u_char rg_offset[8]; /* region offset in MSB form */ u_char rg_size[8]; /* region length in MSB form */ u_char rg_state[2]; /* region dm_state in MSB form */ u_char rg_flags; /* managed region event bits */ u_char rg_fbits; /* region flag bits */ } XFSattrregion_t; typedef struct { u_char fsys; /* filesystem type */ u_char version; /* attribute format version */ u_char state[2]; /* global dm_state in MSB form */ u_char flags[2]; /* global dm_flags in MSB form */ u_char bfid[16]; /* Bitfile ID in MSB form. */ u_char sitetag[4]; /* site tag */ u_char regcnt[2]; /* number of regions in MSB form */ } XFSattrvalue1_t; #define MIN_FORMAT1_ATTR_LEN ( sizeof(XFSattrvalue1_t) + \ sizeof(XFSattrregion_t) ) /* supported fsys values */ /* XFS DMAPI (w/o MMR ) */ #define FSYS_TYPE_XFS 1 /* supported version values */ /* original DMF attr format */ #define DMF_ATTR_FORMAT_0 0 /* DMF attr with multiple regions (real or pseudo) or with a non-zero * site tag. attrs of this format consist of a XFSattrvalue1_t struct * followed by 1 or more XFSattrregion_t structs */ #define DMF_ATTR_FORMAT_1 1 /* Interesting state field values */ #define DMF_ST_DUALSTATE 2 /* file has backups plus online data */ #define DMF_ST_OFFLINE 3 /* file has backups, no online data */ #define DMF_ST_UNMIGRATING 4 /* file data is being staged in */ #define DMF_ST_NOMIGR 5 /* file should not be migrated */ #define DMF_ST_PARTIAL 6 /* file has backups plus parts online */ /* DM_EVENT_* are defined in . Trying to avoid a dmapi dependency * in xfsdump since dmapi is not commonly used, yet this code needs to know some * of the event bits. */ #define DM_EVENT_READ 16 #define DM_EVENT_WRITE 17 #define DM_EVENT_TRUNCATE 18 #define DM_EVENT_DESTROY 20 /* Interesting bit combinations within the bs_dmevmask field of xfs_bstat_t: * OFL, UNM, and PAR files have exactly these bits set. * DUL and MIG files have all but the DM_EVENT_READ bit set */ #define DMF_EV_BITS ( (1<= 0; i--) { dest[i] = (u_char)(src & 0xff); src >>= 8; } } /****************************************************************************** * Name * msb_load - load a variable from a u_char array in MSB format * * Returns * value ******************************************************************************/ static inline uint64_t msb_load( u_char *src, int length) { uint64_t tmp = 0; int i; for (i = 0; i < length; i++) { tmp = (tmp << 8) | src[i]; } return tmp; } /****************************************************************************** * Name * HsmInitFsysContext - allocate and initialize an HSM filesystem context * * Description * HsmInitFsysContext allocates and initializes an HSM filesystem * context to hold all filesystem information that might later be needed * by other HSM routines. The context is read-only, and can be shared * by multiple xfsdump dump streams. It should eventually be freed by * calling HsmDeleteFsysContext(). The caller must provide the mount * point of the filesystem to be dumped and the HSM API version that * xfsdump was compiled with. * * Note: The restore routines do not require an HSM filesystem context. * * Returns * != NULL, then a pointer to the filesystem context that was allocated. * == NULL, either the HSM libary is not compatible with xfsdump, or * the filesystem is not under HSM management. ******************************************************************************/ extern hsm_fs_ctxt_t * HsmInitFsysContext( const char *mountpoint, int dumpversion) { dmf_fs_ctxt_t *dmf_fs_ctxtp; if (dumpversion != HSM_API_VERSION_1) { return NULL; /* we can't handle this version */ } /* Malloc space for a filesystem context, and initialize any fields needed later by other routines. */ if ((dmf_fs_ctxtp = malloc(sizeof(dmf_fs_ctxt_t))) == NULL) { return NULL; } dmf_fs_ctxtp->dumpversion = dumpversion; /* Get the filesystem's handle for later use in building file handles in HsmInitFileContext. */ dmf_fs_ctxtp->fshanp = jdm_getfshandle((char *)mountpoint); if (dmf_fs_ctxtp->fshanp == NULL) { free(dmf_fs_ctxtp); return NULL; } return (hsm_fs_ctxt_t *)dmf_fs_ctxtp; } /****************************************************************************** * Name * HsmDeleteFsysContext - delete an HSM filesystem context * * Description * HsmDeleteFsysContext releases all storage previously allocated to a * HSM filesystem context via HsmInitFsysContext. * * Returns * None. ******************************************************************************/ extern void HsmDeleteFsysContext( hsm_fs_ctxt_t *contextp) { free(contextp); } /****************************************************************************** * Name * HsmEstimateFileSpace - return estimated offline file size * * Description * HsmEstimateFileSpace is called from within estimate_dump_space() only * if -a is selected. It estimates the number of bytes needed to dump * the file assuming that all dual-residency data will be dumped as holes. * * Returns * != 0, then *bytes contains the estimated size of the file in bytes. * == 0, then no estimate made. Caller should use his default estimator. ******************************************************************************/ extern int HsmEstimateFileSpace( hsm_fs_ctxt_t *fscontextp, hsm_f_ctxt_t *fcontextp, const xfs_bstat_t *statp, off64_t *bytes, int accurate) { /* If the estimate needs to be accurate, then we'll have to * pay the price and read the DMF attribute, if there is one, * to determine exactly what DMF state the file is in. Otherwise, * make a guess based on information in the bstat. If a * hsm_f_ctxt_t was provided, an accurate estimate is free. */ if (fcontextp) { dmf_f_ctxt_t *dmf_f_ctxt = (dmf_f_ctxt_t *)fcontextp; if (dmf_f_ctxt->candidate) { *bytes = 0; /* treat the entire file as offline */ return 1; } else { return 0; } } else if (accurate) { dmf_fs_ctxt_t *dmf_fs_ctxtp = (dmf_fs_ctxt_t *)fscontextp; dmf_f_ctxt_t dmf_f_ctxt; /* This is an implicit HsmAllocateFileContext call. */ dmf_f_ctxt.fsys = *dmf_fs_ctxtp; dmf_f_ctxt.candidate = 0; /* Initialize the file context to determine the file's state. */ if (HsmInitFileContext((hsm_f_ctxt_t *)&dmf_f_ctxt, statp)) { return 0; } /* If the file is dualstate, make it appear offline. */ if (dmf_f_ctxt.candidate) { *bytes = 0; /* treat the entire file as offline */ return 1; } else { return 0; } } else { /* This code is assuming that there are no MIG files, and so any file with DMAPI event bits set will be dumped as OFL. The non-dir dump size estimation will be somewhat low if there are MIG files. */ if ((statp->bs_mode & S_IFMT) != S_IFREG) { return 0; /* not a regular file */ } if ((statp->bs_xflags & XFS_XFLAG_HASATTR) == 0) { return 0; /* no DMF attribute can possibly exist */ } if ((statp->bs_dmevmask & DMF_EV_BITS) == 0) { return 0; } *bytes = 0; return 1; } } /****************************************************************************** * Name * HsmEstimateFileOffset - return estimated file offset * * Description * HsmEstimateFileOffset is called from within quantity2offset() only * if -a is selected. It estimates the offset within the file that has * 'bytecount' bytes of physical data preceding it assuming that all * dual-residency data in the file will be dumped as holes. * * Returns * != 0, then *byteoffset contains the estimated offset within the file. * == 0, then no estimate made. Caller should use his default estimator. ******************************************************************************/ /* ARGSUSED */ extern int HsmEstimateFileOffset( hsm_fs_ctxt_t *contextp, const xfs_bstat_t *statp, off64_t bytecount, off64_t *byteoffset) { dmf_fs_ctxt_t *dmf_fs_ctxtp = (dmf_fs_ctxt_t *)contextp; dmf_f_ctxt_t dmf_f_ctxt; /* This is an implicit HsmAllocateFileContext call. */ dmf_f_ctxt.fsys = *dmf_fs_ctxtp; dmf_f_ctxt.candidate = 0; /* Initialize the file context to determine the file's state. */ if (HsmInitFileContext((hsm_f_ctxt_t *)&dmf_f_ctxt, statp)) { return 0; } /* If the file is dualstate, make it appear offline. */ if (dmf_f_ctxt.candidate) { *byteoffset = statp->bs_size; return 1; } else { return 0; } } /****************************************************************************** * Name * HsmAllocateFileContext - allocate an HSM file context * * Description * HsmAllocateFileContext mallocs the maximum-sized file context that * might later needed by HsmInitFileContext(). The context is * read-write. Each xfsdump stream must have its own file context. This * context should eventually be freed by calling HsmDeleteFileContext(). * The caller must provide the HSM filesystem context for the filesystem * being dumped. * * Note: The restore routines do not require an HSM file context. * * Returns * != NULL, then a pointer to the file context that was allocated. ******************************************************************************/ extern hsm_f_ctxt_t * HsmAllocateFileContext( hsm_fs_ctxt_t *contextp) { dmf_f_ctxt_t *dmf_f_ctxtp; if ((dmf_f_ctxtp = malloc(sizeof(dmf_f_ctxt_t))) == NULL) { return NULL; } /* Save the filesystem information in the file context. */ dmf_f_ctxtp->fsys = *(dmf_fs_ctxt_t *)contextp; dmf_f_ctxtp->candidate = 0; return (hsm_f_ctxt_t *)dmf_f_ctxtp; } /****************************************************************************** * Name * HsmDeleteFileContext - delete a previously created HSM file context * * Description * HsmDeleteFileContext releases all storage previously allocated to a * HSM file context via HsmAllocateFileContext. * * Returns * None. ******************************************************************************/ extern void HsmDeleteFileContext( hsm_f_ctxt_t *contextp) { free(contextp); } /****************************************************************************** * Name * HsmInitFileContext - initialize the HSM context for a particular file * * Description * HsmInitFileContext initializes an existing HSM file context for * subsequent operations on a particular regular file. Other HSM routines * use the context to access information collected by HsmInitFileContext * about the file rather than having to recollect the file's information * on each call. * * Returns * == 0, context was created. * != 0, if something is wrong with the file and it should not be dumped. ******************************************************************************/ extern int HsmInitFileContext( hsm_f_ctxt_t *contextp, const xfs_bstat_t *statp) { dmf_f_ctxt_t *dmf_f_ctxtp = (dmf_f_ctxt_t *)contextp; XFSattrvalue0_t *dmfattrp; int state; int error; attr_multiop_t attr_op; dmf_f_ctxtp->candidate = 0; /* assume file will NOT be of interest */ /* Try and rule out a dualstate inode by doing some quick tests. */ if ((statp->bs_mode & S_IFMT) != S_IFREG) { return 0; /* not a regular file */ } if ((statp->bs_xflags & XFS_XFLAG_HASATTR) == 0) { return 0; /* no DMF attribute exists */ } if ((statp->bs_dmevmask & DMF_EV_BITS) == 0 ) { return 0; /* no interesting DMAPI bits set */ } /* We have a likely candidate, so we have to pay the price and look for the DMF attribute. (It could be in a disk block separate from the inode.) */ attr_op.am_opcode = ATTR_OP_GET; attr_op.am_error = 0; attr_op.am_attrname = DMF_ATTR_NAME; attr_op.am_attrvalue = dmf_f_ctxtp->attrval; attr_op.am_length = sizeof(dmf_f_ctxtp->attrval); attr_op.am_flags = ATTR_ROOT; error = jdm_attr_multi(dmf_f_ctxtp->fsys.fshanp, (xfs_bstat_t *)statp, (char *)&attr_op, 1, 0); if (error || attr_op.am_error) return 0; /* no DMF attribute */ dmf_f_ctxtp->attrlen = attr_op.am_length; dmfattrp = (XFSattrvalue0_t *)dmf_f_ctxtp->attrval; if (dmfattrp->fsys != FSYS_TYPE_XFS) return 0; /* unsupported filesystem version */ switch(dmfattrp->version) { case DMF_ATTR_FORMAT_0: if (dmf_f_ctxtp->attrlen != sizeof(XFSattrvalue0_t)) return 0; /* wrong size */ break; case DMF_ATTR_FORMAT_1: if (dmf_f_ctxtp->attrlen < MIN_FORMAT1_ATTR_LEN) return 0; /* wrong size */ break; default: return 0; /* unsupported attr version */ } state = (int)msb_load(dmfattrp->state, sizeof(dmfattrp->state)); switch (state) { case DMF_ST_DUALSTATE: case DMF_ST_UNMIGRATING: case DMF_ST_PARTIAL: case DMF_ST_OFFLINE: /* We have a DMF file that can be treated as offline */ dmf_f_ctxtp->candidate = 1; dmf_f_ctxtp->filesize = statp->bs_size; break; default: break; } return 0; } /****************************************************************************** * Name * HsmModifyInode - modify a xfs_bstat_t to make a file appear offline * * Description * HsmModifyInode uses the context provided by a previous * HsmInitFileContext call to determine how to modify a xfs_bstat_t * structure to make a dual-residency HSM file appear to be offline. * * Returns * != 0, xfs_bstat_t structure was modified. * == 0, if something is wrong with the file and it should not be dumped. ******************************************************************************/ extern int HsmModifyInode( hsm_f_ctxt_t *contextp, xfs_bstat_t *statp) { dmf_f_ctxt_t *dmf_f_ctxtp = (dmf_f_ctxt_t *)contextp; if (dmf_f_ctxtp->candidate) { statp->bs_dmevmask = DMF_EV_BITS; } return 1; } /****************************************************************************** * Name * HsmModifyExtentMap - modify getbmapx array to make file appear offline * * Description * HsmModifyExtentMap uses the context provided by a previous * HsmInitFileContext call to determine how to modify a contiguous array * of getbmapx structures to make a dual-residency HSM file appear to * be offline. * * Returns * != 0, getbmapx array was successfully modified. * == 0, if something is wrong with the file and it should not be dumped. ******************************************************************************/ extern int HsmModifyExtentMap( hsm_f_ctxt_t *contextp, struct getbmapx *bmap) { dmf_f_ctxt_t *dmf_f_ctxtp = (dmf_f_ctxt_t *)contextp; __int64_t length; if (bmap[0].bmv_entries <= 0) { return 1; /* caller must already be at EOF */ } if (!dmf_f_ctxtp->candidate) { return 1; /* not a dualstate file; dump as normal */ } /* We are dumping a dualstate file. Make it look like there is only one getbmapx extent and that it contains a hole which extends from the current offset to the end of the file. The bmap[1].bmv_offset should already be correct. */ length = BTOBB(dmf_f_ctxtp->filesize) - bmap[1].bmv_offset; if (length > 0) { bmap[0].bmv_entries = 1; /* rest of file is one extent */ bmap[1].bmv_block = -1; /* convert to a hole */ bmap[1].bmv_length = length; } else { bmap[0].bmv_entries = 0; /* indicate at EOF */ } return 1; } /****************************************************************************** * Name * HsmFilterExistingAttribute - filter out unwanted extended attributes * * Description * HsmFilterExistingAttribute uses the context provided by a previous * HsmInitFileContext call to determine whether or not the extended * attribute with name 'namep' should be included in a file's dump image. * (An extended attribute can be modified within the dump by filtering * it out with this routine, then adding the new version of the attribute * back with HsmAddNewAttribute.) * * Note: this routine must be idempotent. It is possible that xfsdump * will call this routine a second time for the same attribute if after * the first call it discovers that there isn't room in its buffer to * hold the attribute value. * * Returns * != 0, the attribute was successfully examined. If '*skip_entry' is * non-zero, xfsdump will not add this attribute to the dump. * == 0, if something is wrong with the file and it should not be dumped. ******************************************************************************/ extern int HsmFilterExistingAttribute( hsm_f_ctxt_t *hsm_f_ctxtp, const char *namep, /* attribute name */ uint32_t valuesz, /* value size */ int flag, int *skip_entry) { dmf_f_ctxt_t *dmf_f_ctxtp = (dmf_f_ctxt_t *)hsm_f_ctxtp; *skip_entry = 0; /* assume we will not remove this attribute */ if (!dmf_f_ctxtp->candidate) { return 1; /* not a dualstate file */ } if (flag != ATTR_ROOT) { return 1; /* not a root attribute */ } if (strcmp(namep, DMF_ATTR_NAME)) { return 1; /* not the right attribute */ } if (valuesz < sizeof(XFSattrvalue0_t)) { return 0; /* attribute is corrupt */ } /* Remove the existing DMF attribute, as we will later replace it with our own version. */ *skip_entry = 1; return 1; } /****************************************************************************** * Name * HsmAddNewAttribute - add zero or more HSM attributes to a file's dump * * Description * HsmAddNewAttribute uses the context provided by a previous * HsmInitFileContext call to determine whether or not additional HSM * extended attributes need to be added to a file's dump image. On the * first call for a file, 'cursor' will be zero. xfsdump will increment * 'cursor' by one each time it asks for a new attribute. When no more * attributes are to be added, '*namepp' should be set to NULL. * * Note: this routine must be idempotent. It is possible that xfsdump * will call this routine a second time using the same cursor value if * it discovers that there isn't room in its buffer to hold the attribute * value it was given in the first call. * * Returns * != 0, call was successful. If '*namepp' is non-NULL, then it is the * name of an attribute to be added to the file's dump. '*valuep' * points the the value of the attribute, and '*valueszp' is the * value's size. If '*namep* is NULL, then there are no more * attributes to be added. * == 0, if something is wrong with the file and it should not be dumped. ******************************************************************************/ extern int HsmAddNewAttribute( hsm_f_ctxt_t *hsm_f_ctxtp, int cursor, int flag, char **namepp, /* pointer to new attribute name */ char **valuepp, /* pointer to its value */ uint32_t *valueszp) /* pointer to the value size */ { dmf_f_ctxt_t *dmf_f_ctxtp = (dmf_f_ctxt_t *)hsm_f_ctxtp; XFSattrvalue1_t *dmfattr1p = (XFSattrvalue1_t *)dmf_f_ctxtp->attrval; *namepp = NULL; /* assume we won't add an attribute */ if (!dmf_f_ctxtp->candidate) { return 1; /* not a dualstate file */ } if (flag != ATTR_ROOT) { return 1; /* not in the root attribute section */ } if (cursor > 0) { return 1; /* there is only one attribute to add */ } /* DMF writes format0 (XFSattrvalue0_t) attributes unless: * - the file has multiple regions * - the file has a non-zero site tag * * Here we are writing a single region (OFL), so we only dump a * format1 attribute if the file has a non-zero site tag. */ if (dmfattr1p->version == DMF_ATTR_FORMAT_1 && msb_load(dmfattr1p->sitetag, sizeof(dmfattr1p->sitetag)) != 0) { XFSattrregion_t *reg; reg = (XFSattrregion_t *)( dmf_f_ctxtp->attrval + sizeof(XFSattrvalue1_t) ); dmf_f_ctxtp->attrlen = MIN_FORMAT1_ATTR_LEN; /* make one offline region the size of the whole file */ msb_store(dmfattr1p->regcnt, 1, sizeof(dmfattr1p->regcnt)); msb_store(reg->rg_offset, 0, sizeof(reg->rg_offset)); msb_store(reg->rg_size, dmf_f_ctxtp->filesize, sizeof(reg->rg_size)); msb_store(reg->rg_state, DMF_ST_OFFLINE, sizeof(reg->rg_state)); reg->rg_flags = DMF_MR_FLAGS; reg->rg_fbits = 0; } else { /* writing a format0 attr. ensure correct length and version */ dmfattr1p->version = DMF_ATTR_FORMAT_0; dmf_f_ctxtp->attrlen = sizeof(XFSattrvalue0_t); } /* set the global state to offline */ msb_store(dmfattr1p->state, DMF_ST_OFFLINE, sizeof(dmfattr1p->state)); *valuepp = (char *)dmfattr1p; *namepp = DMF_ATTR_NAME; *valueszp = dmf_f_ctxtp->attrlen; return 1; } /****************************************************************************** * Name * HsmBeginRestoreFile * * Description * HsmBeginRestoreFile is called after a file is created but before any * data has been restored to it. The hsm_flagp param can be used to * keep track of limited state between calls to the HSM restore routines. * * Note that this does not require a filesystem or file context like the * HSM calls for xfsdump. This is currently a crude interface to satisfy * a specific need. It can be generalized at a later time, if necessary. * * Returns * None. ******************************************************************************/ extern void HsmBeginRestoreFile( bstat_t *bstatp, int fd, int *hsm_flagp) { int rv; XFSattrvalue0_t dmattr; /* If it appears to be a DMF-managed file, set the NOMIGR attribute * on it to prevent DMF from touching the file while we are restoring * it. If it turns out to not be a DMF-managed file, we'll need to * remove the attribute when the file is completed. */ *hsm_flagp = 0; if ( bstatp->bs_dmevmask && bstatp->bs_xflags & XFS_XFLAG_HASATTR ) { memset(&dmattr, 0, sizeof(XFSattrvalue0_t)); dmattr.fsys = FSYS_TYPE_XFS; msb_store(dmattr.state, DMF_ST_NOMIGR, sizeof(dmattr.state)); rv = attr_setf(fd, DMF_ATTR_NAME, (char *)&dmattr, sizeof(dmattr), ATTR_ROOT); if (rv == 0) *hsm_flagp = 1; } } /****************************************************************************** * Name * HsmRestoreAttribute * * Description ** HsmRestoreAttribute is called when restoring an extended attribute. * The hsm_flagp param can be used to keep track of limited state * between calls to the HSM restore routines. * * Note that this does not require a filesystem or file context like the * HSM calls for xfsdump. This is currently a crude interface to satisfy * a specific need. It can be generalized at a later time, if necessary. * * Returns * None. ******************************************************************************/ extern void HsmRestoreAttribute( int flag, /* ext attr flags */ char *namep, /* pointer to new attribute name */ int *hsm_flagp) { /* If the DMF attribute is being restored, then we will not * have to remove the NOMIGR attribute when this file is * being completed. */ if (flag & ATTR_ROOT && !strcmp(namep, DMF_ATTR_NAME)) *hsm_flagp = 0; } /****************************************************************************** * Name * HsmEndRestoreFile * * Description * HsmEndRestoreFile is called when all data and extended attributes * have been restored. The hsm_flagsp param can be used to keep track * of limited state between calls to the HSM restore routines. * * Note that this does not require a filesystem or file context like the * HSM calls for xfsdump. This is currently a crude interface to satisfy * a specific need. It can be generalized at a later time, if necessary. * * Returns * None. ******************************************************************************/ extern void HsmEndRestoreFile( char *path, int fd, int *hsm_flagp) { /* We put a NOMIGR on the file because we thought it was a * DMF-managed file. If it was not, then we need to take * that attribute off now. */ if (*hsm_flagp) { int rv; rv = attr_removef( fd, DMF_ATTR_NAME , ATTR_ROOT ); if (rv) { mlog(MLOG_NORMAL | MLOG_WARNING, _("error removing temp DMF attr on %s: %s\n"), path, strerror(errno)); } } } xfsdump-3.1.6+nmu1/common/openutil.c0000644000000000000000000000620412620476160014252 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include "config.h" #include "types.h" #include "mlog.h" char * open_pathalloc( char *dirname, char *basename, pid_t pid ) { size_t dirlen; size_t pidlen; size_t namelen; char *namebuf; if ( strcmp( dirname, "/" )) { dirlen = strlen( dirname ); } else { dirlen = 0; dirname = ""; } /* * We could calculate the length of pid string * = trunc(log10(pid))+1, * but we are restricted to 32 bits for pid anyway. * 32 bits => trunc(log10(2^32))+1 = 10 * And if it ever became 64 bits, * 64 bits => trunc(log10(2^64))+1 = 20 */ if ( pid ) { pidlen = 1 + 20; } else { pidlen = 0; } namelen = dirlen + 1 + strlen( basename ) + pidlen + 1; namebuf = ( char * )calloc( 1, namelen ); assert( namebuf ); if ( pid ) { ( void )snprintf( namebuf, namelen, "%s/%s.%d", dirname, basename, pid ); } else { ( void )snprintf( namebuf, namelen, "%s/%s", dirname, basename ); } return namebuf; } int open_trwp( char *pathname ) { int fd; fd = open( pathname, O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR ); if ( fd < 0 ) { mlog( MLOG_NORMAL, _("could not create %s: %s\n"), pathname, strerror( errno )); } return fd; } int open_erwp( char *pathname ) { int fd; fd = open( pathname, O_EXCL | O_CREAT | O_RDWR, S_IRUSR | S_IWUSR ); if ( fd < 0 ) { mlog( MLOG_NORMAL, _("could not create %s: %s\n"), pathname, strerror( errno )); } return fd; } int open_rwp( char *pathname ) { int fd; fd = open( pathname, O_RDWR ); return fd; } int mkdir_tp( char *pathname ) { int rval; rval = mkdir( pathname, S_IRWXU ); return rval; } int open_trwdb( char *dirname, char *basename, pid_t pid ) { char *pathname; int fd; pathname = open_pathalloc( dirname, basename, pid ); fd = open_trwp( pathname ); free( ( void * )pathname ); return fd; } int open_erwdb( char *dirname, char *basename, pid_t pid ) { char *pathname; int fd; pathname = open_pathalloc( dirname, basename, pid ); fd = open_erwp( pathname ); free( ( void * )pathname ); return fd; } int open_rwdb( char *dirname, char *basename, pid_t pid ) { char *pathname; int fd; pathname = open_pathalloc( dirname, basename, pid ); fd = open_rwp( pathname ); free( ( void * )pathname ); return fd; } xfsdump-3.1.6+nmu1/common/mlog.h0000644000000000000000000001053112620476160013354 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef MLOG_H #define MLOG_H /* mlog.[hc] - message logging abstraction */ #include #include "types.h" /* defined log levels - msg will be logged only if cmdline -v arg * is greater than or equal to its level. */ #define MLOG_NORMAL 0 /* OLD */ #define MLOG_SILENT 0 /* NEW */ #define MLOG_VERBOSE 1 #define MLOG_TRACE 2 #define MLOG_DEBUG 3 #define MLOG_NITTY 4 #define MLOG_LEVELMASK 0xff /* modifier flags for the level - only the first is generally exported */ #define MLOG_BARE 0x010000 /* don't print preamble */ #define MLOG_NOTE 0x020000 /* use NOTE format */ #define MLOG_WARNING 0x040000 /* use WARNING format */ #define MLOG_ERROR 0x080000 /* use ERROR format */ #define MLOG_NOLOCK 0x100000 /* do not attempt to obtain mlog lock */ /* subsystem ids: allows per-subsystem control of log level. * use to index mlog_level_ss. */ #define MLOG_SS_GEN 0 /* default if no subsystem specified */ #define MLOG_SS_PROC 1 /* process/thread-related */ #define MLOG_SS_DRIVE 2 /* I/O-related */ #define MLOG_SS_MEDIA 3 /* media-related */ #define MLOG_SS_INV 4 /* media inventory */ #ifdef DUMP #define MLOG_SS_INOMAP 5 /* dump inode number map */ #endif /* DUMP */ #ifdef RESTORE #define MLOG_SS_TREE 5 /* restore tree */ #endif /* RESTORE */ #define MLOG_SS_EXCLFILES 6 /* list excluded files */ #define MLOG_SS_CNT 7 /* NOTE! bump this when adding ss */ #define MLOG_SS_SHIFT 8 #define MLOG_SS_MASK ( 0xff << MLOG_SS_SHIFT ) /* subsystem flags - NOTE! only one may be specified! use in mlog( first arg ) */ #define MLOG_ALL ( MLOG_SS_GEN << MLOG_SS_SHIFT ) #define MLOG_PROC ( MLOG_SS_PROC << MLOG_SS_SHIFT ) #define MLOG_DRIVE ( MLOG_SS_DRIVE << MLOG_SS_SHIFT ) #define MLOG_MEDIA ( MLOG_SS_MEDIA << MLOG_SS_SHIFT ) #define MLOG_INV ( MLOG_SS_INV << MLOG_SS_SHIFT ) #ifdef DUMP #define MLOG_INOMAP ( MLOG_SS_INOMAP << MLOG_SS_SHIFT ) #endif /* DUMP */ #ifdef RESTORE #define MLOG_TREE ( MLOG_SS_TREE << MLOG_SS_SHIFT ) #endif /* RESTORE */ #define MLOG_EXCLFILES ( MLOG_SS_EXCLFILES << MLOG_SS_SHIFT ) /* mlog_level - set during initialization, exported to facilitate * message logging decisions. one per subsystem (see above) */ extern int mlog_level_ss[ MLOG_SS_CNT ]; /* made external so main.c sigint dialog can change */ extern int mlog_showlevel; extern int mlog_showss; extern int mlog_timestamp; /* mlog_ss_name - so main.c sigint dialog can allow changes */ extern char *mlog_ss_names[ MLOG_SS_CNT ]; /* initializes the mlog abstraction. split into two phases to * unravel some initialization sequencing problems. */ extern void mlog_init0( void ); extern bool_t mlog_init1( int argc, char *argv[ ] ); extern bool_t mlog_init2( void ); /* post-initialization, to tell mlog how many streams */ extern void mlog_tell_streamcnt( size_t streamcnt ); /* override the -v option */ void mlog_override_level( int levelarg ); /* vprintf-based message format */ extern void mlog( int level, char *fmt, ... ); extern void mlog_va( int levelarg, char *fmt, va_list args ); #define mlog_exit( e, r ) _mlog_exit( __FILE__, __LINE__, (e), (r) ) extern int _mlog_exit( const char *file, int line, int exit_code, rv_t return_code ); #define mlog_exit_hint( r ) _mlog_exit_hint( __FILE__, __LINE__, (r) ) extern void _mlog_exit_hint( const char *file, int line, rv_t rv ); extern rv_t mlog_get_hint( void ); extern void mlog_exit_flush( void ); /* the following calls are exported ONLY to dlog.c! */ extern void mlog_lock( void ); extern void mlog_unlock( void ); /* fold_t - a character string made to look like a "fold here" */ #define FOLD_LEN 79 typedef char fold_t[ FOLD_LEN + 1 ]; extern void fold_init( fold_t fold, char *infostr, char c ); #endif /* MLOG_H */ xfsdump-3.1.6+nmu1/common/Makefile0000644000000000000000000000133512607344125013707 0ustar # # Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = .. include $(TOPDIR)/include/builddefs LSRCFILES = arch_xlate.c arch_xlate.h \ cldmgr.c cldmgr.h cleanup.c cleanup.h content.h \ content_common.c content_common.h content_inode.h dlog.c dlog.h \ drive.c drive.h drive_minrmt.c drive_scsitape.c drive_simple.c \ exit.h fs.c fs.h getdents.c getdents.h global.c global.h \ hsmapi.c hsmapi.h inventory.c inventory.h lock.c lock.h \ main.c media.c media.h media_rmvtape.h mlog.c mlog.h \ openutil.c openutil.h path.c path.h qlock.c qlock.h \ rec_hdr.h ring.c ring.h stream.c \ stream.h timeutil.c timeutil.h ts_mtio.h types.h util.c util.h default install install-dev : include $(BUILDRULES) xfsdump-3.1.6+nmu1/common/media_rmvtape.h0000644000000000000000000000352012607344125015233 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef MEDIA_RMVTAPE_H #define MEDIA_RMVTAPE_H /* media_rmvtape.h - removalable tape media abstraction */ /* This structure is overlayed on the mh_specific field of the media_hdr * structure. If is a maximum of 128 byptes long. */ struct media_rmvtape_spec { int32_t mrmv_flags; /* 4 0 */ /* flags field for the rmv media layer */ char mrmv_pad[124]; /* 124 4 */ /* remainder of media specific header */ }; typedef struct media_rmvtape_spec media_rmvtape_spec_t; /* media context specific to the rmvtape media driver * */ struct media_context { uuid_t mc_mediaid; uuid_t mc_dumpid; char mc_medialabel[GLOBAL_HDR_STRING_SZ]; char mc_dumplabel[GLOBAL_HDR_STRING_SZ]; }; typedef struct media_context media_context_t; /* flags defined in the rmv media layer * */ #define RMVMEDIA_TERMINATOR_BLOCK 0x00000001 #define TERM_IS_SET(rmv_hdrp) (rmv_hdrp->mrmv_flags & RMVMEDIA_TERMINATOR_BLOCK) #define CAN_OVERWRITE( drivep ) (drivep->d_capabilities & DRIVE_CAP_OVERWRITE) #define CAN_APPEND( drivep ) (drivep->d_capabilities & DRIVE_CAP_APPEND) #define CAN_BSF( drivep ) (drivep->d_capabilities & DRIVE_CAP_BSF) #endif xfsdump-3.1.6+nmu1/common/content_common.c0000644000000000000000000000743112620476160015440 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "types.h" #include "mlog.h" #include "dlog.h" #include "cldmgr.h" #include "global.h" #include "drive.h" #define PREAMBLEMAX 3 #define QUERYMAX 1 #define CHOICEMAX 2 #define ACKMAX 3 #define POSTAMBLEMAX 3 #define DLOG_TIMEOUT 3600 bool_t Media_prompt_change( drive_t *drivep ) { fold_t fold; char question[ 100 ]; char *preamblestr[ PREAMBLEMAX ]; size_t preamblecnt; char *querystr[ QUERYMAX ]; size_t querycnt; char *choicestr[ CHOICEMAX ]; size_t choicecnt; char *ackstr[ ACKMAX ]; size_t ackcnt; char *postamblestr[ POSTAMBLEMAX ]; size_t postamblecnt; ix_t doix; ix_t dontix; ix_t responseix; ix_t sigintix; retry: preamblecnt = 0; fold_init( fold, _("change media dialog"), '=' ); preamblestr[ preamblecnt++ ] = "\n"; preamblestr[ preamblecnt++ ] = fold; preamblestr[ preamblecnt++ ] = "\n\n"; assert( preamblecnt <= PREAMBLEMAX ); dlog_begin( preamblestr, preamblecnt ); /* query: ask if media changed or declined */ sprintf( question, _( "please change media in " "drive %u\n"), (unsigned int)drivep->d_index ); querycnt = 0; querystr[ querycnt++ ] = question; assert( querycnt <= QUERYMAX ); choicecnt = 0; dontix = choicecnt; choicestr[ choicecnt++ ] = _("media change declined"); doix = choicecnt; choicestr[ choicecnt++ ] = _("media changed"); assert( choicecnt <= CHOICEMAX ); sigintix = IXMAX - 1; responseix = dlog_multi_query( querystr, querycnt, choicestr, choicecnt, 0, /* hilitestr */ IXMAX, /* hiliteix */ 0, /* defaultstr */ doix, /* defaultix */ DLOG_TIMEOUT, dontix, /* timeout ix */ sigintix, /* sigint ix */ dontix, /* sighup ix */ dontix ); /* sigquit ix */ ackcnt = 0; if ( responseix == doix ) { ackstr[ ackcnt++ ] = _("examining new media\n"); } else if ( responseix == dontix ) { ackstr[ ackcnt++ ] = _("media change aborted\n"); } else { assert( responseix == sigintix ); ackstr[ ackcnt++ ] = _("keyboard interrupt\n"); } assert( ackcnt <= ACKMAX ); dlog_multi_ack( ackstr, ackcnt ); postamblecnt = 0; fold_init( fold, _("end dialog"), '-' ); postamblestr[ postamblecnt++ ] = "\n"; postamblestr[ postamblecnt++ ] = fold; postamblestr[ postamblecnt++ ] = "\n\n"; assert( postamblecnt <= POSTAMBLEMAX ); dlog_end( postamblestr, postamblecnt ); if ( responseix == sigintix ) { if ( cldmgr_stop_requested( )) { return BOOL_FALSE; } sleep( 1 ); /* to allow main thread to begin dialog */ mlog( MLOG_NORMAL | MLOG_BARE, "" ); /* to block until main thread dialog complete */ sleep( 1 ); /* to allow main thread to request children die */ if ( cldmgr_stop_requested( )) { return BOOL_FALSE; } mlog( MLOG_DEBUG, "retrying media change dialog\n" ); goto retry; } return responseix == doix; } xfsdump-3.1.6+nmu1/common/getdents.h0000644000000000000000000000151012607344125014230 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GETDENTS_H #define GETDENTS_H int getdents_wrap (int fd, char *buf, size_t nbytes); #endif /* GETDENTS_H */ xfsdump-3.1.6+nmu1/common/global.c0000644000000000000000000002352612620476160013661 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include /* only for util.h include */ #include "config.h" #include "types.h" #include "util.h" /* only for strncpyterm */ #include "mlog.h" #include "dlog.h" #include "global.h" #include "getopt.h" #include "swap.h" /* declarations of externally defined global symbols *************************/ extern void usage( void ); extern bool_t pipeline; /* forward declarations of locally defined static functions ******************/ #ifdef DUMP static char * prompt_label( char *bufp, size_t bufsz ); #endif /* DUMP */ /* definition of locally defined global variables ****************************/ /* definition of locally defined static variables *****************************/ /* definition of locally defined global functions ****************************/ global_hdr_t * global_hdr_alloc( int argc, char *argv[ ] ) { global_hdr_t *ghdrp; int c; char *dumplabel; #ifdef DUMP char labelbuf[ GLOBAL_HDR_STRING_SZ ]; struct stat64 statb; #endif /* DUMP */ int rval; /* sanity checks */ assert( sizeof( time32_t ) == GLOBAL_HDR_TIME_SZ ); assert( sizeof( uuid_t ) == GLOBAL_HDR_UUID_SZ ); /* allocate a global hdr */ ghdrp = ( global_hdr_t * )calloc( 1, sizeof( global_hdr_t )); assert( ghdrp ); /* fill in the magic number */ strncpy( ghdrp->gh_magic, GLOBAL_HDR_MAGIC, GLOBAL_HDR_MAGIC_SZ ); /* fill in the hdr version */ ghdrp->gh_version = GLOBAL_HDR_VERSION; /* fill in the timestamp: all changes made at or after this moment * will be included in increments on this base. This may be * overridden with the GETOPT_DUMPTIME option. */ ghdrp->gh_timestamp = (time32_t) time( 0 ); /* fill in the host id: typecast to fit into a 64 bit field */ ghdrp->gh_ipaddr = ( uint64_t )( unsigned long )gethostid( ); #ifdef DUMP uuid_generate( ghdrp->gh_dumpid ); #endif /* DUMP */ #ifdef RESTORE uuid_clear( ghdrp->gh_dumpid ); #endif /* RESTORE */ /* fill in the hostname */ rval = gethostname( ghdrp->gh_hostname, GLOBAL_HDR_STRING_SZ ); if ( rval ) { mlog( MLOG_NORMAL | MLOG_ERROR, _("unable to determine hostname: %s\n"), strerror( errno )); return 0; } if ( ! strlen( ghdrp->gh_hostname )) { mlog( MLOG_NORMAL | MLOG_ERROR, _("hostname length is zero\n") ); return 0; } /* scan the command line for the dump session label */ dumplabel = 0; optind = 1; opterr = 0; while ( ( c = getopt( argc, argv, GETOPT_CMDSTRING )) != EOF ) { switch ( c ) { case GETOPT_DUMPLABEL: if ( dumplabel ) { mlog( MLOG_NORMAL, _("too many -%c arguments: " "\"-%c %s\" already given\n"), c, c, dumplabel ); usage( ); return 0; } if ( ! optarg || optarg[ 0 ] == '-' ) { mlog( MLOG_NORMAL | MLOG_ERROR, _("-%c argument missing\n"), c ); usage( ); return 0; } dumplabel = optarg; break; #ifdef RESTORE case GETOPT_SESSIONID: if ( ! uuid_is_null( ghdrp->gh_dumpid )) { mlog( MLOG_NORMAL | MLOG_ERROR, _("too many -%c arguments\n"), c ); usage( ); return 0; } if ( ! optarg || optarg[ 0 ] == '-' ) { mlog( MLOG_NORMAL | MLOG_ERROR, _("-%c argument missing\n"), c ); usage( ); return 0; } if ( ! uuid_parse( optarg, ghdrp->gh_dumpid ) ) { mlog( MLOG_NORMAL | MLOG_ERROR, _("-%c argument not a valid uuid\n"), c ); usage( ); return 0; } break; #endif /* RESTORE */ #ifdef DUMP case GETOPT_DUMPTIME: /* Use the timestamp of the specified file for the * dump time, rather than using the current time. */ if ( ! optarg || optarg[ 0 ] == '-' ) { mlog( MLOG_NORMAL | MLOG_ERROR, _("-%c argument missing\n"), c ); usage( ); return 0; } rval = stat64( optarg, &statb ); if ( rval ) { mlog( MLOG_NORMAL | MLOG_ERROR, _("unable to stat %s: %s\n"), optarg, strerror( errno )); usage( ); return 0; } ghdrp->gh_timestamp = statb.st_mtime; break; case GETOPT_FMT2COMPAT: ghdrp->gh_version = GLOBAL_HDR_VERSION_2; break; #endif /* DUMP */ } } #ifdef DUMP /* if no dump label specified, no pipes in use, and dialogs * are allowed, prompt for one */ if ( ! dumplabel && dlog_allowed( )) { dumplabel = prompt_label( labelbuf, sizeof( labelbuf )); } #endif /* DUMP */ if ( ! dumplabel || ! strlen( dumplabel )) { #ifdef DUMP if ( ! pipeline ) { mlog( MLOG_VERBOSE | MLOG_WARNING, _("no session label specified\n") ); } #endif /* DUMP */ dumplabel = ""; } strncpyterm( ghdrp->gh_dumplabel, dumplabel, sizeof( ghdrp->gh_dumplabel )); return ghdrp; } void global_hdr_free( global_hdr_t *ghdrp ) { free( ( void * )ghdrp ); } /* global_hdr_checksum_set - fill in the global media file header checksum. * utility function for use by drive-specific strategies. */ void global_hdr_checksum_set( global_hdr_t *hdrp ) { uint32_t *beginp = ( uint32_t * )&hdrp[ 0 ]; uint32_t *endp = ( uint32_t * )&hdrp[ 1 ]; uint32_t *p; uint32_t accum; hdrp->gh_checksum = 0; accum = 0; for ( p = beginp ; p < endp ; p++ ) { accum += INT_GET(*p, ARCH_CONVERT); } INT_SET(hdrp->gh_checksum, ARCH_CONVERT, (int32_t)(~accum + 1)); } /* global_hdr_checksum_check - check the global media file header checksum. * utility function for use by drive-specific strategies. * returns BOOL_TRUE if ok, BOOL_FALSE if bad */ bool_t global_hdr_checksum_check( global_hdr_t *hdrp ) { uint32_t *beginp = ( uint32_t * )&hdrp[ 0 ]; uint32_t *endp = ( uint32_t * )&hdrp[ 1 ]; uint32_t *p; uint32_t accum; accum = 0; for ( p = beginp ; p < endp ; p++ ) { accum += INT_GET(*p, ARCH_CONVERT); } return accum == 0 ? BOOL_TRUE : BOOL_FALSE; } /* global_version_check - if we know this version number, return BOOL_TRUE * else return BOOL_FALSE */ bool_t global_version_check( uint32_t version ) { switch (version) { case GLOBAL_HDR_VERSION_0: case GLOBAL_HDR_VERSION_1: case GLOBAL_HDR_VERSION_2: case GLOBAL_HDR_VERSION_3: return BOOL_TRUE; default: return BOOL_FALSE; } } /* definition of locally defined static functions ****************************/ #ifdef DUMP #define PREAMBLEMAX 3 #define QUERYMAX 1 #define CHOICEMAX 1 #define ACKMAX 3 #define POSTAMBLEMAX 3 #define DLOG_TIMEOUT 300 /* ARGSUSED */ static void prompt_label_cb( void *uctxp, dlog_pcbp_t pcb, void *pctxp ) { /* query: ask for a dump label */ ( * pcb )( pctxp, _("please enter label for this dump session") ); } static char * prompt_label( char *bufp, size_t bufsz ) { fold_t fold; char *preamblestr[ PREAMBLEMAX ]; size_t preamblecnt; char *ackstr[ ACKMAX ]; size_t ackcnt; char *postamblestr[ POSTAMBLEMAX ]; size_t postamblecnt; const ix_t abortix = 1; const ix_t okix = 2; ix_t responseix; preamblecnt = 0; fold_init( fold, _("dump label dialog"), '=' ); preamblestr[ preamblecnt++ ] = "\n"; preamblestr[ preamblecnt++ ] = fold; preamblestr[ preamblecnt++ ] = "\n\n"; assert( preamblecnt <= PREAMBLEMAX ); dlog_begin( preamblestr, preamblecnt ); responseix = dlog_string_query( prompt_label_cb, 0, bufp, bufsz, DLOG_TIMEOUT, abortix,/* timeout ix */ IXMAX, /* sigint ix */ IXMAX, /* sighup ix */ IXMAX, /* sigquit ix */ okix ); /* ok ix */ ackcnt = 0; if ( responseix == okix ) { ackstr[ ackcnt++ ] = _("session label entered: \""); ackstr[ ackcnt++ ] = bufp; ackstr[ ackcnt++ ] = "\"\n"; } else { ackstr[ ackcnt++ ] = _("session label left blank\n"); } assert( ackcnt <= ACKMAX ); dlog_string_ack( ackstr, ackcnt ); postamblecnt = 0; fold_init( fold, _("end dialog"), '-' ); postamblestr[ postamblecnt++ ] = "\n"; postamblestr[ postamblecnt++ ] = fold; postamblestr[ postamblecnt++ ] = "\n\n"; assert( postamblecnt <= POSTAMBLEMAX ); dlog_end( postamblestr, postamblecnt ); if ( responseix == okix ) { return bufp; } else { return 0; } } #endif /* DUMP */ xfsdump-3.1.6+nmu1/common/path.c0000644000000000000000000001252212620476160013347 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include "config.h" #include "path.h" struct pem { char *pem_head; char *pem_next; }; typedef struct pem pem_t; static pem_t * pem_alloc( char *path ); static void pem_free( pem_t *pemp ); static char * pem_next( pem_t *pemp ); #define PAMAX 1024 struct pa { char *pa_array[ PAMAX ]; int pa_cnt; }; typedef struct pa pa_t; static pa_t * pa_alloc( void ); static void pa_free( pa_t *pap ); static void pa_append( pa_t *pap, char *pep ); static int pa_peel( pa_t *pap ); static char * pa_gen( pa_t *pap ); char * path_diff( char *path, char *base ) { char *diff; assert( *base == '/' ); assert( *path == '/' ); if ( ! path_beginswith( path, base )) { return 0; } for ( ; *base && *path == *base ; path++, base++ ) ; if ( *path == 0 ) { return 0; } if ( *path == '/' ) { path++; } diff = ( char * )calloc( 1, strlen( path ) + 1 ); assert( diff ); strcpy( diff, path ); return diff; } int path_beginswith( char *path, char *base ) { if ( ! base ) { return 0; } return ! strncmp( base, path, strlen( base )); } char * path_reltoabs( char *dir, char *basedir ) { char *absdir; /* check if the path starts with a / or * is a remote path (i.e. contains machine:/path/name ). */ if ( ( *dir != '/' ) && ( strchr(dir, ':') == 0 ) ) { char *absdir; absdir = ( char * )malloc( strlen( basedir ) + 1 + strlen( dir ) + 1 ); assert( absdir ); ( void )sprintf( absdir, "%s/%s", basedir, dir ); dir = absdir; } if ( strchr(dir, ':') == 0 ) { absdir = path_normalize( dir ); } else { absdir = ( char * )malloc( strlen( dir ) + 1); ( void )sprintf( absdir, "%s", dir); } return absdir; } char * path_normalize( char *path ) { pem_t *pemp = pem_alloc( path ); pa_t *pap = pa_alloc( ); char *pep; char *npath; assert( path[ 0 ] == '/' ); while ( ( pep = pem_next( pemp )) != 0 ) { if ( ! strcmp( pep, "" )) { free( ( void * )pep ); continue; } if ( ! strcmp( pep, "." )) { free( ( void * )pep ); continue; } if ( ! strcmp( pep, ".." )) { int ok; free( ( void * )pep ); ok = pa_peel( pap ); if ( ! ok ) { pa_free( pap ); pem_free( pemp ); return 0; } continue; } pa_append( pap, pep ); } npath = pa_gen( pap ); pa_free( pap ); pem_free( pemp ); return npath; } static pem_t * pem_alloc( char *path ) { pem_t *pemp = ( pem_t * )calloc( 1, sizeof( pem_t )); assert( pemp ); pemp->pem_head = path; pemp->pem_next = pemp->pem_head; return pemp; } static void pem_free( pem_t *pemp ) { free( ( void * )pemp ); } static char * pem_next( pem_t *pemp ) { char *nextnext; size_t len; char *p; /* no more left */ if ( *pemp->pem_next == 0 ) { return 0; } /* find the following slash */ nextnext = strchr( pemp->pem_next + 1, '/' ); /* if end of string encountered, place next next at end of string */ if ( ! nextnext ) { for ( nextnext = pemp->pem_next ; *nextnext ; nextnext++ ) ; } /* determine the length of the path element, sans the leading slash */ len = ( size_t )( nextnext - pemp->pem_next - 1 ); /* allocate buffer to hold the path element, incl null termination */ p = ( char * )malloc( len + 1 ); assert( p ); /* copy the path element into the buffer */ strncpy( p, pemp->pem_next + 1, len ); /* null-terminate */ p[ len ] = 0; /* update next */ pemp->pem_next = nextnext; /* return the allocated buffer to the caller */ return p; } static pa_t * pa_alloc( void ) { pa_t *pap = ( pa_t * )calloc( 1, sizeof( pa_t )); assert( pap ); return pap; } static void pa_free( pa_t *pap ) { int i; for ( i = 0 ; i < pap->pa_cnt ; i++ ) { free( ( void * )pap->pa_array[ i ] ); } free( ( void * )pap ); } static void pa_append( pa_t *pap, char *pep ) { assert( pap->pa_cnt < PAMAX ); pap->pa_array[ pap->pa_cnt ] = pep; pap->pa_cnt++; } static int pa_peel( pa_t *pap ) { if ( pap->pa_cnt <= 0 ) { assert( pap->pa_cnt == 0 ); return 0; } pap->pa_cnt--; assert( pap->pa_array[ pap->pa_cnt ] ); free( ( void * )pap->pa_array[ pap->pa_cnt ] ); pap->pa_array[ pap->pa_cnt ] = 0; return 1; } static char * pa_gen( pa_t *pap ) { size_t sz; int i; char *retp; char *p; sz = 0; for ( i = 0 ; i < pap->pa_cnt ; i++ ) { sz += strlen( pap->pa_array[ i ] ) + 1; } if ( i == 0 ) sz++; sz++; retp = ( char * )malloc( sz ); if ( pap->pa_cnt <= 0 ) { assert( pap->pa_cnt == 0 ); sprintf( retp, "/" ); } else { p = retp; for ( i = 0 ; i < pap->pa_cnt ; i++ ) { sprintf( p, "/%s", pap->pa_array[ i ] ); p += strlen( p ); } } return retp; } xfsdump-3.1.6+nmu1/common/stream.h0000644000000000000000000000452212620476160013714 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef STREAM_H #define STREAM_H /* stream.h definitions pertaining to the dump/restore streams */ #define STREAM_SIMMAX 20 /* maximum number of simultaneous streams. */ /* stream exit codes */ #define STREAM_EXIT_SUCCESS 0 /* stream completed successfully */ #define STREAM_EXIT_STOP 1 /* thread requests a stop */ #define STREAM_EXIT_ABORT 2 /* thread requests an abort */ #define STREAM_EXIT_CORE 3 /* thread requests a core dump */ /* S_FREE: stream entry is available for use * S_RUNNING: stream is actively dumping/restoring * S_ZOMBIE: stream is dead but we're keeping it around because we want to * know something about its termination condition. */ typedef enum { S_FREE, S_RUNNING, S_ZOMBIE } stream_state_t; extern void stream_init( void ); extern void stream_register( pthread_t tid, int streamix ); /* NOTE: lock() must be held when calling stream_dead */ extern void stream_dead( pthread_t tid ); extern void stream_free( pthread_t tid ); extern int stream_find_all( stream_state_t states[], int nstates, pthread_t tids[], int ntids ); extern int stream_getix( pthread_t tid ); extern void stream_set_code( pthread_t tid, int code ); extern void stream_set_return( pthread_t tid, rv_t rv ); extern void stream_set_hint( pthread_t tid, rv_t rv ); extern bool_t stream_exists( pthread_t tid ); extern bool_t stream_get_exit_status( pthread_t tid, stream_state_t states[], int nstates, stream_state_t *state, int *ix, int *exit_code, rv_t *exit_return, rv_t *exit_hint); extern size_t stream_cnt( void ); #endif /* STREAM_H */ xfsdump-3.1.6+nmu1/common/arch_xlate.h0000644000000000000000000000721212620476160014532 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef ARCH_XLATE_H #define ARCH_XLATE_H #include #include "types.h" #include "global.h" #include "content.h" #include "content_inode.h" #include "drive.h" #include "media.h" #include "inomap.h" #include "rec_hdr.h" #include "inv_priv.h" #include "swap.h" /* * xlate_global_hdr - endian convert struct global_hdr * * Note: gh_upper field is not converted. This must be done elsewhere * at the time of assignment, because its contents are unknown. */ void xlate_global_hdr(global_hdr_t *gh1, global_hdr_t *gh2, int dir); /* * xlate_drive_hdr - endian convert struct xlate_drive_hdr * which is loaded as the gh_upper field on the global header */ void xlate_drive_hdr(drive_hdr_t *dh1, drive_hdr_t *dh2, int dir); /* * xlate_media_hdr - endian convert struct media_hdr * which is loaded into drive_hdr.dh_upper */ void xlate_media_hdr(media_hdr_t *mh1, media_hdr_t *mh2, int dir); /* * xlate_content_hdr - endian convert struct content_hdr * which is loaded into media_hdr.mh_upper */ void xlate_content_hdr(content_hdr_t *ch1, content_hdr_t *ch2, int dir); /* * xlate_content_inode_hdr - endian convert struct content_inode_hdr * which is loaded into content_hdr.ch_specific */ void xlate_content_inode_hdr(content_inode_hdr_t *cih1, content_inode_hdr_t *cih2, int dir); /* * xlate_startpt - endian convert struct startpt */ void xlate_startpt(startpt_t *sp1, startpt_t *sp2, int dir); /* * xlate_hnk - endian convert struct hnk * Note: struct hnk is defined in 3 different inomap.h files but they're * all the same. Bad things will happen if they're not... */ void xlate_hnk(hnk_t *h1, hnk_t *h2, int dir); /* * xlate_filehdr - endian convert struct filehdr */ void xlate_filehdr(filehdr_t *fh1, filehdr_t *fh2, int dir); /* * xlate_bstat - endian convert struct bstat */ void xlate_bstat(bstat_t *bs1, bstat_t *bs2, int dir); /* * xlate_extenthdr - endian convert struct extenthdr */ void xlate_extenthdr(extenthdr_t *eh1, extenthdr_t *eh2, int dir); /* * xlate_direnthdr - endian convert struct direnthdr */ void xlate_direnthdr(direnthdr_t *dh1, direnthdr_t *dh2, int dir); /* * xlate_direnthdr_v1 - endian convert struct direnthdr_v1 */ void xlate_direnthdr_v1(direnthdr_v1_t *dh1, direnthdr_v1_t *dh2, int dir); /* * xlate_extattrhdr - endian convert struct extattrhdr */ void xlate_extattrhdr(extattrhdr_t *eh1, extattrhdr_t *eh2, int dir); /* * xlate_rec_hdr - endian convert struct rec_hdr */ void xlate_rec_hdr(rec_hdr_t *rh1, rec_hdr_t *rh2, int dir); /* * endian convert inventory structures */ void xlate_invt_seshdr(invt_seshdr_t *ish1, invt_seshdr_t *ish2, int dir); void xlate_invt_session(invt_session_t *is1, invt_session_t *is2, int dir); void xlate_invt_breakpt(invt_breakpt_t *ib1, invt_breakpt_t *ib2, int dir); void xlate_invt_stream(invt_stream_t *ist1, invt_stream_t *ist2, int dir); void xlate_invt_mediafile(invt_mediafile_t *im1, invt_mediafile_t *im2, int dir); #endif /* ARCH_XLATE_H */ xfsdump-3.1.6+nmu1/common/ring.c0000644000000000000000000002610112620476160013350 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include "config.h" #include "types.h" #include "qlock.h" #include "cldmgr.h" #include "ring.h" static int ring_slave_entry( void *ringctxp ); ring_t * ring_create( size_t ringlen, size_t bufsz, bool_t pinpr, ix_t drive_index, int ( *readfunc )( void *clientctxp, char *bufp ), int ( *writefunc )( void *clientctxp, char *bufp ), void *clientctxp, int *rvalp ) { bool_t ok; ring_t *ringp; size_t mix; /* pre-initialize return value */ *rvalp = 0; /* allocate a ring descriptor */ ringp = ( ring_t * )calloc( 1, sizeof( ring_t )); assert( ringp ); ringp->r_len = ringlen; ringp->r_clientctxp = clientctxp; ringp->r_readfunc = readfunc; ringp->r_writefunc = writefunc; /* allocate counting semaphores for the ready and active queues, * and initialize the queue input and output indices. */ ringp->r_ready_qsemh = qsem_alloc( ringlen ); ringp->r_active_qsemh = qsem_alloc( 0 ); ringp->r_ready_in_ix = 0; ringp->r_ready_out_ix = 0; ringp->r_active_in_ix = 0; ringp->r_active_out_ix = 0; ringp->r_client_cnt = 0; ringp->r_slave_cnt = 0; /* initialize the meters */ ringp->r_client_msgcnt = 0; ringp->r_slave_msgcnt = 0; ringp->r_client_blkcnt = 0; ringp->r_slave_blkcnt = 0; ringp->r_first_io_time = 0; ringp->r_all_io_cnt = 0; /* allocate the ring messages */ ringp->r_msgp = ( ring_msg_t * )calloc( ringlen, sizeof( ring_msg_t )); assert( ringp->r_msgp ); /* allocate the buffers and initialize the messages */ for ( mix = 0 ; mix < ringlen ; mix++ ) { ring_msg_t *msgp = &ringp->r_msgp[ mix ]; msgp->rm_mix = mix; msgp->rm_op = RING_OP_NONE; msgp->rm_stat = RING_STAT_INIT; msgp->rm_user = 0; msgp->rm_loc = RING_LOC_READY; msgp->rm_bufp = ( char * )memalign( PGSZ, bufsz ); if ( ! msgp->rm_bufp ) { *rvalp = ENOMEM; return 0; } if ( pinpr ) { int rval; rval = mlock( ( void * )msgp->rm_bufp, bufsz ); if ( rval ) { if ( errno == ENOMEM ) { *rvalp = E2BIG; return 0; } if ( errno == EPERM ) { *rvalp = EPERM; return 0; } assert( 0 ); } } } /* kick off the slave thread */ ok = cldmgr_create( ring_slave_entry, drive_index, _("slave"), ringp ); assert( ok ); return ringp; } ring_msg_t * ring_get( ring_t *ringp ) { ring_msg_t *msgp; /* assert client currently holds no messages */ assert( ringp->r_client_cnt == 0 ); /* bump client message count and note if client needs to block */ ringp->r_client_msgcnt++; if ( qsemPwouldblock( ringp->r_ready_qsemh )) { ringp->r_client_blkcnt++; } /* block until msg available on ready queue ("P") */ qsemP( ringp->r_ready_qsemh ); /* get a pointer to the next msg on the queue */ msgp = &ringp->r_msgp[ ringp->r_ready_out_ix ]; /* assert the message is where it belongs */ assert( msgp->rm_loc == RING_LOC_READY ); /* verify the message index has not become corrupted */ assert( msgp->rm_mix == ringp->r_ready_out_ix ); /* bump the output index */ ringp->r_ready_out_ix = ( ringp->r_ready_out_ix + 1 ) % ringp->r_len; /* update the message location */ msgp->rm_loc = RING_LOC_CLIENT; /* bump the count of messages held by the client */ ringp->r_client_cnt++; /* return the msg to the client */ return msgp; } void ring_put( ring_t *ringp, ring_msg_t *msgp ) { /* assert the client holds exactly one message */ assert( ringp->r_client_cnt == 1 ); /* assert the client is returning the right message */ assert( msgp->rm_mix == ringp->r_active_in_ix ); /* assert the message is where it belongs */ assert( msgp->rm_loc == RING_LOC_CLIENT ); /* decrement the count of messages held by the client */ ringp->r_client_cnt--; /* update the message location */ msgp->rm_loc = RING_LOC_ACTIVE; /* bump the active queue input ix */ ringp->r_active_in_ix = ( ringp->r_active_in_ix + 1 ) % ringp->r_len; /* bump the semaphore for the active queue ("V") */ qsemV( ringp->r_active_qsemh ); } void ring_reset( ring_t *ringp, ring_msg_t *msgp ) { size_t mix; /* if the client is not holding a message, get the next message */ if ( ringp->r_client_cnt == 0 ) { assert( ! msgp ); msgp = ring_get( ringp ); assert( msgp ); assert( ringp->r_client_cnt == 1 ); } else { assert( msgp ); assert( ringp->r_client_cnt == 1 ); } /* tell the slave to abort */ msgp->rm_op = RING_OP_RESET; ring_put( ringp, msgp ); /* wait for the reset to be acknowledged */ assert( ringp->r_client_cnt == 0 ); do { /* pull a message from the ready queue */ qsemP( ringp->r_ready_qsemh ); msgp = &ringp->r_msgp[ ringp->r_ready_out_ix ]; assert( msgp->rm_loc == RING_LOC_READY ); ringp->r_ready_out_ix = ( ringp->r_ready_out_ix + 1 ) % ringp->r_len; ringp->r_client_cnt++; } while ( msgp->rm_stat != RING_STAT_RESETACK ); assert( ringp->r_client_cnt == ringp->r_len ); /* re-initialize the ring */ assert( qsemPavail( ringp->r_ready_qsemh ) == 0 ); assert( qsemPavail( ringp->r_active_qsemh ) == 0 ); ringp->r_ready_in_ix = 0; ringp->r_ready_out_ix = 0; ringp->r_active_in_ix = 0; ringp->r_active_out_ix = 0; ringp->r_client_cnt = 0; ringp->r_slave_cnt = 0; for ( mix = 0 ; mix < ringp->r_len ; mix++ ) { ring_msg_t *msgp = &ringp->r_msgp[ mix ]; msgp->rm_mix = mix; msgp->rm_op = RING_OP_NONE; msgp->rm_stat = RING_STAT_INIT; msgp->rm_user = 0; msgp->rm_loc = RING_LOC_READY; qsemV( ringp->r_ready_qsemh ); } assert( qsemPavail( ringp->r_ready_qsemh ) == ringp->r_len ); assert( qsemPavail( ringp->r_active_qsemh ) == 0 ); } void ring_destroy( ring_t *ringp ) { ring_msg_t *msgp; /* the client must not be holding a message */ assert( ringp->r_client_cnt == 0 ); /* get a message */ msgp = ring_get( ringp ); /* tell the slave to exit */ msgp->rm_op = RING_OP_DIE; ring_put( ringp, msgp ); /* wait for the die to be acknowledged */ do { /* pull a message from the ready queue */ qsemP( ringp->r_ready_qsemh ); msgp = &ringp->r_msgp[ ringp->r_ready_out_ix ]; assert( msgp->rm_loc == RING_LOC_READY ); ringp->r_ready_out_ix = ( ringp->r_ready_out_ix + 1 ) % ringp->r_len; } while ( msgp->rm_stat != RING_STAT_DIEACK ); /* the slave is dead. */ qsem_free( ringp->r_ready_qsemh ); qsem_free( ringp->r_active_qsemh ); free( ( void * )ringp ); } static ring_msg_t * ring_slave_get( ring_t *ringp ) { ring_msg_t *msgp; /* assert slave currently holds no messages */ assert( ringp->r_slave_cnt == 0 ); /* bump slave message count and note if slave needs to block */ ringp->r_slave_msgcnt++; if ( qsemPwouldblock( ringp->r_active_qsemh )) { ringp->r_slave_blkcnt++; } /* block until msg available on active queue ("P") */ qsemP( ringp->r_active_qsemh ); /* get a pointer to the next msg on the queue */ msgp = &ringp->r_msgp[ ringp->r_active_out_ix ]; /* assert the message is where it belongs */ assert( msgp->rm_loc == RING_LOC_ACTIVE ); /* verify the message index has not become corrupted */ assert( msgp->rm_mix == ringp->r_active_out_ix ); /* bump the output index */ ringp->r_active_out_ix = ( ringp->r_active_out_ix + 1 ) % ringp->r_len; /* update the message location */ msgp->rm_loc = RING_LOC_SLAVE; /* bump the count of messages held by the slave */ ringp->r_slave_cnt++; /* return the msg to the slave */ return msgp; } static void ring_slave_put( ring_t *ringp, ring_msg_t *msgp ) { /* assert the slave holds exactly one message */ assert( ringp->r_slave_cnt == 1 ); /* assert the slave is returning the right message */ assert( msgp->rm_mix == ringp->r_ready_in_ix ); /* assert the message is where it belongs */ assert( msgp->rm_loc == RING_LOC_SLAVE ); /* decrement the count of messages held by the slave */ ringp->r_slave_cnt--; /* update the message location */ msgp->rm_loc = RING_LOC_READY; /* bump the ready queue input ix */ ringp->r_ready_in_ix = ( ringp->r_ready_in_ix + 1 ) % ringp->r_len; /* bump the semaphore for the ready queue ("V") */ qsemV( ringp->r_ready_qsemh ); } static int ring_slave_entry( void *ringctxp ) { sigset_t blocked_set; ring_t *ringp = ( ring_t * )ringctxp; enum { LOOPMODE_NORMAL, LOOPMODE_IGNORE, LOOPMODE_DIE } loopmode; /* block signals, let the main thread handle them */ sigemptyset( &blocked_set ); sigaddset( &blocked_set, SIGINT ); sigaddset( &blocked_set, SIGHUP ); sigaddset( &blocked_set, SIGTERM ); sigaddset( &blocked_set, SIGQUIT ); sigaddset( &blocked_set, SIGALRM ); pthread_sigmask( SIG_SETMASK, &blocked_set, NULL ); /* loop reading and precessing messages until told to die */ for ( loopmode = LOOPMODE_NORMAL ; loopmode != LOOPMODE_DIE ; ) { ring_msg_t *msgp; int rval; msgp = ring_slave_get( ringp ); msgp->rm_rval = 0; switch( msgp->rm_op ) { case RING_OP_READ: if ( loopmode == LOOPMODE_IGNORE ) { msgp->rm_stat = RING_STAT_IGNORE; break; } if ( ! ringp->r_first_io_time ) { ringp->r_first_io_time = time( 0 ); assert( ringp->r_first_io_time ); } rval = ( ringp->r_readfunc )( ringp->r_clientctxp, msgp->rm_bufp ); msgp->rm_rval = rval; ringp->r_all_io_cnt++; if ( msgp->rm_rval == 0 ) { msgp->rm_stat = RING_STAT_OK; } else { msgp->rm_stat = RING_STAT_ERROR; loopmode = LOOPMODE_IGNORE; } break; case RING_OP_WRITE: if ( loopmode == LOOPMODE_IGNORE ) { msgp->rm_stat = RING_STAT_IGNORE; break; } if ( ! ringp->r_first_io_time ) { ringp->r_first_io_time = time( 0 ); assert( ringp->r_first_io_time ); } rval = ( ringp->r_writefunc )( ringp->r_clientctxp, msgp->rm_bufp ); msgp->rm_rval = rval; ringp->r_all_io_cnt++; if ( msgp->rm_rval == 0 ) { msgp->rm_stat = RING_STAT_OK; } else { msgp->rm_stat = RING_STAT_ERROR; loopmode = LOOPMODE_IGNORE; } break; case RING_OP_NOP: msgp->rm_stat = RING_STAT_NOPACK; break; case RING_OP_TRACE: msgp->rm_stat = RING_STAT_IGNORE; break; case RING_OP_RESET: loopmode = LOOPMODE_NORMAL; msgp->rm_stat = RING_STAT_RESETACK; break; case RING_OP_DIE: msgp->rm_stat = RING_STAT_DIEACK; loopmode = LOOPMODE_DIE; break; default: msgp->rm_stat = RING_STAT_IGNORE; break; } ring_slave_put( ringp, msgp ); } return 0; } xfsdump-3.1.6+nmu1/common/content.h0000644000000000000000000001117212620476160014072 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef CONTENT_H #define CONTENT_H /* content.[hc] - dump/restore content strategy abstraction */ /* content_hdr_t - content file header * * This header structure will be placed at the beginning of the * content media files by the media manager mo_begin_write() operator, * and will be extracted from the beginning of the media object files by * the mo_begin_read() operator. A content header_t has three parts: generally * useful info, content strategy-specific info, and upper layer info. The hdr * argument of the co_begin_write() operator will be stuffed into the * upper layer info, and extracted for the upper layer by co_begin_read(). */ #define CONTENT_HDR_SZ sizeofmember( media_hdr_t, mh_upper ) #define CONTENT_HDR_FSTYPE_SZ 16 #define CONTENT_STATSZ 160 /* must match dlog.h DLOG_MULTI_STATSZ */ struct content_hdr { char ch_mntpnt[ GLOBAL_HDR_STRING_SZ ]; /* 100 100 */ /* full pathname of fs mount point */ char ch_fsdevice[ GLOBAL_HDR_STRING_SZ ]; /* 100 200 */ /* full pathname of char device containing fs */ char ch_pad1[GLOBAL_HDR_STRING_SZ]; /* 100 300 */ /* in case another label is needed */ char ch_fstype[ CONTENT_HDR_FSTYPE_SZ ]; /* 10 310 */ /* from fsid.h */ uuid_t ch_fsid; /* 10 320 */ /* file system uuid */ char ch_pad2[ GLOBAL_HDR_UUID_SZ ]; /* 10 330 */ /* in case another id is needed */ char ch_pad3[ 8 ]; /* 8 338 */ /* padding */ int32_t ch_strategyid; /* 4 33c */ /* ID of the content strategy used to produce this dump */ char ch_pad4[ 4 ]; /* 4 340 */ /* alignment */ char ch_specific[ 0xc0 ]; /* c0 400 */ /* content strategy-specific info */ }; typedef struct content_hdr content_hdr_t; #define CONTENT_QUOTAFILE "xfsdump_quotas" #define CONTENT_PQUOTAFILE "xfsdump_quotas_proj" #define CONTENT_GQUOTAFILE "xfsdump_quotas_group" #ifdef DUMP struct quota_info { char * desc; /* Quotas type (user, project, etc) */ bool_t savequotas; /* Quotas saved OK */ char * quotafile; /* Filename quota info is stored in */ char quotapath[MAXPATHLEN]; /* Full path to quotafile */ char * repquotaargs; /* Args to repquota to create this quotafile */ int statflag; /* quota stats flag for this type */ ino_t quotaino; /* ino of the quota file */ }; typedef struct quota_info quota_info_t; extern bool_t is_quota_file(ino_t ino); #endif /* DUMP */ #ifdef DUMP extern bool_t content_init( int argc, char *argv[ ], global_hdr_t *gwhdrtemplatep ); /* prepares for multi-stream dump */ extern int content_stream_dump( ix_t strmix ); /* does stream dump */ #endif /* DUMP */ #ifdef RESTORE extern size_t perssz; extern bool_t content_init( int argc, char *argv[ ], size64_t vmsz ); /* prepares for multi-thread restore */ extern int content_stream_restore( ix_t thrdix ); /* does thread restore */ extern bool_t content_overwrite_ok( char *path, int32_t ctime, int32_t mtime, char **reasonstrp, bool_t *exists ); /* called by tree to ask if ok to overwrite file */ extern void content_showinv( void ); /* displays inventory of dump session being restored, * in the context of a second-level dialog */ extern void content_showremainingobjects( void ); /* displays info on media objects remaining to be restored. */ #endif /* RESTORE */ extern bool_t content_complete( void ); /* cleanup: called from main thread. returns TRUE if complete */ extern size_t content_statline( char **lines[ ] ); /* supplies status line for main keyboard intr dialog * returns by ref an array of character strings, and the length * of the array is returned by value. */ extern bool_t content_media_change_needed; /* queried by main thread to decide if interupt dialog needed * for media change confirmation. */ extern char *content_mediachange_query( void ); /* invoked by main thread sigint dialog to allow operator to * confirm media changes and ask what media objects remain */ #endif /* CONTENT_H */ xfsdump-3.1.6+nmu1/common/qlock.c0000644000000000000000000001175012620476160013526 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include "config.h" #include "types.h" #include "qlock.h" #include "mlog.h" struct qlock { ix_t ql_ord; /* ordinal position of this lock */ pthread_mutex_t ql_mutex; }; typedef struct qlock qlock_t; /* internal qlock */ typedef size_t ordmap_t; /* bitmap of ordinals. used to track what ordinals have * been allocated. */ #define ORDMAX ( 8 * sizeof( ordmap_t )) /* ordinals must fit into a wordsize bitmap */ static ordmap_t qlock_ordalloced; /* to enforce allocation of only one lock to each ordinal value */ static __thread ordmap_t thread_ordmap; /* holds the ordmap for each thread */ #define QLOCK_ORDMAP_SET( ordmap, ord ) ( ordmap |= 1U << ord ) /* sets the ordinal bit in an ordmap */ #define QLOCK_ORDMAP_CLR( ordmap, ord ) ( ordmap &= ~( 1U << ord )) /* clears the ordinal bit in an ordmap */ #define QLOCK_ORDMAP_GET( ordmap, ord ) ( ordmap & ( 1U << ord )) /* checks if ordinal set in ordmap */ #define QLOCK_ORDMAP_CHK( ordmap, ord ) ( ordmap & (( 1U << ord ) - 1U )) /* checks if any bits less than ord are set in the ordmap */ qlockh_t qlock_alloc( ix_t ord ) { qlock_t *qlockp; /* verify the ordinal is not already taken, and mark as taken */ assert( ! QLOCK_ORDMAP_GET( qlock_ordalloced, ord )); QLOCK_ORDMAP_SET( qlock_ordalloced, ord ); /* allocate lock memory */ qlockp = ( qlock_t * )calloc( 1, sizeof( qlock_t )); assert( qlockp ); /* initialize the mutex */ pthread_mutex_init( &qlockp->ql_mutex, NULL ); /* assign the ordinal position */ qlockp->ql_ord = ord; return ( qlockh_t )qlockp; } void qlock_lock( qlockh_t qlockh ) { qlock_t *qlockp = ( qlock_t * )qlockh; pthread_t tid; /* REFERENCED */ int rval; /* get the caller's tid */ tid = pthread_self(); /* assert that this lock not already held by this thread */ if ( QLOCK_ORDMAP_GET( thread_ordmap, qlockp->ql_ord )) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_NOLOCK, _("lock already held: tid %lu ord %d map %x\n"), tid, qlockp->ql_ord, thread_ordmap ); } assert( ! QLOCK_ORDMAP_GET( thread_ordmap, qlockp->ql_ord )); /* assert that no locks with a lesser ordinal are held by this thread */ if ( QLOCK_ORDMAP_CHK( thread_ordmap, qlockp->ql_ord )) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_NOLOCK, _("lock ordinal violation: tid %lu ord %d map %x\n"), tid, qlockp->ql_ord, thread_ordmap ); } assert( ! QLOCK_ORDMAP_CHK( thread_ordmap, qlockp->ql_ord )); /* acquire the lock */ rval = pthread_mutex_lock( &qlockp->ql_mutex ); assert( !rval ); /* add ordinal to this threads ordmap */ QLOCK_ORDMAP_SET( thread_ordmap, qlockp->ql_ord ); } void qlock_unlock( qlockh_t qlockh ) { qlock_t *qlockp = ( qlock_t * )qlockh; /* REFERENCED */ int rval; /* verify lock is held by this thread */ assert( QLOCK_ORDMAP_GET( thread_ordmap, qlockp->ql_ord )); /* clear lock's ord from thread's ord map */ QLOCK_ORDMAP_CLR( thread_ordmap, qlockp->ql_ord ); /* release the lock */ rval = pthread_mutex_unlock( &qlockp->ql_mutex ); assert( ! rval ); } qsemh_t qsem_alloc( ix_t cnt ) { sem_t *semp; int rval; /* allocate a semaphore */ semp = ( sem_t * )calloc( 1, sizeof( sem_t )); assert( semp ); /* initialize the semaphore */ rval = sem_init( semp, 0, cnt ); assert( !rval ); return ( qsemh_t )semp; } void qsem_free( qsemh_t qsemh ) { sem_t *semp = ( sem_t * )qsemh; int rval; /* destroy the mutex and condition */ rval = sem_destroy( semp ); assert( !rval ); /* free the semaphore */ free( semp ); } void qsemP( qsemh_t qsemh ) { sem_t *semp = ( sem_t * )qsemh; int rval; /* "P" the semaphore */ rval = sem_wait( semp ); assert( !rval ); } void qsemV( qsemh_t qsemh ) { sem_t *semp = ( sem_t * )qsemh; int rval; /* "V" the semaphore */ rval = sem_post( semp ); assert( !rval ); } bool_t qsemPwouldblock( qsemh_t qsemh ) { sem_t *semp = ( sem_t * )qsemh; int count; int rval; rval = sem_getvalue( semp, &count ); assert( !rval ); return count <= 0 ? BOOL_TRUE : BOOL_FALSE; } size_t qsemPavail( qsemh_t qsemh ) { sem_t *semp = ( sem_t * )qsemh; int count; int rval; rval = sem_getvalue( semp, &count ); assert( !rval ); return count < 0 ? 0 : count; } xfsdump-3.1.6+nmu1/common/lock.c0000644000000000000000000000225112620476160013341 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include "config.h" #include "types.h" #include "qlock.h" #include "mlog.h" static qlockh_t lock_qlockh = QLOCKH_NULL; bool_t lock_init( void ) { /* initialization sanity checks */ assert( lock_qlockh == QLOCKH_NULL ); /* allocate a qlock */ lock_qlockh = qlock_alloc( QLOCK_ORD_CRIT ); return BOOL_TRUE; } void lock( void ) { qlock_lock( lock_qlockh ); } void unlock( void ) { qlock_unlock( lock_qlockh ); } xfsdump-3.1.6+nmu1/common/dlog.h0000644000000000000000000000716712620476160013356 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef DLOG_H #define DLOG_H /* dlog.[hc] - operator dialog abstraction * * abstracts dialogs with the operator */ extern bool_t dlog_init( int argc, char *argv[ ] ); /* tells if dialogs are allowed; * will be false if invoked to right of unnamed pipe, * or if pipe to left breaks. */ extern bool_t dlog_allowed( void ); /* allows signal handler to notify dlog of broken write pipe */ extern void dlog_desist( void ); /* returns the dialog tty file descriptor. returns -1 if none */ extern int dlog_fd( void ); /* returns BOOL_TRUE if a dialog consumed the given signal */ extern bool_t dlog_sighandler( int signo ); /* bracket a dialog session */ extern void dlog_begin( char *preamblestr[ ], size_t preamblecnt ); extern void dlog_end( char *postamblestr[ ], size_t postamblecnt ); /* multiple choice question abstraction. if any exception event index * set to IXMAX, that event will be ignored. returns index of selected * choice, or exception index if exception occured. */ extern ix_t dlog_multi_query( char *querystr[ ], /* pre-choices output */ size_t querycnt, /* length of above */ char *choicestr[ ], /* choices */ size_t choicecnt, /* length of above */ char *hilitestr, /* to distinguish */ ix_t hiliteix, /* highlighted choice */ char *defaultstr, /* to distinguish */ ix_t defaultix, /* return if cr */ time32_t timeout, /* secs b4 giving up */ ix_t timeoutix, /* return if timeout */ ix_t sigintix, /* return if SIGINT */ ix_t sighupix, /* return if SIGHUP */ ix_t sigquitix ); /* return if SIGQUIT */ extern void dlog_multi_ack( char *ackstr[ ], size_t ackcnt ); /* call the caller's callback to display whatever, using provided print * function, then prompt for and return an arbitrary string. two types * defined: pointer to the caller's function to print, and pointer to * function used by that function to do output. returns okix if successful, * timeoutix if times out, sigintix if SIGINT recieved, sighupix if SIGHUP * received, sigquitix if SIGQUIT received. if any of the exception indices * are set to IXMAX by the caller, those events will be ignored. */ typedef void ( * dlog_pcbp_t )( void *pctxp, char *s, ... ); typedef void ( * dlog_ucbp_t )( void *uctxp, dlog_pcbp_t pcb, void *pctxp ); extern ix_t dlog_string_query( dlog_ucbp_t ucb, /* user's print func */ void *uctxp, /* user's context for above */ char *bufp, /* typed string returned in */ size_t bufsz, /* buffer size */ time32_t timeout, /* secs b4 giving up */ ix_t timeoutix, /* return if timeout */ ix_t sigintix, /* return if SIGINT */ ix_t sighupix, /* return if SIGHUP */ ix_t sigquitix, /* return if SIGQUIT */ ix_t okix ); /* return if successful */ extern void dlog_string_ack( char *ackstr[ ], size_t ackcnt ); #endif /* DLOG_H */ xfsdump-3.1.6+nmu1/common/cldmgr.c0000644000000000000000000001214412620476160013663 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include "config.h" #include "exit.h" #include "types.h" #include "lock.h" #include "qlock.h" #include "stream.h" #include "mlog.h" #include "cldmgr.h" extern size_t pgsz; #define CLD_MAX ( STREAM_SIMMAX * 2 ) typedef enum { C_AVAIL, C_ALIVE, C_EXITED } state_t; struct cld { state_t c_state; int c_exit_code; pthread_t c_tid; ix_t c_streamix; int ( * c_entry )( void *arg1 ); void * c_arg1; }; typedef struct cld cld_t; static cld_t cld[ CLD_MAX ]; static bool_t cldmgr_stopflag; static cld_t *cldmgr_getcld( void ); static void *cldmgr_entry( void * ); static void cldmgr_cleanup( void * ); /* REFERENCED */ static pthread_t cldmgr_parenttid; bool_t cldmgr_init( void ) { ( void )memset( ( void * )cld, 0, sizeof( cld )); cldmgr_stopflag = BOOL_FALSE; cldmgr_parenttid = pthread_self( ); return BOOL_TRUE; } bool_t cldmgr_create( int ( * entry )( void *arg1 ), ix_t streamix, char *descstr, void *arg1 ) { cld_t *cldp; int rval; assert( pthread_equal( pthread_self( ), cldmgr_parenttid ) ); cldp = cldmgr_getcld( ); if ( ! cldp ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_PROC, _( "cannot create %s thread for stream %u: " "too many child threads (max allowed is %d)\n"), descstr, streamix, CLD_MAX ); return BOOL_FALSE; } cldp->c_exit_code = EXIT_INTERRUPT; cldp->c_streamix = streamix; cldp->c_entry = entry; cldp->c_arg1 = arg1; rval = pthread_create( &cldp->c_tid, NULL, cldmgr_entry, cldp ); if ( rval ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_PROC, _( "failed creating %s thread for stream %u: %s\n"), descstr, streamix, strerror( rval )); } else { mlog( MLOG_NITTY | MLOG_PROC, "%s thread created for stream %u: tid %lu\n", descstr, streamix, cldp->c_tid ); } return rval ? BOOL_FALSE : BOOL_TRUE; } void cldmgr_stop( void ) { /* must NOT mlog here! * locked up by main loop dialog */ cldmgr_stopflag = BOOL_TRUE; } int cldmgr_join( void ) { cld_t *p = cld; cld_t *ep = cld + sizeof( cld ) / sizeof( cld[ 0 ] ); int xc = EXIT_NORMAL; lock(); for ( ; p < ep ; p++ ) { if ( p->c_state == C_EXITED ) { if ( ( int )( p->c_streamix ) >= 0 ) { stream_dead( p->c_tid ); } pthread_join( p->c_tid, NULL ); if ( p->c_exit_code != EXIT_NORMAL && xc != EXIT_FAULT ) xc = p->c_exit_code; if ( p->c_exit_code != EXIT_NORMAL ) { mlog( MLOG_DEBUG | MLOG_PROC | MLOG_NOLOCK, "child (thread %lu) requested stop: " "exit code %d (%s)\n", p->c_tid, p->c_exit_code, exit_codestring( p->c_exit_code )); } // reinit this child for reuse memset( ( void * )p, 0, sizeof( cld_t )); } } unlock(); return xc; } bool_t cldmgr_stop_requested( void ) { return cldmgr_stopflag; } size_t cldmgr_remainingcnt( void ) { cld_t *p = cld; cld_t *ep = cld + sizeof( cld ) / sizeof( cld[ 0 ] ); size_t cnt; cnt = 0; lock( ); for ( ; p < ep ; p++ ) { if ( p->c_state == C_ALIVE ) { cnt++; } } unlock( ); return cnt; } bool_t cldmgr_otherstreamsremain( ix_t streamix ) { cld_t *p = cld; cld_t *ep = cld + sizeof( cld ) / sizeof( cld[ 0 ] ); lock( ); for ( ; p < ep ; p++ ) { if ( p->c_state == C_ALIVE && p->c_streamix != streamix ) { unlock( ); return BOOL_TRUE; } } unlock( ); return BOOL_FALSE; } static cld_t * cldmgr_getcld( void ) { cld_t *p = cld; cld_t *ep = cld + sizeof( cld ) / sizeof( cld[ 0 ] ); lock(); for ( ; p < ep ; p++ ) { if ( p->c_state == C_AVAIL ) { p->c_state = C_ALIVE; break; } } unlock(); return ( p < ep ) ? p : 0; } static void * cldmgr_entry( void *arg1 ) { cld_t *cldp = ( cld_t * )arg1; pthread_t tid = pthread_self( ); pthread_cleanup_push( cldmgr_cleanup, arg1 ); if ( ( int )( cldp->c_streamix ) >= 0 ) { stream_register( tid, ( int )cldp->c_streamix ); } mlog( MLOG_DEBUG | MLOG_PROC, "thread %lu created for stream %d\n", tid, cldp->c_streamix ); cldp->c_exit_code = ( * cldp->c_entry )( cldp->c_arg1 ); pthread_cleanup_pop( 1 ); return NULL; } static void cldmgr_cleanup( void *arg1 ) { cld_t *cldp = ( cld_t * )arg1; lock(); cldp->c_state = C_EXITED; // signal the main thread to look for exited threads kill( getpid( ), SIGUSR1 ); unlock(); } xfsdump-3.1.6+nmu1/common/rec_hdr.h0000644000000000000000000000530012620476160014022 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef REC_HDR_H #define REC_HDR_H /* this is the drive-specific portion of the drive header defined * in drive.h (dh_specific). the first record in a media file begins * with a global_hdr_t with this embedded in dh_specific. all subsequent * records begin with one of these. note that the first page (STAPE_HDR_SZ) * bytes are always reserved for the header; the user data begins at * record offset STAPE_HDR_SZ. Note also that the first record of each * media file is unused except for the header; user data begins STAPE_HDR_SZ * bytes into the second record. */ /* * This structure is used by both drive_minrmt and drive_scsi. New * strategies should define their own here if they need a different * structure, and add a endian conversion function to arch_xlate.c */ struct rec_hdr { uint64_t magic; /* 8 8 */ /* magic number STAPE_MAGIC (see above) */ int32_t version; /* 4 c */ /* version number STAPE_VERSION (see above) */ int32_t blksize; /* 4 10 */ /* size of tape block in bytes */ int32_t recsize; /* 4 14 */ /* size of this record in bytes, including 4k header */ int32_t capability; /* 4 18 */ /* tape drive capabilities (from drive.h) */ char pad1[ 8 ]; /* 8 20 */ /* padding */ off64_t file_offset; /* 8 28 */ /* this record's byte offset into the media file. * raw, includes header. */ off64_t first_mark_offset; /* 8 30 */ /* raw media file byte offset of first mark set * in this record. set to -1 if no marks in record */ uint32_t rec_used; /* 4 34 */ /* portion of record containing user data plus rec hdr (bytes). * normally set to record size. last record written may * indicate smaller value. includes record header. */ int32_t checksum; /* 4 38 */ int32_t ischecksum; /* 4 3c */ uuid_t dump_uuid; /* 10 4c */ char pad2[ 0x1b4 ]; /* 1b4 200 */ }; /* pad to sizeof drive_hdr_t dh_specific */ typedef struct rec_hdr rec_hdr_t; #endif /* REC_HDR_H */ xfsdump-3.1.6+nmu1/common/fs.c0000644000000000000000000002006012620476160013017 0ustar /* * Copyright (c) 2000-2002 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "types.h" #include "mlog.h" #include "fs.h" /* fs_info - a magic, highly heuristic function to convert a user-supplied * string into a file system type, character special device pathname, * a mount point, and file system ID (uuid). The primary source of information * is the getmntent(3) routines. Correspondence between "standard" disk * block and character device pathnames is used. The fstyp(1) utility * may be invoked as well. * * returns BOOL_TRUE on success, BOOL_FALSE on failure. * * coding rules: to make this very complex and lengthy decision tree * more graspable, some very strict coding rules were followed: * * 1) function arguments are ordered reference returns first, input * parameters second. * * 2) all buffer-like refence return arguments are followed by a * caller-supplied buffer size. * * 3) wherever possible functions return the result buffer pointer. * * 4) boolean functions return TRUE on success, FALSE on failure. * * all variables, parameters, and structure members are named as follows: * object types: * usr - user-specified mystery * typ - file system type * mnt - mount point pathname * blk - block device pathname * chr - character device pathname * id - file system ID * stat - stat buffer * te - file system table entry * object modifiers: appended to object type: * b - buffer * s - string * d - default string * p - pointer * object size indication modifiers: appended to a modified object type: * z - buffer size * l - string length */ /* declarations of externally defined global variables */ /* definitions used locally */ struct fs_tab_ent { char *fte_blks; char *fte_mnts; char *fte_typs; struct fs_tab_ent *fte_nextp; }; typedef struct fs_tab_ent fs_tab_ent_t; static fs_tab_ent_t *fs_tabp; /* forward declarations */ static void fs_tab_build( void ); static void fs_tab_free( void ); static fs_tab_ent_t *fs_tab_ent_build( struct mntent * ); static void fs_tab_ent_free( fs_tab_ent_t * ); static fs_tab_ent_t *fs_tab_lookup_blk( char * ); static fs_tab_ent_t *fs_tab_lookup_mnt( char * ); /* ARGSUSED */ bool_t fs_info( char *typb, /* out */ int typbz, char *typd, char *blkb, /* out */ int blkbz, char *mntb, /* out */ int mntbz, uuid_t *idb, /* out */ char *usrs ) /* in */ { struct stat64 statb; fs_tab_ent_t *tep; char *blks; char *mnts; char *typs; bool_t canstat; bool_t ok = BOOL_UNKNOWN; fs_tab_build( ); canstat = ( stat64( usrs, &statb ) == 0 ); if ( canstat && ( statb.st_mode & S_IFMT ) == S_IFBLK ) { if ( ( tep = fs_tab_lookup_blk( usrs )) != 0 ) { blks = tep->fte_blks; assert( strlen( blks ) < ( size_t )blkbz ); strcpy( blkb, blks ); mnts = tep->fte_mnts; if ( mnts ) { assert( strlen( mnts ) < ( size_t )mntbz ); strcpy( mntb, mnts ); } else { mntb[ 0 ] = 0; } if ( ( typs = tep->fte_typs ) == 0 ) { typs = typd; } assert( strlen( typs ) < ( size_t )typbz ); strcpy( typb, typs ); ok = BOOL_TRUE; } else { ok = BOOL_FALSE; } } else if ( ( tep = fs_tab_lookup_mnt( usrs )) != 0 ) { blks = tep->fte_blks; assert( strlen( blks ) < ( size_t )blkbz ); strcpy( blkb, blks ); mnts = tep->fte_mnts; assert( strlen( mnts ) < ( size_t )mntbz ); strcpy( mntb, mnts ); typs = tep->fte_typs; assert( strlen( typs ) < ( size_t )typbz ); strcpy( typb, typs ); ok = BOOL_TRUE; } else { ok = BOOL_FALSE; } fs_tab_free( ); assert( ok != BOOL_UNKNOWN ); if ( ok == BOOL_TRUE ) { int rval = fs_getid( mntb, idb ); if ( rval ) { mlog( MLOG_NORMAL, _("unable to determine uuid of fs mounted at %s: " "%s\n"), mntb, strerror( errno )); } { char string_uuid[37]; uuid_unparse( *idb, string_uuid ); mlog( MLOG_DEBUG, "fs %s uuid [%s]\n", mntb, string_uuid ); } } return ok; } /* fs_mounted - a predicate determining if the specified file system * is actually currently mounted at its mount point. * will not take time to code this now - just check if mntpt is non-NULL. */ /* ARGSUSED */ bool_t fs_mounted( char *typs, char *chrs, char *mnts, uuid_t *idp ) { return strlen( mnts ) > 0 ? BOOL_TRUE : BOOL_FALSE; } int fs_getid( char *mnts, uuid_t *idb ) { xfs_fsop_geom_v1_t geo; int fd; fd = open( mnts, O_RDONLY ); if ( fd < 0 ) { uuid_clear( *idb ); return -1; } if ( ioctl(fd, XFS_IOC_FSGEOMETRY_V1, &geo ) ) { uuid_clear( *idb ); close(fd); return -1; } close(fd); uuid_copy( *idb, geo.uuid ); return 0; } size_t fs_getinocnt( char *mnts ) { struct statvfs vfsstat; int rval; rval = statvfs( mnts, &vfsstat ); if ( rval ) { return 0; } if ( vfsstat.f_files < vfsstat.f_ffree ) { return 0; } return ( size_t )( vfsstat.f_files - vfsstat.f_ffree ); } static void fs_tab_build( void ) { register struct mntent *mntentp; fs_tab_ent_t *tep; FILE *fp; fs_tabp = 0; fp = setmntent( MOUNTED, "r" ); if ( fp == NULL ) { mlog( MLOG_NORMAL, _("Can't open %s for mount information\n"), MOUNTED ); return; } while ( ( mntentp = getmntent( fp )) != 0 ) { tep = fs_tab_ent_build( mntentp ); tep->fte_nextp = fs_tabp; fs_tabp = tep; } endmntent( fp ); } static void fs_tab_free( void ) { fs_tab_ent_t *tep; fs_tab_ent_t *otep; for ( tep = fs_tabp ; tep ; otep = tep, tep = tep->fte_nextp, fs_tab_ent_free( otep ) ) ; } static fs_tab_ent_t * fs_tab_ent_build( struct mntent *mntentp ) { fs_tab_ent_t *tep; char *cp; tep = ( fs_tab_ent_t * )calloc( 1, sizeof( fs_tab_ent_t )); assert( tep ); if ( mntentp->mnt_dir ) { cp = calloc( 1, strlen( mntentp->mnt_dir ) + 1 ); assert( cp ); ( void )strcpy( cp, mntentp->mnt_dir ); tep->fte_mnts = cp; } else { tep->fte_mnts = 0; } if ( mntentp->mnt_type ) { cp = calloc( 1, strlen( mntentp->mnt_type ) + 1 ); assert( cp ); ( void )strcpy( cp, mntentp->mnt_type ); tep->fte_typs = cp; } else { tep->fte_typs = 0; } if ( mntentp->mnt_fsname ) { cp = calloc( 1, strlen( mntentp->mnt_fsname ) + 1 ); assert( cp ); ( void )strcpy( cp, mntentp->mnt_fsname ); tep->fte_blks = cp; } else { tep->fte_blks = 0; } return tep; } static void fs_tab_ent_free( fs_tab_ent_t *tep ) { if ( tep->fte_blks ) free( tep->fte_blks ); if ( tep->fte_mnts ) free( tep->fte_mnts ); if ( tep->fte_typs ) free( tep->fte_typs ); memset( ( void * )tep, 0, sizeof( *tep )); /* bug catcher */ free( tep ); } static fs_tab_ent_t * fs_tab_lookup_blk( char *blks ) { fs_tab_ent_t *tep; for ( tep = fs_tabp ; tep ; tep = tep->fte_nextp ) { struct stat64 stata; bool_t aok; struct stat64 statb; bool_t bok; if ( ! tep->fte_blks ) { continue; } if ( ! strcmp( tep->fte_blks, blks )) { return tep; } aok = ! stat64( blks, &stata ); bok = ! stat64( tep->fte_blks, &statb ); if ( aok && bok && stata.st_rdev == statb.st_rdev ) { return tep; } } return 0; } static fs_tab_ent_t * fs_tab_lookup_mnt( char *mnts ) { fs_tab_ent_t *tep; for ( tep = fs_tabp ; tep ; tep = tep->fte_nextp ) { if ( tep->fte_mnts && ! strcmp( tep->fte_mnts, mnts )) { return tep; } } return 0; } xfsdump-3.1.6+nmu1/common/types.h0000644000000000000000000001116712620476160013570 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TYPES_H #define TYPES_H /* * Pull in all the standard C types first. */ #include /* * type macros that were naively put into xfs/jdm.h, then used in places that * have nothing to do with file handle operations. */ #define sizeofmember( t, m ) sizeof( ( ( t * )0 )->m ) #define offsetofmember( t, m ) ( ( size_t )( char * )&( ( ( t * )0 )->m ) ) #define XFSDUMP_DIRPATH inv_basepath() /* * Should be, but isn't, defined in uuid/uuid.h */ #define UUID_STR_LEN 36 /* fundamental page size - probably should not be hardwired, but * for now we will */ #define PGSZLOG2 12 #define PGSZ ( 1 << PGSZLOG2 ) #define PGMASK ( PGSZ - 1 ) /* integers */ typedef uint32_t size32_t; typedef uint64_t size64_t; typedef char char_t; typedef unsigned char u_char_t; typedef unsigned int uint; typedef long long_t; typedef unsigned long u_long_t; typedef size_t ix_t; typedef int32_t time32_t; typedef uint64_t xfs_ino_t; #define constpp char * const * /* limits */ #define MKMAX( t, s ) ( ( t ) \ ( ( ( 1ull \ << \ ( ( unsigned long long )sizeof( t ) \ * \ ( unsigned long long )NBBY \ - \ ( s + 1ull ))) \ - \ 1ull ) \ * \ 2ull \ + \ 1ull )) #define MKSMAX( t ) MKMAX( t, 1ull ) #define MKUMAX( t ) MKMAX( t, 0ull ) #define INT32MAX MKSMAX( int32_t ) #define UINT32MAX MKUMAX( uint32_t ) #define SIZE32MAX MKUMAX( size32_t ) #define INT64MAX MKSMAX( int64_t ) #define UINT64MAX MKUMAX( uint64_t ) #define SIZE64MAX MKUMAX( size64_t ) #define INO64MAX MKUMAX( xfs_ino_t ) #define OFF64MAX MKSMAX( off64_t ) #define INTGENMAX MKSMAX( int ) #define UINTGENMAX MKUMAX( uint ) #define OFFMAX MKSMAX( off_t ) #define SIZEMAX MKUMAX( size_t ) #define IXMAX MKUMAX( size_t ) #define INOMAX MKUMAX( ino_t ) #define TIMEMAX MKSMAX( time32_t ) #define INT16MAX 0x7fff #define UINT16MAX 0xffff /* boolean */ typedef int bool_t; #define BOOL_TRUE 1 #define BOOL_FALSE 0 #define BOOL_UNKNOWN ( -1 ) #define BOOL_ERROR ( -2 ) /* useful return code scheme * NOTE: that there are macros and error messages in common/types.h that should * be updated when new error codes are added here. */ typedef enum { RV_OK, /* mission accomplished */ RV_NOTOK, /* media erase request denied */ RV_NOMORE, /* no more work to do */ RV_EOD, /* ran out of data */ RV_EOF, /* hit end of media file */ RV_EOM, /* hit end of media object */ RV_ERROR, /* operator error or resource exhaustion */ RV_DONE, /* return early because someone else did work */ RV_INTR, /* cldmgr_stop_requested( ) */ RV_CORRUPT, /* stopped because corrupt data encountered */ RV_QUIT, /* stop using resource */ RV_DRIVE, /* drive quit working */ RV_TIMEOUT, /* operation timed out */ RV_MEDIA, /* no media object in drive */ RV_PROTECTED, /* want to write but write-protected */ RV_CORE, /* really bad - dump core! */ RV_OPT, /* bad command line option */ RV_INIT, /* could not initialise subsystem */ RV_PERM, /* insufficient privilege */ RV_COMPAT, /* dump incompatible */ RV_INCOMPLETE, /* some part of the dump is incomplete */ RV_KBD_INTR, /* keyboard interrupt */ RV_INV, /* session inventory error */ RV_USAGE, /* print command usage only */ RV_EXISTS, /* file or directory already exists */ RV_NONE, /* no error code available */ RV_UNKNOWN, /* there was an error but we don't know which one */ _RV_NUM /* number of return codes */ } rv_t; /* typedefs I'd like to see ... */ typedef struct stat stat_t; typedef struct stat64 stat64_t; typedef struct getbmapx getbmapx_t; typedef struct fsdmidata fsdmidata_t; /* flg definitions for preemptchk */ #define PREEMPT_FULL 0 #define PREEMPT_PROGRESSONLY 1 #endif /* TYPES_H */ xfsdump-3.1.6+nmu1/common/timeutil.h0000644000000000000000000000217612607344125014260 0ustar /* * Copyright (c) 2009 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TIMEUTIL_H #define TIMEUTIL_H /* timeutil.[hc] - time32_t related functions */ /* ctime32 - takes a time32_t instead of a time_t */ extern char *ctime32( const time32_t *timep ); /* ctime32_r - takes a time32_t instead of a time_t */ extern char *ctime32_r( const time32_t *timep, char *buf ); /* ctimennl - ctime(3C) with newline removed */ extern char *ctimennl( const time32_t *clockp ); #endif /* TIMEUTIL_H */ xfsdump-3.1.6+nmu1/common/util.h0000644000000000000000000001224212620476160013374 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef UTIL_H #define UTIL_H /* util.[hc] - generally useful functions */ /* write_buf - converts the normal manager write method into something simpler * * the managers present a somewhat complicated write interface, for performance * reasons, which eliminates buffer copying. however, there are times when * the data to be written is already buffered, such as when writing out * header structures. This function takes care of the details of writing * the contents of such a buffer using the manager operators. * * if bufp is null, writes bufsz zeros. */ typedef char * ( * gwbfp_t )( void *contextp, size_t wantedsz, size_t *szp); typedef int ( * wfp_t )( void *contextp, char *bufp, size_t bufsz ); extern int write_buf( char *bufp, size_t bufsz, void *contextp, gwbfp_t get_write_buf_funcp, wfp_t write_funcp ); /* read_buf - converts the normal manager read method into something simpler * * the managers present a somewhat complicated read interface, for performance * reasons, which eliminates buffer copying. however, there are times when * the caller wants his buffer to be filled completely, such as when reading * header structures. This function takes care of the details of filling * such a buffer using the manager operators. * * if bufp is null, discards read data. * * returns number of bytes successfully read. returns by reference the * status of the first failure of the read funcp. if no read failures occur, * *statp will be zero. */ typedef char * ( *rfp_t )( void *contextp, size_t wantedsz, size_t *szp, int *statp ); typedef void ( * rrbfp_t )( void *contextp, char *bufp, size_t bufsz ); extern int read_buf( char *bufp, size_t bufsz, void *contextp, rfp_t read_funcp, rrbfp_t return_read_buf_funcp, int *statp ); /* strncpyterm - like strncpy, but guarantees the destination is null-terminated */ extern char *strncpyterm( char *s1, char *s2, size_t n ); /* bigstat - efficient file status gatherer. presents an iterative * callback interface, invoking the caller's callback for each in-use * inode. the caller can specify the first ino, and can limit the callbacks * to just dirs, just non-dirs, or both. if the callback returns non-zero, * aborts the iteration and sets stat to the callback's return; otherwise, * stat is set to zero. return value set to errno if the system call fails, * or EINTR if optional pre-emption func returns TRUE. */ #define BIGSTAT_ITER_DIR ( 1 << 0 ) #define BIGSTAT_ITER_NONDIR ( 1 << 1 ) #define BIGSTAT_ITER_ALL ( ~0 ) typedef int (*bstat_cbfp_t)(void *arg1, jdm_fshandle_t *fshandlep, int fsfd, xfs_bstat_t *statp ); typedef xfs_ino_t (*bstat_seekfp_t)(void *arg1, xfs_ino_t lastino); extern int bigstat_iter( jdm_fshandle_t *fshandlep, int fsfd, int selector, xfs_ino_t start_ino, bstat_cbfp_t fp, void * cb_arg1, bstat_seekfp_t seekfp, void * seek_arg1, int *statp, bool_t ( pfp )( int ), /* preemption chk func */ xfs_bstat_t *buf, size_t buflen ); extern int bigstat_one( int fsfd, xfs_ino_t ino, xfs_bstat_t *statp ); extern int inogrp_iter( int fsfd, int ( * fp )( void *arg1, int fsfd, xfs_inogrp_t *inogrp ), void * arg1, int *statp ); /* calls the callback for every entry in the directory specified * by the stat buffer. supplies the callback with a file system * handler and a stat buffer, and the name from the dirent. * * NOTE: does NOT invoke callback for "." or ".."! * * caller may supply getdents buffer. size must be >= sizeof( dirent_t ) * + MAXPATHLEN. if not supplied (usrgdp NULL), one will be malloc()ed. * * if the callback returns non-zero, returns 1 with cbrval set to the * callback's return value. if syscall fails, returns -1 with errno set. * otherwise returns 0. */ extern int diriter( jdm_fshandle_t *fshandlep, int fsfd, xfs_bstat_t *statp, int ( *cbfp )( void *arg1, jdm_fshandle_t *fshandlep, int fsfd, xfs_bstat_t *statp, char *namep ), void *arg1, int *cbrvalp, char *usrgdp, size_t usrgdsz ); /* macro to copy uuid structures */ #define COPY_LABEL( lab1, lab2) ( bcopy( lab1, lab2, GLOBAL_HDR_STRING_SZ) ) /* * Align pointer up to alignment */ #define ALIGN_PTR(p,a) \ (((intptr_t)(p) & ((a)-1)) ? \ ((void *)(((intptr_t)(p) + ((a)-1)) & ~((a)-1))) : \ ((void *)(p))) #endif /* UTIL_H */ xfsdump-3.1.6+nmu1/common/cldmgr.h0000644000000000000000000000370412620476160013672 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef CLDMGR_H #define CLDMGR_H /* cldmgr.[hc] - manages all child threads */ /* cldmgr_init - initializes child management * returns FALSE if trouble encountered. */ extern bool_t cldmgr_init( void ); /* cldmgr_create - creates a child thread. returns FALSE if trouble * encountered */ extern bool_t cldmgr_create( int ( * entry )( void *arg1 ), ix_t streamix, char *descstr, void *arg1 ); /* cldmgr_stop - asks all children to gracefully terminate, at the next * convenient point in their normal processing loop. */ extern void cldmgr_stop( void ); /* cldmgr_join - join child threads that have exited. * returns EXIT_NORMAL if all exited normally (or no threads have exited), * EXIT_FAULT if any threads requested a core dump, or another EXIT_* * value if any threads exited abnormally. */ extern int cldmgr_join( void ); /* cldmgr_stop_requested - returns TRUE if the child should gracefully * terminate. */ extern bool_t cldmgr_stop_requested( void ); /* cldmgr_remainingcnt - returns number of children remaining */ extern size_t cldmgr_remainingcnt( void ); /* checks if any children serving any other streams are still alive */ extern bool_t cldmgr_otherstreamsremain( ix_t streamix ); #endif /* CLDMGR_H */ xfsdump-3.1.6+nmu1/common/path.h0000644000000000000000000000176312607344125013361 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef PATH_H #define PATH_H /* various pathname helpers */ extern char * path_reltoabs( char *dir, char *basedir ); extern char *path_normalize( char *path ); extern char * path_diff( char *path, char *base ); extern int path_beginswith( char *path, char *base ); #endif /* PATH_H */ xfsdump-3.1.6+nmu1/common/stream.c0000644000000000000000000001477612620476160013723 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include "config.h" #include "types.h" #include "exit.h" #include "stream.h" #include "lock.h" #include "mlog.h" #define N(a) (sizeof((a)) / sizeof((a)[0])) struct spm { stream_state_t s_state; pthread_t s_tid; int s_ix; int s_exit_code; rv_t s_exit_return; rv_t s_exit_hint; }; typedef struct spm spm_t; static spm_t spm[ STREAM_SIMMAX * 3 ]; static bool_t initialized = BOOL_FALSE; void stream_init( void ) { ( void )memset( ( void * )spm, 0, sizeof( spm )); initialized = BOOL_TRUE; } /* * Note that the stream list structure (updated via the stream_* functions) * is indexed by pthread_t (tid). Multiple processes can be registered against * the same stream index, typically: the primary content process that does the * work; and the drive slave process, which just processes stuff off the ring * buffer. In general having multiple tids registered per stream is not an issue * for termination status reporting, as the mlog_exit* logging functions only * ever get called out of the primary content process. */ void stream_register( pthread_t tid, int streamix ) { spm_t *p = spm; spm_t *ep = spm + N(spm); assert( streamix < STREAM_SIMMAX ); lock(); for ( ; p < ep ; p++ ) { if ( p->s_state == S_FREE ) { p->s_state = S_RUNNING; break; } } unlock(); assert( p < ep ); if ( p >= ep ) return; p->s_tid = tid; p->s_ix = streamix; p->s_exit_code = -1; p->s_exit_return = RV_NONE; p->s_exit_hint = RV_NONE; } /* NOTE: lock() must be held when calling stream_dead() */ void stream_dead( pthread_t tid ) { spm_t *p = spm; spm_t *ep = spm + N(spm); for ( ; p < ep ; p++ ) if ( pthread_equal( p->s_tid, tid ) ) { p->s_state = S_ZOMBIE; break; } assert( p < ep ); } void stream_free( pthread_t tid ) { spm_t *p = spm; spm_t *ep = spm + N(spm); lock(); for ( ; p < ep ; p++ ) { if ( pthread_equal( p->s_tid, tid ) ) { (void) memset( (void *) p, 0, sizeof(spm_t) ); p->s_state = S_FREE; break; } } unlock(); assert( p < ep ); } int stream_find_all( stream_state_t states[], int nstates, pthread_t tids[], int ntids ) { int i, count = 0; spm_t *p = spm; spm_t *ep = spm + N(spm); assert(nstates > 0 && ntids > 0); if (!initialized) return 0; /* lock - make sure we get a consistent snapshot of the stream status */ lock(); for ( ; p < ep && count < ntids; p++ ) for (i = 0; i < nstates; i++) if (p->s_state == states[i]) { tids[count++] = p->s_tid; break; } unlock(); return count; } static spm_t * stream_find( pthread_t tid, stream_state_t s[], int nstates ) { int i; spm_t *p = spm; spm_t *ep = spm + N(spm); assert(nstates > 0); /* note we don't lock the stream array in this function */ for ( ; p < ep ; p++ ) if ( pthread_equal( p->s_tid, tid ) ) { /* check state */ for (i = 0; i < nstates; i++) if (p->s_state == s[i]) return p; } #ifdef STREAM_DEBUG { static const char *state_strings[] = { "S_FREE", "S_RUNNING", "S_ZOMBIE" }; mlog( MLOG_DEBUG | MLOG_ERROR | MLOG_NOLOCK | MLOG_BARE, "stream_find(): no stream with tid: %lu and state%s:", tid, nstates == 1 ? "" : "s" ); for (i = 0; i < nstates; i++) mlog( MLOG_DEBUG | MLOG_ERROR | MLOG_NOLOCK | MLOG_BARE, " %s", state_strings[s[i]]); mlog( MLOG_DEBUG | MLOG_ERROR | MLOG_NOLOCK | MLOG_BARE, "\n"); } #endif /* STREAM_DEBUG */ return (spm_t *) NULL; } /* * Note, the following function is called from mlog.c:mlog_va(), * where locking may be disabled and we are already protected by * another lock. So no locking is done in this function. */ int stream_getix( pthread_t tid ) { stream_state_t states[] = { S_RUNNING }; spm_t *p; int ix; p = stream_find( tid, states, N(states) ); ix = p ? p->s_ix : -1; return ix; } /* * We don't currently export spm_t and don't really want callers * keeping pointers into the stream array, so use explicit access * functions. Note we only expect these to be called from running/owner * streams. */ #define stream_set(field_name, tid, value) \ stream_state_t states[] = { S_RUNNING }; \ spm_t *p; \ pthread_t mytid = pthread_self(); \ \ if ( !pthread_equal(mytid, (tid))) { \ mlog( MLOG_DEBUG | MLOG_ERROR | MLOG_NOLOCK, \ "stream_set_" #field_name "(): " \ "foreign stream (tid %lu) " \ "not permitted to update this stream (tid %lu)\n",\ mytid, (tid)); \ return; \ } \ \ lock(); \ p = stream_find( (tid), states, N(states) ); \ if (p) p->s_exit_ ## field_name = (value); \ unlock(); void stream_set_code( pthread_t tid, int exit_code ) { stream_set( code, tid, exit_code ); } void stream_set_return( pthread_t tid, rv_t rv ) { stream_set( return, tid, rv ); } void stream_set_hint( pthread_t tid, rv_t rv ) { stream_set( hint, tid, rv ); } bool_t stream_get_exit_status( pthread_t tid, stream_state_t states[], int nstates, stream_state_t *state, int *ix, int *exit_code, rv_t *exit_return, rv_t *exit_hint) { bool_t sts = BOOL_FALSE; spm_t *p; lock(); p = stream_find( tid, states, nstates ); if (! p) goto unlock; if (state) *state = p->s_state; if (ix) *ix = p->s_ix; if (exit_code) *exit_code = p->s_exit_code; if (exit_return) *exit_return = p->s_exit_return; if (exit_hint) *exit_hint = p->s_exit_hint; sts = BOOL_TRUE; unlock: unlock(); return sts; } size_t stream_cnt( void ) { spm_t *p = spm; spm_t *ep = spm + N(spm); size_t ixmap = 0; size_t ixcnt; size_t bitix; assert( sizeof( ixmap ) * NBBY >= STREAM_SIMMAX ); lock(); for ( ; p < ep ; p++ ) { if ( p->s_state == S_RUNNING ) { ixmap |= ( size_t )1 << p->s_ix; } } unlock(); ixcnt = 0; for ( bitix = 0 ; bitix < STREAM_SIMMAX ; bitix++ ) { if ( ixmap & ( ( size_t )1 << bitix )) { ixcnt++; } } return ixcnt; } xfsdump-3.1.6+nmu1/common/util.c0000644000000000000000000002632712620476160013400 0ustar /* * Copyright (c) 2000-2002 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "types.h" #include "util.h" #include "mlog.h" #include "getdents.h" extern size_t pgsz; int write_buf( char *bufp, size_t bufsz, void *contextp, gwbfp_t get_write_buf_funcp, wfp_t write_funcp ) { char *mbufp; /* buffer obtained from manager */ size_t mbufsz;/* size of buffer obtained from manager */ while ( bufsz ) { int rval; assert( bufsz > 0 ); mbufp = ( *get_write_buf_funcp )( contextp, bufsz, &mbufsz ); assert( mbufsz <= bufsz ); if ( bufp ) { (void)memcpy( ( void * )mbufp, ( void * )bufp, mbufsz ); } else { (void)memset( ( void * )mbufp, 0, mbufsz ); } rval = ( * write_funcp )( contextp, mbufp, mbufsz ); if ( rval ) { return rval; } if ( bufp ) { bufp += mbufsz; } bufsz -= mbufsz; } return 0; } int read_buf( char *bufp, size_t bufsz, void *contextp, rfp_t read_funcp, rrbfp_t return_read_buf_funcp, int *statp ) { char *mbufp; /* manager's buffer pointer */ size_t mbufsz; /* size of manager's buffer */ int nread; nread = 0; *statp = 0; while ( bufsz ) { mbufp = ( * read_funcp )( contextp, bufsz, &mbufsz, statp ); if ( *statp ) { break; } assert( mbufsz <= bufsz ); if ( bufp ) { ( void )memcpy( (void *)bufp, (void *)mbufp, mbufsz ); bufp += mbufsz; } bufsz -= mbufsz; nread += ( int )mbufsz; ( * return_read_buf_funcp )( contextp, mbufp, mbufsz ); } return nread; } char *strncpyterm( char *s1, char *s2, size_t n ) { char *rval; if ( n < 1 ) return 0; rval = strncpy( s1, s2, n ); s1[ n - 1 ] = 0; return rval; } int bigstat_iter( jdm_fshandle_t *fshandlep, int fsfd, int selector, xfs_ino_t start_ino, bstat_cbfp_t fp, void * cb_arg1, bstat_seekfp_t seekfp, void * seek_arg1, int *statp, bool_t ( pfp )( int ), xfs_bstat_t *buf, size_t buflenin ) { __s32 buflenout; xfs_ino_t lastino; int saved_errno; int bulkstatcnt; xfs_fsop_bulkreq_t bulkreq; /* stat set with return from callback func */ *statp = 0; /* NOT COOL: open will affect root dir's access time */ mlog( MLOG_NITTY, "bulkstat iteration initiated: start_ino == %llu\n", start_ino ); /* quirk of the interface: I want to play in terms of the * ino to begin with, and ino 0 is not used. so, ... */ if ( start_ino > 0 ) { lastino = start_ino - 1; } else { lastino = 0; } mlog( MLOG_NITTY + 1, "calling bulkstat\n" ); bulkstatcnt = 0; bulkreq.lastip = (__u64 *)&lastino; bulkreq.icount = buflenin; bulkreq.ubuffer = buf; bulkreq.ocount = &buflenout; while (!ioctl(fsfd, XFS_IOC_FSBULKSTAT, &bulkreq)) { xfs_bstat_t *p; xfs_bstat_t *endp; if ( buflenout == 0 ) { mlog( MLOG_NITTY + 1, "bulkstat returns buflen %d\n", buflenout ); return 0; } mlog( MLOG_NITTY + 1, "bulkstat returns buflen %d ino %llu\n", buflenout, buf->bs_ino ); for ( p = buf, endp = buf + buflenout ; p < endp ; p++ ) { int rval; if ( p->bs_ino == 0 ) continue; if ( !p->bs_nlink || !p->bs_mode ) { /* inode being modified, get synced data */ mlog( MLOG_NITTY + 1, "ino %llu needed second bulkstat\n", p->bs_ino ); if( bigstat_one( fsfd, p->bs_ino, p ) < 0 ) { mlog( MLOG_WARNING, _("failed to get bulkstat information for inode %llu\n"), p->bs_ino ); continue; } if ( !p->bs_nlink || !p->bs_mode || !p->bs_ino ) { mlog( MLOG_TRACE, _("failed to get valid bulkstat information for inode %llu\n"), p->bs_ino ); continue; } } if ( ( p->bs_mode & S_IFMT ) == S_IFDIR ) { if ( ! ( selector & BIGSTAT_ITER_DIR )){ continue; } } else { if ( ! ( selector & BIGSTAT_ITER_NONDIR )){ continue; } } rval = ( * fp )( cb_arg1, fshandlep, fsfd, p ); if ( rval ) { *statp = rval; return 0; } if ( pfp ) ( pfp )( PREEMPT_PROGRESSONLY ); } if ( pfp && (++bulkstatcnt % 10) == 0 && ( pfp )( PREEMPT_FULL )) { return EINTR; } if (seekfp) { lastino = seekfp(seek_arg1, lastino); if (lastino == INO64MAX) { mlog( MLOG_DEBUG, "bulkstat seeked to EOS\n"); return 0; } mlog( MLOG_DEBUG, "bulkstat seeked to %llu\n", lastino); lastino = (lastino > 0) ? lastino - 1 : 0; } mlog( MLOG_NITTY + 1, "calling bulkstat\n" ); } saved_errno = errno; mlog( MLOG_NORMAL, _("syssgi( SGI_FS_BULKSTAT ) on fsroot failed: %s\n"), strerror( saved_errno )); return saved_errno; } /* ARGSUSED */ int bigstat_one( int fsfd, xfs_ino_t ino, xfs_bstat_t *statp ) { xfs_fsop_bulkreq_t bulkreq; int count = 0; assert( ino > 0 ); bulkreq.lastip = (__u64 *)&ino; bulkreq.icount = 1; bulkreq.ubuffer = statp; bulkreq.ocount = &count; return xfsctl(NULL, fsfd, XFS_IOC_FSBULKSTAT_SINGLE, &bulkreq); } /* call the given callback for each inode group in the filesystem. */ #define INOGRPLEN 256 int inogrp_iter( int fsfd, int ( * fp )( void *arg1, int fsfd, xfs_inogrp_t *inogrp ), void * arg1, int *statp ) { xfs_ino_t lastino; int inogrpcnt; xfs_inogrp_t *igrp; xfs_fsop_bulkreq_t bulkreq; /* stat set with return from callback func */ *statp = 0; igrp = malloc(INOGRPLEN * sizeof(xfs_inogrp_t)); if (!igrp) { mlog(MLOG_NORMAL | MLOG_ERROR, _("malloc of stream context failed (%d bytes): %s\n"), INOGRPLEN * sizeof(xfs_inogrp_t), strerror(errno)); return -1; } lastino = 0; inogrpcnt = 0; bulkreq.lastip = (__u64 *)&lastino; bulkreq.icount = INOGRPLEN; bulkreq.ubuffer = igrp; bulkreq.ocount = &inogrpcnt; while (!ioctl(fsfd, XFS_IOC_FSINUMBERS, &bulkreq)) { xfs_inogrp_t *p, *endp; if ( inogrpcnt == 0 ) { free(igrp); return 0; } for ( p = igrp, endp = igrp + inogrpcnt ; p < endp ; p++ ) { int rval; rval = ( * fp )( arg1, fsfd, p ); if ( rval ) { *statp = rval; free(igrp); return 0; } } } free(igrp); return errno; } /* calls the callback for every entry in the directory specified * by the stat buffer. supplies the callback with a file system * handle and a stat buffer, and the name from the dirent. * * NOTE: does NOT invoke callback for "." or ".."! * * if the callback returns non-zero, returns 1 with cbrval set to the * callback's return value. if syscall fails, returns -1 with errno set. * otherwise returns 0. * * caller may supply a dirent buffer. if not, will malloc one */ int diriter( jdm_fshandle_t *fshandlep, int fsfd, xfs_bstat_t *statp, int ( *cbfp )( void *arg1, jdm_fshandle_t *fshandlep, int fsfd, xfs_bstat_t *statp, char *namep ), void *arg1, int *cbrvalp, char *usrgdp, size_t usrgdsz ) { size_t gdsz; struct dirent *gdp; int fd; int gdcnt; int scrval; int cbrval; if ( usrgdp ) { assert( usrgdsz >= sizeof( struct dirent ) ); gdsz = usrgdsz; gdp = ( struct dirent * )usrgdp; } else { gdsz = pgsz; gdp = ( struct dirent * )malloc( gdsz ); assert( gdp ); } /* open the directory */ fd = jdm_open( fshandlep, statp, O_RDONLY ); if ( fd < 0 ) { mlog( MLOG_NORMAL, _("WARNING: unable to open directory ino %llu: %s\n"), statp->bs_ino, strerror( errno )); *cbrvalp = 0; if ( ! usrgdp ) { free( ( void * )gdp ); } return -1; } assert( ( statp->bs_mode & S_IFMT ) == S_IFDIR ); /* lots of buffering done here, to achieve OS-independence. * if proves to be to much overhead, can streamline. */ scrval = 0; cbrval = 0; for ( gdcnt = 1 ; ; gdcnt++ ) { struct dirent *p; int nread; register size_t reclen; assert( scrval == 0 ); assert( cbrval == 0 ); nread = getdents_wrap( fd, (char *)gdp, gdsz ); /* negative count indicates something very bad happened; * try to gracefully end this dir. */ if ( nread < 0 ) { mlog( MLOG_NORMAL, _("WARNING: unable to read dirents (%d) for " "directory ino %llu: %s\n"), gdcnt, statp->bs_ino, strerror( errno )); nread = 0; /* pretend we are done */ } /* no more directory entries: break; */ if ( nread == 0 ) { break; } /* translate and invoke cb each entry: skip "." and "..". */ for ( p = gdp, reclen = ( size_t )p->d_reclen ; nread > 0 ; nread -= ( int )reclen, assert( nread >= 0 ), p = ( struct dirent * )( ( char * )p + reclen ), reclen = ( size_t )p->d_reclen ) { xfs_bstat_t statbuf; assert( scrval == 0 ); assert( cbrval == 0 ); /* skip "." and ".." */ if ( *( p->d_name + 0 ) == '.' && ( *( p->d_name + 1 ) == 0 || ( *( p->d_name + 1 ) == '.' && *( p->d_name + 2 ) == 0 ))) { continue; } /* use bigstat */ scrval = bigstat_one( fsfd, p->d_ino, &statbuf ); if ( scrval ) { mlog( MLOG_NORMAL, _("WARNING: could not stat " "dirent %s ino %llu: %s\n"), p->d_name, ( xfs_ino_t )p->d_ino, strerror( errno )); scrval = 0; continue; } /* if getdents64() not yet available, and ino * occupied more than 32 bits, warn and skip. */ #ifndef __USE_LARGEFILE64 if ( statbuf.bs_ino > ( xfs_ino_t )INOMAX ) { mlog( MLOG_NORMAL, _("WARNING: unable to process dirent %s: " "ino %llu too large\n"), p->d_name, ( xfs_ino_t )p->d_ino ); continue; } #endif /* invoke the callback */ cbrval = ( * cbfp )( arg1, fshandlep, fsfd, &statbuf, p->d_name ); /* abort the iteration if the callback returns non-zero */ if ( cbrval ) { break; } } if ( scrval || cbrval ) { break; } } ( void )close( fd ); if ( ! usrgdp ) { free( ( void * )gdp ); } if ( scrval ) { *cbrvalp = 0; return -1; } else if ( cbrval ) { *cbrvalp = cbrval; return 1; } else { *cbrvalp = 0; return 0; } } int cvtnum( int blocksize, char *s ) { int i; char *sp; i = (int)strtoll(s, &sp, 0); if (i == 0 && sp == s) return -1; if (*sp == '\0') return i; if (*sp == 'b' && blocksize && sp[1] == '\0') return i * blocksize; if (*sp == 'k' && sp[1] == '\0') return 1024 * i; if (*sp == 'm' && sp[1] == '\0') return 1024 * 1024 * i; return -1; } xfsdump-3.1.6+nmu1/common/media.h0000644000000000000000000000627712620476160013511 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef MEDIA_H #define MEDIA_H /* media.[hc] - media abstraction */ /* media_hdr_t - media file header * * This header structure will be placed at the beginning of the * media object files by the drive manager do_begin_write() operator, * and will be extracted from the beginnining of the media object files by * the do_begin_read() operator. A media header_t has three parts: generally * useful info, media strategy-specific info, and upper layer info. The hdr * argument of the mo_begin_write() operator will be stuffed into the * upper layer info, and extracted for the upper layer by mo_begin_read(). */ #define MEDIA_HDR_SZ sizeofmember( drive_hdr_t, dh_upper ) struct media_hdr { char mh_medialabel[ GLOBAL_HDR_STRING_SZ ]; /* 100 100 */ /* label of media object containing file */ char mh_prevmedialabel[ GLOBAL_HDR_STRING_SZ ]; /* 100 200 */ /* label of upstream media object */ char mh_pad1[ GLOBAL_HDR_STRING_SZ ]; /* 100 300 */ /* in case more labels needed */ uuid_t mh_mediaid; /* 10 310 */ /* ID of media object */ uuid_t mh_prevmediaid; /* 10 320 */ /* ID of upstream media object */ char mh_pad2[ GLOBAL_HDR_UUID_SZ ]; /* 10 330 */ /* in case more IDs needed */ uint32_t mh_mediaix; /* 4 334 */ /* 0-based index of this media object within the dump stream */ uint32_t mh_mediafileix; /* 4 338 */ /* 0-based index of this file within this media object */ uint32_t mh_dumpfileix; /* 4 33c */ /* 0-based index of this file within this dump stream */ uint32_t mh_dumpmediafileix; /* 4 340 */ /* 0-based index of file within dump stream and media object */ uint32_t mh_dumpmediaix; /* 4 344 */ /* 0-based index of this dump within the media object */ int32_t mh_strategyid; /* 4 348 */ /* ID of the media strategy used to produce this dump */ char mh_pad3[ 0x38 ]; /* 38 380 */ /* padding */ char mh_specific[ 0x80 ]; /* 80 400 */ /* media strategy-specific info */ char mh_upper[ MEDIA_HDR_SZ - 0x400 ]; /* 400 800 */ /* header info private to upper software layers */ }; typedef struct media_hdr media_hdr_t; /* macros to mark a media file as a terminator. artifact of original * media_rmvtape media strategy */ #define MEDIA_TERMINATOR_CHK( mrhp ) ( mrhp->mh_specific[ 0 ] & 1 ) #define MEDIA_TERMINATOR_SET( mwhp ) ( mwhp->mh_specific[ 0 ] |= 1 ) /* media strategy IDs. artifactis of first version of xfsdump */ #define MEDIA_STRATEGY_SIMPLE 0 #define MEDIA_STRATEGY_RMVTAPE 1 #endif /* MEDIA_H */ xfsdump-3.1.6+nmu1/common/openutil.h0000644000000000000000000000424012620476160014255 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef OPENUTIL_H #define OPENUTIL_H /* openutil.[hc] - useful functions for opening tmp and housekeeping * files. */ /* allocate and fill a character sting buffer with a pathname generated * by catenating the dir and base args. if pid is non-zero, the decimal * representation of the pid will be appended to the pathname, beginning * with a '.'. */ extern char *open_pathalloc( char *dirname, char *basename, pid_t pid ); /* create the specified file, creating or truncating as necessary, * with read and write permissions, given a directory and base. * return the file descriptor, or -1 with errno set. uses mlog( MLOG_NORMAL... * if the creation fails. */ extern int open_trwdb( char *dirname, char *basename, pid_t pid ); extern int open_trwp( char *pathname ); /* open the specified file, with read and write permissions, given a * directory and base.* return the file descriptor, or -1 with errno set. * uses mlog( MLOG_NORMAL... if the open fails. */ extern int open_rwdb( char *dirname, char *basename, pid_t pid ); extern int open_rwp( char *pathname ); /* create and open the specified file, failing if already exists */ extern int open_erwp( char *pathname ); extern int open_erwdb( char *dirname, char *basename, pid_t pid ); /* create the specified directory, guaranteed to be initially empty. returns * 0 on success, -1 if trouble. uses mlog( MLOG_NORMAL... if the creation fails. */ extern int mkdir_tp( char *pathname ); #endif /* UTIL_H */ xfsdump-3.1.6+nmu1/common/arch_xlate.c0000644000000000000000000003731412620476160014533 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include "config.h" #include "arch_xlate.h" #include "types.h" #include "global.h" #include "content.h" #include "content_inode.h" #include "drive.h" #include "media.h" #include "inomap.h" #include "rec_hdr.h" #include "inv_priv.h" #include "mlog.h" #define IXLATE(a1,a2,MEMBER) \ INT_XLATE((a1)->MEMBER, (a2)->MEMBER, dir, ARCH_CONVERT) #define BXLATE(MEMBER) \ bcopy(&(ptr1)->MEMBER, &(ptr2)->MEMBER, sizeof((ptr1)->MEMBER)) /* * xlate_global_hdr - endian convert struct global_hdr * * Note: gh_upper field is not converted. This must be done elsewhere * at the time of assignment, because its contents are unknown. */ void xlate_global_hdr(global_hdr_t *gh1, global_hdr_t *gh2, int dir) { global_hdr_t *ptr1 = gh1; global_hdr_t *ptr2 = gh2; IXLATE(gh1, gh2, gh_version); IXLATE(gh1, gh2, gh_timestamp); IXLATE(gh1, gh2, gh_ipaddr); IXLATE(gh1, gh2, gh_checksum); if (dir < 0) { ptr1 = gh2; ptr2 = gh1; } BXLATE(gh_magic); BXLATE(gh_dumpid); BXLATE(gh_hostname); BXLATE(gh_dumplabel); BXLATE(gh_upper); BXLATE(gh_pad1); BXLATE(gh_pad2); BXLATE(gh_pad3); mlog(MLOG_NITTY, "xlate_global_hdr: pre-xlate\n" "\tgh_magic %.100s\n" "\tgh_version %u\n" "\tgh_checksum %u\n" "\tgh_timestamp %u\n" "\tgh_ipaddr %llu\n" "\tgh_hostname %.100s\n" "\tgh_dumplabel %.100s\n", ptr1->gh_magic, ptr1->gh_version, ptr1->gh_checksum, ptr1->gh_timestamp, ptr1->gh_ipaddr, ptr1->gh_hostname, ptr1->gh_dumplabel); mlog(MLOG_NITTY, "xlate_global_hdr: post-xlate\n" "\tgh_magic %.100s\n" "\tgh_version %u\n" "\tgh_checksum %u\n" "\tgh_timestamp %u\n" "\tgh_ipaddr %llu\n" "\tgh_hostname %.100s\n" "\tgh_dumplabel %.100s\n", ptr2->gh_magic, ptr2->gh_version, ptr2->gh_checksum, ptr2->gh_timestamp, ptr2->gh_ipaddr, ptr2->gh_hostname, ptr2->gh_dumplabel); } /* * xlate_drive_hdr - endian convert struct xlate_drive_hdr * which is loaded into global_hdr.gh_upper */ void xlate_drive_hdr(drive_hdr_t *dh1, drive_hdr_t *dh2, int dir) { drive_hdr_t *ptr1 = dh1; drive_hdr_t *ptr2 = dh2; IXLATE(dh1, dh2, dh_drivecnt); IXLATE(dh1, dh2, dh_driveix); IXLATE(dh1, dh2, dh_strategyid); if (dir < 0) { ptr1 = dh2; ptr2 = dh1; } BXLATE(dh_pad1); BXLATE(dh_specific); BXLATE(dh_upper); mlog(MLOG_NITTY, "xlate_drive_hdr: pre-xlate\n" "\tdh_drivecnt %u\n" "\tdh_driveix %u\n" "\tdh_strategyid %d\n" "\tdh_pad1 %s\n" "\tdh_specific %s\n" "\tdh_upper %s\n", ptr1->dh_drivecnt, ptr1->dh_driveix, ptr1->dh_strategyid, ptr1->dh_pad1, ptr1->dh_specific, ptr1->dh_upper); mlog(MLOG_NITTY, "xlate_drive_hdr: post-xlate\n" "\tdh_drivecnt %u\n" "\tdh_driveix %u\n" "\tdh_strategyid %d\n" "\tdh_pad1 %s\n" "\tdh_specific %s\n" "\tdh_upper %s\n", ptr2->dh_drivecnt, ptr2->dh_driveix, ptr2->dh_strategyid, ptr2->dh_pad1, ptr2->dh_specific, ptr2->dh_upper); } /* * xlate_media_hdr - endian convert struct media_hdr * which is loaded into drive_hdr.dh_upper */ void xlate_media_hdr(media_hdr_t *mh1, media_hdr_t *mh2, int dir) { media_hdr_t *ptr1 = mh1; media_hdr_t *ptr2 = mh2; mlog(MLOG_NITTY, "xlate_media_hdr\n"); IXLATE(mh1, mh2, mh_mediaix); IXLATE(mh1, mh2, mh_mediafileix); IXLATE(mh1, mh2, mh_dumpfileix); IXLATE(mh1, mh2, mh_dumpmediafileix); IXLATE(mh1, mh2, mh_dumpmediaix); IXLATE(mh1, mh2, mh_strategyid); if (dir < 0) { ptr1 = mh2; ptr2 = mh1; } BXLATE(mh_medialabel); BXLATE(mh_prevmedialabel); BXLATE(mh_pad1); BXLATE(mh_mediaid); BXLATE(mh_prevmediaid); BXLATE(mh_pad2); BXLATE(mh_pad3); BXLATE(mh_specific); BXLATE(mh_upper); } /* * xlate_content_hdr - endian convert struct content_hdr * which is loaded into media_hdr.mh_upper */ void xlate_content_hdr(content_hdr_t *ch1, content_hdr_t *ch2, int dir) { content_hdr_t *ptr1 = ch1; content_hdr_t *ptr2 = ch2; mlog(MLOG_NITTY, "xlate_content_hdr\n"); IXLATE(ch1, ch2, ch_strategyid); if (dir < 0) { ptr1 = ch2; ptr2 = ch1; } BXLATE(ch_mntpnt); BXLATE(ch_fsdevice); BXLATE(ch_pad1); BXLATE(ch_fstype); BXLATE(ch_fsid); BXLATE(ch_pad2); BXLATE(ch_pad3); BXLATE(ch_pad4); BXLATE(ch_specific); } /* * xlate_content_inode_hdr - endian convert struct content_inode_hdr * which is loaded into content_hdr.ch_specific */ void xlate_content_inode_hdr(content_inode_hdr_t *cih1, content_inode_hdr_t *cih2, int dir) { content_inode_hdr_t *ptr1 = cih1; content_inode_hdr_t *ptr2 = cih2; mlog(MLOG_NITTY, "xlate_content_inode_hdr\n"); IXLATE(cih1, cih2, cih_mediafiletype); IXLATE(cih1, cih2, cih_dumpattr); IXLATE(cih1, cih2, cih_level); IXLATE(cih1, cih2, cih_last_time); IXLATE(cih1, cih2, cih_resume_time); IXLATE(cih1, cih2, cih_rootino); IXLATE(cih1, cih2, cih_inomap_hnkcnt); IXLATE(cih1, cih2, cih_inomap_segcnt); IXLATE(cih1, cih2, cih_inomap_dircnt); IXLATE(cih1, cih2, cih_inomap_nondircnt); IXLATE(cih1, cih2, cih_inomap_firstino); IXLATE(cih1, cih2, cih_inomap_lastino); IXLATE(cih1, cih2, cih_inomap_datasz); if (dir < 0) { ptr1 = cih2; ptr2 = cih1; } BXLATE(pad1); BXLATE(cih_last_id); BXLATE(cih_resume_id); BXLATE(cih_pad2); xlate_startpt(&cih1->cih_startpt, &cih2->cih_startpt, dir); xlate_startpt(&cih1->cih_endpt, &cih2->cih_endpt, dir); } /* * xlate_startpt - endian convert struct startpt */ void xlate_startpt(startpt_t *sp1, startpt_t *sp2, int dir) { mlog(MLOG_NITTY, "xlate_startpt\n"); IXLATE(sp1, sp2, sp_ino); IXLATE(sp1, sp2, sp_offset); IXLATE(sp1, sp2, sp_flags); IXLATE(sp1, sp2, sp_pad1); } /* * xlate_hnk - endian convert struct hnk * Note: struct hnk is defined in 3 different inomap.c files but they're * all the same. */ void xlate_hnk(hnk_t *h1, hnk_t *h2, int dir) { hnk_t *ptr1 = h1; hnk_t *ptr2 = h2; int i; mlog(MLOG_NITTY, "pre - xlate_hnk\n"); for(i = 0; i < SEGPERHNK; i++) { IXLATE(h1, h2, seg[i].base); IXLATE(h1, h2, seg[i].lobits); IXLATE(h1, h2, seg[i].mebits); IXLATE(h1, h2, seg[i].hibits); } IXLATE(h1, h2, maxino); h2->nextp = NULL; if (dir < 0) { ptr1 = h2; ptr2 = h1; } BXLATE(pad); mlog(MLOG_NITTY, "post - xlate_hnk\n"); } /* * xlate_filehdr - endian convert struct filehdr */ void xlate_filehdr(filehdr_t *fh1, filehdr_t *fh2, int dir) { filehdr_t *ptr1 = fh1; filehdr_t *ptr2 = fh2; IXLATE(fh1, fh2, fh_offset); IXLATE(fh1, fh2, fh_flags); IXLATE(fh1, fh2, fh_checksum); xlate_bstat(&fh1->fh_stat, &fh2->fh_stat, dir); if (dir < 0) { ptr1 = fh2; ptr2 = fh1; } BXLATE(fh_pad2); mlog(MLOG_NITTY, "xlate_filehdr: pre-xlate\n" "\tfh_offset %llu\n" "\tfh_flags %llu\n" "\tfh_checksum %llu\n", ptr1->fh_offset, ptr1->fh_flags, ptr1->fh_checksum); mlog(MLOG_NITTY, "xlate_filehdr: post-xlate\n" "\tfh_offset %llu\n" "\tfh_flags %llu\n" "\tfh_checksum %llu\n", ptr2->fh_offset, ptr2->fh_flags, ptr2->fh_checksum); } /* * xlate_bstat - endian convert struct bstat */ void xlate_bstat(bstat_t *bs1, bstat_t *bs2, int dir) { bstat_t *ptr1 = bs1; bstat_t *ptr2 = bs2; mlog(MLOG_NITTY, "xlate_bstat\n"); IXLATE(bs1, bs2, bs_ino); IXLATE(bs1, bs2, bs_mode); IXLATE(bs1, bs2, bs_nlink); IXLATE(bs1, bs2, bs_uid); IXLATE(bs1, bs2, bs_gid); IXLATE(bs1, bs2, bs_rdev); IXLATE(bs1, bs2, bs_blksize); IXLATE(bs1, bs2, bs_size); IXLATE(bs1, bs2, bs_atime.tv_sec); IXLATE(bs1, bs2, bs_atime.tv_nsec); IXLATE(bs1, bs2, bs_mtime.tv_sec); IXLATE(bs1, bs2, bs_mtime.tv_nsec); IXLATE(bs1, bs2, bs_ctime.tv_sec); IXLATE(bs1, bs2, bs_ctime.tv_nsec); IXLATE(bs1, bs2, bs_blocks); IXLATE(bs1, bs2, bs_xflags); IXLATE(bs1, bs2, bs_extsize); IXLATE(bs1, bs2, bs_extents); IXLATE(bs1, bs2, bs_gen); IXLATE(bs1, bs2, bs_projid_lo); IXLATE(bs1, bs2, bs_forkoff); IXLATE(bs1, bs2, bs_projid_hi); IXLATE(bs1, bs2, bs_dmevmask); IXLATE(bs1, bs2, bs_dmstate); if (dir < 0) { ptr1 = bs2; ptr2 = bs1; } BXLATE(bs_pad); BXLATE(bs_pad1); mlog(MLOG_NITTY, "xlate_bstat: pre-xlate\n" "\tbs_ino %llu\n" "\tbs_mode %lo\n", ptr1->bs_ino, ptr1->bs_mode); mlog(MLOG_NITTY, "xlate_bstat: post-xlate\n" "\tbs_ino %llu\n" "\tbs_mode %lo\n", ptr2->bs_ino, ptr2->bs_mode); } /* * xlate_extenthdr - endian convert struct extenthdr */ void xlate_extenthdr(extenthdr_t *eh1, extenthdr_t *eh2, int dir) { extenthdr_t *ptr1 = eh1; extenthdr_t *ptr2 = eh2; mlog(MLOG_NITTY, "xlate_extenthdr\n"); IXLATE(eh1, eh2, eh_sz); IXLATE(eh1, eh2, eh_offset); IXLATE(eh1, eh2, eh_type); IXLATE(eh1, eh2, eh_flags); IXLATE(eh1, eh2, eh_checksum); if (dir < 0) { ptr1 = eh2; ptr2 = eh1; } BXLATE(eh_pad); } /* * xlate_direnthdr - endian convert struct direnthdr */ void xlate_direnthdr(direnthdr_t *dh1, direnthdr_t *dh2, int dir) { direnthdr_t *ptr1 = dh1; direnthdr_t *ptr2 = dh2; IXLATE(dh1, dh2, dh_ino); IXLATE(dh1, dh2, dh_gen); IXLATE(dh1, dh2, dh_checksum); IXLATE(dh1, dh2, dh_sz); if (dir < 0) { ptr1 = dh2; ptr2 = dh1; } BXLATE(dh_name); mlog(MLOG_NITTY, "xlate_direnthdr: pre-xlate\n" "\tdh_ino %llu\n" "\tdh_gen %u\n" "\tdh_checksum %d\n" "\tdh_sz %d\n" "\tdh_name %.8s\n", ptr1->dh_ino, ptr1->dh_gen, ptr1->dh_checksum, ptr1->dh_sz, ptr1->dh_name ); mlog(MLOG_NITTY, "xlate_direnthdr: post-xlate\n" "\tdh_ino %llu\n" "\tdh_gen %u\n" "\tdh_checksum %d\n" "\tdh_sz %d\n" "\tdh_name %.8s\n", ptr2->dh_ino, ptr2->dh_gen, ptr2->dh_checksum, ptr2->dh_sz, ptr2->dh_name ); } /* * xlate_direnthdr_v1 - endian convert struct direnthdr_v1 */ void xlate_direnthdr_v1(direnthdr_v1_t *dh1, direnthdr_v1_t *dh2, int dir) { direnthdr_v1_t *ptr1 = dh1; direnthdr_v1_t *ptr2 = dh2; IXLATE(dh1, dh2, dh_ino); IXLATE(dh1, dh2, dh_gen); IXLATE(dh1, dh2, dh_sz); IXLATE(dh1, dh2, dh_checksum); if (dir < 0) { ptr1 = dh2; ptr2 = dh1; } BXLATE(dh_name); mlog(MLOG_NITTY, "xlate_direnthdr_v1: pre-xlate\n" "\tdh_ino %llu\n" "\tdh_gen %u\n" "\tdh_sz %d\n" "\tdh_checksum %d\n" "\tdh_name %.8s\n", ptr1->dh_ino, ptr1->dh_gen, ptr1->dh_sz, ptr1->dh_checksum, ptr1->dh_name ); mlog(MLOG_NITTY, "xlate_direnthdr_v1: post-xlate\n" "\tdh_ino %llu\n" "\tdh_gen %u\n" "\tdh_sz %d\n" "\tdh_checksum %d\n" "\tdh_name %.8s\n", ptr2->dh_ino, ptr2->dh_gen, ptr2->dh_sz, ptr2->dh_checksum, ptr2->dh_name ); } /* * xlate_extattrhdr - endian convert struct extattrhdr */ void xlate_extattrhdr(extattrhdr_t *eh1, extattrhdr_t *eh2, int dir) { mlog(MLOG_NITTY, "xlate_extattrhdr\n"); IXLATE(eh1, eh2, ah_sz); IXLATE(eh1, eh2, ah_valoff); IXLATE(eh1, eh2, ah_flags); IXLATE(eh1, eh2, ah_valsz); IXLATE(eh1, eh2, ah_checksum); } /* * xlate_rec_hdr - endian convert struct rec_hdr */ void xlate_rec_hdr(rec_hdr_t *rh1, rec_hdr_t *rh2, int dir) { rec_hdr_t *ptr1 = rh1; rec_hdr_t *ptr2 = rh2; mlog(MLOG_NITTY, "xlate_rec_hdr\n"); IXLATE(rh1, rh2, magic); IXLATE(rh1, rh2, version); IXLATE(rh1, rh2, blksize); IXLATE(rh1, rh2, recsize); IXLATE(rh1, rh2, capability); IXLATE(rh1, rh2, file_offset); IXLATE(rh1, rh2, first_mark_offset); IXLATE(rh1, rh2, rec_used); IXLATE(rh1, rh2, checksum); IXLATE(rh1, rh2, ischecksum); if (dir < 0) { ptr1 = rh2; ptr2 = rh1; } BXLATE(pad1); BXLATE(dump_uuid); BXLATE(pad2); mlog(MLOG_NITTY, "xlate_rec_hdr: pre-xlate\n" "\tmagic %llu\n" "\tversion %d\n" "\tblksize %d\n" "\trecsize %d\n" "\tcapability %d\n" "\tfile_offset %lld\n" "\tfirst_mark_offset %lld\n" "\trec_used %u\n" "\tchecksum %d\n" "\tischecksum %d\n", ptr1->magic, ptr1->version, ptr1->blksize, ptr1->recsize, ptr1->capability, ptr1->file_offset, ptr1->first_mark_offset, ptr1->rec_used, ptr1->checksum, ptr1->ischecksum); mlog(MLOG_NITTY, "xlate_rec_hdr: post-xlate\n" "\tmagic %llu\n" "\tversion %d\n" "\tblksize %d\n" "\trecsize %d\n" "\tcapability %d\n" "\tfile_offset %lld\n" "\tfirst_mark_offset %lld\n" "\trec_used %u\n" "\tchecksum %d\n" "\tischecksum %d\n", ptr2->magic, ptr2->version, ptr2->blksize, ptr2->recsize, ptr2->capability, ptr2->file_offset, ptr2->first_mark_offset, ptr2->rec_used, ptr2->checksum, ptr2->ischecksum); } /* * endian convert inventory structures */ void xlate_invt_seshdr(invt_seshdr_t *ish1, invt_seshdr_t *ish2, int dir) { invt_seshdr_t *ptr1 = ish1; invt_seshdr_t *ptr2 = ish2; mlog(MLOG_NITTY, "xlate_invt_seshdr\n"); IXLATE(ish1, ish2, sh_sess_off); IXLATE(ish1, ish2, sh_streams_off); IXLATE(ish1, ish2, sh_time); IXLATE(ish1, ish2, sh_flag); if (dir < 0) { ptr1 = ish2; ptr2 = ish1; } BXLATE(sh_level); BXLATE(sh_pruned); BXLATE(sh_padding); } void xlate_invt_session(invt_session_t *is1, invt_session_t *is2, int dir) { invt_session_t *ptr1 = is1; invt_session_t *ptr2 = is2; mlog(MLOG_NITTY, "xlate_invt_session\n"); IXLATE(is1, is2, s_cur_nstreams); IXLATE(is1, is2, s_max_nstreams); if (dir < 0) { ptr1 = is2; ptr2 = is1; } BXLATE(s_sesid); BXLATE(s_fsid); BXLATE(s_label); BXLATE(s_mountpt); BXLATE(s_devpath); BXLATE(s_padding); mlog(MLOG_NITTY, "xlate_invt_session: pre-xlate\n" "\ts_cur_nstreams %u\n" "\ts_max_nstreams %u\n", ptr1->s_cur_nstreams, ptr1->s_max_nstreams); mlog(MLOG_NITTY, "xlate_invt_session: post-xlate\n" "\ts_cur_nstreams %u\n" "\ts_max_nstreams %u\n", ptr2->s_cur_nstreams, ptr2->s_max_nstreams); } void xlate_invt_breakpt(invt_breakpt_t *ib1, invt_breakpt_t *ib2, int dir) { mlog(MLOG_NITTY, "xlate_invt_breakpt\n"); IXLATE(ib1, ib2, ino); IXLATE(ib1, ib2, offset); } void xlate_invt_stream(invt_stream_t *ist1, invt_stream_t *ist2, int dir) { invt_stream_t *ptr1 = ist1; invt_stream_t *ptr2 = ist2; mlog(MLOG_NITTY, "xlate_invt_stream\n"); IXLATE(ist1, ist2, st_firstmfile); IXLATE(ist1, ist2, st_lastmfile); IXLATE(ist1, ist2, st_nmediafiles); IXLATE(ist1, ist2, st_interrupted); if (dir < 0) { ptr1 = ist2; ptr2 = ist1; } BXLATE(st_cmdarg); BXLATE(st_padding); xlate_invt_breakpt(&ist1->st_startino, &ist2->st_startino, dir); xlate_invt_breakpt(&ist1->st_endino, &ist2->st_endino, dir); } void xlate_invt_mediafile(invt_mediafile_t *im1, invt_mediafile_t *im2, int dir) { invt_mediafile_t *ptr1 = im1; invt_mediafile_t *ptr2 = im2; mlog(MLOG_NITTY, "xlate_invt_mediafile\n"); IXLATE(im1, im2, mf_nextmf); IXLATE(im1, im2, mf_prevmf); IXLATE(im1, im2, mf_mfileidx); IXLATE(im1, im2, mf_size); if (dir < 0) { ptr1 = im2; ptr2 = im1; } BXLATE(mf_moid); BXLATE(mf_label); BXLATE(mf_flag); BXLATE(mf_padding); xlate_invt_breakpt(&im1->mf_startino, &im2->mf_startino, dir); xlate_invt_breakpt(&im1->mf_endino, &im2->mf_endino, dir); } xfsdump-3.1.6+nmu1/common/content_common.h0000644000000000000000000000153212607344125015441 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef CONTENT_COMMON_H #define CONTENT_COMMON_H extern bool_t Media_prompt_change( drive_t *drivep ); #endif /* CONTENT_COMMON_H */ xfsdump-3.1.6+nmu1/common/dlog.c0000644000000000000000000002724112620476160013344 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "types.h" #include "mlog.h" #include "dlog.h" #include "getopt.h" static int dlog_ttyfd = -1; static volatile bool_t dlog_allowed_flag = BOOL_FALSE; static bool_t dlog_timeouts_flag = BOOL_FALSE; static char *promptstr = " -> "; static sigset_t dlog_registered_sigs; static bool_t promptinput( char *buf, size_t bufsz, ix_t *exceptionixp, time32_t timeout, ix_t timeoutix, ix_t sigintix, ix_t sighupix, ix_t sigquitix, char *fmt, ... ); static void dlog_string_query_print( void *ctxp, char *fmt, ... ); bool_t dlog_init( int argc, char *argv[ ] ) { int c; /* can only call once */ assert( dlog_ttyfd == -1 ); /* initially allow dialog, use stdin fd */ dlog_ttyfd = 0; /* stdin */ dlog_allowed_flag = BOOL_TRUE; dlog_timeouts_flag = BOOL_TRUE; sigemptyset( &dlog_registered_sigs ); /* look for command line option claiming the operator knows * what's up. */ optind = 1; opterr = 0; while ( ( c = getopt( argc, argv, GETOPT_CMDSTRING )) != EOF ) { switch ( c ) { case GETOPT_FORCE: dlog_ttyfd = -1; dlog_allowed_flag = BOOL_FALSE; break; case GETOPT_NOTIMEOUTS: dlog_timeouts_flag = BOOL_FALSE; break; } } #ifdef RESTORE /* look to see if restore source coming in on * stdin. If so , try to open /dev/tty for dialogs. */ if ( optind < argc && ! strcmp( argv[ optind ], "-" )) { dlog_ttyfd = open( "/dev/tty", O_RDWR ); if ( dlog_ttyfd < 0 ) { perror("/dev/tty"); dlog_ttyfd = -1; dlog_allowed_flag = BOOL_FALSE; } } #endif /* RESTORE */ #ifdef CHKSTDIN /* if stdin is not a tty, don't allow dialogs */ if ( dlog_allowed_flag ) { struct stat statbuf; int rval; assert( dlog_ttyfd >= 0 ); rval = fstat( dlog_ttyfd, &statbuf ); if ( rval ) { mlog( MLOG_VERBOSE | MLOG_WARNING, _("could not fstat stdin (fd %d): %s (%d)\n"), dlog_ttyfd, strerror( errno ), errno ); } else { mlog( MLOG_DEBUG, "stdin mode 0x%x\n", statbuf.st_mode ); } } #endif /* CHKSTDIN */ return BOOL_TRUE; } bool_t dlog_allowed( void ) { return dlog_allowed_flag; } void dlog_desist( void ) { dlog_allowed_flag = BOOL_FALSE; } int dlog_fd( void ) { return dlog_ttyfd; } void dlog_begin( char *preamblestr[ ], size_t preamblecnt ) { size_t ix; mlog_lock( ); for ( ix = 0 ; ix < preamblecnt ; ix++ ) { mlog( MLOG_NORMAL | MLOG_NOLOCK | MLOG_BARE, preamblestr[ ix ] ); } } void dlog_end( char *postamblestr[ ], size_t postamblecnt ) { size_t ix; for ( ix = 0 ; ix < postamblecnt ; ix++ ) { mlog( MLOG_NORMAL | MLOG_NOLOCK | MLOG_BARE, postamblestr[ ix ] ); } mlog_unlock( ); } ix_t dlog_multi_query( char *querystr[ ], size_t querycnt, char *choicestr[ ], size_t choicecnt, char *hilitestr, size_t hiliteix, char *defaultstr, ix_t defaultix, time32_t timeout, ix_t timeoutix, ix_t sigintix, ix_t sighupix, ix_t sigquitix ) { size_t ix; char buf[ 100 ]; char *prepromptstr; /* sanity */ assert( dlog_allowed_flag ); /* display query description strings */ for ( ix = 0 ; ix < querycnt ; ix++ ) { mlog( MLOG_NORMAL | MLOG_NOLOCK | MLOG_BARE, querystr[ ix ] ); } /* display the choices: NOTE: display is 1-based, code intfs 0-based! */ for ( ix = 0 ; ix < choicecnt ; ix++ ) { mlog( MLOG_NORMAL | MLOG_NOLOCK | MLOG_BARE, "%u: %s", ix + 1, choicestr[ ix ] ); if ( ix == hiliteix ) { mlog( MLOG_NORMAL | MLOG_NOLOCK | MLOG_BARE, "%s", hilitestr ? hilitestr : " *" ); } if ( ix == defaultix ) { mlog( MLOG_NORMAL | MLOG_NOLOCK | MLOG_BARE, "%s", defaultstr ? defaultstr : _(" (default)") ); } if ( dlog_timeouts_flag && timeoutix != IXMAX && ix == timeoutix ) { mlog( MLOG_NORMAL | MLOG_NOLOCK | MLOG_BARE, _(" (timeout in %u sec)"), timeout ); } mlog( MLOG_NORMAL | MLOG_NOLOCK | MLOG_BARE, "\n" ); } /* read the tty until we get a proper answer or are interrupted */ prepromptstr = ""; for ( ; ; ) { ix_t exceptionix; bool_t ok; /* prompt and accept input */ ok = promptinput( buf, sizeof( buf ), &exceptionix, timeout, timeoutix, sigintix, sighupix, sigquitix, prepromptstr, choicecnt ); if ( ok ) { long int val; char *end = buf; if ( ! strlen( buf )) { return defaultix; } val = strtol( buf, &end, 10 ); if ( *end != '\0' || val < 1 || val > choicecnt ) { prepromptstr = _( "please enter a value " "between 1 and %d inclusive "); continue; } return val - 1; // return value is a 0-based index } else { return exceptionix; } } /* NOTREACHED */ } void dlog_multi_ack( char *ackstr[ ], size_t ackcnt ) { size_t ix; for ( ix = 0 ; ix < ackcnt ; ix++ ) { mlog( MLOG_NORMAL | MLOG_NOLOCK | MLOG_BARE, ackstr[ ix ] ); } } ix_t dlog_string_query( dlog_ucbp_t ucb, /* user's print func */ void *uctxp, /* user's context for above */ char *bufp, /* typed string returned in */ size_t bufsz, /* buffer size */ time32_t timeout, /* secs b4 giving up */ ix_t timeoutix, ix_t sigintix, ix_t sighupix, ix_t sigquitix, ix_t okix ) { ix_t exceptionix; bool_t ok; /* sanity */ assert( dlog_allowed_flag ); /* call the caller's callback with his context, print context, and * print operator */ ( * ucb )( uctxp, dlog_string_query_print, 0 ); /* if called for, print the timeout and a newline. * if not, print just a newline */ if ( dlog_timeouts_flag && timeoutix != IXMAX ) { mlog( MLOG_NORMAL | MLOG_NOLOCK | MLOG_BARE, _(" (timeout in %u sec)\n"), timeout ); } else { mlog( MLOG_NORMAL | MLOG_NOLOCK | MLOG_BARE, "\n" ); } /* prompt and accept input */ ok = promptinput( bufp, bufsz, &exceptionix, timeout, timeoutix, sigintix, sighupix, sigquitix, "" ); if ( ok ) { return okix; } else { return exceptionix; } } void dlog_string_ack( char *ackstr[ ], size_t ackcnt ) { dlog_multi_ack( ackstr, ackcnt ); } /* ok that this is a static, since used under mutual exclusion lock */ static volatile int dlog_signo_received; bool_t dlog_sighandler( int signo ) { if ( sigismember( &dlog_registered_sigs, signo ) < 1 ) return BOOL_FALSE; // only process the first signal sigemptyset( &dlog_registered_sigs ); dlog_signo_received = signo; return BOOL_TRUE; } /* ARGSUSED */ static void dlog_string_query_print( void *ctxp, char *fmt, ... ) { va_list args; assert( ! ctxp ); va_start( args, fmt ); mlog_va( MLOG_NORMAL | MLOG_NOLOCK | MLOG_BARE, fmt, args ); va_end( args ); } static bool_t promptinput( char *buf, size_t bufsz, ix_t *exceptionixp, time32_t timeout, ix_t timeoutix, ix_t sigintix, ix_t sighupix, ix_t sigquitix, char *fmt, ... ) { va_list args; time32_t now = time( NULL ); int nread = -1; sigset_t orig_set; char *bufp = buf; /* display the pre-prompt */ va_start( args, fmt ); mlog_va( MLOG_NORMAL | MLOG_NOLOCK | MLOG_BARE, fmt, args ); va_end( args ); /* display standard prompt */ #ifdef NOTYET if ( dlog_timeouts_flag && timeoutix != IXMAX ) { mlog( MLOG_NORMAL | MLOG_NOLOCK | MLOG_BARE, _("(timeout in %d sec)"), timeout ); } #endif /* NOTYET */ mlog( MLOG_NORMAL | MLOG_NOLOCK | MLOG_BARE, promptstr ); /* set up timeout */ if ( dlog_timeouts_flag && timeoutix != IXMAX ) { timeout += now; } else { timeout = TIMEMAX; } /* set up signal handling * the mlog lock is held for the life of the dialog (see dlog_begin) * and it's possible the main thread, which normally does the signal * handling, is now waiting on the mlog lock trying to log a message. * so unblock the relevant signals for this thread. note this means * the current thread or the main thread might handle one of these * signals. */ dlog_signo_received = -1; sigemptyset( &dlog_registered_sigs ); if ( sigintix != IXMAX ) { sigaddset( &dlog_registered_sigs, SIGINT ); } if ( sighupix != IXMAX ) { sigaddset( &dlog_registered_sigs, SIGHUP ); sigaddset( &dlog_registered_sigs, SIGTERM ); } if ( sigquitix != IXMAX ) { sigaddset( &dlog_registered_sigs, SIGQUIT ); } pthread_sigmask( SIG_UNBLOCK, &dlog_registered_sigs, &orig_set ); /* wait for input, timeout, or interrupt. * note we come out of the select() frequently in order to * check for a signal. the signal may have been handled by the * the main thread, so we can't rely on the signal waking us * up from the select(). */ while ( now < timeout && dlog_signo_received == -1 && dlog_allowed_flag ) { int rc; fd_set rfds; struct timeval tv = { 0, 100000 }; // 100 ms FD_ZERO( &rfds ); FD_SET( dlog_ttyfd, &rfds ); rc = select( dlog_ttyfd + 1, &rfds, NULL, NULL, &tv ); if ( rc > 0 && FD_ISSET( dlog_ttyfd, &rfds ) ) { nread = read( dlog_ttyfd, bufp, bufsz ); if ( nread < 0 ) { break; // error handled below } else if ( nread == 0 && buf == bufp ) { mlog( MLOG_NORMAL | MLOG_NOLOCK | MLOG_BARE, "\n" ); *bufp = 0; break; // no input, return an empty string } else if ( nread > 0 && bufp[nread-1] == '\n' ) { // received a full line, chomp the newline bufp[nread-1] = 0; break; } else if ( nread == bufsz ) { // no more room, truncate and return bufp[nread-1] = 0; break; } // keep waiting for a full line of input bufp += nread; bufsz -= nread; nread = -1; } now = time( NULL ); } /* restore signal handling */ pthread_sigmask( SIG_SETMASK, &orig_set, NULL ); sigemptyset( &dlog_registered_sigs ); /* check for timeout or interrupt */ if ( nread < 0 ) { if ( now >= timeout ) { mlog( MLOG_NORMAL | MLOG_NOLOCK | MLOG_BARE, _("timeout\n") ); *exceptionixp = timeoutix; } else if ( dlog_signo_received == SIGINT ) { mlog( MLOG_NORMAL | MLOG_NOLOCK | MLOG_BARE, _("keyboard interrupt\n") ); mlog_exit_hint(RV_KBD_INTR); *exceptionixp = sigintix; } else if ( dlog_signo_received == SIGHUP ) { mlog( MLOG_NORMAL | MLOG_NOLOCK | MLOG_BARE, _("hangup\n") ); *exceptionixp = sighupix; } else if ( dlog_signo_received == SIGTERM ) { mlog( MLOG_NORMAL | MLOG_NOLOCK | MLOG_BARE, _("terminate\n") ); *exceptionixp = sighupix; } else if ( dlog_signo_received == SIGQUIT ) { mlog( MLOG_NORMAL | MLOG_NOLOCK | MLOG_BARE, _("keyboard quit\n") ); mlog_exit_hint(RV_KBD_INTR); *exceptionixp = sigquitix; } else { mlog( MLOG_NORMAL | MLOG_NOLOCK | MLOG_BARE, _("abnormal dialog termination\n")); *exceptionixp = sigquitix; } return BOOL_FALSE; } else { assert( dlog_signo_received == -1 ); *exceptionixp = 0; return BOOL_TRUE; } } xfsdump-3.1.6+nmu1/common/drive_simple.c0000644000000000000000000012025112620476160015074 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* needed only for util.h include */ #include "config.h" #include "types.h" #include "util.h" /* needed onyl for I/O routines */ #include "stream.h" #include "mlog.h" #include "global.h" #include "drive.h" #include "media.h" #include "arch_xlate.h" /* this rmt junk is here because the rmt protocol supports writing ordinary * (non-device) files in the remote /dev directory! yuck! */ #define open rmtopen #define creat rmtcreat #define close rmtclose #define ioctl rmtioctl #define read rmtread #define write rmtwrite extern int rmtclose( int ); extern int rmtcreat (char *path, int mode); extern int rmtioctl( int, int, ... ); extern int rmtopen( char *, int, ... ); extern int rmtread( int, void*, uint); extern int rmtwrite( int, const void *, uint); /* drive_simple.c - drive strategy for standard in or a file */ /* structure definitions used locally ****************************************/ /* drive context - drive-specific context * buf must be page-aligned and at least 1 page in size */ #define PGPERBUF 64 /* private read buffer */ #define BUFSZ ( PGPERBUF * PGSZ ) /* operational mode */ typedef enum { OM_NONE, OM_READ, OM_WRITE } om_t; struct drive_context { char dc_buf[ BUFSZ ]; /* input/output buffer */ om_t dc_mode; /* current mode of operation */ ix_t dc_fmarkcnt; /* how many file marks to the left */ char *dc_ownedp; /* first byte owned by caller */ size_t dc_ownedsz; /* how much owned by caller (write only) */ char *dc_nextp; /* next byte avail. to read/write */ char *dc_emptyp; /* first empty slot in buffer */ off64_t dc_bufstroff; /* offset in stream of top of buf */ int dc_fd; /* input/output file descriptor */ drive_mark_t dc_firstmark;/* first mark's offset within mfile (dump) */ ix_t dc_markcnt; /* count of marks set (dump) */ bool_t dc_rampr; /* can randomly access file (not a pipe) */ bool_t dc_isrmtpr; /* is accessed via rmt */ bool_t dc_israwdevpr; /* is a raw disk partition */ }; typedef struct drive_context drive_context_t; /* declarations of externally defined global variables ***********************/ extern size_t pgsz; /* forward declarations of locally defined static functions ******************/ /* strategy functions */ static int ds_match( int, char *[], drive_t * ); static int ds_instantiate( int, char *[], drive_t * ); /* declare manager operators */ static bool_t do_init( drive_t * ); static bool_t do_sync( drive_t * ); static int do_begin_read( drive_t * ); static char *do_read( drive_t *, size_t , size_t *, int * ); static void do_return_read_buf( drive_t *, char *, size_t ); static void do_get_mark( drive_t *, drive_mark_t * ); static int do_seek_mark( drive_t *, drive_mark_t * ); static int do_next_mark( drive_t * ); static void do_get_mark( drive_t *, drive_mark_t * ); static void do_end_read( drive_t * ); static int do_begin_write( drive_t * ); static void do_set_mark( drive_t *, drive_mcbfp_t, void *, drive_markrec_t * ); static char * do_get_write_buf( drive_t *, size_t , size_t * ); static int do_write( drive_t *, char *, size_t ); static size_t do_get_align_cnt( drive_t * ); static int do_end_write( drive_t *, off64_t * ); static int do_rewind( drive_t * ); static int do_erase( drive_t * ); static int do_get_device_class( drive_t * ); static void do_quit( drive_t * ); /* definition of locally defined global variables ****************************/ /* simple drive strategy for file or stdin. referenced by drive.c */ drive_strategy_t drive_strategy_simple = { DRIVE_STRATEGY_SIMPLE, /* ds_id */ "file dump (drive_simple)", /* ds_description */ ds_match, /* ds_match */ ds_instantiate, /* ds_instantiate */ 0x1000000ll, /* ds_recmarksep */ OFF64MAX /* ds_recmfilesz */ }; /* definition of locally defined static variables *****************************/ /* drive operators */ static drive_ops_t drive_ops = { do_init, /* do_init */ do_sync, /* do_sync */ do_begin_read, /* do_begin_read */ do_read, /* do_read */ do_return_read_buf, /* do_return_read_buf */ do_get_mark, /* do_get_mark */ do_seek_mark, /* do_seek_mark */ do_next_mark, /* do_next_mark */ do_end_read, /* do_end_read */ do_begin_write, /* do_begin_write */ do_set_mark, /* do_set_mark */ do_get_write_buf, /* do_get_write_buf */ do_write, /* do_write */ do_get_align_cnt, /* do_get_align_cnt */ do_end_write, /* do_end_write */ 0, /* do_fsf */ 0, /* do_bsf */ do_rewind, /* do_rewind */ do_erase, /* do_erase */ 0, /* do_eject_media */ do_get_device_class, /* do_get_device_class */ 0, /* do_display_metrics */ do_quit, /* do_quit */ }; /* definition of locally defined global functions ****************************/ /* definition of locally defined static functions ****************************/ /* strategy match - determines if this is the right strategy */ /* ARGSUSED */ static int ds_match( int argc, char *argv[], drive_t *drivep ) { bool_t isrmtpr; struct stat64 statbuf; /* sanity checks */ assert( ! ( sizeofmember( drive_context_t, dc_buf ) % PGSZ )); /* determine if this is an rmt file. if so, give a weak match: * might be an ordinary file accessed via the rmt protocol. */ if ( strchr( drivep->d_pathname, ':') ) { isrmtpr = BOOL_TRUE; } else { isrmtpr = BOOL_FALSE; } if ( isrmtpr ) { return 1; } /* willing to pick up anything not picked up by other strategies, * as long as it exists and is not a directory */ if ( ! strcmp( drivep->d_pathname, "stdio" )) { return 1; } if ( stat64( drivep->d_pathname, &statbuf )) { return -1; } if ( S_ISDIR( statbuf.st_mode )) { return -1; } return 1; } /* strategy instantiate - initializes the pre-allocated drive descriptor */ /*ARGSUSED*/ static bool_t ds_instantiate( int argc, char *argv[], drive_t *drivep ) { drive_context_t *contextp; /* hook up the drive ops */ drivep->d_opsp = &drive_ops; /* initialize the drive context - allocate a page-aligned * structure, so the buffer is page-aligned. */ contextp = ( drive_context_t * )memalign( PGSZ, sizeof( drive_context_t )); assert( contextp ); assert( ( void * )contextp->dc_buf == ( void * )contextp ); memset( ( void * )contextp, 0, sizeof( *contextp )); /* scan drive device pathname to see if remote tape */ if ( strchr( drivep->d_pathname, ':') ) { contextp->dc_isrmtpr = BOOL_TRUE; } else { contextp->dc_isrmtpr = BOOL_FALSE; } /* determine drive capabilities of and open the named file. */ drivep->d_capabilities = 0; drivep->d_capabilities |= DRIVE_CAP_AUTOREWIND; if ( ! strcmp( drivep->d_pathname, "stdio" )) { #ifdef DUMP contextp->dc_fd = 1; #endif /* DUMP */ #ifdef RESTORE drivep->d_capabilities |= DRIVE_CAP_READ; contextp->dc_fd = 0; #endif /* RESTORE */ } else if ( contextp->dc_isrmtpr ) { int oflags; #ifdef DUMP oflags = O_WRONLY | O_CREAT | O_TRUNC; #endif /* DUMP */ #ifdef RESTORE oflags = O_RDONLY; drivep->d_capabilities |= DRIVE_CAP_READ; #endif /* RESTORE */ contextp->dc_rampr = BOOL_FALSE; contextp->dc_fd = open( drivep->d_pathname, oflags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ); if ( contextp->dc_fd < 0 ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_DRIVE, _("unable to open %s: %s\n"), drivep->d_pathname, strerror( errno )); return BOOL_FALSE; } } else { int oflags = 0; struct stat statbuf; int rval; rval = stat( drivep->d_pathname, &statbuf ); #ifdef DUMP if ( rval ) { if ( errno != ENOENT ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_DRIVE, _("stat of %s failed: %s\n"), drivep->d_pathname, strerror( errno )); return BOOL_FALSE; } drivep->d_capabilities |= DRIVE_CAP_REWIND; drivep->d_capabilities |= DRIVE_CAP_READ; drivep->d_capabilities |= DRIVE_CAP_ERASE; contextp->dc_rampr = BOOL_TRUE; oflags = O_RDWR | O_CREAT; } else { switch( statbuf.st_mode & S_IFMT ) { case S_IFREG: drivep->d_capabilities |= DRIVE_CAP_ERASE; drivep->d_capabilities |= DRIVE_CAP_REWIND; drivep->d_capabilities |= DRIVE_CAP_READ; contextp->dc_rampr = BOOL_TRUE; oflags = O_RDWR; break; case S_IFCHR: contextp->dc_israwdevpr = BOOL_TRUE; /* intentional fall-through */ case S_IFBLK: /* intentional fall-through */ case S_IFIFO: oflags = O_WRONLY; break; default: mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_DRIVE, _("cannot dump to %s " "file type %x\n"), drivep->d_pathname, statbuf.st_mode & S_IFMT ); return BOOL_FALSE; } } #endif /* DUMP */ #ifdef RESTORE if ( rval ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_DRIVE, _("stat of %s failed: %s\n"), drivep->d_pathname, strerror( errno )); return BOOL_FALSE; } oflags = O_RDONLY; switch( statbuf.st_mode & S_IFMT ) { case S_IFREG: case S_IFCHR: case S_IFBLK: drivep->d_capabilities |= DRIVE_CAP_REWIND; drivep->d_capabilities |= DRIVE_CAP_READ; break; case S_IFIFO: drivep->d_capabilities |= DRIVE_CAP_READ; break; default: mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_DRIVE, _("cannot restore from %s file type %x\n"), drivep->d_pathname, statbuf.st_mode & S_IFMT ); return BOOL_FALSE; } #endif /* RESTORE */ contextp->dc_fd = open( drivep->d_pathname, oflags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ); if ( contextp->dc_fd < 0 ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_DRIVE, _("unable to open %s: %s\n"), drivep->d_pathname, strerror( errno )); return BOOL_FALSE; } } /* initialize the operational mode. fmarkcnt is bumped on each * end_read and end_write, set back to 0 on rewind. */ contextp->dc_mode = OM_NONE; contextp->dc_fmarkcnt = 0; drivep->d_contextp = ( void * )contextp; drivep->d_cap_est = -1; drivep->d_rate_est = -1; return BOOL_TRUE; } /* drive op init - second pass drive manager init - nothing to do, * since async I/O not used. */ /* ARGSUSED */ static bool_t do_init( drive_t *drivep ) { #ifdef DUMP drive_hdr_t *dwhdrp = drivep->d_writehdrp; media_hdr_t *mwhdrp = ( media_hdr_t * )dwhdrp->dh_upper; #endif /* DUMP */ #ifdef DUMP /* fill in media strategy id: artifact of first version of xfsdump */ mwhdrp->mh_strategyid = MEDIA_STRATEGY_SIMPLE; #endif /* DUMP */ return BOOL_TRUE; } /* drive op init - third pass drive manager init - nothing to do, * since async I/O not used. */ /* ARGSUSED */ static bool_t do_sync( drive_t *drivep ) { return BOOL_TRUE; } /* drive op begin_read - prepare file for reading - main job is to * read the media hdr */ static int do_begin_read( drive_t *drivep ) { #ifdef DEBUG int dcaps = drivep->d_capabilities; #endif global_hdr_t *grhdrp = drivep->d_greadhdrp; drive_hdr_t *drhdrp = drivep->d_readhdrp; drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; int nread; int rval; global_hdr_t *tmphdr = (global_hdr_t *)malloc(GLOBAL_HDR_SZ); drive_hdr_t *tmpdh = (drive_hdr_t *)tmphdr->gh_upper; media_hdr_t *tmpmh = (media_hdr_t *)tmpdh->dh_upper; content_hdr_t *tmpch = (content_hdr_t *)tmpmh->mh_upper; content_inode_hdr_t *tmpcih = (content_inode_hdr_t *)tmpch->ch_specific; drive_hdr_t *dh = (drive_hdr_t *)grhdrp->gh_upper; media_hdr_t *mh = (media_hdr_t *)dh->dh_upper; content_hdr_t *ch = (content_hdr_t *)mh->mh_upper; content_inode_hdr_t *cih = (content_inode_hdr_t *)ch->ch_specific; mlog( MLOG_NITTY | MLOG_DRIVE, "drive_simple begin_read( )\n" ); /* verify protocol being followed */ assert( dcaps & DRIVE_CAP_READ ); assert( contextp->dc_fd >= 0 ); assert( contextp->dc_mode == OM_NONE ); /* can only read one media file */ if ( contextp->dc_fmarkcnt > 0 ) { return DRIVE_ERROR_EOM; } /* prepare the drive context */ contextp->dc_ownedp = 0; contextp->dc_emptyp = &contextp->dc_buf[ 0 ]; contextp->dc_nextp = contextp->dc_emptyp; contextp->dc_bufstroff = 0; /* read the global header using the read_buf() utility function and * my own read and return_read_buf operators. spoof the mode */ contextp->dc_mode = OM_READ; nread = read_buf( ( char * )tmphdr, GLOBAL_HDR_SZ, ( void * )drivep, ( rfp_t )drivep->d_opsp->do_read, ( rrbfp_t )drivep->d_opsp->do_return_read_buf, &rval ); contextp->dc_mode = OM_NONE; /* if EOD and nread is zero, there is no data after the file mark */ if ( rval == DRIVE_ERROR_EOD ) { if ( nread == 0 ) { free(tmphdr); return DRIVE_ERROR_BLANK; } else { free(tmphdr); return DRIVE_ERROR_FORMAT; } } if ( rval ) { free(tmphdr); return rval; } assert( ( size_t )nread == GLOBAL_HDR_SZ ); mlog(MLOG_NITTY, "do_begin_read: global_hdr\n" "\tgh_magic %.100s\n" "\tgh_version %u\n" "\tgh_checksum %u\n" "\tgh_timestamp %u\n" "\tgh_ipaddr %llu\n" "\tgh_hostname %.100s\n" "\tgh_dumplabel %.100s\n", tmphdr->gh_magic, tmphdr->gh_version, tmphdr->gh_checksum, tmphdr->gh_timestamp, tmphdr->gh_ipaddr, tmphdr->gh_hostname, tmphdr->gh_dumplabel); /* check the checksum */ if ( ! global_hdr_checksum_check( tmphdr )) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_DRIVE, _("media file header checksum error\n") ); free(tmphdr); return DRIVE_ERROR_CORRUPTION; } xlate_global_hdr(tmphdr, grhdrp, 1); xlate_drive_hdr(tmpdh, dh, 1); *(( drive_mark_t * )dh->dh_specific) = INT_GET(*(( drive_mark_t * )tmpdh->dh_specific), ARCH_CONVERT); xlate_media_hdr(tmpmh, mh, 1); xlate_content_hdr(tmpch, ch, 1); xlate_content_inode_hdr(tmpcih, cih, 1); free(tmphdr); /* check the magic number */ if ( strncmp( grhdrp->gh_magic, GLOBAL_HDR_MAGIC, GLOBAL_HDR_MAGIC_SZ)) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_DRIVE, _("media file header magic number mismatch: %s, %s\n"), grhdrp->gh_magic, GLOBAL_HDR_MAGIC); return DRIVE_ERROR_FORMAT; } /* check the version */ if ( global_version_check( grhdrp->gh_version ) != BOOL_TRUE ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_DRIVE, _("unrecognized media file header version (%d)\n"), grhdrp->gh_version ); return DRIVE_ERROR_VERSION; } /* check the strategy id */ if ( drhdrp->dh_strategyid != drive_strategy_simple.ds_id ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_DRIVE, _("unrecognized drive strategy ID " "(media says %d, expected %d)\n"), drhdrp->dh_strategyid, drive_strategy_simple.ds_id ); return DRIVE_ERROR_FORMAT; } /* record the offset of the first mark */ contextp->dc_firstmark = *( drive_mark_t * )drhdrp->dh_specific; /* adjust the drive capabilities based on presence of first mark. * this is a hack workaround for a bug in xfsdump which causes the * first mark offset to not always be placed in the hdr. */ if ( contextp->dc_firstmark ) { drivep->d_capabilities |= DRIVE_CAP_NEXTMARK; } /* note that a successful begin_read ocurred */ contextp->dc_mode = OM_READ; return 0; } /* read - supply the caller with some filled buffer */ static char * do_read( drive_t *drivep, size_t wantedcnt, size_t *actualcntp, int *rvalp ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; size_t remainingcnt; size_t actualcnt; mlog( MLOG_NITTY | MLOG_DRIVE, "drive_simple read( want %u )\n", wantedcnt ); /* assert protocol */ assert( contextp->dc_mode == OM_READ ); assert( ! contextp->dc_ownedp ); assert( wantedcnt > 0 ); /* pre-initialize reference return */ *rvalp = 0; /* count number of unread bytes in buffer */ assert( contextp->dc_emptyp >= contextp->dc_nextp ); remainingcnt = ( size_t )( contextp->dc_emptyp - contextp->dc_nextp ); /* if no unread bytes in buffer, refill */ if ( remainingcnt == 0 ) { size_t bufhowfullcnt; int nread; /* calculate how many bytes were in the buffer. this will * be used to adjust the recorded offset (relative to the * beginning of the media file) of the top of the buffer * after we refill the buffer. */ bufhowfullcnt = ( size_t ) ( contextp->dc_emptyp - contextp->dc_buf ); /* attempt to fill the buffer. nread may be less if at EOF */ nread = read( contextp->dc_fd, contextp->dc_buf, BUFSZ ); if ( nread < 0 ) { *rvalp = DRIVE_ERROR_DEVICE; return 0; } /* adjust the recorded offset of the top of the buffer * relative to the beginning of the media file */ contextp->dc_bufstroff += ( off64_t )bufhowfullcnt; /* record the ptrs to the first empty byte and the next * byte to be read */ assert( nread <= BUFSZ ); contextp->dc_emptyp = contextp->dc_buf + nread; contextp->dc_nextp = contextp->dc_buf; /* if no bytes were read, the caller has seen all bytes. */ if ( nread == 0 ) { *rvalp = DRIVE_ERROR_EOD; return 0; } /* adjust the remaining count */ remainingcnt = ( size_t )nread; } /* the caller specified at most how many bytes he wants. if less * than that remain unread in buffer, just return that many. */ actualcnt = min( wantedcnt, remainingcnt ); /* set the owned ptr to the first byte to be supplied */ contextp->dc_ownedp = contextp->dc_nextp; /* advance the next ptr to the next byte to be supplied */ contextp->dc_nextp += actualcnt; assert( contextp->dc_nextp <= contextp->dc_emptyp ); /* return the actual number of bytes supplied, and a ptr to the first */ *actualcntp = actualcnt; return contextp->dc_ownedp; } /* return_read_buf - lets the caller give back all of the * buffer obtained from a call to do_read(). */ /* ARGSUSED */ static void do_return_read_buf( drive_t *drivep, char *retp, size_t retcnt ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; /* REFERENCED */ size_t ownedcnt; mlog( MLOG_NITTY | MLOG_DRIVE, "drive_simple return_read_buf( returning %u )\n", retcnt ); /* verify protocol */ assert( contextp->dc_mode == OM_READ ); assert( contextp->dc_ownedp ); /* verify returning right buffer */ assert( retp == contextp->dc_ownedp ); /* verify all of buffer provided is being returned */ ownedcnt = ( size_t )( contextp->dc_nextp - contextp->dc_ownedp ); assert( retcnt == ownedcnt ); /* indicate nothing now owned by caller */ contextp->dc_ownedp = 0; } /* the mark is simply the offset into the media file of the * next byte to be read */ static void do_get_mark( drive_t *drivep, drive_mark_t *markp ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; off64_t nextoff; off64_t strmoff; mlog( MLOG_NITTY | MLOG_DRIVE, "drive_simple get_mark( )\n" ); /* assert protocol */ assert( contextp->dc_mode == OM_READ ); assert( ! contextp->dc_ownedp ); /* calculate the offset of the next byte to be supplied relative to * the beginning of the buffer and relative to the beginning of * ther media file. */ nextoff = ( off64_t )( contextp->dc_nextp - contextp->dc_buf ); strmoff = contextp->dc_bufstroff + nextoff; *markp = ( drive_mark_t )strmoff; } /* seek forward to the specified mark. the caller must not have already read * past that point. */ static int do_seek_mark( drive_t *drivep, drive_mark_t *markp ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; off64_t mark = *( off64_t * )markp; off64_t nextoff; off64_t strmoff; /* REFERENCED */ int nread; off64_t nreadneeded64; int nreadneeded; int rval; mlog( MLOG_NITTY | MLOG_DRIVE, "drive_simple seek_mark( )\n" ); /* assert protocol */ assert( contextp->dc_mode == OM_READ ); assert( ! contextp->dc_ownedp ); /* calculate the current offset within the media file * of the next byte to be read */ nextoff = ( off64_t )( contextp->dc_nextp - contextp->dc_buf ); strmoff = contextp->dc_bufstroff + nextoff; /* if the caller attempts to seek past the current offset, * this is really bad */ if ( strmoff > mark ) { return DRIVE_ERROR_CORE; } /* use read_buf util func to eat up difference */ nreadneeded64 = mark - strmoff; while ( nreadneeded64 > 0 ) { if ( nreadneeded64 > INTGENMAX ) nreadneeded = INTGENMAX; else nreadneeded = ( int )nreadneeded64; nread = read_buf( 0, nreadneeded, drivep, ( rfp_t )drivep->d_opsp->do_read, ( rrbfp_t )drivep->d_opsp->do_return_read_buf, &rval ); if ( rval ) { return rval; } nreadneeded64 -= nread; } /* verify we are on the mark */ nextoff = ( off64_t )( contextp->dc_nextp - contextp->dc_buf ); strmoff = contextp->dc_bufstroff + nextoff; assert( strmoff == mark ); return 0; } /* seek forward to the next mark. we only know of one mark, the first * mark in the media file (recorded in the header). if the caller * has already read past that mark, blow up. */ static int do_next_mark( drive_t *drivep ) { #ifdef DEBUG int dcaps = drivep->d_capabilities; #endif drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; drive_mark_t mark = contextp->dc_firstmark; int rval; mlog( MLOG_NITTY | MLOG_DRIVE, "drive_simple next_mark( )\n" ); /* assert protocol */ assert( dcaps & DRIVE_CAP_NEXTMARK ); assert( contextp->dc_mode == OM_READ ); assert( ! contextp->dc_ownedp ); if ( ! mark ) { return DRIVE_ERROR_EOF; } rval = do_seek_mark( drivep, ( drive_mark_t * )&mark ); if ( rval ) { return rval; } return 0; } /* end_read - tell the drive we are done reading the media file * just discards any buffered data */ void do_end_read( drive_t *drivep ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; mlog( MLOG_NITTY | MLOG_DRIVE, "drive_simple end_read( )\n" ); /* be sure we are following protocol */ assert( contextp->dc_mode == OM_READ ); contextp->dc_mode = OM_NONE; /* bump the file mark cnt */ contextp->dc_fmarkcnt++; assert( contextp->dc_fmarkcnt == 1 ); } /* begin_write - prepare file for writing */ static int do_begin_write( drive_t *drivep ) { int dcaps = drivep->d_capabilities; global_hdr_t *gwhdrp = drivep->d_gwritehdrp; drive_hdr_t *dwhdrp = drivep->d_writehdrp; drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; int rval; global_hdr_t *tmphdr; drive_hdr_t *tmpdh; media_hdr_t *tmpmh; content_hdr_t *tmpch; content_inode_hdr_t *tmpcih; drive_hdr_t *dh = (drive_hdr_t *)gwhdrp->gh_upper; media_hdr_t *mh = (media_hdr_t *)dh->dh_upper; content_hdr_t *ch = (content_hdr_t *)mh->mh_upper; content_inode_hdr_t *cih = (content_inode_hdr_t *)ch->ch_specific; mlog( MLOG_NITTY | MLOG_DRIVE, "drive_simple begin_write( )\n" ); /* sanity checks */ assert( dwhdrp->dh_strategyid == DRIVE_STRATEGY_SIMPLE ); /* assert protocol */ assert( contextp->dc_fd >= 0 ); assert( contextp->dc_mode == OM_NONE ); /* only one media file may be written */ if ( contextp->dc_fmarkcnt > 0 ) { return DRIVE_ERROR_EOM; } /* indicate in the header that there is no recorded mark. */ *( ( off64_t * )dwhdrp->dh_specific ) = 0; /* prepare the drive context. initially the caller does not own * any of the write buffer, so the next portion of the buffer to * be supplied is the top of the buffer. emptyp never changes; * it always points to the byte after the end of the buffer. markcnt * keeps track of the number marks the caller has set in the media file. */ contextp->dc_ownedp = 0; contextp->dc_nextp = contextp->dc_buf; contextp->dc_emptyp = contextp->dc_buf + sizeof( contextp->dc_buf ); contextp->dc_bufstroff = 0; contextp->dc_markcnt = 0; /* truncate the destination if it supports read. */ if ( dcaps & DRIVE_CAP_READ ) { rval = ftruncate( contextp->dc_fd, 0 ); if ( rval ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("attempt to truncate %s failed: %d (%s)\n"), drivep->d_pathname, errno, strerror( errno )); } } /* set the mode */ contextp->dc_mode = OM_WRITE; tmphdr = (global_hdr_t *)malloc(GLOBAL_HDR_SZ); assert(tmphdr); memset(tmphdr, 0, GLOBAL_HDR_SZ); tmpdh = (drive_hdr_t *)tmphdr->gh_upper; tmpmh = (media_hdr_t *)tmpdh->dh_upper; tmpch = (content_hdr_t *)tmpmh->mh_upper; tmpcih = (content_inode_hdr_t *)tmpch->ch_specific; xlate_global_hdr(gwhdrp, tmphdr, 1); xlate_drive_hdr(dh, tmpdh, 1); INT_SET(*(( drive_mark_t * )tmpdh->dh_specific), ARCH_CONVERT, *(( drive_mark_t * )dh->dh_specific)); xlate_media_hdr(mh, tmpmh, 1); xlate_content_hdr(ch, tmpch, 1); xlate_content_inode_hdr(cih, tmpcih, 1); /* checksum the header */ global_hdr_checksum_set( tmphdr ); mlog(MLOG_NITTY, "do_begin_write: global_hdr\n" "\tgh_magic %.100s\n" "\tgh_version %u\n" "\tgh_checksum %u\n" "\tgh_timestamp %u\n" "\tgh_ipaddr %llu\n" "\tgh_hostname %.100s\n" "\tgh_dumplabel %.100s\n", tmphdr->gh_magic, tmphdr->gh_version, tmphdr->gh_checksum, tmphdr->gh_timestamp, tmphdr->gh_ipaddr, tmphdr->gh_hostname, tmphdr->gh_dumplabel); if ( ! global_hdr_checksum_check( tmphdr )) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_DRIVE, _("media file header checksum error\n") ); } else { mlog( MLOG_NITTY, "media file header checksum OK!\n" ); } /* write the header using the write_buf() utility function and * my own get_write_buf and write operators. */ rval = write_buf( ( char * )tmphdr, GLOBAL_HDR_SZ, ( void * )drivep, ( gwbfp_t )drivep->d_opsp->do_get_write_buf, ( wfp_t )drivep->d_opsp->do_write ); free(tmphdr); /* if error while writing hdr, undo mode */ if ( rval ) { contextp->dc_mode = OM_NONE; } return rval; } /* do_set_mark - record a markrecord and callback */ static void do_set_mark( drive_t *drivep, drive_mcbfp_t cbfuncp, void *cbcontextp, drive_markrec_t *markrecp ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; drive_mark_t mark; mlog( MLOG_NITTY | MLOG_DRIVE, "drive_simple set_mark( )\n" ); /* assert protocol */ assert( contextp->dc_mode == OM_WRITE ); assert( ! contextp->dc_ownedp ); assert( contextp->dc_nextp ); /* calculate the mark offset */ mark = ( drive_mark_t )( contextp->dc_bufstroff + ( off64_t ) ( contextp->dc_nextp - contextp->dc_buf )); /* fill in the mark field of the mark record */ markrecp->dm_log = mark; /* bump the mark count. if this is the first mark, record it * in the drive strategy-specific header. this allows multiple * media object restores to work. NOTE that the mark will not * be recorded if the destination does not support random access * and the write buffer has been flushed at least once. * this is hidden by save_first_mark, and detected during restore * by noting the first mark offset is NULL. to do this, must seek * back to the header, rewrite and rechecksum the header, * and seek back to the current position. HOWEVER, if the write * buffer has not yet been flushed, we can just edit the buffer. */ contextp->dc_markcnt++; if ( contextp->dc_markcnt == 1 ) { if ( contextp->dc_bufstroff == 0 ) { /* cast the write buffer into a media file hdr */ global_hdr_t *gwhdrp = ( global_hdr_t * )contextp->dc_buf; drive_hdr_t *dwhdrp = ( drive_hdr_t * )gwhdrp->gh_upper; mlog( MLOG_NITTY | MLOG_DRIVE, "re-writing media file header with first mark " "(in buffer)\n" ); /* record mark in hdr */ INT_SET(*( ( drive_mark_t * )dwhdrp->dh_specific ), ARCH_CONVERT, mark); /* adjust header checksum */ global_hdr_checksum_set( gwhdrp ); } else if ( contextp->dc_rampr ) { global_hdr_t *gwhdrp = drivep->d_gwritehdrp; drive_hdr_t *dwhdrp = drivep->d_writehdrp; off64_t newoff; /* REFERENCED */ int nwritten; /* assert the header has been flushed */ assert( contextp->dc_bufstroff >= sizeof( *gwhdrp )); /* record mark in hdr */ INT_SET(*( ( drive_mark_t * )dwhdrp->dh_specific ), ARCH_CONVERT, mark); /* adjust header checksum */ global_hdr_checksum_set( gwhdrp ); /* seek to beginning */ newoff = lseek64( contextp->dc_fd, ( off64_t )0, SEEK_SET ); if ( newoff < 0 ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("could not save first mark: %d (%s)\n"), errno, strerror( errno )); } else { global_hdr_t *tmphdr; drive_hdr_t *tmpdh; media_hdr_t *tmpmh; content_hdr_t *tmpch; content_inode_hdr_t *tmpcih; drive_hdr_t *dh = (drive_hdr_t *)gwhdrp->gh_upper; media_hdr_t *mh = (media_hdr_t *)dh->dh_upper; content_hdr_t *ch = (content_hdr_t *)mh->mh_upper; content_inode_hdr_t *cih = (content_inode_hdr_t *)ch->ch_specific; assert( newoff == 0 ); /* write and seek back to current offset */ mlog( MLOG_NITTY | MLOG_DRIVE, "re-writing media file header " "with first mark " "(on media)\n" ); tmphdr = (global_hdr_t *)malloc(GLOBAL_HDR_SZ); assert(tmphdr); tmpdh = (drive_hdr_t *)tmphdr->gh_upper; tmpmh = (media_hdr_t *)tmpdh->dh_upper; tmpch = (content_hdr_t *)tmpmh->mh_upper; tmpcih = (content_inode_hdr_t *)tmpch->ch_specific; xlate_global_hdr(gwhdrp, tmphdr, 1); xlate_drive_hdr(dh, tmpdh, 1); INT_SET(*(( drive_mark_t * )tmpdh->dh_specific), ARCH_CONVERT, *(( drive_mark_t * )dh->dh_specific)); xlate_media_hdr(mh, tmpmh, 1); xlate_content_hdr(ch, tmpch, 1); xlate_content_inode_hdr(cih, tmpcih, 1); /* adjust header checksum */ global_hdr_checksum_set( tmphdr ); mlog(MLOG_NITTY, "do_set_mark: global_hdr\n" "\tgh_magic %.100s\n" "\tgh_version %u\n" "\tgh_checksum %u\n" "\tgh_timestamp %u\n" "\tgh_ipaddr %llu\n" "\tgh_hostname %.100s\n" "\tgh_dumplabel %.100s\n", tmphdr->gh_magic, tmphdr->gh_version, tmphdr->gh_checksum, tmphdr->gh_timestamp, tmphdr->gh_ipaddr, tmphdr->gh_hostname, tmphdr->gh_dumplabel); nwritten = write( contextp->dc_fd, tmphdr, sizeof( *tmphdr )); assert( ( size_t )nwritten == sizeof( *tmphdr )); free(tmphdr); newoff = lseek64( contextp->dc_fd, contextp->dc_bufstroff, SEEK_SET ); assert( newoff == contextp->dc_bufstroff ); } } } /* if all written are committed, send the mark back immediately. * otherwise put the mark record on the tail of the queue. */ if ( contextp->dc_nextp == contextp->dc_buf ) { assert( drivep->d_markrecheadp == 0 ); ( * cbfuncp )( cbcontextp, markrecp, BOOL_TRUE ); return; } else { markrecp->dm_cbfuncp = cbfuncp; markrecp->dm_cbcontextp = cbcontextp; markrecp->dm_nextp = 0; if ( drivep->d_markrecheadp == 0 ) { drivep->d_markrecheadp = markrecp; drivep->d_markrectailp = markrecp; } else { assert( drivep->d_markrectailp ); drivep->d_markrectailp->dm_nextp = markrecp; drivep->d_markrectailp = markrecp; } } } /* get_write_buf - supply the caller with buffer space. the caller * will fill the space with data, then call write() to request that * some or all of the buffer be written and to return the buffer space. */ /*ARGSUSED*/ static char * do_get_write_buf( drive_t *drivep, size_t wanted_bufsz, size_t *actual_bufszp ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; size_t remaining_bufsz; size_t actual_bufsz; mlog( MLOG_NITTY | MLOG_DRIVE, "drive_simple get_write_buf( want %u )\n", wanted_bufsz ); /* assert protocol */ assert( contextp->dc_mode == OM_WRITE ); assert( ! contextp->dc_ownedp ); assert( contextp->dc_nextp ); assert( contextp->dc_nextp < contextp->dc_emptyp ); assert( contextp->dc_ownedsz == 0 ); /* calculate how much buffer remains */ remaining_bufsz =( size_t )( contextp->dc_emptyp - contextp->dc_nextp ); /* give the caller the lesser of what he wants and what is available */ actual_bufsz = min( wanted_bufsz, remaining_bufsz ); /* caller will own that portion of buffer */ contextp->dc_ownedp = contextp->dc_nextp; contextp->dc_ownedsz = actual_bufsz; /* won't know nextp until write */ contextp->dc_nextp = 0; /* return the portion of the buffer to the caller */ *actual_bufszp = actual_bufsz; return contextp->dc_ownedp; } /* write - write and accept ownership of the portion of the buffer owned by the * caller. */ /*ARGSUSED*/ static int do_write( drive_t *drivep, char *bufp, size_t writesz ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; off64_t ownedstroff = contextp->dc_bufstroff + ( off64_t ) ( contextp->dc_ownedp - contextp->dc_buf ); mlog( MLOG_NITTY | MLOG_DRIVE, "drive_simple write( " "offset %lld (0x%llx 0%llo) " "size %u (0x%x 0%o) " ")\n", ownedstroff, ownedstroff, ownedstroff, writesz, writesz, writesz, 0 ); /* assert protocol */ assert( contextp->dc_mode == OM_WRITE ); assert( contextp->dc_ownedp ); assert( bufp == contextp->dc_ownedp ); assert( ! contextp->dc_nextp ); assert( contextp->dc_ownedp < contextp->dc_emptyp ); assert( writesz == contextp->dc_ownedsz ); /* calculate next portion of buffer available for get_write_buf, * and indicate no portion is owned. */ contextp->dc_nextp = contextp->dc_ownedp + writesz; assert( contextp->dc_nextp <= contextp->dc_emptyp ); contextp->dc_ownedp = 0; contextp->dc_ownedsz = 0; if ( writesz == 0 ) { return 0; /* returning unused buffer */ } /* if buffer is full, flush it */ if ( contextp->dc_nextp == contextp->dc_emptyp ) { int nwritten; mlog( MLOG_DEBUG | MLOG_DRIVE, "flushing write buf addr 0x%x size 0x%x\n", contextp->dc_buf, sizeof( contextp->dc_buf )); contextp->dc_nextp = 0; nwritten = write( contextp->dc_fd, contextp->dc_buf, sizeof( contextp->dc_buf )); if ( nwritten < 0 ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("write to %s failed: %d (%s)\n"), drivep->d_pathname, errno, strerror( errno )); nwritten = 0; } contextp->dc_bufstroff += ( off64_t )nwritten; drive_mark_commit( drivep, contextp->dc_bufstroff ); contextp->dc_nextp = contextp->dc_buf; if ( ( size_t )nwritten < sizeof( contextp->dc_buf )) { return DRIVE_ERROR_EOM; } } return 0; } /* get_align_cnt - returns the number of bytes which must be written to * cause the next call to get_write_buf() to be page-aligned. */ static size_t do_get_align_cnt( drive_t *drivep ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; intptr_t next_alignment_off; char *next_alignment_point; mlog( MLOG_NITTY | MLOG_DRIVE, "drive_simple get_align_cnt( )\n" ); /* assert protocol */ assert( contextp->dc_mode == OM_WRITE ); assert( ! contextp->dc_ownedp ); assert( contextp->dc_nextp ); assert( contextp->dc_nextp < contextp->dc_emptyp ); /* calculate the next alignment point at or beyond the current nextp. * the following algorithm works because dc_buf is page-aligned and * a multiple of PGSZ. */ next_alignment_off = ( intptr_t )contextp->dc_nextp; next_alignment_off += PGMASK; next_alignment_off &= ~PGMASK; next_alignment_point = ( char * )next_alignment_off; assert( next_alignment_point <= contextp->dc_emptyp ); /* return the number of bytes to the next alignment point */ return ( size_t )( next_alignment_point - contextp->dc_nextp ); } /* end_write - flush any buffered data, and return by reference how many * bytes were committed. */ static int do_end_write( drive_t *drivep, off64_t *ncommittedp ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; size_t remaining_bufsz; mlog( MLOG_NITTY | MLOG_DRIVE, "drive_simple end_write( )\n" ); /* assert protocol */ assert( contextp->dc_mode == OM_WRITE ); assert( ! contextp->dc_ownedp ); assert( contextp->dc_nextp ); assert( contextp->dc_nextp < contextp->dc_emptyp ); /* calculate length of un-written portion of buffer */ assert( contextp->dc_nextp >= contextp->dc_buf ); remaining_bufsz = ( size_t )( contextp->dc_nextp - contextp->dc_buf ); if ( remaining_bufsz ) { int nwritten; if ( contextp->dc_israwdevpr ) { remaining_bufsz = ( remaining_bufsz + ( BBSIZE - 1 )) & ~( BBSIZE - 1 ); } mlog( MLOG_DEBUG | MLOG_DRIVE, "flushing write buf addr 0x%x size 0x%x\n", contextp->dc_buf, remaining_bufsz ); nwritten = write( contextp->dc_fd, contextp->dc_buf, remaining_bufsz ); if ( nwritten < 0 ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("write to %s failed: %d (%s)\n"), drivep->d_pathname, errno, strerror( errno )); drive_mark_discard( drivep ); *ncommittedp = contextp->dc_bufstroff; contextp->dc_mode = OM_NONE; return DRIVE_ERROR_DEVICE; } contextp->dc_bufstroff += ( off64_t )nwritten; drive_mark_commit( drivep, contextp->dc_bufstroff ); if ( ( size_t )nwritten < remaining_bufsz ) { *ncommittedp = contextp->dc_bufstroff; contextp->dc_mode = OM_NONE; return DRIVE_ERROR_EOM; } } /* bump the file mark cnt */ contextp->dc_fmarkcnt++; assert( contextp->dc_fmarkcnt == 1 ); *ncommittedp = contextp->dc_bufstroff; contextp->dc_mode = OM_NONE; return 0; } /* rewind - return the current file offset to the beginning */ int do_rewind( drive_t *drivep ) { #ifdef DEBUG int dcaps = drivep->d_capabilities; #endif drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; off64_t newoff; mlog( MLOG_NITTY | MLOG_DRIVE, "drive_simple rewind( )\n" ); /* assert protocol */ assert( contextp->dc_mode == OM_NONE ); assert( dcaps & DRIVE_CAP_REWIND ); assert( contextp->dc_fd >= 0 ); /* seek to beginning of file */ newoff = lseek64( contextp->dc_fd, ( off64_t )0, SEEK_SET ); if ( newoff ) { assert( newoff < 0 ); mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("could not rewind %s: %s\n"), drivep->d_pathname, strerror( errno )); return DRIVE_ERROR_DEVICE; } return 0; } /* erase - truncate to zero length */ int do_erase( drive_t *drivep ) { #ifdef DEBUG int dcaps = drivep->d_capabilities; #endif drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; off64_t newoff; int rval; mlog( MLOG_NITTY | MLOG_DRIVE, "drive_simple erase( )\n" ); /* assert protocol */ assert( contextp->dc_mode == OM_NONE ); assert( dcaps & DRIVE_CAP_ERASE ); assert( contextp->dc_fd >= 0 ); /* seek to beginning of file */ newoff = lseek64( contextp->dc_fd, ( off64_t )0, SEEK_SET ); if ( newoff ) { assert( newoff < 0 ); mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("could not rewind %s in prep for erase: %s\n"), drivep->d_pathname, strerror( errno )); return DRIVE_ERROR_DEVICE; } /* erase to beginning of file */ rval = ftruncate64( contextp->dc_fd, ( off64_t )0 ); if ( rval ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("could not erase %s: %s (%d)\n"), drivep->d_pathname, strerror( errno ), errno ); return DRIVE_ERROR_DEVICE; } contextp->dc_fmarkcnt = 0; return 0; } /* get_media_class() */ /* ARGSUSED */ static int do_get_device_class( drive_t *drivep ) { mlog( MLOG_NITTY | MLOG_DRIVE, "drive_simple get_device_class( )\n" ); assert( drivep ); return DEVICE_NONREMOVABLE; } static void do_quit( drive_t *drivep ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; mlog( MLOG_NITTY | MLOG_DRIVE, "drive_simple quit( )\n" ); /* assert protocol */ assert( contextp->dc_mode == OM_NONE ); assert( contextp ); /* close file */ if ( contextp->dc_fd > 1 ) { close( contextp->dc_fd ); } contextp->dc_fd = -1; /* free context */ free( ( void * )contextp ); drivep->d_contextp = 0; } xfsdump-3.1.6+nmu1/common/mlog.c0000644000000000000000000004770712620476160013366 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "types.h" #include "qlock.h" #include "stream.h" #include "mlog.h" #include "cldmgr.h" #include "getopt.h" #include "exit.h" #include "global.h" #include "drive.h" extern char *progname; extern void usage( void ); extern pthread_t parenttid; #ifdef DUMP static FILE *mlog_fp = NULL; /* stderr */; #endif /* DUMP */ #ifdef RESTORE static FILE *mlog_fp = NULL; /* stdout */; #endif /* RESTORE */ int mlog_level_ss[ MLOG_SS_CNT ]; int mlog_showlevel = BOOL_FALSE; int mlog_showss = BOOL_FALSE; int mlog_timestamp = BOOL_FALSE; static int mlog_sym_lookup( char * ); static size_t mlog_streamcnt; static char mlog_levelstr[ 3 ]; #define MLOG_SS_NAME_MAX 15 #ifdef DUMP #define PROGSTR "dump" #define PROGSTR_CAPS "Dump" #else #define PROGSTR "restore" #define PROGSTR_CAPS "Restore" #endif /* DUMP */ #define N(a) (sizeof((a)) / sizeof((a)[0])) static char mlog_ssstr[ MLOG_SS_NAME_MAX + 2 ]; static char mlog_tsstr[ 10 ]; struct mlog_sym { char *sym; int level; }; typedef struct mlog_sym mlog_sym_t; char *mlog_ss_names[ MLOG_SS_CNT ] = { "general", /* MLOG_SS_GEN */ "proc", /* MLOG_SS_PROC */ "drive", /* MLOG_SS_DRIVE */ "media", /* MLOG_SS_MEDIA */ "inventory", /* MLOG_SS_INV */ #ifdef DUMP "inomap", /* MLOG_SS_INOMAP */ #endif /* DUMP */ #ifdef RESTORE "tree", /* MLOG_SS_TREE */ #endif /* RESTORE */ "excluded_files" /* MLOG_SS_EXCLFILES */ }; static mlog_sym_t mlog_sym[ ] = { {"0", MLOG_SILENT}, {"1", MLOG_VERBOSE}, {"2", MLOG_TRACE}, {"3", MLOG_DEBUG}, {"4", MLOG_NITTY}, {"5", MLOG_NITTY + 1}, {"silent", MLOG_SILENT}, {"verbose", MLOG_VERBOSE}, {"trace", MLOG_TRACE}, {"debug", MLOG_DEBUG}, {"nitty", MLOG_NITTY} }; static qlockh_t mlog_qlockh; static int mlog_main_exit_code = -1; static rv_t mlog_main_exit_return = RV_NONE; static rv_t mlog_main_exit_hint = RV_NONE; void mlog_init0( void ) { int i; #ifdef DUMP mlog_fp = stderr; #endif /* DUMP */ #ifdef RESTORE mlog_fp = stdout; #endif /* RESTORE */ /* initialize stream count. will be updated later by call to * mlog_tell_streamcnt( ), after drive layer has counted drives */ mlog_streamcnt = 1; for( i = 0 ; i < MLOG_SS_CNT ; i++ ) { mlog_level_ss[ i ] = MLOG_VERBOSE; } } bool_t mlog_init1( int argc, char *argv[ ] ) { char **suboptstrs; ix_t ssix; ix_t soix; size_t vsymcnt; int c; /* prepare an array of suboption token strings. this will be the * concatenation of the subsystem names with the verbosity symbols. * this array of char pts must be null terminated for getsubopt( 3 ). */ vsymcnt = sizeof( mlog_sym ) / sizeof( mlog_sym[ 0 ] ); suboptstrs = ( char ** )calloc( MLOG_SS_CNT + vsymcnt + 1, sizeof( char * )); assert( suboptstrs ); for ( soix = 0 ; soix < MLOG_SS_CNT ; soix++ ) { assert( strlen( mlog_ss_names[ soix ] ) <= MLOG_SS_NAME_MAX ); /* unrelated, but opportunity to chk */ suboptstrs[ soix ] = mlog_ss_names[ soix ]; } for ( ; soix < MLOG_SS_CNT + vsymcnt ; soix++ ) { suboptstrs[ soix ] = mlog_sym[ soix - MLOG_SS_CNT ].sym; } suboptstrs[ soix ] = 0; /* set all of the subsystem log levels to -1, so we can see which * subsystems where explicitly called out. those which weren't will * be given the "general" level. */ for ( ssix = 0 ; ssix < MLOG_SS_CNT ; ssix++ ) { mlog_level_ss[ ssix ] = -1; } mlog_level_ss[ MLOG_SS_GEN ] = MLOG_VERBOSE; /* get command line options */ optind = 1; opterr = 0; while ( ( c = getopt( argc, argv, GETOPT_CMDSTRING )) != EOF ) { char *options; switch ( c ) { case GETOPT_VERBOSITY: if ( ! optarg || optarg[ 0 ] == '-' ) { fprintf( stderr, _("%s: -%c argument missing\n"), progname, c ); usage( ); return BOOL_FALSE; } options = optarg; while ( *options ) { int suboptix; char *valstr; suboptix = getsubopt( &options, (constpp)suboptstrs, &valstr ); if ( suboptix < 0 ) { fprintf( stderr, _("%s: -%c argument invalid\n"), progname, c ); usage( ); return BOOL_FALSE; } assert( ( ix_t )suboptix < MLOG_SS_CNT + vsymcnt ); if ( suboptix < MLOG_SS_CNT ) { if ( ! valstr ) { fprintf( stderr, _("%s: -%c subsystem " "subargument " "%s requires a " "verbosity value\n"), progname, c, mlog_ss_names[ suboptix ] ); usage( ); return BOOL_FALSE; } ssix = ( ix_t )suboptix; mlog_level_ss[ ssix ] = mlog_sym_lookup( valstr ); } else { if ( valstr ) { fprintf( stderr, _("%s: -%c argument " "does not require " "a value\n"), progname, c ); usage( ); return BOOL_FALSE; } ssix = MLOG_SS_GEN; mlog_level_ss[ ssix ] = mlog_sym_lookup( suboptstrs[ suboptix ] ); } if ( mlog_level_ss[ ssix ] < 0 ) { fprintf( stderr, _("%s: -%c argument " "invalid\n"), progname, c ); usage( ); return BOOL_FALSE; } } break; case GETOPT_SHOWLOGLEVEL: mlog_showlevel = BOOL_TRUE; break; case GETOPT_SHOWLOGSS: mlog_showss = BOOL_TRUE; break; case GETOPT_TIMESTAMP: mlog_timestamp = BOOL_TRUE; break; } } free( ( void * )suboptstrs ); /* give subsystems not explicitly called out the "general" verbosity */ for ( ssix = 0 ; ssix < MLOG_SS_CNT ; ssix++ ) { if ( mlog_level_ss[ ssix ] < 0 ) { assert( mlog_level_ss[ ssix ] == -1 ); assert( mlog_level_ss[ MLOG_SS_GEN ] >= 0 ); mlog_level_ss[ ssix ] = mlog_level_ss[ MLOG_SS_GEN ]; } } /* prepare a string for optionally displaying the log level */ mlog_levelstr[ 0 ] = 0; mlog_levelstr[ 1 ] = 0; mlog_levelstr[ 2 ] = 0; if ( mlog_showlevel ) { mlog_levelstr[ 0 ] = ':'; } #ifdef DUMP /* note if dump going to stdout. if so, can't * send mlog output there. since at compile time * mlog_fd set to stderr, see if we can switch * to stdout. */ if ( optind >= argc || strcmp( argv[ optind ], "-" )) { mlog_fp = stdout; } #endif /* DUMP */ mlog_qlockh = QLOCKH_NULL; return BOOL_TRUE; } bool_t mlog_init2( void ) { /* allocate a qlock */ mlog_qlockh = qlock_alloc( QLOCK_ORD_MLOG ); return BOOL_TRUE; } void mlog_tell_streamcnt( size_t streamcnt ) { mlog_streamcnt = streamcnt; } void mlog_lock( void ) { qlock_lock( mlog_qlockh ); } void mlog_unlock( void ) { qlock_unlock( mlog_qlockh ); } /* * Override the -v option. * Useful for debugging at particular points * where doing it program-wide would produce * too much output. */ void mlog_override_level( int levelarg ) { int level; ix_t ss; /* SubSystem */ level = levelarg & MLOG_LEVELMASK; ss = ( ix_t )( ( levelarg & MLOG_SS_MASK ) >> MLOG_SS_SHIFT ); if (ss == MLOG_SS_GEN) { /* do level for all subsys */ for (ss = 0 ; ss < MLOG_SS_CNT ; ss++ ) { mlog_level_ss[ ss ] = level; } } else { /* do a particular subsys */ mlog_level_ss[ ss ] = level; } } void mlog( int levelarg, char *fmt, ... ) { va_list args; va_start( args, fmt ); mlog_va( levelarg, fmt, args ); va_end( args ); } void mlog_va( int levelarg, char *fmt, va_list args ) { int level; ix_t ss; level = levelarg & MLOG_LEVELMASK; ss = ( ix_t )( ( levelarg & MLOG_SS_MASK ) >> MLOG_SS_SHIFT ); assert( ss < MLOG_SS_CNT ); if ( level > mlog_level_ss[ ss ] ) { return; } if ( ! ( levelarg & MLOG_NOLOCK )) { mlog_lock( ); } if ( ! ( levelarg & MLOG_BARE )) { int streamix; streamix = stream_getix( pthread_self( ) ); if ( mlog_showss ) { sprintf( mlog_ssstr, ":%s", mlog_ss_names[ ss ] ); } else { mlog_ssstr[ 0 ] = 0; } if ( mlog_timestamp ) { time_t now = time( 0 ); struct tm *tmp = localtime( &now ); sprintf( mlog_tsstr, ":%02d.%02d.%02d", tmp->tm_hour, tmp->tm_min, tmp->tm_sec ); assert( strlen( mlog_tsstr ) < sizeof( mlog_tsstr )); } else { mlog_tsstr[ 0 ] = 0; } if ( mlog_showlevel ) { mlog_levelstr[ 0 ] = ':'; if ( level > 9 ) { mlog_levelstr[ 1 ] = '?'; } else { mlog_levelstr[ 1 ] = ( char ) ( level + ( int )'0' ); } } else { mlog_levelstr[ 0 ] = 0; } if ( streamix != -1 && mlog_streamcnt > 1 ) { fprintf( mlog_fp, _("%s%s%s%s: drive %d: "), progname, mlog_tsstr, mlog_ssstr, mlog_levelstr, streamix ); } else { fprintf( mlog_fp, "%s%s%s%s: ", progname, mlog_tsstr, mlog_ssstr, mlog_levelstr ); } if ( levelarg & MLOG_NOTE ) { fprintf( mlog_fp, "NOTE: " ); } if ( levelarg & MLOG_WARNING ) { fprintf( mlog_fp, "WARNING: " ); } if ( levelarg & MLOG_ERROR ) { fprintf( mlog_fp, "ERROR: " ); } } vfprintf( mlog_fp, fmt, args ); fflush( mlog_fp ); if ( ! ( levelarg & MLOG_NOLOCK )) { mlog_unlock( ); } } /* * Map RV codes to actual error messages. */ struct rv_map { int rv; const char * rv_string; const char * rv_desc; }; static struct rv_map rvs[_RV_NUM] = { /* Return Code Displayed Code Explanation */ { RV_OK, "OK", "success" }, { RV_NOTOK, "ERASE_FAILED", "media erase request denied" }, { RV_NOMORE, "NOMORE", "no more work to do" }, { RV_EOD, "EOD", "ran out of data" }, { RV_EOF, "EOF", "hit end of media file" }, { RV_EOM, "EOM", "hit end of media" }, { RV_ERROR, "ERROR", "operator error or resource exhaustion" }, { RV_DONE, "ALREADY_DONE", "another stream completed the operation" }, { RV_INTR, "INTERRUPT", PROGSTR " interrupted" }, { RV_CORRUPT, "CORRUPTION", "corrupt data encountered" }, { RV_QUIT, "QUIT", "media is no longer usable" }, { RV_DRIVE, "DRIVE_ERROR", "drive error" }, { RV_TIMEOUT, "TIMEOUT", "operation timed out" }, { RV_MEDIA, "NO_MEDIA", "no media in drive" }, { RV_PROTECTED, "WRITE_PROTECTED","object write protected" }, { RV_CORE, "CORE", "fatal error - core dumped" }, { RV_OPT, "OPT_ERROR", "bad command line option" }, { RV_INIT, "INIT_ERROR", "could not initialise subsystem" }, { RV_PERM, "NO_PERMISSION","insufficient privilege" }, { RV_COMPAT, "INCOMPATIBLE", "cannot apply - dump incompatible" }, { RV_INCOMPLETE,"INCOMPLETE", "the " PROGSTR " is incomplete" }, { RV_KBD_INTR, "KEYBOARD_INTERRUPT", "keyboard interrupt" }, { RV_INV, "INVENTORY", "error updating session inventory" }, { RV_USAGE, "USAGE_ONLY", "printing usage only" }, { RV_EXISTS, "EXISTS", "file or directory already exists" }, { RV_NONE, "NONE", "no error code" }, { RV_UNKNOWN, "UNKNOWN", "unknown error" }, }; static struct rv_map rv_unknown = { _RV_NUM, "???", "unknown error code" }; static const struct rv_map * rv_getdesc(rv_t rv) { int rvidx; if (rv < 0 || rv >= _RV_NUM) { return &rv_unknown; } for (rvidx = 0; rvidx < _RV_NUM; rvidx++) if (rv == rvs[rvidx].rv) return &rvs[rvidx]; return &rv_unknown; } /* * mlog_exit takes two arguments an exit code (EXIT_*) and the internal * return code (RV_*) that was signalled prior to the exit. mlog_exit * stores these values in a per-stream structure managed by the stream_* * functions. * * mlog_exit is called for: all returns from the content threads * (content_stream_dump and content_stream_restore); for returns from * the main process; and also from a couple of other locations where an * error is known to directly lead to the termination of the program. * * For example, in the places mentioned above "return EXIT_ERROR;" has * now been replaced with a call like * "return mlog_exit(EXIT_ERROR, RV_DRIVE);" that specifies both the exit * code, and the reason why the program is terminating. * * mlog_exit_flush uses the per-stream exit information recorded using * mlog_exit to print a detailed status report, showing both the exit * status of each stream, and the overall exit status of the * program. This additional log information allows the user to detect * failures that cannot be distinguished by looking at the exit code * alone. In particular, the exit code does not currently allow the * user to distinguish EOM conditions from user interruptions, and to * detect an incomplete dump (caused, for example, by drive errors or * corruption). * * Note, that to maintain backwards compatibility the exit codes * returned by dump/restore have _not_ been changed. For more * information see PV #784355. * * While mlog_exit provides considerably more information about the * reasons for a dump terminating, there are a number of cases where * dump maps return codes that have specific values such as RV_DRIVE, * to return codes with less specific values such as RV_INTR, and in * doing so throws away information that would have been useful in * diagnosing the reasons for a failure. To alleviate this, an * additional function mlog_exit_hint is provided that allows a "hint" * to be made about the real reason a stream is terminating. A call to * mlog_exit_hint should be made anywhere in the code a change in * program state has occured that might lead to the termination of the * dump. The mlog_exit_flush routine uses this additional information * help work out what really happened. */ int _mlog_exit( const char *file, int line, int exit_code, rv_t rv ) { pthread_t tid; const struct rv_map *rvp; tid = pthread_self(); rvp = rv_getdesc(rv); mlog( MLOG_DEBUG | MLOG_NOLOCK, "%s: %d: mlog_exit called: " "exit_code: %s return: %s (%s)\n", file, line, exit_codestring(exit_code), rvp->rv_string, rvp->rv_desc); if (rv < 0 || rv >= _RV_NUM) { mlog( MLOG_DEBUG | MLOG_ERROR | MLOG_NOLOCK, "mlog_exit(): bad return code"); return exit_code; } /* * NOTE: we record the first call only. Exit codes can be mapped from * more specific values to less specific values as we return up the * call chain. We assume therefore that the first call contains the * most accurate information about the termination condition. */ if ( pthread_equal( tid, parenttid ) ) { if (mlog_main_exit_code == -1) { mlog_main_exit_code = exit_code; mlog_main_exit_return = rv; } } else { stream_state_t states[] = { S_RUNNING }; stream_state_t state; int streamix; int exit_code; rv_t exit_return, exit_hint; if (stream_get_exit_status(tid, states, N(states), &state, &streamix, &exit_code, &exit_return, &exit_hint)) { if (exit_code == -1) { stream_set_code(tid, exit_code); stream_set_return(tid, rv); } } } return exit_code; } void _mlog_exit_hint( const char *file, int line, rv_t rv ) { pthread_t tid; const struct rv_map *rvp; tid = pthread_self(); rvp = rv_getdesc(rv); mlog( MLOG_DEBUG | MLOG_NOLOCK, "%s: %d: mlog_exit_hint called: " "hint: %s (%s)\n", file, line, rvp->rv_string, rvp->rv_desc); if (rv < 0 || rv >= _RV_NUM) { mlog( MLOG_DEBUG | MLOG_ERROR | MLOG_NOLOCK, "mlog_exit_hint(): bad return code"); return; } /* * NOTE: we use the last hint before exit. Unlike exit codes we've added * calls to mlog_exit_hint to improve error reporting. In general the * call closest to the final exit point will provide the most accurate * information about the termination condition. */ if ( pthread_equal( tid, parenttid ) ) mlog_main_exit_hint = rv; else stream_set_hint( tid, rv ); } rv_t mlog_get_hint( void ) { stream_state_t states[] = { S_RUNNING }; /* REFERENCED */ bool_t ok; rv_t hint; if ( pthread_equal( pthread_self(), parenttid ) ) return mlog_main_exit_hint; ok = stream_get_exit_status(pthread_self(), states, N(states), NULL, NULL, NULL, NULL, &hint); assert(ok); return hint; } #define IS_INCOMPLETE(rv) \ ((rv) == RV_CORRUPT || \ (rv) == RV_INCOMPLETE || \ (rv) == RV_EOD || \ (rv) == RV_EOF || \ (rv) == RV_EOM) #define VALID_EXIT_CODE(code) \ ((code) == EXIT_NORMAL || \ (code) == EXIT_ERROR || \ (code) == EXIT_INTERRUPT || \ (code) == EXIT_FAULT) void mlog_exit_flush(void) { pthread_t tids[STREAM_SIMMAX]; int i, ntids; const struct rv_map *rvp; stream_state_t states[] = { S_RUNNING, S_ZOMBIE }; bool_t incomplete = BOOL_FALSE; bool_t quit = BOOL_FALSE; bool_t interrupt = BOOL_FALSE; const char *status_str; rv_t rv; if (mlog_level_ss[MLOG_SS_GEN] == MLOG_SILENT) return; if (mlog_main_exit_hint == RV_USAGE) return; ntids = stream_find_all(states, N(states), tids, STREAM_SIMMAX); if (ntids > 0) { /* print the state of all the streams */ fprintf(mlog_fp, _("%s: %s Summary:\n"), progname, PROGSTR_CAPS ); for (i = 0; i < ntids; i++) { stream_state_t state; int streamix; int exit_code; rv_t exit_return, exit_hint; /* REFERENCED */ bool_t ok; ok = stream_get_exit_status(tids[i], states, N(states), &state, &streamix, &exit_code, &exit_return, &exit_hint); assert(ok); /* hint takes priority over return */ rv = (exit_hint != RV_NONE) ? exit_hint : exit_return; /* print status of this stream */ rvp = rv_getdesc(rv); fprintf(mlog_fp, _("%s: stream %d %s " "%s (%s)\n"), progname, streamix, drivepp[streamix]->d_pathname, rvp->rv_string, rvp->rv_desc); /* If the following conditions are true for any stream * then they are true for the entire dump/restore. */ if (rv == RV_INTR) interrupt = BOOL_TRUE; else if (rv == RV_QUIT) quit = BOOL_TRUE; else if (IS_INCOMPLETE(rv)) incomplete = BOOL_TRUE; } } /* Also check return codes for the main process */ rv = (mlog_main_exit_hint != RV_NONE) ? mlog_main_exit_hint : mlog_main_exit_return; if (rv == RV_INTR) interrupt = BOOL_TRUE; else if (rv == RV_QUIT) quit = BOOL_TRUE; else if (IS_INCOMPLETE(rv)) incomplete = BOOL_TRUE; /* if we don't have an exit code here there is a problem */ assert(VALID_EXIT_CODE(mlog_main_exit_code)); if (interrupt) status_str = "INTERRUPT"; else if (quit) status_str = "QUIT"; else if (incomplete) status_str = "INCOMPLETE"; else status_str = exit_codestring(mlog_main_exit_code); /* now print the overall state of the dump/restore */ fprintf(mlog_fp, "%s: %s Status: %s\n", progname, PROGSTR_CAPS, status_str); fflush(mlog_fp); } static int mlog_sym_lookup( char *sym ) { mlog_sym_t *p = mlog_sym; mlog_sym_t *ep = mlog_sym + sizeof( mlog_sym ) / sizeof( mlog_sym[ 0 ] ); for ( ; p < ep ; p++ ) { if ( ! strcmp( sym, p->sym )) { return p->level; } } return -1; } void fold_init( fold_t fold, char *infostr, char c ) { size_t infolen; size_t dashlen; size_t predashlen; size_t postdashlen; char *p; char *endp; ix_t cnt; assert( sizeof( fold_t ) == FOLD_LEN + 1 ); infolen = strlen( infostr ); if ( infolen > FOLD_LEN - 4 ) { infolen = FOLD_LEN - 4; } dashlen = FOLD_LEN - infolen - 3; predashlen = dashlen / 2; postdashlen = dashlen - predashlen; p = &fold[ 0 ]; endp = &fold[ sizeof( fold_t ) - 1 ]; assert( p < endp ); *p++ = ' '; for ( cnt = 0 ; cnt < predashlen && p < endp ; cnt++, p++ ) { *p = c; } assert( p < endp ); *p++ = ' '; assert( p < endp ); assert( p + infolen < endp ); strcpy( p, infostr ); p += infolen; assert( p < endp ); *p++ = ' '; assert( p < endp ); for ( cnt = 0 ; cnt < postdashlen && p < endp ; cnt++, p++ ) { *p = c; } assert( p <= endp ); *p = 0; } xfsdump-3.1.6+nmu1/common/drive_minrmt.c0000644000000000000000000030776412620476160015131 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "types.h" #include "qlock.h" #include "cldmgr.h" #include "mlog.h" #include "dlog.h" #include "global.h" #include "drive.h" #include "media.h" #include "getopt.h" #include "stream.h" #include "ring.h" #include "rec_hdr.h" #include "arch_xlate.h" #include "ts_mtio.h" /* drive_minrmt.c - drive strategy for non-SGI rmt tape devices * This strategy is derived from the scsitape strategy. It is designed * so that tapes written using this strategy can be read with the * scsitape strategy and vice versa. */ /* structure definitions used locally ****************************************/ /* remote tape protocol debug */ #ifdef RMTDBG #define open(p,f) dbgrmtopen(p,f) #define close(fd) dbgrmtclose(fd) #define ioctl(fd,op,arg) dbgrmtioctl(fd,op,arg) #define read(fd,p,sz) dbgrmtread(fd,p,sz) #define write(fd,p,sz) dbgrmtwrite(fd,p,sz) #else /* RMTDBG */ #define open rmtopen #define close rmtclose #define ioctl rmtioctl #define read rmtread #define write rmtwrite #endif /* RMTDBG */ /* if the media file header structure changes, this number must be * bumped, and STAPE_VERSION_1 must be defined and recognized. */ #define STAPE_VERSION 1 /* a bizarre number to help reduce the odds of mistaking random data * for a media file or record header */ #define STAPE_MAGIC 0x13579bdf02468acell /* this much of each record is reserved for header info: the user * data always begins at this offset from the beginning of each * record. be sure global_hdr_t fits. */ #define STAPE_HDR_SZ PGSZ /* maximum tape record size. this is the max size of I/O buffers sent to drive. * note that for variable block devices this determines the block size as well. */ #define STAPE_MAX_RECSZ 0x200000 /* 2M */ /* this is the smallest maximum block size for any tape device * supported by xfsdump/xfsrestore. we use this when it is not possible * to ask the driver for block size info. */ #define STAPE_MIN_MAX_BLKSZ 0x3c000 /* 240K, 245760 */ /* QIC tapes always use 512 byte blocks */ #define QIC_BLKSZ 512 /* number of record buffers in the I/O ring */ #define RINGLEN_MIN 1 #define RINGLEN_MAX 10 #define RINGLEN_DEFAULT 3 /* tape i/o request retry limit */ #define MTOP_TRIES_MAX 10 /* operational mode. can be reading or writing, but not both */ typedef enum { OM_NONE, OM_READ, OM_WRITE } om_t; /* drive_context - control state * * NOTE: ring used only if not singlethreaded */ struct drive_context { om_t dc_mode; /* current mode of operation (READ or WRITE) */ size_t dc_ringlen; /* number of tape_recsz buffers in ring. only used * for displaying ring info */ bool_t dc_ringpinnedpr; /* are the ring buffers pinned down */ ring_t *dc_ringp; /* handle to ring */ ring_msg_t *dc_msgp; /* currently held ring message */ char *dc_bufp; /* pre-allocated record buffer (only if ring not used) */ char *dc_recp; /* pointer to current record buffer. once the current * record is completely read or written by client, * set to NULL. */ char *dc_recendp; /* always set to point to just off the end of the * current record buffer pointed to by dc_recp. valid * only when dc_recp non-NULL. */ char *dc_dataendp; /* same as dc_recendp, except for first and last * records in media file. the first record is all * pads after the header page. the last record may * have been padded (as indicated by the rec_used * field of the record header). in either case * dc_dataendp points to first padding byte. */ char *dc_ownedp; /* first byte in current buffer owned by caller. * given to caller by do_read or do_get_write_buf * set to null by do_return_read_buf or do_write. */ char *dc_nextp; /* next byte available in current buffer to give * to do_get_write_buf for writing or do_read for * reading. */ off64_t dc_reccnt; /* count of the number of records completely read or * written by client, and therefore not represented * by current dc_recp. valid initially and after * each call to do_return_read_buf or do_write. * NOT valid after a call to do_read or * do_get_write_buf. always bumped regardless of * read or write error status. */ off64_t dc_iocnt; /* count of the number of records read or written * to media without error. includes media file header * record. this is incremented when the actual I/O is * done. dc_reccnt is different, indicating what has * been seen by client. slave may have read ahead / * written behind. */ int dc_fd; /* drive file descriptor. -1 when not open */ bool_t dc_isQICpr; /* fixed 512 byte block size device. */ bool_t dc_canfsrpr; /* can seek forward records at a time */ size_t dc_blksz; /* actual tape blksize selected */ size_t dc_recsz; /* actual tape record size selected */ off64_t dc_lostrecmax; /* maximum number of records written without error * which may be lost due to a near end-of-tape * experience. a function of drive type and * compression */ bool_t dc_singlethreadedpr; /* single-threaded operation (no slave) */ bool_t dc_errorpr; /* TRUE if error encountered during reading or writing. * used to detect attempts to read or write after * error reported. */ bool_t dc_recchksumpr; /* TRUE if records should be checksumed */ bool_t dc_unloadokpr; /* ok to issue unload command when do_eject invoked. */ bool_t dc_overwritepr; /* overwrite tape without checking whats on it */ off64_t dc_filesz; /* media file size given as argument */ }; typedef struct drive_context drive_context_t; /* macros for shortcut references to context. assumes a local variable named * 'contextp'. */ #define tape_recsz ( contextp->dc_recsz ) #define tape_blksz ( contextp->dc_blksz ) /* declarations of externally defined global variables ***********************/ extern void usage( void ); #ifdef DUMP extern uint64_t hdr_mfilesz; #endif /* DUMP */ /* remote tape protocol declarations (should be a system header file) */ extern int rmtopen( char *, int, ... ); extern int rmtclose( int ); extern int rmtfstat( int, struct stat * ); extern int rmtioctl( int, int, ... ); extern int rmtread( int, void*, uint); extern int rmtwrite( int, const void *, uint); /* forward declarations of locally defined static functions ******************/ /* strategy functions */ static int ds_match( int, char *[], drive_t * ); static int ds_instantiate( int, char *[], drive_t * ); /* manager operations */ static bool_t do_init( drive_t * ); static bool_t do_sync( drive_t * ); static int do_begin_read( drive_t * ); static char *do_read( drive_t *, size_t , size_t *, int * ); static void do_return_read_buf( drive_t *, char *, size_t ); static void do_get_mark( drive_t *, drive_mark_t * ); static int do_seek_mark( drive_t *, drive_mark_t * ); static int do_next_mark( drive_t * ); static void do_get_mark( drive_t *, drive_mark_t * ); static void do_end_read( drive_t * ); static int do_begin_write( drive_t * ); static void do_set_mark( drive_t *, drive_mcbfp_t, void *, drive_markrec_t * ); static char * do_get_write_buf( drive_t *, size_t , size_t * ); static int do_write( drive_t *, char *, size_t ); static size_t do_get_align_cnt( drive_t * ); static int do_end_write( drive_t *, off64_t * ); static int do_fsf( drive_t *, int , int *); static int do_bsf( drive_t *, int , int *); static int do_rewind( drive_t * ); static int do_erase( drive_t * ); static int do_eject_media( drive_t * ); static int do_get_device_class( drive_t * ); static void do_display_metrics( drive_t *drivep ); static void do_quit( drive_t * ); /* misc. local utility funcs */ static int mt_op(int , int , int ); static int determine_write_error( int, int ); static int read_label( drive_t *); static bool_t tape_rec_checksum_check( drive_context_t *, char * ); static void set_recommended_sizes( drive_t * ); static void display_access_failed_message( drive_t *); static bool_t get_tpcaps( drive_t * ); static int prepare_drive( drive_t *drivep ); static bool_t Open( drive_t *drivep ); static void Close( drive_t *drivep ); static int Read( drive_t *drivep, char *bufp, size_t cnt, int *errnop ); static int Write( drive_t *drivep, char *bufp, size_t cnt, int *saved_errnop ); static int record_hdr_validate( drive_t *drivep, char *bufp, bool_t chkoffpr ); static int ring_read( void *clientctxp, char *bufp ); static int ring_write( void *clientctxp, char *bufp ); static double percent64( off64_t num, off64_t denom ); static int getrec( drive_t *drivep ); static int write_record( drive_t *drivep, char *bufp, bool_t chksumpr, bool_t xlatepr ); static ring_msg_t * Ring_get( ring_t *ringp ); static void Ring_reset( ring_t *ringp, ring_msg_t *msgp ); static void Ring_put( ring_t *ringp, ring_msg_t *msgp ); static int validate_media_file_hdr( drive_t *drivep ); static void calc_max_lost( drive_t *drivep ); static void display_ring_metrics( drive_t *drivep, int mlog_flags ); #ifdef CLRMTAUD static uint32_t rewind_and_verify( drive_t *drivep ); static uint32_t erase_and_verify( drive_t *drivep ); static uint32_t bsf_and_verify( drive_t *drivep ); static uint32_t fsf_and_verify( drive_t *drivep ); #else /* CLRMTAUD */ static short rewind_and_verify( drive_t *drivep ); static short erase_and_verify( drive_t *drivep ); static short bsf_and_verify( drive_t *drivep ); static short fsf_and_verify( drive_t *drivep ); #endif /* CLRMTAUD */ static bool_t set_best_blk_and_rec_sz( drive_t *drivep ); static bool_t isefsdump( drive_t *drivep ); static bool_t isxfsdumperasetape( drive_t *drivep ); /* RMT trace stubs */ #ifdef RMTDBG static int dbgrmtopen( char *, int ); static int dbgrmtclose( int ); static int dbgrmtioctl( int, int, void * ); static int dbgrmtread( int, void *, uint); static int dbgrmtwrite( int, void *, uint); #endif /* RMTDBG */ #define ERASE_MAGIC "$^*@++! This tape was quick erased by SGI xfsdump $^*@++!" /* definition of locally defined global variables ****************************/ /* rmt drive strategy. referenced by drive.c */ drive_strategy_t drive_strategy_rmt = { DRIVE_STRATEGY_RMT, /* ds_id */ "minimum scsi tape (drive_minrmt)", /* ds_description */ ds_match, /* ds_match */ ds_instantiate, /* ds_instantiate */ 0x1000000ll, /* ds_recmarksep 16 MB */ OFF64MAX, /* ds_recmfilesz */ }; /* definition of locally defined static variables *****************************/ /* drive operators */ static drive_ops_t drive_ops = { do_init, /* do_init */ do_sync, /* do_sync */ do_begin_read, /* do_begin_read */ do_read, /* do_read */ do_return_read_buf, /* do_return_read_buf */ do_get_mark, /* do_get_mark */ do_seek_mark, /* do_seek_mark */ do_next_mark, /* do_next_mark */ do_end_read, /* do_end_read */ do_begin_write, /* do_begin_write */ do_set_mark, /* do_set_mark */ do_get_write_buf, /* do_get_write_buf */ do_write, /* do_write */ do_get_align_cnt, /* do_get_align_cnt */ do_end_write, /* do_end_write */ do_fsf, /* do_fsf */ do_bsf, /* do_bsf */ do_rewind, /* do_rewind */ do_erase, /* do_erase */ do_eject_media, /* do_eject_media */ do_get_device_class, /* do_get_device_class */ do_display_metrics, /* do_display_metrics */ do_quit, /* do_quit */ }; static uint32_t cmdlineblksize = 0; /* definition of locally defined global functions ****************************/ /* definition of locally defined static functions ****************************/ /* strategy match - determines if this is the right strategy */ /* ARGSUSED */ static int ds_match( int argc, char *argv[], drive_t *drivep ) { int fd; int c; bool_t minrmt = BOOL_FALSE; /* heuristics to determine if this is a drive. */ if ( ! strcmp( drivep->d_pathname, "stdio" )) { return -10; } /* Check if the min rmt flag and block size have * been specified. * If so , this is a non-SGI drive and this is the right * strategy. */ { optind = 1; opterr = 0; while ( ( c = getopt( argc, argv, GETOPT_CMDSTRING )) != EOF ) { switch (c) { case GETOPT_BLOCKSIZE: if ( ! optarg || optarg[ 0 ] == '-' ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("-%c argument missing\n"), c ); return -10; } cmdlineblksize = ( uint32_t )atoi( optarg ); errno = 0; fd = open( drivep->d_pathname, O_RDONLY ); if ( fd < 0 ) return -10; close( fd ); break; case GETOPT_MINRMT: minrmt = BOOL_TRUE; break; } } if (minrmt == BOOL_TRUE) { if (cmdlineblksize != 0) return 20; else mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("Minimal rmt cannot be used without specifying blocksize. Use -%c\n"), GETOPT_BLOCKSIZE ); } } /* catch all */ return -10; } /* strategy instantiate - initializes the pre-allocated drive descriptor */ /*ARGSUSED*/ static bool_t ds_instantiate( int argc, char *argv[], drive_t *drivep ) { drive_context_t *contextp; int c; /* opportunity for sanity checking */ assert( sizeof( global_hdr_t ) <= STAPE_HDR_SZ ); assert( sizeof( rec_hdr_t ) == sizeofmember( drive_hdr_t, dh_specific )); assert( ! ( STAPE_MAX_RECSZ % PGSZ )); /* hook up the drive ops */ drivep->d_opsp = &drive_ops; /* allocate context for the drive manager */ contextp = ( drive_context_t * )calloc( 1, sizeof( drive_context_t )); assert( contextp ); memset( ( void * )contextp, 0, sizeof( *contextp )); /* do not enable a separate I/O thread, * more testing to be done first... */ contextp->dc_singlethreadedpr = BOOL_TRUE; /* scan the command line for the I/O buffer ring length * and record checksum request */ contextp->dc_ringlen = RINGLEN_DEFAULT; contextp->dc_ringpinnedpr = BOOL_FALSE; contextp->dc_recchksumpr = BOOL_FALSE; contextp->dc_unloadokpr = BOOL_FALSE; contextp->dc_filesz = 0; contextp->dc_isQICpr = BOOL_FALSE; optind = 1; opterr = 0; while ( ( c = getopt( argc, argv, GETOPT_CMDSTRING )) != EOF ) { switch ( c ) { case GETOPT_RINGLEN: if ( ! optarg || optarg[ 0 ] == '-' ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("-%c argument missing\n"), c ); return BOOL_FALSE; } contextp->dc_ringlen = ( size_t )atoi( optarg ); if ( contextp->dc_ringlen < RINGLEN_MIN || contextp->dc_ringlen > RINGLEN_MAX ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_DRIVE, _("-%c argument must be " "between %u and %u: ignoring %u\n"), c, RINGLEN_MIN, RINGLEN_MAX, contextp->dc_ringlen ); return BOOL_FALSE; } break; case GETOPT_RINGPIN: contextp->dc_ringpinnedpr = BOOL_TRUE; break; case GETOPT_RECCHKSUM: contextp->dc_recchksumpr = BOOL_TRUE; break; case GETOPT_UNLOAD: contextp->dc_unloadokpr = BOOL_TRUE; break; case GETOPT_QIC: contextp->dc_isQICpr = BOOL_TRUE; break; #ifdef DUMP case GETOPT_OVERWRITE: contextp->dc_overwritepr = BOOL_TRUE; mlog( MLOG_DEBUG | MLOG_DRIVE, _("Overwrite command line option\n") ); break; case GETOPT_FILESZ: if ( ! optarg || optarg [ 0 ] == '-' ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("-%c argument missing\n"), c ); return BOOL_FALSE; } contextp->dc_filesz = (off64_t)atoi( optarg ) * 1024 * 1024; if (contextp->dc_filesz <= 0) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("-%c argument must be a " "positive number (MB): ignoring %u\n"), c, contextp->dc_filesz ); return BOOL_FALSE; } break; #endif } } /* set drive file descriptor to null value */ contextp->dc_fd = -1; /* record location of context descriptor in drive descriptor */ drivep->d_contextp = (void *)contextp; /* indicate neither capacity nor rate estimates available */ drivep->d_cap_est = -1; drivep->d_rate_est = -1; /* if threads not allowed, allocate a record buffer. otherwise * create a ring, from which buffers will be taken. */ if ( contextp->dc_singlethreadedpr ) { contextp->dc_bufp = ( char * )memalign( PGSZ, STAPE_MAX_RECSZ ); assert( contextp->dc_bufp ); } else { int rval; mlog( (MLOG_NITTY + 1) | MLOG_DRIVE, "ring op: create: ringlen == %u\n", contextp->dc_ringlen ); contextp->dc_ringp = ring_create( contextp->dc_ringlen, STAPE_MAX_RECSZ, contextp->dc_ringpinnedpr, drivep->d_index, ring_read, ring_write, ( void * )drivep, &rval ); if ( ! contextp->dc_ringp ) { if ( rval == ENOMEM ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_DRIVE, _("unable to allocate memory " "for I/O buffer ring\n") ); } else if ( rval == E2BIG ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_DRIVE, _("not enough physical memory " "to pin down I/O buffer ring\n") ); } else if ( rval == EPERM ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_DRIVE, _("not allowed " "to pin down I/O buffer ring\n") ); } else { assert( 0 ); } return BOOL_FALSE; } } /* several of contextp predicates cannot yet be determined. * mark them as unknown for now. however, if this is an RMT * access, we know immediately some capabilities are missing. */ /* specify that we are currently neither reading nor writing */ contextp->dc_mode = OM_NONE; /* set the capabilities flags advertised in the drive_t d_capabilities * field that we know a priori to be true. later additional flags * may be set */ drivep->d_capabilities = 0 | DRIVE_CAP_BSF | DRIVE_CAP_FSF | DRIVE_CAP_REWIND | DRIVE_CAP_FILES | DRIVE_CAP_NEXTMARK | DRIVE_CAP_READ | DRIVE_CAP_REMOVABLE | DRIVE_CAP_ERASE | DRIVE_CAP_EJECT ; return BOOL_TRUE; } /* drive op init - do more time-consuming init/checking here. read and * write headers are available now. * * NOTE: * When using a RMT device, the MTIOCGETBLKINFO, MTCAPABILITY and * MTSPECOP ioctl calls are not supported. This means that we have * to assume that the drive does not support the MTCAN_APPEND capability. */ /* ARGSUSED */ static bool_t do_init( drive_t *drivep ) { #ifdef DUMP drive_hdr_t *dwhdrp = drivep->d_writehdrp; media_hdr_t *mwhdrp = ( media_hdr_t * )dwhdrp->dh_upper; #endif /* DUMP */ mlog( MLOG_DEBUG | MLOG_DRIVE, "rmt drive op: init\n" ); #ifdef DUMP /* fill in media strategy id: artifact of first version of xfsdump */ mwhdrp->mh_strategyid = MEDIA_STRATEGY_RMVTAPE; #endif /* DUMP */ return BOOL_TRUE; } /* wait here for slave to complete initialization. * set drive capabilities flags. NOTE: currently don't make use of this * feature: drive initialization done whenever block/record sizes unknown. */ /* ARGSUSED */ static bool_t do_sync( drive_t *drivep ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "rmt drive op: sync\n" ); return BOOL_TRUE; } /* begin_read * Set up the tape device and read the media file header. * if allowed, begin read-ahead. * * RETURNS: * 0 on success * DRIVE_ERROR_* on failure * */ static int do_begin_read( drive_t *drivep ) { drive_context_t *contextp; int rval; mlog( MLOG_DEBUG | MLOG_DRIVE, "rmt drive op: begin read\n" ); /* get drive context */ contextp = ( drive_context_t * )drivep->d_contextp; /* verify protocol being followed */ assert( drivep->d_capabilities & DRIVE_CAP_READ ); assert( contextp->dc_mode == OM_NONE ); assert( ! contextp->dc_recp ); /* get a record buffer to use during initialization. */ if ( contextp->dc_singlethreadedpr ) { contextp->dc_recp = contextp->dc_bufp; } else { assert( contextp->dc_ringp ); contextp->dc_msgp = Ring_get( contextp->dc_ringp ); assert( contextp->dc_msgp->rm_stat == RING_STAT_INIT ); contextp->dc_recp = contextp->dc_msgp->rm_bufp; } /* if the tape is not open, open, determine the record size, and * read the first record. otherwise read a record using the record * size previously determined. */ contextp->dc_iocnt = 0; if ( contextp->dc_fd < 0 ) { assert( contextp->dc_fd == -1 ); rval = prepare_drive( drivep ); if ( rval ) { if ( ! contextp->dc_singlethreadedpr ) { Ring_reset( contextp->dc_ringp, contextp->dc_msgp ); } contextp->dc_msgp = 0; contextp->dc_recp = 0; return rval; } } else { rval = read_label( drivep ) ; if ( rval ) { if ( ! contextp->dc_singlethreadedpr ) { Ring_reset( contextp->dc_ringp, contextp->dc_msgp ); } contextp->dc_msgp = 0; contextp->dc_recp = 0; return rval; } } assert( contextp->dc_iocnt == 1 ); /* set by prepare_drive or read_label */ /* all is well. adjust context. don't kick off read-aheads just yet; * the client may not want this media file. */ if ( ! contextp->dc_singlethreadedpr ) { contextp->dc_msgp->rm_op = RING_OP_NOP; contextp->dc_msgp->rm_user = 0; /* do diff. use in do_seek */ Ring_put( contextp->dc_ringp, contextp->dc_msgp ); contextp->dc_msgp = 0; } contextp->dc_recp = 0; contextp->dc_recendp = 0; contextp->dc_dataendp = 0; contextp->dc_ownedp = 0; contextp->dc_nextp = 0; contextp->dc_reccnt = 1; /* used to detect attempt to read after an error was reported */ contextp->dc_errorpr = BOOL_FALSE; /* successfully entered read mode. must do end_read to get out. */ contextp->dc_mode = OM_READ; return 0; } /* do_read * Supply the caller with all or a portion of the current buffer, * filled with data from a record. * * RETURNS: * a pointer to a buffer containing "*actual_bufszp" bytes of data * or 0 on failure with "*rvalp" containing the error (DRIVE_ERROR_...) * */ static char * do_read( drive_t *drivep, size_t wantedcnt, size_t *actualcntp, int *rvalp ) { drive_context_t *contextp; size_t availcnt; size_t actualcnt; int rval; mlog( MLOG_DEBUG | MLOG_DRIVE, "rmt drive op: read: wanted %u (0x%x)\n", wantedcnt, wantedcnt ); /* get context ptrs */ contextp = ( drive_context_t * )drivep->d_contextp; /* assert protocol being followed */ assert( contextp->dc_mode == OM_READ ); assert( ! contextp->dc_errorpr ); assert( ! contextp->dc_ownedp ); assert( wantedcnt > 0 ); /* clear the return status field */ *rvalp = 0; /* read a new record if necessary */ rval = getrec( drivep ); if ( rval ) { mlog( MLOG_NITTY | MLOG_DRIVE, "rmt drive op read returning error rval=%d\n", rval ); *rvalp = rval; return 0; } /* figure how much data is available, and how much should be supplied */ availcnt = ( size_t )( contextp->dc_dataendp - contextp->dc_nextp ); actualcnt = min( wantedcnt, availcnt ); /* adjust the context */ contextp->dc_ownedp = contextp->dc_nextp; contextp->dc_nextp += actualcnt; assert( contextp->dc_nextp <= contextp->dc_dataendp ); mlog( MLOG_NITTY | MLOG_DRIVE, "rmt drive op read actual == %d (0x%x)\n", actualcnt, actualcnt ); *actualcntp = actualcnt; return contextp->dc_ownedp; } /* do_return_read_buf - * Lets the caller give back the buffer portion obtained from the preceding * call to do_read(). * * RETURNS: * void */ /* ARGSUSED */ static void do_return_read_buf( drive_t *drivep, char *bufp, size_t retcnt ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; /* REFERENCED */ size_t ownedcnt; mlog( MLOG_DEBUG | MLOG_DRIVE, "rmt drive op: return read buf: sz %d (0x%x)\n", retcnt, retcnt ); /* assert protocol being followed */ assert( contextp->dc_mode == OM_READ ); assert( ! contextp->dc_errorpr ); assert( contextp->dc_ownedp ); assert( bufp == contextp->dc_ownedp ); /* calculate how much the caller owns */ assert( contextp->dc_nextp >= contextp->dc_ownedp ); ownedcnt = ( size_t )( contextp->dc_nextp - contextp->dc_ownedp ); assert( ownedcnt == retcnt ); /* take possession of buffer portion */ contextp->dc_ownedp = 0; /* if caller is done with this record, take the buffer back * and (if ring in use) give buffer to ring for read-ahead. */ if ( contextp->dc_nextp >= contextp->dc_dataendp ) { assert( contextp->dc_nextp == contextp->dc_dataendp ); if ( ! contextp->dc_singlethreadedpr ) { contextp->dc_msgp->rm_op = RING_OP_READ; Ring_put( contextp->dc_ringp, contextp->dc_msgp ); contextp->dc_msgp = 0; } contextp->dc_recp = 0; contextp->dc_recendp = 0; contextp->dc_dataendp = 0; contextp->dc_nextp = 0; contextp->dc_reccnt++; } } /* do_get_mark * Get the current read tape location. * * RETURNS: * void */ static void do_get_mark( drive_t *drivep, drive_mark_t *markp ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; off64_t offset; mlog( MLOG_DEBUG | MLOG_DRIVE, "rmt drive op: get mark\n" ); /* assert protocol being followed */ assert( contextp->dc_mode == OM_READ ); assert( ! contextp->dc_errorpr ); assert( ! contextp->dc_ownedp ); /* the mark is simply the offset into the media file of the * next byte to be read. */ offset = contextp->dc_reccnt * ( off64_t )tape_recsz; if ( contextp->dc_recp ) { offset += ( off64_t )( contextp->dc_nextp - contextp->dc_recp ); } *markp = ( drive_mark_t )offset; return; } typedef enum { SEEKMODE_BUF, SEEKMODE_RAW } seekmode_t; /* do_seek_mark * Advance the tape to the given mark. does dummy reads to * advance tape, as well as FSR if supported. * * RETURNS: * 0 on success * DRIVE_ERROR_* on failure * */ static int do_seek_mark( drive_t *drivep, drive_mark_t *markp ) { drive_context_t *contextp; off64_t wantedoffset; off64_t currentoffset; /* get the drive context */ contextp = (drive_context_t *)drivep->d_contextp; /* assert protocol being followed */ assert( contextp->dc_mode == OM_READ ); assert( ! contextp->dc_errorpr ); assert( ! contextp->dc_ownedp ); /* the desired mark is passed by reference, and is really just an * offset into the raw (incl rec hdrs) read stream */ wantedoffset = *( off64_t * )markp; mlog( MLOG_DEBUG | MLOG_DRIVE, "drive op: seek mark: %lld (0x%llx)\n", wantedoffset, wantedoffset ); /* determine the current offset. assert that the wanted offset is * not less than the current offset. */ currentoffset = contextp->dc_reccnt * ( off64_t )tape_recsz; if ( contextp->dc_recp ) { uint32_t recoff; #ifdef DEBUG rec_hdr_t *rechdrp = ( rec_hdr_t * )contextp->dc_recp; #endif assert( contextp->dc_nextp >= contextp->dc_recp ); recoff = ( uint32_t )( contextp->dc_nextp - contextp->dc_recp ); assert( recoff <= tape_recsz ); assert( rechdrp->rec_used <= tape_recsz ); assert( recoff >= STAPE_HDR_SZ ); assert( rechdrp->rec_used >= STAPE_HDR_SZ ); assert( recoff <= rechdrp->rec_used ); currentoffset += ( off64_t )recoff; } assert( wantedoffset >= currentoffset ); /* if we are currently holding a record and the desired offset * is not within the current record, eat the current record. */ if ( contextp->dc_recp ) { off64_t nextrecoffset; rec_hdr_t *rechdrp = ( rec_hdr_t * )contextp->dc_recp; nextrecoffset = contextp->dc_reccnt * ( off64_t )tape_recsz + ( off64_t )rechdrp->rec_used; if ( wantedoffset >= nextrecoffset ) { uint32_t recoff; size_t wantedcnt; char *dummybufp; size_t actualcnt; int rval; /* if this is the last record, the wanted offset * must be just after it. */ if ( rechdrp->rec_used < tape_recsz ) { assert( wantedoffset == nextrecoffset ); } /* figure how much to ask for */ assert( contextp->dc_nextp >= contextp->dc_recp ); recoff = ( uint32_t )( contextp->dc_nextp - contextp->dc_recp ); wantedcnt = ( size_t )( rechdrp->rec_used - recoff ); /* eat that much tape */ rval = 0; dummybufp = do_read( drivep, wantedcnt, &actualcnt, &rval ); if ( rval ) { return rval; } assert( actualcnt == wantedcnt ); do_return_read_buf( drivep, dummybufp, actualcnt ); currentoffset += ( off64_t )actualcnt; assert( currentoffset == nextrecoffset ); assert( wantedoffset >= currentoffset ); assert( ! contextp->dc_recp ); assert( currentoffset == contextp->dc_reccnt * ( off64_t )tape_recsz ); } } /* if FSR is supported, while the desired offset is more than a record * away, eat records. this is tricky. if read-ahead has already read * to the desired point, no need to FSR: fall through to next code block * where we get there by eating excess records. if read-ahead has not * made it there, suspend read-ahead, eat those readahead records, * FSR the remaining, and resume readahead. */ if ( contextp->dc_canfsrpr && wantedoffset - currentoffset >= ( off64_t )tape_recsz ) { off64_t wantedreccnt; seekmode_t seekmode; assert( ! contextp->dc_recp ); wantedreccnt = wantedoffset / ( off64_t )tape_recsz; if ( contextp->dc_singlethreadedpr ) { seekmode = SEEKMODE_RAW; } else { seekmode = SEEKMODE_BUF; } assert( wantedreccnt != 0 ); /* so NOP below can be * distinguished from use * in do_begin_read */ while ( contextp->dc_reccnt < wantedreccnt ) { off64_t recskipcnt64; off64_t recskipcnt64remaining; if ( seekmode == SEEKMODE_BUF ) { ring_stat_t rs; assert( ! contextp->dc_msgp ); contextp->dc_msgp = Ring_get( contextp->dc_ringp ); rs = contextp->dc_msgp->rm_stat; if ( rs == RING_STAT_ERROR ) { contextp->dc_errorpr = BOOL_TRUE; return contextp->dc_msgp->rm_rval; } if ( rs != RING_STAT_OK && rs != RING_STAT_INIT && rs != RING_STAT_NOPACK ) { assert( 0 ); contextp->dc_errorpr = BOOL_TRUE; return DRIVE_ERROR_CORE; } if ( rs == RING_STAT_OK ) { contextp->dc_reccnt++; } if ( rs == RING_STAT_NOPACK && contextp->dc_msgp->rm_user == wantedreccnt ) { seekmode = SEEKMODE_RAW; } contextp->dc_msgp->rm_op = RING_OP_NOP; contextp->dc_msgp->rm_user = wantedreccnt; Ring_put( contextp->dc_ringp, contextp->dc_msgp ); contextp->dc_msgp = 0; continue; } assert( contextp->dc_reccnt == contextp->dc_iocnt ); assert( wantedreccnt > contextp->dc_reccnt ); recskipcnt64 = wantedreccnt - contextp->dc_reccnt; recskipcnt64remaining = recskipcnt64; while ( recskipcnt64remaining ) { int recskipcnt; int saved_errno; int rval; assert( recskipcnt64remaining > 0 ); if ( recskipcnt64remaining > INTGENMAX ) { recskipcnt = INTGENMAX; } else { recskipcnt = ( int ) recskipcnt64remaining; } assert( recskipcnt > 0 ); rval = mt_op( contextp->dc_fd, MTFSR, recskipcnt ); saved_errno = errno; if ( rval ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("could not forward space %d " "tape blocks: " "rval == %d, errno == %d (%s)\n"), rval, saved_errno, strerror( saved_errno )); return DRIVE_ERROR_MEDIA; } recskipcnt64remaining -= ( off64_t )recskipcnt; } contextp->dc_reccnt += recskipcnt64; contextp->dc_iocnt += recskipcnt64; currentoffset = contextp->dc_reccnt * ( off64_t )tape_recsz; assert( wantedoffset >= currentoffset ); assert( wantedoffset - currentoffset < ( off64_t )tape_recsz ); } } /* remove excess records by eating them. won't be any if * FSR supported */ while ( wantedoffset - currentoffset >= ( off64_t )tape_recsz ) { size_t wantedcnt; char *dummybufp; size_t actualcnt; int rval; assert( ! contextp->dc_recp ); /* figure how much to ask for. to eat an entire record, * ask for a record sans the header. do_read will eat * the header, we eat the rest. */ wantedcnt = ( size_t )( tape_recsz - STAPE_HDR_SZ ); /* eat that much tape */ rval = 0; dummybufp = do_read( drivep, wantedcnt, &actualcnt, &rval ); if ( rval ) { return rval; } assert( actualcnt == wantedcnt ); do_return_read_buf( drivep, dummybufp, actualcnt ); assert( ! contextp->dc_recp ); currentoffset += ( off64_t )tape_recsz; assert( currentoffset == contextp->dc_reccnt * ( off64_t )tape_recsz ); } /* eat that portion of the next record leading up to the * desired offset. */ if ( wantedoffset != currentoffset ) { size_t wantedcnt; char *dummybufp; size_t actualcnt; assert( wantedoffset > currentoffset ); assert( wantedoffset - currentoffset < ( off64_t )tape_recsz ); wantedcnt = ( size_t )( wantedoffset - currentoffset ); if ( contextp->dc_recp ) { uint32_t recoff; #ifdef DEBUG rec_hdr_t *rechdrp = ( rec_hdr_t * )contextp->dc_recp; #endif recoff = ( uint32_t )( contextp->dc_nextp - contextp->dc_recp ); assert( recoff <= tape_recsz ); assert( rechdrp->rec_used <= tape_recsz ); assert( recoff >= STAPE_HDR_SZ ); assert( rechdrp->rec_used >= STAPE_HDR_SZ ); assert( recoff <= rechdrp->rec_used ); assert( recoff + wantedcnt <= rechdrp->rec_used ); } else { assert( wantedcnt >= STAPE_HDR_SZ ); wantedcnt -= STAPE_HDR_SZ; } /* eat that much tape */ if ( wantedcnt > 0 ) { int rval; rval = 0; dummybufp = do_read( drivep, wantedcnt, &actualcnt, &rval ); if ( rval ) { return rval; } assert( actualcnt == wantedcnt ); do_return_read_buf( drivep, dummybufp, actualcnt ); } } /* as a sanity check, refigure the current offset and make sure * it is equal to the wanted offset */ currentoffset = contextp->dc_reccnt * ( off64_t )tape_recsz; if ( contextp->dc_recp ) { uint32_t recoff; #ifdef DEBUG rec_hdr_t *rechdrp = ( rec_hdr_t * )contextp->dc_recp; #endif assert( contextp->dc_nextp >= contextp->dc_recp ); recoff = ( uint32_t )( contextp->dc_nextp - contextp->dc_recp ); assert( recoff <= tape_recsz ); assert( rechdrp->rec_used <= tape_recsz ); assert( recoff >= STAPE_HDR_SZ ); assert( rechdrp->rec_used >= STAPE_HDR_SZ ); assert( recoff <= rechdrp->rec_used ); currentoffset += ( off64_t )recoff; } assert( wantedoffset == currentoffset ); return 0; } /* do_next_mark * Advance the tape position to the next valid mark. if in * error mode, first attempt to move past error by re-reading. if * that fails, try to FSR. also deals with QIC possibility of * reading a block not at a record boundary. * * RETURNS: * 0 on success * DRIVE_ERROR_* on failure */ static int do_next_mark( drive_t *drivep ) { drive_context_t *contextp = (drive_context_t *)drivep->d_contextp; rec_hdr_t *rechdrp; char *p; ix_t trycnt; const ix_t maxtrycnt = 5; int nread; off64_t markoff; int saved_errno; size_t tailsz; int rval; /* assert protocol being followed. */ assert( contextp->dc_mode == OM_READ ); assert( ! contextp->dc_errorpr ); assert( ! contextp->dc_ownedp ); mlog( MLOG_DEBUG | MLOG_DRIVE, "rmt drive op: next mark\n" ); trycnt = 0; if ( contextp->dc_errorpr ) { goto resetring; } else { goto noerrorsearch; } noerrorsearch: for ( ; ; ) { rval = getrec( drivep ); if ( rval == DRIVE_ERROR_CORRUPTION ) { goto resetring; } else if ( rval ) { return rval; } rechdrp = ( rec_hdr_t * )contextp->dc_recp; assert( rechdrp->first_mark_offset != 0 ); if ( rechdrp->first_mark_offset > 0 ) { off64_t markoff = rechdrp->first_mark_offset - rechdrp->file_offset; off64_t curoff = ( off64_t )( contextp->dc_nextp - contextp->dc_recp ); assert( markoff > 0 ); assert( curoff > 0 ); if ( markoff >= curoff ) { break; } } if ( ! contextp->dc_singlethreadedpr ) { Ring_put( contextp->dc_ringp, contextp->dc_msgp ); contextp->dc_msgp = 0; } contextp->dc_recp = 0; contextp->dc_reccnt++; } assert( rechdrp->first_mark_offset - rechdrp->file_offset <= ( off64_t )tape_recsz ); contextp->dc_nextp = contextp->dc_recp + ( size_t )( rechdrp->first_mark_offset - rechdrp->file_offset ); assert( contextp->dc_nextp <= contextp->dc_dataendp ); assert( contextp->dc_nextp >= contextp->dc_recp + STAPE_HDR_SZ ); if ( contextp->dc_nextp == contextp->dc_dataendp ) { if ( ! contextp->dc_singlethreadedpr ) { Ring_put( contextp->dc_ringp, contextp->dc_msgp ); contextp->dc_msgp = 0; } contextp->dc_recp = 0; contextp->dc_reccnt++; } return 0; resetring: if ( ! contextp->dc_singlethreadedpr ) { Ring_reset( contextp->dc_ringp, contextp->dc_msgp ); contextp->dc_msgp = 0; } contextp->dc_recp = 0; /* get a record buffer and cast a record header pointer */ if ( contextp->dc_singlethreadedpr ) { contextp->dc_recp = contextp->dc_bufp; } else { contextp->dc_msgp = Ring_get( contextp->dc_ringp ); assert( contextp->dc_msgp->rm_stat == RING_STAT_INIT ); contextp->dc_recp = contextp->dc_msgp->rm_bufp; } rechdrp = ( rec_hdr_t * )contextp->dc_recp; goto readrecord; readrecord: trycnt++; if ( trycnt > maxtrycnt ) { mlog( MLOG_NORMAL | MLOG_DRIVE, _("unable to locate next mark in media file\n") ); return DRIVE_ERROR_MEDIA; } nread = Read( drivep, contextp->dc_recp, tape_recsz, &saved_errno ); goto validateread; validateread: if ( nread == ( int )tape_recsz ) { goto validatehdr; } if ( nread >= 0 ) { assert( ( size_t )nread <= tape_recsz ); mlog( MLOG_DEBUG | MLOG_DRIVE, "short read (nread == %d, record size == %d)\n", nread, tape_recsz ); goto getbeyonderror; } /* some other error */ mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_DRIVE, _("unexpected error attempting to read record: " "read returns %d, errno %s (%s)\n"), nread, errno, strerror( errno )); goto getbeyonderror; validatehdr: rval = record_hdr_validate( drivep, contextp->dc_recp, BOOL_FALSE ); if ( rval && ( contextp->dc_isQICpr == BOOL_TRUE || contextp->dc_isQICpr == BOOL_UNKNOWN )) { goto huntQIC; } if ( rval ) { goto readrecord; } contextp->dc_reccnt = rechdrp->file_offset / ( off64_t )tape_recsz; contextp->dc_iocnt = contextp->dc_reccnt + 1; if ( rechdrp->first_mark_offset < 0 ) { mlog( MLOG_NORMAL | MLOG_DRIVE, _("valid record %lld but no mark\n"), contextp->dc_iocnt - 1 ); goto readrecord; } assert( ! ( rechdrp->file_offset % ( off64_t )tape_recsz )); markoff = rechdrp->first_mark_offset - rechdrp->file_offset; assert( markoff >= ( off64_t )STAPE_HDR_SZ ); assert( markoff < ( off64_t )tape_recsz ); assert( rechdrp->rec_used > STAPE_HDR_SZ ); assert( rechdrp->rec_used < tape_recsz ); goto alliswell; alliswell: contextp->dc_nextp = contextp->dc_recp + ( size_t )markoff; assert( ! ( rechdrp->file_offset % ( off64_t )tape_recsz )); contextp->dc_reccnt = rechdrp->file_offset / ( off64_t )tape_recsz; contextp->dc_iocnt = contextp->dc_reccnt + 1; contextp->dc_recendp = contextp->dc_recp + tape_recsz; contextp->dc_dataendp = contextp->dc_recp + rechdrp->rec_used; assert( contextp->dc_dataendp <= contextp->dc_recendp ); assert( contextp->dc_nextp < contextp->dc_dataendp ); contextp->dc_errorpr = BOOL_FALSE; mlog( MLOG_NORMAL | MLOG_DRIVE, _("resynchronized at record %lld " "offset %u\n"), contextp->dc_iocnt - 1, contextp->dc_nextp - contextp->dc_recp ); return 0; getbeyonderror: rval = mt_op( contextp->dc_fd, MTFSR, 1 ); saved_errno = errno; if ( rval ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("could not forward space one tape block beyond " "read error: rval == %d, errno == %d (%s)\n"), rval, saved_errno, strerror( saved_errno )); return DRIVE_ERROR_MEDIA; } goto readrecord; huntQIC: /* we have a full tape_recsz record. look for the magic number at the * beginning of each 512 byte block. If we find one, shift that and * the following blocks to the head of the record buffer, and try * to read the remaining blocks in the record. */ for ( p = contextp->dc_recp + QIC_BLKSZ ; p < contextp->dc_recendp ; p += QIC_BLKSZ ) { if ( *( uint64_t * )p == STAPE_MAGIC ) { goto adjustQIC; } } goto readrecord; adjustQIC: tailsz = ( size_t )( contextp->dc_recendp - p ); memcpy( ( void * )contextp->dc_recp, ( void * )p, tailsz ); nread = Read( drivep, contextp->dc_recp + tailsz, tape_recsz - tailsz, &saved_errno ); goto validateread; } /* do_end_read * Discard any buffered reads. * Tell the reader/writer process to wait. * * RETURNS: * void */ static void do_end_read( drive_t *drivep ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; mlog( MLOG_DEBUG | MLOG_DRIVE, "rmt drive op: end read\n" ); /* assert protocol being followed */ assert( contextp->dc_mode == OM_READ ); assert( ! contextp->dc_ownedp ); /* In the scsi version, read_label() does a status command to the * drive to then decide if doing a 'fsf' is appropriate. For minrmt, * we don't have the status command so we need to space forward at * the moment we know we need to go forward... which is here. */ ( void )fsf_and_verify( drivep ); if ( ! contextp->dc_singlethreadedpr ) { Ring_reset( contextp->dc_ringp, contextp->dc_msgp ); contextp->dc_msgp = 0; } contextp->dc_recp = 0; contextp->dc_mode = OM_NONE; } /* do_begin_write * prepare drive for writing. set up drive context. write a header record. * * RETURNS: * 0 on success * DRIVE_ERROR_... on failure */ static int do_begin_write( drive_t *drivep ) { drive_context_t *contextp; drive_hdr_t *dwhdrp; global_hdr_t *gwhdrp; rec_hdr_t *tpwhdrp; rec_hdr_t *rechdrp; int rval; media_hdr_t *mwhdrp; content_hdr_t *ch; content_inode_hdr_t *cih; global_hdr_t *tmpgh; drive_hdr_t *tmpdh; media_hdr_t *tmpmh; rec_hdr_t *tmprh; content_hdr_t *tmpch; content_inode_hdr_t *tmpcih; /* get drive context */ contextp = ( drive_context_t * )drivep->d_contextp; mlog( MLOG_DEBUG | MLOG_DRIVE, "rmt drive op: begin write\n" ); /* verify protocol being followed */ assert( contextp->dc_mode == OM_NONE ); assert( ! drivep->d_markrecheadp ); assert( ! contextp->dc_recp ); /* get pointers into global write header */ gwhdrp = drivep->d_gwritehdrp; dwhdrp = drivep->d_writehdrp; tpwhdrp = ( rec_hdr_t * )dwhdrp->dh_specific; /* must already be open. The only way to open is to do a begin_read. * so all interaction with tape requires reading first. */ assert( contextp->dc_fd != -1 ); /* fill in write header's drive specific info */ tpwhdrp->magic = STAPE_MAGIC; tpwhdrp->version = STAPE_VERSION; tpwhdrp->blksize = ( int32_t )tape_blksz; tpwhdrp->recsize = ( int32_t )tape_recsz; tpwhdrp->rec_used = 0; tpwhdrp->file_offset = 0; tpwhdrp->first_mark_offset= 0; tpwhdrp->capability = drivep->d_capabilities; /* get a record buffer. will be used for the media file header, * and is needed to "prime the pump" for first call to do_write. */ assert( ! contextp->dc_recp ); if ( contextp->dc_singlethreadedpr ) { assert( contextp->dc_bufp ); contextp->dc_recp = contextp->dc_bufp; } else { assert( contextp->dc_ringp ); assert( ! contextp->dc_msgp ); contextp->dc_msgp = Ring_get( contextp->dc_ringp ); assert( contextp->dc_msgp->rm_stat == RING_STAT_INIT ); contextp->dc_recp = contextp->dc_msgp->rm_bufp; } /* write the record. be sure to prevent a record checksum from * being produced! */ contextp->dc_iocnt = 0; memset( ( void * )contextp->dc_recp, 0, tape_recsz ); tmpgh = (global_hdr_t *)contextp->dc_recp; tmpdh = (drive_hdr_t *)tmpgh->gh_upper; tmpmh = (media_hdr_t *)tmpdh->dh_upper; tmprh = (rec_hdr_t *)tmpdh->dh_specific; tmpch = (content_hdr_t *)tmpmh->mh_upper; tmpcih = (content_inode_hdr_t *)tmpch->ch_specific; mwhdrp = (media_hdr_t *)dwhdrp->dh_upper; ch = (content_hdr_t *)mwhdrp->mh_upper; cih = (content_inode_hdr_t *)ch->ch_specific; xlate_global_hdr(gwhdrp, tmpgh, 1); xlate_drive_hdr(dwhdrp, tmpdh, 1); xlate_media_hdr(mwhdrp, tmpmh, 1); xlate_content_hdr(ch, tmpch, 1); xlate_content_inode_hdr(cih, tmpcih, 1); xlate_rec_hdr(tpwhdrp, tmprh, 1); /* checksum the global header */ global_hdr_checksum_set( tmpgh ); rval = write_record( drivep, contextp->dc_recp, BOOL_TRUE, BOOL_FALSE ); if ( rval ) { if ( ! contextp->dc_singlethreadedpr ) { Ring_reset( contextp->dc_ringp, contextp->dc_msgp ); contextp->dc_msgp = 0; } contextp->dc_recp = 0; return rval; } /* prepare the drive context. must have a record buffer ready to * go, header initialized. */ assert( ! contextp->dc_ownedp ); contextp->dc_reccnt = 1; /* count the header record */ contextp->dc_recendp = contextp->dc_recp + tape_recsz; contextp->dc_nextp = contextp->dc_recp + STAPE_HDR_SZ; /* intialize header in new record */ rechdrp = (rec_hdr_t*)contextp->dc_recp; rechdrp->magic = STAPE_MAGIC; rechdrp->version = STAPE_VERSION; rechdrp->file_offset = contextp->dc_reccnt * ( off64_t )tape_recsz; rechdrp->blksize = ( int32_t )tape_blksz; rechdrp->recsize = ( int32_t )tape_recsz; rechdrp->capability = drivep->d_capabilities; rechdrp->first_mark_offset = -1LL; uuid_copy( rechdrp->dump_uuid, gwhdrp->gh_dumpid ); /* set mode now so operators will work */ contextp->dc_mode = OM_WRITE; contextp->dc_errorpr = BOOL_FALSE; return 0; } /* do_set_mark - queue a mark request. if first mark set in record, record * in record. */ static void do_set_mark( drive_t *drivep, drive_mcbfp_t cbfuncp, void *cbcontextp, drive_markrec_t *markrecp ) { drive_context_t *contextp; off64_t nextoff; rec_hdr_t *rechdrp; /* get drive context */ contextp = ( drive_context_t * )drivep->d_contextp; /* verify protocol being followed */ assert( contextp->dc_mode == OM_WRITE ); assert( ! contextp->dc_errorpr ); assert( ! contextp->dc_ownedp ); assert( contextp->dc_recp ); assert( contextp->dc_nextp ); /* calculate and fill in the mark record offset */ assert( contextp->dc_recp ); nextoff = contextp->dc_reccnt * ( off64_t )tape_recsz + ( off64_t )( contextp->dc_nextp - contextp->dc_recp ); markrecp->dm_log = ( drive_mark_t )nextoff; mlog( MLOG_DEBUG | MLOG_DRIVE, "rmt drive op: set mark: %lld (0x%llx)\n", nextoff, nextoff ); /* note the location of the first mark in this tape record. */ rechdrp = ( rec_hdr_t * )contextp->dc_recp; if ( rechdrp->first_mark_offset == -1LL ) { assert( nextoff != -1LL ); rechdrp->first_mark_offset = nextoff; } /* put the mark on the tail of the queue. */ markrecp->dm_cbfuncp = cbfuncp; markrecp->dm_cbcontextp = cbcontextp; markrecp->dm_nextp = 0; if ( drivep->d_markrecheadp == 0 ) { drivep->d_markrecheadp = markrecp; drivep->d_markrectailp = markrecp; } else { assert( drivep->d_markrectailp ); drivep->d_markrectailp->dm_nextp = markrecp; drivep->d_markrectailp = markrecp; } } /* do_get_write_buf - supply the caller with some or all of the current record * buffer. the supplied buffer must be fully returned (via a single call to * do_write) prior to the next call to do_get_write_buf. * * RETURNS: * the address of a buffer * "actual_bufszp" points to the size of the buffer */ static char * do_get_write_buf( drive_t *drivep, size_t wantedcnt, size_t *actualcntp ) { drive_context_t *contextp; size_t remainingcnt; size_t actualcnt; /* get drive context */ contextp = ( drive_context_t * )drivep->d_contextp; /* verify protocol being followed */ assert( contextp->dc_mode == OM_WRITE ); assert( ! contextp->dc_errorpr ); assert( ! contextp->dc_ownedp ); assert( contextp->dc_recp ); assert( contextp->dc_nextp ); assert( contextp->dc_nextp < contextp->dc_recendp ); /* figure how much is available; supply the min of what is * available and what is wanted. */ remainingcnt = ( size_t )( contextp->dc_recendp - contextp->dc_nextp ); actualcnt = min( remainingcnt, wantedcnt ); *actualcntp = actualcnt; contextp->dc_ownedp = contextp->dc_nextp; contextp->dc_nextp += actualcnt; mlog( MLOG_DEBUG | MLOG_DRIVE, "rmt drive op: get write buf: wanted %u (0x%x) actual %u (0x%x)\n", wantedcnt, wantedcnt, actualcnt, actualcnt ); return contextp->dc_ownedp; } /* do_write - accept ownership of the portion of the current record buffer * being returned by the caller. if returned portion includes end of record * buffer, write the buffer and get and prepare a new one in anticipation of * the next call to do_get_write_buf. also, process any queued marks which * are guaranteed to be committed to media. NOTE: the caller must return * everything obtained with the preceeding call to do_get_write_buf. * * RETURNS: * 0 on success * non 0 on error */ /* ARGSUSED */ static int do_write( drive_t *drivep, char *bufp, size_t retcnt ) { drive_context_t *contextp; rec_hdr_t *rechdrp; global_hdr_t *gwhdrp; size_t heldcnt; off64_t last_rec_wrtn_wo_err; /* zero-based index */ int rval; /* get drive context and pointer to global write hdr */ contextp = ( drive_context_t * )drivep->d_contextp; gwhdrp = drivep->d_gwritehdrp; /* calculate how many bytes we believe caller is holding */ heldcnt = ( size_t )( contextp->dc_nextp - contextp->dc_ownedp ); mlog( MLOG_DEBUG | MLOG_DRIVE, "rmt drive op: write: retcnt %u (0x%x) heldcnt %u (0x%x)\n", retcnt, retcnt, heldcnt, heldcnt ); /* verify protocol being followed */ assert( contextp->dc_mode == OM_WRITE ); assert( ! contextp->dc_errorpr ); assert( contextp->dc_ownedp ); assert( contextp->dc_recp ); assert( contextp->dc_nextp ); assert( contextp->dc_nextp <= contextp->dc_recendp ); /* verify the caller is returning exactly what is held */ assert( bufp == contextp->dc_ownedp ); assert( retcnt == heldcnt ); /* take it back */ contextp->dc_ownedp = 0; /* if some portion of the record buffer has not yet been * held by the client, just return. */ if ( contextp->dc_nextp < contextp->dc_recendp ) { return 0; } /* record in record header that entire record is used */ rechdrp = ( rec_hdr_t * )contextp->dc_recp; rechdrp->rec_used = tape_recsz; /* write out the record buffer and get a new one. */ if ( contextp->dc_singlethreadedpr ) { rval = write_record( drivep, contextp->dc_recp, BOOL_TRUE, BOOL_TRUE ); last_rec_wrtn_wo_err = contextp->dc_reccnt; /* conv cnt to ix */ } else { contextp->dc_msgp->rm_op = RING_OP_WRITE; contextp->dc_msgp->rm_user = contextp->dc_reccnt; Ring_put( contextp->dc_ringp, contextp->dc_msgp ); contextp->dc_msgp = 0; contextp->dc_msgp = Ring_get( contextp->dc_ringp ); contextp->dc_recp = contextp->dc_msgp->rm_bufp; last_rec_wrtn_wo_err = contextp->dc_msgp->rm_user; switch( contextp->dc_msgp->rm_stat ) { case RING_STAT_OK: case RING_STAT_INIT: rval = 0; break; case RING_STAT_ERROR: rval = contextp->dc_msgp->rm_rval; break; default: assert( 0 ); return DRIVE_ERROR_CORE; } } /* check for errors. if none, commit all marks before a safety margin * before the no error offset. */ if ( rval ) { contextp->dc_errorpr = BOOL_TRUE; } else { off64_t recs_wrtn_wo_err; off64_t recs_committed; off64_t bytes_committed; recs_wrtn_wo_err = last_rec_wrtn_wo_err + 1; recs_committed = recs_wrtn_wo_err - contextp->dc_lostrecmax; bytes_committed = recs_committed * ( off64_t )tape_recsz; drive_mark_commit( drivep, bytes_committed ); } /* adjust context */ contextp->dc_reccnt++; contextp->dc_recendp = contextp->dc_recp + tape_recsz; contextp->dc_nextp = contextp->dc_recp + STAPE_HDR_SZ; /* intialize header in new record */ rechdrp = ( rec_hdr_t * )contextp->dc_recp; rechdrp->magic = STAPE_MAGIC; rechdrp->version = STAPE_VERSION; rechdrp->file_offset = contextp->dc_reccnt * ( off64_t )tape_recsz; rechdrp->blksize = ( int32_t )tape_blksz; rechdrp->recsize = ( int32_t )tape_recsz; rechdrp->capability = drivep->d_capabilities; rechdrp->first_mark_offset = -1LL; uuid_copy( rechdrp->dump_uuid, gwhdrp->gh_dumpid ); return rval; } /* do_get_align_cnt - * Returns the number of bytes which must be written to * cause the next call to get_write_buf() to be page-aligned. * * RETURNS: * the number of bytes to next alignment */ static size_t do_get_align_cnt( drive_t * drivep ) { char *next_alignment_point; intptr_t next_alignment_off; drive_context_t *contextp; contextp = ( drive_context_t * )drivep->d_contextp; mlog( MLOG_DEBUG | MLOG_DRIVE, "rmt drive op: get align cnt\n" ); /* verify protocol being followed */ assert( contextp->dc_mode == OM_WRITE ); assert( ! contextp->dc_errorpr ); assert( ! contextp->dc_ownedp ); assert( contextp->dc_recp ); assert( contextp->dc_nextp ); assert( contextp->dc_nextp < contextp->dc_recendp ); /* calculate the next alignment point at or beyond the current nextp. * the following algorithm works because all buffers are page-aligned * and a multiple of PGSZ. */ next_alignment_off = ( intptr_t )contextp->dc_nextp; next_alignment_off += PGMASK; next_alignment_off &= ~PGMASK; next_alignment_point = ( char * )next_alignment_off; assert( next_alignment_point <= contextp->dc_recendp ); /* return the number of bytes to the next alignment offset */ assert( next_alignment_point >= contextp->dc_nextp ); return ( size_t )( next_alignment_point - contextp->dc_nextp ); } /* do_end_write - pad and write pending record if any client data in it. * flush all pending writes. write a file mark. figure how many records are * guaranteed to be on media, and commit/discard marks accordingly. * RETURNS: * 0 on success * DRIVE_ERROR_* on failure */ static int do_end_write( drive_t *drivep, off64_t *ncommittedp ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; off64_t first_rec_w_err; /* zero-based index */ off64_t recs_wtn_wo_err; off64_t recs_guaranteed; off64_t bytes_committed; int rval; mlog( MLOG_DEBUG | MLOG_DRIVE, "rmt drive op: end write\n" ); /* verify protocol being followed */ assert( contextp->dc_mode == OM_WRITE ); assert( ! contextp->dc_ownedp ); assert( contextp->dc_recp ); assert( contextp->dc_nextp ); assert( contextp->dc_nextp >= contextp->dc_recp + STAPE_HDR_SZ ); assert( contextp->dc_nextp < contextp->dc_recendp ); /* pre-initialize return of count of bytes committed to media */ *ncommittedp = 0; /* if in error mode, a write error occured earlier. don't bother * to do anymore writes, just cleanup and return 0. don't need to * do commits, already done when error occured. */ if ( contextp->dc_errorpr ) { if ( ! contextp->dc_singlethreadedpr ) { Ring_reset( contextp->dc_ringp, contextp->dc_msgp ); contextp->dc_msgp = 0; } contextp->dc_mode = OM_NONE; drive_mark_discard( drivep ); *ncommittedp = ( contextp->dc_iocnt - contextp->dc_lostrecmax ) * ( off64_t )tape_recsz; contextp->dc_recp = 0; return 0; } /* if any user data in current record buffer, send it out. */ if ( contextp->dc_nextp > contextp->dc_recp + STAPE_HDR_SZ ) { rec_hdr_t *rechdrp; size_t bufusedcnt; rechdrp = ( rec_hdr_t * )contextp->dc_recp; bufusedcnt = ( size_t )( contextp->dc_nextp - contextp->dc_recp ); rechdrp->rec_used = bufusedcnt; mlog( MLOG_DEBUG | MLOG_DRIVE, "writing padded last record\n" ); if ( contextp->dc_singlethreadedpr ) { rval = write_record( drivep, contextp->dc_recp, BOOL_TRUE, BOOL_TRUE ); } else { assert( contextp->dc_msgp ); contextp->dc_msgp->rm_op = RING_OP_WRITE; contextp->dc_msgp->rm_user = contextp->dc_reccnt; Ring_put( contextp->dc_ringp, contextp->dc_msgp ); contextp->dc_msgp = 0; contextp->dc_msgp = Ring_get( contextp->dc_ringp ); switch( contextp->dc_msgp->rm_stat ) { case RING_STAT_OK: case RING_STAT_INIT: rval = 0; break; case RING_STAT_ERROR: rval = contextp->dc_msgp->rm_rval; break; default: assert( 0 ); contextp->dc_recp = 0; return DRIVE_ERROR_CORE; } } contextp->dc_reccnt++; } else { rval = 0; } /* now flush the ring until error or tracer bullet seen. * note the record index in the first msg received with * an error indication. this will be used to calculate * the number of records guaranteed to have made it onto * media, and that will be used to select which marks * to commit and which to discard. */ if ( rval ) { first_rec_w_err = contextp->dc_iocnt; /* because dc_iocnt bumped by write_record * only if no error */ } else { first_rec_w_err = -1L; } if ( ! contextp->dc_singlethreadedpr ) { while ( ! rval ) { assert( contextp->dc_msgp ); contextp->dc_msgp->rm_op = RING_OP_TRACE; Ring_put( contextp->dc_ringp, contextp->dc_msgp ); contextp->dc_msgp = 0; contextp->dc_msgp = Ring_get( contextp->dc_ringp ); if ( contextp->dc_msgp->rm_op == RING_OP_TRACE ) { break; } switch( contextp->dc_msgp->rm_stat ) { case RING_STAT_OK: case RING_STAT_INIT: assert( rval == 0 ); break; case RING_STAT_ERROR: rval = contextp->dc_msgp->rm_rval; first_rec_w_err = contextp->dc_msgp->rm_user; break; default: assert( 0 ); contextp->dc_recp = 0; return DRIVE_ERROR_CORE; } } } /* the ring is now flushed. reset */ if ( ! contextp->dc_singlethreadedpr ) { Ring_reset( contextp->dc_ringp, contextp->dc_msgp ); contextp->dc_msgp = 0; } contextp->dc_recp = 0; /* if no error so far, write a file mark. this will have the * side-effect of flushing the driver/drive of pending writes, * exposing any write errors. */ if ( ! rval ) { int weofrval; weofrval = mt_op( contextp->dc_fd, MTWEOF, 1 ); if ( weofrval ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "MTWEOF returned %d: errno == %d (%s)\n", weofrval, errno, strerror( errno )); rval = DRIVE_ERROR_EOM; } } /* if an error occured, first_rec_w_err now contains * the count of records written without error, all of which * were full records. subtract from this dc_lostrecmax, * and we have the number of records guaranteed to have made * it to media. * * if no errors have occured, all I/O has been committed. * we can use dc_iocnt, which is the count of records actually * written without error. * * commit marks contained in committed records, discard the rest, * and return rval. return by reference the number of bytes committed * to tape. */ if ( rval ) { assert( first_rec_w_err >= 0 ); recs_wtn_wo_err = first_rec_w_err; recs_guaranteed = recs_wtn_wo_err - contextp->dc_lostrecmax; } else { assert( first_rec_w_err == -1 ); recs_wtn_wo_err = contextp->dc_iocnt; recs_guaranteed = recs_wtn_wo_err; } bytes_committed = recs_guaranteed * ( off64_t )tape_recsz; drive_mark_commit( drivep, bytes_committed ); drive_mark_discard( drivep ); contextp->dc_mode = OM_NONE; *ncommittedp = bytes_committed; return rval; } /* do_fsf * Advance the tape by count files. * * RETURNS: * number of media files skipped * *statp set to zero or DRIVE_ERROR_... */ static int do_fsf( drive_t *drivep, int count, int *statp ) { int i, done, op_failed, opcount; drive_context_t *contextp; /* get drive context */ contextp = ( drive_context_t * )drivep->d_contextp; /* verify protocol being followed */ assert( contextp->dc_mode == OM_NONE ); mlog( MLOG_DEBUG | MLOG_DRIVE, "rmt drive op: fsf: count %d\n", count ); assert( count ); assert( contextp->dc_mode == OM_NONE ); for ( i = 0 ; i < count; i++ ) { done = 0; opcount = 2; /* the tape may encounter errors will trying to * reach the next file. */ while ( !done ) { /* advance the tape to the next file mark * NOTE: * ignore return code */ mlog( MLOG_VERBOSE | MLOG_DRIVE, _("advancing tape to next media file\n") ); op_failed = 0; assert( contextp->dc_fd >= 0 ); if ( mt_op( contextp->dc_fd, MTFSF, 1 ) ) { op_failed = 1; } /* Check for a file mark to * determine if the fsf command worked. */ if (!op_failed) { done = 1; } /* If the FSF command has been issued multiple * times, and a file mark has not been reached, * return an error. */ if ( --opcount < 0 ) { mlog( MLOG_VERBOSE | MLOG_DRIVE, _("FSF tape command failed\n") ); *statp = DRIVE_ERROR_DEVICE; return i; } } } return count; } /* do_bsf * Backup the tape by count files. zero means just back up to the beginning * of the last media file read or written. * * RETURNS: * number of media files skipped * *statp set to zero or DRIVE_ERROR_... */ static int do_bsf( drive_t *drivep, int count, int *statp ) { #ifdef DEBUG drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; #endif int skipped; int rval; mlog( MLOG_DEBUG | MLOG_DRIVE, "rmt drive op: bsf: count %d\n", count ); assert( contextp->dc_mode == OM_NONE ); *statp = 0; /* back space - places us to left of previous file mark * if we hit BOT, return */ assert( drivep->d_capabilities & DRIVE_CAP_BSF ); rval = bsf_and_verify( drivep ); if (rval) { if (errno == ENOSPC/*IRIX*/ || errno == EIO/*Linux*/) { if ( count ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "rmt drive op: bsf reached BOT " "unexpectedly (%d files to go)\n", count); /* set statp - BOT is unexpected */ } else { mlog( MLOG_DEBUG | MLOG_DRIVE, "rmt drive op: bsf reached BOT\n"); /* don't set statp, BOT is fine */ return 0; } } *statp = DRIVE_ERROR_DEVICE; return 0; } /* now loop, skipping media files */ for ( skipped = 0 ; skipped < count ; skipped++ ) { /* move to the left of the next file mark on the left. * check for BOT. */ rval = bsf_and_verify( drivep ); if (rval) { if (errno == ENOSPC/*IRIX*/ || errno == EIO/*Linux*/) { if ( count - skipped - 1 ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "rmt drive op: bsf reached BOT " "unexpectedly (%d files to go)\n", count - skipped - 1); /* set statp - BOT is unexpected */ *statp = DRIVE_ERROR_DEVICE; return skipped + 1; } else { mlog( MLOG_DEBUG | MLOG_DRIVE, "rmt drive op: bsf reached BOT\n"); /* don't set statp - BOT is fine */ return skipped + 1; } *statp = DRIVE_ERROR_DEVICE; return skipped; } } } /* we're not at BOT, so we need to move to the right side of * the file mark */ ( void )fsf_and_verify( drivep ); /* indicate the number of media files skipped */ return skipped; } /* do_rewind * Position the tape at the beginning of the recorded media. * * RETURNS: * 0 on sucess * DRIVE_ERROR_* on failure */ static int do_rewind( drive_t *drivep ) { #ifdef DEBUG drive_context_t *contextp = (drive_context_t *)drivep->d_contextp; #endif mlog( MLOG_DEBUG | MLOG_DRIVE, "rmt drive op: rewind\n" ); assert( contextp->dc_mode == OM_NONE ); assert( contextp->dc_fd >= 0 ); /* use validating tape rewind util func */ ( void )rewind_and_verify( drivep ); return 0; } /* do_erase * erase media from beginning * * RETURNS: * 0 on sucess * DRIVE_ERROR_* on failure */ static int do_erase( drive_t *drivep ) { #ifdef DEBUG drive_context_t *contextp = (drive_context_t *)drivep->d_contextp; #endif mlog( MLOG_DEBUG | MLOG_DRIVE, "rmt drive op: erase\n" ); assert( contextp->dc_mode == OM_NONE ); assert( contextp->dc_fd >= 0 ); /* use validating tape rewind util func */ (void )rewind_and_verify( drivep ); /* use validating tape erase util func */ ( void )erase_and_verify( drivep ); /* rewind again */ ( void )rewind_and_verify( drivep ); /* close the drive so we start from scratch */ Close( drivep ); return 0; } /* do_eject * pop the tape out - may be a nop on some drives * * RETURNS: * 0 on sucess * DRIVE_ERROR_DEVICE on failure */ static int do_eject_media( drive_t *drivep ) { drive_context_t *contextp = (drive_context_t *)drivep->d_contextp; mlog( MLOG_DEBUG | MLOG_DRIVE, "rmt drive op: eject media\n" ); /* drive must be open */ assert( contextp->dc_fd >= 0 ); assert( contextp->dc_mode == OM_NONE ); /* issue tape unload */ if ( contextp->dc_unloadokpr ) { ( void )mt_op( contextp->dc_fd, MTUNLOAD, 0 ); } /* close the device driver */ Close( drivep ); return 0; } /* do_get_device_class * Return the device class * * RETURNS: * always returns DEVICE_TAPE_REMOVABLE */ /* ARGSUSED */ static int do_get_device_class( drive_t *drivep) { mlog( MLOG_DEBUG | MLOG_DRIVE, "rmt drive op: get device class\n" ); return DEVICE_TAPE_REMOVABLE; } /* do_display_metrics - print ring stats if using I/O ring */ static void do_display_metrics( drive_t *drivep ) { drive_context_t *contextp = (drive_context_t *)drivep->d_contextp; ring_t *ringp = contextp->dc_ringp; if ( ringp ) { if ( drivecnt > 1 ) { mlog( MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK | MLOG_DRIVE, _("drive %u "), drivep->d_index ); } display_ring_metrics( drivep, MLOG_NORMAL | MLOG_BARE | MLOG_NOLOCK ); } } /* do_quit */ static void do_quit( drive_t *drivep ) { drive_context_t *contextp = (drive_context_t *)drivep->d_contextp; ring_t *ringp = contextp->dc_ringp; mlog( MLOG_DEBUG | MLOG_DRIVE, "rmt drive op: quit\n" ); /* print the ring metrics and kill the ring */ if ( ringp ) { display_ring_metrics( drivep, MLOG_VERBOSE ); /* tell slave to die */ mlog( (MLOG_NITTY + 1) | MLOG_DRIVE, "ring op: destroy\n" ); ring_destroy( ringp ); } Close(drivep); mlog( MLOG_DEBUG | MLOG_DRIVE, "rmt drive op quit complete\n" ); } static double percent64( off64_t num, off64_t denom ) { return ( double )( num * 100 ) / ( double )denom; } /* read_label * responsible for reading and validating the first record from a * media file. can assume that prepare_drive has already been run * on this tape. if read fails due to an encounter with a file mark, * end of media, or end of data, position the media to allow an * append. * * RETURNS: * 0 on success * DRIVE_ERROR_* on failure */ static int read_label( drive_t *drivep ) { drive_context_t *contextp; int nread; int saved_errno; int rval; /* initialize context ptr */ contextp = ( drive_context_t * )drivep->d_contextp; /* read the first record of the media file directly */ nread = Read( drivep, contextp->dc_recp, tape_recsz, &saved_errno ); /* if a read error, get status */ if ( nread != ( int )tape_recsz ) { assert( nread < ( int )tape_recsz ); } /* check for an unexpected errno */ if ( nread < 0 && saved_errno != ENOSPC ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("could not read from drive: %s (%d)\n"), strerror( errno ), errno ); return DRIVE_ERROR_DEVICE; } /* check for a blank tape/EOD. */ if (( nread == 0 ) /* takes care of sun */ || /* now handle SGI */ (nread < 0 && saved_errno == ENOSPC )) { mlog( MLOG_NORMAL | MLOG_DRIVE, #ifdef DUMP _("encountered EOD : assuming blank media\n") ); #endif #ifdef RESTORE _("encountered EOD : end of data\n") ); #endif ( void )rewind_and_verify( drivep ); #ifdef DUMP return DRIVE_ERROR_BLANK; #endif #ifdef RESTORE return DRIVE_ERROR_EOD; #endif } /* dc_iocnt is count of number of records read without error */ contextp->dc_iocnt = 1; rval = validate_media_file_hdr( drivep ); return rval; } static int validate_media_file_hdr( drive_t *drivep ) { global_hdr_t *grhdrp = drivep->d_greadhdrp; drive_hdr_t *drhdrp = drivep->d_readhdrp; rec_hdr_t *tprhdrp = (rec_hdr_t *)drhdrp->dh_specific; media_hdr_t *mrhdrp = (media_hdr_t *)drhdrp->dh_upper; content_hdr_t *ch = (content_hdr_t *)mrhdrp->mh_upper; content_inode_hdr_t *cih = (content_inode_hdr_t *)ch->ch_specific; drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; char tmpbuf[GLOBAL_HDR_SZ]; global_hdr_t *tmpgh = (global_hdr_t *)&tmpbuf[0]; drive_hdr_t *tmpdh = (drive_hdr_t *)tmpgh->gh_upper; media_hdr_t *tmpmh = (media_hdr_t *)tmpdh->dh_upper; rec_hdr_t *tmprh = (rec_hdr_t *)tmpdh->dh_specific; content_hdr_t *tmpch = (content_hdr_t *)tmpmh->mh_upper; content_inode_hdr_t *tmpcih = (content_inode_hdr_t *)tmpch->ch_specific; mlog( MLOG_DEBUG | MLOG_DRIVE, "validating media file header\n" ); memcpy( tmpbuf, contextp->dc_recp, GLOBAL_HDR_SZ ); /* check the checksum */ if ( ! global_hdr_checksum_check( tmpgh )) { mlog( MLOG_DEBUG | MLOG_DRIVE, "bad media file header checksum\n"); return DRIVE_ERROR_CORRUPTION; } if ( ! tape_rec_checksum_check( contextp, contextp->dc_recp )) { mlog( MLOG_NORMAL | MLOG_DRIVE, _("tape record checksum error\n") ); return DRIVE_ERROR_CORRUPTION; } xlate_global_hdr(tmpgh, grhdrp, 1); xlate_drive_hdr(tmpdh, drhdrp, 1); xlate_media_hdr(tmpmh, mrhdrp, 1); xlate_content_hdr(tmpch, ch, 1); xlate_content_inode_hdr(tmpcih, cih, 1); xlate_rec_hdr(tmprh, tprhdrp, 1); memcpy( contextp->dc_recp, grhdrp, GLOBAL_HDR_SZ ); /* check the magic number */ if ( strncmp( grhdrp->gh_magic, GLOBAL_HDR_MAGIC,GLOBAL_HDR_MAGIC_SZ)) { mlog( MLOG_DEBUG | MLOG_DRIVE, "missing magic number in tape label\n"); return DRIVE_ERROR_FORMAT; } /* check the version */ if ( global_version_check( grhdrp->gh_version ) != BOOL_TRUE ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "invalid version number (%d) in tape label\n", grhdrp->gh_version ); return DRIVE_ERROR_VERSION; } /* check the strategy id */ if ( drhdrp->dh_strategyid != drivep->d_strategyp->ds_id ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "unrecognized drive strategy ID (%d)\n", drivep->d_readhdrp->dh_strategyid ); return DRIVE_ERROR_FORMAT; } /* check the record magic number */ if ( tprhdrp->magic != STAPE_MAGIC ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "invalid record magic number in tape label\n"); return DRIVE_ERROR_FORMAT; } /* check the record version number */ if ( tprhdrp->version != STAPE_VERSION ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "invalid record version number in tape label\n"); return DRIVE_ERROR_VERSION; } mlog( MLOG_DEBUG | MLOG_DRIVE, "media file header valid: " "media file ix %d\n", mrhdrp->mh_mediafileix ); return 0; } /* get_tpcaps * Get the specific tape drive capabilities. Set the * d_capabilities field of the driver structure. * set the blksz limits and tape type in the context structure. * * RETURNS: * TRUE on success * FALSE on error */ static bool_t get_tpcaps( drive_t *drivep ) { #ifdef DEBUG drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; assert( contextp->dc_fd >= 0 ); #endif /* can't ask about blksz, can't set blksz, can't ask about * drive types/caps. assume a drive which can overwrite. * assume NOT QIC, since fixed blksz devices not supported * via RMT. */ drivep->d_capabilities |= DRIVE_CAP_OVERWRITE; drivep->d_capabilities |= DRIVE_CAP_BSF; set_recommended_sizes( drivep ); return BOOL_TRUE; } /* set_recommended_sizes * Determine the recommended tape file size and mark separation * based on tape device type. * * RETURNS: * void */ static void set_recommended_sizes( drive_t *drivep ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; off64_t fsize = drive_strategy_rmt.ds_recmfilesz; off64_t marksep = drive_strategy_rmt.ds_recmarksep; if (contextp->dc_filesz > 0) { fsize = contextp->dc_filesz; #ifdef DUMP if ( hdr_mfilesz > fsize ) { mlog( MLOG_WARNING, _( "recommended media file size of %llu Mb less than " "estimated file header size %llu Mb for %s\n"), fsize / ( 1024 * 1024 ), hdr_mfilesz / ( 1024 * 1024 ), drivep->d_pathname ); } #endif /* DUMP */ } mlog( MLOG_DEBUG | MLOG_DRIVE, "recommended tape media file size set to 0x%llx bytes\n", fsize ); mlog( MLOG_DEBUG | MLOG_DRIVE, "recommended tape media mark separation set to 0x%llx bytes\n", marksep ); drivep->d_recmfilesz = fsize; drivep->d_recmarksep = marksep; return; } /* mt_op * Issue MTIOCTOP ioctl operation to the tape device. * * RETURNS: * 0 on sucess * -1 on failure */ static int mt_op(int fd, int sub_op, int param ) { struct mtop mop; char *printstr; int rval; mop.mt_op = (short )sub_op; mop.mt_count = param; assert( fd >= 0 ); switch ( sub_op ) { case MTSEEK: printstr = "seek"; break; case MTBSF: /* 2 */ printstr = "back space file"; break; case MTWEOF: /* 0 */ printstr = "write file mark"; break; case MTFSF: /* 1 */ printstr = "forward space file"; break; case MTREW: /* 5 */ printstr = "rewind"; break; case MTUNLOAD: printstr = "unload"; break; case MTEOM: printstr = "advance to EOD"; break; case MTFSR: /* 3 */ printstr = "forward space block"; break; case MTERASE: printstr = "erase"; break; #ifdef CLRMTAUD #ifdef MTAUD case MTAUD: printstr = _("audio"); break; #endif /* MTAUD */ #endif /* CLRMTAUD */ default: printstr = "???"; break; } mlog( MLOG_DEBUG | MLOG_DRIVE, "tape op: %s %d\n", printstr, param ); rval = ioctl( fd, MTIOCTOP, &mop ); if ( rval < 0 ) { /* failure */ mlog( MLOG_DEBUG | MLOG_DRIVE, "tape op %s %d returns %d: errno == %d (%s)\n", printstr, param, rval, errno, strerror( errno )); return -1; } /* success */ return 0; } /* determine_write_error() * Using the errno and the tape status information, determine the * type of tape write error that has occured. * * RETURNS: * DRIVE_ERROR_* */ static int determine_write_error( int nwritten, int saved_errno ) { int ret = 0; if ( saved_errno == EACCES ) { mlog(MLOG_NORMAL, _("tape is write protected\n") ); ret = DRIVE_ERROR_DEVICE; } else if ( ( saved_errno == ENOSPC ) || ( saved_errno == EIO ) || (( saved_errno == 0 ) && ( nwritten >= 0 )) /* short write indicates EOM */ ) { mlog(MLOG_NORMAL, _("tape media error on write operation\n") ); mlog(MLOG_NORMAL, _("no more data can be written to this tape\n") ); ret = DRIVE_ERROR_EOM; } else if ( saved_errno != 0 ) { ret = DRIVE_ERROR_CORE; mlog( MLOG_DEBUG | MLOG_DRIVE, "tape unknown error on write operation: " "%d, %d\n", nwritten, saved_errno); } mlog( MLOG_NITTY | MLOG_DRIVE, "tape write operation nwritten %d, errno %d\n", nwritten, saved_errno); return ( ret ); } static void tape_rec_checksum_set( drive_context_t *contextp, char *bufp ) { rec_hdr_t *rechdrp = ( rec_hdr_t * )bufp; uint32_t *beginp = ( uint32_t * )bufp; uint32_t *endp = ( uint32_t * )( bufp + tape_recsz ); uint32_t *p; uint32_t accum; if ( ! contextp->dc_recchksumpr ) { return; } INT_SET(rechdrp->ischecksum, ARCH_CONVERT, 1); rechdrp->checksum = 0; accum = 0; for ( p = beginp ; p < endp ; p++ ) { accum += INT_GET(*p, ARCH_CONVERT); } INT_SET(rechdrp->checksum, ARCH_CONVERT, ( int32_t )( ~accum + 1 )); } static bool_t tape_rec_checksum_check( drive_context_t *contextp, char *bufp ) { rec_hdr_t *rechdrp = ( rec_hdr_t * )bufp; uint32_t *beginp = ( uint32_t * )bufp; uint32_t *endp = ( uint32_t * )( bufp + tape_recsz ); uint32_t *p; uint32_t accum; if ( contextp->dc_recchksumpr && INT_GET(rechdrp->ischecksum, ARCH_CONVERT) ) { accum = 0; for ( p = beginp ; p < endp ; p++ ) { accum += INT_GET(*p, ARCH_CONVERT); } return accum == 0 ? BOOL_TRUE : BOOL_FALSE; } else { return BOOL_TRUE; } } /* to trace rmt operations */ #ifdef RMTDBG static int dbgrmtopen( char *path, int flags ) { int rval; rval = rmtopen( path, flags ); mlog( MLOG_NORMAL | MLOG_DRIVE, _("RMTOPEN( %s, %d ) returns %d: errno=%d (%s)\n"), path, flags, rval, errno, strerror( errno )); return rval; } static int dbgrmtclose( int fd ) { int rval; rval = rmtclose( fd ); mlog( MLOG_NORMAL | MLOG_DRIVE, _("RMTCLOSE( %d ) returns %d: errno=%d (%s)\n"), fd, rval, errno, strerror( errno )); return rval; } static int dbgrmtioctl( int fd, int op, void *arg ) { int rval; rval = rmtioctl( fd, op, arg ); mlog( MLOG_NORMAL | MLOG_DRIVE, _("RMTIOCTL( %d, %d, 0x%x ) returns %d: errno=%d (%s)\n"), fd, op, arg, rval, errno, strerror( errno )); return rval; } static int dbgrmtread( int fd, void *p, uint sz ) { int rval; rval = rmtread( fd, p, sz ); mlog( MLOG_NORMAL | MLOG_DRIVE, _("RMTREAD( %d, 0x%x, %u ) returns %d: errno=%d (%s)\n"), fd, p, sz, rval, errno, strerror( errno )); return rval; } static int dbgrmtwrite( int fd, void *p, uint sz ) { int rval; rval = rmtwrite( fd, p, sz ); mlog( MLOG_NORMAL | MLOG_DRIVE, _("RMTWRITE( %d, 0x%x, %u ) returns %d: errno=%d (%s)\n"), fd, p, sz, rval, errno, strerror( errno )); return rval; } #endif /* RMTDBG */ /* display_access_failed_message() * Print tape device open/access failed message. * * RETURNS: * void */ static void display_access_failed_message( drive_t *drivep ) { mlog( MLOG_NORMAL | MLOG_DRIVE, _( "attempt to access/open remote " "tape drive %s failed: %d (%s)\n"), drivep->d_pathname, errno, strerror( errno )); return; } /* prepare_drive - called by begin_read if drive device not open. * determines record size and sets block size if fixed block device. * determines other drive attributes. determines if any previous * xfsdumps on media. */ static int prepare_drive( drive_t *drivep ) { drive_context_t *contextp; bool_t ok; ix_t try; ix_t maxtries; bool_t changedblkszpr; int rval; /* get pointer to drive context */ contextp = ( drive_context_t * )drivep->d_contextp; /* retry: */ if ( cldmgr_stop_requested( )) { return DRIVE_ERROR_STOP; } /* shouldn't be here if drive is open */ assert( contextp->dc_fd == -1 ); mlog( MLOG_VERBOSE | MLOG_DRIVE, _("preparing drive\n") ); /* determine if tape is present or write protected. try several times. * if not present or write-protected during dump, return. */ maxtries = 15; for ( try = 1 ; ; sleep( 10 ), try++ ) { if ( cldmgr_stop_requested( )) { return DRIVE_ERROR_STOP; } /* open the drive */ ok = Open( drivep ); if ( ! ok ) { if ( errno != EBUSY ) { display_access_failed_message( drivep ); return DRIVE_ERROR_DEVICE; } else { mlog( MLOG_DEBUG | MLOG_DRIVE, "open drive returns EBUSY\n" ); if ( try >= maxtries ) { mlog( MLOG_TRACE | MLOG_DRIVE, "giving up waiting for drive " "to indicate online\n" ); return DRIVE_ERROR_MEDIA; } Close( drivep ); continue; } } else break; } /* determine tape capabilities. this will set the drivep->d_capabilities * and contextp->dc_{...}blksz and dc_isQICpr, as well as recommended * mark separation and media file size. */ ok = get_tpcaps( drivep ); if ( ! ok ) { return DRIVE_ERROR_DEVICE; } /* establish the initial block and record sizes we will try. * if unable to ask drive about fixed block sizes, we will * guess. */ tape_blksz = cmdlineblksize; if ( tape_blksz > STAPE_MAX_RECSZ ) { tape_blksz = STAPE_MAX_RECSZ; } if ( contextp->dc_isQICpr == BOOL_TRUE ) tape_recsz = STAPE_MIN_MAX_BLKSZ; else tape_recsz = tape_blksz; /* if the overwrite option was specified , return. */ if ( contextp->dc_overwritepr ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "Overwrite option specified.\n" ); return DRIVE_ERROR_OVERWRITE; } /* loop trying to read a record. begin with the record size * calculated above. if it appears we have selected the wrong * block size and if we are able to alter the fixed block size, * and the record size we tried initially was not less than * the minmax block size, change the block size to minmax and * try to read a one block record again. */ maxtries = 5; changedblkszpr = BOOL_FALSE; for ( try = 1 ; ; try++ ) { int nread; int saved_errno; if ( cldmgr_stop_requested( )) { return DRIVE_ERROR_STOP; } /* bail out if we've tried too many times */ if ( try > maxtries ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("giving up attempt to determining " "tape record size\n") ); return DRIVE_ERROR_MEDIA; } mlog( MLOG_DEBUG | MLOG_DRIVE, "determining tape record size: trying %d (0x%x) bytes\n", tape_recsz, tape_recsz ); /* read a record. use the first ring buffer */ saved_errno = 0; nread = Read( drivep, contextp->dc_recp, tape_recsz, &saved_errno ); assert( saved_errno == 0 || nread < 0 ); /* RMT can require a retry */ if ( saved_errno == EAGAIN ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "read returned EAGAIN: retrying\n" ); continue; } /* block size is bigger than buffer; should never happen */ if ( saved_errno == EINVAL ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "read returned EINVAL: " "trying new record size\n" ); goto largersize; } /* block size is bigger than buffer; should never happen */ if ( saved_errno == ENOMEM ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "read returned ENOMEM: " "trying new record size\n" ); goto largersize; } /* I/O error */ if ( saved_errno == EIO ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "read returned EIO: will reopen, " "and try again\n" ); Close( drivep ); ok = Open( drivep ); if ( ! ok ) { display_access_failed_message( drivep ); return DRIVE_ERROR_DEVICE; } #ifdef RESTORE continue; #endif #ifdef DUMP if (3 == try) return DRIVE_ERROR_BLANK; /* sun rmt returns EIO for blank media */ else continue; #endif } /* ENOSPC */ if ( saved_errno == ENOSPC ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "read returned ENOSPC: will reopen, " "and try again\n" ); Close( drivep ); ok = Open( drivep ); if ( ! ok ) { display_access_failed_message( drivep ); return DRIVE_ERROR_DEVICE; } #ifdef RESTORE continue; #endif #ifdef DUMP if (3 == try) /* IRIX rmt returns ENOSPC for blank media */ /* It reads to the EOD */ return DRIVE_ERROR_BLANK; else continue; #endif } if ( nread == ( int )tape_recsz ) { mlog( MLOG_DEBUG | MLOG_DRIVE, "nread == selected blocksize " "indicates correct blocksize found\n" ); goto checkhdr; } /* short read */ if (( saved_errno == 0 ) && ( nread < (int)tape_recsz)) { mlog( MLOG_DEBUG | MLOG_DRIVE, "nread < selected blocksize " "indicates incorrect blocksize found " "or foreign media\n" ); return DRIVE_ERROR_FOREIGN; } /* if we fell through the seive, code is wrong. * display useful info and abort */ mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_DRIVE, _( "unexpected tape error: " "errno %d " "nread %d " "blksz %d " "recsz %d " "\n"), saved_errno, nread, tape_blksz, tape_recsz, 0 ); /*return DRIVE_ERROR_CORE; */ return DRIVE_ERROR_MEDIA; checkhdr: rval = validate_media_file_hdr( drivep ); if ( rval ) { if ( rval == DRIVE_ERROR_VERSION ) { global_hdr_t *grhdrp = drivep->d_greadhdrp; mlog( MLOG_NORMAL | MLOG_DRIVE, _( "media file header version (%d) " "invalid: advancing\n"), grhdrp->gh_version ); continue; } else { if ( isefsdump( drivep )) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("may be an EFS dump at BOT\n")); } else /* Check if the tape was erased by us */ if ( isxfsdumperasetape( drivep )) { mlog( MLOG_NORMAL | MLOG_DRIVE, _("This tape was erased earlier " "by xfsdump.\n") ); ( void )rewind_and_verify( drivep ); return DRIVE_ERROR_BLANK; } else { mlog( MLOG_NORMAL | MLOG_DRIVE, _("bad media file header at BOT " "indicates foreign or " "corrupted tape\n") ); } ( void )rewind_and_verify( drivep ); ok = set_best_blk_and_rec_sz( drivep ); if ( ! ok ) { return DRIVE_ERROR_DEVICE; } return DRIVE_ERROR_FOREIGN; } } else { drive_hdr_t *drhdrp; rec_hdr_t *tprhdrp; drhdrp = drivep->d_readhdrp; tprhdrp = ( rec_hdr_t * )drhdrp->dh_specific; assert( tprhdrp->recsize >= 0 ); tape_recsz = ( size_t )tprhdrp->recsize; break; } largersize: /* we end up here if we want to try a new larger record size * because the last one was not big enough for the tape block */ if ( changedblkszpr ) { mlog( MLOG_NORMAL | MLOG_DRIVE, _("cannot determine tape block size " "after two tries\n") ); mlog( MLOG_NORMAL | MLOG_DRIVE, _("assuming media is corrupt " "or contains non-xfsdump data\n") ); ok = set_best_blk_and_rec_sz( drivep ); if ( ! ok ) { return DRIVE_ERROR_DEVICE; } return DRIVE_ERROR_FOREIGN; } /* Make it as large as we can go */ if ( tape_recsz != STAPE_MAX_RECSZ ) { tape_recsz = STAPE_MAX_RECSZ; if ( ! contextp->dc_isQICpr ) { tape_blksz = tape_recsz;; } changedblkszpr = BOOL_TRUE; } else { mlog( MLOG_NORMAL | MLOG_DRIVE, _("cannot determine tape block size\n") ); return DRIVE_ERROR_MEDIA; } continue; } mlog( MLOG_DEBUG | MLOG_DRIVE, "read first record of first media file encountered on media: " "recsz == %u\n", tape_recsz ); /* calculate maximum bytes lost without error at end of tape */ calc_max_lost( drivep ); contextp->dc_iocnt = 1; return 0; } /* if BOOL_FALSE returned, errno is valid */ static bool_t Open( drive_t *drivep ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; int oflags; #ifdef DUMP oflags = O_RDWR; #endif /* DUMP */ #ifdef RESTORE oflags = O_RDONLY; #endif /* RESTORE */ mlog( MLOG_DEBUG | MLOG_DRIVE, "tape op: opening drive\n" ); assert( contextp->dc_fd == -1 ); errno = 0; contextp->dc_fd = open( drivep->d_pathname, oflags ); if ( contextp->dc_fd <= 0 ) { return BOOL_FALSE; } return BOOL_TRUE; } static void Close( drive_t *drivep ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; mlog( MLOG_DEBUG | MLOG_DRIVE, "tape op: closing drive\n" ); assert( contextp->dc_fd >= 0 ); ( void )close( contextp->dc_fd ); contextp->dc_fd = -1; } static int Read( drive_t *drivep, char *bufp, size_t cnt, int *errnop ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; int nread; mlog( MLOG_DEBUG | MLOG_DRIVE, "tape op: reading %u bytes\n", cnt ); assert( contextp->dc_fd >= 0 ); assert( bufp ); *errnop = 0; errno = 0; nread = read( contextp->dc_fd, ( void * )bufp, cnt ); if ( nread < 0 ) { *errnop = errno; mlog( MLOG_NITTY | MLOG_DRIVE, "tape op read of %u bytes failed: errno == %d (%s)\n", cnt, errno, strerror( errno )); } else if ( nread != ( int )cnt ) { mlog( MLOG_NITTY | MLOG_DRIVE, "tape op read of %u bytes short: nread == %d\n", cnt, nread ); } else { mlog( MLOG_NITTY | MLOG_DRIVE, "tape op read of %u bytes successful\n", cnt ); } return nread; } static int Write( drive_t *drivep, char *bufp, size_t cnt, int *errnop ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; int nwritten; mlog( MLOG_DEBUG | MLOG_DRIVE, "tape op: writing %u bytes\n", cnt ); assert( contextp->dc_fd >= 0 ); assert( bufp ); *errnop = 0; errno = 0; nwritten = write( contextp->dc_fd, ( void * )bufp, cnt ); if ( nwritten < 0 ) { *errnop = errno; mlog( MLOG_NITTY | MLOG_DRIVE, "tape op write of %u bytes failed: errno == %d (%s)\n", cnt, errno, strerror( errno )); } else if ( nwritten != ( int )cnt ) { mlog( MLOG_NITTY | MLOG_DRIVE, "tape op write of %u bytes short: nwritten == %d\n", cnt, nwritten ); } else { mlog( MLOG_NITTY | MLOG_DRIVE, "tape op write of %u bytes successful\n", cnt ); } return nwritten; } /* validate a record header, log any anomolies, and return appropriate * indication. */ static int record_hdr_validate( drive_t *drivep, char *bufp, bool_t chkoffpr ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; global_hdr_t *grhdrp = drivep->d_greadhdrp; rec_hdr_t rechdr; rec_hdr_t *rechdrp = &rechdr; rec_hdr_t *tmprh = ( rec_hdr_t * )bufp; if ( ! tape_rec_checksum_check( contextp, bufp )) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("record %lld corrupt: bad record checksum\n"), contextp->dc_iocnt - 1 ); return DRIVE_ERROR_CORRUPTION; } xlate_rec_hdr(tmprh, rechdrp, 1); if ( rechdrp->magic != STAPE_MAGIC ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("record %lld corrupt: bad magic number\n"), contextp->dc_iocnt - 1 ); return DRIVE_ERROR_CORRUPTION; } if ( uuid_is_null( rechdrp->dump_uuid )) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("record %lld corrupt: null dump id\n"), contextp->dc_iocnt - 1 ); return DRIVE_ERROR_CORRUPTION; } if ( uuid_compare( grhdrp->gh_dumpid, rechdrp->dump_uuid ) != 0) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("record %lld corrupt: dump id mismatch\n"), contextp->dc_iocnt - 1 ); return DRIVE_ERROR_CORRUPTION; } /* can't check size field of record header, since * 5.3 version of xfsdump did not set it properly. */ #ifdef RECSZCHK if ( ( size_t )rechdrp->recsize != tape_recsz ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _( "record %lld corrupt: incorrect record size in header\n"), contextp->dc_iocnt - 1 ); return DRIVE_ERROR_CORRUPTION; } #else /* RECSZCHK */ mlog( (MLOG_NITTY + 1) | MLOG_NOTE | MLOG_DRIVE, "record %lld header record size %d (0x%x)\n", contextp->dc_iocnt - 1, rechdrp->recsize, rechdrp->recsize ); #endif /* RECSZCHK */ if ( rechdrp->file_offset % ( off64_t )tape_recsz ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("record %lld corrupt: record offset in header " "not a multiple of record size\n"), contextp->dc_iocnt - 1 ); return DRIVE_ERROR_CORRUPTION; } if ( chkoffpr && rechdrp->file_offset != ( contextp->dc_iocnt - 1 ) * ( off64_t )tape_recsz ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("record %lld corrupt: " "incorrect record offset in header (0x%llx)\n"), contextp->dc_iocnt - 1, rechdrp->file_offset ); return DRIVE_ERROR_CORRUPTION; } if ( rechdrp->rec_used > tape_recsz || rechdrp->rec_used < STAPE_HDR_SZ ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_DRIVE, _("record %lld corrupt: " "incorrect record padding offset in header\n"), contextp->dc_iocnt - 1 ); return DRIVE_ERROR_CORRUPTION; } memcpy(tmprh, rechdrp, sizeof(*rechdrp)); return 0; } /* do a read, determine DRIVE_ERROR_... if failure, and return failure code. * return 0 on success. */ static int read_record( drive_t *drivep, char *bufp ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; int nread; int saved_errno; int rval; nread = Read( drivep, bufp, tape_recsz, &saved_errno ); if ( nread == ( int )tape_recsz ) { contextp->dc_iocnt++; rval = record_hdr_validate( drivep, bufp, BOOL_TRUE ); return rval; } /* check for a blank tape/EOD. */ if (( nread == 0 ) /* takes care of sun */ || /* now handle SGI */ (nread < 0 && saved_errno == ENOSPC )) { mlog( MLOG_NORMAL | MLOG_DRIVE, #ifdef DUMP _("read_record encountered EOD : assuming blank media\n") #endif #ifdef RESTORE _("read_record encountered EOD : end of data\n") #endif ); #ifdef DUMP return DRIVE_ERROR_BLANK; #endif #ifdef RESTORE return DRIVE_ERROR_EOD; #endif } /* some other error */ if ( saved_errno == EIO ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_DRIVE, _("unexpected EIO error attempting to read record\n") ); #ifdef RESTORE return DRIVE_ERROR_EOM; #endif #ifdef DUMP return DRIVE_ERROR_CORRUPTION; #endif } /* short read */ if ( nread >= 0 ) { assert( nread <= ( int )tape_recsz ); mlog( MLOG_DEBUG | MLOG_DRIVE, "short read record %lld (nread == %d)\n", contextp->dc_iocnt, nread ); return DRIVE_ERROR_CORRUPTION; } /* some other error */ mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_DRIVE, _("unexpected error attempting to read record %lld: " "read returns %d, errno %d (%s)\n"), contextp->dc_iocnt, nread, saved_errno, strerror( saved_errno )); return DRIVE_ERROR_CORRUPTION; } static int ring_read( void *clientctxp, char *bufp ) { return read_record( ( drive_t * )clientctxp, bufp ); } /* gets another record IF dc_recp is NULL */ static int getrec( drive_t *drivep ) { drive_context_t *contextp; contextp = ( drive_context_t * )drivep->d_contextp; while ( ! contextp->dc_recp ) { rec_hdr_t *rechdrp; if ( contextp->dc_singlethreadedpr ) { int rval; contextp->dc_recp = contextp->dc_bufp; rval = read_record( drivep, contextp->dc_recp ); if ( rval ) { contextp->dc_errorpr = BOOL_TRUE; return rval; } } else { contextp->dc_msgp = Ring_get( contextp->dc_ringp ); switch( contextp->dc_msgp->rm_stat ) { case RING_STAT_OK: contextp->dc_recp = contextp->dc_msgp->rm_bufp; break; case RING_STAT_INIT: case RING_STAT_NOPACK: case RING_STAT_IGNORE: contextp->dc_msgp->rm_op = RING_OP_READ; Ring_put( contextp->dc_ringp, contextp->dc_msgp ); contextp->dc_msgp = 0; continue; case RING_STAT_ERROR: contextp->dc_errorpr = BOOL_TRUE; return contextp->dc_msgp->rm_rval; default: assert( 0 ); contextp->dc_errorpr = BOOL_TRUE; return DRIVE_ERROR_CORE; } } rechdrp = ( rec_hdr_t * )contextp->dc_recp; contextp->dc_recendp = contextp->dc_recp + tape_recsz; contextp->dc_dataendp = contextp->dc_recp + rechdrp->rec_used; contextp->dc_nextp = contextp->dc_recp + STAPE_HDR_SZ; assert( contextp->dc_nextp <= contextp->dc_dataendp ); } return 0; } /* do a write, determine DRIVE_ERROR_... if failure, and return failure code. * return 0 on success. */ /*ARGSUSED*/ static int write_record( drive_t *drivep, char *bufp, bool_t chksumpr, bool_t xlatepr ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; int nwritten; int saved_errno; int rval; if ( xlatepr ) { rec_hdr_t rechdr; memcpy( &rechdr, bufp, sizeof(rechdr) ); xlate_rec_hdr( &rechdr, ( rec_hdr_t * )bufp, 1 ); } if ( chksumpr ) { tape_rec_checksum_set( contextp, bufp ); } nwritten = Write( drivep, bufp, tape_recsz, &saved_errno ); if ( nwritten == ( int )tape_recsz ) { contextp->dc_iocnt++; return 0; } rval = determine_write_error( nwritten, saved_errno ); assert(rval); return rval; } static int ring_write( void *clientctxp, char *bufp ) { return write_record( ( drive_t * )clientctxp, bufp, BOOL_TRUE, BOOL_TRUE ); } static ring_msg_t * Ring_get( ring_t *ringp ) { ring_msg_t *msgp; mlog( (MLOG_NITTY + 1) | MLOG_DRIVE, "ring op: get\n" ); msgp = ring_get( ringp ); return msgp; } static void Ring_put( ring_t *ringp, ring_msg_t *msgp ) { mlog( (MLOG_NITTY + 1) | MLOG_DRIVE, "ring op: put %d\n", msgp->rm_op ); ring_put( ringp, msgp ); } static void Ring_reset( ring_t *ringp, ring_msg_t *msgp ) { mlog( (MLOG_NITTY + 1) | MLOG_DRIVE, "ring op: reset\n" ); assert( ringp ); ring_reset( ringp, msgp ); } /* a simple heuristic to calculate the maximum uncertainty * of how much data actually was written prior to encountering * end of media. */ static void calc_max_lost( drive_t *drivep ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; if ( contextp->dc_isQICpr ) { contextp->dc_lostrecmax = 1; } else { contextp->dc_lostrecmax = 2; } } static void display_ring_metrics( drive_t *drivep, int mlog_flags ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; ring_t *ringp = contextp->dc_ringp; char bufszbuf[ 16 ]; char *bufszsfxp; if ( tape_recsz == STAPE_MIN_MAX_BLKSZ ) { assert( ! ( STAPE_MIN_MAX_BLKSZ % 0x400 )); sprintf( bufszbuf, "%u", STAPE_MIN_MAX_BLKSZ / 0x400 ); assert( strlen( bufszbuf ) < sizeof( bufszbuf )); bufszsfxp = _("KB"); } else if ( tape_recsz == STAPE_MAX_RECSZ ) { assert( ! ( STAPE_MAX_RECSZ % 0x100000 )); sprintf( bufszbuf, "%u", STAPE_MAX_RECSZ / 0x100000 ); assert( strlen( bufszbuf ) < sizeof( bufszbuf )); bufszsfxp = _("MB"); } else { sprintf( bufszbuf, "%u", (unsigned int)(tape_recsz / 0x400) ); bufszsfxp = _("KB"); } mlog( mlog_flags, _( "I/O metrics: " "%u by %s%s %sring; " "%lld/%lld (%.0lf%%) records streamed; " "%.0lfB/s\n"), contextp->dc_ringlen, bufszbuf, bufszsfxp, contextp->dc_ringpinnedpr ? _("pinned ") : "", ringp->r_slave_msgcnt - ringp->r_slave_blkcnt, ringp->r_slave_msgcnt, percent64( ringp->r_slave_msgcnt - ringp->r_slave_blkcnt, ringp->r_slave_msgcnt ), ( double )( ringp->r_all_io_cnt ) * ( double )tape_recsz / ( double )( time( 0 ) - ringp->r_first_io_time )); } #ifdef CLRMTAUD static uint32_t #else /* CLRMTAUD */ static short #endif /* CLRMTAUD */ rewind_and_verify( drive_t *drivep ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; ix_t try; int rval; rval = mt_op( contextp->dc_fd, MTREW, 0 ); for ( try = 1 ; ; try++ ) { if ( rval ) { sleep( 1 ); rval = mt_op( contextp->dc_fd, MTREW, 0 ); } else return 0; if ( try >= MTOP_TRIES_MAX ) { return 0; } sleep( 1 ); } /* NOTREACHED */ } #ifdef CLRMTAUD static uint32_t #else /* CLRMTAUD */ static short #endif /* CLRMTAUD */ erase_and_verify( drive_t *drivep ) { char *tempbufp; int saved_errno; drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; mlog( MLOG_DEBUG | MLOG_DRIVE, "rmt : erase_and_verify\n" ); /* Erase is not standard rmt. So we cannot use the line below. ( void )mt_op( contextp->dc_fd, MTERASE, 0 ); * So write a record of zeros to fake erase . Poor man's erase! * We put the ERASE_MAGIC string at the beginning so we can * detect if we have erased the tape. */ tempbufp = (char *) calloc( 1 , ( size_t )tape_recsz ); strcpy( tempbufp, ERASE_MAGIC ); Write( drivep, tempbufp, tape_recsz, &saved_errno ); free(tempbufp); return 0; } #ifdef CLRMTAUD static uint32_t #else /* CLRMTAUD */ static short #endif /* CLRMTAUD */ bsf_and_verify( drive_t *drivep ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; return mt_op( contextp->dc_fd, MTBSF, 1 ); } #ifdef CLRMTAUD static uint32_t #else /* CLRMTAUD */ static short #endif /* CLRMTAUD */ fsf_and_verify( drive_t *drivep ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; ( void )mt_op( contextp->dc_fd, MTFSF, 1 ); return 0; } static bool_t set_best_blk_and_rec_sz( drive_t *drivep ) { drive_context_t *contextp = ( drive_context_t * )drivep->d_contextp; if ( contextp->dc_isQICpr == BOOL_TRUE ) tape_recsz = STAPE_MIN_MAX_BLKSZ; else tape_recsz = cmdlineblksize; return BOOL_TRUE; } static bool_t isefsdump( drive_t *drivep ) { int32_t *efshdrp = ( int32_t * )drivep->d_greadhdrp; int32_t efsmagic = efshdrp[ 6 ]; if ( efsmagic == 60011 || efsmagic == 60012 ) { return BOOL_TRUE; } else { return BOOL_FALSE; } } static bool_t isxfsdumperasetape( drive_t *drivep ) { if ( !strcmp( ( char * )drivep->d_greadhdrp, ERASE_MAGIC ) ) return BOOL_TRUE; else return BOOL_FALSE; } xfsdump-3.1.6+nmu1/common/ts_mtio.h0000644000000000000000000007367512607344125014116 0ustar #ifndef __TS_MTIO_H__ #define __TS_MTIO_H__ #include #ifndef __KERNEL__ #include #ifndef _UCHAR_T_DEFINED typedef unsigned char uchar_t; #define _UCHAR_T_DEFINED 1 #endif typedef unsigned int uint_t; #endif /* __KERNEL */ typedef unsigned int major_t; typedef unsigned int minor_t; #define TAPEPATH "/dev/ts" #ifndef _BITS_TYPES_H #endif /* _BITS_TYPES_H */ #define NBPSCTR 512 /* Bytes per sector from irix/kern/sys/param.h */ #define SCTRSHFT 9 /* Shift for BPSECT from irix/kern/sys/param.h */ /* * TS supports the following MTIOCTOP subcodes. These subcode * have been defined in sys/mtio.h and are supported in ST as well. * See sys/mtio.h for details. * * operations (mt_op values for MTIOCTOP) * * #define MTFSF 1 forward space file * #define MTBSF 2 backward space file * #define MTFSR 3 forward space record * #define MTBSR 4 backward space record * #define MTWEOF 5 write an end-of-file record * #define MTREW 6 rewind * #define MTOFFL 7 rewind and put the drive offline * #define MTNOP 8 no operation, sets status only * #define MTRETEN 9 retention operation * #define MTEOM 12 space to end of recorded data * #define MTERASE 13 erase tape from current position to EOT * #define MTSETBLK 20 set block length * #define MTSEEK 22 Seek to the given block number. Not all * drives support this option. For drives * that support audio, the block number * actually becomes the program number ( 0 * meaning leadin area, 0xfffffffe meaning * leadout, and other values (currently 1- * 799 decimal) the program #). For seeking * to times in audio mode, see MTSETAUDIO. * #define MTWSM 27 write mt_count setmarks (DAT) * #define MTUNLOAD 31 unload tape from drive * #define MTSETPART 33 skip to partition in mt_count (DAT); for * DDS format DAT drives (only ones * supported current), partition 1 is the * first partition on the tape (nearest * BOT), and partition 0 is the remainder of * the tape. * #define MTMKPART 34 create partition (DAT), count is * multiplied by 1 Mybte (2^20 bytes) to * give the size of partition 1; if 0, then * changes tape to a single partition * tape. * */ #define MTRET MTRETEN /* retention operation */ #define MTRSV 0x7000 /* Issue a unit reserve command */ #define MTRLS 0x7001 /* Issue a unit release command */ #define MTPREEMPT 0x7002 /* Preempt active persistent reservation */ #define MTCLEAR 0x7003 /* Clear persistent reservation and keys */ #define MTAFILE 0x7004 /* space to end of last file before FM (so * next data written is appended) */ #define MTSKSM 0x7005 /* skip setmark (DAT); skip backwards if mt_ * count is negative */ #define MTAUD 0x7006 /* turn audio mode on and off. If count is * 0, we are in data mode (default), if 1, * put drive in audio mode. This is only * needed for writing tapes, since when * reading the tape type (data or audio) is * recognized automaticly. (DAT only for * now). Remains set until same ioctl is * reused, or until reboot. */ /* MTSPECOP - special drive specific operations. * These use the mtop structure. * MTSPECOP subcodes start at 0x6000. */ #define MTSCSI_CIPHER_SEC_ON 0x6001 /* enable reporting of recovered * errors on the Cipher 540S */ #define MTSCSI_CIPHER_SEC_OFF 0x6002 /* disable recovered error report */ /* These are meaningful only for Exabyte. Default is to return errors if read length is less than the block length */ #define MTSCSI_SILI 0x6003 /* suppress illegal length indication */ #define MTSCSI_EILI 0x6004 /* enable illegal length indication. * currently implemented only for * SCSI tape driver */ #define MTSCSI_SETFIXED 0x6005 /* set size of blocks for fixed * block device in mt_count. Lasts * till reset same way, or till next * boot. */ #define MTSCSI_SPEED 0x6006 /* set speed for multispeed devices * in mt_count. Current legal * values are 0 (50 ips) and 1 (100 * ips) on Kennedy drives only. * Default is currently 100. */ #define MTSCSI_SM 0x6007 /* How DAT setmarks are handled. * default is to treat similar to * FM (also if non-zero in mt_ * count). 0 in mt_count causes * setmarks to be ignored. Lasts * until reboot or reset. */ #define MTSCSI_LOG_OFF 0x6008 /* Disable sense data logging */ #define MTSCSI_LOG_ON 0x6009 /* Enable sense data logging */ #define ABI_MTIOCTOP (('t' << 8) | 9) #define ABI_MTWEOF 0 /* same as MTWEOF */ #define ABI_MTFSF 1 /* same as MTFSF */ #define ABI_MTBSF 2 /* same as MTBSF */ #define ABI_MTFSR 3 /* same as MTFSR */ #define ABI_MTBSR 4 /* same as MTBSR */ #define ABI_MTREW 5 /* same as MTREW */ #define ABI_MTOFFL 6 /* same as MTOFFL */ /* structure for MTIOCGET_SGI - mag tape get status command; note that * in audio mode, the blkno is actually the program number; see * also the MTGETAUDIO ioctl and structure. For the 3 special * position in audio mode (leadin, leadout, and unknown), the * low nibbles are replicated, so they don't match valid program * numbers (which are 1-799 decimal), giving values of 0xBBB, 0xEEE, * and 0xAAA, respectively. */ struct mtget_sgi { short mt_type; /* type of magtape device */ unsigned short mt_dposn; /* status of tape position (see below)*/ /* the following two registers are device dependent */ unsigned short mt_dsreg; /* ``drive status'' register */ short mt_erreg; /* ``error'' register */ short mt_resid; /* residual count; for SCSI, this is * used to report the current partition * # for DAT tapes that are partitioned */ /* the following two are not yet fully implemented */ int mt_fileno; /* file number of current position */ int mt_blkno; /* block number of current position */ }; /* old mtget structure , still keep it around for compatibility reason */ /* the librmt and /etc/rmt code uses it */ struct old_mtget { short mt_type; /* type of magtape device */ /* the following two registers are device dependent */ unsigned short mt_dsreg; /* ``drive status'' register */ short mt_erreg; /* ``error'' register */ short mt_resid; /* residual count */ /* the following two are not yet fully implemented */ int mt_fileno; /* file number of current position */ int mt_blkno; /* block number of current position */ }; /* * Structure to get persistent reservation state */ struct mt_prsv { int mt_flags; /* flags for per rsv state */ int mt_active_gen; /* generation of per rsv */ int mt_type; /* prsv type */ char mt_active_key[8]; /* active prsv key */ char mt_local_key[8]; /* key used by local host */ }; #define MT_PRSV_VALID_RSV 0x01 /* valid persistent rsv */ /* structure for MTIOCGETEXT * * mt_type Type of tape device * mt_dposn Status of tape position. See below. * mt_dsreg Drive status register. See below. * mt_erreg Error registers. The error register bits for a SCSI * device are defined in tpsc.h, the upper 16 bits of * ct_state in word0, ct_state2 in word 1. * resid Difference between what was requested and what has * completed, in bytes or blocks depending on the command. * fileno Not currently supported. * blkno Block number (from device) * partno Partition number. * cblkno Block number calculated by driver, includes filemarks. * lastreq Last device request made by user. See MTR_xxx request * codes defined below. * mt_ilimode 1 if ILI reporting is on, otherwise 0. * mt_buffmmode 1 if filemarks are buffered, otherwise 0. */ typedef struct mtgetext { short mt_type; unsigned short mt_dposn; /* Status of tape position */ unsigned short mt_dsreg; /* Drive status register */ unsigned short mt_erreg[5]; /* Error registers */ int mt_resid; /* Residual count */ int mt_fileno; /* File number */ int mt_blkno; /* Block number (from device) */ int mt_partno; /* Partition number */ int mt_cblkno; /* Block number (calculated) */ int mt_lastreq; /* Last device request */ int mt_ilimode; /* State of ILI reporting mode */ int mt_buffmmode; /* State of buffered filemarks */ int mt_subtype; /* Device type */ uint_t mt_capability; /* Device capabilities (MTCAN*) */ int64_t mt_nreads; /* Bytes read since tape load */ int64_t mt_nwrites; /* Bytes written since tape load*/ int mt_future[2]; /* Future additions */ } mtgetext_t; /* * Structure for MTACCT * */ typedef struct mtacct { u_char mt_hinv; /* Tape type defined in invent.h */ uint_t mt_capability; /* Tape capabilities */ uint64_t mt_reads; /* read()s since boot time */ uint64_t mt_rbytes; /* bytes read since boot time */ uint64_t mt_writes; /* write()s since boot time */ uint64_t mt_wbytes; /* bytes written since boot time */ uint64_t mt_ioctls; /* ioctl()s since boot time */ uint64_t mt_reads_load; /* read()s at last load */ uint64_t mt_rbytes_load; /* bytes read at last load */ uint64_t mt_writes_load; /* write()s at last load */ uint64_t mt_wbytes_load; /* bytes written at last load */ uint64_t mt_ioctls_load; /* ioctl()s at last load */ uint64_t mt_future[16]; /* Future additions */ } mtacct_t; #define MT_MAX_VID 6 /* Max characters in volume id sans null */ struct mtvid { char vid[MT_MAX_VID+1]; }; /* structure for MTIOCGETBLKINFO - all quantities in bytes. A value of 0 indicates no limit When using the variable block size device, the lastread field is determined by reading one block and then spacing backwards, if no i/o has yet been done to this tape. Unlike MTIOCGETBLKSIZE, all quantities are in bytes. */ struct mtblkinfo { unsigned minblksz; /* minimum block size */ unsigned maxblksz; /* maximum block size */ unsigned curblksz; /* size of block at last i/o. For fixed mode, all requests must be a multiple of this. */ unsigned recblksz; /* "recommended" size for i/o. Mostly based on compatibility with earlier releases and/or other vendors */ }; /* structure for MTSCSI_RDLOG The fields in this structure reflect the values required in the SCSI Log Sense command. See a product manual for an explanation of the fields. */ #define MTSCSI_LOGLEN 4096 typedef struct mtscsi_rdlog { uint mtppc : 1, /* Parameter pointer control */ mtsp : 1, /* Saving paramters */ mtpc : 2, /* Page control */ mtpage : 6; /* Page code of requested page */ unsigned short mtparam; /* Parameter pointer */ unsigned short mtlen; /* Size of buffer receiving log */ caddr_t mtarg; /* Buffer pointer */ } mtscsi_rdlog_t; #if _KERNEL typedef struct irix5_mtscsi_rdlog { uint mtppc : 1, /* Parameter pointer control */ mtsp : 1, /* Saving paramters */ mtpc : 2, /* Page control */ mtpage : 6; /* Page code of requested page */ unsigned short mtparam; /* Parameter pointer */ unsigned short mtlen; /* Size of buffer receiving log */ app32_ptr_t mtarg; /* Buffer pointer */ } irix5_mtscsi_rdlog_t; #endif /* _KERNEL */ /* structure and defines for MT[GS]ETAUDIO. * When using SETAUDIO to locate to a particular point, the type * should be set to one of the MTAUDPOSN_* values, * and only the corresponding fields need be filled in. See the DAT * audio spec for more detail on the definitions of the different times. * There are 34 frames per second, legal values are 0 through 33. The * maximum value for the hours field is 99 hours. Positioning commands * return immediately (as does rewind) in audio mode, and requests for * current position may be made while the positioning is in progress. * Other commands will block while positioning is in progress. * When known, all 4 of the positions are returned for GET (that is * pnum1-index, and all 3 of the mtaudtime structures). The program * must determine by looking for 0xA in both nibbles whether any particular * field is valid. */ #define MTAUDPOSN_PROG 0 /* seek to program number */ #define MTAUDPOSN_ABS 1 /* seek to absolute time */ #define MTAUDPOSN_RUN 2 /* seek to running time */ #define MTAUDPOSN_PTIME 3 /* seek to program time (within program) */ /* * all the times are BCD digits, for both SET and GET. * a value of 0xA in BOTH nibbles, (i.e., not a valid BCD number) * means that the field isn't valid. */ struct mtaudtimecode { uchar_t hhi:4, hlo:4; /* hours */ uchar_t mhi:4, mlo:4; /* minutes */ uchar_t shi:4, slo:4; /* seconds */ uchar_t fhi:4, flo:4; /* frame # (finer grain than seconds) */ }; struct mtaudio { uchar_t zero1:4, pno1:4; /* 3 BCD digits giving program number the zero */ uchar_t zero2:4, pno2:4; /* fields should always be 0, or 0xA, when the */ uchar_t zero3:4, pno3:4; /* pno field is also 0xA, indicating not valid */ uchar_t indexhi:4, index:4; /* index number within program; hi is the most significant BCD digit, index the least. */ struct mtaudtimecode ptime; /* program time */ struct mtaudtimecode atime; /* absolute time */ struct mtaudtimecode rtime; /* running time */ uchar_t seektype; /* one of the MTAUDPOSN_* values */ uchar_t cfuture[11]; /* future expansion */ }; /* structure for MTCAPABILITY */ struct mt_capablity { int mtsubtype; /* this is NOT the same as mt_type, this is the actual tape type, from invent.h, such as 9track, or DAT; otherwise it is difficult to associate a particular device with its type from a program. */ uint_t mtcapablity; /* the MTCAN* bits */ uint_t mtfuture[8]; /* for future additions */ }; /* Constants for mt_type byte */ #define MT_ISSCSI 0x09 /* Western Digital SCSI controller */ /* values for mt_dposn; values chosen for compatiblity with existing programs! Note that these bits and the gaps between are also used in tpsc.h */ /* The expected relative behaviour of MT_EW, MT_EOT and MTANSI can be described as follows. - writing from BOT, with MTANSI disabled, when LEOT is encountered, MT_EW and MT_EOT are set. If MTANSI is now enabled, MT_EOT will be reset and writing will be permitted until PEOT is encountered, whereupon MT_EOT will again be set and will remain so until the tape is repositioned. - reading from BOT, MT_EOT will be set when PEOT is encountered. LEOT is not normally reported by the drive, and therefore MT_EW will normally not be set, unless the drive supports the REW mode bit. (few do) */ #define MT_EOT 0x01 /* tape is at end of media */ #define MT_BOT 0x02 /* tape is at beginning of media */ #define MT_WPROT 0x04 /* tape is write-protected */ #define MT_EW 0x08 /* hit early warning marker */ #define MT_ONL 0x40 /* drive is online */ #define MT_EOD 0x4000 /* tape is at end of data */ #define MT_FMK 0x8000 /* tape is at file mark */ #define MT_POSMSK 0xC04F /* mask for supported bits */ /* * mt_dsreg bits which are not also mt_dposn values. MT_QIC24 and MTQIC120 * are set only for drives that support QIC150 as well as the older formats. */ #define MT_GETBLKLEN 0x0010 /* Request to determine block length pending */ #define MT_MOTION 0x0020 /* Command performed which (potentially) moves*/ /* the tape since last load or reset */ #define MT_QIC24 0x0080 /* QIC24 cartridge in drive */ #define MT_QIC120 0x0100 /* QIC120 cartridge in drive */ #define MT_OPEN 0x0200 /* Device is open */ #define MT_READ 0x0400 /* Last motion request is read */ #define MT_WRITE 0x0800 /* Last motion request is write */ #define MT_CHG 0x1000 /* Unit attention has occurred */ #define MT_DIDIO 0x2000 /* I/O or user requested tape motion command */ /* has successfully completed since open */ /* or space/rewind */ /* * mt_erreg or mt_erreg[0] bits. */ #define MT_NEEDBOT 0x0001 /* Must position at BOT before I/O. */ #define MT_LOADED 0x0002 /* Tape is loaded */ #define MT_ANSI 0x0004 /* I/O permitted after EOT detected */ #define MT_SMK 0x0008 /* Drive is positioned at setmark */ #define MT_AUDIO 0x0010 /* Drive is in audio mode. Persists until */ /* reset, tape change, or reboot. */ #define MT_AUD_MED 0x0020 /* Drive media is in audio format */ #define MT_MULTPART 0x0040 /* Drive media is multi-partitioned */ #define MT_SEEKING 0x0080 /* Seek/rewind in immediate mode is pending */ #define MT_HITFMSHORT 0x0100 /* Fixed block I/O, hit FM and returned short */ /* non-zero count. Next read will return 0 */ #define MT_INCOMPAT_MEDIA 0x0200 /* Media is incompatible with drive */ #define MT_CLEANHEADS 0x0400 /* Drive needs cleaning */ #define MT_COMPRESS 0x0800 /* Drive in compress mode */ #define MT_RESERVED 0x1000 /* Persistent reserve placed on drive */ #define MT_MEDIA_ERR 0x4000 /* Media error has occurred */ /* * mt_erreg[1] bits. */ #define MT_BAD_REQT 0x0001 /* Invalid request issued to device */ #define MT_LARGE_BLK 0x0002 /* Block size on tape larger than request size*/ #define MT_LOAD_ERR 0x0004 /* Load error */ #define MT_HWERR 0x0008 /* Hardware error */ #define MT_NOT_READY 0x0010 /* Device is not ready */ #define MT_BLKLEN 0x0020 /* Set block size differs from actual size */ #define MT_INV_POS 0x0040 /* Tape position has not been established */ #define MT_BLANK_TAPE 0x0080 /* Blank Tape detected */ /* * mag tape io control commands * * Ioctls 1-10000 are reserved by the TS driver and personality * daemons. * */ #define MTPDTRACE 6000 /* From pd_ioctl.h */ #define MTIOCODE(x) ('t'<<8|(x)) #ifndef _SYS_MTIO_H #define MTIOCTOP MTIOCODE('a') /* perform tape op */ #endif /* _SYS_MTIO_H */ #define MTIOCGET_SGI MTIOCODE('b') /* get tape status */ #define MTIOCGETBLKSIZE MTIOCODE('c') /* get tape block size * in multiples of 512 bytes */ #define MTSCSIINQ MTIOCODE('d') /* return scsi inquiry info ( * scsi tape drives only!); * 3rd arg is a ptr to a * buffer of at least izeof( * ct_g0inq_data_t) from * tpsc.h */ #define MTSCSI_INQUIRY_LEN 82 /* length of inquiry data * for scsi tapes */ #define MTSPECOP MTIOCODE('e') /* special drive specific ops */ #define MTIOCGETBLKINFO MTIOCODE('f') /* get tape block info */ #define MTANSI MTIOCODE('g') /* allows i/o past EOT mark * to provide for ANSI 3.27 * labeling. Doesn't * persist across opens. If * used, standard SGI EOT * handling for tar, bru, * etc. won't work * correctly. Currently * implemented only on SCSI * tape drives. An arg of 1 * enables, 0 disables. * NOTE: when the EOT marker * is encountered, the * current i/o operation * returns either a short * count (if any i/o * completed), or -1 (if no * i/o completed); it is the * programmers responsiblity * to determine if EOT has * been encountered by using * MTIOCGET or logic * internal to the program. * This ioctl should be * issued AFTER encountering * EOT, if ANSI 3.27 EOT * handling is desired. * subsequent i/o's will * then be allowed, and will * return the count actually * transferred, or -1 if the * drive was unable to * transfer any data. The * standard calls for * writing a FM before the * label. If this isn't * done, the drive may * return label info as * data. */ #define MTCAPABILITY MTIOCODE('h') /* returns drive type and * capablities (MTCAN*). * Currently implemented * only for SCSI drives. See * mt_capablity struct */ #define MTSETAUDIO MTIOCODE('i') /* sets audio position, * etc. */ #define MTGETAUDIO MTIOCODE('j') /* returns info about * position, etc. in audio * mode */ #define MTABORT MTIOCODE('k') /* abort current tape * operation, if any. Useful * only with commands that * run asynchronously to the * caller, such as seek and * rewind when in audio * mode. */ #define MTALIAS MTIOCODE('l') /* for use by ioconfig in * the hardware graph*/ #define MTSCSI_SENSE MTIOCODE('m') /* returns the data for the * most recent request sense * issued as the result of a * scsi tape driver command * that got a SCSI * checkcondition. returns * up to MTSCSI_SENSE_LEN * bytes of data. The buffer * supplied as the 3rd ioctl * argument must be at least * that large. The actual * amount of data will * usually be less. */ #define MTSCSI_SENSE_LEN 256 /* length of sense data * returned by MTSCSI_SENSE * ioctl. returned data * must be examined for for * actual valid length. */ #define MTILIMODE MTIOCODE('n') /* Set ILI mode */ #define MTIOCKGET MTIOCODE('o') /* CA UniCenter kernel call */ #define MTSCSI_RDLOG MTIOCODE('p') /* Return SCSI device log * data */ #define MTIOCGETEXT MTIOCODE('q') /* Get extended tape status */ #define MTGETATTR MTIOCODE('r') /* Get tape device attributes */ #define MTBUFFMMODE MTIOCODE('s') /* Set Buffered filemark mode */ #define MTFPMESSAGE MTIOCODE('t') /* Write to diagnostic * display (if supported) */ #define MTGETPOS MTIOCODE('u') /* Get vendor specific * position */ #define MTSETPOS MTIOCODE('v') /* Set vendor specific * position */ #define MTIOCGETEXTL MTIOCODE('w') /* Get last extended tape * status */ #define MTACCT MTIOCODE('x') /* Return accounting data */ #define MTSETVID MTIOCODE('y') /* Set device volume id */ #define MTPRSV MTIOCODE('z') /* Get persistent reserve * out key */ /* definitions for tape capablities. Only those that are not * shared by all tape drives are shown. */ #define MTCAN_BSF 0x1 /* can backspace file */ #define MTCAN_BSR 0x2 /* can backspace record (block) */ #define MTCAN_APPEND 0x4 /* can append to existing tape files */ #define MTCAN_SETMK 0x8 /* can do setmarks */ #define MTCAN_PART 0x10 /* can do multiple partitions (DAT) */ #define MTCAN_PREV 0x20 /* can prevent/allow media removal */ #define MTCAN_SYNC 0x40 /* can do synchronous mode SCSI */ /* Note. If SPEOD are set, or just SPEOD is set, * then a simple space to EOD is done; the combination * of SPEOD and LEOD is meaningless, and is treated as SPEOD, when * spacing, or as LEOD when closing; i.e., do NOT set both, or you * will get inconsistent results. * Some drives, such as the 8mm drive, have a drive detectible EOD, * but don't support the space EOD command. For these drives, * neither SPEOD nor LEOD should be set. We then fake it by looping * on space record and space FM until we get a blank check or other * indication of EOD. */ #define MTCAN_LEOD 0x80 /* Use a logical EOD (as opposed to an EOD * detectable by the drive). Currently only 9-track drives. * If set, it is assumed EOD is marked by 2 sequential filemarks. * Setting this also implies causes two sequential FM's to be written * on close, when writing. */ #define MTCAN_SPEOD 0x100 /* can execute the space EOD command. */ #define MTCAN_CHKRDY 0x200 /* can determine if a tape is present; some * drives, such as Cipher540S return OK on a test unit ready even if * no cartridge is present. */ #define MTCAN_VAR 0x400 /* can do variable block sizes */ #define MTCAN_SETSZ 0x800 /* can set fixed block size */ #define MTCAN_SETSP 0x1000 /* can set tape speed (some 9track) */ #define MTCAN_SETDEN 0x2000 /* can set tape density (some 9track) */ #define MTCAN_SILI 0x4000 /* can set suppress illegal length errors; * only on drives that support variable block sizes */ #define MTCANT_RET 0x8000 /* some drives can't retension; the driver * will do it's best by spacing to EOD and rewinding. */ #define MTCAN_AUDIO 0x10000 /* drive supports audio over the SCSI bus; * only DAT at this time. The data is expected to be read * or written in the standard DAT format, including subcodes. * collection and gathering of subcodes is handled by the drive. * all 7 subcodes follow the data, then the mainID. * The drive reports/sets audio or data tapes via the density code * in the modesense/select block descriptor. Actual data layout * is as below: * 5760 bytes of audio data (16 bits left, 16 bits right, repeat) * 7 subcode packs of 8 bytes each * 4 bytes of subid (4bits each of ctrlid, dataid, program # high * nibble, # of valid pack items, progno # middle nibble, progno * low nibble, 2 reserved nibbles) * 2 bytes main id (2 bits each of fmtid, and id1 - id7) */ #define MTCAN_SEEK 0x20000 /* drive supports seeking to a particular * block (or sometimes program # if AUDIO supported) */ #define MTCAN_CHTYPEANY 0x40000 /* drive can change density and/or fixed to variable at any point (if it can change at all). Otherwise it can change only at BOT */ #define MTCANT_IMM 0x80000 /* drive doesn't work correctly when immediate mode rewind, etc. is enabled. Setting this bit will disable immediate mode rewind on the drive, independent of the setting of tpsc_immediate_rewind (in master.d/tpsc) */ #define MTCAN_COMPRESS 0x100000 /* drive supports compression */ #define MTCAN_BUFFM 0x200000 /* drive supports writing of * buffered filemarks */ #define MTCAN_FASTSEEK 0x400000 /* Drive needs BT bit set in read position and * locate commands for fast seeking. */ #define MTCANT_LOAD 0x800000 /* Do NOT issue SCSI LOAD command for this drive */ #define MTCAN_LDREW 0x1000000 /* Issue Rewind instead of Load command. Used * in conjunction with MTCANT_LOAD. */ /* * Definitions for MTGETATTR */ /* Definition of MTGETATTR return struct */ struct mt_attr { char *ma_name; char *ma_value; int ma_vlen; }; /* Definitions of attribute names */ #define MT_ATTR_NAME_REWIND "rewind" #define MT_ATTR_NAME_VARIABLE "varblk" #define MT_ATTR_NAME_SWAP "swap" #define MT_ATTR_NAME_COMPRESS_DENS "compress" #define MT_ATTR_NAME_DEVSCSI "devscsi" /* (Some of the) Definitions of return values */ #define MT_ATTR_VALUE_TRUE "true" #define MT_ATTR_VALUE_FALSE "false" #define MT_ATTR_MAX_NAMELEN 32 #define MT_ATTR_MAX_VALLEN 256 /* * Definitions for MTFPMESSAGE */ #define MT_FPMSG_MAX_MSGLEN 64 #define MT_FPMSG_IBM_MSGLEN 0x18 #define MT_FPMSG_DIANA_MSGLEN 0x11 /* Definition of MTFPMESSAGE struct */ struct mt_fpmsg { int mm_mlen; union { char mm_msg[MT_FPMSG_MAX_MSGLEN]; /* Generic format */ struct { /* Format for IBM 3590 type*/ char display_type; /* Display Type: Set to 0x80 */ char msg_type:3, /* Message type: 0x00 = General * Status message */ msg_cntrl:3, /* Message control: 0 = Display message 0 1 = Display message 1 2 = Flash message 0 3 = Flash message 1 4 = Alternate message 0 and 1 */ rsvd1:2; char rsvd2[4]; ushort msg_len; /* Message length:Set to 0x10 */ char msg1[8]; /* message 1 */ char msg2[8]; /* message 2 */ } ibm3590; struct { /* Format for Fujitsu Diana 1,2,3 */ char display_mode:3, display_len:1, flash:1, half_msg:1, :1, data_format:1; char msg1[8]; char msg2[8]; } diana; } u; }; #define default_mm_msg u.mm_msg #define ibm3590_display_type u.ibm3590.display_type #define ibm3590_msg_type u.ibm3590.msg_type #define ibm3590_msg_cntrl u.ibm3590.msg_cntrl #define ibm3590_msg_len u.ibm3590.msg_len #define ibm3590_msg1 u.ibm3590.msg1 #define ibm3590_msg2 u.ibm3590.msg2 #define diana_display_mode u.diana.display_mode #define diana_display_len u.diana.display_len #define diana_flash u.diana.flash #define diana_half_msg u.diana.half_msg #define diana_data_format u.diana.data_format #define diana_msg1 u.diana.msg1 #define diana_msg2 u.diana.msg2 /* Definition of MTGETPOS/MTSETPOS structure */ #define MAX_VEND_POS_SIZE 256 /* Maximum vendor specific position * data size. */ struct vendor_specific_pos { u_short position_type;/* Identifies which position type is required. */ short size; /* Number of bytes of position data. */ u_char pos[MAX_VEND_POS_SIZE];/*Generic vendor specific position data*/ }; /* Definition for vendor_specific_pos position_type. */ #define BLKPOSTYPE 0x1001 /* Ampex DST Block Position type. */ #define FSNPOSTYPE 0x1002 /* Ampex DST File Section Position type. */ #define DISPOSTYPE 0x1003 /* Ampex DIS Timecode Position type. */ /* * Define user request codes. These values are returned in field lastreq * of structure mtgetext_t. */ #define MTR_READ 1 /* Read */ #define MTR_WRITE 2 /* Write */ #define MTR_WFM 3 /* Write filemark(s) */ #define MTR_SRB 4 /* Skip records backward, position after FM */ #define MTR_SRF 5 /* Skip records forward, position after FM */ #define MTR_SFB 6 /* Skip filemarks backwards */ #define MTR_SFF 7 /* Skip filemarks forward */ #define MTR_SEOD 8 /* Space to the end of data */ #define MTR_SEOM 9 /* Space to the end of media */ #define MTR_FORMAT 10 /* Skip filemarkds forward */ #define MTR_PART 11 /* Position to a partition */ #define MTR_SSM 12 /* Skip setmarks */ #define MTR_WSM 13 /* Write setmarks */ #define MTR_MODEAUD 14 /* Enable or disable audio mode */ #define MTR_REW 15 /* Rewind */ #define MTR_ERASE 16 /* Erase from current pos to EOT*/ #define MTR_RETEN 17 /* Retension */ #define MTR_UNLOAD 18 /* Unload */ #define MTR_PABS 19 /* Position to an absolute pos */ #define MTR_PAUDIO 20 /* Audio position */ #define MTR_GAUDIO 21 /* Get audio position */ #define MTR_RDLOG 22 /* Read log */ #define MTR_ATTR 23 /* Set attribute */ #define MTR_SPOS 24 /* Set vendor specific position */ #define MTR_GPOS 25 /* Get vendor specific position */ #define MTR_RSV 26 /* Unit reserve */ #define MTR_RLS 27 /* Unit release */ #define MTR_PREEMPT 28 #define MTR_CLEAR 29 #define MTR_LOAD 30 /* Load */ #define MTR_SFBM 31 /* Skip filemarks backward, position at FM */ #define MTR_SFFM 32 /* Skip filemarks forward, position at FM */ #endif /* __TS_MTIO_H__ */ xfsdump-3.1.6+nmu1/common/qlock.h0000644000000000000000000000477112607344125013540 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef QLOCK_H #define QLOCK_H /* qlock - quick locks abstraction * * threads may allocate quick locks using qlock_alloc, and free them with * qlock_free. * * deadlock detection is accomplished by giving an ordinal number to each * lock allocated, and record all locks held by each thread. locks may not * be acquired out of order. that is, subsequently acquired locks must have * a lower ordinal than all locks currently held. for convenience, the ordinals * of all locks to be allocated will be defined in this file. */ #define QLOCK_ORD_CRIT 0 /* ordinal for global critical region lock */ #define QLOCK_ORD_WIN 1 /* ordinal for win abstraction critical regions */ #define QLOCK_ORD_PI 2 /* ordinal for persistent inventory abstraction critical regions */ #define QLOCK_ORD_MLOG 3 /* ordinal for mlog lock */ typedef void *qlockh_t; #define QLOCKH_NULL 0 /* opaque handle */ extern qlockh_t qlock_alloc( ix_t ord ); /* allocates a qlock with the specified ordinal. returns * NULL if lock can't be allocated. */ extern void qlock_lock( qlockh_t qlockh ); /* acquires the specified lock. */ extern void qlock_unlock( qlockh_t qlockh ); /* releases the specified lock. */ typedef void *qsemh_t; #define QSEMH_NULL 0 /* opaque handle */ extern qsemh_t qsem_alloc( size_t cnt ); /* allocates a counting semaphore initialized to the specified * count. returns a qsem handle */ extern void qsem_free( qsemh_t qsemh ); /* frees the counting semaphore */ extern void qsemP( qsemh_t qsemh ); /* "P" (decrement) op */ extern void qsemV( qsemh_t qsemh ); /* "V" (increment) op */ extern bool_t qsemPwouldblock( qsemh_t qsemh ); /* returns true if a qsemP op would block */ extern size_t qsemPavail( qsemh_t qsemh ); /* number of resources available */ #endif /* QLOCK_H */ xfsdump-3.1.6+nmu1/common/cleanup.h0000644000000000000000000000242312607344125014046 0ustar /* * Copyright (c) 2000-2001 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would 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 the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef CLEANUP_H #define CLEANUP_H /* cleanup.[hc] - allows registration of callbacks to be invoked * on exit */ typedef void cleanup_t; extern void cleanup_init( void ); extern cleanup_t *cleanup_register( void ( *funcp )( void *arg1, void *arg2 ), void *arg1, void *arg2 ); extern cleanup_t *cleanup_register_early( void ( *funcp )( void *arg1, void *arg2 ), void *arg1, void *arg2 ); extern void cleanup_cancel( cleanup_t *cleanupp ); extern void cleanup( void ); extern void cleanup_early( void ); #endif /* CLEANUP_H */ xfsdump-3.1.6+nmu1/.gitignore0000644000000000000000000000424712607344125012754 0ustar # object files *.o .dep # build system .census .gitcensus /include/config.h /include/builddefs /install-sh # packaging /doc/CHANGES.gz xfsdump-* xfsdump_* # autoconf generated files /aclocal.m4 /m4/libtool.m4 /m4/ltoptions.m4 /m4/ltsugar.m4 /m4/ltversion.m4 /m4/lt~obsolete.m4 /autom4te.cache/ /config.guess /config.log /config.status /config.sub /configure # libtool /libtool /ltmain.sh *.lo *.la .libs .ltdep # gettext /po/xfsdump.pot /po/*.mo # cscope stuff cscope.* # quilt stuff /.pc/ /patches/ # binaries /dump/xfsdump /invutil/xfsinvutil /restore/xfsrestore # @%#% symlinked sourced files /dump/arch_xlate.[ch] /dump/cldmgr.[ch] /dump/content.h /dump/content_common.[ch] /dump/content_inode.h /dump/dlog.[ch] /dump/drive.[ch] /dump/drive_minrmt.c /dump/drive_scsitape.c /dump/drive_simple.c /dump/exit.h /dump/fs.[ch] /dump/getdents.[ch] /dump/global.[ch] /dump/hsmapi.[ch] /dump/inv_api.c /dump/inv_core.c /dump/inv_files.c /dump/inv_fstab.c /dump/inv_idx.c /dump/inv_mgr.c /dump/inv_priv.h /dump/inv_stobj.c /dump/inventory.h /dump/lock.[ch] /dump/main.c /dump/media.h /dump/mlog.[ch] /dump/openutil.[ch] /dump/path.[ch] /dump/qlock.[ch] /dump/rec_hdr.h /dump/ring.[ch] /dump/sproc.[ch] /dump/stream.[ch] /dump/timeutil.[ch] /dump/ts_mtio.h /dump/types.h /dump/util.[ch] /invutil/global.h /invutil/inv_files.c /invutil/inv_priv.h /invutil/inventory.h /invutil/mlog.h /invutil/timeutil.[ch] /invutil/types.h /invutil/util.h /restore/arch_xlate.[ch] /restore/cldmgr.[ch] /restore/content.h /restore/content_inode.h /restore/dlog.[ch] /restore/drive.[ch] /restore/drive_minrmt.c /restore/drive_scsitape.c /restore/drive_simple.c /restore/exit.h /restore/fs.[ch] /restore/getdents.[ch] /restore/global.[ch] /restore/hsmapi.[ch] /restore/inv_api.c /restore/inv_core.c /restore/inv_files.c /restore/inv_fstab.c /restore/inv_idx.c /restore/inv_mgr.c /restore/inv_priv.h /restore/inv_stobj.c /restore/inventory.h /restore/lock.[ch] /restore/main.c /restore/media.h /restore/mlog.[ch] /restore/openutil.[ch] /restore/path.[ch] /restore/qlock.[ch] /restore/rec_hdr.h /restore/ring.[ch] /restore/sproc.[ch] /restore/stream.[ch] /restore/timeutil.[ch] /restore/ts_mtio.h /restore/types.h /restore/util.[ch] xfsdump-3.1.6+nmu1/debian/0000755000000000000000000000000012643557300012200 5ustar xfsdump-3.1.6+nmu1/debian/rules0000755000000000000000000000234112607344125013257 0ustar #!/usr/bin/make -f export DH_VERBOSE=1 package=xfsdump dirme = debian/$(package) pkgme = DIST_ROOT=`pwd`/$(dirme); export DIST_ROOT; stdenv = @GZIP=-q; export GZIP; options = export DEBUG=-DNDEBUG DISTRIBUTION=debian \ INSTALL_USER=root INSTALL_GROUP=root ; checkdir = test -f debian/rules build: built built: config @echo "== dpkg-buildpackage: build" 1>&2 $(MAKE) default touch built config: .census .census: @echo "== dpkg-buildpackage: configure" 1>&2 $(checkdir) dh_autotools-dev_updateconfig $(options) $(MAKE) include/config.h touch .census clean: @echo "== dpkg-buildpackage: clean" 1>&2 $(checkdir) -rm -f built .census $(MAKE) distclean -rm -rf $(dirme) -rm -f debian/*substvars debian/files* debian/*.debhelper dh_autotools-dev_restoreconfig dh_clean binary-indep: binary-arch: checkroot built @echo "== dpkg-buildpackage: binary-arch" 1>&2 $(checkdir) -rm -rf $(dirme) $(pkgme) $(MAKE) -C . install $(pkgme) $(MAKE) dist dh_installdocs dh_installchangelogs dh_strip dh_compress dh_fixperms dh_makeshlibs dh_installdeb dh_shlibdeps dh_gencontrol dh_md5sums dh_builddeb binary: binary-indep binary-arch checkroot: test 0 -eq `id -u` .PHONY: binary binary-arch binary-indep clean checkroot xfsdump-3.1.6+nmu1/debian/xfsdump.postinst0000644000000000000000000000030312643556443015476 0ustar #!/bin/sh set -e if [ "$1" = 'configure' ]; then for file in xfsdump xfsrestore; do if [ ! -e /usr/sbin/$file ]; then ln -s /sbin/$file /usr/sbin/$file fi done fi #DEBHELPER# xfsdump-3.1.6+nmu1/debian/copyright0000644000000000000000000000072012607344125014131 0ustar This package was debianized by Nathan Scott nathans@debian.org on Sun, 19 Nov 2000 07:37:09 -0500. It was downloaded from ftp://oss.sgi.com/projects/xfs/download/ Copyright: Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. You are free to distribute this software under the terms of the GNU General Public License. On Debian systems, the complete text of the GNU General Public License can be found in /usr/share/common-licenses/GPL file. xfsdump-3.1.6+nmu1/debian/compat0000644000000000000000000000000212607344125013375 0ustar 5 xfsdump-3.1.6+nmu1/debian/Makefile0000644000000000000000000000073012607344125013637 0ustar # # Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved. # TOPDIR = .. include $(TOPDIR)/include/builddefs LSRCFILES = changelog compat control copyright rules shlibs.local watch LDIRDIRT = xfsdump LDIRT = files *.log *.substvars *.debhelper default: include $(BUILDRULES) install: default ifeq ($(PKG_DISTRIBUTION), debian) $(INSTALL) -m 755 -d $(PKG_DOC_DIR) $(INSTALL) -m 644 changelog $(PKG_DOC_DIR)/changelog.Debian endif install-dev: default xfsdump-3.1.6+nmu1/debian/watch0000644000000000000000000000022612607344125013230 0ustar version=3 opts=uversionmangle=s/(\d)[_\.\-\+]?((RC|rc|pre|dev|beta|alpha)\d*)$/$1~$2/ \ ftp://oss.sgi.com/projects/xfs/cmd_tars/xfsdump-(.+)\.tar\.gz xfsdump-3.1.6+nmu1/debian/changelog0000644000000000000000000002512212643557257014067 0ustar xfsdump (3.1.6+nmu1) unstable; urgency=medium * Non-maintainer upload. * Create in postinst the xfsdump and xfsrestore compatibility symlinks. This is needed to support merged /usr systems (closes: #767926) -- Marco d'Itri Thu, 07 Jan 2016 22:44:28 +0100 xfsdump (3.1.6) unstable; urgency=low * New upstream release -- Nathan Scott Tue, 10 Nov 2015 16:16:03 +1100 xfsdump (3.1.5) unstable; urgency=low * New upstream release (closes: #799201) -- Nathan Scott Wed, 14 Oct 2015 12:53:24 +1100 xfsdump (3.1.4) unstable; urgency=low * New upstream release (closes: #747079) * Add a watch file (closes: #748482) * Update configure files during build (closes: #746531) -- Nathan Scott Wed, 16 Jul 2014 13:26:02 +1000 xfsdump (3.1.3) unstable; urgency=low * New upstream release -- Nathan Scott Wed, 08 May 2013 11:53:54 -0500 xfsdump (3.1.1) unstable; urgency=low * New upstream release * Add German translation from Chris Leick (closes: #576257) -- Nathan Scott Wed, 31 Oct 2012 12:39:11 +1100 xfsdump (3.1.0) unstable; urgency=low * New upstream release -- Nathan Scott Mon, 19 Mar 2012 15:07:12 +1100 xfsdump (3.0.6) unstable; urgency=low * New upstream release -- Nathan Scott Wed, 11 Oct 2011 16:46:01 +1100 xfsdump (3.0.5) unstable; urgency=low * New upstream release -- Nathan Scott Wed, 31 Mar 2011 07:30:00 +1100 xfsdump (3.0.4) unstable; urgency=low * New bugfix release -- Nathan Scott Wed, 13 Jan 2009 17:46:03 +1100 xfsdump (3.0.2) unstable; urgency=low * New bugfix release * Update packaging dependencies on latest xfsprogs (closes: #527651) -- Nathan Scott Sat, 09 May 2009 04:42:48 +1000 xfsdump (3.0.0-1) unstable; urgency=low * New upstream release -- Nathan Scott Wed, 28 Jan 2009 22:00:42 +1100 xfsdump (2.2.48-1) unstable; urgency=low * New upstream release * xfsdump depends on ${misc:Depends} * Add debian/watch * Add homepage control header * Fix the following lintian issues: W: xfsdump source: package-uses-deprecated-debhelper-compat-version 1 W: xfsdump source: ancient-standards-version 3.5.9 (current is 3.7.3) -- Anibal Monsalve Salazar Wed, 23 Apr 2008 22:06:34 +1000 xfsdump (2.2.45-1) unstable; urgency=low * New upstream release (closes: #417894). -- Nathan Scott Mon, 28 May 2007 16:09:14 +1000 xfsdump (2.2.38-1) unstable; urgency=low * New upstream release (closes: #368423). -- Nathan Scott Tue, 20 Jun 2006 16:50:49 +1000 xfsdump (2.2.36-1) unstable; urgency=low * New upstream release -- Nathan Scott Thu, 06 Apr 2006 17:07:33 +1000 xfsdump (2.2.35-1) unstable; urgency=low * New upstream release * Switch from debmake to debhelper -- Nathan Scott Wed, 15 Feb 2006 20:04:55 +1100 xfsdump (2.2.30-1) unstable; urgency=low * New upstream release (closes: #318088). -- Nathan Scott Wed, 27 Jul 2005 16:45:42 +1000 xfsdump (2.2.27-1) unstable; urgency=low * New upstream release (closes: #298407). -- Nathan Scott Tue, 08 Mar 2005 10:59:22 +1100 xfsdump (2.2.25-1) unstable; urgency=low * New upstream release -- Nathan Scott Wed, 13 Oct 2004 10:17:53 +1000 xfsdump (2.2.23-1) unstable; urgency=low * New upstream release (closes: #271666) -- Nathan Scott Wed, 15 Sep 2004 07:14:46 +1000 xfsdump (2.2.21-1) unstable; urgency=low * New upstream release (closes: #240908, #214574) -- Nathan Scott Fri, 16 Apr 2004 11:50:56 +1000 xfsdump (2.2.18-1) unstable; urgency=low * New upstream release * Support for the security extended attributes namespace * Update xfsprogs and xfslibs-dev package dependency information -- Nathan Scott Thu, 26 Feb 2004 14:44:41 +1100 xfsdump (2.2.16-1) unstable; urgency=low * New upstream release * Update xfslibs-dev package dependency information -- Nathan Scott Tue, 27 Jan 2004 08:47:23 +1100 xfsdump (2.2.14-1) unstable; urgency=low * New upstream release * Update DMAPI package dependency information -- Nathan Scott Sat, 18 Oct 2003 10:32:47 +1000 xfsdump (2.2.13-1) unstable; urgency=low * New upstream release -- Nathan Scott Wed, 23 Jul 2003 08:31:02 +1000 xfsdump (2.2.12-1) unstable; urgency=low * New upstream release -- Nathan Scott Thu, 29 May 2003 17:26:52 +1000 xfsdump (2.2.11-1) unstable; urgency=low * New upstream release * Fine-tuned shared library dependencies slightly, so we depend on libattr itself (rather than attr which depends on libattr). -- Nathan Scott Sat, 26 Apr 2003 06:30:30 +1000 xfsdump (2.2.10-1) unstable; urgency=low * New upstream release -- Nathan Scott Mon, 14 Apr 2003 11:11:26 +1000 xfsdump (2.2.9-1) unstable; urgency=high * New upstream release fixing xfsdump quota file security issues -- Nathan Scott Thu, 27 Mar 2003 11:05:54 +1100 xfsdump (2.2.8-1) unstable; urgency=low * New upstream release * Updated policy version to which this package conforms -- Nathan Scott Thu, 27 Mar 2003 10:30:18 +1100 xfsdump (2.2.6-1) unstable; urgency=low * New upstream release * Update build dependencies to require new XFS headers -- Nathan Scott Thu, 19 Dec 2002 13:10:49 +1100 xfsdump (2.2.4-1) unstable; urgency=low * New upstream release * Update packaging dependencies to reflect renamed libattr1-dev * Switch from using curses library to ncurses library directly -- Nathan Scott Fri, 8 Nov 2002 09:58:50 +1100 xfsdump (2.2.2-1) unstable; urgency=low * New upstream release (closes: #162038). -- Nathan Scott Mon, 7 Oct 2002 05:19:51 +1000 xfsdump (2.2.0-1) unstable; urgency=low * New upstream release, fixing compatibility with older kernels -- Nathan Scott Tue, 3 Sep 2002 09:22:24 +1000 xfsdump (2.1.5-1) unstable; urgency=low * New upstream release -- Nathan Scott Wed, 14 Aug 2002 09:47:15 +1000 xfsdump (2.1.3-1) unstable; urgency=low * New upstream release -- Nathan Scott Tue, 30 Jul 2002 14:34:17 +1000 xfsdump (2.1.2-1) unstable; urgency=low * New upstream release -- Nathan Scott Mon, 29 Jul 2002 15:43:47 +1000 xfsdump (2.1.0-1) unstable; urgency=low * New upstream release * Uses updated XFS geometry ioctl (version change differentiates this). -- Nathan Scott Thu, 20 Jun 2002 14:43:07 +1000 xfsdump (2.0.4-1) unstable; urgency=low * New upstream release -- Nathan Scott Tue, 18 Jun 2002 09:48:30 +1000 xfsdump (2.0.3-1) unstable; urgency=low * New upstream release (closes: #146121). -- Nathan Scott Wed, 8 May 2002 15:38:18 +1000 xfsdump (2.0.1-1) unstable; urgency=low * New upstream release -- Nathan Scott Sat, 13 Apr 2002 09:45:06 +1000 xfsdump (2.0.0-1) unstable; urgency=low * Major new upstream release * Several system call changes - THIS WILL NOT WORK WITH OLD KERNELS! * Uses the new shared ext2/ext3/XFS extended attributes interfaces -- Nathan Scott Thu, 7 Feb 2002 13:25:26 +1100 xfsdump (1.1.14-1) unstable; urgency=low * New upstream bug-fix release -- Nathan Scott Thu, 17 Jan 2002 11:13:19 +1100 xfsdump (1.1.13-1) unstable; urgency=low * New upstream bug-fix release -- Nathan Scott Mon, 14 Jan 2002 10:59:50 +1100 xfsdump (1.1.12-1) unstable; urgency=low * New upstream bug-fix release * Several xfsrestore performance improvements -- Nathan Scott Wed, 9 Jan 2002 14:21:56 +1100 xfsdump (1.1.10-1) unstable; urgency=low * New upstream bug-fix release -- Nathan Scott Wed, 12 Dec 2001 10:49:17 +1100 xfsdump (1.1.6-0) unstable; urgency=low * New upstream release * Several fixes for IA64 and 64-bit Linux platforms in general * FHS compliance for xfsdump inventory directory (closes: #112566) -- Nathan Scott Wed, 3 Oct 2001 15:09:51 +1000 xfsdump (1.1.3-0) unstable; urgency=low * More changes to libtool build procedure (closes: #106702) -- Nathan Scott Fri, 27 Jul 2001 07:59:49 +1000 xfsdump (1.1.2-1) unstable; urgency=low * Minor changes to build procedure * Add missing libtool build dependency (closes: #106506) -- Nathan Scott Wed, 25 Jul 2001 12:57:42 +1000 xfsdump (1.1.2-0) unstable; urgency=low * New upstream release -- Nathan Scott Tue, 24 Jul 2001 12:15:30 +1000 xfsdump (1.1.1-0) unstable; urgency=low * New upstream release -- Nathan Scott Mon, 23 Jul 2001 10:27:37 +1000 xfsdump (1.1.0-0) unstable; urgency=low * Reworked package slightly so that its not Debian native * Debian-specific changes now documented in changelog.Debian.gz * New upstream release (see /usr/share/doc/xfsdump/changelog.gz) * Checked standards compliance - update standards version to 3.5.5 * Introduce a shlibs.local file to track package inter-dependencies -- Nathan Scott Wed, 18 Jul 2001 15:57:04 +1000 xfsdump (1.0.9) unstable; urgency=low * Correctly [xfs]restore the suid and guid mode bits -- Nathan Scott Tue, 15 May 2001 14:40:03 +1000 xfsdump (1.0.8) unstable; urgency=low * Add a build dependency on xfslibs-dev 1.2.5 (closes: #97097) -- Nathan Scott Sat, 12 May 2001 08:52:27 +1000 xfsdump (1.0.7) unstable; urgency=low * Fix numerous warnings, remove last -Wall filter * Support realtime files in dump/restore * Cleanup arch-specific code, esp. the byteswab routines * Fix bug dumping to remote tape device with given user -- Nathan Scott Wed, 9 May 2001 15:23:23 +1000 xfsdump (1.0.6) unstable; urgency=low * Remove spurious warnings when dumping quota information. -- Nathan Scott Tue, 1 May 2001 15:32:24 +1000 xfsdump (1.0.5) unstable; urgency=low * Initial release (closes: #83832). -- Nathan Scott Wed, 25 Apr 2001 12:19:15 +1000 Local variables: mode: debian-changelog End: xfsdump-3.1.6+nmu1/debian/control0000644000000000000000000000261212607344125013603 0ustar Source: xfsdump Section: admin Priority: optional Maintainer: Nathan Scott Uploaders: Anibal Monsalve Salazar Build-Depends: xfslibs-dev (>= 3.0.0), uuid-dev, libattr1-dev (>= 2.4.14), libncurses-dev, autoconf, debhelper (>= 5), gettext, libtool, autotools-dev Standards-Version: 3.8.1 Homepage: http://oss.sgi.com/projects/xfs/ Package: xfsdump Depends: ${shlibs:Depends}, ${misc:Depends} Suggests: acl, attr, quota Conflicts: xfsprogs (<< 3.0.0) Architecture: any Description: Administrative utilities for the XFS filesystem The xfsdump package contains xfsdump, xfsrestore and a number of other administrative utilities for managing XFS filesystems. . xfsdump examines files in a filesystem, determines which need to be backed up, and copies those files to a specified disk, tape or other storage medium. It uses XFS-specific directives for optimizing the dump of an XFS filesystem, and also knows how to backup XFS extended attributes. Backups created with xfsdump are "endian safe" and can thus be transfered between Linux machines of different architectures and also between IRIX machines. . xfsrestore performs the inverse function of xfsdump; it can restore a full backup of a filesystem. Subsequent incremental backups can then be layered on top of the full backup. Single files and directory subtrees may be restored from full or partial backups. xfsdump-3.1.6+nmu1/debian/xfsdump.postrm0000644000000000000000000000025712643556443015147 0ustar #!/bin/sh set -e if [ "$1" = 'remove' ]; then for file in xfsdump xfsrestore; do if [ -L /usr/sbin/$file ]; then rm /usr/sbin/$file fi done fi #DEBHELPER# xfsdump-3.1.6+nmu1/debian/shlibs.local0000644000000000000000000000010012607344125014466 0ustar libattr 1 libattr1 (>= 2.0.0) libhandle 1 xfsprogs (>= 2.6.30) xfsdump-3.1.6+nmu1/configure.ac0000644000000000000000000000374512620476160013254 0ustar AC_INIT([xfsdump], [3.1.6]) AC_PREREQ(2.50) AC_CONFIG_AUX_DIR([.]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_SRCDIR([common/main.c]) AC_CONFIG_HEADER(include/config.h) AC_PREFIX_DEFAULT(/usr) AC_PROG_LIBTOOL AC_ARG_ENABLE(shared, [ --enable-shared=[yes/no] Enable use of shared libraries [default=yes]],, enable_shared=yes) AC_SUBST(enable_shared) AC_ARG_ENABLE(gettext, [ --enable-gettext=[yes/no] Enable alternate language support [default=yes]],, enable_gettext=yes) AC_SUBST(enable_gettext) AC_ARG_ENABLE(lib64, [ --enable-lib64=[yes/no] Enable lib64 support [default=yes]],, enable_lib64=yes) AC_SUBST(enable_lib64) # # If the user specified a libdir ending in lib64 do not append another # 64 to the library names. # base_libdir=`basename "$libdir"` case $base_libdir in lib64) enable_lib64=no esac # # Some important tools should be installed into the root partitions. # # Check whether exec_prefix=/usr: and install them to /sbin in that # case. If the user choses a different prefix assume he just wants # a local install for testing and not a system install. # case $exec_prefix:$prefix in NONE:NONE | NONE:/usr | /usr:*) root_sbindir='/sbin' root_libdir="/${base_libdir}" ;; *) root_sbindir="${sbindir}" root_libdir="${libdir}" ;; esac AC_SUBST([root_sbindir]) AC_SUBST([root_libdir]) # Find localized files LOCALIZED_FILES="" for lfile in `find ${srcdir} -name '*.c' -type f || exit 1`; do LOCALIZED_FILES="$LOCALIZED_FILES \$(TOPDIR)/$lfile" done AC_SUBST(LOCALIZED_FILES) AC_PACKAGE_GLOBALS(xfsdump) AC_PACKAGE_UTILITIES(xfsdump) AC_MULTILIB($enable_lib64) AC_PACKAGE_NEED_UUID_H AC_PACKAGE_NEED_UUIDCOMPARE AC_PACKAGE_NEED_PTHREAD_H AC_PACKAGE_NEED_PTHREADMUTEXINIT AC_PACKAGE_NEED_NCURSES_H AC_PACKAGE_WANT_WORKING_LIBNCURSES AC_PACKAGE_NEED_XFS_XFS_H AC_PACKAGE_NEED_XFS_HANDLE_H AC_PACKAGE_NEED_OPEN_BY_FSHANDLE AC_PACKAGE_NEED_ATTRIBUTES_H AC_PACKAGE_NEED_ATTRIBUTES_MACROS AC_PACKAGE_NEED_ATTRGET_LIBATTR AC_MANUAL_FORMAT AC_CONFIG_FILES([include/builddefs]) AC_OUTPUT