Imported Debian patch 0.4b40-1 debian/0.4b40-1
authorBdale Garbee <bdale@gag.com>
Wed, 28 Sep 2005 06:50:29 +0000 (00:50 -0600)
committerBdale Garbee <bdale@gag.com>
Tue, 20 May 2008 05:04:27 +0000 (23:04 -0600)
37 files changed:
CHANGES
MCONFIG.in
THANKS
TODO
compat/include/bsdcompat.h
compat/include/protocols/dumprestore.h
config.h.in
configure
configure.in
debian/changelog
debian/compat [new file with mode: 0644]
debian/config
debian/control
debian/po/cs.po [new file with mode: 0644]
debian/po/sv.po
debian/po/vi.po [new file with mode: 0644]
debian/postinst
debian/postrm [new file with mode: 0644]
debian/rules
dump.lsm
dump.spec
dump/dump.8.in
dump/tape.c
dump/traverse.c
examples/dump_on_cd_3/README [new file with mode: 0644]
examples/dump_on_cd_3/dump_disk [new file with mode: 0755]
restore/Makefile.in
restore/dirs.c
restore/extern.h
restore/main.c
restore/restore.8.in
restore/restore.c
restore/restore.h
restore/symtab.c
restore/tape.c
restore/utilities.c
restore/xattr.c [new file with mode: 0644]

diff --git a/CHANGES b/CHANGES
index 501bc1655f6f0feed9edcbc5530abea2183395e4..c4d497d8bb13ad4c762245c447916006cd71935e 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,101 @@
-$Id: CHANGES,v 1.254 2004/07/07 13:34:06 stelian Exp $
+$Id: CHANGES,v 1.275 2005/05/02 15:13:40 stelian Exp $
+
+Changes between versions 0.4b39 and 0.4b40 (released May 2, 2005)
+=================================================================
+
+1.     Changed restore to emit warnings (instead of emitting a fatal
+       error) if a file (or a directory) is unavailable for a 
+       comparision (if the user doesn't have the necessary permissions
+       to access it for example). Thanks to Kenneth Porter
+       <shiva@sewingwitch.com> for the bug report.
+
+2.     Re-done the 'do not save directory entries to non-dumped inodes
+       (excluded from dump)' feature. The previous implementation
+       worked well for excluded directories but not for regular files.
+       Thanks to Kenneth Porter <shiva@sewingwitch.com> for the bug
+       report.
+
+3.     Fixed a bug in dump where the tape size was miscalculated when
+       the user used -d/-s to specify the tape characteristics. Thanks
+       to Philip Goisman <goisman@physics.arizona.edu> for reporting
+       the bug.
+
+4.     Fixed another bug introduced in restore with the hashtree
+       implementation. This one caused restore to stop saying
+       "removenode: non-empty directory" in some cases.
+
+5.     Added support for dumping and restoring ext2/3 extended
+       attributes (EA), like the access control lists (ACL) or
+       the security labels used by SELinux.
+
+Changes between versions 0.4b38 and 0.4b39 (released January 21, 2005)
+======================================================================
+
+1.     The newly added dump_on_cd_3 example was buggy, replace it
+       with an updated version from Andrew Basterfield
+       <bob@cemetery.homeunix.org>.
+
+2.     Made restore to chdir() back into the initial directory when
+       dumping core while aborting a comparision operation. The
+       previous behaviour was to write the corefile at the root of
+       the directory being compared, which could very well be 
+       read only and preventing the corefile generation. Thanks
+       to Kenneth Porter <shiva@sewingwitch.com> for the bug report.
+
+3.     Silenced the failure to call fgetflags() when comparing an
+       entry which has no ext2 attributes (as in lsattr()).
+
+4.     Fix a brown paper bug in restore -C which broke restore and
+       caused modifications on the filesystem being compared
+       (directories containing a file with the same name as the
+       directory get renamed to RSTTMP...). Thanks to Kenneth Porter
+       <shiva@sewingwitch.com> for finding the bug and helping me
+       reproduce it.
+
+5.     Made restore -C force the -N flag (no writing allowed on
+       the disk) in order to prevent more bugs like the above one.
+
+Changes between versions 0.4b37 and 0.4b38 (released January 7, 2005)
+=====================================================================
+
+1.     Fix a couple of troff syntax bugs in the man pages.
+       Thanks to Eric Raymond <esr@thyrsus.com> for the patch.
+
+2.     Made restore use either libncurses or libtermcap, depending
+       on which one is available at configure time.
+
+3.     Fixed restore negative size display bug when comparing a
+       dump containing files over 2GB. Thanks to Steve Bonds
+       <sbonds@users.sourceforge.net> for the bug report.
+
+4.     Do not save directory entries to non-dumped inodes 
+       (excluded from dump). This will eliminate the 'missing
+       file' warnings when doing 'restore -C'.
+
+5.     Fix dump crash when backuping a huge (2TB) filesystem,
+       due to a bogus calculation on the inode map size.
+       Thanks to Kevin B. Haines <K.B.Haines@rl.ac.uk> for 
+       submitting the bug and testing the fix.
+
+6.     Fix a problem in restore where the final \0 in the symbolic
+       link names could have been lost, generating corrupt filenames.
+       Thanks to Kyle Wilson <kyle.wilson@amd.com> for reporting the
+       bug.
+
+7.     Implemented a hash list for the directory names in restore.
+       The linear list used before caused problems in interactive
+       restores when dealing with directories having thousands of
+       entries. Thanks to Brian Ristuccia <bristuccia@starentnetworks.com>
+       for reporting the bug.
+
+8.     Improved restore -C, this time including the directory
+       attributes into the comparision.
+
+9.     Made restore understand tapes containing EA/ACLs (which will
+       be dumped by the next version of dump). In this version 
+       extended attributes on the tape are ignored, for full EA/ACL
+       support wait for the next version or try the experimental EA
+       patch.
 
 Changes between versions 0.4b36 and 0.4b37 (released July 7, 2004)
 ==================================================================
index e20399ee3e3061e1ca7fec1d63e2d3ee102ee3eb..8bce8b0cec0f6d9687c43c6326472dfe5de77f21 100644 (file)
@@ -1,5 +1,5 @@
-VERSION=       0.4b37
-DATE=          July 7, 2004
+VERSION=       0.4b40
+DATE=          May 2, 2005
 
 AR=            @AR@
 CC=            @CC@
diff --git a/THANKS b/THANKS
index 3e2854cf7845c16b29a100d0a024e25eb67b7036..cb7596d4555a7bcf5acb4be2571272ed5649b6a1 100644 (file)
--- a/THANKS
+++ b/THANKS
@@ -1,4 +1,4 @@
-$Id: THANKS,v 1.85 2004/07/01 09:14:48 stelian Exp $
+$Id: THANKS,v 1.89 2004/12/14 14:07:56 stelian Exp $
 
 Dump and restore were written by the people of the CSRG at the University
 of California, Berkeley.
@@ -52,6 +52,7 @@ Arcady Genkin         antipode@users.sourceforge.net
 Uwe Gohlke             uwe@ugsoft.de
 Ian Gordon             iangordon@users.sourceforge.net
 Ted Grzesik            tedgyz@roostme.com
+Kevin B. Haines                K.B.Haines@rl.ac.uk
 Mike Harris            mharris@redhat.com
 Andreas Hasenack       andreas@conectiva.com.br
 Christian Haul         haul@informatik.tu-darmstadt.de
@@ -96,9 +97,10 @@ David B. Peterson    dave@toppledwagon.com
 Trent Piepho           xyzzy@speakeasy.org
 Dave Platt             dplatt@snulbug.mtview.ca.us
 Kenneth Porter         shiva@well.com
-Eric S. Raymond                esr@minx.thyrsus.com
+Eric S. Raymond                esr@thyrsus.com
 Graham Reed            greed@users.sourceforge.net
 Gunther Reiszig                gunther@mit.edu
+Brian Ristuccia                bristuccia@starentnetworks.com
 David Ronis            ronis@ronispc.chem.mcgill.ca
 Dietrich Rothe         d-rothe@users.sourceforge.net
 Bernhard Sadlowski     sadlowsk@Mathematik.Uni-Bielefeld.DE
@@ -128,6 +130,7 @@ Daniel Veillard             Daniel.Veillard@imag.fr
 Jason Venner           jason@idiom.com
 John I Wang            jiwang@users.sourceforge.net
 Christian Weisgerber   naddy@mips.rhein-neckar.de
+Kyle Wilson            kyle.wilson@amd.com
 Kim Yong-jun           loveyou@hackerslab.org
 John Yu                        jky@it.bu.edu
 Ian Zimmerman          itz@speakeasy.org
diff --git a/TODO b/TODO
index d3d4102b842328f813ba7ae85fddfff29b79153b..349b1d15e0c9421445f06b84ca98d80804334d4f 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,4 +1,4 @@
-$Id: TODO,v 1.24 2002/01/25 14:59:53 stelian Exp $
+$Id: TODO,v 1.25 2005/05/02 15:10:44 stelian Exp $
 
 Need to verify:
 ---------------
@@ -31,7 +31,4 @@ All others:
 
 5.     Make a bootable dump tape? I don't know if it is possible...
 
-6.     EA/ACL support in dump (requested by Michael Ju. Tokarev 
-       <mjt@tls.msk.ru>.
-
-7.     Better readline completition in restore (escape spaces etc).
+6.     Better readline completition in restore (escape spaces etc).
index 4b9b9077ac6edacbf38a9e27e2f793a5122a9b52..7bc216038c96b34f9b0804e140a0cbe1699e4e72 100644 (file)
@@ -5,7 +5,7 @@
  *     Stelian Pop <stelian@popies.net>, 1999-2000
  *     Stelian Pop <stelian@popies.net> - Alcôve <www.alcove.com>, 2000-2002
  *
- *     $Id: bsdcompat.h,v 1.23 2004/07/01 09:14:48 stelian Exp $
+ *     $Id: bsdcompat.h,v 1.24 2005/05/02 15:10:45 stelian Exp $
  */
 
 #include <config.h>
@@ -130,6 +130,8 @@ struct dinode {
        __u16   di_uidhigh;
        __u16   di_gidhigh;
        __u32   di_spare;
+       __u16   di_extraisize;
+       __u16   di_pad2;
 };
 
 #define di_rdev                di_db[0]
index fc437159619b7ef60349b0a8be15e3d80ebb5a97..816a83f508a33e336ba30b9c74f92876a658b1dd 100644 (file)
@@ -5,7 +5,7 @@
  *     Stelian Pop <stelian@popies.net>, 1999-2000
  *     Stelian Pop <stelian@popies.net> - Alcôve <www.alcove.com>, 2000-2002
  *
- *     $Id: dumprestore.h,v 1.22 2004/07/01 09:14:49 stelian Exp $
+ *     $Id: dumprestore.h,v 1.24 2005/05/02 15:10:46 stelian Exp $
  */
 
 /*
@@ -150,8 +150,7 @@ union u_spcl {
 #define EXT_REGULAR            0
 #define EXT_MACOSFNDRINFO      1
 #define EXT_MACOSRESFORK       2
-#define EXT_ACL                        3
-
+#define EXT_XATTR              3
 
 /*
  * compression flags for the tapebuf header.
@@ -172,4 +171,9 @@ struct tapebuf {
 #endif
 };
 
+/* used for EA on tape */
+#define EXT2_GOOD_OLD_INODE_SIZE       128
+#define EXT2_XATTR_MAGIC               0xEA020000      /* block EA */
+#define EXT2_XATTR_MAGIC2              0xEA020001      /* in inode EA */
+
 #endif /* !_DUMPRESTORE_H_ */
index 799b2f0ddf4c9cb9c4b4dab4ed25d32b9b2bf294..828ef11b7b5fbfcb871e297ac6360f0208cab18b 100644 (file)
 /* Define to 1 if you have the <ext2fs/ext2_fs.h> header file. */
 #undef HAVE_EXT2FS_EXT2_FS_H
 
+/* Define this if your ext2fs libs have the ext2fs_read_inode_full function.
+   */
+#undef HAVE_EXT2FS_READ_INODE_FULL
+
 /* Define if we have the ext2_ino_t type (from e2fsprogs 1.20+). */
 #undef HAVE_EXT2_INO_T
 
index fde7bb1b9b2c1a2da6336469452875aec1b757d9..522d7b48710baab8bd5e2646d2c84f8b51b8d63d 100755 (executable)
--- a/configure
+++ b/configure
@@ -309,7 +309,7 @@ ac_includes_default="\
 # include <unistd.h>
 #endif"
 
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS SET_MAKE LN_S CP MV RM AR ac_ct_AR RANLIB ac_ct_RANLIB PATCH ac_ct_PATCH CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CPP EGREP DUMPDEBUG RESTOREDEBUG STATIC RMTDIR ERMT CRYPTO OPTDEFS READLINE LD CCOPTS LDOPTS BINOWNER BINGRP BINMODE MANOWNER MANGRP MANMODE DUMPDATESPATH BLKID ZLIB BZLIB top_builddir LIBOBJS LTLIBOBJS'
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS SET_MAKE LN_S CP MV RM AR ac_ct_AR RANLIB ac_ct_RANLIB PATCH ac_ct_PATCH CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CPP EGREP DUMPDEBUG RESTOREDEBUG STATIC RMTDIR ERMT CRYPTO OPTDEFS LD CCOPTS LDOPTS BINOWNER BINGRP BINMODE MANOWNER MANGRP MANMODE DUMPDATESPATH BLKID READLINE ZLIB BZLIB top_builddir LIBOBJS LTLIBOBJS'
 ac_subst_files='MCONFIG'
 
 # Initialize some variables set by options.
@@ -3537,7 +3537,7 @@ then
        READLINE=""
        echo "Not including readline support"
 else
-       READLINE="-lreadline -ltermcap"
+       READLINE="yes"
 
 cat >>confdefs.h <<\_ACEOF
 #define HAVE_READLINE 1
@@ -3547,7 +3547,7 @@ _ACEOF
 fi
 
 else
-  READLINE="-lreadline -ltermcap"
+  READLINE="yes"
 
 cat >>confdefs.h <<\_ACEOF
 #define HAVE_READLINE 1
@@ -3557,7 +3557,6 @@ echo "Including readline support by default"
 
 fi;
 
-
 # Check whether --enable-oldstylefscript or --disable-oldstylefscript was given.
 if test "${enable_oldstylefscript+set}" = set; then
   enableval="$enable_oldstylefscript"
@@ -3937,6 +3936,84 @@ echo "$as_me: error: You need to install the Ext2fs libraries from the E2fsprogs
    { (exit 1); exit 1; }; }
 fi
 
