Annotation of src/usr.bin/rsync/copy.c, Revision 1.2.4.1
1.2.4.1 ! bluhm 1: /* $OpenBSD: copy.c,v 1.2 2021/10/24 21:24:17 deraadt Exp $ */
1.1 claudio 2: /*
3: * Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org>
4: *
5: * Permission to use, copy, modify, and distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
8: *
9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16: */
17:
18: #include <sys/param.h> /* MAXBSIZE */
19:
20: #include <err.h>
21: #include <fcntl.h>
22: #include <unistd.h>
23:
24: #include "extern.h"
25:
26: /*
27: * Return true if all bytes in buffer are zero.
28: * A buffer of zero lenght is also considered a zero buffer.
29: */
30: static int
31: iszero(const void *b, size_t len)
32: {
33: const unsigned char *c = b;
34:
35: for (; len > 0; len--) {
36: if (*c++ != '\0')
37: return 0;
38: }
39: return 1;
40: }
41:
42: static int
43: copy_internal(int fromfd, int tofd)
44: {
45: char buf[MAXBSIZE];
46: ssize_t r, w;
47:
48: while ((r = read(fromfd, buf, sizeof(buf))) > 0) {
49: if (iszero(buf, sizeof(buf))) {
50: if (lseek(tofd, r, SEEK_CUR) == -1)
51: return -1;
52: } else {
53: w = write(tofd, buf, r);
54: if (r != w || w == -1)
55: return -1;
56: }
57: }
58: if (r == -1)
59: return -1;
60: if (ftruncate(tofd, lseek(tofd, 0, SEEK_CUR)) == -1)
61: return -1;
62: return 0;
63: }
64:
65: void
66: copy_file(int rootfd, const char *basedir, const struct flist *f)
67: {
68: int fromfd, tofd, dfd;
69:
1.2 deraadt 70: dfd = openat(rootfd, basedir, O_RDONLY | O_DIRECTORY);
1.1 claudio 71: if (dfd == -1)
72: err(ERR_FILE_IO, "%s: openat", basedir);
73:
1.2 deraadt 74: fromfd = openat(dfd, f->path, O_RDONLY | O_NOFOLLOW);
1.1 claudio 75: if (fromfd == -1)
76: err(ERR_FILE_IO, "%s/%s: openat", basedir, f->path);
77: close(dfd);
78:
79: tofd = openat(rootfd, f->path,
80: O_WRONLY | O_NOFOLLOW | O_TRUNC | O_CREAT | O_EXCL,
81: 0600);
82: if (tofd == -1)
83: err(ERR_FILE_IO, "%s: openat", f->path);
84:
85: if (copy_internal(fromfd, tofd) == -1)
86: err(ERR_FILE_IO, "%s: copy file", f->path);
87:
88: close(fromfd);
89: close(tofd);
90: }