test-copy.c revision 4c1fc3e404d648c70bd2f50ac50aeac6ece8872e
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/***
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering This file is part of systemd
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Copyright 2014 Ronny Chevalier
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is free software; you can redistribute it and/or modify it
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering under the terms of the GNU Lesser General Public License as published by
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (at your option) any later version.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is distributed in the hope that it will be useful, but
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Lesser General Public License for more details.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering You should have received a copy of the GNU Lesser General Public License
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering***/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <unistd.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
8bdbb8d9cbe1d35708385573d70984ab4533812dLennart Poettering#include "copy.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "path-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "fileio.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "mkdir.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "strv.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "macro.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "util.h"
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering#include "rm-rf.h"
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poetteringstatic void test_copy_file(void) {
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering _cleanup_free_ char *buf = NULL;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering char fn[] = "/tmp/test-copy_file.XXXXXX";
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering char fn_copy[] = "/tmp/test-copy_file.XXXXXX";
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering size_t sz = 0;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen int fd;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fd = mkostemp_safe(fn, O_RDWR|O_CLOEXEC);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_se(fd >= 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering close(fd);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen fd = mkostemp_safe(fn_copy, O_RDWR|O_CLOEXEC);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_se(fd >= 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering close(fd);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_se(write_string_file(fn, "foo bar bar bar foo", WRITE_STRING_FILE_CREATE) == 0);
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert_se(copy_file(fn, fn_copy, 0, 0644, 0) == 0);
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering assert_se(read_full_file(fn_copy, &buf, &sz) == 0);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering assert_se(streq(buf, "foo bar bar bar foo\n"));
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering assert_se(sz == 20);
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering unlink(fn);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering unlink(fn_copy);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic void test_copy_file_fd(void) {
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen char in_fn[] = "/tmp/test-copy-file-fd-XXXXXX";
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char out_fn[] = "/tmp/test-copy-file-fd-XXXXXX";
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_close_ int in_fd = -1, out_fd = -1;
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering char text[] = "boohoo\nfoo\n\tbar\n";
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char buf[64] = {0};
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering in_fd = mkostemp_safe(in_fn, O_RDWR);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_se(in_fd >= 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering out_fd = mkostemp_safe(out_fn, O_RDWR);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_se(out_fd >= 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_se(write_string_file(in_fn, text, WRITE_STRING_FILE_CREATE) == 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_se(copy_file_fd("/a/file/which/does/not/exist/i/guess", out_fd, true) < 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_se(copy_file_fd(in_fn, out_fd, true) >= 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_se(lseek(out_fd, SEEK_SET, 0) == 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_se(read(out_fd, buf, sizeof(buf)) == sizeof(text) - 1);
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering assert_se(streq(buf, text));
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen unlink(in_fn);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen unlink(out_fn);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen}
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic void test_copy_tree(void) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char original_dir[] = "/tmp/test-copy_tree/";
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char copy_dir[] = "/tmp/test-copy_tree-copy/";
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering char **files = STRV_MAKE("file", "dir1/file", "dir1/dir2/file", "dir1/dir2/dir3/dir4/dir5/file");
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering char **links = STRV_MAKE("link", "file",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "link2", "dir1/file");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char **p, **link;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen (void) rm_rf(copy_dir, REMOVE_ROOT|REMOVE_PHYSICAL);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen (void) rm_rf(original_dir, REMOVE_ROOT|REMOVE_PHYSICAL);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen STRV_FOREACH(p, files) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen char *f = strjoina(original_dir, *p);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert_se(mkdir_parents(f, 0755) >= 0);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert_se(write_string_file(f, "file", WRITE_STRING_FILE_CREATE) == 0);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen }
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering STRV_FOREACH_PAIR(link, p, links) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char *f = strjoina(original_dir, *p);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char *l = strjoina(original_dir, *link);
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen assert_se(mkdir_parents(l, 0755) >= 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_se(symlink(f, l) == 0);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen }
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering assert_se(copy_tree(original_dir, copy_dir, true) == 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen STRV_FOREACH(p, files) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_free_ char *buf = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering size_t sz = 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char *f = strjoina(copy_dir, *p);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert_se(access(f, F_OK) == 0);
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering assert_se(read_full_file(f, &buf, &sz) == 0);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert_se(streq(buf, "file\n"));
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen }
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering STRV_FOREACH_PAIR(link, p, links) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_free_ char *target = NULL;
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen char *f = strjoina(original_dir, *p);
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen char *l = strjoina(copy_dir, *link);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_se(readlink_and_canonicalize(l, &target) == 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_se(path_equal(f, target));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering assert_se(copy_tree(original_dir, copy_dir, false) < 0);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering assert_se(copy_tree("/tmp/inexistent/foo/bar/fsdoi", copy_dir, false) < 0);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering (void) rm_rf(copy_dir, REMOVE_ROOT|REMOVE_PHYSICAL);
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering (void) rm_rf(original_dir, REMOVE_ROOT|REMOVE_PHYSICAL);
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering}
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poetteringstatic void test_copy_bytes(void) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering _cleanup_close_pair_ int pipefd[2] = {-1, -1};
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering _cleanup_close_ int infd = -1;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering int r, r2;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering char buf[1024], buf2[1024];
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering infd = open("/usr/lib/os-release", O_RDONLY|O_CLOEXEC);
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering if (infd < 0)
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering infd = open("/etc/os-release", O_RDONLY|O_CLOEXEC);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering assert_se(infd >= 0);
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering assert_se(pipe2(pipefd, O_CLOEXEC) == 0);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering r = copy_bytes(infd, pipefd[1], (off_t) -1, false);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering assert_se(r == 0);
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering r = read(pipefd[0], buf, sizeof(buf));
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering assert_se(r >= 0);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering assert_se(lseek(infd, 0, SEEK_SET) == 0);
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering r2 = read(infd, buf2, sizeof(buf2));
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering assert_se(r == r2);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering assert_se(strneq(buf, buf2, r));
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering /* test copy_bytes with invalid descriptors */
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering r = copy_bytes(pipefd[0], pipefd[0], 1, false);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering assert_se(r == -EBADF);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering r = copy_bytes(pipefd[1], pipefd[1], 1, false);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering assert_se(r == -EBADF);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering r = copy_bytes(pipefd[1], infd, 1, false);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering assert_se(r == -EBADF);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering}
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poetteringint main(int argc, char *argv[]) {
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering test_copy_file();
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering test_copy_file_fd();
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering test_copy_tree();
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering test_copy_bytes();
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering return 0;
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering}
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering