]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/copy.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / basic / copy.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2014 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <dirent.h>
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <stddef.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <sys/sendfile.h>
29 #include <sys/stat.h>
30 #include <sys/xattr.h>
31 #include <time.h>
32 #include <unistd.h>
33
34 #include "alloc-util.h"
35 #include "btrfs-util.h"
36 #include "chattr-util.h"
37 #include "copy.h"
38 #include "dirent-util.h"
39 #include "fd-util.h"
40 #include "fileio.h"
41 #include "fs-util.h"
42 #include "io-util.h"
43 #include "macro.h"
44 #include "missing.h"
45 #include "string-util.h"
46 #include "strv.h"
47 #include "time-util.h"
48 #include "umask-util.h"
49 #include "user-util.h"
50 #include "xattr-util.h"
51
52 #define COPY_BUFFER_SIZE (16*1024u)
53
54 static ssize_t try_copy_file_range(int fd_in, loff_t *off_in,
55 int fd_out, loff_t *off_out,
56 size_t len,
57 unsigned int flags) {
58 static int have = -1;
59 ssize_t r;
60
61 if (have == false)
62 return -ENOSYS;
63
64 r = copy_file_range(fd_in, off_in, fd_out, off_out, len, flags);
65 if (_unlikely_(have < 0))
66 have = r >= 0 || errno != ENOSYS;
67 if (r >= 0)
68 return r;
69 else
70 return -errno;
71 }
72
73 int copy_bytes(int fdf, int fdt, uint64_t max_bytes, CopyFlags copy_flags) {
74 bool try_cfr = true, try_sendfile = true, try_splice = true;
75 int r;
76 size_t m = SSIZE_MAX; /* that is the maximum that sendfile and c_f_r accept */
77
78 assert(fdf >= 0);
79 assert(fdt >= 0);
80
81 /* Try btrfs reflinks first. */
82 if ((copy_flags & COPY_REFLINK) &&
83 max_bytes == (uint64_t) -1 &&
84 lseek(fdf, 0, SEEK_CUR) == 0 &&
85 lseek(fdt, 0, SEEK_CUR) == 0) {
86
87 r = btrfs_reflink(fdf, fdt);
88 if (r >= 0)
89 return 0; /* we copied the whole thing, hence hit EOF, return 0 */
90 }
91
92 for (;;) {
93 ssize_t n;
94
95 if (max_bytes != (uint64_t) -1) {
96 if (max_bytes <= 0)
97 return 1; /* return > 0 if we hit the max_bytes limit */
98
99 if (m > max_bytes)
100 m = max_bytes;
101 }
102
103 /* First try copy_file_range(), unless we already tried */
104 if (try_cfr) {
105 n = try_copy_file_range(fdf, NULL, fdt, NULL, m, 0u);
106 if (n < 0) {
107 if (!IN_SET(n, -EINVAL, -ENOSYS, -EXDEV, -EBADF))
108 return n;
109
110 try_cfr = false;
111 /* use fallback below */
112 } else if (n == 0) /* EOF */
113 break;
114 else
115 /* Success! */
116 goto next;
117 }
118
119 /* First try sendfile(), unless we already tried */
120 if (try_sendfile) {
121 n = sendfile(fdt, fdf, NULL, m);
122 if (n < 0) {
123 if (!IN_SET(errno, EINVAL, ENOSYS))
124 return -errno;
125
126 try_sendfile = false;
127 /* use fallback below */
128 } else if (n == 0) /* EOF */
129 break;
130 else
131 /* Success! */
132 goto next;
133 }
134
135 /* Then try splice, unless we already tried */
136 if (try_splice) {
137 n = splice(fdf, NULL, fdt, NULL, m, 0);
138 if (n < 0) {
139 if (!IN_SET(errno, EINVAL, ENOSYS))
140 return -errno;
141
142 try_splice = false;
143 /* use fallback below */
144 } else if (n == 0) /* EOF */
145 break;
146 else
147 /* Success! */
148 goto next;
149 }
150
151 /* As a fallback just copy bits by hand */
152 {
153 uint8_t buf[MIN(m, COPY_BUFFER_SIZE)];
154
155 n = read(fdf, buf, sizeof buf);
156 if (n < 0)
157 return -errno;
158 if (n == 0) /* EOF */
159 break;
160
161 r = loop_write(fdt, buf, (size_t) n, false);
162 if (r < 0)
163 return r;
164 }
165
166 next:
167 if (max_bytes != (uint64_t) -1) {
168 assert(max_bytes >= (uint64_t) n);
169 max_bytes -= n;
170 }
171 /* sendfile accepts at most SSIZE_MAX-offset bytes to copy,
172 * so reduce our maximum by the amount we already copied,
173 * but don't go below our copy buffer size, unless we are
174 * close the limit of bytes we are allowed to copy. */
175 m = MAX(MIN(COPY_BUFFER_SIZE, max_bytes), m - n);
176 }
177
178 return 0; /* return 0 if we hit EOF earlier than the size limit */
179 }
180
181 static int fd_copy_symlink(
182 int df,
183 const char *from,
184 const struct stat *st,
185 int dt,
186 const char *to,
187 uid_t override_uid,
188 gid_t override_gid,
189 CopyFlags copy_flags) {
190
191 _cleanup_free_ char *target = NULL;
192 int r;
193
194 assert(from);
195 assert(st);
196 assert(to);
197
198 r = readlinkat_malloc(df, from, &target);
199 if (r < 0)
200 return r;
201
202 if (symlinkat(target, dt, to) < 0)
203 return -errno;
204
205 if (fchownat(dt, to,
206 uid_is_valid(override_uid) ? override_uid : st->st_uid,
207 gid_is_valid(override_gid) ? override_gid : st->st_gid,
208 AT_SYMLINK_NOFOLLOW) < 0)
209 return -errno;
210
211 return 0;
212 }
213
214 static int fd_copy_regular(
215 int df,
216 const char *from,
217 const struct stat *st,
218 int dt,
219 const char *to,
220 uid_t override_uid,
221 gid_t override_gid,
222 CopyFlags copy_flags) {
223
224 _cleanup_close_ int fdf = -1, fdt = -1;
225 struct timespec ts[2];
226 int r, q;
227
228 assert(from);
229 assert(st);
230 assert(to);
231
232 fdf = openat(df, from, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
233 if (fdf < 0)
234 return -errno;
235
236 fdt = openat(dt, to, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, st->st_mode & 07777);
237 if (fdt < 0)
238 return -errno;
239
240 r = copy_bytes(fdf, fdt, (uint64_t) -1, copy_flags);
241 if (r < 0) {
242 unlinkat(dt, to, 0);
243 return r;
244 }
245
246 if (fchown(fdt,
247 uid_is_valid(override_uid) ? override_uid : st->st_uid,
248 gid_is_valid(override_gid) ? override_gid : st->st_gid) < 0)
249 r = -errno;
250
251 if (fchmod(fdt, st->st_mode & 07777) < 0)
252 r = -errno;
253
254 ts[0] = st->st_atim;
255 ts[1] = st->st_mtim;
256 (void) futimens(fdt, ts);
257 (void) copy_xattr(fdf, fdt);
258
259 q = close(fdt);
260 fdt = -1;
261
262 if (q < 0) {
263 r = -errno;
264 unlinkat(dt, to, 0);
265 }
266
267 return r;
268 }
269
270 static int fd_copy_fifo(
271 int df,
272 const char *from,
273 const struct stat *st,
274 int dt,
275 const char *to,
276 uid_t override_uid,
277 gid_t override_gid,
278 CopyFlags copy_flags) {
279 int r;
280
281 assert(from);
282 assert(st);
283 assert(to);
284
285 r = mkfifoat(dt, to, st->st_mode & 07777);
286 if (r < 0)
287 return -errno;
288
289 if (fchownat(dt, to,
290 uid_is_valid(override_uid) ? override_uid : st->st_uid,
291 gid_is_valid(override_gid) ? override_gid : st->st_gid,
292 AT_SYMLINK_NOFOLLOW) < 0)
293 r = -errno;
294
295 if (fchmodat(dt, to, st->st_mode & 07777, 0) < 0)
296 r = -errno;
297
298 return r;
299 }
300
301 static int fd_copy_node(
302 int df,
303 const char *from,
304 const struct stat *st,
305 int dt,
306 const char *to,
307 uid_t override_uid,
308 gid_t override_gid,
309 CopyFlags copy_flags) {
310 int r;
311
312 assert(from);
313 assert(st);
314 assert(to);
315
316 r = mknodat(dt, to, st->st_mode, st->st_rdev);
317 if (r < 0)
318 return -errno;
319
320 if (fchownat(dt, to,
321 uid_is_valid(override_uid) ? override_uid : st->st_uid,
322 gid_is_valid(override_gid) ? override_gid : st->st_gid,
323 AT_SYMLINK_NOFOLLOW) < 0)
324 r = -errno;
325
326 if (fchmodat(dt, to, st->st_mode & 07777, 0) < 0)
327 r = -errno;
328
329 return r;
330 }
331
332 static int fd_copy_directory(
333 int df,
334 const char *from,
335 const struct stat *st,
336 int dt,
337 const char *to,
338 dev_t original_device,
339 uid_t override_uid,
340 gid_t override_gid,
341 CopyFlags copy_flags) {
342
343 _cleanup_close_ int fdf = -1, fdt = -1;
344 _cleanup_closedir_ DIR *d = NULL;
345 struct dirent *de;
346 bool created;
347 int r;
348
349 assert(st);
350 assert(to);
351
352 if (from)
353 fdf = openat(df, from, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
354 else
355 fdf = fcntl(df, F_DUPFD_CLOEXEC, 3);
356 if (fdf < 0)
357 return -errno;
358
359 d = fdopendir(fdf);
360 if (!d)
361 return -errno;
362 fdf = -1;
363
364 r = mkdirat(dt, to, st->st_mode & 07777);
365 if (r >= 0)
366 created = true;
367 else if (errno == EEXIST && (copy_flags & COPY_MERGE))
368 created = false;
369 else
370 return -errno;
371
372 fdt = openat(dt, to, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
373 if (fdt < 0)
374 return -errno;
375
376 r = 0;
377
378 FOREACH_DIRENT_ALL(de, d, return -errno) {
379 struct stat buf;
380 int q;
381
382 if (dot_or_dot_dot(de->d_name))
383 continue;
384
385 if (fstatat(dirfd(d), de->d_name, &buf, AT_SYMLINK_NOFOLLOW) < 0) {
386 r = -errno;
387 continue;
388 }
389
390 if (buf.st_dev != original_device)
391 continue;
392
393 if (S_ISREG(buf.st_mode))
394 q = fd_copy_regular(dirfd(d), de->d_name, &buf, fdt, de->d_name, override_uid, override_gid, copy_flags);
395 else if (S_ISDIR(buf.st_mode))
396 q = fd_copy_directory(dirfd(d), de->d_name, &buf, fdt, de->d_name, original_device, override_uid, override_gid, copy_flags);
397 else if (S_ISLNK(buf.st_mode))
398 q = fd_copy_symlink(dirfd(d), de->d_name, &buf, fdt, de->d_name, override_uid, override_gid, copy_flags);
399 else if (S_ISFIFO(buf.st_mode))
400 q = fd_copy_fifo(dirfd(d), de->d_name, &buf, fdt, de->d_name, override_uid, override_gid, copy_flags);
401 else if (S_ISBLK(buf.st_mode) || S_ISCHR(buf.st_mode) || S_ISSOCK(buf.st_mode))
402 q = fd_copy_node(dirfd(d), de->d_name, &buf, fdt, de->d_name, override_uid, override_gid, copy_flags);
403 else
404 q = -EOPNOTSUPP;
405
406 if (q == -EEXIST && (copy_flags & COPY_MERGE))
407 q = 0;
408
409 if (q < 0)
410 r = q;
411 }
412
413 if (created) {
414 struct timespec ut[2] = {
415 st->st_atim,
416 st->st_mtim
417 };
418
419 if (fchown(fdt,
420 uid_is_valid(override_uid) ? override_uid : st->st_uid,
421 gid_is_valid(override_gid) ? override_gid : st->st_gid) < 0)
422 r = -errno;
423
424 if (fchmod(fdt, st->st_mode & 07777) < 0)
425 r = -errno;
426
427 (void) copy_xattr(dirfd(d), fdt);
428 (void) futimens(fdt, ut);
429 }
430
431 return r;
432 }
433
434 int copy_tree_at(int fdf, const char *from, int fdt, const char *to, uid_t override_uid, gid_t override_gid, CopyFlags copy_flags) {
435 struct stat st;
436
437 assert(from);
438 assert(to);
439
440 if (fstatat(fdf, from, &st, AT_SYMLINK_NOFOLLOW) < 0)
441 return -errno;
442
443 if (S_ISREG(st.st_mode))
444 return fd_copy_regular(fdf, from, &st, fdt, to, override_uid, override_gid, copy_flags);
445 else if (S_ISDIR(st.st_mode))
446 return fd_copy_directory(fdf, from, &st, fdt, to, st.st_dev, override_uid, override_gid, copy_flags);
447 else if (S_ISLNK(st.st_mode))
448 return fd_copy_symlink(fdf, from, &st, fdt, to, override_uid, override_gid, copy_flags);
449 else if (S_ISFIFO(st.st_mode))
450 return fd_copy_fifo(fdf, from, &st, fdt, to, override_uid, override_gid, copy_flags);
451 else if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode) || S_ISSOCK(st.st_mode))
452 return fd_copy_node(fdf, from, &st, fdt, to, override_uid, override_gid, copy_flags);
453 else
454 return -EOPNOTSUPP;
455 }
456
457 int copy_tree(const char *from, const char *to, uid_t override_uid, gid_t override_gid, CopyFlags copy_flags) {
458 return copy_tree_at(AT_FDCWD, from, AT_FDCWD, to, override_uid, override_gid, copy_flags);
459 }
460
461 int copy_directory_fd(int dirfd, const char *to, CopyFlags copy_flags) {
462 struct stat st;
463
464 assert(dirfd >= 0);
465 assert(to);
466
467 if (fstat(dirfd, &st) < 0)
468 return -errno;
469
470 if (!S_ISDIR(st.st_mode))
471 return -ENOTDIR;
472
473 return fd_copy_directory(dirfd, NULL, &st, AT_FDCWD, to, st.st_dev, UID_INVALID, GID_INVALID, copy_flags);
474 }
475
476 int copy_directory(const char *from, const char *to, CopyFlags copy_flags) {
477 struct stat st;
478
479 assert(from);
480 assert(to);
481
482 if (lstat(from, &st) < 0)
483 return -errno;
484
485 if (!S_ISDIR(st.st_mode))
486 return -ENOTDIR;
487
488 return fd_copy_directory(AT_FDCWD, from, &st, AT_FDCWD, to, st.st_dev, UID_INVALID, GID_INVALID, copy_flags);
489 }
490
491 int copy_file_fd(const char *from, int fdt, CopyFlags copy_flags) {
492 _cleanup_close_ int fdf = -1;
493 int r;
494
495 assert(from);
496 assert(fdt >= 0);
497
498 fdf = open(from, O_RDONLY|O_CLOEXEC|O_NOCTTY);
499 if (fdf < 0)
500 return -errno;
501
502 r = copy_bytes(fdf, fdt, (uint64_t) -1, copy_flags);
503
504 (void) copy_times(fdf, fdt);
505 (void) copy_xattr(fdf, fdt);
506
507 return r;
508 }
509
510 int copy_file(const char *from, const char *to, int flags, mode_t mode, unsigned chattr_flags, CopyFlags copy_flags) {
511 int fdt = -1, r;
512
513 assert(from);
514 assert(to);
515
516 RUN_WITH_UMASK(0000) {
517 fdt = open(to, flags|O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, mode);
518 if (fdt < 0)
519 return -errno;
520 }
521
522 if (chattr_flags != 0)
523 (void) chattr_fd(fdt, chattr_flags, (unsigned) -1);
524
525 r = copy_file_fd(from, fdt, copy_flags);
526 if (r < 0) {
527 close(fdt);
528 unlink(to);
529 return r;
530 }
531
532 if (close(fdt) < 0) {
533 unlink_noerrno(to);
534 return -errno;
535 }
536
537 return 0;
538 }
539
540 int copy_file_atomic(const char *from, const char *to, mode_t mode, unsigned chattr_flags, CopyFlags copy_flags) {
541 _cleanup_free_ char *t = NULL;
542 int r;
543
544 assert(from);
545 assert(to);
546
547 r = tempfn_random(to, NULL, &t);
548 if (r < 0)
549 return r;
550
551 r = copy_file(from, t, O_NOFOLLOW|O_EXCL, mode, chattr_flags, copy_flags);
552 if (r < 0)
553 return r;
554
555 if (copy_flags & COPY_REPLACE) {
556 r = renameat(AT_FDCWD, t, AT_FDCWD, to);
557 if (r < 0)
558 r = -errno;
559 } else
560 r = rename_noreplace(AT_FDCWD, t, AT_FDCWD, to);
561 if (r < 0) {
562 (void) unlink(t);
563 return r;
564 }
565
566 return 0;
567 }
568
569 int copy_times(int fdf, int fdt) {
570 struct timespec ut[2];
571 struct stat st;
572 usec_t crtime = 0;
573
574 assert(fdf >= 0);
575 assert(fdt >= 0);
576
577 if (fstat(fdf, &st) < 0)
578 return -errno;
579
580 ut[0] = st.st_atim;
581 ut[1] = st.st_mtim;
582
583 if (futimens(fdt, ut) < 0)
584 return -errno;
585
586 if (fd_getcrtime(fdf, &crtime) >= 0)
587 (void) fd_setcrtime(fdt, crtime);
588
589 return 0;
590 }
591
592 int copy_xattr(int fdf, int fdt) {
593 _cleanup_free_ char *bufa = NULL, *bufb = NULL;
594 size_t sza = 100, szb = 100;
595 ssize_t n;
596 int ret = 0;
597 const char *p;
598
599 for (;;) {
600 bufa = malloc(sza);
601 if (!bufa)
602 return -ENOMEM;
603
604 n = flistxattr(fdf, bufa, sza);
605 if (n == 0)
606 return 0;
607 if (n > 0)
608 break;
609 if (errno != ERANGE)
610 return -errno;
611
612 sza *= 2;
613
614 bufa = mfree(bufa);
615 }
616
617 p = bufa;
618 while (n > 0) {
619 size_t l;
620
621 l = strlen(p);
622 assert(l < (size_t) n);
623
624 if (startswith(p, "user.")) {
625 ssize_t m;
626
627 if (!bufb) {
628 bufb = malloc(szb);
629 if (!bufb)
630 return -ENOMEM;
631 }
632
633 m = fgetxattr(fdf, p, bufb, szb);
634 if (m < 0) {
635 if (errno == ERANGE) {
636 szb *= 2;
637 bufb = mfree(bufb);
638 continue;
639 }
640
641 return -errno;
642 }
643
644 if (fsetxattr(fdt, p, bufb, m, 0) < 0)
645 ret = -errno;
646 }
647
648 p += l + 1;
649 n -= l + 1;
650 }
651
652 return ret;
653 }