summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWaLyong Cho <walyong.cho@samsung.com>2016-11-15 08:12:06 (GMT)
committerWaLyong Cho <walyong.cho@samsung.com>2016-11-15 08:12:08 (GMT)
commit920f4d6b249c198863b1935b189ccbfae517228d (patch)
treeeac8a96c50d2d1a89f76efdf01c51c0943596304
parentecb9c927e17ba677106181d8c487c775b30f78a7 (diff)
downloadlibsystem-920f4d6b249c198863b1935b189ccbfae517228d.zip
libsystem-920f4d6b249c198863b1935b189ccbfae517228d.tar.gz
libsystem-920f4d6b249c198863b1935b189ccbfae517228d.tar.bz2
libsystem: introduce do_cp_force() and do_cp_mode_force()
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>
-rw-r--r--src/libsystem/libsystem.c45
-rw-r--r--src/libsystem/libsystem.h33
-rw-r--r--src/test/test-cp.c19
3 files changed, 83 insertions, 14 deletions
diff --git a/src/libsystem/libsystem.c b/src/libsystem/libsystem.c
index fc704f9..cb74b34 100644
--- a/src/libsystem/libsystem.c
+++ b/src/libsystem/libsystem.c
@@ -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) {
diff --git a/src/libsystem/libsystem.h b/src/libsystem/libsystem.h
index 9b0bd1e..a6ed0db 100644
--- a/src/libsystem/libsystem.h
+++ b/src/libsystem/libsystem.h
@@ -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".
*
diff --git a/src/test/test-cp.c b/src/test/test-cp.c
index c875cca..532dee7 100644
--- a/src/test/test-cp.c
+++ b/src/test/test-cp.c
@@ -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);