test-copy.c revision 63c372cb9df3bee01e3bf8cd7f96f336bddda846
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier/***
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier This file is part of systemd
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier Copyright 2014 Ronny Chevalier
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier systemd is free software; you can redistribute it and/or modify it
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier under the terms of the GNU Lesser General Public License as published by
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier the Free Software Foundation; either version 2.1 of the License, or
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier (at your option) any later version.
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier systemd is distributed in the hope that it will be useful, but
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier WITHOUT ANY WARRANTY; without even the implied warranty of
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier Lesser General Public License for more details.
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier You should have received a copy of the GNU Lesser General Public License
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier along with systemd; If not, see <http://www.gnu.org/licenses/>.
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier***/
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier#include <unistd.h>
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier#include "copy.h"
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier#include "path-util.h"
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier#include "fileio.h"
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier#include "mkdir.h"
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier#include "strv.h"
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier#include "macro.h"
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier#include "util.h"
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalierstatic void test_copy_file(void) {
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier _cleanup_free_ char *buf = NULL;
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier char fn[] = "/tmp/test-copy_file.XXXXXX";
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier char fn_copy[] = "/tmp/test-copy_file.XXXXXX";
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier size_t sz = 0;
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier int fd;
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier fd = mkostemp_safe(fn, O_RDWR|O_CLOEXEC);
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier assert_se(fd >= 0);
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier close(fd);
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier fd = mkostemp_safe(fn_copy, O_RDWR|O_CLOEXEC);
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier assert_se(fd >= 0);
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier close(fd);
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier assert_se(write_string_file(fn, "foo bar bar bar foo") == 0);
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier
f2068bcce01db31cdc9422f44185f3b49c04d2ceLennart Poettering assert_se(copy_file(fn, fn_copy, 0, 0644, 0) == 0);
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier assert_se(read_full_file(fn_copy, &buf, &sz) == 0);
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier assert_se(streq(buf, "foo bar bar bar foo\n"));
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poettering assert_se(sz == 20);
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier unlink(fn);
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier unlink(fn_copy);
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier}
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poetteringstatic void test_copy_file_fd(void) {
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poettering char in_fn[] = "/tmp/test-copy-file-fd-XXXXXX";
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poettering char out_fn[] = "/tmp/test-copy-file-fd-XXXXXX";
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poettering _cleanup_close_ int in_fd = -1, out_fd = -1;
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poettering char text[] = "boohoo\nfoo\n\tbar\n";
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poettering char buf[64] = {0};
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poettering
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poettering in_fd = mkostemp_safe(in_fn, O_RDWR);
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poettering assert_se(in_fd >= 0);
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poettering out_fd = mkostemp_safe(out_fn, O_RDWR);
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poettering assert_se(out_fd >= 0);
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poettering
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poettering assert_se(write_string_file(in_fn, text) == 0);
7430ec6ac08f2c0416d9f806964c46b30f3862b2Lennart Poettering assert_se(copy_file_fd("/a/file/which/does/not/exist/i/guess", out_fd, true) < 0);
7430ec6ac08f2c0416d9f806964c46b30f3862b2Lennart Poettering assert_se(copy_file_fd(in_fn, out_fd, true) >= 0);
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poettering assert_se(lseek(out_fd, SEEK_SET, 0) == 0);
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poettering
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poettering assert_se(read(out_fd, buf, sizeof(buf)) == sizeof(text) - 1);
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poettering assert_se(streq(buf, text));
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poettering
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poettering unlink(in_fn);
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poettering unlink(out_fn);
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poettering}
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poettering
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalierstatic void test_copy_tree(void) {
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier char original_dir[] = "/tmp/test-copy_tree/";
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier char copy_dir[] = "/tmp/test-copy_tree-copy/";
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier char **files = STRV_MAKE("file", "dir1/file", "dir1/dir2/file", "dir1/dir2/dir3/dir4/dir5/file");
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier char **links = STRV_MAKE("link", "file",
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier "link2", "dir1/file");
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier char **p, **link;
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier rm_rf_dangerous(copy_dir, false, true, false);
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier rm_rf_dangerous(original_dir, false, true, false);
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier STRV_FOREACH(p, files) {
63c372cb9df3bee01e3bf8cd7f96f336bddda846Lennart Poettering char *f = strjoina(original_dir, *p);
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier assert_se(mkdir_parents(f, 0755) >= 0);
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier assert_se(write_string_file(f, "file") == 0);
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier }
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier STRV_FOREACH_PAIR(link, p, links) {
63c372cb9df3bee01e3bf8cd7f96f336bddda846Lennart Poettering char *f = strjoina(original_dir, *p);
63c372cb9df3bee01e3bf8cd7f96f336bddda846Lennart Poettering char *l = strjoina(original_dir, *link);
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier assert_se(mkdir_parents(l, 0755) >= 0);
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier assert_se(symlink(f, l) == 0);
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier }
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier assert_se(copy_tree(original_dir, copy_dir, true) == 0);
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier STRV_FOREACH(p, files) {
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier _cleanup_free_ char *buf = NULL;
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier size_t sz = 0;
63c372cb9df3bee01e3bf8cd7f96f336bddda846Lennart Poettering char *f = strjoina(copy_dir, *p);
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier assert_se(access(f, F_OK) == 0);
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier assert_se(read_full_file(f, &buf, &sz) == 0);
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier assert_se(streq(buf, "file\n"));
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier }
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier STRV_FOREACH_PAIR(link, p, links) {
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier _cleanup_free_ char *target = NULL;
63c372cb9df3bee01e3bf8cd7f96f336bddda846Lennart Poettering char *f = strjoina(original_dir, *p);
63c372cb9df3bee01e3bf8cd7f96f336bddda846Lennart Poettering char *l = strjoina(copy_dir, *link);
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier assert_se(readlink_and_canonicalize(l, &target) == 0);
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier assert_se(path_equal(f, target));
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier }
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier assert_se(copy_tree(original_dir, copy_dir, false) < 0);
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier assert_se(copy_tree("/tmp/inexistent/foo/bar/fsdoi", copy_dir, false) < 0);
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier rm_rf_dangerous(copy_dir, false, true, false);
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier rm_rf_dangerous(original_dir, false, true, false);
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier}
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalierint main(int argc, char *argv[]) {
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier test_copy_file();
cda134ab1eac84f874aacf8e885a07112a7fd5ceLennart Poettering test_copy_file_fd();
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier test_copy_tree();
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier return 0;
641d1f99b8c4c5427a1fedcb4740586a130ac6cfRonny Chevalier}