]> git.wh0rd.org - dump.git/commitdiff
dump -m implementation.
authorStelian Pop <stelian@popies.net>
Thu, 4 Apr 2002 08:20:19 +0000 (08:20 +0000)
committerStelian Pop <stelian@popies.net>
Thu, 4 Apr 2002 08:20:19 +0000 (08:20 +0000)
CHANGES
compat/include/protocols/dumprestore.h
dump/dump.8.in
dump/dump.h
dump/main.c
dump/traverse.c
restore/extern.h
restore/restore.c
restore/tape.c

diff --git a/CHANGES b/CHANGES
index 9c18c539e35a76e95f14b4866588b48a340731dd..c29c393879f0836fc317de73c0c2bbfaad143616 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,4 @@
-$Id: CHANGES,v 1.169 2002/03/28 14:53:01 stelian Exp $
+$Id: CHANGES,v 1.170 2002/04/04 08:20:19 stelian Exp $
 
 Changes between versions 0.4b27 and 0.4b28 (released ?????????????????)
 =======================================================================
@@ -39,6 +39,16 @@ Changes between versions 0.4b27 and 0.4b28 (released ?????????????????)
        Thanks to Uwe Gohlke <uwe@ugsoft.de> for reporting the bug and
        providing a test case.
 
+8.     Added the -m parameter to dump which optimises the output for
+       inodes having been changed but not modified since the last dump
+       ('changed' and 'modified' have the meaning defined in stat(2)).
+       For those inodes, dump will save only the metadata, instead of
+       saving the entire inode contents. Inodes which are either 
+       directories or have been modified since the last dump are saved
+       in a regular way.  Uses of this flag must be consistent, meaning
+       that either every dump in an incremental dump set have the flag,
+       or no one has it.
+
 Changes between versions 0.4b26 and 0.4b27 (released February 15, 2002)
 =======================================================================
 
index 2c3a945fc851ad88c76a0d45724cd6d7b769057e..d9e72fe0e5e69fd028375c94e5e2ba7fa1c870fc 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.16 2002/01/25 14:59:53 stelian Exp $
+ *     $Id: dumprestore.h,v 1.17 2002/04/04 08:20:23 stelian Exp $
  */
 
 /*
@@ -131,6 +131,8 @@ union u_spcl {
 #define DR_NEWHEADER   0x0001  /* new format tape header */
 #define DR_NEWINODEFMT 0x0002  /* new format inodes on tape */
 #define DR_COMPRESSED  0x0080  /* dump tape is compressed */
+#define DR_METAONLY    0x0100  /* only the metadata of the inode has
+                                  been dumped */
 #define DR_INODEINFO   0x0002  /* TS_END header contains c_inos information */
 
 
index 5cb450e44098edb5cd1ec6488b3aa56c4c3c5674..657f78065382a046730c3d26721aad359bc5ae01 100644 (file)
@@ -30,7 +30,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\"    $Id: dump.8.in,v 1.39 2002/02/25 10:00:44 stelian Exp $
+.\"    $Id: dump.8.in,v 1.40 2002/04/04 08:20:23 stelian Exp $
 .\"
 .Dd __DATE__
 .Dt DUMP 8
@@ -270,6 +270,22 @@ Note that this label is limited
 to be at most LBLSIZE (currently 16) characters, which must include
 the terminating
 .Ql \e0 .
+.It Fl m
+If this flag is specified,
+.Nm
+will optimise the output for inodes having been changed but not
+modified since the last dump ('changed' and 'modified' have the
+meaning defined in stat(2)). For those inodes,
+.Nm
+will save only the metadata, instead of saving the entire inode 
+contents. Inodes which are either directories or have been modified
+since the last dump are saved in a regular way.
+Uses of this flag must be consistent, meaning that either every dump 
+in an incremental dump set have the flag, or no one has it.
+.Pp
+Tapes written using such 'metadata only' inodes will not be compatible
+with the BSD tape format or older versions of
+.Nm restore.
 .It Fl M
 Enable the multi-volume feature. The name specified with 
 .Fl f 
