libsystem: introduce do_cp_force() and do_cp_mode_force()
authorWaLyong Cho <walyong.cho@samsung.com>
Tue, 15 Nov 2016 08:12:06 +0000 (17:12 +0900)
committerWaLyong Cho <walyong.cho@samsung.com>
Tue, 15 Nov 2016 08:12:08 +0000 (17:12 +0900)
The origin do_cp() and do_cp_mode() always overwrite the destination
file. It does not make sense. So check the destination file exists, if
yes, return -EALREADY.
And to support force overwrite, add new do_cp_force() and
do_cp_mode_force(). Those does not check the destination file exist.

Change-Id: I9b0936f15195b737c4701bf1fa64ce49124873ce
Signed-off-by: WaLyong Cho <walyong.cho@samsung.com>
src/libsystem/libsystem.c
src/libsystem/libsystem.h
src/test/test-cp.c

index fc704f9..cb74b34 100644 (file)
@@ -424,22 +424,31 @@ int do_copy(const char *src, const char *dst, const char *option, int64_t timeou
         return do_fork_exec(argv, NULL, timeout_msec);
 }
 
-int do_cp_mode(const char *src, const char *dst, mode_t mode) {
+static int do_cp_internal(const char *src, const char *dst, mode_t mode, bool force) {
         _cleanup_close_ int rfd = -1, wfd = -1;
-        ssize_t red;
         char buf[1024];
+        ssize_t red;
+        int r;
 
         assert(src);
         assert(dst);
 
-        rfd = open(src, O_RDONLY);
-        if (rfd < 0)
-                return -errno;
+        if (!force) {
+                r = access(dst, F_OK);
+                if (r == 0)
+                        return -EALREADY;
+                else if (errno != ENOENT)
+                        return -errno;
+        }
 
         wfd = open(dst, O_CREAT | O_WRONLY | O_TRUNC, mode);
         if (wfd < 0)
                 return -errno;
 
+        rfd = open(src, O_RDONLY);
+        if (rfd < 0)
+                return -errno;
+
         while ((red = read(rfd, buf, 1024)) > 0)
                 if (write(wfd, buf, red) != red)
                         return -errno;
@@ -450,12 +459,36 @@ int do_cp_mode(const char *src, const char *dst, mode_t mode) {
         return 0;
 }
 
+int do_cp_mode(const char *src, const char *dst, mode_t mode) {
+
+        assert(src);
+        assert(dst);
+
+        return do_cp_internal(src, dst, mode, false);
+}
+
+int do_cp_mode_force(const char *src, const char *dst, mode_t mode) {
+
+        assert(src);
+        assert(dst);
+
+        return do_cp_internal(src, dst, mode, true);
+}
+
 int do_cp(const char *src, const char *dst) {
 
         assert(src);
         assert(dst);
 
-        return do_cp_mode(src, dst, 0644);
+        return do_cp_internal(src, dst, 0644, false);
+}
+
+int do_cp_force(const char *src, const char *dst) {
+
+        assert(src);
+        assert(dst);
+
+        return do_cp_internal(src, dst, 0644, true);
 }
 
 int do_mkdir(const char *path, mode_t mode) {
index 9b0bd1e..a6ed0db 100644 (file)
@@ -274,27 +274,54 @@ bool is_number(const char *s, int l);
 int do_copy(const char *src, const char *dst, const char *option, int64_t timeout_msec);
 
 /**
- * @brief copy a file with mode
+ * @brief copy a file with mode, if destination file exists, return
+ * error.
  *
  * @param src source file path
  * @param dst destination file path
  * @param mode destination file mode
  *
- * @return 0 on success, -errno on failure.
+ * @return 0 on success, -errno on failure. -EALREADY if destination
+ * file exist.
  */
 int do_cp_mode(const char *src, const char *dst, mode_t mode);
 
 /**
- * @brief copy a file, destination file mode is 0644
+ * @brief copy a file with mode, if destination file exists, the file
+ * is overwritten.
  *
  * @param src source file path
  * @param dst destination file path
+ * @param mode destination file mode
  *
  * @return 0 on success, -errno on failure.
  */
+int do_cp_mode_force(const char *src, const char *dst, mode_t mode);
+
+/**
+ * @brief copy a file, destination file mode is 0644, if destination
+ * file exist, return error.
+ *
+ * @param src source file path
+ * @param dst destination file path
+ *
+ * @return 0 on success, -errno on failure. -EALREADY if destination
+ * file exist.
+ */
 int do_cp(const char *src, const char *dst);
 
 /**
+ * @brief copy a file, destination file mode is 0644, if destination
+ * file exist, the file is overwritten.
+ *
+ * @param src source file path
+ * @param dst destination file path
+ *
+ * @return 0 on success, -errno on failure.
+ */
+int do_cp_force(const char *src, const char *dst);
+
+/**
  * @brief Make a directory. If parent directories are also absent,
  * make them also. Corresponding with "mkdir -p".
  *
index c875cca..532dee7 100644 (file)
@@ -106,22 +106,31 @@ static void compare_file(void) {
         }
 }
 
-static void test_n_byte_cp(unsigned int n) {
+static void test_overwite(void) {
         assert(unlink(TEST_SRC_FILE) == 0 || errno == ENOENT);
+        assert(unlink(TEST_DST_FILE) == 0 || errno == ENOENT);
 
-        assert(unlink(TEST_SRC_FILE) == 0 || errno == ENOENT);
+        assert(touch(TEST_SRC_FILE) == 0);
+        assert(touch(TEST_DST_FILE) == 0);
+
+        assert(do_cp(TEST_SRC_FILE, TEST_DST_FILE) == -EALREADY);
+        assert(do_cp_force(TEST_SRC_FILE, TEST_DST_FILE) == 0);
+        compare_file();
+}
 
+static void test_n_byte_cp_force(unsigned int n) {
         assert(write_src_file(n) == 0);
-        assert(do_cp(TEST_SRC_FILE, TEST_DST_FILE) == 0);
+        assert(do_cp_force(TEST_SRC_FILE, TEST_DST_FILE) == 0);
         compare_file();
 }
 
 int main(int argc, char *argv[]) {
-
         unsigned int b;
 
+        test_overwite();
+
         for (b = 8; b < (1 << 30); b = b << 1)
-                test_n_byte_cp(b);
+                test_n_byte_cp_force(b);
 
         unlink(TEST_SRC_FILE);
         unlink(TEST_DST_FILE);