Subject: Re: restore and schg flag
To: None <tech-userlevel@NetBSD.org>
From: Manuel Bouyer <bouyer@antioche.eu.org>
List: tech-userlevel
Date: 10/12/2004 00:06:18
--y0ulUmNC+osPPQO6
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Mon, Oct 11, 2004 at 10:33:52PM +0200, Manuel Bouyer wrote:
> [...]
> 
> My idea for this is to defer this work to mtree. I'll add a -M<file> flag to
> restore, which, when set, will cause restore to not set the file flags
> (either for files or directory), but instead write (append, so that we can
> have in a single file the output of a multilevel restore) a mtree file in the
> format of /etc/mtree/*. Then the user can run mtree against this file
> to restore the flags. I can't think of a better way to handle all the
> corner cases *chg or *appnd can create for restore.
> 
> Comments ?

Here is a patch. It works in my case, at last:
#/tmp/restore -M /tmp/mtree -rvf ../wd0a.0
[...]
#/tmp/restore -M /tmp/mtree -rvf ../wd0a.1
[...]
# sort /tmp/mtree | mtree -e -i -u
testdir: 
        flags ("uchg" is not "none", modified to "uchg")

We need to process the file though sort, because mtree needs to have the specs
for a directory before the files in this directory. But it works very well
for my test cases.

Should I update the man page, and commit this ?

-- 
Manuel Bouyer <bouyer@antioche.eu.org>
     NetBSD: 26 ans d'experience feront toujours la difference
--

--y0ulUmNC+osPPQO6
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=diff

? .gdbinit
? restore
? restore.cat8
Index: dirs.c
===================================================================
RCS file: /cvsroot/src/sbin/restore/dirs.c,v
retrieving revision 1.40
diff -u -r1.40 dirs.c
--- dirs.c	5 Nov 2003 22:27:16 -0000	1.40
+++ dirs.c	11 Oct 2004 22:00:46 -0000
@@ -649,7 +649,12 @@
 				(void) utimes(cp, node.mtimep);
 				(void) chown(cp, node.uid, node.gid);
 				(void) chmod(cp, node.mode);
-				(void) chflags(cp, node.flags);
+				if (Mtreefile) {
+					writemtree(cp, "dir",
+					    node.uid, node.gid, node.mode,
+					    node.flags);
+				} else 
+					(void) chflags(cp, node.flags);
 			}
 			ep->e_flags &= ~NEW;
 		}
Index: extern.h
===================================================================
RCS file: /cvsroot/src/sbin/restore/extern.h,v
retrieving revision 1.9
diff -u -r1.9 extern.h
--- extern.h	7 Aug 2003 10:04:37 -0000	1.9
+++ extern.h	11 Oct 2004 22:00:46 -0000
@@ -99,6 +99,8 @@
 void	 	 treescan __P((char *, ino_t, long (*)(char *, ino_t, int)));
 ino_t		 upperbnd __P((ino_t));
 long		 verifyfile __P((char *, ino_t, int));
+void		 writemtree __P((const char *, const char *, const uid_t,
+				const gid_t, const mode_t, const u_long));
 void		 xtrnull __P((char *, long));
 
 /* From ../dump/dumprmt.c */
Index: main.c
===================================================================
RCS file: /cvsroot/src/sbin/restore/main.c,v
retrieving revision 1.23
diff -u -r1.23 main.c
--- main.c	7 Aug 2003 10:04:37 -0000	1.23
+++ main.c	11 Oct 2004 22:00:46 -0000
@@ -77,6 +77,8 @@
 FILE 	*terminal;
 char	*tmpdir;
 
+FILE *Mtreefile = NULL;
+
 int	main __P((int, char *[]));
 static	void obsolete __P((int *, char **[]));
 static	void usage __P((void));
@@ -100,7 +102,7 @@
 	if ((tmpdir = getenv("TMPDIR")) == NULL)
 		tmpdir = _PATH_TMP;
 	obsolete(&argc, &argv);
