aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2021-04-12 21:23:31 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2021-04-12 21:23:31 +0000
commit1fa0602e27013df395e2d13c7b5e36269afd7edf (patch)
treee437e1284d484aa28b795fd0325867e9b5c75e2d
parent8f417134fc2653c51a18ead0c799d3f059acf2bc (diff)
parentb9bece4ecdc6105812b2b71e73022094d2cc9079 (diff)
downloadtoybox-1fa0602e27013df395e2d13c7b5e36269afd7edf.tar.gz
Merge remote-tracking branch 'toybox/master' into HEAD am: 937df7b865 am: b9bece4ecd
Original change: https://android-review.googlesource.com/c/platform/external/toybox/+/1673746 Change-Id: I1e9cf524bd444c80fc8200ef7d414fa0820ca53f
-rw-r--r--Config.in2
-rw-r--r--android/device/generated/flags.h22
-rw-r--r--android/device/generated/globals.h7
-rw-r--r--android/device/generated/help.h4
-rw-r--r--android/device/generated/newtoys.h2
-rw-r--r--android/linux/generated/flags.h22
-rw-r--r--android/linux/generated/globals.h7
-rw-r--r--android/linux/generated/help.h4
-rw-r--r--android/linux/generated/newtoys.h2
-rw-r--r--android/mac/generated/flags.h22
-rw-r--r--android/mac/generated/globals.h7
-rw-r--r--android/mac/generated/help.h4
-rw-r--r--android/mac/generated/newtoys.h2
-rw-r--r--lib/xwrap.c8
-rwxr-xr-xtests/cp.test5
-rw-r--r--toys/pending/readelf.c14
-rw-r--r--toys/pending/sh.c105
-rw-r--r--toys/posix/cp.c7
18 files changed, 146 insertions, 100 deletions
diff --git a/Config.in b/Config.in
index 27948ad3..b626f3c1 100644
--- a/Config.in
+++ b/Config.in
@@ -182,6 +182,6 @@ config TOYBOX_FORCE_NOMMU
to force every program to either include all nommu code in every
instance ever built, or drop nommu support altogether.
- Building a toolchain scripts/mcm-buildall.sh patches musl to fix this.
+ Building a scripts/mcm-buildall.sh toolchain patches musl to fix this.
endmenu
diff --git a/android/device/generated/flags.h b/android/device/generated/flags.h
index d0fa452b..9c544272 100644
--- a/android/device/generated/flags.h
+++ b/android/device/generated/flags.h
@@ -381,9 +381,9 @@
#undef FOR_count
#endif
-// cp <1(preserve):;D(parents)RHLPprdaslvnF(remove-destination)fit:T[-HLPd][-ni] <1(preserve):;D(parents)RHLPprdaslvnF(remove-destination)fit:T[-HLPd][-ni]
+// cp <1(preserve):;D(parents)RHLPprudaslvnF(remove-destination)fit:T[-HLPd][-niu] <1(preserve):;D(parents)RHLPprudaslvnF(remove-destination)fit:T[-HLPd][-niu]
#undef OPTSTR_cp
-#define OPTSTR_cp "<1(preserve):;D(parents)RHLPprdaslvnF(remove-destination)fit:T[-HLPd][-ni]"
+#define OPTSTR_cp "<1(preserve):;D(parents)RHLPprudaslvnF(remove-destination)fit:T[-HLPd][-niu]"
#ifdef CLEANUP_cp
#undef CLEANUP_cp
#undef FOR_cp
@@ -398,6 +398,7 @@
#undef FLAG_s
#undef FLAG_a
#undef FLAG_d
+#undef FLAG_u
#undef FLAG_r
#undef FLAG_p
#undef FLAG_P
@@ -3924,14 +3925,15 @@
#define FLAG_s (1<<8)
#define FLAG_a (1<<9)
#define FLAG_d (1<<10)
-#define FLAG_r (1<<11)
-#define FLAG_p (1<<12)
-#define FLAG_P (1<<13)
-#define FLAG_L (1<<14)
-#define FLAG_H (1<<15)
-#define FLAG_R (1<<16)
-#define FLAG_D (1<<17)
-#define FLAG_preserve (1<<18)
+#define FLAG_u (1<<11)
+#define FLAG_r (1<<12)
+#define FLAG_p (1<<13)
+#define FLAG_P (1<<14)
+#define FLAG_L (1<<15)
+#define FLAG_H (1<<16)
+#define FLAG_R (1<<17)
+#define FLAG_D (1<<18)
+#define FLAG_preserve (1<<19)
#endif
#ifdef FOR_cpio
diff --git a/android/device/generated/globals.h b/android/device/generated/globals.h
index 2211732f..f0e13a80 100644
--- a/android/device/generated/globals.h
+++ b/android/device/generated/globals.h
@@ -849,11 +849,11 @@ struct sh_data {
} exec;
};
- // keep ifs here: used to work around compiler limitation in run_command()
- char *ifs, *isexec, *wcpat;
+ // keep SECONDS here: used to work around compiler limitation in run_command()
+ long long SECONDS;
+ char *isexec, *wcpat;
unsigned options, jobcnt, LINENO;
int hfd, pid, bangpid, varslen, cdcount, srclvl, recursion;
- long long SECONDS;
// FUNCTION transplant pipelines from place to place?
// function keyword can have pointer to function struct? Still refcnt?
@@ -884,6 +884,7 @@ struct sh_data {
// struct sh_function *func;
struct sh_pipeline *pl;
+ char *ifs;
int varslen;
struct sh_arg arg;
struct arg_list *delete;
diff --git a/android/device/generated/help.h b/android/device/generated/help.h
index 6a403233..68769532 100644
--- a/android/device/generated/help.h
+++ b/android/device/generated/help.h
@@ -1,4 +1,4 @@
-#define HELP_toybox_force_nommu "When using musl-libc on a nommu system, you'll need to say \"y\" here\nunless you used the patch in the mcm-buildall.sh script. You can also\nsay \"y\" here to test the nommu codepaths on an mmu system.\n\nA nommu system can't use fork(), it can only vfork() which suspends\nthe parent until the child calls exec() or exits. When a program\nneeds a second instance of itself to run specific code at the same\ntime as the parent, it must use a more complicated approach (such as\nexec(\"/proc/self/exe\") then pass data to the new child through a pipe)\nwhich is larger and slower, especially for things like toysh subshells\nthat need to duplicate a lot of internal state in the child process\nfork() gives you for free.\n\nLibraries like uclibc omit fork() on nommu systems, allowing\ncompile-time probes to select which codepath to use. But musl\nintentionally includes a broken version of fork() that always returns\n-ENOSYS on nommu systems, and goes out of its way to prevent any\ncross-compile compatible compile-time probes for a nommu system.\n(It doesn't even #define __MUSL__ in features.h.) Musl does this\ndespite the fact that a nommu system can't even run standard ELF\nbinaries (requiring specially packaged executables) because it wants\nto force every program to either include all nommu code in every\ninstance ever built, or drop nommu support altogether.\n\nBuilding a toolchain scripts/mcm-buildall.sh patches musl to fix this."
+#define HELP_toybox_force_nommu "When using musl-libc on a nommu system, you'll need to say \"y\" here\nunless you used the patch in the mcm-buildall.sh script. You can also\nsay \"y\" here to test the nommu codepaths on an mmu system.\n\nA nommu system can't use fork(), it can only vfork() which suspends\nthe parent until the child calls exec() or exits. When a program\nneeds a second instance of itself to run specific code at the same\ntime as the parent, it must use a more complicated approach (such as\nexec(\"/proc/self/exe\") then pass data to the new child through a pipe)\nwhich is larger and slower, especially for things like toysh subshells\nthat need to duplicate a lot of internal state in the child process\nfork() gives you for free.\n\nLibraries like uclibc omit fork() on nommu systems, allowing\ncompile-time probes to select which codepath to use. But musl\nintentionally includes a broken version of fork() that always returns\n-ENOSYS on nommu systems, and goes out of its way to prevent any\ncross-compile compatible compile-time probes for a nommu system.\n(It doesn't even #define __MUSL__ in features.h.) Musl does this\ndespite the fact that a nommu system can't even run standard ELF\nbinaries (requiring specially packaged executables) because it wants\nto force every program to either include all nommu code in every\ninstance ever built, or drop nommu support altogether.\n\nBuilding a scripts/mcm-buildall.sh toolchain patches musl to fix this."
#define HELP_toybox_uid_usr "When commands like useradd/groupadd allocate user IDs, start here."
@@ -612,7 +612,7 @@
#define HELP_mv "usage: mv [-finTv] [-t TARGET] SOURCE... [DEST]\n\n-f Force copy by deleting destination file\n-i Interactive, prompt before overwriting existing DEST\n-n No clobber (don't overwrite DEST)\n-t Move to TARGET dir (no DEST)\n-T DEST always treated as file, max 2 arguments\n-v Verbose"
-#define HELP_cp "usage: cp [-adfHiLlnPpRrsTv] [--preserve=motcxa] [-t TARGET] SOURCE... [DEST]\n\nCopy files from SOURCE to DEST. If more than one SOURCE, DEST must\nbe a directory.\n\n-a Same as -dpr\n-D Create leading dirs under DEST (--parents)\n-d Don't dereference symlinks\n-F Delete any existing destination file first (--remove-destination)\n-f Delete destination files we can't write to\n-H Follow symlinks listed on command line\n-i Interactive, prompt before overwriting existing DEST\n-L Follow all symlinks\n-l Hard link instead of copy\n-n No clobber (don't overwrite DEST)\n-P Do not follow symlinks\n-p Preserve timestamps, ownership, and mode\n-R Recurse into subdirectories (DEST must be a directory)\n-r Synonym for -R\n-s Symlink instead of copy\n-t Copy to TARGET dir (no DEST)\n-T DEST always treated as file, max 2 arguments\n-v Verbose\n\nArguments to --preserve are the first letter(s) of:\n\n mode - permissions (ignore umask for rwx, copy suid and sticky bit)\n ownership - user and group\n timestamps - file creation, modification, and access times.\n context - security context\n xattr - extended attributes\n all - all of the above"
+#define HELP_cp "usage: cp [-adfHiLlnPpRrsTv] [--preserve=motcxa] [-t TARGET] SOURCE... [DEST]\n\nCopy files from SOURCE to DEST. If more than one SOURCE, DEST must\nbe a directory.\n\n-a Same as -dpr\n-D Create leading dirs under DEST (--parents)\n-d Don't dereference symlinks\n-F Delete any existing destination file first (--remove-destination)\n-f Delete destination files we can't write to\n-H Follow symlinks listed on command line\n-i Interactive, prompt before overwriting existing DEST\n-L Follow all symlinks\n-l Hard link instead of copy\n-n No clobber (don't overwrite DEST)\n-u Update (keep newest mtime)\n-P Do not follow symlinks\n-p Preserve timestamps, ownership, and mode\n-R Recurse into subdirectories (DEST must be a directory)\n-r Synonym for -R\n-s Symlink instead of copy\n-t Copy to TARGET dir (no DEST)\n-T DEST always treated as file, max 2 arguments\n-v Verbose\n\nArguments to --preserve are the first letter(s) of:\n\n mode - permissions (ignore umask for rwx, copy suid and sticky bit)\n ownership - user and group\n timestamps - file creation, modification, and access times.\n context - security context\n xattr - extended attributes\n all - all of the above"
#define HELP_comm "usage: comm [-123] FILE1 FILE2\n\nRead FILE1 and FILE2, which should be ordered, and produce three text\ncolumns as output: lines only in FILE1; lines only in FILE2; and lines\nin both files. Filename \"-\" is a synonym for stdin.\n\n-1 Suppress the output column of lines unique to FILE1\n-2 Suppress the output column of lines unique to FILE2\n-3 Suppress the output column of lines duplicated in FILE1 and FILE2"
diff --git a/android/device/generated/newtoys.h b/android/device/generated/newtoys.h
index 8513181b..6a39d804 100644
--- a/android/device/generated/newtoys.h
+++ b/android/device/generated/newtoys.h
@@ -42,7 +42,7 @@ USE_CLEAR(NEWTOY(clear, NULL, TOYFLAG_USR|TOYFLAG_BIN))
USE_CMP(NEWTOY(cmp, "<1>2ls(silent)(quiet)[!ls]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)))
USE_COMM(NEWTOY(comm, "<2>2321", TOYFLAG_USR|TOYFLAG_BIN))
USE_COUNT(NEWTOY(count, NULL, TOYFLAG_USR|TOYFLAG_BIN))
-USE_CP(NEWTOY(cp, "<1(preserve):;D(parents)RHLPprdaslvnF(remove-destination)fit:T[-HLPd][-ni]", TOYFLAG_BIN))
+USE_CP(NEWTOY(cp, "<1(preserve):;D(parents)RHLPprudaslvnF(remove-destination)fit:T[-HLPd][-niu]", TOYFLAG_BIN))
USE_CPIO(NEWTOY(cpio, "(quiet)(no-preserve-owner)md(make-directories)uH:p|i|t|F:v(verbose)o|[!pio][!pot][!pF]", TOYFLAG_BIN))
USE_CRC32(NEWTOY(crc32, 0, TOYFLAG_BIN))
USE_CROND(NEWTOY(crond, "fbSl#<0=8d#<0L:c:[-bf][-LS][-ld]", TOYFLAG_USR|TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
diff --git a/android/linux/generated/flags.h b/android/linux/generated/flags.h
index 84944ce9..6dbebfee 100644
--- a/android/linux/generated/flags.h
+++ b/android/linux/generated/flags.h
@@ -381,9 +381,9 @@
#undef FOR_count
#endif
-// cp <1(preserve):;D(parents)RHLPprdaslvnF(remove-destination)fit:T[-HLPd][-ni] <1(preserve):;D(parents)RHLPprdaslvnF(remove-destination)fit:T[-HLPd][-ni]
+// cp <1(preserve):;D(parents)RHLPprudaslvnF(remove-destination)fit:T[-HLPd][-niu] <1(preserve):;D(parents)RHLPprudaslvnF(remove-destination)fit:T[-HLPd][-niu]
#undef OPTSTR_cp
-#define OPTSTR_cp "<1(preserve):;D(parents)RHLPprdaslvnF(remove-destination)fit:T[-HLPd][-ni]"
+#define OPTSTR_cp "<1(preserve):;D(parents)RHLPprudaslvnF(remove-destination)fit:T[-HLPd][-niu]"
#ifdef CLEANUP_cp
#undef CLEANUP_cp
#undef FOR_cp
@@ -398,6 +398,7 @@
#undef FLAG_s
#undef FLAG_a
#undef FLAG_d
+#undef FLAG_u
#undef FLAG_r
#undef FLAG_p
#undef FLAG_P
@@ -3924,14 +3925,15 @@
#define FLAG_s (1<<8)
#define FLAG_a (1<<9)
#define FLAG_d (1<<10)
-#define FLAG_r (1<<11)
-#define FLAG_p (1<<12)
-#define FLAG_P (1<<13)
-#define FLAG_L (1<<14)
-#define FLAG_H (1<<15)
-#define FLAG_R (1<<16)
-#define FLAG_D (1<<17)
-#define FLAG_preserve (1<<18)
+#define FLAG_u (1<<11)
+#define FLAG_r (1<<12)
+#define FLAG_p (1<<13)
+#define FLAG_P (1<<14)
+#define FLAG_L (1<<15)
+#define FLAG_H (1<<16)
+#define FLAG_R (1<<17)
+#define FLAG_D (1<<18)
+#define FLAG_preserve (1<<19)
#endif
#ifdef FOR_cpio
diff --git a/android/linux/generated/globals.h b/android/linux/generated/globals.h
index 2211732f..f0e13a80 100644
--- a/android/linux/generated/globals.h
+++ b/android/linux/generated/globals.h
@@ -849,11 +849,11 @@ struct sh_data {
} exec;
};
- // keep ifs here: used to work around compiler limitation in run_command()
- char *ifs, *isexec, *wcpat;
+ // keep SECONDS here: used to work around compiler limitation in run_command()
+ long long SECONDS;
+ char *isexec, *wcpat;
unsigned options, jobcnt, LINENO;
int hfd, pid, bangpid, varslen, cdcount, srclvl, recursion;
- long long SECONDS;
// FUNCTION transplant pipelines from place to place?
// function keyword can have pointer to function struct? Still refcnt?
@@ -884,6 +884,7 @@ struct sh_data {
// struct sh_function *func;
struct sh_pipeline *pl;
+ char *ifs;
int varslen;
struct sh_arg arg;
struct arg_list *delete;
diff --git a/android/linux/generated/help.h b/android/linux/generated/help.h
index eebbf545..b2fde269 100644
--- a/android/linux/generated/help.h
+++ b/android/linux/generated/help.h
@@ -1,4 +1,4 @@
-#define HELP_toybox_force_nommu "When using musl-libc on a nommu system, you'll need to say \"y\" here\nunless you used the patch in the mcm-buildall.sh script. You can also\nsay \"y\" here to test the nommu codepaths on an mmu system.\n\nA nommu system can't use fork(), it can only vfork() which suspends\nthe parent until the child calls exec() or exits. When a program\nneeds a second instance of itself to run specific code at the same\ntime as the parent, it must use a more complicated approach (such as\nexec(\"/proc/self/exe\") then pass data to the new child through a pipe)\nwhich is larger and slower, especially for things like toysh subshells\nthat need to duplicate a lot of internal state in the child process\nfork() gives you for free.\n\nLibraries like uclibc omit fork() on nommu systems, allowing\ncompile-time probes to select which codepath to use. But musl\nintentionally includes a broken version of fork() that always returns\n-ENOSYS on nommu systems, and goes out of its way to prevent any\ncross-compile compatible compile-time probes for a nommu system.\n(It doesn't even #define __MUSL__ in features.h.) Musl does this\ndespite the fact that a nommu system can't even run standard ELF\nbinaries (requiring specially packaged executables) because it wants\nto force every program to either include all nommu code in every\ninstance ever built, or drop nommu support altogether.\n\nBuilding a toolchain scripts/mcm-buildall.sh patches musl to fix this."
+#define HELP_toybox_force_nommu "When using musl-libc on a nommu system, you'll need to say \"y\" here\nunless you used the patch in the mcm-buildall.sh script. You can also\nsay \"y\" here to test the nommu codepaths on an mmu system.\n\nA nommu system can't use fork(), it can only vfork() which suspends\nthe parent until the child calls exec() or exits. When a program\nneeds a second instance of itself to run specific code at the same\ntime as the parent, it must use a more complicated approach (such as\nexec(\"/proc/self/exe\") then pass data to the new child through a pipe)\nwhich is larger and slower, especially for things like toysh subshells\nthat need to duplicate a lot of internal state in the child process\nfork() gives you for free.\n\nLibraries like uclibc omit fork() on nommu systems, allowing\ncompile-time probes to select which codepath to use. But musl\nintentionally includes a broken version of fork() that always returns\n-ENOSYS on nommu systems, and goes out of its way to prevent any\ncross-compile compatible compile-time probes for a nommu system.\n(It doesn't even #define __MUSL__ in features.h.) Musl does this\ndespite the fact that a nommu system can't even run standard ELF\nbinaries (requiring specially packaged executables) because it wants\nto force every program to either include all nommu code in every\ninstance ever built, or drop nommu support altogether.\n\nBuilding a scripts/mcm-buildall.sh toolchain patches musl to fix this."
#define HELP_toybox_uid_usr "When commands like useradd/groupadd allocate user IDs, start here."
@@ -618,7 +618,7 @@
#define HELP_mv "usage: mv [-finTv] [-t TARGET] SOURCE... [DEST]\n\n-f Force copy by deleting destination file\n-i Interactive, prompt before overwriting existing DEST\n-n No clobber (don't overwrite DEST)\n-t Move to TARGET dir (no DEST)\n-T DEST always treated as file, max 2 arguments\n-v Verbose"
-#define HELP_cp "usage: cp [-adfHiLlnPpRrsTv] [--preserve=motcxa] [-t TARGET] SOURCE... [DEST]\n\nCopy files from SOURCE to DEST. If more than one SOURCE, DEST must\nbe a directory.\n\n-a Same as -dpr\n-D Create leading dirs under DEST (--parents)\n-d Don't dereference symlinks\n-F Delete any existing destination file first (--remove-destination)\n-f Delete destination files we can't write to\n-H Follow symlinks listed on command line\n-i Interactive, prompt before overwriting existing DEST\n-L Follow all symlinks\n-l Hard link instead of copy\n-n No clobber (don't overwrite DEST)\n-P Do not follow symlinks\n-p Preserve timestamps, ownership, and mode\n-R Recurse into subdirectories (DEST must be a directory)\n-r Synonym for -R\n-s Symlink instead of copy\n-t Copy to TARGET dir (no DEST)\n-T DEST always treated as file, max 2 arguments\n-v Verbose\n\nArguments to --preserve are the first letter(s) of:\n\n mode - permissions (ignore umask for rwx, copy suid and sticky bit)\n ownership - user and group\n timestamps - file creation, modification, and access times.\n context - security context\n xattr - extended attributes\n all - all of the above"
+#define HELP_cp "usage: cp [-adfHiLlnPpRrsTv] [--preserve=motcxa] [-t TARGET] SOURCE... [DEST]\n\nCopy files from SOURCE to DEST. If more than one SOURCE, DEST must\nbe a directory.\n\n-a Same as -dpr\n-D Create leading dirs under DEST (--parents)\n-d Don't dereference symlinks\n-F Delete any existing destination file first (--remove-destination)\n-f Delete destination files we can't write to\n-H Follow symlinks listed on command line\n-i Interactive, prompt before overwriting existing DEST\n-L Follow all symlinks\n-l Hard link instead of copy\n-n No clobber (don't overwrite DEST)\n-u Update (keep newest mtime)\n-P Do not follow symlinks\n-p Preserve timestamps, ownership, and mode\n-R Recurse into subdirectories (DEST must be a directory)\n-r Synonym for -R\n-s Symlink instead of copy\n-t Copy to TARGET dir (no DEST)\n-T DEST always treated as file, max 2 arguments\n-v Verbose\n\nArguments to --preserve are the first letter(s) of:\n\n mode - permissions (ignore umask for rwx, copy suid and sticky bit)\n ownership - user and group\n timestamps - file creation, modification, and access times.\n context - security context\n xattr - extended attributes\n all - all of the above"
#define HELP_comm "usage: comm [-123] FILE1 FILE2\n\nRead FILE1 and FILE2, which should be ordered, and produce three text\ncolumns as output: lines only in FILE1; lines only in FILE2; and lines\nin both files. Filename \"-\" is a synonym for stdin.\n\n-1 Suppress the output column of lines unique to FILE1\n-2 Suppress the output column of lines unique to FILE2\n-3 Suppress the output column of lines duplicated in FILE1 and FILE2"
diff --git a/android/linux/generated/newtoys.h b/android/linux/generated/newtoys.h
index 8513181b..6a39d804 100644
--- a/android/linux/generated/newtoys.h
+++ b/android/linux/generated/newtoys.h
@@ -42,7 +42,7 @@ USE_CLEAR(NEWTOY(clear, NULL, TOYFLAG_USR|TOYFLAG_BIN))
USE_CMP(NEWTOY(cmp, "<1>2ls(silent)(quiet)[!ls]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)))
USE_COMM(NEWTOY(comm, "<2>2321", TOYFLAG_USR|TOYFLAG_BIN))
USE_COUNT(NEWTOY(count, NULL, TOYFLAG_USR|TOYFLAG_BIN))
-USE_CP(NEWTOY(cp, "<1(preserve):;D(parents)RHLPprdaslvnF(remove-destination)fit:T[-HLPd][-ni]", TOYFLAG_BIN))
+USE_CP(NEWTOY(cp, "<1(preserve):;D(parents)RHLPprudaslvnF(remove-destination)fit:T[-HLPd][-niu]", TOYFLAG_BIN))
USE_CPIO(NEWTOY(cpio, "(quiet)(no-preserve-owner)md(make-directories)uH:p|i|t|F:v(verbose)o|[!pio][!pot][!pF]", TOYFLAG_BIN))
USE_CRC32(NEWTOY(crc32, 0, TOYFLAG_BIN))
USE_CROND(NEWTOY(crond, "fbSl#<0=8d#<0L:c:[-bf][-LS][-ld]", TOYFLAG_USR|TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
diff --git a/android/mac/generated/flags.h b/android/mac/generated/flags.h
index d3a16fe3..741e1413 100644
--- a/android/mac/generated/flags.h
+++ b/android/mac/generated/flags.h
@@ -381,9 +381,9 @@
#undef FOR_count
#endif
-// cp <1(preserve):;D(parents)RHLPprdaslvnF(remove-destination)fit:T[-HLPd][-ni] <1(preserve):;D(parents)RHLPprdaslvnF(remove-destination)fit:T[-HLPd][-ni]
+// cp <1(preserve):;D(parents)RHLPprudaslvnF(remove-destination)fit:T[-HLPd][-niu] <1(preserve):;D(parents)RHLPprudaslvnF(remove-destination)fit:T[-HLPd][-niu]
#undef OPTSTR_cp
-#define OPTSTR_cp "<1(preserve):;D(parents)RHLPprdaslvnF(remove-destination)fit:T[-HLPd][-ni]"
+#define OPTSTR_cp "<1(preserve):;D(parents)RHLPprudaslvnF(remove-destination)fit:T[-HLPd][-niu]"
#ifdef CLEANUP_cp
#undef CLEANUP_cp
#undef FOR_cp
@@ -398,6 +398,7 @@
#undef FLAG_s
#undef FLAG_a
#undef FLAG_d
+#undef FLAG_u
#undef FLAG_r
#undef FLAG_p
#undef FLAG_P
@@ -3924,14 +3925,15 @@
#define FLAG_s (1<<8)
#define FLAG_a (1<<9)
#define FLAG_d (1<<10)
-#define FLAG_r (1<<11)
-#define FLAG_p (1<<12)
-#define FLAG_P (1<<13)
-#define FLAG_L (1<<14)
-#define FLAG_H (1<<15)
-#define FLAG_R (1<<16)
-#define FLAG_D (1<<17)
-#define FLAG_preserve (1<<18)
+#define FLAG_u (1<<11)
+#define FLAG_r (1<<12)
+#define FLAG_p (1<<13)
+#define FLAG_P (1<<14)
+#define FLAG_L (1<<15)
+#define FLAG_H (1<<16)
+#define FLAG_R (1<<17)
+#define FLAG_D (1<<18)
+#define FLAG_preserve (1<<19)
#endif
#ifdef FOR_cpio
diff --git a/android/mac/generated/globals.h b/android/mac/generated/globals.h
index 2211732f..f0e13a80 100644
--- a/android/mac/generated/globals.h
+++ b/android/mac/generated/globals.h
@@ -849,11 +849,11 @@ struct sh_data {
} exec;
};
- // keep ifs here: used to work around compiler limitation in run_command()
- char *ifs, *isexec, *wcpat;
+ // keep SECONDS here: used to work around compiler limitation in run_command()
+ long long SECONDS;
+ char *isexec, *wcpat;
unsigned options, jobcnt, LINENO;
int hfd, pid, bangpid, varslen, cdcount, srclvl, recursion;
- long long SECONDS;
// FUNCTION transplant pipelines from place to place?
// function keyword can have pointer to function struct? Still refcnt?
@@ -884,6 +884,7 @@ struct sh_data {
// struct sh_function *func;
struct sh_pipeline *pl;
+ char *ifs;
int varslen;
struct sh_arg arg;
struct arg_list *delete;
diff --git a/android/mac/generated/help.h b/android/mac/generated/help.h
index eebbf545..b2fde269 100644
--- a/android/mac/generated/help.h
+++ b/android/mac/generated/help.h
@@ -1,4 +1,4 @@
-#define HELP_toybox_force_nommu "When using musl-libc on a nommu system, you'll need to say \"y\" here\nunless you used the patch in the mcm-buildall.sh script. You can also\nsay \"y\" here to test the nommu codepaths on an mmu system.\n\nA nommu system can't use fork(), it can only vfork() which suspends\nthe parent until the child calls exec() or exits. When a program\nneeds a second instance of itself to run specific code at the same\ntime as the parent, it must use a more complicated approach (such as\nexec(\"/proc/self/exe\") then pass data to the new child through a pipe)\nwhich is larger and slower, especially for things like toysh subshells\nthat need to duplicate a lot of internal state in the child process\nfork() gives you for free.\n\nLibraries like uclibc omit fork() on nommu systems, allowing\ncompile-time probes to select which codepath to use. But musl\nintentionally includes a broken version of fork() that always returns\n-ENOSYS on nommu systems, and goes out of its way to prevent any\ncross-compile compatible compile-time probes for a nommu system.\n(It doesn't even #define __MUSL__ in features.h.) Musl does this\ndespite the fact that a nommu system can't even run standard ELF\nbinaries (requiring specially packaged executables) because it wants\nto force every program to either include all nommu code in every\ninstance ever built, or drop nommu support altogether.\n\nBuilding a toolchain scripts/mcm-buildall.sh patches musl to fix this."
+#define HELP_toybox_force_nommu "When using musl-libc on a nommu system, you'll need to say \"y\" here\nunless you used the patch in the mcm-buildall.sh script. You can also\nsay \"y\" here to test the nommu codepaths on an mmu system.\n\nA nommu system can't use fork(), it can only vfork() which suspends\nthe parent until the child calls exec() or exits. When a program\nneeds a second instance of itself to run specific code at the same\ntime as the parent, it must use a more complicated approach (such as\nexec(\"/proc/self/exe\") then pass data to the new child through a pipe)\nwhich is larger and slower, especially for things like toysh subshells\nthat need to duplicate a lot of internal state in the child process\nfork() gives you for free.\n\nLibraries like uclibc omit fork() on nommu systems, allowing\ncompile-time probes to select which codepath to use. But musl\nintentionally includes a broken version of fork() that always returns\n-ENOSYS on nommu systems, and goes out of its way to prevent any\ncross-compile compatible compile-time probes for a nommu system.\n(It doesn't even #define __MUSL__ in features.h.) Musl does this\ndespite the fact that a nommu system can't even run standard ELF\nbinaries (requiring specially packaged executables) because it wants\nto force every program to either include all nommu code in every\ninstance ever built, or drop nommu support altogether.\n\nBuilding a scripts/mcm-buildall.sh toolchain patches musl to fix this."
#define HELP_toybox_uid_usr "When commands like useradd/groupadd allocate user IDs, start here."
@@ -618,7 +618,7 @@
#define HELP_mv "usage: mv [-finTv] [-t TARGET] SOURCE... [DEST]\n\n-f Force copy by deleting destination file\n-i Interactive, prompt before overwriting existing DEST\n-n No clobber (don't overwrite DEST)\n-t Move to TARGET dir (no DEST)\n-T DEST always treated as file, max 2 arguments\n-v Verbose"
-#define HELP_cp "usage: cp [-adfHiLlnPpRrsTv] [--preserve=motcxa] [-t TARGET] SOURCE... [DEST]\n\nCopy files from SOURCE to DEST. If more than one SOURCE, DEST must\nbe a directory.\n\n-a Same as -dpr\n-D Create leading dirs under DEST (--parents)\n-d Don't dereference symlinks\n-F Delete any existing destination file first (--remove-destination)\n-f Delete destination files we can't write to\n-H Follow symlinks listed on command line\n-i Interactive, prompt before overwriting existing DEST\n-L Follow all symlinks\n-l Hard link instead of copy\n-n No clobber (don't overwrite DEST)\n-P Do not follow symlinks\n-p Preserve timestamps, ownership, and mode\n-R Recurse into subdirectories (DEST must be a directory)\n-r Synonym for -R\n-s Symlink instead of copy\n-t Copy to TARGET dir (no DEST)\n-T DEST always treated as file, max 2 arguments\n-v Verbose\n\nArguments to --preserve are the first letter(s) of:\n\n mode - permissions (ignore umask for rwx, copy suid and sticky bit)\n ownership - user and group\n timestamps - file creation, modification, and access times.\n context - security context\n xattr - extended attributes\n all - all of the above"
+#define HELP_cp "usage: cp [-adfHiLlnPpRrsTv] [--preserve=motcxa] [-t TARGET] SOURCE... [DEST]\n\nCopy files from SOURCE to DEST. If more than one SOURCE, DEST must\nbe a directory.\n\n-a Same as -dpr\n-D Create leading dirs under DEST (--parents)\n-d Don't dereference symlinks\n-F Delete any existing destination file first (--remove-destination)\n-f Delete destination files we can't write to\n-H Follow symlinks listed on command line\n-i Interactive, prompt before overwriting existing DEST\n-L Follow all symlinks\n-l Hard link instead of copy\n-n No clobber (don't overwrite DEST)\n-u Update (keep newest mtime)\n-P Do not follow symlinks\n-p Preserve timestamps, ownership, and mode\n-R Recurse into subdirectories (DEST must be a directory)\n-r Synonym for -R\n-s Symlink instead of copy\n-t Copy to TARGET dir (no DEST)\n-T DEST always treated as file, max 2 arguments\n-v Verbose\n\nArguments to --preserve are the first letter(s) of:\n\n mode - permissions (ignore umask for rwx, copy suid and sticky bit)\n ownership - user and group\n timestamps - file creation, modification, and access times.\n context - security context\n xattr - extended attributes\n all - all of the above"
#define HELP_comm "usage: comm [-123] FILE1 FILE2\n\nRead FILE1 and FILE2, which should be ordered, and produce three text\ncolumns as output: lines only in FILE1; lines only in FILE2; and lines\nin both files. Filename \"-\" is a synonym for stdin.\n\n-1 Suppress the output column of lines unique to FILE1\n-2 Suppress the output column of lines unique to FILE2\n-3 Suppress the output column of lines duplicated in FILE1 and FILE2"
diff --git a/android/mac/generated/newtoys.h b/android/mac/generated/newtoys.h
index 8513181b..6a39d804 100644
--- a/android/mac/generated/newtoys.h
+++ b/android/mac/generated/newtoys.h
@@ -42,7 +42,7 @@ USE_CLEAR(NEWTOY(clear, NULL, TOYFLAG_USR|TOYFLAG_BIN))
USE_CMP(NEWTOY(cmp, "<1>2ls(silent)(quiet)[!ls]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)))
USE_COMM(NEWTOY(comm, "<2>2321", TOYFLAG_USR|TOYFLAG_BIN))
USE_COUNT(NEWTOY(count, NULL, TOYFLAG_USR|TOYFLAG_BIN))
-USE_CP(NEWTOY(cp, "<1(preserve):;D(parents)RHLPprdaslvnF(remove-destination)fit:T[-HLPd][-ni]", TOYFLAG_BIN))
+USE_CP(NEWTOY(cp, "<1(preserve):;D(parents)RHLPprudaslvnF(remove-destination)fit:T[-HLPd][-niu]", TOYFLAG_BIN))
USE_CPIO(NEWTOY(cpio, "(quiet)(no-preserve-owner)md(make-directories)uH:p|i|t|F:v(verbose)o|[!pio][!pot][!pF]", TOYFLAG_BIN))
USE_CRC32(NEWTOY(crc32, 0, TOYFLAG_BIN))
USE_CROND(NEWTOY(crond, "fbSl#<0=8d#<0L:c:[-bf][-LS][-ld]", TOYFLAG_USR|TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
diff --git a/lib/xwrap.c b/lib/xwrap.c
index 607f3c61..64137da9 100644
--- a/lib/xwrap.c
+++ b/lib/xwrap.c
@@ -96,7 +96,6 @@ void *xrealloc(void *ptr, size_t size)
char *xstrndup(char *s, size_t n)
{
char *ret = strndup(s, n);
-
if (!ret) error_exit("xstrndup");
return ret;
@@ -127,8 +126,7 @@ char *xmprintf(char *format, ...)
va_copy(va2, va);
// How long is it?
- len = vsnprintf(0, 0, format, va);
- len++;
+ len = vsnprintf(0, 0, format, va)+1;
va_end(va);
// Allocate and do the sprintf()
@@ -225,8 +223,8 @@ pid_t __attribute__((returns_twice)) xvforkwrap(pid_t pid)
void xexec(char **argv)
{
// Only recurse to builtin when we have multiplexer and !vfork context.
- if (CFG_TOYBOX && !CFG_TOYBOX_NORECURSE && toys.stacktop && **argv != '/')
- toy_exec(argv);
+ if (CFG_TOYBOX && !CFG_TOYBOX_NORECURSE)
+ if (toys.stacktop && !strchr(*argv, '/')) toy_exec(argv);
execvp(argv[0], argv);
toys.exitval = 126+(errno == ENOENT);
diff --git a/tests/cp.test b/tests/cp.test
index 3fcea3be..b0d5d3a4 100755
--- a/tests/cp.test
+++ b/tests/cp.test
@@ -136,6 +136,11 @@ testing "-t one arg" 'cp -t sub/ input && cat sub/input' 'yes\n' 'yes\n' ''
toyonly testing "-Dt" 'cp -Dt sub2 input && cat sub2/input' 'and\n' 'and\n' ''
rm -rf sub sub2
+testing '-u1' 'echo one>one; sleep .1; echo two>two; cp -u one two; cat two' \
+ 'two\n' '' ''
+testing '-u2' 'echo two>two; sleep .1; echo one>one; cp -u one two; cat two' \
+ 'one\n' '' ''
+
# cp -r ../source destdir
# cp -r one/two/three missing
# cp -r one/two/three two
diff --git a/toys/pending/readelf.c b/toys/pending/readelf.c
index a8564a4d..e6e1623f 100644
--- a/toys/pending/readelf.c
+++ b/toys/pending/readelf.c
@@ -96,9 +96,11 @@ static int get_sh(unsigned i, struct sh *s)
s->addralign = elf_long(&shdr);
s->entsize = elf_long(&shdr);
- if (s->offset>TT.size || s->size>TT.size || s->offset>TT.size-s->size) {
- printf("Bad offset/size %llu/%llu for sh %d\n", s->offset, s->size, i);
- return 0;
+ if (s->type != 8) {
+ if (s->offset>TT.size || s->size>TT.size || s->offset>TT.size-s->size) {
+ printf("Bad offset/size %llu/%llu for sh %d\n", s->offset, s->size, i);
+ return 0;
+ }
}
if (!TT.shstrtab) s->name = "?";
@@ -425,7 +427,7 @@ static void scan_elf()
TT.shstrtabsz = shstr.size;
}
- w = 8*(TT.bits+1);
+ w = 8<<TT.bits;
if (FLAG(S)) {
if (!TT.shnum) printf("\nThere are no sections in this file.\n");
else {
@@ -435,7 +437,7 @@ static void scan_elf()
}
printf("\n"
"Section Headers:\n"
- " [Nr] %-20s %-14s %-*s %-6s %-6s ES Flg Lk Inf Al\n",
+ " [Nr] %-17s %-15s %-*s %-6s %-6s ES Flg Lk Inf Al\n",
"Name", "Type", w, "Address", "Off", "Size");
}
}
@@ -455,7 +457,7 @@ static void scan_elf()
char sh_flags[12] = {}, *p = sh_flags;
for (j=0; j<12; j++) if (s.flags&(1<<j)) *p++="WAXxMSILOTC"[j];
- printf(" [%2d] %-20s %-14s %0*llx %06llx %06llx %02llx %3s %2d %2d %2lld\n",
+ printf(" [%2d] %-17s %-15s %0*llx %06llx %06llx %02llx %3s %2d %2d %2lld\n",
i, s.name, sh_type(s.type), w, s.addr, s.offset, s.size,
s.entsize, sh_flags, s.link, s.info, s.addralign);
}
diff --git a/toys/pending/sh.c b/toys/pending/sh.c
index 7096d135..0ccaa792 100644
--- a/toys/pending/sh.c
+++ b/toys/pending/sh.c
@@ -216,11 +216,11 @@ GLOBALS(
} exec;
};
- // keep ifs here: used to work around compiler limitation in run_command()
- char *ifs, *isexec, *wcpat;
+ // keep SECONDS here: used to work around compiler limitation in run_command()
+ long long SECONDS;
+ char *isexec, *wcpat;
unsigned options, jobcnt, LINENO;
int hfd, pid, bangpid, varslen, cdcount, srclvl, recursion;
- long long SECONDS;
// FUNCTION transplant pipelines from place to place?
// function keyword can have pointer to function struct? Still refcnt?
@@ -251,6 +251,7 @@ GLOBALS(
// struct sh_function *func;
struct sh_pipeline *pl;
+ char *ifs;
int varslen;
struct sh_arg arg;
struct arg_list *delete;
@@ -399,6 +400,7 @@ static struct sh_vars *addvar(char *s, struct sh_fcall *ff)
{
if (!(ff->varslen&31))
ff->vars = xrealloc(ff->vars, (ff->varslen+32)*sizeof(*ff->vars));
+ if (!s) return ff->vars;
ff->vars[ff->varslen].flags = 0;
ff->vars[ff->varslen].str = s;
@@ -421,9 +423,10 @@ long long do_math(char **s)
// ft
static struct sh_vars *setvar(char *s)
{
- int len = varend(s)-s;
- long flags;
+ struct sh_fcall *ff;
struct sh_vars *var;
+ long flags;
+ int len = varend(s)-s;
if (s[len] != '=') {
error_msg("bad setvar %s\n", s);
@@ -431,8 +434,10 @@ static struct sh_vars *setvar(char *s)
return 0;
}
- if (!strncmp(s, "IFS=", 4)) TT.ifs = s+4;
- if (!(var = findvar(s, 0))) return addvar(s, TT.ff->prev);
+ if (!(var = findvar(s, &ff))) ff = TT.ff->prev;
+ if (!strncmp(s, "IFS=", 4))
+ do ff->ifs = s+4; while ((ff = ff->next) != TT.ff->prev);
+ if (!var) return addvar(s, TT.ff->prev);
flags = (var->flags &= ~VAR_WHITEOUT);
if (flags&VAR_READONLY) {
@@ -483,6 +488,8 @@ static void unsetvar(char *name)
if (!(var->flags&VAR_NOFREE)) free(var->str);
memmove(ff->vars+ii, ff->vars+ii+1, (ff->varslen--)-ii);
}
+ if (!strcmp(name, "IFS"))
+ do ff->ifs = " \t\n"; while ((ff = ff->next) != TT.ff->prev);
}
static struct sh_vars *setvarval(char *name, char *val)
@@ -829,6 +836,7 @@ static void call_function(void)
// default $* is to copy previous
TT.ff->arg.v = TT.ff->next->arg.v;
TT.ff->arg.c = TT.ff->next->arg.c;
+ TT.ff->ifs = TT.ff->next->ifs;
}
// returns 0 if source popped, nonzero if function popped
@@ -838,7 +846,6 @@ static int end_function(int funconly)
int func = ff->next!=ff && ff->vars;
if (!func && funconly) return 0;
-
llist_traverse(ff->delete, llist_free_arg);
ff->delete = 0;
while (TT.ff->blk->next) pop_block();
@@ -865,7 +872,7 @@ static int end_function(int funconly)
static int run_subshell(char *str, int len)
{
pid_t pid;
-//dprintf(2, "%d run_subshell %.*s\n", getpid(), len, str);
+//dprintf(2, "%d run_subshell %.*s\n", getpid(), len, str); debug_show_fds();
// The with-mmu path is significantly faster.
if (CFG_TOYBOX_FORK) {
if ((pid = fork())<0) perror_msg("fork");
@@ -1563,8 +1570,8 @@ barf:
nosplit++;
if (flags&SEMI_IFS) strcpy(sep, " ");
// TODO what if separator is bigger? Need to grab 1 column of combining chars
- else if (0<(dd = utf8towc(&wc, TT.ifs, 4)))
- sprintf(sep, "%.*s", dd, TT.ifs);
+ else if (0<(dd = utf8towc(&wc, TT.ff->ifs, 4)))
+ sprintf(sep, "%.*s", dd, TT.ff->ifs);
}
// when aa proceed through entries until NULL, else process ifs once
@@ -1737,7 +1744,8 @@ barf:
// find end of (split) word
if ((qq&1) || nosplit) ss = ifs+strlen(ifs);
- else for (ss = ifs; *ss; ss += kk) if (utf8chr(ss, TT.ifs, &kk)) break;
+ else for (ss = ifs; *ss; ss += kk)
+ if (utf8chr(ss, TT.ff->ifs, &kk)) break;
// when no prefix, not splitting, no suffix: use existing memory
if (!oo && !*ss && !((mm==aa.c) ? str[ii] : nosplit)) {
@@ -1771,7 +1779,7 @@ barf:
}
// Skip trailing seperator (combining whitespace)
- while ((jj = utf8chr(ss, TT.ifs, &ll))) {
+ while ((jj = utf8chr(ss, TT.ff->ifs, &ll))) {
ss += ll;
if (!iswspace(jj)) break;
}
@@ -2280,46 +2288,64 @@ static struct sh_process *run_command(void)
struct sh_process *pp = 0;
struct arg_list *delete = 0;
- // Count leading variable assignments and perform any assignment(s)
- for (envlen = 0; envlen<arg->c; envlen++) {
- s = varend(arg->v[envlen]);
- if (s == arg->v[envlen] || *s != '=') break;
- }
+ // Count leading variable assignments
+ for (envlen = 0; envlen<arg->c; envlen++)
+ if ((s = varend(arg->v[envlen])) == arg->v[envlen] || *s != '=') break;
+
+ // perform any assignments
if (envlen) {
struct sh_fcall *ff;
struct sh_vars *vv;
// If prefix assignment, create temp function context to hold vars
- if (!(persist = envlen==arg->c || TT.ff->blk->pipe)) call_function();
+ if (envlen!=arg->c || TT.ff->blk->pipe) {
+ call_function();
+ addvar(0, TT.ff); // function context (not source) so end_function deletes
+ persist = 0;
+ } else ff = TT.ff->prev;
for (; jj<envlen && !pp; jj++) {
-// TODO this is localize(), merge with export() and local_main
- s = arg->v[jj];
- if (!persist && (!(vv = findvar(s, &ff)) || ff != TT.ff)) {
- if (vv && (vv->flags&VAR_READONLY)) {
- error_msg("%.*s: readonly variable", (int)(varend(s)-s), s);
- continue;
- }
- addvar(s, TT.ff)->flags = VAR_NOFREE|VAR_GLOBAL;
+ if (!(vv = findvar(s = arg->v[jj], &ff))) ff = persist?TT.ff->prev:TT.ff;
+ if (vv && (vv->flags&VAR_READONLY)) {
+ error_msg("%.*s: readonly variable", (int)(varend(s)-s), s);
+ continue;
}
+ if (!vv || (!persist && ff != TT.ff && (ff = TT.ff)))
+ (vv = addvar(s, ff))->flags = VAR_NOFREE|(VAR_GLOBAL*!persist);
if (!(sss = expand_one_arg(s, SEMI_IFS, persist ? 0 : &delete))) {
- if (!pp) pp = xzalloc(sizeof(struct sh_process));
+ if (!pp) pp = xzalloc(sizeof(*pp));
pp->exit = 1;
- } else setvar((!persist || sss != s) ? sss : xstrdup(sss));
+ } else {
+ if (persist || sss != s) {
+ vv->flags &= ~VAR_NOFREE;
+ vv->str = sss==s ? xstrdup(sss) : sss;
+ }
+ if (!strncmp(vv->str, "IFS=", 4))
+ do ff->ifs = vv->str+4; while ((ff = ff->next) != TT.ff->prev);
+ }
+ }
+ }
+
+ // expand cmdline with _old_ var context, matching bash's order of operations
+ if (!pp) {
+ sss = persist ? 0 : dlist_pop(&TT.ff);
+ pp = expand_redir(arg, envlen, 0);
+ if (!persist) {
+ dlist_add_nomalloc((void *)&TT.ff, (void *)sss);
+ TT.ff = TT.ff->prev;
}
}
- // Expand command line and do what it says
- if (!pp) pp = expand_redir(arg, envlen, 0);
+ // Do the thing
if (pp->exit || envlen==arg->c) s = 0; // leave $_ alone
else if (!pp->arg.v) s = ""; // nothing to do but blank $_
else {
- struct toy_list *tl = toy_find(pp->arg.v[envlen]);
+ struct toy_list *tl = toy_find(*pp->arg.v);
jj = tl ? tl->flags : 0;
TT.pp = pp;
s = pp->arg.v[pp->arg.c-1];
sss = pp->arg.v[pp->arg.c];
-//dprintf(2, "%d run command %s\n", getpid(), pp->arg.v[envlen]);
+//dprintf(2, "%d run command %p %s\n", getpid(), TT.ff, *pp->arg.v); debug_show_fds();
// TODO handle ((math)): else if (!strcmp(*pp->arg.v, "(("))
// TODO: call functions() FUNCTION
// TODO what about "echo | x=1 | export fruit", must subshell? Test this.
@@ -2337,7 +2363,7 @@ static struct sh_process *run_command(void)
// The compiler complains "declaration does not declare anything" if we
// name the union in TT, only works WITHOUT name. So we can't
// sizeof(union) instead offsetof() first thing after union to get size.
- memset(&TT, 0, offsetof(struct sh_data, ifs));
+ memset(&TT, 0, offsetof(struct sh_data, SECONDS));
if (!sigsetjmp(rebound, 1)) {
toys.rebound = &rebound;
toy_singleinit(tl, pp->arg.v);
@@ -2355,6 +2381,7 @@ static struct sh_process *run_command(void)
// cleanup process
unredirect(pp->urd);
+ pp->urd = 0;
if (!persist) end_function(0);
if (s) setvarval("_", s);
llist_traverse(delete, llist_free_arg);
@@ -2795,7 +2822,9 @@ static int parse_line(char *line, struct sh_pipeline **ppl,
flush:
if (s) syntax_err(s);
llist_traverse(*ppl, free_pipeline);
+ *ppl = 0;
llist_traverse(*expect, free);
+ *expect = 0;
return 0-!!s;
}
@@ -3085,6 +3114,7 @@ static void run_lines(void)
continue;
}
TT.ff->pl = TT.ff->pl->end;
+ pop_block();
dlist_add_nomalloc((void *)&pplist, (void *)pp);
// handle start of block in this process
@@ -3328,7 +3358,7 @@ int do_source(char *name, FILE *ff)
do {
if ((void *)1 == (new = get_next_line(ff, more+1))) goto is_binary;
-//dprintf(2, "%d getline from %p %s\n", getpid(), ff, new);
+//dprintf(2, "%d getline from %p %s\n", getpid(), ff, new); debug_show_fds();
// did we exec an ELF file or something?
if (!TT.LINENO++ && name && new) {
wchar_t wc;
@@ -3423,7 +3453,7 @@ static void subshell_setup(void)
initvar("PS4", "+ ");
// Ensure environ copied and toys.envc set, and clean out illegal entries
- TT.ifs = " \t\n";
+ TT.ff->ifs = " \t\n";
for (from = pid = ppid = zpid = 0; (s = environ[from]); from++) {
@@ -3449,7 +3479,7 @@ static void subshell_setup(void)
shv->flags |= VAR_GLOBAL;
shv->str = s;
}
- if (!memcmp(s, "IFS=", 4)) TT.ifs = s+4;
+ if (!memcmp(s, "IFS=", 4)) TT.ff->ifs = s+4;
}
// set/update PWD
@@ -3696,7 +3726,6 @@ void unset_main(void)
}
// unset magic variable?
- if (!strcmp(*arg, "IFS")) TT.ifs = " \t\n";
unsetvar(*arg);
}
}
diff --git a/toys/posix/cp.c b/toys/posix/cp.c
index a27c200a..8eaecc9c 100644
--- a/toys/posix/cp.c
+++ b/toys/posix/cp.c
@@ -15,7 +15,7 @@
// options shared between mv/cp must be in same order (right to left)
// for FLAG macros to work out right in shared infrastructure.
-USE_CP(NEWTOY(cp, "<1(preserve):;D(parents)RHLPprdaslvnF(remove-destination)fit:T[-HLPd][-ni]", TOYFLAG_BIN))
+USE_CP(NEWTOY(cp, "<1(preserve):;D(parents)RHLPprudaslvnF(remove-destination)fit:T[-HLPd][-niu]", TOYFLAG_BIN))
USE_MV(NEWTOY(mv, "<1vnF(remove-destination)fit:T[-ni]", TOYFLAG_BIN))
USE_INSTALL(NEWTOY(install, "<1cdDpsvt:m:o:g:", TOYFLAG_USR|TOYFLAG_BIN))
@@ -38,6 +38,7 @@ config CP
-L Follow all symlinks
-l Hard link instead of copy
-n No clobber (don't overwrite DEST)
+ -u Update (keep newest mtime)
-P Do not follow symlinks
-p Preserve timestamps, ownership, and mode
-R Recurse into subdirectories (DEST must be a directory)
@@ -152,7 +153,7 @@ static int cp_node(struct dirtree *try)
return 0;
}
- // Handle -invF
+ // Handle -inuvF
if (!faccessat(cfd, catch, F_OK, 0) && !S_ISDIR(cst.st_mode)) {
char *s;
@@ -165,6 +166,8 @@ static int cp_node(struct dirtree *try)
error_msg("unlink '%s'", catch);
return 0;
} else if (flags & FLAG_n) return 0;
+ else if ((flags & FLAG_u) && nanodiff(&try->st.st_mtim, &cst.st_mtim)>0)
+ return 0;
else if (flags & FLAG_i) {
fprintf(stderr, "%s: overwrite '%s'", toys.which->name,
s = dirtree_path(try, 0));