From ken@globalremit.com  Mon Feb 20 19:03:24 2006
Return-Path: <ken@globalremit.com>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id DFA2716A420
	for <FreeBSD-gnats-submit@freebsd.org>; Mon, 20 Feb 2006 19:03:23 +0000 (GMT)
	(envelope-from ken@globalremit.com)
Received: from dev.torus.ca (dev.torus.ca [159.18.147.50])
	by mx1.FreeBSD.org (Postfix) with ESMTP id 74AC043D5D
	for <FreeBSD-gnats-submit@freebsd.org>; Mon, 20 Feb 2006 19:03:21 +0000 (GMT)
	(envelope-from ken@globalremit.com)
Received: from p2.torus.ca ([10.0.0.8])
	by dev.torus.ca (8.13.5/8.13.5) with ESMTP id k1KJ36uE008346
	(version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NOT)
	for <FreeBSD-gnats-submit@freebsd.org>; Mon, 20 Feb 2006 14:03:07 -0500 (EST)
Received: from p2.torus.ca (localhost [127.0.0.1])
	by p2.torus.ca (8.13.4/8.13.4) with ESMTP id k1KJ36t7000960
	for <FreeBSD-gnats-submit@freebsd.org>; Mon, 20 Feb 2006 14:03:06 -0500 (EST)
	(envelope-from ken@p2.torus.ca)
Received: (from ken@localhost)
	by p2.torus.ca (8.13.4/8.13.4/Submit) id k1KJ35tC000959;
	Mon, 20 Feb 2006 14:03:05 -0500 (EST)
	(envelope-from ken)
Message-Id: <200602201903.k1KJ35tC000959@p2.torus.ca>
Date: Mon, 20 Feb 2006 14:03:05 -0500 (EST)
From: Ken Lalonde <ken@globalremit.com>
Reply-To: Ken Lalonde <ken@globalremit.com>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: restore fails if /tmp fills [patch]
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         93603
>Category:       bin
>Synopsis:       [patch] restore(8) fails if /tmp fills
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Feb 20 19:10:03 GMT 2006
>Closed-Date:    Mon Apr 14 20:22:59 UTC 2008
>Last-Modified:  Mon Apr 14 20:30:01 UTC 2008
>Originator:     Ken Lalonde
>Release:        FreeBSD 6.0-RELEASE i386
>Organization:
Global Remittance Network
>Environment:
System: FreeBSD p2.torus.ca 6.0-RELEASE FreeBSD 6.0-RELEASE #1: Wed Feb 8 00:26:53 EST 2006 ken@p2.torus.ca:/usr/src/sys/i386/compile/P2 i386

>Description:
	restore(8) does not check for write failure while building two temp files
	containing directory and ownership data.  If /tmp fills, the console is
	blasted with zillions of "file system full" errors, and restore continues on,
	even though directory and/or ownership data has been lost.
	This is particularly likely to happen when running from the live CD,
	which has little /tmp space.

>How-To-Repeat:
	Boot the live CD and attempt to restore a large filesystem,
	or just inspect the code.

>Fix:
	The attached patch against the 6.0 source causes restore to quit
	with an appropriate error message in the event of write failure.
	If the failure is ENOSPC, a further suggestion is displayed.
	Also, failure to re-open the directory data file is now fatal.


--- d begins here ---
--- dirs.c	2006/02/18 00:22:58	1.1
+++ dirs.c	2006/02/20 18:22:47
@@ -118,6 +118,7 @@
 static void		 rst_seekdir(RST_DIR *, long, long);
 static long		 rst_telldir(RST_DIR *);
 static struct direct	*searchdir(ino_t, char *);
