---
 cp.1         | 22 ++++++++++++++++------
 cp.c         |  7 ++++++-
 libutil/cp.c | 18 ++++++++++++++++++
 3 files changed, 40 insertions(+), 7 deletions(-)

diff --git a/cp.1 b/cp.1
index 54126e2..4bbe4d0 100644
--- a/cp.1
+++ b/cp.1
@@ -6,7 +6,7 @@
 .Nd copy files and directories
 .Sh SYNOPSIS
 .Nm
-.Op Fl afpv
+.Op Fl afipv
 .Oo
 .Fl R
 .Op Fl H | L | P
@@ -35,7 +35,15 @@ and
 .It Fl f
 If an existing
 .Ar dest
-cannot be opened, remove it and try again.
+cannot be opened, remove it and try again. Ignores
+.Fl i
+if this option is used after it
+.It Fl i
+If
+.Ar dest
+exists and is not a directory, prompt before overwriting it. Ignores
+.Fl f
+if this option is used after it.
 .It Fl p
 Preserve mode, timestamp and permissions.
 .It Fl v
@@ -62,10 +70,12 @@ The
 .Nm
 utility is compliant with the
 .St -p1003.1-2013
-specification except from the
-.Op Fl i
-flag.
+specification.
 .Pp
 The
 .Op Fl av
-flags are an extension to that specification.
+flags are an extension to that specification, as is the mutual exclusivity of 
the
+.Fl f
+and
+.Fl i
+flags.
diff --git a/cp.c b/cp.c
index d87e77e..f72de04 100644
--- a/cp.c
+++ b/cp.c
@@ -7,7 +7,7 @@
 static void
 usage(void)
 {
-       eprintf("usage: %s [-afpv] [-R [-H | -L | -P]] source ... dest\n", 
argv0);
+       eprintf("usage: %s [-afipv] [-R [-H | -L | -P]] source ... dest\n", 
argv0);
 }

 int
@@ -22,6 +22,11 @@ main(int argc, char *argv[])
                break;
        case 'f':
                cp_fflag = 1;
+               cp_iflag = 0;
+               break;
+       case 'i':
+               cp_iflag = 1;
+               cp_fflag = 0;
                break;
        case 'p':
                cp_pflag = 1;
diff --git a/libutil/cp.c b/libutil/cp.c
index c398962..2a0cdd1 100644
--- a/libutil/cp.c
+++ b/libutil/cp.c
@@ -17,12 +17,22 @@

 int cp_aflag  = 0;
 int cp_fflag  = 0;
+int cp_iflag  = 0;
 int cp_pflag  = 0;
 int cp_rflag  = 0;
 int cp_vflag  = 0;
 int cp_status = 0;
 int cp_follow = 'L';

+inline static int
+exists(const char *s)
+{
+       struct stat st;
+
+       stat(s, &st);
+       return S_ISREG(st.st_mode);
+}
+
 int
 cp(const char *s1, const char *s2, int depth)
 {
@@ -34,6 +44,7 @@ cp(const char *s1, const char *s2, int depth)
        ssize_t r;
        int (*statf)(const char *, struct stat *);
        char target[PATH_MAX], ns1[PATH_MAX], ns2[PATH_MAX], *statf_name;
+       int c; /* used for i flag */

        if (cp_follow == 'P' || (cp_follow == 'H' && depth)) {
                statf_name = "lstat";
@@ -112,6 +123,13 @@ cp(const char *s1, const char *s2, int depth)
                        return 0;
                }
        } else {
+               if (cp_iflag && exists(s2)) {
+                       weprintf("overwrite %s with %s? ", s2, s1);
+                       while ((c = getchar()) != '\n' && c != EOF) {
+                               if (c != 'y' && c != 'Y')
+                                       return 0;
+                       }
+               }
                if (!(f1 = fopen(s1, "r"))) {
                        weprintf("fopen %s:", s1);
                        cp_status = 1;
--
2.10.0

Reply via email to