aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2021-03-16 08:53:02 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2021-03-16 08:53:02 +0000
commit87a238b94eb2da20a8f0ccb0fb726992ea682739 (patch)
treef01f5289bd5c7d4ce31e793f817d8958de9b4d70
parent340afa9d22bae29c616b5e449a2e4e781fb70bac (diff)
parent32380c5430cdf3fd285272d709fcbf72ec237cba (diff)
downloadtoybox-87a238b94eb2da20a8f0ccb0fb726992ea682739.tar.gz
Merge remote-tracking branch 'toybox/master' into HEAD am: 7b76a4f414 am: 935eafc9a6 am: 32380c5430
Original change: https://android-review.googlesource.com/c/platform/external/toybox/+/1639371 Change-Id: Ibd60d202458d3bb1eccb297667c69c827a456b83
-rw-r--r--lib/portability.c3
-rwxr-xr-xtests/chmod.test5
-rw-r--r--toys/posix/chmod.c2
-rw-r--r--toys/posix/cp.c21
4 files changed, 19 insertions, 12 deletions
diff --git a/lib/portability.c b/lib/portability.c
index 0c364c29..f3c3c251 100644
--- a/lib/portability.c
+++ b/lib/portability.c
@@ -622,12 +622,13 @@ long long sendfile_len(int in, int out, long long bytes, long long *consumed)
len = bytes-total;
if (bytes<0 || len>sizeof(libbuf)) len = sizeof(libbuf);
+ errno = 0;
#if CFG_TOYBOX_COPYFILERANGE
len = copy_file_range(in, 0, out, 0, bytes, 0);
#else
ww = len = read(in, libbuf, len);
#endif
- if (!len && errno==EAGAIN) continue;
+ if (len<1 && errno==EAGAIN) continue;
if (len<1) break;
if (consumed) *consumed += len;
if (ww && writeall(out, libbuf, len) != len) return -1;
diff --git a/tests/chmod.test b/tests/chmod.test
index cd4f8100..6c4de0c0 100755
--- a/tests/chmod.test
+++ b/tests/chmod.test
@@ -115,6 +115,11 @@ unset SKIP
chtest +t "drwxr-xr-t\n-rw-r--r-T\n"
chtest a=r+w+x "drwxrwxrwx\n-rwxrwxrwx\n"
+# (chtest starts off with a directory that's +x...)
+testing "+X" \
+ "mkdir -m 000 Xd && touch Xf && chmod +X Xd Xf && ls -ld Xd Xf | cut -d' ' -f 1" \
+ "d--x--x--x\n-rw-r--r--\n" "" ""
+
mkdir foo
ln -s bar foo/baz
# If you explicitly ask us, we'll try (and fail) to chmod a symlink.
diff --git a/toys/posix/chmod.c b/toys/posix/chmod.c
index 2cdda951..ef74c4fa 100644
--- a/toys/posix/chmod.c
+++ b/toys/posix/chmod.c
@@ -50,7 +50,7 @@ static int do_chmod(struct dirtree *try)
// symlinks mentioned directly as arguments. We'll fail, of course,
// but that's what you asked for in that case.
} else {
- mode = string_to_mode(TT.mode, try->st.st_mode & ~S_IFMT);
+ mode = string_to_mode(TT.mode, try->st.st_mode) & ~S_IFMT;
if (FLAG(v)) {
char *s = dirtree_path(try, 0);
diff --git a/toys/posix/cp.c b/toys/posix/cp.c
index 56fbadf9..d98c2ae7 100644
--- a/toys/posix/cp.c
+++ b/toys/posix/cp.c
@@ -412,11 +412,11 @@ void cp_main(void)
// Loop through sources
for (i=0; i<toys.optc; i++) {
- char *src = toys.optargs[i], *trail = src;
- int rc = 1;
+ char *src = toys.optargs[i], *trail;
+ int send = 1;
- while (*++trail);
- if (*--trail == '/') *trail = 0;
+ if (!(trail = strrchr(src, '/')) || trail[1]) trail = 0;
+ else while (trail>src && *trail=='/') *trail-- = 0;
if (destdir) {
char *s = FLAG(D) ? src : getbasename(src);
@@ -433,6 +433,7 @@ void cp_main(void)
}
} else TT.destname = destname;
+ // "mv across devices" triggers cp fallback path, so set that as default
errno = EXDEV;
if (CFG_MV && toys.which->name[0] == 'm') {
int force = FLAG(f), no_clobber = FLAG(n);
@@ -446,18 +447,18 @@ void cp_main(void)
// _else_) but I don't care.
if (exists && (FLAG(i) || (!(st.st_mode & 0222) && isatty(0)))) {
fprintf(stderr, "%s: overwrite '%s'", toys.which->name, TT.destname);
- if (!yesno(0)) rc = 0;
+ if (!yesno(0)) send = 0;
else unlink(TT.destname);
}
// if -n and dest exists, don't try to rename() or copy
- if (exists && no_clobber) rc = 0;
+ if (exists && no_clobber) send = 0;
}
- if (rc) rc = rename(src, TT.destname);
- if (errno && !*trail) *trail = '/';
+ if (send) send = rename(src, TT.destname);
+ if (trail) trail[1] = '/';
}
- // Copy if we didn't mv, skipping nonexistent sources
- if (rc) {
+ // Copy if we didn't mv or hit an error, skipping nonexistent sources
+ if (send) {
if (errno!=EXDEV || dirtree_flagread(src, DIRTREE_SHUTUP+
DIRTREE_SYMFOLLOW*!!(FLAG(H)||FLAG(L)), TT.callback))
perror_msg("bad '%s'", src);