+static void		 tmp_write_failed(char *);
 
 /*
  *	Extract directory contents, building up a directory structure
@@ -171,13 +172,16 @@
 		curfile.name = "<directory file - name unknown>";
 		curfile.action = USING;
 		if (curfile.mode == 0 || (curfile.mode & IFMT) != IFDIR) {
-			(void) fclose(df);
+			if (fclose(df))
+				tmp_write_failed(dirfile);
 			dirp = opendirfile(dirfile);
-			if (dirp == NULL)
-				fprintf(stderr, "opendirfile: %s\n",
-				    strerror(errno));
+			if (dirp == NULL) {
+				warn(dirfile);
+				done(1);
+			}
 			if (mf != NULL)
-				(void) fclose(mf);
+				if (fclose(mf))
+					tmp_write_failed(modefile);
 			i = dirlookup(dot);
 			if (i == 0)
 				panic("Root directory is not on tape\n");
@@ -389,7 +393,8 @@
 	if (dirloc + dp->d_reclen > DIRBLKSIZ) {
 		((struct direct *)(dirbuf + prev))->d_reclen =
 		    DIRBLKSIZ - prev;
-		(void) fwrite(dirbuf, 1, DIRBLKSIZ, df);
+		if (fwrite(dirbuf, DIRBLKSIZ, 1, df) != 1)
+			tmp_write_failed(dirfile);
 		dirloc = 0;
 	}
 	memmove(dirbuf + dirloc, dp, (long)dp->d_reclen);
@@ -404,7 +409,8 @@
 flushent(void)
 {
 	((struct direct *)(dirbuf + prev))->d_reclen = DIRBLKSIZ - prev;
-	(void) fwrite(dirbuf, (int)dirloc, 1, df);
+	if (fwrite(dirbuf, dirloc, 1, df) != 1)
+		tmp_write_failed(dirfile);
 	seekpt = ftell(df);
 	dirloc = 0;
 }
@@ -688,7 +694,8 @@
 	node.flags = ctxp->file_flags;
 	node.uid = ctxp->uid;
 	node.gid = ctxp->gid;
-	(void) fwrite((char *)&node, 1, sizeof(struct modeinfo), mf);
+	if (fwrite((char *)&node, sizeof(struct modeinfo), 1, mf) != 1)
+		tmp_write_failed(modefile);
 	return (itp);
 }
 
@@ -719,4 +726,19 @@
 	if (dirfile[0] != '#')
 		(void) unlink(dirfile);
 	exit(exitcode);
+}
+
+static void
+tmp_write_failed(char *path)
+{
+	const char *tmpdir;
+
+	warn("%s: write", path);
+	if (errno == ENOSPC) {
+		if ((tmpdir = getenv("TMPDIR")) == NULL || tmpdir[0] == '\0')
+			tmpdir = _PATH_TMP;
+		fprintf(stderr, "Try making space in %s, or set TMPDIR elsewhere.",
+			tmpdir);
+	}
+	done(1);
 }
--- d ends here ---


>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->closed 
State-Changed-By: mckusick 
State-Changed-When: Mon Apr 14 20:17:44 UTC 2008 
State-Changed-Why:  
The submitted fix by Ken Lalonde has been applied and tested to 
verify that it correctly handles the problem. A possible future 
extension would be to try building the database in memory if the 
filesystem is too small to hold it. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=93603 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/93603: commit references a PR
Date: Mon, 14 Apr 2008 20:16:12 +0000 (UTC)

 mckusick    2008-04-14 20:15:53 UTC
 
   FreeBSD src repository
 
   Modified files:
     sbin/restore         dirs.c 
   Log:
   restore(8) does not check for write failure while building two temp
   files containing directory and ownership data. If /tmp fills, the
   console is blasted with zillions of "file system full" errors, and
   restore continues on, even though directory and/or ownership data
   has been lost. This is particularly likely to happen when running
   from the live CD, which has little /tmp space.
   
   PR:         bin/93603, also probably bin/107213
   Fix from:   Ken Lalonde
   
   Revision  Changes    Path
   1.34      +68 -24    src/sbin/restore/dirs.c
 _______________________________________________
 cvs-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/cvs-all
 To unsubscribe, send any mail to "cvs-all-unsubscribe@freebsd.org"
 
>Unformatted:
