Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 8 Jan 2011 00:03:19 +0000 (UTC)
From:      Jilles Tjoelker <jilles@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r217133 - head/usr.bin/sed
Message-ID:  <201101080003.p0803J1S070169@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jilles
Date: Sat Jan  8 00:03:18 2011
New Revision: 217133
URL: http://svn.freebsd.org/changeset/base/217133

Log:
  sed: Try hard links to make -i target available continually.
  
  When creating a backup file, sed renamed the original before renaming the
  changed copy into place, leading to a short time when no file with the
  original name was present (usually only visible on SMP systems). Try
  creating the backup file using a hard link instead, avoiding this problem.
  If creating the hard link fails for any reason, fall back to the old rename
  method.
  
  When not creating a backup file, sed already renamed the changed copy onto
  the original. This remains unchanged.
  
  I am not adding the suppression of redundant fchown/fchmod to this commit,
  because FreeBSD appears to check this in the kernel (for msdosfs at least).
  
  PR:		bin/153261
  Submitted by:	Pedro F. Giffuni
  Reviewed by:	dds (older version)
  Obtained from:	Illumos
  MFC after:	2 weeks

Modified:
  head/usr.bin/sed/main.c

Modified: head/usr.bin/sed/main.c
==============================================================================
--- head/usr.bin/sed/main.c	Fri Jan  7 23:39:41 2011	(r217132)
+++ head/usr.bin/sed/main.c	Sat Jan  8 00:03:18 2011	(r217133)
@@ -338,18 +338,35 @@ mf_fgets(SPACE *sp, enum e_spflag spflag
 		if (infile != NULL) {
 			fclose(infile);
 			if (*oldfname != '\0') {
-				if (rename(fname, oldfname) != 0) {
+				/* if there was a backup file, remove it */
+				unlink(oldfname);
+				/*
+				 * Backup the original.  Note that hard links
+				 * are not supported on all filesystems.
+				 */
+				if ((link(fname, oldfname) != 0) &&
+				   (rename(fname, oldfname) != 0)) {
 					warn("rename()");
-					unlink(tmpfname);
+					if (*tmpfname)
+						unlink(tmpfname);
 					exit(1);
 				}
 				*oldfname = '\0';
 			}
 			if (*tmpfname != '\0') {
 				if (outfile != NULL && outfile != stdout)
-					fclose(outfile);
+					if (fclose(outfile) != 0) {
+						warn("fclose()");
+						unlink(tmpfname);
+						exit(1);
+					}
 				outfile = NULL;
-				rename(tmpfname, fname);
+				if (rename(tmpfname, fname) != 0) {
+					/* this should not happen really! */
+					warn("rename()");
+					unlink(tmpfname);
+					exit(1);
+				}
 				*tmpfname = '\0';
 			}
 			outfname = NULL;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201101080003.p0803J1S070169>