Date: Mon, 20 Feb 2006 14:03:05 -0500 (EST) From: Ken Lalonde <ken@globalremit.com> To: FreeBSD-gnats-submit@FreeBSD.org Subject: bin/93603: restore fails if /tmp fills [patch] Message-ID: <200602201903.k1KJ35tC000959@p2.torus.ca> Resent-Message-ID: <200602201910.k1KJA4q8016288@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 93603 >Category: bin >Synopsis: restore fails if /tmp fills [patch] >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Mon Feb 20 19:10:03 GMT 2006 >Closed-Date: >Last-Modified: >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: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200602201903.k1KJ35tC000959>