Fix -S with -b not atomically updating the destination file.
With both of these flags, the backup was created via rename(dest, backup) followed by rename(tmp, dest). This left the destination file missing for a moment which contradicts the point of -S. This fixes a race with installworld where PRECIOUSPROG and PRECIOUSLIB files (which use -S for installation) would briefly be missing. In the case of installing rtld with parallel installworld it could render an error due to not having rtld present to run install/cp in another process. Reported by: jhb Reviewed by: jhb MFC after: 1 week Sponsored by: EMC / Isilon Storage Division Differential Revision: https://reviews.freebsd.org/D7451
This commit is contained in:
parent
e96f85f48f
commit
032a51f8f0
@ -892,11 +892,17 @@ install(const char *from_name, const char *to_name, u_long fset, u_int flags)
|
||||
}
|
||||
if (verbose)
|
||||
(void)printf("install: %s -> %s\n", to_name, backup);
|
||||
if (rename(to_name, backup) < 0) {
|
||||
if (unlink(backup) < 0 && errno != ENOENT) {
|
||||
serrno = errno;
|
||||
unlink(tempfile);
|
||||
errno = serrno;
|
||||
err(EX_OSERR, "rename: %s to %s", to_name,
|
||||
err(EX_OSERR, "unlink: %s", backup);
|
||||
}
|
||||
if (link(to_name, backup) < 0) {
|
||||
serrno = errno;
|
||||
unlink(tempfile);
|
||||
errno = serrno;
|
||||
err(EX_OSERR, "link: %s to %s", to_name,
|
||||
backup);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user