-	while ((ch = getopt(argc, argv, "b:cdf:himNRrs:tuvxy")) != -1)
+	while ((ch = getopt(argc, argv, "b:cdf:himM:NRrs:tuvxy")) != -1)
 		switch(ch) {
 		case 'b':
 			/* Change default tape blocksize. */
@@ -140,6 +142,11 @@
 		case 'N':
 			Nflag = 1;
 			break;
+		case 'M':
+			Mtreefile = fopen(optarg, "a");
+			if (Mtreefile == NULL)
+				err(1, "can't open %s", optarg);
+			break;
 		case 's':
 			/* Dumpnum (skip to) for multifile dump tapes. */
 			dumpnum = strtol(optarg, &p, 10);
@@ -293,20 +300,20 @@
 	const char *progname = getprogname();
 
 	(void)fprintf(stderr,
-	    "usage: %s -i [-cdhmvyN] [-b blocksize] [-f file] [-s fileno]\n",
-	    progname);
+	    "usage: %s -i [-cdhmvyN] [-b blocksize] [-f file] [-s fileno] "
+	    "[-M mtreefile]\n", progname);
 	(void)fprintf(stderr,
-	    "\t%s -R [-cdvyN] [-b blocksize] [-f file] [-s fileno]\n",
-	    progname);
+	    "\t%s -R [-cdvyN] [-b blocksize] [-f file] [-s fileno] "
+	    "[-M mtreefile]\n", progname);
 	(void)fprintf(stderr,
-	    "\t%s -r [-cdvyN] [-b blocksize] [-f file] [-s fileno]\n",
-	    progname);
+	    "\t%s -r [-cdvyN] [-b blocksize] [-f file] [-s fileno] "
+	    "[-M mtreefile]\n", progname);
 	(void)fprintf(stderr,
-	    "\t%s -t [-cdhvy] [-b blocksize] [-f file] [-s fileno] [file ...]\n",
-	    progname);
+	    "\t%s -t [-cdhvy] [-b blocksize] [-f file] [-s fileno] "
+	    "[-M mtreefile] [file ...]\n", progname);
 	(void)fprintf(stderr,
-	    "\t%s -x [-cdhmvyN] [-b blocksize] [-f file] [-s fileno] [file ...]\n",
-	    progname);
+	    "\t%s -x [-cdhmvyN] [-b blocksize] [-f file] [-s fileno] "
+	    "[-M mtreefile] [file ...]\n", progname);
 	exit(1);
 }
 
Index: restore.h
===================================================================
RCS file: /cvsroot/src/sbin/restore/restore.h,v
retrieving revision 1.14
diff -u -r1.14 restore.h
--- restore.h	7 Aug 2003 10:04:38 -0000	1.14
+++ restore.h	11 Oct 2004 22:00:46 -0000
@@ -65,6 +65,7 @@
 extern char	*tmpdir;	/* where to store temporary files */
 extern int	oldinofmt;	/* reading tape with old format inodes */
 extern int	Bcvt;		/* need byte swapping on inodes and dirs */
