copy.c revision c622fbdb8d37796c35ab1e08240a18b4222e5c9f
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer/***
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer This file is part of systemd.
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer Copyright 2014 Lennart Poettering
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer systemd is free software; you can redistribute it and/or modify it
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer under the terms of the GNU Lesser General Public License as published by
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier the Free Software Foundation; either version 2.1 of the License, or
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier (at your option) any later version.
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier systemd is distributed in the hope that it will be useful, but
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier WITHOUT ANY WARRANTY; without even the implied warranty of
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier Lesser General Public License for more details.
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier You should have received a copy of the GNU Lesser General Public License
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier along with systemd; If not, see <http://www.gnu.org/licenses/>.
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier***/
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include <sys/sendfile.h>
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include <sys/xattr.h>
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "util.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "btrfs-util.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "strv.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#include "copy.h"
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier#define COPY_BUFFER_SIZE (16*1024)
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalierint copy_bytes(int fdf, int fdt, uint64_t max_bytes, bool try_reflink) {
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier bool try_sendfile = true, try_splice = true;
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier int r;
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier assert(fdf >= 0);
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier assert(fdt >= 0);
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier /* Try btrfs reflinks first. */
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier if (try_reflink &&
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier max_bytes == (uint64_t) -1 &&
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier lseek(fdf, 0, SEEK_CUR) == 0 &&
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier lseek(fdt, 0, SEEK_CUR) == 0) {
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier r = btrfs_reflink(fdf, fdt);
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier if (r >= 0)
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier return r;
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier }
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier for (;;) {
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier size_t m = COPY_BUFFER_SIZE;
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier ssize_t n;
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier if (max_bytes != (uint64_t) -1) {
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier if (max_bytes <= 0)
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier return -EFBIG;
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier if ((uint64_t) m > max_bytes)
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier m = (size_t) max_bytes;
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier }
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier /* First try sendfile(), unless we already tried */
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier if (try_sendfile) {
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier n = sendfile(fdt, fdf, NULL, m);
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier if (n < 0) {
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier if (errno != EINVAL && errno != ENOSYS)
8a8332f77e61d41f3bb28b8f929ed41e0ffaf721Zbigniew Jędrzejewski-Szmek return -errno;
8a8332f77e61d41f3bb28b8f929ed41e0ffaf721Zbigniew Jędrzejewski-Szmek
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier try_sendfile = false;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier /* use fallback below */
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier } else if (n == 0) /* EOF */
8a8332f77e61d41f3bb28b8f929ed41e0ffaf721Zbigniew Jędrzejewski-Szmek break;
8a8332f77e61d41f3bb28b8f929ed41e0ffaf721Zbigniew Jędrzejewski-Szmek else if (n > 0)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier /* Success! */
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier goto next;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier /* The try splice, unless we already tried */
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (try_splice) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier n = splice(fdf, NULL, fdt, NULL, m, 0);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (n < 0) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (errno != EINVAL && errno != ENOSYS)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return -errno;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier try_splice = false;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier /* use fallback below */
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier } else if (n == 0) /* EOF */
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier break;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier else if (n > 0)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier /* Success! */
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier goto next;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier /* As a fallback just copy bits by hand */
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier char buf[m];
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier n = read(fdf, buf, m);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (n < 0)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return -errno;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (n == 0) /* EOF */
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier break;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier r = loop_write(fdt, buf, (size_t) n, false);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (r < 0)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return r;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier next:
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (max_bytes != (uint64_t) -1) {
8a8332f77e61d41f3bb28b8f929ed41e0ffaf721Zbigniew Jędrzejewski-Szmek assert(max_bytes >= (uint64_t) n);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier max_bytes -= n;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return 0;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier}
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalierstatic int fd_copy_symlink(int df, const char *from, const struct stat *st, int dt, const char *to) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier _cleanup_free_ char *target = NULL;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier int r;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier assert(from);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier assert(st);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier assert(to);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
739d81ddd005fae2bb82edce5b8a6173c7c48b34Zbigniew Jędrzejewski-Szmek r = readlinkat_malloc(df, from, &target);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (r < 0)
b8667ee4162cd2510363602b417cecede9fd2ccaZbigniew Jędrzejewski-Szmek return r;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
739d81ddd005fae2bb82edce5b8a6173c7c48b34Zbigniew Jędrzejewski-Szmek if (symlinkat(target, dt, to) < 0)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return -errno;
b8667ee4162cd2510363602b417cecede9fd2ccaZbigniew Jędrzejewski-Szmek
b8667ee4162cd2510363602b417cecede9fd2ccaZbigniew Jędrzejewski-Szmek if (fchownat(dt, to, st->st_uid, st->st_gid, AT_SYMLINK_NOFOLLOW) < 0)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return -errno;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return 0;
739d81ddd005fae2bb82edce5b8a6173c7c48b34Zbigniew Jędrzejewski-Szmek}
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalierstatic int fd_copy_regular(int df, const char *from, const struct stat *st, int dt, const char *to) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier _cleanup_close_ int fdf = -1, fdt = -1;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier struct timespec ts[2];
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier int r, q;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier assert(from);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier assert(st);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier assert(to);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier fdf = openat(df, from, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (fdf < 0)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return -errno;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier fdt = openat(dt, to, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, st->st_mode & 07777);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (fdt < 0)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return -errno;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier r = copy_bytes(fdf, fdt, (uint64_t) -1, true);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (r < 0) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier unlinkat(dt, to, 0);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return r;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (fchown(fdt, st->st_uid, st->st_gid) < 0)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier r = -errno;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (fchmod(fdt, st->st_mode & 07777) < 0)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier r = -errno;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier ts[0] = st->st_atim;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier ts[1] = st->st_mtim;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier (void) futimens(fdt, ts);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier (void) copy_xattr(fdf, fdt);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier q = close(fdt);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier fdt = -1;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (q < 0) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier r = -errno;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier unlinkat(dt, to, 0);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return r;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier}
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalierstatic int fd_copy_fifo(int df, const char *from, const struct stat *st, int dt, const char *to) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier int r;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier assert(from);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier assert(st);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier assert(to);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier r = mkfifoat(dt, to, st->st_mode & 07777);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (r < 0)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return -errno;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (fchownat(dt, to, st->st_uid, st->st_gid, AT_SYMLINK_NOFOLLOW) < 0)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier r = -errno;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (fchmodat(dt, to, st->st_mode & 07777, 0) < 0)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier r = -errno;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return r;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier}
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalierstatic int fd_copy_node(int df, const char *from, const struct stat *st, int dt, const char *to) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier int r;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier assert(from);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier assert(st);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier assert(to);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier r = mknodat(dt, to, st->st_mode, st->st_rdev);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (r < 0)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return -errno;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (fchownat(dt, to, st->st_uid, st->st_gid, AT_SYMLINK_NOFOLLOW) < 0)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier r = -errno;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (fchmodat(dt, to, st->st_mode & 07777, 0) < 0)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier r = -errno;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return r;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier}
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalierstatic int fd_copy_directory(
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier int df,
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier const char *from,
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier const struct stat *st,
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier int dt,
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier const char *to,
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier dev_t original_device,
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier bool merge) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier _cleanup_close_ int fdf = -1, fdt = -1;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier _cleanup_closedir_ DIR *d = NULL;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier struct dirent *de;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier bool created;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier int r;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier assert(st);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier assert(to);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (from)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier fdf = openat(df, from, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier else
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier fdf = fcntl(df, F_DUPFD_CLOEXEC, 3);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier d = fdopendir(fdf);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (!d)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return -errno;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier fdf = -1;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier r = mkdirat(dt, to, st->st_mode & 07777);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (r >= 0)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier created = true;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier else if (errno == EEXIST && merge)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier created = false;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier else
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return -errno;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier fdt = openat(dt, to, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (fdt < 0)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return -errno;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier r = 0;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (created) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier struct timespec ut[2] = {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier st->st_atim,
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier st->st_mtim
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier };
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (fchown(fdt, st->st_uid, st->st_gid) < 0)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier r = -errno;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (fchmod(fdt, st->st_mode & 07777) < 0)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier r = -errno;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier (void) futimens(fdt, ut);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier (void) copy_xattr(dirfd(d), fdt);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier FOREACH_DIRENT_ALL(de, d, return -errno) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier struct stat buf;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier int q;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (STR_IN_SET(de->d_name, ".", ".."))
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier continue;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (fstatat(dirfd(d), de->d_name, &buf, AT_SYMLINK_NOFOLLOW) < 0) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier r = -errno;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier continue;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier }
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (buf.st_dev != original_device)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier continue;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (S_ISREG(buf.st_mode))
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier q = fd_copy_regular(dirfd(d), de->d_name, &buf, fdt, de->d_name);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier else if (S_ISDIR(buf.st_mode))
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier q = fd_copy_directory(dirfd(d), de->d_name, &buf, fdt, de->d_name, original_device, merge);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier else if (S_ISLNK(buf.st_mode))
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier q = fd_copy_symlink(dirfd(d), de->d_name, &buf, fdt, de->d_name);
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer else if (S_ISFIFO(buf.st_mode))
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier q = fd_copy_fifo(dirfd(d), de->d_name, &buf, fdt, de->d_name);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier else if (S_ISBLK(buf.st_mode) || S_ISCHR(buf.st_mode))
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier q = fd_copy_node(dirfd(d), de->d_name, &buf, fdt, de->d_name);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier else
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer q = -EOPNOTSUPP;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (q == -EEXIST && merge)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer q = 0;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (q < 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = q;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return r;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer}
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyerint copy_tree_at(int fdf, const char *from, int fdt, const char *to, bool merge) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer struct stat st;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(from);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(to);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (fstatat(fdf, from, &st, AT_SYMLINK_NOFOLLOW) < 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return -errno;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (S_ISREG(st.st_mode))
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return fd_copy_regular(fdf, from, &st, fdt, to);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer else if (S_ISDIR(st.st_mode))
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return fd_copy_directory(fdf, from, &st, fdt, to, st.st_dev, merge);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer else if (S_ISLNK(st.st_mode))
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return fd_copy_symlink(fdf, from, &st, fdt, to);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer else if (S_ISFIFO(st.st_mode))
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return fd_copy_fifo(fdf, from, &st, fdt, to);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer else if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode))
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return fd_copy_node(fdf, from, &st, fdt, to);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer else
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return -EOPNOTSUPP;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer}
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyerint copy_tree(const char *from, const char *to, bool merge) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return copy_tree_at(AT_FDCWD, from, AT_FDCWD, to, merge);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer}
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyerint copy_directory_fd(int dirfd, const char *to, bool merge) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer struct stat st;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(dirfd >= 0);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(to);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (fstat(dirfd, &st) < 0)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return -errno;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (!S_ISDIR(st.st_mode))
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier return -ENOTDIR;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return fd_copy_directory(dirfd, NULL, &st, AT_FDCWD, to, st.st_dev, merge);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer}
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyerint copy_file_fd(const char *from, int fdt, bool try_reflink) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer _cleanup_close_ int fdf = -1;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer int r;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(from);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(fdt >= 0);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer fdf = open(from, O_RDONLY|O_CLOEXEC|O_NOCTTY);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (fdf < 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return -errno;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = copy_bytes(fdf, fdt, (uint64_t) -1, try_reflink);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer (void) copy_times(fdf, fdt);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer (void) copy_xattr(fdf, fdt);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return r;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer}
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyerint copy_file(const char *from, const char *to, int flags, mode_t mode, unsigned chattr_flags) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer int fdt = -1, r;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(from);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(to);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer RUN_WITH_UMASK(0000) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer fdt = open(to, flags|O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, mode);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (fdt < 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return -errno;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (chattr_flags != 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer (void) chattr_fd(fdt, chattr_flags, (unsigned) -1);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = copy_file_fd(from, fdt, true);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer close(fdt);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer unlink(to);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return r;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (close(fdt) < 0) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer unlink_noerrno(to);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return -errno;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return 0;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer}
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyerint copy_file_atomic(const char *from, const char *to, mode_t mode, bool replace, unsigned chattr_flags) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer _cleanup_free_ char *t = NULL;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer int r;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(from);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(to);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = tempfn_random(to, NULL, &t);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return r;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = copy_file(from, t, O_NOFOLLOW|O_EXCL, mode, chattr_flags);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return r;
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (replace) {
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer r = renameat(AT_FDCWD, t, AT_FDCWD, to);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = -errno;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer } else
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = rename_noreplace(AT_FDCWD, t, AT_FDCWD, to);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer (void) unlink_noerrno(t);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return r;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return 0;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer}
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyerint copy_times(int fdf, int fdt) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer struct timespec ut[2];
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer struct stat st;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer usec_t crtime = 0;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(fdf >= 0);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(fdt >= 0);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (fstat(fdf, &st) < 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return -errno;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer ut[0] = st.st_atim;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer ut[1] = st.st_mtim;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (futimens(fdt, ut) < 0)
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer return -errno;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer if (fd_getcrtime(fdf, &crtime) >= 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer (void) fd_setcrtime(fdt, crtime);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return 0;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer}
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyerint copy_xattr(int fdf, int fdt) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer _cleanup_free_ char *bufa = NULL, *bufb = NULL;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer size_t sza = 100, szb = 100;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer ssize_t n;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer int ret = 0;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer const char *p;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer for (;;) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer bufa = malloc(sza);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (!bufa)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return -ENOMEM;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer n = flistxattr(fdf, bufa, sza);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (n == 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return 0;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (n > 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer break;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (errno != ERANGE)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return -errno;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer sza *= 2;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer bufa = mfree(bufa);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer p = bufa;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer while (n > 0) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer size_t l;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer l = strlen(p);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer assert(l < (size_t) n);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (startswith(p, "user.")) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer ssize_t m;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (!bufb) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer bufb = malloc(szb);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (!bufb)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return -ENOMEM;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer m = fgetxattr(fdf, p, bufb, szb);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (m < 0) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (errno == ERANGE) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer szb *= 2;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer bufb = mfree(bufb);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer continue;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return -errno;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (fsetxattr(fdt, p, bufb, m, 0) < 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer ret = -errno;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer p += l + 1;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer n -= l + 1;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer }
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer return ret;
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer}
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer