Annotation of src/usr.bin/rsync/server.c, Revision 1.1
1.1 ! benno 1: /* $Id$ */
! 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>
! 25:
! 26: #include "extern.h"
! 27:
! 28: static int
! 29: fcntl_nonblock(struct sess *sess, int fd)
! 30: {
! 31: int fl;
! 32:
! 33: if (-1 == (fl = fcntl(fd, F_GETFL, 0)))
! 34: ERR(sess, "fcntl: F_GETFL");
! 35: else if (-1 == fcntl(fd, F_SETFL, fl|O_NONBLOCK))
! 36: ERR(sess, "fcntl: F_SETFL");
! 37: else
! 38: return 1;
! 39:
! 40: return 0;
! 41: }
! 42:
! 43: /*
! 44: * The server (remote) side of the system.
! 45: * This parses the arguments given it by the remote shell then moves
! 46: * into receiver or sender mode depending upon those arguments.
! 47: *
! 48: * Pledges: unveil rpath, cpath, wpath, stdio, fattr.
! 49: *
! 50: * Pledges (dry-run): -cpath, -wpath, -fattr.
! 51: * Pledges (!preserve_times): -fattr.
! 52: */
! 53: int
! 54: rsync_server(const struct opts *opts, size_t argc, char *argv[])
! 55: {
! 56: struct sess sess;
! 57: int fdin = STDIN_FILENO,
! 58: fdout = STDOUT_FILENO, c = 0;
! 59:
! 60: memset(&sess, 0, sizeof(struct sess));
! 61: sess.opts = opts;
! 62:
! 63: /* Begin by making descriptors non-blocking. */
! 64:
! 65: if ( ! fcntl_nonblock(&sess, fdin) ||
! 66: ! fcntl_nonblock(&sess, fdout)) {
! 67: ERRX1(&sess, "fcntl_nonblock");
! 68: goto out;
! 69: }
! 70:
! 71: /* Standard rsync preamble, server side. */
! 72:
! 73: sess.lver = RSYNC_PROTOCOL;
! 74: sess.seed = arc4random();
! 75:
! 76: if ( ! io_read_int(&sess, fdin, &sess.rver)) {
! 77: ERRX1(&sess, "io_read_int");
! 78: goto out;
! 79: } else if ( ! io_write_int(&sess, fdout, sess.lver)) {
! 80: ERRX1(&sess, "io_write_int");
! 81: goto out;
! 82: } else if ( ! io_write_int(&sess, fdout, sess.seed)) {
! 83: ERRX1(&sess, "io_write_int");
! 84: goto out;
! 85: }
! 86:
! 87: sess.mplex_writes = 1;
! 88:
! 89: if (sess.rver < sess.lver) {
! 90: ERRX(&sess, "remote protocol is older "
! 91: "than our own (%" PRId32 " < %" PRId32 "): "
! 92: "this is not supported",
! 93: sess.rver, sess.lver);
! 94: goto out;
! 95: }
! 96:
! 97: LOG2(&sess, "server detected client version %" PRId32
! 98: ", server version %" PRId32 ", seed %" PRId32,
! 99: sess.rver, sess.lver, sess.seed);
! 100:
! 101: if (sess.opts->sender) {
! 102: LOG2(&sess, "server starting sender");
! 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], ".")) {
! 113: ERRX(&sess, "first argument must "
! 114: "be a standalone period");
! 115: goto out;
! 116: }
! 117: argv++;
! 118: argc--;
! 119: if (0 == argc) {
! 120: ERRX(&sess, "must have arguments");
! 121: goto out;
! 122: }
! 123:
! 124: if ( ! rsync_sender(&sess, fdin, fdout, argc, argv)) {
! 125: ERRX1(&sess, "rsync_sender");
! 126: goto out;
! 127: }
! 128: } else {
! 129: LOG2(&sess, "server starting receiver");
! 130:
! 131: /*
! 132: * I don't understand why this calling convention
! 133: * exists, but we must adhere to it.
! 134: * rsync [flags] "." <destination>
! 135: */
! 136:
! 137: if (2 != argc) {
! 138: ERRX(&sess, "server receiver mode "
! 139: "requires two argument");
! 140: goto out;
! 141: } else if (strcmp(argv[0], ".")) {
! 142: ERRX(&sess, "first argument must "
! 143: "be a standalone period");
! 144: goto out;
! 145: }
! 146:
! 147: if ( ! rsync_receiver(&sess, fdin, fdout, argv[1])) {
! 148: ERRX1(&sess, "rsync_receiver");
! 149: goto out;
! 150: }
! 151: }
! 152:
! 153: #if 0
! 154: /* Probably the EOF. */
! 155: if (io_read_check(&sess, fdin))
! 156: WARNX(&sess, "data remains in read pipe");
! 157: #endif
! 158:
! 159: c = 1;
! 160: out:
! 161: return c;
! 162: }