+extern FILE	*Mtreefile;	/* file descriptor for the mtree file */
 
 /*
  * Each file in the file system is described by one of these entries
Index: tape.c
===================================================================
RCS file: /cvsroot/src/sbin/restore/tape.c,v
retrieving revision 1.49
diff -u -r1.49 tape.c
--- tape.c	7 Aug 2003 10:04:38 -0000	1.49
+++ tape.c	11 Oct 2004 22:00:46 -0000
@@ -52,6 +52,7 @@
 #include <ufs/ufs/dinode.h>
 #include <protocols/dumprestore.h>
 
+#include <err.h>
 #include <errno.h>
 #include <paths.h>
 #include <setjmp.h>
@@ -542,6 +543,21 @@
 		spcl.c_level, spcl.c_filesys, 
 		*spcl.c_host? spcl.c_host: "[unknown]", spcl.c_dev);
 	fprintf(stderr, "Label: %s\n", spcl.c_label);
+
+	if (Mtreefile) {
+		ttime = spcl.c_date;
+		fprintf(Mtreefile, "#Dump   date: %s", ctime(&ttime));
+		ttime = spcl.c_ddate;
+		fprintf(Mtreefile, "#Dumped from: %s",
+		    (spcl.c_ddate == 0) ? "the epoch\n" : ctime(&ttime));
+		fprintf(Mtreefile, "#Level %d dump of %s on %s:%s\n",
+			spcl.c_level, spcl.c_filesys, 
+			*spcl.c_host? spcl.c_host: "[unknown]", spcl.c_dev);
+		fprintf(Mtreefile, "#Label: %s\n", spcl.c_label);
+		fprintf(Mtreefile, "/set uname=root gname=wheel\n");
+		if (ferror(Mtreefile))
+			err(1, "error writing to mtree file");
+	}
 }
 
 int
@@ -615,7 +631,11 @@
 			(void) lutimes(name, mtimep);
 			(void) lchown(name, uid, gid);
 			(void) lchmod(name, mode);
-			(void) lchflags(name, flags);
+			if (Mtreefile) {
+				writemtree(name, "link",
+				    uid, gid, mode, flags);
+			} else 
+				(void) lchflags(name, flags);
 			return (GOOD);
 		}
 		return (FAIL);
@@ -642,7 +662,13 @@
 		(void) utimes(name, mtimep);
 		(void) chown(name, uid, gid);
 		(void) chmod(name, mode);
-		(void) chflags(name, flags);
+		if (Mtreefile) {
+			writemtree(name,
+			    ((mode & (S_IFBLK | IFCHR)) == IFBLK) ?
+			    "block" : "char",
+			    uid, gid, mode, flags);
+		} else 
+			(void) chflags(name, flags);
 		return (GOOD);
 
 	case IFIFO:
@@ -665,7 +691,11 @@
 		(void) utimes(name, mtimep);
 		(void) chown(name, uid, gid);
 		(void) chmod(name, mode);
-		(void) chflags(name, flags);
+		if (Mtreefile) {
+			writemtree(name, "fifo",
+			    uid, gid, mode, flags);
+		} else 
+			(void) chflags(name, flags);
 		return (GOOD);
 
 	case IFREG:
@@ -689,7 +719,11 @@
 		(void) futimes(ofile, mtimep);
 		(void) fchown(ofile, uid, gid);
 		(void) fchmod(ofile, mode);
-		(void) fchflags(ofile, flags);
+		if (Mtreefile) {
+			writemtree(name, "file",
+			    uid, gid, mode, flags);
+		} else 
+			(void) fchflags(ofile, flags);
 		(void) close(ofile);
 		return (GOOD);
 	}
Index: utilities.c
===================================================================
RCS file: /cvsroot/src/sbin/restore/utilities.c,v
retrieving revision 1.17
diff -u -r1.17 utilities.c
--- utilities.c	7 Aug 2003 10:04:38 -0000	1.17
+++ utilities.c	11 Oct 2004 22:00:46 -0000
@@ -44,6 +44,7 @@
 #include <ufs/ufs/dinode.h>
 #include <ufs/ufs/dir.h>
 
+#include <err.h>
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -423,3 +424,48 @@
 		exit(1);
 	}
 }
+
+void
+writemtree(const char *name, const char *type,
+    const uid_t uid, const gid_t gid, const mode_t mode, const u_long flags)
+{
+	char *sep = "";
+	if ((name[0] != '.') || (name[1] != '/' && name[1] != '\0'))
+		fprintf(Mtreefile, "./");
+	fprintf(Mtreefile, "%s type=%s uid=%d gid=%d mode=%#4.4o",
+	    name, type, uid, gid,
+	    mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISTXT));
+	if (flags != 0)
+		fprintf(Mtreefile, " flags=");
+	if (flags & UF_NODUMP) {
+		fprintf(Mtreefile, "nodump");
+		sep=",";
+	}
+	if (flags & UF_IMMUTABLE) {
+		fprintf(Mtreefile, "%suchg", sep);
+		sep=",";
+	}
+	if (flags & UF_APPEND) {
+		fprintf(Mtreefile, "%suappnd", sep);
+		sep=",";
+	}
+	if (flags & UF_OPAQUE) {
+		fprintf(Mtreefile, "%sopaque", sep);
+		sep=",";
+	}
+	if (flags & SF_ARCHIVED) {
+		fprintf(Mtreefile, "%sarch", sep);
+		sep=",";
+	}
+	if (flags & SF_IMMUTABLE) {
+		fprintf(Mtreefile, "%sschg", sep);
+		sep=",";
+	}
+	if (flags & SF_APPEND) {
+		fprintf(Mtreefile, "%ssappnd", sep);
+		sep=",";
+	}
+	fprintf(Mtreefile, "\n");
+	if (ferror(Mtreefile))
+		err(1, "error writing to mtree file");
+}

--y0ulUmNC+osPPQO6--