commit 4a9feccb1c5055f69721b7b6dbb7c04bf74afc55
Author: Tim Woodall <tim@woodall.me.uk>
Date:   Sun Sep 29 19:21:06 2024 +0100

    Add -q flag to restore

--- a/dump/main.c
+++ b/dump/main.c
@@ -940,7 +940,7 @@ main(int argc, char *argv[])
 			continue;
 #ifdef	__linux__
 		/*
-		 * Skip directory inodes deleted and not yes reallocated...
+		 * Skip directory inodes deleted and not yet reallocated...
 		 */
 		if (dp->di_nlink == 0 || dp->di_dtime != 0)
 			continue;
--- a/restore/dirs.c
+++ b/restore/dirs.c
@@ -690,7 +690,7 @@ setdirmodes(int flags)
 			}
 			if ((flags & FORCE) == 0 &&
 			    node.ino == ROOTINO &&
-		   	    reply("set owner/mode for '.'") == FAIL)
+			    reply("set owner/mode/attributes for '.'", 0) == FAIL)
 				continue;
 		}
 		if (ep == NULL) {
--- a/restore/extern.h
+++ b/restore/extern.h
@@ -98,7 +98,7 @@ void		 removenode (struct entry *);
 void		 removeoldleaves (void);
 void		 removeoldnodes (void);
 void		 renameit (char *, char *);
-int		 reply (const char *);
+int		 reply (const char *, int);
 void		 resizemaps (dump_ino_t, dump_ino_t);
 RST_DIR		*rst_opendir (const char *);
 struct direct	*rst_readdir (RST_DIR *);
--- a/restore/interactive.c
+++ b/restore/interactive.c
@@ -829,7 +829,9 @@ onintr(UNUSED(int signo))
 
 	if (command == 'i' && runshell)
 		longjmp(reset, 1);
-	if (reply("restore interrupted, continue") == FAIL)
+	if (qflag)
+		exit(1);
+	if (reply("restore interrupted, continue", 0) == FAIL)
 		exit(1);
 	errno = save_errno;
 }
--- a/restore/main.c
+++ b/restore/main.c
@@ -86,7 +86,7 @@ int abortifconnerr = 1;		/* set to 1 if
 
 int	aflag = 0, bflag = 0, cvtflag = 0, dflag = 0, vflag = 0, yflag = 0;
 int	hflag = 1, mflag = 1, Mflag = 0, Nflag = 0, Vflag = 0, zflag = 0;
-int	uflag = 0, lflag = 0, Lflag = 0, oflag = 0;
+int	uflag = 0, lflag = 0, Lflag = 0, oflag = 0, qflag = 0;
 int	nullflag = 0;		/* \0 terminated file names */
 int	ufs2flag = 0;
 char	*Afile = NULL;
@@ -194,7 +194,7 @@ main(int argc, char *argv[])
 #ifdef USE_QFA
 		"P:Q:"
 #endif