index 2ce50e3c7c8787c7db8567a2293c8963d2c0626c..177329bbc5917b3bddf08637cfbc901d8f6b9deb 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: dump.h,v 1.36 2002/01/25 14:59:53 stelian Exp $
+ *     $Id: dump.h,v 1.37 2002/04/04 08:20:23 stelian Exp $
  */
 
 /*-
@@ -54,6 +54,8 @@ extern int    mapsize;        /* size of the state maps */
 extern char    *usedinomap;    /* map of allocated inodes */
 extern char    *dumpdirmap;    /* map of directories to be dumped */
 extern char    *dumpinomap;    /* map of files to be dumped */
+extern char    *metainomap;    /* which of the inodes in dumpinomap
+                                  will get only their metadata dumped */
 /*
  * Map manipulation macros.
  */
@@ -77,6 +79,7 @@ extern char   level;          /* dump level of this dump */
 extern int     Afile;          /* archive file descriptor */
 extern int     bzipflag;       /* compression is done using bzlib */
 extern int     uflag;          /* update flag */
+extern int     mflag;          /* dump metadata only if possible flag */
 extern int     Mflag;          /* multi-volume flag */
 extern int     qflag;          /* quit on errors flag */
 extern int      breademax;      /* maximum number of bread errors before we quit */
@@ -155,7 +158,7 @@ int mapdirs __P((dump_ino_t maxino, long *tapesize));
 /* file dumping routines */
 void   blksout __P((daddr_t *blkp, int frags, dump_ino_t ino));
 void   bread __P((daddr_t blkno, char *buf, int size));
-void   dumpino __P((struct dinode *dp, dump_ino_t ino));
+void   dumpino __P((struct dinode *dp, dump_ino_t ino, int metaonly));
 #ifdef __linux__
 void   dumpdirino __P((struct dinode *dp, dump_ino_t ino));
 #endif
index 3d4e693fc4ea6cb8672edd8a38716cd1959f0121..93c175c73b509e604595f1e874da4890ca4c14aa 100644 (file)
@@ -41,7 +41,7 @@
 
 #ifndef lint
 static const char rcsid[] =
-       "$Id: main.c,v 1.70 2002/03/11 10:17:43 stelian Exp $";
+       "$Id: main.c,v 1.71 2002/04/04 08:20:23 stelian Exp $";
 #endif /* not lint */
 
 #include <config.h>
@@ -96,6 +96,8 @@ int   mapsize;        /* size of the state maps */
 char   *usedinomap;    /* map of allocated inodes */
 char   *dumpdirmap;    /* map of directories to be dumped */
 char   *dumpinomap;    /* map of files to be dumped */
+char   *metainomap;    /* which of the inodes in dumpinomap will get
+                          only their metadata dumped */
 
 const char *disk;      /* name of the disk file */
 char   tape[MAXPATHLEN];/* name of the tape file */
@@ -106,6 +108,7 @@ char        level;          /* dump level of this dump */
 int    bzipflag;       /* compression is done using bzlib */
 int    Afile = 0;      /* archive file descriptor */
 int    uflag;          /* update flag */
+int    mflag;          /* dump metadata only if possible */
 int    Mflag;          /* multi-volume flag */
 int    qflag;          /* quit on errors flag */
 int     breademax = 32; /* maximum number of bread errors before we quit */
@@ -248,7 +251,7 @@ main(int argc, char *argv[])
 #ifdef KERBEROS
                            "k"
 #endif
-                           "Mnq"
+                           "mMnq"
 #ifdef USE_QFA
                            "Q:"
 #endif
@@ -377,6 +380,10 @@ main(int argc, char *argv[])
                        }
                        break;
 
+               case 'm':               /* metadata only flag */
+                       mflag = 1;
+                       break;
+
                case 'M':               /* multi-volume flag */
                        Mflag = 1;
                        break;
@@ -730,7 +737,9 @@ main(int argc, char *argv[])
        usedinomap = (char *)calloc((unsigned) mapsize, sizeof(char));
        dumpdirmap = (char *)calloc((unsigned) mapsize, sizeof(char));
        dumpinomap = (char *)calloc((unsigned) mapsize, sizeof(char));
-       if (usedinomap == NULL || dumpdirmap == NULL || dumpinomap == NULL)
+       metainomap = (char *)calloc((unsigned) mapsize, sizeof(char));
+       if (usedinomap == NULL || dumpdirmap == NULL || 
+           dumpinomap == NULL || metainomap == NULL)
                quit("out of memory allocating inode maps\n");
        tapesize = 2 * (howmany(mapsize * sizeof(char), TP_BSIZE) + 1);
 
