summaryrefslogtreecommitdiffstats
path: root/usr.bin
diff options
context:
space:
mode:
authorjilles <jilles@FreeBSD.org>2011-01-08 00:03:18 +0000
committerjilles <jilles@FreeBSD.org>2011-01-08 00:03:18 +0000
commit6ef9696fb44fbc1b12fdac123542630a9bec6bad (patch)
treeb86c1734dc9ae41a27d4271519188d0056277885 /usr.bin
parent16de4d95f52c6e680c13464902c761f154b200af (diff)
downloadFreeBSD-src-6ef9696fb44fbc1b12fdac123542630a9bec6bad.zip
FreeBSD-src-6ef9696fb44fbc1b12fdac123542630a9bec6bad.tar.gz
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
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/sed/main.c25
1 files changed, 21 insertions, 4 deletions
diff --git a/usr.bin/sed/main.c b/usr.bin/sed/main.c
index 8d4fe95..049d2ea 100644
--- a/usr.bin/sed/main.c
+++ b/usr.bin/sed/main.c
@@ -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;
OpenPOWER on IntegriCloud