+echo "$as_me:$LINENO: checking for ext2fs_read_inode_full in -lext2fs" >&5
+echo $ECHO_N "checking for ext2fs_read_inode_full in -lext2fs... $ECHO_C" >&6
+if test "${ac_cv_lib_ext2fs_ext2fs_read_inode_full+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lext2fs -lcom_err $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char ext2fs_read_inode_full ();
+int
+main ()
+{
+ext2fs_read_inode_full ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_ext2fs_ext2fs_read_inode_full=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_ext2fs_ext2fs_read_inode_full=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_ext2fs_ext2fs_read_inode_full" >&5
+echo "${ECHO_T}$ac_cv_lib_ext2fs_ext2fs_read_inode_full" >&6
+if test $ac_cv_lib_ext2fs_ext2fs_read_inode_full = yes; then
+  rif=yes
+else
+  rif=no
+fi
+
+if test "$rif" = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_EXT2FS_READ_INODE_FULL 1
+_ACEOF
+
+fi
+
 
 for ac_header in ext2fs/ext2_fs.h
 do
@@ -4244,6 +4321,76 @@ _ACEOF
 fi
 
 
+echo "$as_me:$LINENO: checking for tgetent in -lncurses" >&5
+echo $ECHO_N "checking for tgetent in -lncurses... $ECHO_C" >&6
+if test "${ac_cv_lib_ncurses_tgetent+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lncurses  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char tgetent ();
+int
+main ()
+{
+tgetent ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_ncurses_tgetent=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_ncurses_tgetent=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_ncurses_tgetent" >&5
+echo "${ECHO_T}$ac_cv_lib_ncurses_tgetent" >&6
+if test $ac_cv_lib_ncurses_tgetent = yes; then
+  ncurses_lib=yes
+else
+  ncurses_lib=no
+fi
+
 echo "$as_me:$LINENO: checking for tgetent in -ltermcap" >&5
 echo $ECHO_N "checking for tgetent in -ltermcap... $ECHO_C" >&6
 if test "${ac_cv_lib_termcap_tgetent+set}" = set; then
@@ -4314,13 +4461,19 @@ else
   termcap_lib=no
 fi
 
-if test "$termcap_lib" = no; then
-       if test "$READLINE" = "-lreadline -ltermcap"; then
-               { { echo "$as_me:$LINENO: error: You need to install the GNU termcap library or configure without --enable-readline" >&5
-echo "$as_me: error: You need to install the GNU termcap library or configure without --enable-readline" >&2;}
+
+if test "$ncurses_lib" = no -a "$termcap_lib" = no; then
+       if test "$READLINE" = "yes"; then
+               { { echo "$as_me:$LINENO: error: You need to install the ncurses or termcap library or configure without --enable-readline" >&5
+echo "$as_me: error: You need to install the ncurses or termcap library or configure without --enable-readline" >&2;}
    { (exit 1); exit 1; }; }
        fi
 fi
+if test "$ncurses_lib" = yes; then
+       rdllib="-lncurses"
+elif test "$termcap_lib" = yes; then
+       rdllib="-ltermcap"
+fi
 
 echo "$as_me:$LINENO: checking for readline/readline.h" >&5
 echo $ECHO_N "checking for readline/readline.h... $ECHO_C" >&6
@@ -4377,7 +4530,7 @@ if test "${ac_cv_lib_readline_readline+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   ac_check_lib_save_LIBS=$LIBS
-LIBS="-lreadline "-ltermcap" $LIBS"
+LIBS="-lreadline $rdllib $LIBS"
 cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
@@ -4442,12 +4595,16 @@ else
 fi
 
 if test "$readline_h" = no -o "$readline_lib" = no; then
-       if test "$READLINE" = "-lreadline -ltermcap"; then
+       if test "$READLINE" = "yes"; then
                { { echo "$as_me:$LINENO: error: You need to install the GNU readline library or configure without --enable-readline" >&5
 echo "$as_me: error: You need to install the GNU readline library or configure without --enable-readline" >&2;}
    { (exit 1); exit 1; }; }
        fi
 fi
+if test "$READLINE" = yes; then
+       READLINE="-lreadline $rdllib"
+fi
+
 
 echo "$as_me:$LINENO: checking for rl_completion_matches in -lreadline" >&5
 echo $ECHO_N "checking for rl_completion_matches in -lreadline... $ECHO_C" >&6
@@ -6126,7 +6283,6 @@ s,@RMTDIR@,$RMTDIR,;t t
 s,@ERMT@,$ERMT,;t t
 s,@CRYPTO@,$CRYPTO,;t t
 s,@OPTDEFS@,$OPTDEFS,;t t
-s,@READLINE@,$READLINE,;t t
 s,@LD@,$LD,;t t
 s,@CCOPTS@,$CCOPTS,;t t
 s,@LDOPTS@,$LDOPTS,;t t
@@ -6138,6 +6294,7 @@ s,@MANGRP@,$MANGRP,;t t
 s,@MANMODE@,$MANMODE,;t t
 s,@DUMPDATESPATH@,$DUMPDATESPATH,;t t
 s,@BLKID@,$BLKID,;t t
+s,@READLINE@,$READLINE,;t t
 s,@ZLIB@,$ZLIB,;t t
 s,@BZLIB@,$BZLIB,;t t
 s,@top_builddir@,$top_builddir,;t t
index bcafc467e8b911da99478bd52c5a7cd2042ca0da..3788737049e9edfe9a492949e03fc264e5f6f2d8 100644 (file)
@@ -161,16 +161,15 @@ then
        READLINE=""
        echo "Not including readline support"
 else
-       READLINE="-lreadline -ltermcap"
+       READLINE="yes"
        AC_DEFINE([HAVE_READLINE],1,[Define if you want to include readline support.])
        echo "Including readline support"
 fi
 ,
-READLINE="-lreadline -ltermcap"
+READLINE="yes"
 AC_DEFINE([HAVE_READLINE],1,[Define if you want to include readline support.])
 echo "Including readline support by default"
 )
-AC_SUBST(READLINE)
 
 dnl
 dnl Handle --enable-oldsylefscript
@@ -394,6 +393,14 @@ if test "$ext2fs_h" = no -o "$ext2fs_lib" = no; then
        AC_MSG_ERROR(You need to install the Ext2fs libraries from the E2fsprogs distribution first - hint: make install-libs)
 fi
 
+dnl
+dnl Check for ext2fs_read_inode_full
+dnl
+AC_CHECK_LIB(ext2fs, ext2fs_read_inode_full, [rif=yes], [rif=no], [-lcom_err])
+if test "$rif" = yes; then
+       AC_DEFINE([HAVE_EXT2FS_READ_INODE_FULL],1,[Define this if your ext2fs libs have the ext2fs_read_inode_full function.])
+fi
+
 dnl
 dnl Try to use ext2_fs.h header from libext2fs instead of from the kernel
 dnl
@@ -443,25 +450,36 @@ fi
 AC_SUBST(BLKID)
 
 dnl
-dnl Check for termcap libraries
+dnl Check for ncurses or termcap libraries
 dnl
+AC_CHECK_LIB(ncurses, tgetent, [ncurses_lib=yes], [ncurses_lib=no])
 AC_CHECK_LIB(termcap, tgetent, [termcap_lib=yes], [termcap_lib=no])
-if test "$termcap_lib" = no; then
-       if test "$READLINE" = "-lreadline -ltermcap"; then
-               AC_MSG_ERROR(You need to install the GNU termcap library or configure without --enable-readline)
+
+if test "$ncurses_lib" = no -a "$termcap_lib" = no; then
+       if test "$READLINE" = "yes"; then
+               AC_MSG_ERROR(You need to install the ncurses or termcap library or configure without --enable-readline)
        fi
 fi
+if test "$ncurses_lib" = yes; then
+       rdllib="-lncurses"
+elif test "$termcap_lib" = yes; then
+       rdllib="-ltermcap"
+fi
 
 dnl
 dnl Check for readline headers and libraries
 dnl
 AC_CHECK_HEADER(readline/readline.h, [readline_h=yes], [readline_h=no], [-])
-AC_CHECK_LIB(readline, readline, [readline_lib=yes], [readline_lib=no], "-ltermcap")
+AC_CHECK_LIB(readline, readline, [readline_lib=yes], [readline_lib=no], $rdllib)
 if test "$readline_h" = no -o "$readline_lib" = no; then
-       if test "$READLINE" = "-lreadline -ltermcap"; then
+       if test "$READLINE" = "yes"; then
                AC_MSG_ERROR(You need to install the GNU readline library or configure without --enable-readline)
        fi
 fi
+if test "$READLINE" = yes; then
+       READLINE="-lreadline $rdllib"
+fi
+AC_SUBST(READLINE)
 
 dnl
 dnl Check for rl_completion_matches
index 39ea0004de7b23e24abef9e84570490ca63400bb..fa233d4aa22b1ed821663fb42624d0196923ef25 100644 (file)
@@ -1,3 +1,19 @@
+dump (0.4b40-1) unstable; urgency=low
+
+  * new upstream version, closes: #289210, #291644, #307423
+  * add debconf-2.0 as an alternate dependency
+  * updated Swedish translation from Daniel Nylander, closes: #330316
+  * remove /var/lib/dumpdates on purge, since we created it on install,
+    closes: #330363
+  * update dependencies in light of libreadline5-dev, closes: #326374
+  * rebuild ensures fresh version of zlib in case we've been vulnerable
+    to CAN-2005-2096, closes: #317966
+  * merge Vietnamese translation, closes: #311599
+  * merge Czech translation, closes: #315825
+  * update debhelper compatibility level, plus a few tweaks to pacify lintian
+
+ -- Bdale Garbee <bdale@gag.com>  Wed, 28 Sep 2005 00:50:29 -0600
+
 dump (0.4b37-2) unstable; urgency=low
 
   * merge updated de.po, closes: #281076
diff --git a/debian/compat b/debian/compat
new file mode 100644 (file)
index 0000000..b8626c4
--- /dev/null
@@ -0,0 +1 @@
+4
index 448965653a3394bcd52ca3d565d7eeeb1349cb66..1d8f82e7b7ed493ccb787aae13244eb22d934d0d 100644 (file)
@@ -13,7 +13,7 @@ if [ -L /etc/dumpdates ]; then
     db_go
 fi
 
-if [ -f /etc/dumpdates -a ! -f /var/lib/dumpdates ]; then
+if [ -f /etc/dumpdates ] && [ -f /var/lib/dumpdates ]; then
     # moving from etc to var
     db_input medium dump/moving_from_etc_to_var || true
     db_go
index 83785a072610791da47316cef04e528ea09bdcd2..75dad1ac4e2caddf6afeb7d646cf6612fdf828b7 100644 (file)
@@ -2,12 +2,12 @@ Source: dump
 Section: utils
 Priority: optional
 Maintainer: Bdale Garbee <bdale@gag.com>
-Build-Depends: autoconf, comerr-dev, debhelper (>= 4.1.16), e2fslibs-dev, libbz2-dev, libreadline4-dev, zlib1g-dev, libblkid-dev, uuid-dev
-Standards-Version: 3.6.1.0
+Build-Depends: autoconf, comerr-dev, debhelper (>= 4.1.16), e2fslibs-dev, libbz2-dev, libreadline5-dev | libreadline-dev, zlib1g-dev, libblkid-dev, uuid-dev
+Standards-Version: 3.6.2.1
 
 Package: dump
 Architecture: any
-Depends: ${shlibs:Depends}, debconf (>= 0.5.00), tar (>= 1.13.92-3)
+Depends: ${shlibs:Depends}, debconf (>= 0.5.00) | debconf-2.0, tar (>= 1.13.92-3)
 Description: 4.4bsd dump and restore for ext2 filesystems
  Dump examines files on a filesystem and determines which files need to be 
  backed up.  These files are copied to the given disk, tape or other storage 
diff --git a/debian/po/cs.po b/debian/po/cs.po
new file mode 100644 (file)
index 0000000..7cc808f
--- /dev/null
@@ -0,0 +1,52 @@
+#
+#    Translators, if you are not familiar with the PO format, gettext
+#    documentation is worth reading, especially sections dedicated to
+#    this format, e.g. by running:
+#         info -n '(gettext)PO Files'
+#         info -n '(gettext)Header Entry'
+#
+#    Some information specific to po-debconf are available at
+#            /usr/share/doc/po-debconf/README-trans
+#         or http://www.debian.org/intl/l10n/po-debconf/README-trans
+#
+#    Developers do not need to manually edit POT or PO files.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: dump\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2003-08-19 16:21-0600\n"
+"PO-Revision-Date: 2005-06-25 17:53+0200\n"
+"Last-Translator: Miroslav Kure <kurem@debian.cz>\n"
+"Language-Team: Czech <debian-l10n-czech@lists.debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Description
+#: ../templates:3
+msgid "/etc/dumpdates is a symlink, dump will look in /var/lib/dumpdates"
+msgstr "/etc/dumpdates je symbolický odkaz, dump hledá /var/lib/dumpdates"
+
+#. Description
+#: ../templates:3
+msgid ""
+"Your /etc/dumpdates is a symlink.  Dump will look for dumpdates in /var/lib/"
+"dumpdates.  A symlink in /etc/dumpdates adds no known value (as nothing "
+"outside the dump package is known to use it) and is likely to  confuse "
+"someone eventually.  The most likely reason for this symlink to exist is "
+"that you once had a much earlier version of the Debian dump package "
+"installed that behaved poorly.  Please remove /etc/dumpdates."
+msgstr ""
+"/etc/dumpdates je symbolický odkaz. Dump bude hledat dumpdates ve /var/lib/"
+"dumpdates. Odkaz /etc/dumpdates nepřináší nic užitečného, protože vyjma "
+"balíku dump jej nic jiného nepoužívá a dříve či později někoho zmate. "
+"Nejpravděpodobnější vysvětlení pro existenci tohoto odkazu je, že jste "
+"kdysi dávno používali prastarou verzi balíku dump. Odstraňte prosím "
+"odkaz /etc/dumpdates."
+
+#. Description
+#: ../templates:13
+msgid "Moving existing /etc/dumpdates to /var/lib for FHS compliance."
+msgstr ""
+"Přesouvám stávající /etc/dumpdates do /var/lib kvůli kompatibilitě s FHS."
index 9181b1f8400ab5db386183c14526b7da4ce8dccd..96bdef208c1b952e974c1ceab4b08d11f50c5128 100644 (file)
@@ -1,28 +1,26 @@
-#
-#    Translators, if you are not familiar with the PO format, gettext
-#    documentation is worth reading, especially sections dedicated to
-#    this format, e.g. by running:
-#         info -n '(gettext)PO Files'
-#         info -n '(gettext)Header Entry'
-#
-#    Some information specific to po-debconf are available at
-#            /usr/share/doc/po-debconf/README-trans
-#         or http://www.debian.org/intl/l10n/po-debconf/README-trans
-#
-#    Developers do not need to manually edit POT or PO files.
-#
-#, fuzzy
+# Translators, if you are not familiar with the PO format, gettext
+# documentation is worth reading, especially sections dedicated to
+# this format, e.g. by running:
+# info -n '(gettext)PO Files'
+# info -n '(gettext)Header Entry'
+# Some information specific to po-debconf are available at
+# /usr/share/doc/po-debconf/README-trans
+# or http://www.debian.org/intl/l10n/po-debconf/README-trans
+# Developers do not need to manually edit POT or PO files.
+# , fuzzy
+# 
+# 
 msgid ""
 msgstr ""
-"Project-Id-Version: PACKAGE VERSION\n"
+"Project-Id-Version: dump 0.4b37-2\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2003-08-19 16:21-0600\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: LANGUAGE <LL@li.org>\n"
+"PO-Revision-Date: 2005-09-27 15:47-0700\n"
+"Last-Translator: Daniel Nylander <po@danielnylander.se>\n"
+"Language-Team: Swedish <sv@li.org>\n"
 "MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=ISO-8859-1\n"
-"Content-Transfer-Encoding: 8bit\n"
+"Content-Type: text/plain; charset=iso-8859-1\n"
+"Content-Transfer-Encoding: 8bit"
 
 #. Description
 #: ../templates:3
@@ -38,7 +36,7 @@ msgid ""
 "someone eventually.  The most likely reason for this symlink to exist is "
 "that you once had a much earlier version of the Debian dump package "
 "installed that behaved poorly.  Please remove /etc/dumpdates."
-msgstr ""
+msgstr "Din /etc/dumpdates fil är en symbolisk länk. Dump kommer att leta efter dumpdatum i /var/lib/dumpdates. En symbolisk länk i /etc/dumpdates saknar värde och skapar bara förvirring. Ett antagande är att filen existerar sedan en gammal version av dump som blev installerad felaktigt. Var vänlig och radera /etc/dumpdates."
 
 #. Description
 #: ../templates:13
@@ -49,5 +47,5 @@ msgstr "Flyttar existerande /etc/dumpdates till /var/lib f
 #~ "Your /etc/dumpdates is a symlink.  Dump will look for dumpdates in /var/"
 #~ "lib/dumpdates.  Please fix things."
 #~ msgstr ""
-#~ "Din /etc/dumpdates är en symlänk. Dump kommer att kolla efter dumpdates "
-#~ "i /var/lib/dumpdates. Var snäll och fixa till detta."
+#~ "Din /etc/dumpdates är en symlänk. Dump kommer att kolla efter dumpdates "
+#~ "i /var/lib/dumpdates. Var snäll och fixa till detta."
diff --git a/debian/po/vi.po b/debian/po/vi.po
new file mode 100644 (file)
index 0000000..ffa3a16
--- /dev/null
@@ -0,0 +1,37 @@
+# Vietnamese Translation for dump.
+# Copyright © 2005 Free Software Foundation, Inc.
+# Clytie Siddall <clytie@riverland.net.au>, 2005.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: dump 0.4b37-1\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2003-08-19 16:21-0600\n"
+"PO-Revision-Date: 2005-06-02 15:39+0930\n"
+"Last-Translator: Clytie Siddall <clytie@riverland.net.au>\n"
+"Language-Team: Vietnamese <gnomevi-list@lists.sourceforge.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0\n"
+
+#. Description
+#: ../templates:3
+msgid "/etc/dumpdates is a symlink, dump will look in /var/lib/dumpdates"
+msgstr "/etc/dumpdates là một liên kết tượng trưng nên trình dump sẽ tìm trong /var/lib/dumpdates"
+
+#. Description
+#: ../templates:3
+msgid ""
+"Your /etc/dumpdates is a symlink.  Dump will look for dumpdates in /var/lib/"
+"dumpdates.  A symlink in /etc/dumpdates adds no known value (as nothing "
+"outside the dump package is known to use it) and is likely to  confuse "
+"someone eventually.  The most likely reason for this symlink to exist is "
+"that you once had a much earlier version of the Debian dump package "
+"installed that behaved poorly.  Please remove /etc/dumpdates."
+msgstr "/etc/dumpdates của bạn là một liên kết tượng trưng, nên trình dump sẽ tìm dumpdates (ngày đổ) trong /var/lib/dumpdates. Một liên kết tượng trưng trong /etc/dumpdates không thêm giá trị hữu ích nào (vì không có gì ở ngoại gói dump sẽ dùng nó) và rất có thể sẽ làm cho người dùng lẫn lộn cuối cùng. Có liên kết tượng trưng ấy rất có thể vì trước này bạn đã cài đặt một phiên bản nhiều cũ hơn của gói tin dump Debian mà không hoạt động cho đúng. Hãy loại bỏ /etc/dumpdates."
+
+#. Description
+#: ../templates:13
+msgid "Moving existing /etc/dumpdates to /var/lib for FHS compliance."
+msgstr "Đang di chuyển /etc/dumpdates đã có vào /var/lib để tương tác với FHS."
index 4b13729b4d0257e55c701bbfc1e1c86f7fcead65..f7bc15440ef5d82aebaa75bfa7040e631815ebd0 100644 (file)
@@ -4,7 +4,7 @@ set -e
 
 . /usr/share/debconf/confmodule
 
-if [ -f /etc/dumpdates -a ! -f /var/lib/dumpdates ]; then
+if [ -f /etc/dumpdates ] && [ ! -f /var/lib/dumpdates ]; then
   mv /etc/dumpdates /var/lib/dumpdates
 fi
 
diff --git a/debian/postrm b/debian/postrm
new file mode 100644 (file)
index 0000000..f5ca1ce
--- /dev/null
@@ -0,0 +1,5 @@
+#!/bin/sh -e
+
+rm -f /var/lib/dumpdates
+
+#DEBHELPER#
index 4c603dd959ae95e8f12de60b065aaf47eba7789b..7aa812bdd74d24a56f051045d9a37d09980ffdbe 100755 (executable)
@@ -27,16 +27,16 @@ binary-arch: build
        dh_clean -k
        dh_installdirs
        make install \
-               SBINDIR=`pwd`/debian/tmp/sbin \
-               MANDIR=`pwd`/debian/tmp/usr/share/man/man8
+               SBINDIR=`pwd`/debian/dump/sbin \
+               MANDIR=`pwd`/debian/dump/usr/share/man/man8
 
-       mv debian/tmp/usr/share/man/man8/rmt.8 \
-               debian/tmp/usr/share/man/man8/rmt-dump.8
-       mv debian/tmp/sbin/rmt debian/tmp/usr/sbin/rmt-dump
+       mv debian/dump/usr/share/man/man8/rmt.8 \
+               debian/dump/usr/share/man/man8/rmt-dump.8
+       mv debian/dump/sbin/rmt debian/dump/usr/sbin/rmt-dump
 
-       (cd debian/tmp/sbin ; rm -f rdump rrestore ; \
+       (cd debian/dump/sbin ; rm -f rdump rrestore ; \
                ln -s dump rdump ; ln -s restore rrestore )
-       (cd debian/tmp/usr/share/man/man8 ; rm -f rdump* rrestore* ; \
+       (cd debian/dump/usr/share/man/man8 ; rm -f rdump* rrestore* ; \
                ln -s dump.8.gz rdump.8.gz ; ln -s restore.8.gz rrestore.8.gz )
        dh_installdocs KNOWNBUGS MAINTAINERS README THANKS TODO
        dh_installexamples examples/*
index 73f53f7adf6eccbc4837e3ddf607dd6f2b783904..043c2e2fd9b5283904c14d99fe7778ab741bd43b 100644 (file)
--- a/dump.lsm
+++ b/dump.lsm
@@ -1,13 +1,13 @@
 Begin3
 Title:          dump and restore for Ext2fs
-Version:        0.4b37
-Entered-date:   07JUL04
+Version:        0.4b40
+Entered-date:   01MAY05
 Description:    Port of the 4.4BSD dump and restore backup suite
 Keywords:       backup, filesystem, Ext2fs
 Author:         University of California, Berkeley
 Maintained-by:  stelian@popies.net (Stelian Pop)
 Primary-site:   http://dump.sourceforge.net/
-                0kB dump-0.4b37.tar.gz
+                0kB dump-0.4b40.tar.gz
                 0 dump.lsm
 Original-site:  ftp.freebsd.org /pub/bsd-sources/4.4BSD-Lite2/sbin
                 dump/*
index ae0c08e17aab04420f0d9fceb559dedff6ef6260..6d9019384f91ca59aa208bc8fec96b74bccfb587 100644 (file)
--- a/dump.spec
+++ b/dump.spec
@@ -4,7 +4,7 @@
 
 Summary: Programs for backing up and restoring ext2/ext3 filesystems.
 Name: dump
-Version: 0.4b37
+Version: 0.4b40
 Release: 1
 License: BSD
 URL: http://dump.sourceforge.net
@@ -136,6 +136,12 @@ rm -rf %{buildroot}
 %{_sbindir}/rrestore.static
 
 %changelog
+* Fri Jan 21 2005 Stelian Pop <stelian@popies.net>
+- dump 0.4b39 released, first packaging.
+
+* Fri Jan  7 2005 Stelian Pop <stelian@popies.net>
+- dump 0.4b38 released, first packaging.
+
 * Wed Jul  7 2004 Stelian Pop <stelian@popies.net>
 - dump 0.4b37 released, first packaging.
 
index 487302d89272b94faadce9e3e18bd003f1103b69..a6bf3f0805ac5ba1e84ca5b56511dee660ade92a 100644 (file)
@@ -26,7 +26,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\"    $Id: dump.8.in,v 1.56 2004/04/21 08:55:48 stelian Exp $
+.\"    $Id: dump.8.in,v 1.57 2004/07/13 08:17:32 stelian Exp $
 .\"
 .TH DUMP 8 "version __VERSION__ of __DATE__" BSD "System management commands"
 .SH NAME
@@ -57,9 +57,6 @@ dump \- ext2/3 filesystem backup
 .PP
 .B dump 
 [\fB\-W \fR| \fB\-w\fR]
-.PP
-(The 4.3BSD option syntax is implemented for backward compatibility but is not
-documented here.)
 .SH DESCRIPTION
 .B Dump
 examines files on an ext2/3 filesystem and determines which files need to be
@@ -530,6 +527,9 @@ set of tapes per dumped file system is used, also on a cyclical basis.
 .PP
 After several months or so, the daily and weekly tapes should get rotated out
 of the dump cycle and fresh tapes brought in.
+.PP
+(The 4.3BSD option syntax is implemented for backward compatibility but is not
+documented here.)
 .SH ENVIRONMENT
 .TP 
 .B TAPE
index 2df4d1e242772338f88bce5b9cf6bbd5e4b48cc7..89f630d278ea3484c4ac8aa8054575a81bcdc7a6 100644 (file)
@@ -37,7 +37,7 @@
 
 #ifndef lint
 static const char rcsid[] =
-       "$Id: tape.c,v 1.86 2004/07/07 11:07:29 stelian Exp $";
+       "$Id: tape.c,v 1.88 2005/03/02 08:46:55 stelian Exp $";
 #endif /* not lint */
 
 #include <config.h>
@@ -420,6 +420,10 @@ flushtape(void)
 
        int siz = (char *)nextblock - (char *)slp->req;
 
+       /* make sure returned has sane values in case we don't read 
+        * them from the slave in this pass */
+       returned.unclen = returned.clen = writesize;
+
        slp->req[trecno].count = 0;                     /* Sentinel */
 
        if (dump_atomic_write( slp->fd, (char *)slp->req, siz) != siz)
@@ -475,10 +479,14 @@ flushtape(void)
        }
 
        blks = 0;
-       if (spcl.c_type != TS_END) {
-               for (i = 0; i < spcl.c_count; i++)
-                       if (spcl.c_addr[i] != 0)
-                               blks++;
+       if (spcl.c_type == TS_CLRI || spcl.c_type == TS_BITS)
+               blks = spcl.c_count;
+       else {
+               if (spcl.c_type != TS_END) {
+                       for (i = 0; i < spcl.c_count; i++)
+                               if (spcl.c_addr[i] != 0)
+                                       blks++;
+               }
        }
        slp->count = lastspclrec + blks + 1 - spcl.c_tapea;
        slp->tapea = spcl.c_tapea;
@@ -616,6 +624,10 @@ rollforward(void)
        tslp = &slaves[SLAVES];
        ntb = (union u_spcl *)tslp->tblock[1];
 
+       /* make sure returned has sane values in case we don't read 
+        * them from the slave in this pass */
+       returned.unclen = returned.clen = writesize;
+
        /*
         * Each of the N slaves should have requests that need to
         * be replayed on the next tape.  Use the extra slave buffers
index 41047999c7d921c07237655e50db09f3840136b3..64c32a5b75fc253e0ef4864c58f9c9c1b3fe81e3 100644 (file)
@@ -37,7 +37,7 @@
 
 #ifndef lint
 static const char rcsid[] =
-       "$Id: traverse.c,v 1.61 2004/07/01 09:14:49 stelian Exp $";
+       "$Id: traverse.c,v 1.66 2005/05/02 15:10:46 stelian Exp $";
 #endif /* not lint */
 
 #include <config.h>
@@ -100,6 +100,7 @@ static      void dmpindir __P((dump_ino_t ino, daddr_t blk, int level, fsizeT *size))
 static int searchdir __P((dump_ino_t ino, daddr_t blkno, long size, long filesize));
 #endif
 static void mapfileino __P((dump_ino_t ino, struct dinode const *dp, long *tapesize, int *dirskipped));
+static void dump_xattr __P((dump_ino_t ino, struct dinode *dp));
 
 #ifdef HAVE_EXT2_JOURNAL_INUM
 #define ext2_journal_ino(sb) (sb->s_journal_inum)
@@ -283,6 +284,9 @@ mapfileino(dump_ino_t ino, struct dinode const *dp, long *tapesize, int *dirskip
         */
        SETINO(ino, usedinomap);
 
+       if (NODUMP_FLAG(dp))
+               do_exclude_ino(ino, "nodump attribute");
+
        if (mode == IFDIR)
                SETINO(ino, dumpdirmap);
        if (WANTTODUMP(dp, ino)) {
@@ -296,7 +300,7 @@ mapfileino(dump_ino_t ino, struct dinode const *dp, long *tapesize, int *dirskip
                return;
        }
        if (mode == IFDIR) {
-               if ( NODUMP_FLAG(dp) || exclude_ino(ino) )
+               if (exclude_ino(ino))
                        CLRINO(ino, usedinomap);
                *dirskipped = 1;
        }
@@ -793,6 +797,68 @@ dumponeblock(UNUSED(ext2_filsys fs), blk_t *blocknr, e2_blkcnt_t blockcnt,
 }
 #endif
 
+static void
+dump_xattr(dump_ino_t ino, struct dinode *dp) {
+
+       if (dp->di_extraisize != 0) {
+#ifdef HAVE_EXT2FS_READ_INODE_FULL
+               char inode[EXT2_INODE_SIZE(fs->super)];
+               errcode_t err;
+               u_int32_t *magic;
+
+               memset(inode, 0, EXT2_INODE_SIZE(fs->super));
+               err = ext2fs_read_inode_full(fs, (ext2_ino_t)ino,
+                                            (struct ext2_inode *) inode,
+                                            EXT2_INODE_SIZE(fs->super));
+               if (err) {
+                       com_err(disk, err, "while reading inode #%ld\n", (long)ino);
+                       exit(X_ABORT);
+               }
+
+               magic = (void *)inode + EXT2_GOOD_OLD_INODE_SIZE + dp->di_extraisize;
+               if (*magic == EXT2_XATTR_MAGIC) {
+                       char xattr[EXT2_INODE_SIZE(fs->super)];
+                       int i;
+                       char *cp;
+
+                       if (vflag)
+                               msg("dumping EA (inode) in inode #%ld\n", (long)ino);
+                       memset(xattr, 0, EXT2_INODE_SIZE(fs->super));
+                       memcpy(xattr, (void *)magic,
+                              EXT2_INODE_SIZE(fs->super) - 
+                              (EXT2_GOOD_OLD_INODE_SIZE + dp->di_extraisize));
+                       magic = (u_int32_t *)xattr;
+                       *magic = EXT2_XATTR_MAGIC2;
+
+                       spcl.c_type = TS_INODE;
+                       spcl.c_dinode.di_size = EXT2_INODE_SIZE(fs->super);
+                       spcl.c_flags |= DR_EXTATTRIBUTES;
+                       spcl.c_extattributes = EXT_XATTR;
+                       spcl.c_count = howmany(EXT2_INODE_SIZE(fs->super), TP_BSIZE);
+                       writeheader(ino);
+                       for (i = 0, cp = xattr; i < spcl.c_count; i++, cp += TP_BSIZE)
+                               writerec(cp, 0);
+                       spcl.c_flags &= ~DR_EXTATTRIBUTES;
+                       spcl.c_extattributes = 0;
+               }
+#endif
+       }
+
+       if (dp->di_file_acl) {
+
+               if (vflag)
+                       msg("dumping EA (block) in inode #%ld\n", (long)ino);
+
+               spcl.c_type = TS_INODE;
+               spcl.c_dinode.di_size = sblock->fs_bsize;
+               spcl.c_flags |= DR_EXTATTRIBUTES;
+               spcl.c_extattributes = EXT_XATTR;
+               blksout(&dp->di_file_acl, EXT2_FRAGS_PER_BLOCK(fs->super), ino);
+               spcl.c_flags &= ~DR_EXTATTRIBUTES;
+               spcl.c_extattributes = 0;
+       }
+}
+
 /*
  * Dump passes 3 and 4.
  *
@@ -839,8 +905,6 @@ dumpino(struct dinode *dp, dump_ino_t ino, int metaonly)
        nbi.di_gen = dp->di_gen;
        nbi.di_uid = (((int32_t)dp->di_uidhigh) << 16) | dp->di_uid;
        nbi.di_gid = (((int32_t)dp->di_gidhigh) << 16) | dp->di_gid;
-       if (dp->di_file_acl)
-               msg("ACLs in inode #%ld won't be dumped\n", (long)ino);
        memmove(&spcl.c_dinode, &nbi, sizeof(nbi));
 #else  /* __linux__ */
        spcl.c_dinode = *dp;
@@ -853,6 +917,7 @@ dumpino(struct dinode *dp, dump_ino_t ino, int metaonly)
                spcl.c_count = 0;
                writeheader(ino);
                spcl.c_flags &= ~DR_METAONLY;
+               dump_xattr(ino, dp);
                return;
        }
 
@@ -883,6 +948,7 @@ dumpino(struct dinode *dp, dump_ino_t ino, int metaonly)
                        memmove(buf, dp->di_db, (u_long)dp->di_size);
                        buf[dp->di_size] = '\0';
                        writerec(buf, 0);
+                       dump_xattr(ino, dp);
                        return;
                }
 #endif /* __linux__ */
@@ -913,6 +979,7 @@ dumpino(struct dinode *dp, dump_ino_t ino, int metaonly)
        case S_IFCHR:
        case S_IFBLK:
                writeheader(ino);
+               dump_xattr(ino, dp);
                return;
 
        default:
@@ -928,8 +995,10 @@ dumpino(struct dinode *dp, dump_ino_t ino, int metaonly)
        else
                cnt = howmany(i_size, sblock->fs_fsize);
        blksout(&dp->di_db[0], cnt, ino);
-       if ((quad_t) (size = i_size - NDADDR * sblock->fs_bsize) <= 0)
+       if ((quad_t) (size = i_size - NDADDR * sblock->fs_bsize) <= 0) {
+               dump_xattr(ino, dp);
                return;
+       }
 #ifdef __linux__
        bc.max = NINDIR(sblock) * EXT2_FRAGS_PER_BLOCK(fs->super);
        bc.buf = (int *)malloc (bc.max * sizeof (int));
@@ -953,6 +1022,7 @@ dumpino(struct dinode *dp, dump_ino_t ino, int metaonly)
                blksout (bc.buf, bc.cnt, bc.ino);
        }
        free(bc.buf);
+       dump_xattr(ino, dp);
 #else
        for (ind_level = 0; ind_level < NIADDR; ind_level++) {
                dmpindir(ino, dp->di_ib[ind_level], ind_level, &size);
@@ -985,6 +1055,10 @@ convert_dir(struct ext2_dir_entry *dirent, UNUSED(int offset),
        struct direct *dp;
        int reclen;
 
+       /* do not save entries to excluded inodes */
+       if (exclude_ino(dirent->inode))
+               return 0;
+
        p = (struct convert_dir_context *)private;
 
        reclen = EXT2_DIR_REC_LEN((dirent->name_len & 0xFF) + 1);
@@ -1097,8 +1171,6 @@ dumpdirino(struct dinode *dp, dump_ino_t ino)
        nbi.di_gen = dp->di_gen;
        nbi.di_uid = (((int32_t)dp->di_uidhigh) << 16) | dp->di_uid;
        nbi.di_gid = (((int32_t)dp->di_gidhigh) << 16) | dp->di_gid;
-       if (dp->di_file_acl)
-               msg("ACLs in inode #%ld won't be dumped\n", (long)ino);
        memmove(&spcl.c_dinode, &nbi, sizeof(nbi));
 #else  /* __linux__ */
        spcl.c_dinode = *dp;
@@ -1135,6 +1207,7 @@ dumpdirino(struct dinode *dp, dump_ino_t ino)
        }
 
        (void)free(cdc.buf);
+       dump_xattr(ino, dp);
 }
 #endif /* __linux__ */
 
@@ -1241,6 +1314,7 @@ dumpmap(char *map, int type, dump_ino_t ino)
 
        spcl.c_type = type;
        spcl.c_count = howmany(mapsize * sizeof(char), TP_BSIZE);
+       spcl.c_dinode.di_size = mapsize;
        writeheader(ino);
        for (i = 0, cp = map; i < spcl.c_count; i++, cp += TP_BSIZE)
                writerec(cp, 0);
@@ -1291,7 +1365,11 @@ getino(dump_ino_t inum)
        errcode_t err;
 
        curino = inum;
+#ifdef HAVE_EXT2FS_READ_INODE_FULL
+       err = ext2fs_read_inode_full(fs, (ext2_ino_t)inum, (struct ext2_inode *) &dinode, sizeof(struct dinode));
+#else
        err = ext2fs_read_inode(fs, (ext2_ino_t)inum, (struct ext2_inode *) &dinode);
+#endif
        if (err) {
                com_err(disk, err, "while reading inode #%ld\n", (long)inum);
                exit(X_ABORT);
diff --git a/examples/dump_on_cd_3/README b/examples/dump_on_cd_3/README
new file mode 100644 (file)
index 0000000..c632be6
--- /dev/null
@@ -0,0 +1,16 @@
+I took the dump_on_cd_2/EN/* scripts and merged the pair of scripts into one
+script, which checks it's arguments to tell whether or not it is called from
+dump and acts accordingly.
+
+The script commandline takes dump arguments except -f (output file/device), -F
+(script to run after each volume is finished) and -B (volume size) which are
+overridden.
+
+You can use the script to backup to CD with cdrtecord from cdrtools or to
+DVD with either cdrtools with DVD support or growisofs from dvd+rw-tools.
+You must configure the burning process by adjusting the variables at the top
+of the script.
+
+Andrew Basterfield
+
+bob@cemetery.homeunix.org
diff --git a/examples/dump_on_cd_3/dump_disk b/examples/dump_on_cd_3/dump_disk
new file mode 100755 (executable)
index 0000000..3e9200d
--- /dev/null
@@ -0,0 +1,100 @@
+#!/bin/sh
+
+# This script dumps the specified Filesystem via dump on a CD/DVD
+# DISK_CAPACITY defines the capacity in MB per disk.
+# The script's own name $0 is passed via the -F option of dump
+# When using cdrecord/dvdrecord and at least for my DVD-Recorder (a PHILIPS
+# DVR-A03) it is necessary to define the tracksize for the next track before
+# the DVD is written. This is done via the -tsize option of cdrecord. Since
+# tsize takes its arguments in Bytes, the shell cannot compute the value
+# correctly anymore (value too high), so I use bc.
+
+# Set this to 4300 for DVD and 650 or 700 for CD
+#DISK_CAPACITY=10      # testing
+#DISK_CAPACITY=650
+DISK_CAPACITY=4300
+
+BSIZE="$(echo "$DISK_CAPACITY*1024" | bc -l )"
+TSIZE="$(echo "$DISK_CAPACITY*1024*1024" | bc -l )"
+
+# This is used for testing
+#RECORD_BIN="dd of=/dev/null bs=1k if="
+
+# This is for writing to CD with cdrtools, this uses track-at-once mode
+# in case cdrtools does not support disk-at-once with your burner
+#RECORD_BIN="/usr/bin/cdrecord dev=0,0,0 fs=64M speed=2 -eject -tao -pad -tsize=$TSIZE -data "
+
+# This is for writing to DVD with cdrtools with DVD support, this has to
+# use disk-at-once mode.
+#RECORD_BIN="/usr/bin/cdrecord dev=0,0,0 fs=64M speed=2 -eject -dao -pad -tsize=$TSIZE -data "
+
+# This is for writing to DVD with growisofs
+RECORD_BIN="/usr/bin/growisofs -Z /dev/dvd="
+
+FIFO="/tmp/dump.$$.fifo"
+DUMP="/sbin/dump"
+
+cleanup() {
+       rm -f $FIFO
+}
+
+error_exit() {
+       retcode=$?
+       echo >&2 "Error $retcode: exiting"
+       exit $retcode
+}
+
+trap error_exit ERR
+
+write_output() {
+       # supplied info from "dump -F":
+       # $1 = filename
+       # $2 = sequence number
+       echo "Please insert disk No. $(($2+1))"
+       ANSWER=""
+       while [ "$ANSWER" != "y" ] ; do
+               echo -n "Is the disk ready? (y/n) "
+               read  </dev/tty ANSWER
+               if [ "$ANSWER" == "y" ] ; then
+                       (${RECORD_BIN}${1}) &
+                       return 0
+               elif [ "$ANSWER" == "n" ] ; then
+                       EXIT=""
+                       echo -n "Do you really want to exit? (y/n) "
+                       read </dev/tty EXIT
+                       if [ "$EXIT" == "y" ] ; then
+                               return 1
+                       fi
+               fi
+       done
+}
+
+if [ "$#" = "0" ] || [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
+       echo >&2 "Usage: $0 <dump options>"
+       echo >&2 "See 'man dump' for dump options"
+       echo >&2 "the dump options -F -f -B are not required and are overridden"
+       exit 1
+fi
+
+set -m # We need proper job control
+
+if [ "$#" = "2" ] && [ -p "$1" ]; then
+       write_output "$@" || (kill $$ >/dev/null 2>&1; exit 1)
+       exit 0
+else
+       mkfifo $FIFO
+       trap cleanup EXIT
+       if write_output "$FIFO" "0"; then
+               if $DUMP "$@" -F "$0" -f "$FIFO" -B$BSIZE; then
+                       echo "Waiting for background writing process to complete"
+                       wait %                  # Wait for the background writing process
+               else
+                       kill % >/dev/null 2>&1  # or kill it
+                       exit 1
+               fi
+               exit 0
+       else
+               kill % >/dev/null 2>&1  # Kill the background writing process
+               exit 1
+       fi
+fi
index cdc2004cf1076daf784e0e939990ac04781cdacb..79e03ea609065b0e1a458734e3565386d05be94f 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: Makefile.in,v 1.12 2003/05/08 21:11:39 stelian Exp $
+# $Id: Makefile.in,v 1.13 2005/05/02 15:10:46 stelian Exp $
 
 top_srcdir=    @top_srcdir@
 srcdir=                @srcdir@
@@ -16,9 +16,9 @@ PROG=         restore
 RPROG=         rrestore
 LINKS=         ${SBINDIR}/restore ${SBINDIR}/rrestore
 SRCS=          dirs.c interactive.c main.c restore.c symtab.c tape.c \
-               utilities.c
+               utilities.c xattr.c
 OBJS=          dirs.o interactive.o main.o restore.o symtab.o tape.o \
-               utilities.o ../common/dumprmt.o
+               utilities.o xattr.o ../common/dumprmt.o
 MAN8=          restore.8
 RMAN8=         rrestore.8
 
index 2a23f9486b62c940530954b69b1bdf346ff3b8f7..b049f49007801c6caa8c70d755b38ecce9dbc860 100644 (file)
@@ -42,7 +42,7 @@
 
 #ifndef lint
 static const char rcsid[] =
-       "$Id: dirs.c,v 1.28 2004/05/25 10:39:30 stelian Exp $";
+       "$Id: dirs.c,v 1.32 2005/05/02 15:10:46 stelian Exp $";
 #endif /* not lint */
 
 #include <config.h>
@@ -114,6 +114,7 @@ struct modeinfo {
        uid_t uid;
        gid_t gid;
        unsigned int flags;
+       char xattr;
 };
 
 /*
@@ -148,9 +149,11 @@ struct odirect {
 };
 
 #if defined(__linux__) || defined(sunos)
-static struct inotab   *allocinotab __P((dump_ino_t, struct new_bsd_inode *, OFF_T));
+static struct inotab   *allocinotab __P((dump_ino_t, OFF_T));
+static void            savemodeinfo __P((dump_ino_t, struct new_bsd_inode *, char *));
 #else
-static struct inotab   *allocinotab __P((dump_ino_t, struct dinode *, OFF_T));
+static struct inotab   *allocinotab __P((dump_ino_t, OFF_T));
+static void            savemodeinfo __P((dump_ino_t, struct dinode *, char *));
 #endif
 static void             dcvt __P((struct odirect *, struct direct *));
 static void             flushent __P((void));
@@ -177,13 +180,16 @@ extractdirs(int genmode)
 {
        int i;
 #if defined(__linux__) || defined(sunos)
-       struct new_bsd_inode *ip;
+       struct new_bsd_inode ip;
 #else
-       struct dinode *ip;
+       struct dinode ip;
 #endif
        struct inotab *itp;
        struct direct nulldir;
        int fd;
+       char xattr[XATTR_MAXSIZE];
+       int xattr_found = 0;
+       dump_ino_t ino;
 
        Vprintf(stdout, "Extract directories from tape\n");
        (void) snprintf(dirfile, sizeof(dirfile), "%s/rstdir%ld", tmpdir,
@@ -222,8 +228,8 @@ extractdirs(int genmode)
        for (;;) {
                curfile.name = "<directory file - name unknown>";
                curfile.action = USING;
-               ip = curfile.dip;
-               if (ip == NULL || (ip->di_mode & IFMT) != IFDIR) {
+               ino = curfile.ino;
+               if (curfile.dip == NULL || (curfile.dip->di_mode & IFMT) != IFDIR) {
                        if ( fclose(df) == EOF )
                                err(1, "cannot write to file %s", dirfile);
                        dirp = opendirfile(dirfile);
@@ -236,8 +242,30 @@ extractdirs(int genmode)
                                panic("Root directory is not on tape\n");
                        return;
                }
-               itp = allocinotab(curfile.ino, ip, seekpt);
+               memcpy(&ip, curfile.dip, sizeof(ip));
+               itp = allocinotab(ino, seekpt);
                getfile(putdir, xtrnull);
+               xattr_found = 0;
+               while (spcl.c_flags & DR_EXTATTRIBUTES) {
+                       switch (spcl.c_extattributes) {
+                       case EXT_MACOSFNDRINFO:
+                               msg("MacOSX attributes not supported, skipping\n");
+                               skipfile();
+                               break;
+                       case EXT_MACOSRESFORK:
+                               msg("MacOSX attributes not supported, skipping\n");
+                               skipfile();
+                               break;
+                       case EXT_XATTR:
+                               if (readxattr(xattr) == GOOD)
+                                       xattr_found = 1;
+                               break;
+                       }
+               }
+               if (xattr_found)
+                       savemodeinfo(ino, &ip, xattr);
+               else
+                       savemodeinfo(ino, &ip, NULL);
                putent(&nulldir);
                flushent();
                itp->t_size = seekpt - itp->t_seekpt;
@@ -654,9 +682,15 @@ setdirmodes(int flags)
        }
        clearerr(mf);
        for (;;) {
+               char xattr[XATTR_MAXSIZE];
                (void) fread((char *)&node, 1, sizeof(struct modeinfo), mf);
                if (feof(mf))
                        break;
+               if (node.xattr) {
+                       (void) fread(xattr, 1, XATTR_MAXSIZE, mf);
+                       if (feof(mf))
+                               break;
+               }
                ep = lookupino(node.ino);
                if (command == 'i' || command == 'x') {
                        if (ep == NULL)
@@ -678,7 +712,7 @@ setdirmodes(int flags)
                        (void) chmod(cp, node.mode);
                        if (node.flags)
 #ifdef __linux__
-                               (void) fsetflags(cp, node.flags);
+                               (void) lsetflags(cp, node.flags);
 #else
 #ifdef sunos
 #else
@@ -686,6 +720,105 @@ setdirmodes(int flags)
 #endif
 #endif
                        utimes(cp, node.timep);
+                       if (node.xattr)
+                               xattr_extract(cp, xattr);
+                       ep->e_flags &= ~NEW;
+               }
+       }
+       if (ferror(mf))
+               panic("error setting directory modes\n");
+       (void) fclose(mf);
+}
+
+/*
+ * In restore -C mode, tests the attributes for all directories
+ */
+void
+comparedirmodes(void)
+{
+       FILE *mf;
+       struct modeinfo node;
+       struct entry *ep;
+       char *cp;
+
+       Vprintf(stdout, "Compare directories modes, owner, attributes.\n");
+       if (modefile[0] == '#') {
+               panic("modefile not defined\n");
+               fprintf(stderr, "directory mode, owner, and times not set\n");
+               return;
+       }
+       mf = fopen(modefile, "r");
+       if (mf == NULL) {
+               warn("fopen");
+               fprintf(stderr, "cannot open mode file %s\n", modefile);
+               fprintf(stderr, "directory mode, owner, and times not set\n");
+               return;
+       }
+       clearerr(mf);
+       for (;;) {
+               char xattr[XATTR_MAXSIZE];
+               (void) fread((char *)&node, 1, sizeof(struct modeinfo), mf);
+               if (feof(mf))
+                       break;
+               if (node.xattr) {
+                       (void) fread(xattr, 1, XATTR_MAXSIZE, mf);
+                       if (feof(mf))
+                               break;
+               }
+               ep = lookupino(node.ino);
+               if (ep == NULL) {
+                       panic("cannot find directory inode %d\n", node.ino);
+               } else {
+                       cp = myname(ep);
+                       struct STAT sb;
+                       unsigned long newflags;
+
+                       if (LSTAT(cp, &sb) < 0) {
+                               warn("unable to stat %s", cp);
+                               do_compare_error;
+                               continue;
+                       }
+
+                       Vprintf(stdout, "comparing directory %s\n", cp);
+
+                       if (sb.st_mode != node.mode) {
+                               fprintf(stderr, "%s: mode changed from 0%o to 0%o.\n",
+                                       cp, node.mode & 07777, sb.st_mode & 07777);
+                               do_compare_error;
+                       }
+                       if (sb.st_uid != node.uid) {
+                               fprintf(stderr, "%s: uid changed from %d to %d.\n",
+                                       cp, node.uid, sb.st_uid);
+                               do_compare_error;
+                       }
+                       if (sb.st_gid != node.gid) {
+                               fprintf(stderr, "%s: gid changed from %d to %d.\n",
+                                       cp, node.gid, sb.st_gid);
+                               do_compare_error;
+                       }
+#ifdef __linux__
+                       if (lgetflags(cp, &newflags) < 0) {
+                               if (node.flags != 0) {
+                                       warn("%s: lgetflags failed", cp);
+                                       do_compare_error;
+                               }
+                       }
+                       else {
+                               if (newflags != node.flags) {
+                                       fprintf(stderr, "%s: flags changed from 0x%08x to 0x%08lx.\n",
+                                               cp, node.flags, newflags);
+                                       do_compare_error;
+                               }
+                       }
+#endif
+                       if (node.xattr) {
+                               if (xattr_compare(cp, xattr) == FAIL)
+                                       do_compare_error;
+                       }
+                       else {
+                               if (xattr_compare(cp, NULL) == FAIL)
+                                       do_compare_error;
+                       }
                        ep->e_flags &= ~NEW;
                }
        }
@@ -751,13 +884,12 @@ inodetype(dump_ino_t ino)
  */
 static struct inotab *
 #if defined(__linux__) || defined(sunos)
-allocinotab(dump_ino_t ino, struct new_bsd_inode *dip, OFF_T seekpt)
+allocinotab(dump_ino_t ino, OFF_T seekpt)
 #else
-allocinotab(dump_ino_t ino, struct dinode *dip, OFF_T seekpt)
+allocinotab(dump_ino_t ino, OFF_T seekpt)
 #endif
 {
        struct inotab   *itp;
-       struct modeinfo node;
 
        itp = calloc(1, sizeof(struct inotab));
        if (itp == NULL)
@@ -766,8 +898,19 @@ allocinotab(dump_ino_t ino, struct dinode *dip, OFF_T seekpt)
        inotab[INOHASH(ino)] = itp;
        itp->t_ino = ino;
        itp->t_seekpt = seekpt;
+       return itp;
+}
+
+static void
+#if defined(__linux__) || defined(sunos)
+savemodeinfo(dump_ino_t ino, struct new_bsd_inode *dip, char *xattr) {
+#else
+savemodeinfo(dump_ino_t ino, struct dinode *dip, char *xattr) {
+#endif
+       struct modeinfo node;
+
        if (mf == NULL)
-               return (itp);
+               return;
        node.ino = ino;
 #if defined(__linux__) || defined(sunos)
        node.timep[0].tv_sec = dip->di_atime.tv_sec;
@@ -784,9 +927,12 @@ allocinotab(dump_ino_t ino, struct dinode *dip, OFF_T seekpt)
        node.flags = dip->di_flags;
        node.uid = dip->di_uid;
        node.gid = dip->di_gid;
+       node.xattr = xattr ? 1 : 0;
        if ( fwrite((char *)&node, 1, sizeof(struct modeinfo), mf) != sizeof(struct modeinfo) )
                err(1,"cannot write to file %s", modefile);
-       return (itp);
+       if (xattr)
+               if ( fwrite(xattr, 1, XATTR_MAXSIZE, mf) != XATTR_MAXSIZE)
+                       err(1,"cannot write to file %s", modefile);
 }
 
 /*
index e2702ed6587de0b58d6adbe985884c76d8a8691b..16e2440e380e9b7d5fa915e183c05433ef8b1d53 100644 (file)
@@ -5,7 +5,7 @@
  *     Stelian Pop <stelian@popies.net>, 1999-2000
  *     Stelian Pop <stelian@popies.net> - Alcôve <www.alcove.com>, 2000-2002
  *
- *     $Id: extern.h,v 1.23 2003/10/26 16:05:48 stelian Exp $
+ *     $Id: extern.h,v 1.25 2005/05/02 15:10:46 stelian Exp $
  */
 
 /*-
@@ -107,6 +107,7 @@ void                 rst_closedir __P((RST_DIR *dirp));
 void            runcmdshell __P((void));
 char           *savename __P((char *));
 void            setdirmodes __P((int));
+void            comparedirmodes __P((void));
 void            setinput __P((char *));
 void            setup __P((void));
 void            skipdirs __P((void));
@@ -131,6 +132,9 @@ int fsetflags __P((const char *, unsigned long));
 int fgetflags __P((const char *, unsigned long *));
 int setflags __P((int, unsigned long));
 
+int lsetflags __P((const char *, unsigned long));
+int lgetflags __P((const char *, unsigned long *));
+
 #ifdef USE_QFA
 int    Inode2Tapepos __P((dump_ino_t, long *, long long *, int));
 int    GetTapePos __P((long long *));
@@ -152,5 +156,7 @@ int extractresourceufs __P((char *));
 int    CreateAppleDoubleFileRes __P((char *, FndrFileInfo *, mode_t, int, struct timeval *, u_int32_t, u_int32_t));
 #endif
 
-
-
+void   skipxattr __P((void));
+int    readxattr __P((char *));
+int    xattr_compare __P((char *, char *));
+int    xattr_extract __P((char *, char *));
index f53d740513c1718b9c156bde174737c15e1edc7a..dfbe8c6ce557ca18d282e67c290b0f8f0ad911ef 100644 (file)
@@ -37,7 +37,7 @@
 
 #ifndef lint
 static const char rcsid[] =
-       "$Id: main.c,v 1.46 2004/04/13 13:04:33 stelian Exp $";
+       "$Id: main.c,v 1.49 2005/01/14 13:04:56 stelian Exp $";
 #endif /* not lint */
 
 #include <config.h>
@@ -112,6 +112,7 @@ char        filesys[NAMELEN];
 static const char *stdin_opt = NULL;
 char   *bot_script = NULL;
 dump_ino_t volinfo[TP_NINOS];
+int    wdfd;
 
 #ifdef USE_QFA
 FILE   *gTapeposfp;
@@ -356,6 +357,10 @@ main(int argc, char *argv[])
        else
                setinput(inputdev);
 
+       wdfd = open(".", O_RDONLY);
+       if (wdfd < 0)
+               err(1, "can't get current directory");
+
        if (argc == 0 && !filelist) {
                argc = 1;
                *--argv = ".";
@@ -419,6 +424,7 @@ main(int argc, char *argv[])
                Vprintf(stdout, "Begin compare restore\n");
                compare_ignore_not_found = 0;
                compare_errors = 0;
+               Nflag = 1;
                setup();
                printf("filesys = %s\n", filesys);
                if (STAT(filesys, &stbuf) < 0)
@@ -427,9 +433,10 @@ main(int argc, char *argv[])
                        err(1, "cannot cd to %s", filesys);
                compare_ignore_not_found = dumptime > 0;
                initsymtable((char *)0);
-               extractdirs(0);
+               extractdirs(1);
                treescan(".", ROOTINO, nodeupdates);
                compareleaves();
+               comparedirmodes();
                checkrestore();
                if (compare_errors) {
                        printf("Some files were modified!\n");
index d7f934b34e836374e7a2f9c180e839fc01bb8b19..1d9234220e6415a807626bb04c6b719dcefa8e5d 100644 (file)
@@ -25,7 +25,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\"    $Id: restore.8.in,v 1.31 2003/06/11 13:01:36 stelian Exp $
+.\"    $Id: restore.8.in,v 1.32 2004/07/13 08:17:32 stelian Exp $
 .\"
 .TH RESTORE 8 "version __VERSION__ of __DATE__" BSD "System management commands"
 .SH NAME
@@ -102,9 +102,6 @@ restore \- restore files or file systems from backups made with dump
 [\fB\-T \fIdirectory\fR]
 [\fB\-X \fIfilelist\fR]
 [ \fIfile ... \fR]
-.PP
-(The 4.3BSD option syntax is implemented for backward compatibility but is not 
-documented here.)
 .SH DESCRIPTION
 The
 .B restore
@@ -541,6 +538,9 @@ may be an ordinary file or
 .B \-y
 Do not ask the user whether to abort the restore in the event of an error.
 Always try to skip over the bad block(s) and continue.
+.PP
+(The 4.3BSD option syntax is implemented for backward compatibility but is not 
+documented here.)
 .SH DIAGNOSTICS
 Complains if it gets a read error. If 
 .B y
index b95e3569cd8b79e07c21ecc8c2f13c73fb5c8458..94e0bb6cc8f853c5a4243aeaf0c2dcf738568a2c 100644 (file)
@@ -37,7 +37,7 @@
 
 #ifndef lint
 static const char rcsid[] =
-       "$Id: restore.c,v 1.33 2003/11/22 16:52:16 stelian Exp $";
+       "$Id: restore.c,v 1.36 2005/03/18 22:12:55 stelian Exp $";
 #endif /* not lint */
 
 #include <config.h>
@@ -572,19 +572,24 @@ findunreflinks(void)
 {
        struct entry *ep, *np;
        dump_ino_t i;
+       int j;
 
        Vprintf(stdout, "Find unreferenced names.\n");
        for (i = ROOTINO; i < maxino; i++) {
                ep = lookupino(i);
                if (ep == NULL || ep->e_type == LEAF || TSTINO(i, dumpmap) == 0)
                        continue;
-               for (np = ep->e_entries; np != NULL; np = np->e_sibling) {
-                       if (np->e_flags == 0) {
-                               Dprintf(stdout,
-                                   "%s: remove unreferenced name\n",
-                                   myname(np));
-                               removeleaf(np);
-                               freeentry(np);
+               if (ep->e_entries == NULL)
+                       continue;
+               for (j = 0; j < DIRHASH_SIZE; j++) {
+                       for (np = ep->e_entries[j]; np != NULL; np = np->e_sibling) {
+                               if (np->e_flags == 0) {
+                                       Dprintf(stdout,
+                                           "%s: remove unreferenced name\n",
+                                           myname(np));
+                                       removeleaf(np);
+                                       freeentry(np);
+                               }
                        }
                }
        }
@@ -592,15 +597,19 @@ findunreflinks(void)
         * Any leaves remaining in removed directories is unreferenced.
         */
        for (ep = removelist; ep != NULL; ep = ep->e_next) {
-               for (np = ep->e_entries; np != NULL; np = np->e_sibling) {
-                       if (np->e_type == LEAF) {
-                               if (np->e_flags != 0)
-                                       badentry(np, "unreferenced with flags");
-                               Dprintf(stdout,
-                                   "%s: remove unreferenced name\n",
-                                   myname(np));
-                               removeleaf(np);
-                               freeentry(np);
+               if (ep->e_entries == NULL)
+                       continue;
+               for (j = 0; j < DIRHASH_SIZE; j++) {
+                       for (np = ep->e_entries[j]; np != NULL; np = np->e_sibling) {
+                               if (np->e_type == LEAF) {
+                                       if (np->e_flags != 0)
+                                               badentry(np, "unreferenced with flags");
+                                       Dprintf(stdout,
+                                           "%s: remove unreferenced name\n",
+                                           myname(np));
+                                       removeleaf(np);
+                                       freeentry(np);
+                               }
                        }
                }
        }
@@ -626,10 +635,19 @@ removeoldnodes(void)
                change = 0;
                prev = &removelist;
                for (ep = removelist; ep != NULL; ep = *prev) {
+                       int docont = 0;
                        if (ep->e_entries != NULL) {
-                               prev = &ep->e_next;
-                               continue;
+                               int i;
+                               for (i = 0; i < DIRHASH_SIZE; i++) {
+                                       if (ep->e_entries[i] != NULL) {
+                                               prev = &ep->e_next;
+                                               docont = 1;
+                                               break;
+                                       }
+                               }
                        }
+                       if (docont)
+                               continue;
                        *prev = ep->e_next;
                        removenode(ep);
                        freeentry(ep);
@@ -651,7 +669,10 @@ compare_entry(struct entry *ep, int do_compare)
                badentry(ep, "unexpected file on tape");
                do_compare_error;
        }
-       if (do_compare) (void) comparefile(myname(ep));
+       if (do_compare) {
+               (void) comparefile(myname(ep));
+               skipxattr();
+       }
        ep->e_flags &= ~(NEW|EXTRACT);
 }
 
@@ -807,39 +828,9 @@ createleaves(char *symtabfile)
                else
                        doremove = 0;
                (void) extractfile(ep, doremove);
+               skipxattr();
                ep->e_flags &= ~(NEW|EXTRACT);
 
-finderres:
-               if ((first == curfile.ino) && (spcl.c_flags & DR_EXTATTRIBUTES)) {
-                       switch (spcl.c_extattributes) {
-                       case EXT_MACOSFNDRINFO:
-#ifdef DUMP_MACOSX
-                               (void)extractfinderinfoufs(myname(ep));
-#else
-                               msg("MacOSX not supported in this version, skipping\n");
-                               skipfile();
-#endif
-                               break;
-                       case EXT_MACOSRESFORK:
-#ifdef DUMP_MACOSX
-                               (void)extractresourceufs(myname(ep));
-#else
-                               msg("MacOSX not supported in this version, skipping\n");
-                               skipfile();
-#endif
-                               break;
-                       case EXT_ACL:
-                               msg("ACLs not supported in this version, skipping\n");
-                               skipfile();
-                               break;
-                       default:
-                               msg("unexpected inode extension %ld, skipping\n", spcl.c_extattributes);
-                               skipfile();
-                               break;
-                       }
-                       goto finderres;
-               }
-
                /*
                 * We checkpoint the restore after every tape reel, so
                 * as to simplify the amount of work required by the
@@ -1070,37 +1061,7 @@ createfiles(void)
                        } else {
 #endif /* USE_QFA */
                                (void) extractfile(ep, 0);
-
-finderres:
-                               if ((next == curfile.ino) && (spcl.c_flags & DR_EXTATTRIBUTES)) {
-                                       switch (spcl.c_extattributes) {
-                                       case EXT_MACOSFNDRINFO:
-#ifdef DUMP_MACOSX
-                                               (void)extractfinderinfoufs(myname(ep));
-#else
-                                               msg("MacOSX not supported in this version, skipping\n");
-                                               skipfile();
-#endif
-                                               break;
-                                       case EXT_MACOSRESFORK:
-#ifdef DUMP_MACOSX
-                                               (void)extractresourceufs(myname(ep));
-#else
-                                               msg("MacOSX not supported in this version, skipping\n");
-                                               skipfile();
-#endif
-                                               break;
-                                       case EXT_ACL:
-                                               msg("ACLs not supported in this version, skipping\n");
-                                               skipfile();
-                                               break;
-                                       default:
-                                               msg("unexpected inode extension %ld, skipping\n", spcl.c_extattributes);
-                                               skipfile();
-                                               break;
-                                       }
-                                       goto finderres;
-                               }
+                               skipxattr();
 
 #ifdef USE_QFA
                        }
index bf6284b126c986950fc50c75284b94fafad0ec6e..4f5236f4ac7466c17bbe8bf3c01a4c959db5e6df 100644 (file)
@@ -5,7 +5,7 @@
  *     Stelian Pop <stelian@popies.net>, 1999-2000
  *     Stelian Pop <stelian@popies.net> - Alcôve <www.alcove.com>, 2000-2002
  *
- *     $Id: restore.h,v 1.29 2004/04/13 13:04:33 stelian Exp $
+ *     $Id: restore.h,v 1.32 2005/05/02 15:10:46 stelian Exp $
  */
 
 /*
@@ -91,6 +91,9 @@ extern int    compare_ignore_not_found;
 extern int     compare_errors; /* did we encounter any compare errors? */
 extern char    filesys[NAMELEN];/* name of dumped filesystem */
 extern dump_ino_t volinfo[];   /* which inode on which volume archive info */
+extern int     wdfd;           /* original working directory */
+
+#define DIRHASH_SIZE 1024
 
 /*
  * Each file in the file system is described by one of these entries
@@ -105,7 +108,7 @@ struct entry {
        struct  entry *e_parent;        /* pointer to parent directory (..) */
        struct  entry *e_sibling;       /* next element in this directory (.) */
        struct  entry *e_links;         /* hard links to this inode */
-       struct  entry *e_entries;       /* for directories, their entries */
+       struct  entry **e_entries;      /* for directories, their entries */
        struct  entry *e_next;          /* hash chain list */
 };
 /* types */
@@ -194,3 +197,4 @@ char        smtcpath[2048];
                exit(2); \
        }
 
+#define XATTR_MAXSIZE  4096
index 3e6d3fc2b6674a31a076dcb2eb3204790e1159d3..b69259a7fe9185986fddbe54477cac1c6ace6dfc 100644 (file)
@@ -37,7 +37,7 @@
 
 #ifndef lint
 static const char rcsid[] =
-       "$Id: symtab.c,v 1.22 2003/10/26 16:05:48 stelian Exp $";
+       "$Id: symtab.c,v 1.25 2005/03/30 13:34:00 stelian Exp $";
 #endif /* not lint */
 
 /*
@@ -100,6 +100,25 @@ static long entrytblsize;
 static void             addino __P((dump_ino_t, struct entry *));
 static struct entry    *lookupparent __P((char *));
 static void             removeentry __P((struct entry *));
+static int              dir_hash __P((char *));
+
+/*
+ * Returns a hash given a file name
+ */
+static int
+dir_hash(char *name)
+{
+       unsigned long hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9;
+       int len = strlen(name);
+       
+       while (len--) {
+               unsigned long hash = hash1 + (hash0 ^ (*name++ * 7152373));
+               if (hash & 0x80000000) hash -= 0x7fffffff;
+               hash1 = hash0;
+               hash0 = hash; 
+       }       
+       return hash0 % DIRHASH_SIZE;
+}
 
 /*
  * Look up an entry by inode number
@@ -166,21 +185,51 @@ deleteino(dump_ino_t inum)
 struct entry *
 lookupname(char *name)
 {
-       struct entry *ep;
+       struct entry *ep, *oldep;
        char *np, *cp;
        char buf[MAXPATHLEN];
 
+       ep = lookupino(ROOTINO);
+
        cp = name;
-       for (ep = lookupino(ROOTINO); ep != NULL; ep = ep->e_entries) {
+       if (*cp == '.')
+               ++cp;
+       if (*cp == '/')
+               ++cp;
+       if (*cp == '\0')
+               return ep;
+
+       while (ep != NULL) {
                for (np = buf; *cp != '/' && *cp != '\0' &&
                                np < &buf[sizeof(buf)]; )
                        *np++ = *cp++;
                if (np == &buf[sizeof(buf)])
                        break;
                *np = '\0';
-               for ( ; ep != NULL; ep = ep->e_sibling)
-                       if (strcmp(ep->e_name, buf) == 0)
-                               break;
+
+               oldep = ep;
+
+               if (ep->e_entries != NULL) {
+
+                       ep = ep->e_entries[dir_hash(buf)];
+                       for ( ; ep != NULL; ep = ep->e_sibling)
+                               if (strcmp(ep->e_name, buf) == 0)
+                                       break;
+
+                       /* search all hash lists for renamed inodes */
+                       if (ep == NULL) {
+                               int j;
+                               for (j = 0; j < DIRHASH_SIZE; j++) {
+                                       ep = oldep->e_entries[j];
+                                       for ( ; ep != NULL; ep = ep->e_sibling)
+                                               if (strcmp(ep->e_name, buf) == 0)
+                                                       break;
+                                       if (ep != NULL)
+                                               break;
+                               }
+                       }
+               }
+
                if (ep == NULL)
                        break;
                if (*cp++ == '\0')
@@ -256,6 +305,11 @@ addentry(char *name, dump_ino_t inum, int type)
                        errx(1, "no memory to extend symbol table");
        }
        np->e_type = type & ~LINK;
+       if (type & NODE) {
+               np->e_entries = calloc(1, DIRHASH_SIZE * sizeof(struct entry *));
+               if (np->e_entries == NULL)
+                       panic("unable to allocate directory entries\n");
+       }
        ep = lookupparent(name);
        if (ep == NULL) {
                if (inum != ROOTINO || lookupino(ROOTINO) != NULL)
@@ -269,8 +323,8 @@ addentry(char *name, dump_ino_t inum, int type)
        np->e_name = savename(strrchr(name, '/') + 1);
        np->e_namlen = strlen(np->e_name);
        np->e_parent = ep;
-       np->e_sibling = ep->e_entries;
-       ep->e_entries = np;
+       np->e_sibling = ep->e_entries[dir_hash(np->e_name)];
+       ep->e_entries[dir_hash(np->e_name)] = np;
        if (type & LINK) {
                ep = lookupino(inum);
                if (ep == NULL)
@@ -300,8 +354,13 @@ freeentry(struct entry *ep)
        if (ep->e_type == NODE) {
                if (ep->e_links != NULL)
                        badentry(ep, "freeing referenced directory");
-               if (ep->e_entries != NULL)
-                       badentry(ep, "freeing non-empty directory");
+               if (ep->e_entries != NULL) {
+                       int i;
+                       for (i = 0; i < DIRHASH_SIZE; i++) {
+                               if (ep->e_entries[i] != NULL) 
+                                       badentry(ep, "freeing non-empty directory");
+                       }
+               }
        }
        if (ep->e_ino != 0) {
                np = lookupino(ep->e_ino);
@@ -344,8 +403,8 @@ moveentry(struct entry *ep, char *newname)
        if (np != ep->e_parent) {
                removeentry(ep);
                ep->e_parent = np;
-               ep->e_sibling = np->e_entries;
-               np->e_entries = ep;
+               ep->e_sibling = np->e_entries[dir_hash(ep->e_name)];
+               np->e_entries[dir_hash(ep->e_name)] = ep;
        }
        cp = strrchr(newname, '/') + 1;
        freename(ep->e_name);
@@ -363,20 +422,40 @@ moveentry(struct entry *ep, char *newname)
 static void
 removeentry(struct entry *ep)
 {
-       struct entry *np;
+       struct entry *np = ep->e_parent;
+       struct entry *entry = np->e_entries[dir_hash(ep->e_name)];
 
-       np = ep->e_parent;
-       if (np->e_entries == ep) {
-               np->e_entries = ep->e_sibling;
+       if (entry == ep) {
+               np->e_entries[dir_hash(ep->e_name)] = ep->e_sibling;
        } else {
-               for (np = np->e_entries; np != NULL; np = np->e_sibling) {
+               for (np = entry; np != NULL; np = np->e_sibling) {
                        if (np->e_sibling == ep) {
                                np->e_sibling = ep->e_sibling;
                                break;
                        }
                }
-               if (np == NULL)
+               if (np == NULL) {
+
+                       /* search all hash lists for renamed inodes */
+                       int j;
+                       for (j = 0; j < DIRHASH_SIZE; j++) {
+                               np = ep->e_parent;
+                               entry = np->e_entries[j];
+                               if (entry == ep) {
+                                       np->e_entries[j] = ep->e_sibling;
+                                       return;
+                               }
+                               else {
+                                       for (np = entry; np != NULL; np = np->e_sibling) {
+                                               if (np->e_sibling == ep) {
+                                                       np->e_sibling = ep->e_sibling;
+                                                       return;
+                                               }
+                                       }
+                               }
+                       }
                        badentry(ep, "cannot find entry in parent list");
+               }
        }
 }
 
@@ -449,6 +528,7 @@ freename(char *name)
 struct symtableheader {
        int32_t volno;
        int32_t stringsize;
+       int32_t hashsize;
        int32_t entrytblsize;
        time_t  dumptime;
        time_t  dumpdate;
@@ -466,9 +546,10 @@ dumpsymtable(char *filename, long checkpt)
        struct entry *ep, *tep;
        dump_ino_t i;
        struct entry temp, *tentry;
-       long mynum = 1, stroff = 0;
+       long mynum = 1, stroff = 0, hashoff = 0;
        FILE *fd;
        struct symtableheader hdr;
+       struct entry *temphash[DIRHASH_SIZE];
 
        Vprintf(stdout, "Check pointing the restore\n");
        if (Nflag)
@@ -490,11 +571,28 @@ dumpsymtable(char *filename, long checkpt)
                               (int)allocsize(ep->e_namlen), fd);
                }
        }
+       /*
+        * Write out e_entries tables
+        */
+       for (i = WINO; i <= maxino; i++) {
+               for (ep = lookupino(i); ep != NULL; ep = ep->e_links) {
+                       if (ep->e_entries != NULL) {
+                               int j;
+                               memcpy(temphash, ep->e_entries, DIRHASH_SIZE * sizeof(struct entry *));
+                               for (j = 0; j < DIRHASH_SIZE; j++) {
+                                       if (temphash[j])
+                                               temphash[j] = (struct entry *)ep->e_entries[j]->e_index;
+                               }
+                               fwrite(temphash, DIRHASH_SIZE, sizeof(struct entry *), fd);
+                       }
+               }
+       }
        /*
         * Convert pointers to indexes, and output
         */
        tep = &temp;
        stroff = 0;
+       hashoff = 0;
        for (i = WINO; i <= maxino; i++) {
                for (ep = lookupino(i); ep != NULL; ep = ep->e_links) {
                        memmove(tep, ep, sizeof(struct entry));
@@ -507,9 +605,10 @@ dumpsymtable(char *filename, long checkpt)
                        if (ep->e_sibling != NULL)
                                tep->e_sibling =
                                        (struct entry *)ep->e_sibling->e_index;
-                       if (ep->e_entries != NULL)
-                               tep->e_entries =
-                                       (struct entry *)ep->e_entries->e_index;
+                       if (ep->e_entries != NULL) {
+                               tep->e_entries = (struct entry **)hashoff;
+                               hashoff += DIRHASH_SIZE * sizeof(struct entry *);
+                       }
                        if (ep->e_next != NULL)
                                tep->e_next =
                                        (struct entry *)ep->e_next->e_index;
@@ -530,6 +629,7 @@ dumpsymtable(char *filename, long checkpt)
        hdr.maxino = maxino;
        hdr.entrytblsize = entrytblsize;
        hdr.stringsize = stroff;
+       hdr.hashsize = hashoff;
        hdr.dumptime = dumptime;
        hdr.dumpdate = dumpdate;
        hdr.ntrec = ntrec;
@@ -612,12 +712,14 @@ initsymtable(char *filename)
                panic("initsymtable called from command %c\n", command);
                break;
        }
-       resizemaps(maxino, hdr.maxino);
-       maxino = hdr.maxino;
+       if (hdr.maxino > maxino) {
+               resizemaps(maxino, hdr.maxino);
+               maxino = hdr.maxino;
+       }
        entrytblsize = hdr.entrytblsize;
        entry = (struct entry **)
                (base + tblsize - (entrytblsize * sizeof(struct entry *)));
-       baseep = (struct entry *)(base + hdr.stringsize - sizeof(struct entry));
+       baseep = (struct entry *)(base + hdr.stringsize + hdr.hashsize - sizeof(struct entry));
        lep = (struct entry *)entry;
        for (i = 0; i < entrytblsize; i++) {
                if (entry[i] == NULL)
@@ -631,8 +733,16 @@ initsymtable(char *filename)
                        ep->e_sibling = &baseep[(long)ep->e_sibling];
                if (ep->e_links != NULL)
                        ep->e_links = &baseep[(long)ep->e_links];
-               if (ep->e_entries != NULL)
-                       ep->e_entries = &baseep[(long)ep->e_entries];
+               if (ep->e_type == NODE) {
+                       int i;
+                       ep->e_entries = (struct entry **)(base + hdr.stringsize + (long)ep->e_entries);
+                       for (i = 0; i < DIRHASH_SIZE; i++) {
+                               if (ep->e_entries[i])
+                                       ep->e_entries[i] = &baseep[(long)ep->e_entries[i]];
+                       }
+               }
+               else
+                       ep->e_entries = NULL;
                if (ep->e_next != NULL)
                        ep->e_next = &baseep[(long)ep->e_next];
        }
index 2f344dbc85e87785dc3629c44ce690ee105c13e1..e60921bf3b86b1afff5ce0a8666978da04fe89d7 100644 (file)
@@ -42,7 +42,7 @@
 
 #ifndef lint
 static const char rcsid[] =
-       "$Id: tape.c,v 1.81 2004/05/25 10:39:31 stelian Exp $";
+       "$Id: tape.c,v 1.89 2005/05/02 15:10:46 stelian Exp $";
 #endif /* not lint */
 
 #include <config.h>
@@ -167,7 +167,10 @@ static void         xtrlnkskip __P((char *, size_t));
 static void     xtrmap __P((char *, size_t));
 static void     xtrmapskip __P((char *, size_t));
 static void     xtrskip __P((char *, size_t));
+static void     xtrxattr __P((char *, size_t));
 static void     setmagtapein __P((void));
+static int      extractattr __P((char *));
+static void     compareattr __P((char *));
 
 #if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) || defined(HAVE_LZO)
 static void    newcomprbuf __P((int));
@@ -194,6 +197,9 @@ static void xtrcmpskip __P((char *, size_t));
 static int readmapflag;
 static int readingmaps;                /* set to 1 while reading the maps */
 
+static char xattrbuf[XATTR_MAXSIZE];
+static int xattrlen;
+
 #ifdef DUMP_MACOSX
 static DumpFinderInfo  gFndrInfo;
 #endif
@@ -840,14 +846,19 @@ extractfile(struct entry *ep, int doremove)
                return (GOOD);
 
        case IFDIR:
+       {
+               int ret;
                if (mflag) {
                        if (ep == NULL || ep->e_flags & EXTRACT)
                                panic("unextracted directory %s\n", name);
                        skipfile();
                        return (GOOD);
                }
-               Vprintf(stdout, "extract file %s\n", name);
-               return (genliteraldir(name, curfile.ino));
+               Vprintf(stdout, "extract dir %s\n", name);
+               ret = genliteraldir(name, curfile.ino);
+               extractattr(name);
+               return ret;
+       }
 
        case IFLNK:
        {
@@ -873,6 +884,7 @@ extractfile(struct entry *ep, int doremove)
 #ifdef HAVE_LCHOWN
                (void) lchown(name, luid, lgid);
 #endif
+               extractattr(name);
                return (GOOD);
        }
 
@@ -895,7 +907,7 @@ extractfile(struct entry *ep, int doremove)
                (void) chmod(name, mode);
                if (flags)
 #ifdef  __linux__
-                       (void) fsetflags(name, flags);
+                       (void) lsetflags(name, flags);
 #else
 #ifdef sunos
                        {
@@ -907,6 +919,7 @@ extractfile(struct entry *ep, int doremove)
 #endif
 #endif
                skipfile();
+               extractattr(name);
                utimes(name, timep);
                return (GOOD);
 
@@ -931,8 +944,8 @@ extractfile(struct entry *ep, int doremove)
                if (flags)
 #ifdef __linux__
                        {
-                       warn("%s: fsetflags called on a special file", name);
-                       (void) fsetflags(name, flags);
+                       warn("%s: lsetflags called on a special file", name);
+                       (void) lsetflags(name, flags);
                        }
 #else
 #ifdef sunos
@@ -948,6 +961,7 @@ extractfile(struct entry *ep, int doremove)
 #endif
 #endif
                skipfile();
+               extractattr(name);
                utimes(name, timep);
                return (GOOD);
 
@@ -979,7 +993,7 @@ extractfile(struct entry *ep, int doremove)
                (void) chmod(name, mode);
                if (flags)
 #ifdef __linux__
-                       (void) fsetflags(name, flags);
+                       (void) lsetflags(name, flags);
 #else
 #ifdef sunos
                        {
@@ -990,6 +1004,7 @@ extractfile(struct entry *ep, int doremove)
                        (void) chflags(name, flags);
 #endif
 #endif
+               extractattr(name);
                utimes(name, timep);
                return (GOOD);
        }
@@ -997,6 +1012,44 @@ extractfile(struct entry *ep, int doremove)
        /* NOTREACHED */
 }
 
+static int
+extractattr(char *path)
+{
+       while (spcl.c_flags & DR_EXTATTRIBUTES) {
+               switch (spcl.c_extattributes) {
+               case EXT_MACOSFNDRINFO:
+#ifdef DUMP_MACOSX
+                       (void)extractfinderinfoufs(path);
+#else
+                       msg("MacOSX not supported in this version, skipping\n");
+                       skipfile();
+#endif
+                       break;
+               case EXT_MACOSRESFORK:
+#ifdef DUMP_MACOSX
+                       (void)extractresourceufs(path);
+#else
+                       msg("MacOSX not supported in this version, skipping\n");
+                       skipfile();
+#endif
+                       break;
+               case EXT_XATTR: {
+                       char xattr[XATTR_MAXSIZE];
+                       
+                       if (readxattr(xattr) == GOOD) {
+                               xattr_extract(path, xattr);
+                               break;
+                       }
+               }
+               default:
+                       msg("unexpected inode extension %ld, skipping\n", spcl.c_extattributes);
+                       skipfile();
+                       break;
+               }
+       }
+       return GOOD;
+}
+
 #ifdef DUMP_MACOSX
 int
 extractfinderinfoufs(char *name)
@@ -1009,7 +1062,6 @@ extractfinderinfoufs(char *name)
        u_int32_t       uid;
        u_int32_t       gid;
        char    path[MAXPATHLEN], fname[MAXPATHLEN];
-       int toto;
 
        curfile.name = name;
        curfile.action = USING;
@@ -1161,7 +1213,7 @@ extractresourceufs(char *name)
                (void) fchown(ofile, uid, gid);
                (void) fchmod(ofile, mode);
                (void) close(ofile);
-               (void) fsetflags(oFileRsrc, flags);
+               (void) lsetflags(oFileRsrc, flags);
                utimes(oFileRsrc, timep);
                return (GOOD);
        }
@@ -1169,6 +1221,29 @@ extractresourceufs(char *name)
 }
 #endif /* DUMP_MACOSX */
 
+int
+readxattr(char *buffer)
+{
+       if (dflag)
+               msg("reading EA data for inode %lu\n", curfile.ino);
+
+       curfile.name = "EA block";
+       if (curfile.dip->di_size > XATTR_MAXSIZE) {
+               fprintf(stderr, "EA size too big (%ld)", (long)curfile.dip->di_size);
+               skipfile();
+               return (FAIL);
+       }
+       
+       memset(xattrbuf, 0, XATTR_MAXSIZE);
+       xattrlen = 0;
+
+       getfile(xtrxattr, xtrnull);
+
+       memcpy(buffer, xattrbuf, XATTR_MAXSIZE);
+
+       return (GOOD);
+}
+
 /*
  * skip over bit maps on the tape
  */
@@ -1191,6 +1266,17 @@ skipfile(void)
        getfile(xtrnull, xtrnull);
 }
 
+/*
+ * skip over any extended attributes.
+ */
+void
+skipxattr(void)
+{
+
+       while (spcl.c_flags & DR_EXTATTRIBUTES)
+               skipfile();
+}
+
 /*
  * Extract a file from the tape.
  * When an allocated block is found it is passed to the fill function;
@@ -1290,8 +1376,6 @@ xtrfile(char *buf, size_t size)
 static void
 xtrfilefinderinfo(char *buf, size_t size)
 {
-       if (Nflag)
-               return;
        bcopy(buf, &gFndrInfo, size);
 }
 #endif /* DUMP_MACOSX */
@@ -1317,10 +1401,13 @@ xtrlnkfile(char *buf, size_t size)
 {
 
        pathlen += size;
-       if (pathlen > MAXPATHLEN)
+       if (pathlen > MAXPATHLEN) {
+               buf[size - 1] = '\0';
                errx(1, "symbolic link name: %s->%s%s; too long %d",
                    curfile.name, lnkbuf, buf, pathlen);
+       }
        (void) strcat(lnkbuf, buf);
+       lnkbuf[pathlen] = '\0';
 }
 
 /*
@@ -1424,9 +1511,20 @@ xtrcmpskip(UNUSED(char *buf), size_t size)
 }
 #endif /* COMPARE_ONTHEFLY */
 
+static void
+xtrxattr(char *buf, size_t size)
+{
+       if (xattrlen + size > XATTR_MAXSIZE) {
+               fprintf(stderr, "EA size too big (%ld)", (long)xattrlen + size);
+               return;
+       }
+       memcpy(xattrbuf + xattrlen, buf, size);
+       xattrlen += size;
+}
+
 #if !COMPARE_ONTHEFLY
 static int
-do_cmpfiles(int fd_tape, int fd_disk, long size)
+do_cmpfiles(int fd_tape, int fd_disk, OFF_T size)
 {
        static char buf_tape[BUFSIZ];
        static char buf_disk[BUFSIZ];
@@ -1468,15 +1566,15 @@ cmpfiles(char *tapefile, char *diskfile, struct STAT *sbuf_disk)
        int fd_tape, fd_disk;
 
        if (STAT(tapefile, &sbuf_tape) != 0) {
-               panic("Can't lstat tmp file %s: %s\n", tapefile,
+               panic("can't lstat tmp file %s: %s\n", tapefile,
                      strerror(errno));
                do_compare_error;
        }
 
        if (sbuf_disk->st_size != sbuf_tape.st_size) {
                fprintf(stderr,
-                       "%s: size changed from %ld to %ld.\n",
-                       diskfile, (long)sbuf_tape.st_size, (long)sbuf_disk->st_size);
+                       "%s: size changed from %lld to %lld.\n",
+                       diskfile, (long long)sbuf_tape.st_size, (long long)sbuf_disk->st_size);
                do_compare_error;
 #ifdef COMPARE_FAIL_KEEP_FILE
                return (0);
@@ -1486,12 +1584,12 @@ cmpfiles(char *tapefile, char *diskfile, struct STAT *sbuf_disk)
        }
 
        if ((fd_tape = OPEN(tapefile, O_RDONLY)) < 0) {
-               panic("Can't open %s: %s\n", tapefile, strerror(errno));
+               panic("can't open %s: %s\n", tapefile, strerror(errno));
                do_compare_error;
        }
        if ((fd_disk = OPEN(diskfile, O_RDONLY)) < 0) {
                close(fd_tape);
-               panic("Can't open %s: %s\n", diskfile, strerror(errno));
+               panic("can't open %s: %s\n", diskfile, strerror(errno));
                do_compare_error;
        }
 
@@ -1536,6 +1634,43 @@ cmpfiles(char *tapefile, char *diskfile, struct STAT *sbuf_disk)
 }
 #endif /* !COMPARE_ONTHEFLY */
 
+static void
+compareattr(char *name)
+{
+       int xattr_done = 0;
+       
+       while (spcl.c_flags & DR_EXTATTRIBUTES) {
+               switch (spcl.c_extattributes) {
+               case EXT_MACOSFNDRINFO:
+                       msg("MacOSX not supported for comparision in this version, skipping\n");
+                       skipfile();
+                       break;
+               case EXT_MACOSRESFORK:
+                       msg("MacOSX not supported for comparision in this version, skipping\n");
+                       skipfile();
+                       break;
+               case EXT_XATTR: {
+                       char xattr[XATTR_MAXSIZE];
+
+                       if (readxattr(xattr) == GOOD) {
+                               if (xattr_compare(name, xattr) == FAIL)
+                                       do_compare_error;
+                               xattr_done = 1;
+                       }
+                       else
+                               do_compare_error;
+                       break;
+               }
+               default:
+                       msg("unexpected inode extension %ld, skipping\n", spcl.c_extattributes);
+                       skipfile();
+                       break;
+               }
+       }
+       if (!xattr_done && xattr_compare(name, NULL) == FAIL)
+               do_compare_error;
+}
+
 #if !COMPARE_ONTHEFLY
 static char tmpfilename[MAXPATHLEN];
 #endif
@@ -1543,17 +1678,23 @@ static char tmpfilename[MAXPATHLEN];
 void
 comparefile(char *name)
 {
-       unsigned int mode;
+       mode_t mode;
+       uid_t uid;
+       uid_t gid;
+       unsigned int flags;
+       unsigned long newflags;
        struct STAT sb;
        int r;
 #if !COMPARE_ONTHEFLY
        static char *tmpfile = NULL;
        struct STAT stemp;
 #endif
-
        curfile.name = name;
        curfile.action = USING;
        mode = curfile.dip->di_mode;
+       flags = curfile.dip->di_flags;
+       uid = curfile.dip->di_uid;
+       gid =  curfile.dip->di_gid;
 
        if ((mode & IFMT) == IFSOCK) {
                Vprintf(stdout, "skipped socket %s\n", name);
@@ -1562,20 +1703,45 @@ comparefile(char *name)
        }
 
        if ((r = LSTAT(name, &sb)) != 0) {
-               warn("%s: does not exist (%d)", name, r);
+               warn("unable to stat %s", name);
                do_compare_error;
                skipfile();
                return;
        }
 
-       Vprintf(stdout, "comparing %s (size: %ld, mode: 0%o)\n", name,
-               (long)sb.st_size, mode);
+       Vprintf(stdout, "comparing %s (size: %lld, mode: 0%o)\n", name,
+               (long long)sb.st_size, mode);
 
        if (sb.st_mode != mode) {
                fprintf(stderr, "%s: mode changed from 0%o to 0%o.\n",
                        name, mode & 07777, sb.st_mode & 07777);
                do_compare_error;
        }
+       if (sb.st_uid != uid) {
+               fprintf(stderr, "%s: uid changed from %d to %d.\n",
+                       name, uid, sb.st_uid);
+               do_compare_error;
+       }
+       if (sb.st_gid != gid) {
+               fprintf(stderr, "%s: gid changed from %d to %d.\n",
+                       name, gid, sb.st_gid);
+               do_compare_error;
+       }
+#ifdef  __linux__
+       if (lgetflags(name, &newflags) < 0) {
+               if (flags != 0) {
+                       warn("%s: lgetflags failed", name);
+                       do_compare_error;
+               }
+       }
+       else {
+               if (newflags != flags) {
+                       fprintf(stderr, "%s: flags changed from 0x%08x to 0x%08lx.\n",
+                               name, flags, newflags);
+                       do_compare_error;
+               }
+       }
+#endif
        if (spcl.c_flags & DR_METAONLY) {
                skipfile();
                return;
@@ -1591,6 +1757,7 @@ comparefile(char *name)
 
        case IFDIR:
                skipfile();
+               compareattr(name);
                return;
 
        case IFLNK: {
@@ -1614,7 +1781,7 @@ comparefile(char *name)
                        return;
                }
                if ((lsize = readlink(name, lbuf, MAXPATHLEN)) < 0) {
-                       panic("readlink of %s failed: %s", name,
+                       panic("readlink of %s failed: %s\n", name,
                              strerror(errno));
                        do_compare_error;
                }
@@ -1626,6 +1793,7 @@ comparefile(char *name)
                        do_compare_error;
                        return;
                }
+               compareattr(name);
                return;
        }
 
@@ -1650,12 +1818,13 @@ comparefile(char *name)
                        do_compare_error;
                }
                skipfile();
+               compareattr(name);
                return;
 
        case IFREG:
 #if COMPARE_ONTHEFLY
                if ((ifile = OPEN(name, O_RDONLY)) < 0) {
-                       panic("Can't open %s: %s\n", name, strerror(errno));
+                       warn("can't open %s", name);
                        skipfile();
                        do_compare_error;
                }
@@ -1698,6 +1867,7 @@ comparefile(char *name)
                unlink(tmpfile);
 #endif
 #endif /* COMPARE_ONTHEFLY */
+               compareattr(name);
                return;
        }
        /* NOTREACHED */
index e0db9afa83b5c68e9ed70d73e81450901f4a2123..f17bd9ce458a7214ab50050f787c794d79a033a1 100644 (file)
@@ -37,7 +37,7 @@
 
 #ifndef lint
 static const char rcsid[] =
-       "$Id: utilities.c,v 1.24 2003/11/22 16:52:16 stelian Exp $";
+       "$Id: utilities.c,v 1.28 2005/03/30 13:21:45 stelian Exp $";
 #endif /* not lint */
 
 #include <config.h>
@@ -187,8 +187,13 @@ removenode(struct entry *ep)
 
        if (ep->e_type != NODE)
                badentry(ep, "removenode: not a node");
-       if (ep->e_entries != NULL)
-               badentry(ep, "removenode: non-empty directory");
+       if (ep->e_entries != NULL) {
+               int i;
+               for (i = 0; i < DIRHASH_SIZE; i++) {
+                       if (ep->e_entries[i] != NULL)
+                               badentry(ep, "removenode: non-empty directory");
+               }
+       }
        ep->e_flags |= REMOVED;
        ep->e_flags &= ~TMPNAME;
        cp = myname(ep);
@@ -264,10 +269,10 @@ linkit(char *existing, char *new, int type)
                         */
 #ifdef sunos
 #else
-                       if (fgetflags (existing, &s) != -1 &&
-                           fsetflags (existing, 0) != -1) {
+                       if (lgetflags (existing, &s) != -1 &&
+                           lsetflags (existing, 0) != -1) {
                                ret = link(existing, new);
-                               fsetflags(existing, s);
+                               lsetflags(existing, s);
                        }
 #endif
 #endif
@@ -371,8 +376,15 @@ badentry(struct entry *ep, const char *msg)
        fprintf(stderr, "parent name %s\n", myname(ep->e_parent));
        if (ep->e_sibling != NULL)
                fprintf(stderr, "sibling name: %s\n", myname(ep->e_sibling));
-       if (ep->e_entries != NULL)
-               fprintf(stderr, "next entry name: %s\n", myname(ep->e_entries));
+       if (ep->e_entries != NULL) {
+               int i;
+               for (i = 0; i < DIRHASH_SIZE; i++) {
+                       if (ep->e_entries[i] != NULL) {
+                               fprintf(stderr, "next entry name: %s\n", myname(ep->e_entries[i]));
+                               break;
+                       }
+               }
+       }
        if (ep->e_links != NULL)
                fprintf(stderr, "next link name: %s\n", myname(ep->e_links));
        if (ep->e_next != NULL)
@@ -475,8 +487,10 @@ panic(fmt, va_alist)
        if (yflag)
                return;
        if (reply("abort") == GOOD) {
-               if (reply("dump core") == GOOD)
+               if (reply("dump core") == GOOD) {
+                       fchdir(wdfd);
                        abort();
+               }
                exit(1);
        }
 }
@@ -712,9 +726,46 @@ CreateAppleDoubleFileRes(char *oFile, FndrFileInfo *finderinfo, mode_t mode, int
        (void)fchown(fdout, uid, gid);
        (void)fchmod(fdout, mode);
        close(fdout);
-       (void)fsetflags(oFile, flags);
+       (void)lsetflags(oFile, flags);
        utimes(oFile, timep);
        free(pp);
        return err;
 }
 #endif /* DUMP_MACOSX */
+
+int
+lgetflags(const char *path, unsigned long *flags)
+{
+       int err;
+       struct STAT sb;
+
+       err = LSTAT(path, &sb);
+       if (err < 0)
+               return err;
+
+       if (S_ISLNK(sb.st_mode) || S_ISFIFO(sb.st_mode)) {
+               // no way to get/set flags on a symlink
+               *flags = 0;
+               return 0;
+       }
+       else
+               return fgetflags(path, flags);
+}
+
+int
+lsetflags(const char *path, unsigned long flags)
+{
+       int err;
+       struct STAT sb;
+
+       err = LSTAT(path, &sb);
+       if (err < 0)
+               return err;
+
+       if (S_ISLNK(sb.st_mode) || S_ISFIFO(sb.st_mode)) {
+               // no way to get/set flags on a symlink
+               return 0;
+       }
+       else
+               return fsetflags(path, flags);
+}
diff --git a/restore/xattr.c b/restore/xattr.c
new file mode 100644 (file)
index 0000000..6da39eb
--- /dev/null
@@ -0,0 +1,444 @@
+/*
+ * Copyright (c) 1999-2004
+ *     Stelian Pop <stelian@popies.net>, 1999-2004
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+       "$Id: xattr.c,v 1.1 2005/05/02 15:10:47 stelian Exp $";
+#endif /* not lint */
+
+#include <config.h>
+#include <compatlfs.h>
+#include <compaterr.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <bsdcompat.h>
+#include <protocols/dumprestore.h>
+#include "restore.h"
+#include "extern.h"
+#include "pathnames.h"
+
+/*
+ * Data structures below taken from the kernel
+ */
+
+/* Maximum number of references to one attribute block */
+#define EXT2_XATTR_REFCOUNT_MAX                1024
+
+/* Name indexes */
+#define EXT2_XATTR_INDEX_MAX                   10
+#define EXT2_XATTR_INDEX_USER                  1
+#define EXT2_XATTR_INDEX_POSIX_ACL_ACCESS      2
+#define EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT     3
+#define EXT2_XATTR_INDEX_TRUSTED               4
+#define        EXT2_XATTR_INDEX_LUSTRE                 5
+#define EXT2_XATTR_INDEX_SECURITY              6
+
+struct ext2_xattr_header {
+       u_int32_t       h_magic;        /* magic number for identification */
+       u_int32_t       h_refcount;     /* reference count */
+       u_int32_t       h_blocks;       /* number of disk blocks used */
+       u_int32_t       h_hash;         /* hash value of all attributes */
+       u_int32_t       h_reserved[4];  /* zero right now */
+};
+
+struct ext3_xattr_ibody_header {
+       u_int32_t       h_magic;        /* magic number for identification */
+};
+
+struct ext2_xattr_entry {
+       u_char          e_name_len;     /* length of name */
+       u_char          e_name_index;   /* attribute name index */
+       u_int16_t       e_value_offs;   /* offset in disk block of value */
+       u_int32_t       e_value_block;  /* disk block attribute is stored on (n/i) */
+       u_int32_t       e_value_size;   /* size of attribute value */
+       u_int32_t       e_hash;         /* hash value of name and value */
+       char            e_name[0];      /* attribute name */
+};
+
+#define EXT2_XATTR_PAD_BITS            2
+#define EXT2_XATTR_PAD         (1<<EXT2_XATTR_PAD_BITS)
+#define EXT2_XATTR_ROUND               (EXT2_XATTR_PAD-1)
+#define EXT2_XATTR_LEN(name_len) \
+       (((name_len) + EXT2_XATTR_ROUND + \
+       sizeof(struct ext2_xattr_entry)) & ~EXT2_XATTR_ROUND)
+#define EXT2_XATTR_NEXT(entry) \
+       ( (struct ext2_xattr_entry *)( \
+         (char *)(entry) + EXT2_XATTR_LEN((entry)->e_name_len)) )
+#define EXT3_XATTR_SIZE(size) \
+       (((size) + EXT2_XATTR_ROUND) & ~EXT2_XATTR_ROUND)
+
+#define HDR(buffer) ((struct ext2_xattr_header *)(buffer))
+#define ENTRY(ptr) ((struct ext2_xattr_entry *)(ptr))
+#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
+
+#define BFIRST(buffer) ENTRY(HDR(buffer)+1)
+#define IFIRST(buffer) ENTRY(((struct ext3_xattr_ibody_header *)(buffer))+1)
+
+#define FIRST_ENTRY(buffer) \
+       ((HDR(buffer)->h_magic == EXT2_XATTR_MAGIC2) ? \
+               IFIRST(buffer) : \
+               BFIRST(buffer))
+
+/*
+ * On-block xattr value offsets start at the beginning of the block, but
+ * on-inode xattr value offsets start after the initial header 
+ * (ext3_xattr_ibody_header).
+ */
+#define VALUE_OFFSET(buffer, entry) \
+       (((HDR(buffer)->h_magic == EXT2_XATTR_MAGIC2) ? \
+               (entry)->e_value_offs + sizeof(struct ext3_xattr_ibody_header) : \
+               (entry)->e_value_offs))
+       
+/*
+ * xattr syscalls do not exist yet in libc, get our own copy here,
+ * taken from libattr.
+ */
+#if defined (__i386__)
+# define HAVE_XATTR_SYSCALLS 1
+# define __NR_lsetxattr                227
+# define __NR_lgetxattr                230
+# define __NR_llistxattr       233
+#elif defined (__sparc__)
+# define HAVE_XATTR_SYSCALLS 1
+# define __NR_lsetxattr                170
+# define __NR_lgetxattr                173
+# define __NR_llistxattr       179
+#elif defined (__ia64__)
+# define HAVE_XATTR_SYSCALLS 1
+# define __NR_lsetxattr                1218
+# define __NR_lgetxattr                1221
+# define __NR_llistxattr       1224
+#elif defined (__powerpc__)
+# define HAVE_XATTR_SYSCALLS 1
+# define __NR_lsetxattr                210
+# define __NR_lgetxattr                213
+# define __NR_llistxattr       216
+#elif defined (__x86_64__)
+# define HAVE_XATTR_SYSCALLS 1
+# define __NR_lsetxattr                189
+# define __NR_lgetxattr                192
+# define __NR_llistxattr       195
+#elif defined (__s390__)
+# define HAVE_XATTR_SYSCALLS 1
+# define __NR_lsetxattr                225
+# define __NR_lgetxattr                228
+# define __NR_llistxattr       231
+#elif defined (__arm__)
+# define HAVE_XATTR_SYSCALLS 1
+# define __NR_SYSCALL_BASE 0x900000
+# define __NR_lsetxattr                (__NR_SYSCALL_BASE+227)
+# define __NR_lgetxattr                (__NR_SYSCALL_BASE+230)
+# define __NR_llistxattr       (__NR_SYSCALL_BASE+233)
+#elif defined (__mips64__)
+# define HAVE_XATTR_SYSCALLS 1
+# define __NR_Linux 5000
+# define __NR_lsetxattr                (__NR_Linux + 218)
+# define __NR_lgetxattr                (__NR_Linux + 221)
+# define __NR_llistxattr       (__NR_Linux + 224)
+#elif defined (__mips__)
+# define HAVE_XATTR_SYSCALLS 1
+# define __NR_Linux 4000
+# define __NR_lsetxattr                (__NR_Linux + 225)
+# define __NR_lgetxattr                (__NR_Linux + 228)
+# define __NR_llistxattr       (__NR_Linux + 231)
+#elif defined (__alpha__)
+# define HAVE_XATTR_SYSCALLS 1
+# define __NR_lsetxattr                383
+# define __NR_lgetxattr                386
+# define __NR_llistxattr       389
+#elif defined (__mc68000__)
+# define HAVE_XATTR_SYSCALLS 1
+# define __NR_lsetxattr                224
+# define __NR_lgetxattr                227
+# define __NR_llistxattr       230
+#else
+# warning "Extended attribute syscalls undefined for this architecture"
+# define HAVE_XATTR_SYSCALLS 0
+#endif
+
+#if HAVE_XATTR_SYSCALLS
+# define SYSCALL(args...)      syscall(args)
+#else
+# define SYSCALL(args...)      ( errno = ENOSYS, -1 )
+#endif
+
+static int lsetxattr __P((const char *, const char *, void *, size_t, int));
+static ssize_t lgetxattr __P((const char *, const char *, void *, size_t));
+static ssize_t llistxattr __P((const char *, char *, size_t));
+static int xattr_cb_list __P((char *, char *, int, void *));
+static int xattr_cb_set __P((char *, char *, int, void *));
+static int xattr_cb_compare __P((char *, char *, int, void *));
+static int xattr_verify __P((char *));
+static int xattr_count __P((char *, int *));
+static int xattr_walk __P((char *, int (*)(char *, char *, int, void *), void *));
+
+static int
+lsetxattr(const char *path, const char *name, void *value, size_t size, int flags)
+{
+       return SYSCALL(__NR_lsetxattr, path, name, value, size, flags);
+}
+
+static ssize_t
+lgetxattr(const char *path, const char *name, void *value, size_t size)
+{
+       return SYSCALL(__NR_lgetxattr, path, name, value, size);
+}
+
+static ssize_t
+llistxattr(const char *path, char *list, size_t size)
+{
+       return SYSCALL(__NR_llistxattr, path, list, size);
+}
+
+/*
+ * Dump code starts here :)
+ */
+
+static int
+xattr_cb_list(char *name, char *value, int valuelen, void *private)
+{
+       value[valuelen] = '\0';
+       printf("EA: %s:%s\n", name, value);
+
+       return GOOD;
+}
+
+static int
+xattr_cb_set(char *name, char *value, int valuelen, void *private)
+{
+       char *path = (char *)private;
+
+       if (lsetxattr(path, name, value, valuelen, 0) < 0) {
+               warn("lsetxattr %s failed", path);
+               return FAIL;
+       }
+       return GOOD;
+}
+
+static int
+xattr_cb_compare(char *name, char *value, int valuelen, void *private)
+{
+       char *path = (char *)private;
+       char valuef[XATTR_MAXSIZE];
+       int valuesz;
+
+       valuesz = lgetxattr(path, name, valuef, XATTR_MAXSIZE);
+       if (valuesz < 0) {
+               warn("%s: lgetxattr failed\n", path);
+               return FAIL;
+       }
+
+       if (valuesz != valuelen) {
+               fprintf(stderr, "%s: EA %s value changed\n", path, value);
+               return FAIL;
+       }
+
+       if (memcmp(value, valuef, valuelen)) {
+               fprintf(stderr, "%s: EA %s value changed\n", path, value);
+               return FAIL;
+       }
+
+       return GOOD;
+}
+
+static int
+xattr_verify(char *buffer)
+{
+       struct ext2_xattr_entry *entry;
+       char *end;
+
+       end = buffer + XATTR_MAXSIZE;
+
+       if (Bcvt)
+               swabst("4i", (u_char *)buffer);
+
+       if (HDR(buffer)->h_magic != EXT2_XATTR_MAGIC &&
+           HDR(buffer)->h_magic != EXT2_XATTR_MAGIC2) {
+               fprintf(stderr, "error in EA block 1\n");
+               fprintf(stderr, "magic = %x\n", HDR(buffer)->h_magic);
+               
+               return FAIL;
+       }
+
+       /* check the on-disk data structure */
+       entry = FIRST_ENTRY(buffer);
+       if (Bcvt) 
+               swabst("2b1s3i", (u_char *)entry);
+       while (!IS_LAST_ENTRY(entry)) {
+               struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(entry);
+
+               if ((char *)next >= end) {
+                       fprintf(stderr, "error in EA block\n");
+                       return FAIL;
+               }
+               entry = next;
+               if (Bcvt) 
+                       swabst("2b1s3i", (u_char *)entry);
+       }
+       return GOOD;
+}
+
+static int
+xattr_count(char *buffer, int *count)
+{
+       struct ext2_xattr_entry *entry;
+       int result = 0;
+
+       /* list the attribute names */
+       for (entry = FIRST_ENTRY(buffer); !IS_LAST_ENTRY(entry);
+            entry = EXT2_XATTR_NEXT(entry))
+               result++;
+
+       *count = result;
+       return GOOD;
+}
+
+static int
+xattr_walk(char *buffer, int (*xattr_cb)(char *, char *, int, void *), void *private)
+{
+       struct ext2_xattr_entry *entry;
+
+       /* list the attribute names */
+       for (entry = FIRST_ENTRY(buffer); !IS_LAST_ENTRY(entry);
+            entry = EXT2_XATTR_NEXT(entry)) {
+               char name[XATTR_MAXSIZE], value[XATTR_MAXSIZE];
+               int off;
+
+               switch (entry->e_name_index) {
+               case EXT2_XATTR_INDEX_USER:
+                       strcpy(name, "user.");
+                       break;
+               case EXT2_XATTR_INDEX_POSIX_ACL_ACCESS:
+               case EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT:
+                       strcpy(name, "system.");
+                       break;
+               case EXT2_XATTR_INDEX_TRUSTED:
+                       strcpy(name, "trusted.");
+                       break;
+               case EXT2_XATTR_INDEX_LUSTRE:
+                       strcpy(name, "lustre.");
+                       break;
+               case EXT2_XATTR_INDEX_SECURITY:
+                       strcpy(name, "security.");
+                       break;
+               default:
+                       fprintf(stderr, "Unknown EA index\n");
+                       return FAIL;
+               }
+
+               off = strlen(name);
+               memcpy(name + off, entry->e_name, entry->e_name_len);
+               name[off + entry->e_name_len] = '\0';
+
+
+               memcpy(value, buffer + VALUE_OFFSET(buffer, entry), entry->e_value_size);
+
+               if (xattr_cb(name, value, entry->e_value_size, private) != GOOD)
+                       return FAIL;
+       }
+
+       return GOOD;
+}
+
+int
+xattr_compare(char *path, char *buffer)
+{
+       int countf, countt;
+       char *names = NULL, *end_names, *name;
+
+       countf = llistxattr(path, NULL, 0);
+       if (countf < 0) {
+               warn("%s: llistxattr failed", path);
+               return FAIL;
+       }
+
+       names = malloc(countf + 1);
+       if (!names) {
+               warn("%s: llistxattr failed", path);
+               return FAIL;
+       }
+
+       countf = llistxattr(path, names, countf);
+       if (countf < 0) {
+               warn("%s: llistxattr failed", path);
+               free(names);
+               return FAIL;
+       }
+
+       names[countf] = '\0';
+       end_names = names + countf;
+
+       countf = 0;
+       for (name = names; name != end_names; name = strchr(name, '\0') + 1) {
+               if (!*name)
+                       continue;
+               countf++;
+       }
+
+       free(names);
+
+       if (buffer) {
+               if (xattr_verify(buffer) == FAIL)
+                       return FAIL;
+
+               if (xattr_count(buffer, &countt) == FAIL)
+                       return FAIL;
+       }
+       else
+               countt = 0;
+
+       if (countf != countt) {
+               fprintf(stderr, "%s: EA count changed from %d to %d\n", path, countt, countf);
+               return FAIL;
+       }
+
+       if (!buffer)
+               return GOOD;
+
+       return xattr_walk(buffer, xattr_cb_compare, path);
+}
+
+int
+xattr_extract(char *path, char *buffer)
+{
+       if (dflag) {
+               fprintf(stderr, "xattr_extract(%s)\n", path);
+               xattr_walk(buffer, xattr_cb_list, NULL);
+       }
+
+       if (xattr_verify(buffer) == FAIL)
+               return FAIL;
+
+       return xattr_walk(buffer, xattr_cb_set, path);
+}
+