mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-28 11:57:28 +00:00
Make mv more robust. A race has been fixed, as well as an extra warning
added when sbits are cleared. Fixes PR 1351 and 1377 (I hope).
This commit is contained in:
parent
f71e91691c
commit
03001f577f
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=23525
38
bin/mv/mv.c
38
bin/mv/mv.c
@ -33,7 +33,7 @@
|
|||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* $Id$
|
* $Id: mv.c,v 1.11 1997/02/22 14:04:12 peter Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
@ -206,22 +206,31 @@ fastcopy(from, to, sbp)
|
|||||||
struct timeval tval[2];
|
struct timeval tval[2];
|
||||||
static u_int blen;
|
static u_int blen;
|
||||||
static char *bp;
|
static char *bp;
|
||||||
|
mode_t oldmode;
|
||||||
register int nread, from_fd, to_fd;
|
register int nread, from_fd, to_fd;
|
||||||
|
|
||||||
if ((from_fd = open(from, O_RDONLY, 0)) < 0) {
|
if ((from_fd = open(from, O_RDONLY, 0)) < 0) {
|
||||||
warn("%s", from);
|
warn("%s", from);
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
if ((to_fd =
|
if (blen < sbp->st_blksize) {
|
||||||
open(to, O_CREAT | O_TRUNC | O_WRONLY, sbp->st_mode)) < 0) {
|
if (bp != NULL)
|
||||||
|
free(bp);
|
||||||
|
if ((bp = malloc(sbp->st_blksize)) == NULL) {
|
||||||
|
blen = 0;
|
||||||
|
warnx("malloc failed");
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
blen = sbp->st_blksize;
|
||||||
|
}
|
||||||
|
while ((to_fd =
|
||||||
|
open(to, O_CREAT | O_EXCL | O_TRUNC | O_WRONLY, 0)) < 0) {
|
||||||
|
if (errno == EEXIST && unlink(to) == 0)
|
||||||
|
continue;
|
||||||
warn("%s", to);
|
warn("%s", to);
|
||||||
(void)close(from_fd);
|
(void)close(from_fd);
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
if (!blen && !(bp = malloc(blen = sbp->st_blksize))) {
|
|
||||||
warn(NULL);
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
while ((nread = read(from_fd, bp, blen)) > 0)
|
while ((nread = read(from_fd, bp, blen)) > 0)
|
||||||
if (write(to_fd, bp, nread) != nread) {
|
if (write(to_fd, bp, nread) != nread) {
|
||||||
warn("%s", to);
|
warn("%s", to);
|
||||||
@ -237,10 +246,19 @@ err: if (unlink(to))
|
|||||||
}
|
}
|
||||||
(void)close(from_fd);
|
(void)close(from_fd);
|
||||||
|
|
||||||
if (fchown(to_fd, sbp->st_uid, sbp->st_gid))
|
oldmode = sbp->st_mode & ALLPERMS;
|
||||||
warn("%s: set owner/group", to);
|
if (fchown(to_fd, sbp->st_uid, sbp->st_gid)) {
|
||||||
|
warn("%s: set owner/group (was: %u/%u)", to, sbp->st_uid,
|
||||||
|
sbp->st_gid);
|
||||||
|
if (oldmode & (S_ISUID | S_ISGID)) {
|
||||||
|
warnx(
|
||||||
|
"%s: owner/group changed; clearing suid/sgid (mode was 0%03o)",
|
||||||
|
to, oldmode);
|
||||||
|
sbp->st_mode &= ~(S_ISUID | S_ISGID);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (fchmod(to_fd, sbp->st_mode))
|
if (fchmod(to_fd, sbp->st_mode))
|
||||||
warn("%s: set mode", to);
|
warn("%s: set mode (was: 0%03o)", to, oldmode);
|
||||||
|
|
||||||
tval[0].tv_sec = sbp->st_atime;
|
tval[0].tv_sec = sbp->st_atime;
|
||||||
tval[1].tv_sec = sbp->st_mtime;
|
tval[1].tv_sec = sbp->st_mtime;
|
||||||
|
Loading…
Reference in New Issue
Block a user