copy.c revision 93cc7779e0c121b75183920173f37cd1ee9d59cf
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright 2014 Lennart Poettering
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/sendfile.h>
#include <time.h>
#include <unistd.h>
#include "alloc-util.h"
#include "btrfs-util.h"
#include "chattr-util.h"
#include "copy.h"
#include "dirent-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
#include "io-util.h"
#include "macro.h"
#include "string-util.h"
#include "strv.h"
#include "time-util.h"
#include "umask-util.h"
#include "xattr-util.h"
bool try_sendfile = true, try_splice = true;
int r;
/* Try btrfs reflinks first. */
if (try_reflink &&
if (r >= 0)
return 0; /* we copied the whole thing, hence hit EOF, return 0 */
}
for (;;) {
size_t m = COPY_BUFFER_SIZE;
ssize_t n;
if (max_bytes <= 0)
return 1; /* return > 0 if we hit the max_bytes limit */
}
/* First try sendfile(), unless we already tried */
if (try_sendfile) {
if (n < 0) {
return -errno;
try_sendfile = false;
/* use fallback below */
} else if (n == 0) /* EOF */
break;
else if (n > 0)
/* Success! */
goto next;
}
/* The try splice, unless we already tried */
if (try_splice) {
if (n < 0) {
return -errno;
try_splice = false;
/* use fallback below */
} else if (n == 0) /* EOF */
break;
else if (n > 0)
/* Success! */
goto next;
}
/* As a fallback just copy bits by hand */
{
if (n < 0)
return -errno;
if (n == 0) /* EOF */
break;
if (r < 0)
return r;
}
next:
max_bytes -= n;
}
}
return 0; /* return 0 if we hit EOF earlier than the size limit */
}
static int fd_copy_symlink(int df, const char *from, const struct stat *st, int dt, const char *to) {
int r;
if (r < 0)
return r;
return -errno;
return -errno;
return 0;
}
static int fd_copy_regular(int df, const char *from, const struct stat *st, int dt, const char *to) {
int r, q;
if (fdf < 0)
return -errno;
if (fdt < 0)
return -errno;
if (r < 0) {
return r;
}
r = -errno;
r = -errno;
fdt = -1;
if (q < 0) {
r = -errno;
}
return r;
}
int r;
if (r < 0)
return -errno;
r = -errno;
r = -errno;
return r;
}
int r;
if (r < 0)
return -errno;
r = -errno;
r = -errno;
return r;
}
static int fd_copy_directory(
int df,
const char *from,
int dt,
const char *to,
bool merge) {
bool created;
int r;
if (from)
else
if (!d)
return -errno;
fdf = -1;
if (r >= 0)
created = true;
created = false;
else
return -errno;
if (fdt < 0)
return -errno;
r = 0;
if (created) {
};
r = -errno;
r = -errno;
}
int q;
continue;
r = -errno;
continue;
}
continue;
else
q = -EOPNOTSUPP;
q = 0;
if (q < 0)
r = q;
}
return r;
}
return -errno;
else
return -EOPNOTSUPP;
}
}
return -errno;
return -ENOTDIR;
}
int r;
if (fdf < 0)
return -errno;
return r;
}
int fdt = -1, r;
RUN_WITH_UMASK(0000) {
if (fdt < 0)
return -errno;
}
if (chattr_flags != 0)
if (r < 0) {
return r;
}
return -errno;
}
return 0;
}
int copy_file_atomic(const char *from, const char *to, mode_t mode, bool replace, unsigned chattr_flags) {
_cleanup_free_ char *t = NULL;
int r;
if (r < 0)
return r;
if (r < 0)
return r;
if (replace) {
if (r < 0)
r = -errno;
} else
if (r < 0) {
(void) unlink_noerrno(t);
return r;
}
return 0;
}
return -errno;
return -errno;
return 0;
}
ssize_t n;
int ret = 0;
const char *p;
for (;;) {
if (!bufa)
return -ENOMEM;
if (n == 0)
return 0;
if (n > 0)
break;
return -errno;
sza *= 2;
}
p = bufa;
while (n > 0) {
size_t l;
l = strlen(p);
if (startswith(p, "user.")) {
ssize_t m;
if (!bufb) {
if (!bufb)
return -ENOMEM;
}
if (m < 0) {
szb *= 2;
continue;
}
return -errno;
}
}
p += l + 1;
n -= l + 1;
}
return ret;
}