-$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 ?????????????????)
=======================================================================
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)
=======================================================================
* 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 $
*/
/*
#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 */
.\" 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
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
* 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 $
*/
/*-
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.
*/
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 */
/* 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
#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>
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 */
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 */
#ifdef KERBEROS
"k"
#endif
- "Mnq"
+ "mMnq"
#ifdef USE_QFA
"Q:"
#endif
}
break;
+ case 'm': /* metadata only flag */
+ mflag = 1;
+ break;
+
case 'M': /* multi-volume flag */
Mflag = 1;
break;
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);
* inodes since this is done in dumpino().
*/
#endif
- (void)dumpino(dp, ino);
+ (void)dumpino(dp, ino, mflag && TSTINO(ino, metainomap));
}
tend_writing = time(NULL);
#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] "
#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>
}
/* 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
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
* 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;
#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;
#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:
* 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 $
*/
/*-
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 *));
#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>
struct entry *ep;
dump_ino_t first;
long curvol;
+ int doremove;
if (command == 'R') {
Vprintf(stdout, "Continue extraction of new leaves\n");
* 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
else {
msg("restoring %s\n", myname(ep));
#endif /* USE_QFA */
- (void) extractfile(myname(ep));
+ (void) extractfile(ep, 0);
#ifdef USE_QFA
}
#endif /* USE_QFA */
#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>
#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;
case IFDIR:
if (mflag) {
- ep = lookupname(name);
if (ep == NULL || ep->e_flags & EXTRACT)
panic("unextracted directory %s\n", name);
skipfile();
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
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);
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);
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 */
}
name, mode & 07777, sb.st_mode & 07777);
do_compare_error;
}
+ if (spcl.c_flags & DR_METAONLY) {
+ skipfile();
+ return;
+ }
switch (mode & IFMT) {
default:
skipfile();