diff options
author | Alan Modra <amodra@gmail.com> | 2021-02-23 12:10:58 +1030 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2021-02-24 09:34:42 +1030 |
commit | c42c71a1527dd70417d3966dce7ba9edbcf4bdb4 (patch) | |
tree | c84495ca493b5b03e8e144701fcc276a01d736d5 /binutils/rename.c | |
parent | cca8873dd5a6015d5557ea44bc1ea9c252435a29 (diff) | |
download | binutils-c42c71a1527dd70417d3966dce7ba9edbcf4bdb4.zip binutils-c42c71a1527dd70417d3966dce7ba9edbcf4bdb4.tar.gz binutils-c42c71a1527dd70417d3966dce7ba9edbcf4bdb4.tar.bz2 |
Use make_tempname file descriptor in smart_rename
This patch makes use of the temp file descriptor in smart_rename
rather than reopening the file. I don't believe there is a security
issue in reopening the file, but this way is one less directory
operation. The patch also attempts to preserve S_ISUID and S_ISGID.
PR 27456
* bucomm.h (smart_rename): Update prototype.
* rename.c (smart_rename): Add fromfd and preserve_dates params.
Pass fromfd and target_stat to simple_copy. Call set_times
when preserve_dates.
(simple_copy): Accept fromfd rather than from filename. Add
target_stat param. Rewind fromfd rather than opening. Open
"to" file without O_CREAT. Try to preserve S_ISUID and S_ISGID.
* ar.c (write_archive): Rename ofd to tmpfd. Dup tmpfd before
closing output temp file, and pass tmpfd to smart_rename.
* arsup.c (temp_fd): Rename from real_fd.
(ar_save): Dup temp_fd and pass to smart_rename.
* objcopy.c (strip_main, copy_main): Likewise, and pass
preserve_dates.
Diffstat (limited to 'binutils/rename.c')
-rw-r--r-- | binutils/rename.c | 35 |
1 files changed, 21 insertions, 14 deletions
diff --git a/binutils/rename.c b/binutils/rename.c index 72a9323..f688f35 100644 --- a/binutils/rename.c +++ b/binutils/rename.c @@ -31,24 +31,21 @@ /* The number of bytes to copy at once. */ #define COPY_BUF 8192 -/* Copy file FROM to file TO, performing no translations. +/* Copy file FROMFD to file TO, performing no translations. Return 0 if ok, -1 if error. */ static int -simple_copy (const char *from, const char *to) +simple_copy (int fromfd, const char *to, struct stat *target_stat) { - int fromfd, tofd, nread; + int tofd, nread; int saved; char buf[COPY_BUF]; - fromfd = open (from, O_RDONLY | O_BINARY); - if (fromfd < 0) + if (fromfd < 0 + || lseek (fromfd, 0, SEEK_SET) != 0) return -1; -#ifdef O_CREAT - tofd = open (to, O_CREAT | O_WRONLY | O_TRUNC | O_BINARY, 0777); -#else - tofd = creat (to, 0777); -#endif + + tofd = open (to, O_WRONLY | O_TRUNC | O_BINARY); if (tofd < 0) { saved = errno; @@ -56,6 +53,7 @@ simple_copy (const char *from, const char *to) errno = saved; return -1; } + while ((nread = read (fromfd, buf, sizeof buf)) > 0) { if (write (tofd, buf, nread) != nread) @@ -67,7 +65,16 @@ simple_copy (const char *from, const char *to) return -1; } } + saved = errno; + +#if !defined (_WIN32) || defined (__CYGWIN32__) + /* Writing to a setuid/setgid file may clear S_ISUID and S_ISGID. + Try to restore them, ignoring failure. */ + if (target_stat != NULL) + fchmod (tofd, target_stat->st_mode); +#endif + close (fromfd); close (tofd); if (nread < 0) @@ -118,17 +125,17 @@ set_times (const char *destination, const struct stat *statbuf) various systems. So now we just copy. */ int -smart_rename (const char *from, const char *to, - struct stat *target_stat) +smart_rename (const char *from, const char *to, int fromfd, + struct stat *target_stat, bfd_boolean preserve_dates) { int ret; - ret = simple_copy (from, to); + ret = simple_copy (fromfd, to, target_stat); if (ret != 0) non_fatal (_("unable to copy file '%s'; reason: %s"), to, strerror (errno)); - if (target_stat != NULL) + if (preserve_dates) set_times (to, target_stat); unlink (from); |