-		"Rrs:tT:uvVxX:y0")) != -1)
+		"qRrs:tT:uvVxX:y0")) != -1)
 		switch(ch) {
 		case 'a':
 			aflag = 1;
@@ -303,6 +303,9 @@ main(int argc, char *argv[])
 		case 'o':
 			oflag = 1;
 			break;
+		case 'q':
+			qflag = 1;
+			break;
 #ifdef USE_QFA
 		case 'Q':
 			gTapeposfile = optarg;
@@ -724,21 +727,21 @@ usage(void)
 #endif
 	fprintf(stderr,
 		"usage:"
-		"\t%s -C [-cd" tseflag "H" kerbflag "lMvVy] [-b blocksize] [-D filesystem] " tsEflag"\n"
+		"\t%s -C [-cd" tseflag "H" kerbflag "lMqvVy] [-b blocksize] [-D filesystem] " tsEflag"\n"
 		"\t%s    [-f file] [-F script] [-L limit] [-s fileno]\n"
-		"\t%s -i [-acd" tseflag "hH" kerbflag "lmMouvVy] [-A file] [-b blocksize] " tsEflag"\n"
+		"\t%s -i [-acd" tseflag "hH" kerbflag "lmMoquvVy] [-A file] [-b blocksize] " tsEflag"\n"
 		"\t%s    [-f file] [-F script] " qfaflag "[-s fileno]\n"
 #ifdef USE_QFA
-		"\t%s -P file [-acdhH" kerbflag "lmMuvVy] [-b blocksize]\n"
+		"\t%s -P file [-acdhH" kerbflag "lmMquvVy] [-b blocksize]\n"
 		"\t%s    [-f file] [-F script] [-s fileno] [-X filelist] [file ...]\n"
 #endif
-		"\t%s -r [-cd" tseflag "H" kerbflag "lMuvVy] [-b blocksize] " tsEflag"\n"
+		"\t%s -r [-cd" tseflag "H" kerbflag "lMquvVy] [-b blocksize] " tsEflag"\n"
 		"\t%s    [-f file] [-F script] [-s fileno] [-T directory]\n"
-		"\t%s -R [-cd" tseflag "H" kerbflag "lMuvVy] [-b blocksize] " tsEflag"\n"
+		"\t%s -R [-cd" tseflag "H" kerbflag "lMquvVy] [-b blocksize] " tsEflag"\n"
 		"\t%s    [-f file] [-F script] [-s fileno] [-T directory]\n"
-		"\t%s -t [-cdhH" kerbflag "lMuvVy0] [-A file] [-b blocksize]\n"
+		"\t%s -t [-cdhH" kerbflag "lMquvVy0] [-A file] [-b blocksize]\n"
 		"\t%s    [-f file] [-F script] " qfaflag "[-s fileno] [-X filelist] [file ...]\n"
-		"\t%s -x [-acd" tseflag "hH" kerbflag "lmMouvVy] [-A file] [-b blocksize] " tsEflag"\n"
+		"\t%s -x [-acd" tseflag "hH" kerbflag "lmMqouvVy] [-A file] [-b blocksize] " tsEflag"\n"
 		"\t%s    [-f file] [-F script] " qfaflag "[-s fileno] [-X filelist] [file ...]\n",
 		__progname, white,
 		__progname, white,
--- a/restore/restore.8.in
+++ b/restore/restore.8.in
@@ -30,7 +30,7 @@
 restore \- restore files or file systems from backups made with dump
 .SH SYNOPSIS
 .B restore \-C
-[\fB\-cdHklMvVy\fR]
+[\fB\-cdHklMqvVy\fR]
 [\fB\-b \fIblocksize\fR]
 [\fB\-D \fIfilesystem\fR]
 [\fB\-f \fIfile\fR]
@@ -40,7 +40,7 @@ restore \- restore files or file systems
 [\fB\-T \fIdirectory\fR]
 .PP
 .B restore \-i
-[\fB\-acdhHklmMNouvVy\fR]
+[\fB\-acdhHklmMNoquvVy\fR]
 [\fB\-A \fIfile\fR]
 [\fB\-b \fIblocksize\fR]
 [\fB\-f \fIfile\fR]
@@ -51,7 +51,7 @@ restore \- restore files or file systems
 .PP
 .B restore \-P
 .I file
-[\fB\-acdhHklmMNuvVy\fR]
+[\fB\-acdhHklmMNquvVy\fR]
 [\fB\-b \fIblocksize\fR]
 [\fB\-f \fIfile\fR]
 [\fB\-F \fIscript\fR]
@@ -61,7 +61,7 @@ restore \- restore files or file systems
 [ \fIfile ... \fR]
 .PP
 .B restore \-R
-[\fB\-cdHklMNuvVy\fR]
+[\fB\-cdHklMNquvVy\fR]
 [\fB\-b \fIblocksize\fR]
 [\fB\-f \fIfile\fR]
 [\fB\-F \fIscript\fR]
@@ -69,7 +69,7 @@ restore \- restore files or file systems
 [\fB\-T \fIdirectory\fR]
 .PP
 .B restore \-r
-[\fB\-cdHklMNuvVy\fR]
+[\fB\-cdHklMNquvVy\fR]
 [\fB\-b \fIblocksize\fR]
 [\fB\-f \fIfile\fR]
 [\fB\-F \fIscript\fR]
@@ -77,7 +77,7 @@ restore \- restore files or file systems
 [\fB\-T \fIdirectory\fR]
 .PP
 .B restore \-t
-[\fB\-cdhHklMNuvV0y\fR]
+[\fB\-cdhHklMNquvV0y\fR]
 [\fB\-A \fIfile\fR]
 [\fB\-b \fIblocksize\fR]
 [\fB\-f \fIfile\fR]
@@ -89,7 +89,7 @@ restore \- restore files or file systems
 [ \fIfile ... \fR]
 .PP
 .B restore \-x
-[\fB\-adchHklmMNouvVy\fR]
+[\fB\-adchHklmMNqouvVy\fR]
 [\fB\-A \fIfile\fR]
 [\fB\-b \fIblocksize\fR]
 [\fB\-f \fIfile\fR]
@@ -450,6 +450,14 @@ or
 .B \-x
 modes.
 .TP
+.B \-q
+The
+.B \-q
+flag causes
+.B restore
+to abort immediately whenever operator attention is required, without prompting
+in case of read errors, tape changes etc.
+.TP
 .BI \-Q " file"
 Use the file
 .I file
--- a/restore/restore.h
+++ b/restore/restore.h
@@ -65,6 +65,7 @@ extern int	uflag;		/* unlink symlink tar
 extern int	vflag;		/* print out actions taken */
 extern int	yflag;		/* always try to recover from tape errors */
 extern int	zflag;		/* tape is in compressed format */
+extern int	qflag;		/* abort on operator intervention required */
 extern int	nullflag;	/* \0 separated output in t mode */
 extern int	ufs2flag;	/* tape is a FreeBSD UFS2 dump */
 extern char*	bot_script;	/* beginning of tape script */
--- a/restore/tape.c
+++ b/restore/tape.c
@@ -2139,7 +2139,7 @@ getmore:
 				(unsigned long)curfile.ino);
 			break;
 		}