@@ -933,7 +942,7 @@ main(int argc, char *argv[])
                 * inodes since this is done in dumpino().
                 */
 #endif
-               (void)dumpino(dp, ino);
+               (void)dumpino(dp, ino, mflag && TSTINO(ino, metainomap));
        }
 
        tend_writing = time(NULL);
@@ -1016,7 +1025,7 @@ usage(void)
 #ifdef KERBEROS
                "k"
 #endif
-               "MnqSu"
+               "mMnqSu"
                "] [-A file] [-B records] [-b blocksize]\n"
                "\t%s [-d density] [-e inode#,inode#,...] [-E file] [-f file]\n"
                "\t%s [-h level] [-I nr errors] "
index eda65e1379e87fa4e1417d6f6295b59529795fb4..c8547604a7c0751f14833407938e762acf1ca56f 100644 (file)
@@ -41,7 +41,7 @@
 
 #ifndef lint
 static const char rcsid[] =
-       "$Id: traverse.c,v 1.43 2002/02/04 11:18:46 stelian Exp $";
+       "$Id: traverse.c,v 1.44 2002/04/04 08:20:23 stelian Exp $";
 #endif /* not lint */
 
 #include <config.h>
@@ -217,8 +217,12 @@ blockest(struct dinode const *dp)
 }
 
 /* Auxiliary macro to pick up files changed since previous dump. */
+#define CSINCE(dp, t) \
+       ((dp)->di_ctime >= (t))
+#define MSINCE(dp, t) \
+       ((dp)->di_mtime >= (t))
 #define        CHANGEDSINCE(dp, t) \
-       ((dp)->di_mtime >= (t) || (dp)->di_ctime >= (t))
+       (CSINCE(dp, t) || MSINCE(dp, t))
 
 /* The NODUMP_FLAG macro tests if a file has the nodump flag. */
 #ifdef UF_NODUMP
