Adds the `-i` flag to prompt the user for confirmation when attempting
to perform certain activities such as overwriting files in `cp` and `mv`
or removing files/directories in `rm`.
---
 cp.c         |  5 ++++-
 fs.h         |  2 ++
 libutil/cp.c |  8 ++++++++
 libutil/rm.c |  6 ++++++
 mv.c         | 15 +++++++++++++--
 rm.c         |  3 +++
 6 files changed, 36 insertions(+), 3 deletions(-)

diff --git a/cp.c b/cp.c
index 6abe02c..bb29629 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
@@ -23,6 +23,9 @@ main(int argc, char *argv[])
        case 'f':
                cp_fflag = 1;
                break;
+        case 'i':
+               cp_iflag = 1;
+               break;
        case 'p':
                cp_pflag = 1;
                break;
diff --git a/fs.h b/fs.h
index 00ecd3b..5e45e80 100644
--- a/fs.h
+++ b/fs.h
@@ -28,6 +28,7 @@ enum {

 extern int cp_aflag;
 extern int cp_fflag;
+extern int cp_iflag;
 extern int cp_pflag;
 extern int cp_rflag;
 extern int cp_vflag;
@@ -35,6 +36,7 @@ extern int cp_follow;
 extern int cp_status;

 extern int rm_fflag;
+extern int rm_iflag;
 extern int rm_rflag;
 extern int rm_status;

diff --git a/libutil/cp.c b/libutil/cp.c
index 23275ac..c5039e2 100644
--- a/libutil/cp.c
+++ b/libutil/cp.c
@@ -16,6 +16,7 @@

 int cp_aflag  = 0;
 int cp_fflag  = 0;
+int cp_iflag  = 0;
 int cp_pflag  = 0;
 int cp_rflag  = 0;
 int cp_vflag  = 0;
@@ -29,6 +30,7 @@ cp(const char *s1, const char *s2, int depth)
        int f1, f2, flags = 0;
        struct dirent *d;
        struct stat st;
+       struct stat dst;
        struct timespec times[2];
        ssize_t r;
        char target[PATH_MAX], ns1[PATH_MAX], ns2[PATH_MAX];
@@ -42,6 +44,12 @@ cp(const char *s1, const char *s2, int depth)
                return 0;
        }

+        /* -i emits a prompt if file may be overwritten */
+        if (cp_iflag && stat(s2, &dst) == 0) {
+                if (promptyn("not overwritten", "overwrite %s?", s2) == 1)
+                        return 0;
+        }
+
        if (cp_vflag)
                printf("%s -> %s\n", s1, s2);

diff --git a/libutil/rm.c b/libutil/rm.c
index 8d4be08..ae8c024 100644
--- a/libutil/rm.c
+++ b/libutil/rm.c
@@ -10,10 +10,16 @@
 #include "../util.h"

 int rm_status = 0;
+int rm_iflag = 0;

 void
 rm(int dirfd, const char *name, struct stat *st, void *data, struct
recursor *r)
 {
+        if (rm_iflag) {
+                if (promptyn("not removed", "remove %s?", name) == 1)
+                        return;
+        }
+
        if (!r->maxdepth && S_ISDIR(st->st_mode)) {
                recurse(dirfd, name, NULL, r);

diff --git a/mv.c b/mv.c
index 8441f9c..51efde5 100644
--- a/mv.c
+++ b/mv.c
@@ -9,14 +9,22 @@
 #include "util.h"

 static int mv_status = 0;
+static int mv_iflag = 0;

 static int
 mv(const char *s1, const char *s2, int depth)
 {
        struct recursor r = { .fn = rm, .follow = 'P' };
+        struct stat st;
+
+        if (mv_iflag && stat(s2, &st) == 0) {
+                if (promptyn("not overwritten", "overwrite %s?", s2) == 1)
+                        return 0;
+        }

        if (!rename(s1, s2))
-               return 0;
+                return 0;
+
        if (errno == EXDEV) {
                cp_aflag = cp_rflag = cp_pflag = 1;
                cp_follow = 'P';
@@ -38,7 +46,7 @@ mv(const char *s1, const char *s2, int depth)
 static void
 usage(void)
 {
-       eprintf("usage: %s [-f] source ... dest\n", argv0);
+       eprintf("usage: %s [-fi] source ... dest\n", argv0);
 }

 int
@@ -49,6 +57,9 @@ main(int argc, char *argv[])
        ARGBEGIN {
        case 'f':
                break;
+        case 'i':
+                mv_iflag = 1;
+                break;
        default:
                usage();
        } ARGEND
diff --git a/rm.c b/rm.c
index 8bebfcb..70da082 100644
--- a/rm.c
+++ b/rm.c
@@ -19,6 +19,9 @@ main(int argc, char *argv[])
        case 'f':
                r.flags |= SILENT;
                break;
+        case 'i':
+                rm_iflag = 1;
+                break;
        case 'R':
        case 'r':
                r.maxdepth = 0;
--
2.37.3

Reply via email to