-		if (!yflag && !reply("continue"))
+		if (qflag || !reply("continue", yflag))
 			exit(1);
 		i = ntrec * TP_BSIZE;
 		memset(tapebuf, 0, (size_t)i);
@@ -2152,7 +2152,7 @@ getmore:
 
 		if (seek_failed) {
 			warn("continuation failed");
-			if (!yflag && !reply("assume end-of-tape and continue"))
+			if (qflag || !reply("assume end-of-tape and continue", yflag))
 				exit(1);
 			i = 0;
 		}
@@ -2237,7 +2237,7 @@ readtape_comprfile(char *buf)
 	tbufptr = decompress_tapebuf(tpb, rl + PREFIXSIZE);
 	if (tbufptr == NULL) {
 		msg_read_error("File decompression error while");
-		if (!yflag && !reply("continue"))
+		if (qflag || !reply("continue", yflag))
 			exit(1);
 		memset(tapebuf, 0, bufsize);
 		tbufptr = tapebuf;
@@ -2269,7 +2269,7 @@ readerr:
 		}
 	}
 	msg_read_error("Read error while");
-	/* if (!yflag && !reply("continue")) */
+	/* if (!reply("continue", yflag)) */
 		exit(1);
 }
 
@@ -2315,7 +2315,7 @@ readtape_comprtape(char *buf)
 	tbufptr = decompress_tapebuf(tpb, rl);
 	if (tbufptr == NULL) {
 		msg_read_error("Tape decompression error while");
-		if (!yflag && !reply("continue"))
+		if (qflag || !reply("continue", yflag))
 			exit(1);
 		memset(tapebuf, 0, PREFIXSIZE + bufsize);
 		tbufptr = tapebuf;
@@ -2337,7 +2337,7 @@ readerr:
 	}
 
 	msg_read_error("Tape read error while");
-	if (!yflag && !reply("continue"))
+	if (qflag || !reply("continue", yflag))
 		exit(1);
 	memset(tapebuf, 0, PREFIXSIZE + bufsize);
 	tbufptr = tapebuf;
@@ -2355,7 +2355,7 @@ readerr:
 
 	if (rl < 0) {
 		warn("continuation failed");
-		if (!yflag && !reply("assume end-of-tape and continue"))
+		if (qflag || !reply("assume end-of-tape and continue", yflag))
 			exit(1);
 		ret = 0;         /* end of tape */
 		goto readerr;
--- a/restore/utilities.c
+++ b/restore/utilities.c
@@ -437,8 +437,11 @@ dirlookup(const char *name)
  * Elicit a reply.
  */
 int
-reply(const char *question)
+reply(const char *question, int yflag)
 {
+	if (yflag)
+		return (GOOD);
+
 	char c;
 
 	do	{
@@ -480,10 +483,12 @@ panic(fmt, va_alist)
 #endif
 
 	vfprintf(stderr, fmt, ap);
+	if (qflag)
+		exit(1);
 	if (yflag)
 		return;
-	if (reply("abort") == GOOD) {
-		if (reply("dump core") == GOOD) {
+	if (reply("abort", 0) == GOOD) {
+		if (reply("dump core", 0) == GOOD) {
 			if (fchdir(wdfd) < 0)
 				warn("fchdir");
 			abort();