@@ -266,6 +270,8 @@ mapfileino(dump_ino_t ino, struct dinode const *dp, long *tapesize, int *dirskip
                SETINO(ino, dumpdirmap);
        if (WANTTODUMP(dp, ino)) {
                SETINO(ino, dumpinomap);
+               if (!MSINCE(dp, spcl.c_ddate))
+                       SETINO(ino, metainomap);
                if (mode != IFREG && mode != IFDIR && mode != IFLNK)
                        *tapesize += 1;
                else
@@ -773,7 +779,7 @@ dumponeblock(ext2_filsys fs, blk_t *blocknr, e2_blkcnt_t blockcnt,
  * Dump the contents of an inode to tape.
  */
 void
-dumpino(struct dinode *dp, dump_ino_t ino)
+dumpino(struct dinode *dp, dump_ino_t ino, int metaonly)
 {
        unsigned long cnt;
        fsizeT size, remaining;
@@ -785,7 +791,12 @@ dumpino(struct dinode *dp, dump_ino_t ino)
 #else
        int ind_level;
 #endif
-       u_quad_t i_size = dp->di_size + ((u_quad_t) dp->di_size_high << 32);
+       u_quad_t i_size;
+       
+       if (metaonly)
+               i_size = 0;
+       else 
+               i_size = dp->di_size + ((u_quad_t) dp->di_size_high << 32);
 
        if (newtape) {
                newtape = 0;
@@ -814,6 +825,16 @@ dumpino(struct dinode *dp, dump_ino_t ino)
 #endif /* __linux__ */
        spcl.c_type = TS_INODE;
        spcl.c_count = 0;
+
+       if (metaonly && (dp->di_mode & S_IFMT)) {
+               printf("Write header with spcl.c_count=%d\n",spcl.c_count);
+               spcl.c_flags |= DR_METAONLY;
+               spcl.c_count = 0;
+               writeheader(ino);
+               spcl.c_flags &= ~DR_METAONLY;
+               return;
+       }
+
        switch (dp->di_mode & S_IFMT) {
 
        case 0:
index 408169fc5ae49eac8954097cd8b5405a03bfc1fc..0a4cbb1c94232135299eea0e138033ff6432284b 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.16 2002/02/04 11:18:46 stelian Exp $
+ *     $Id: extern.h,v 1.17 2002/04/04 08:20:23 stelian Exp $
  */
 
 /*-
@@ -62,7 +62,7 @@ void           delwhiteout __P((struct entry *));
 dump_ino_t      dirlookup __P((const char *));
 void            dumpsymtable __P((char *, long));
 void            extractdirs __P((int));
-int             extractfile __P((char *));
+int             extractfile __P((struct entry *, int));
 void            findunreflinks __P((void));
 char           *flagvalues __P((struct entry *));
 void            freeentry __P((struct entry *));
index eba23e13e939584427390ba50949fa4a9249a5c4..854c3fcd392a9880807c8173bb8e12e4c954c13f 100644 (file)
@@ -41,7 +41,7 @@
 
 #ifndef lint
 static const char rcsid[] =
-       "$Id: restore.c,v 1.28 2002/02/04 11:21:20 stelian Exp $";
+       "$Id: restore.c,v 1.29 2002/04/04 08:20:23 stelian Exp $";
 #endif /* not lint */
 
 #include <config.h>
@@ -746,6 +746,7 @@ createleaves(char *symtabfile)
        struct entry *ep;
        dump_ino_t first;
        long curvol;
+       int doremove;
 
        if (command == 'R') {
                Vprintf(stdout, "Continue extraction of new leaves\n");
@@ -796,11 +797,11 @@ createleaves(char *symtabfile)
                 * be removed since its type may change from one leaf type
                 * to another (e.g. "file" to "character special").
                 */
-               if ((ep->e_flags & EXTRACT) != 0) {
-                       removeleaf(ep);
-                       ep->e_flags &= ~REMOVED;
-               }
-               (void) extractfile(myname(ep));
+               if ((ep->e_flags & EXTRACT) != 0)
+                       doremove = 1;
+               else
+                       doremove = 0;
+               (void) extractfile(ep, doremove);
                ep->e_flags &= ~(NEW|EXTRACT);
                /*
                 * We checkpoint the restore after every tape reel, so
@@ -1029,7 +1030,7 @@ createfiles(void)
                        else {
                                msg("restoring %s\n", myname(ep));
 #endif /* USE_QFA */
-                               (void) extractfile(myname(ep));
+                               (void) extractfile(ep, 0);
 #ifdef USE_QFA
                        }
 #endif /* USE_QFA */
index 43ce99eaddf42ec9bc0b50fb9102a588f4134df6..453b7eb276e533f694cfc73bfdd7d2ae0b8c32c1 100644 (file)
@@ -46,7 +46,7 @@
 
 #ifndef lint
 static const char rcsid[] =
-       "$Id: tape.c,v 1.59 2002/03/28 14:53:01 stelian Exp $";
+       "$Id: tape.c,v 1.60 2002/04/04 08:20:23 stelian Exp $";
 #endif /* not lint */
 
 #include <config.h>
@@ -718,12 +718,24 @@ struct timeval
 #endif
 
 int
-extractfile(char *name)
+extractfile(struct entry *ep, int doremove)
 {
        unsigned int flags;
        mode_t mode;
        struct timeval timep[2];
-       struct entry *ep;
+       char *name = myname(ep);
+
+       /* If removal is requested (-r mode) do remove it unless
+        * we are extracting a metadata only inode */
+       if (spcl.c_flags & DR_METAONLY) {
+               Vprintf(stdout, "file %s is metadata only\n", name);
+       }
+       else {
+               if (doremove) {
+                       removeleaf(ep);
+                       ep->e_flags &= ~REMOVED;
+               }
+       }
 
        curfile.name = name;
        curfile.action = USING;
@@ -754,7 +766,6 @@ extractfile(char *name)
 
        case IFDIR:
                if (mflag) {
-                       ep = lookupname(name);
                        if (ep == NULL || ep->e_flags & EXTRACT)
                                panic("unextracted directory %s\n", name);
                        skipfile();
@@ -769,16 +780,21 @@ extractfile(char *name)
                uid_t luid = curfile.dip->di_uid;
                gid_t lgid = curfile.dip->di_gid;
 #endif
-               lnkbuf[0] = '\0';
-               pathlen = 0;
-               getfile(xtrlnkfile, xtrlnkskip);
-               if (pathlen == 0) {
-                       Vprintf(stdout,
-                           "%s: zero length symbolic link (ignored)\n", name);
-                       return (GOOD);
+               if (! (spcl.c_flags & DR_METAONLY)) {
+                       lnkbuf[0] = '\0';
+                       pathlen = 0;
+                       getfile(xtrlnkfile, xtrlnkskip);
+                       if (pathlen == 0) {
+                               Vprintf(stdout,
+                                   "%s: zero length symbolic link (ignored)\n", name);
+                               return (GOOD);
+                       }
+                       if (linkit(lnkbuf, name, SYMLINK) == FAIL)
+                               return (FAIL);
                }
-               if (linkit(lnkbuf, name, SYMLINK) == FAIL)
-                       return (FAIL);
+               else
+                       skipfile();
+
 #ifdef HAVE_LCHOWN
                (void) lchown(name, luid, lgid);
 #endif
@@ -791,12 +807,14 @@ extractfile(char *name)
                        skipfile();
                        return (GOOD);
                }
-               if (uflag && !Nflag)
-                       (void)unlink(name);
-               if (mkfifo(name, mode) < 0) {
-                       warn("%s: cannot create fifo", name);
-                       skipfile();
-                       return (FAIL);
+               if (! (spcl.c_flags & DR_METAONLY)) {
+                       if (uflag && !Nflag)
+                               (void)unlink(name);
+                       if (mkfifo(name, mode) < 0) {
+                               warn("%s: cannot create fifo", name);
+                               skipfile();
+                               return (FAIL);
+                       }
                }
                (void) chown(name, curfile.dip->di_uid, curfile.dip->di_gid);
                (void) chmod(name, mode);
@@ -817,12 +835,14 @@ extractfile(char *name)
                        skipfile();
                        return (GOOD);
                }
-               if (uflag)
-                       (void)unlink(name);
-               if (mknod(name, mode, (int)curfile.dip->di_rdev) < 0) {
-                       warn("%s: cannot create special file", name);
-                       skipfile();
-                       return (FAIL);
+               if (! (spcl.c_flags & DR_METAONLY)) {
+                       if (uflag)
+                               (void)unlink(name);
+                       if (mknod(name, mode, (int)curfile.dip->di_rdev) < 0) {
+                               warn("%s: cannot create special file", name);
+                               skipfile();
+                               return (FAIL);
+                       }
                }
                (void) chown(name, curfile.dip->di_uid, curfile.dip->di_gid);
                (void) chmod(name, mode);
@@ -840,32 +860,41 @@ extractfile(char *name)
                return (GOOD);
 
        case IFREG:
+       {
+               uid_t luid = curfile.dip->di_uid;
+               gid_t lgid = curfile.dip->di_gid;
+
                Vprintf(stdout, "extract file %s\n", name);
                if (Nflag) {
                        skipfile();
                        return (GOOD);
                }
-               if (uflag)
-                       (void)unlink(name);
-               if ((ofile = OPEN(name, O_WRONLY | O_CREAT | O_TRUNC,
-                   0666)) < 0) {
-                       warn("%s: cannot create file", name);
-                       skipfile();
-                       return (FAIL);
+               if (! (spcl.c_flags & DR_METAONLY)) {
+                       if (uflag)
+                               (void)unlink(name);
+                       if ((ofile = OPEN(name, O_WRONLY | O_CREAT | O_TRUNC,
+                           0666)) < 0) {
+                               warn("%s: cannot create file", name);
+                               skipfile();
+                               return (FAIL);
+                       }
+                       getfile(xtrfile, xtrskip);
+                       (void) close(ofile);
                }
-               (void) fchown(ofile, curfile.dip->di_uid, curfile.dip->di_gid);
-               (void) fchmod(ofile, mode);
+               else
+                       skipfile();
+               (void) chown(name, luid, lgid);
+               (void) chmod(name, mode);
                if (flags)
 #ifdef __linux__
-                       (void) setflags(ofile, flags);
+                       (void) fsetflags(name, flags);
 #else
-                       (void) fchflags(ofile, flags);
+                       (void) chflags(name, flags);
 #endif
-               getfile(xtrfile, xtrskip);
-               (void) close(ofile);
                utimes(name, timep);
                return (GOOD);
        }
+       }
        /* NOTREACHED */
 }
 
@@ -1260,6 +1289,10 @@ comparefile(char *name)
                        name, mode & 07777, sb.st_mode & 07777);
                do_compare_error;
        }
+       if (spcl.c_flags & DR_METAONLY) {
+               skipfile();
+               return;
+       }
        switch (mode & IFMT) {
        default:
                skipfile();