Annotation of src/usr.bin/rsync/server.c, Revision 1.13
1.13 ! claudio 1: /* $Id: server.c,v 1.12 2019/05/08 21:30:11 benno Exp $ */
1.1 benno 2: /*
3: * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
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: #include <sys/stat.h>
18:
19: #include <assert.h>
20: #include <fcntl.h>
21: #include <inttypes.h>
22: #include <stdlib.h>
23: #include <string.h>
24: #include <unistd.h>
1.8 deraadt 25: #include <err.h>
1.1 benno 26:
27: #include "extern.h"
28:
29: static int
1.12 benno 30: fcntl_nonblock(int fd)
1.1 benno 31: {
32: int fl;
33:
1.4 deraadt 34: if ((fl = fcntl(fd, F_GETFL, 0)) == -1)
1.11 benno 35: ERR("fcntl: F_GETFL");
1.4 deraadt 36: else if (fcntl(fd, F_SETFL, fl|O_NONBLOCK) == -1)
1.11 benno 37: ERR("fcntl: F_SETFL");
1.1 benno 38: else
39: return 1;
40:
41: return 0;
42: }
43:
44: /*
45: * The server (remote) side of the system.
46: * This parses the arguments given it by the remote shell then moves
47: * into receiver or sender mode depending upon those arguments.
1.9 deraadt 48: * Returns exit code 0 on success, 1 on failure, 2 on failure with
49: * incompatible protocols.
1.1 benno 50: */
51: int
52: rsync_server(const struct opts *opts, size_t argc, char *argv[])
53: {
54: struct sess sess;
1.2 benno 55: int fdin = STDIN_FILENO,
1.9 deraadt 56: fdout = STDOUT_FILENO, rc = 1;
1.8 deraadt 57:
58: if (pledge("stdio unix rpath wpath cpath dpath fattr chown getpw unveil",
59: NULL) == -1)
1.13 ! claudio 60: err(ERR_IPC, "pledge");
1.1 benno 61:
62: memset(&sess, 0, sizeof(struct sess));
63: sess.opts = opts;
64:
65: /* Begin by making descriptors non-blocking. */
66:
1.12 benno 67: if (!fcntl_nonblock(fdin) ||
68: !fcntl_nonblock(fdout)) {
1.11 benno 69: ERRX1("fcntl_nonblock");
1.1 benno 70: goto out;
71: }
72:
73: /* Standard rsync preamble, server side. */
74:
75: sess.lver = RSYNC_PROTOCOL;
76: sess.seed = arc4random();
77:
1.3 deraadt 78: if (!io_read_int(&sess, fdin, &sess.rver)) {
1.11 benno 79: ERRX1("io_read_int");
1.1 benno 80: goto out;
1.3 deraadt 81: } else if (!io_write_int(&sess, fdout, sess.lver)) {
1.11 benno 82: ERRX1("io_write_int");
1.1 benno 83: goto out;
1.3 deraadt 84: } else if (!io_write_int(&sess, fdout, sess.seed)) {
1.11 benno 85: ERRX1("io_write_int");
1.1 benno 86: goto out;
87: }
88:
89: sess.mplex_writes = 1;
90:
91: if (sess.rver < sess.lver) {
1.11 benno 92: ERRX("remote protocol %d is older than our own %d: unsupported",
1.7 benno 93: sess.rver, sess.lver);
94: rc = 2;
1.1 benno 95: goto out;
96: }
97:
1.11 benno 98: LOG2("server detected client version %d, server version %d, seed %d",
1.10 deraadt 99: sess.rver, sess.lver, sess.seed);
1.1 benno 100:
101: if (sess.opts->sender) {
1.11 benno 102: LOG2("server starting sender");
1.1 benno 103:
104: /*
105: * At this time, I always get a period as the first
106: * argument of the command line.
107: * Let's make it a requirement until I figure out when
108: * that differs.
109: * rsync [flags] "." <source> <...>
110: */
111:
112: if (strcmp(argv[0], ".")) {
1.11 benno 113: ERRX("first argument must be a standalone period");
1.1 benno 114: goto out;
115: }
116: argv++;
117: argc--;
1.4 deraadt 118: if (argc == 0) {
1.11 benno 119: ERRX("must have arguments");
1.1 benno 120: goto out;
121: }
122:
1.3 deraadt 123: if (!rsync_sender(&sess, fdin, fdout, argc, argv)) {
1.11 benno 124: ERRX1("rsync_sender");
1.1 benno 125: goto out;
126: }
127: } else {
1.11 benno 128: LOG2("server starting receiver");
1.1 benno 129:
130: /*
131: * I don't understand why this calling convention
132: * exists, but we must adhere to it.
133: * rsync [flags] "." <destination>
134: */
135:
1.4 deraadt 136: if (argc != 2) {
1.11 benno 137: ERRX("server receiver mode requires two argument");
1.1 benno 138: goto out;
139: } else if (strcmp(argv[0], ".")) {
1.11 benno 140: ERRX("first argument must be a standalone period");
1.1 benno 141: goto out;
142: }
143:
1.3 deraadt 144: if (!rsync_receiver(&sess, fdin, fdout, argv[1])) {
1.11 benno 145: ERRX1("rsync_receiver");
1.1 benno 146: goto out;
147: }
148: }
149:
150: #if 0
151: /* Probably the EOF. */
152: if (io_read_check(&sess, fdin))
1.11 benno 153: WARNX("data remains in read pipe");
1.1 benno 154: #endif
155:
1.9 deraadt 156: rc = 0;
1.1 benno 157: out:
1.7 benno 158: return rc;
1.1 benno 159: }