From c42089fed7adbf3ae1a0fd73b3a7b1e4f10e31db Mon Sep 17 00:00:00 2001
From: Rob Landley <rob@landley.net>
Date: Fri, 19 Feb 2021 11:12:04 -0600
Subject: Fix cp -t with one argument and make --parents work with -t.

---
 tests/cp.test   |  5 +++++
 toys/posix/cp.c | 23 +++++++++++++++--------
 2 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/tests/cp.test b/tests/cp.test
index 293f0348..3fcea3be 100755
--- a/tests/cp.test
+++ b/tests/cp.test
@@ -131,6 +131,11 @@ testing "-P symlink" "cp -P lnk ldst && stat -c %F ldst" "symbolic link\n" "" ""
 testing "follow symlink" "cp lnk ldst2 && stat -c %F ldst2" "regular file\n" "" ""
 rm file fdst lnk ldst ldst2
 
+mkdir sub
+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
+
 # cp -r ../source destdir
 # cp -r one/two/three missing
 # cp -r one/two/three two
diff --git a/toys/posix/cp.c b/toys/posix/cp.c
index 3fe1908d..56fbadf9 100644
--- a/toys/posix/cp.c
+++ b/toys/posix/cp.c
@@ -15,8 +15,8 @@
 // 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, "<2(preserve):;D(parents)RHLPprdaslvnF(remove-destination)fit:T[-HLPd][-ni]", TOYFLAG_BIN))
-USE_MV(NEWTOY(mv, "<2vnF(remove-destination)fit:T[-ni]", TOYFLAG_BIN))
+USE_CP(NEWTOY(cp, "<1(preserve):;D(parents)RHLPprdaslvnF(remove-destination)fit:T[-HLPd][-ni]", 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))
 
 config CP
@@ -364,16 +364,24 @@ void cp_main(void)
 {
   char *tt = *toys.which->name == 'i' ? TT.i.t : TT.c.t,
     *destname = tt ? : toys.optargs[--toys.optc];
-  int i, destdir = !stat(destname, &TT.top) && S_ISDIR(TT.top.st_mode);
+  int i, destdir = !stat(destname, &TT.top);
+
+  if (!toys.optc) error_exit("Needs 2 arguments");
+  if (!destdir && errno==ENOENT && FLAG(D)) {
+    if (tt && mkpathat(AT_FDCWD, tt, 0777, MKPATHAT_MAKE|MKPATHAT_MKLAST))
+      perror_exit("-t '%s'", tt);
+    destdir = 1;
+  } else {
+    destdir = destdir && S_ISDIR(TT.top.st_mode);
+    if (!destdir && (toys.optc>1 || FLAG(D) || tt))
+      error_exit("'%s' not directory", destname);
+  }
 
   if (FLAG(T)) {
     if (toys.optc>1) help_exit("Max 2 arguments");
     if (destdir) error_exit("'%s' is a directory", destname);
   }
 
-  if ((toys.optc>1 || FLAG(D) || tt) && !destdir)
-    error_exit("'%s' not directory", destname);
-
   if (FLAG(a)||FLAG(p)) TT.pflags = _CP_mode|_CP_ownership|_CP_timestamps;
 
   // Not using comma_args() (yet?) because interpeting as letters.
@@ -511,13 +519,12 @@ void install_main(void)
     return;
   }
 
-  if (FLAG(D)) {
+  if (FLAG(D) && !FLAG(t)) {
     TT.destname = toys.optargs[toys.optc-1];
     if (mkpathat(AT_FDCWD, TT.destname, 0, MKPATHAT_MAKE))
       perror_exit("-D '%s'", TT.destname);
     if (toys.optc == 1) return;
   }
-  if (toys.optc < 2) error_exit("needs 2 args");
 
   // Translate flags from install to cp
   toys.optflags = cp_flag_F() + cp_flag_v()*!!FLAG(v)
-- 
cgit v1.2.3