X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/65f6b6b0ef8684bfe7d0ab018ae10a19ddfb1d23..ec8637f3679b891041c798400774141024e24a4e:/clientserver.c diff --git a/clientserver.c b/clientserver.c index 20a164e6..1e3af63a 100644 --- a/clientserver.c +++ b/clientserver.c @@ -23,6 +23,7 @@ #include "ifuncs.h" extern int verbose; +extern int dry_run; extern int output_motd; extern int list_only; extern int am_sender; @@ -39,6 +40,7 @@ extern int remote_protocol; extern int protocol_version; extern int io_timeout; extern int no_detach; +extern int write_batch; extern int default_af_hint; extern int logfile_format_has_i; extern int logfile_format_has_o_or_i; @@ -56,6 +58,7 @@ extern char curr_dir[]; char *auth_user; int read_only = 0; int module_id = -1; +int munge_symlinks = 0; struct chmod_mode_struct *daemon_chmod_modes; /* module_dirlen is the length of the module_dir string when in daemon @@ -192,21 +195,31 @@ static int exchange_protocols(int f_in, int f_out, char *buf, size_t bufsiz, int int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char *argv[]) { - int i; + int i, modlen; char line[BIGPATHBUFLEN]; char *sargs[MAX_ARGS]; int sargc = 0; - char *p, *path = *argv; + char *p, *modname; - if (argc == 0 && !am_sender) - list_only |= 1; + assert(argc > 0); - if (*path == '/') { + if (**argv == '/') { rprintf(FERROR, "ERROR: The remote path must start with a module name\n"); return -1; } + if (!(p = strchr(*argv, '/'))) + modlen = strlen(*argv); + else + modlen = p - *argv; + + if (!(modname = new_array(char, modlen+1+1))) /* room for '/' & '\0' */ + out_of_memory("start_inband_exchange"); + strlcpy(modname, *argv, modlen + 1); + modname[modlen] = '/'; + modname[modlen+1] = '\0'; + if (!user) user = getenv("USER"); if (!user) @@ -232,7 +245,12 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char rprintf(FERROR, "internal: args[] overflowed in do_cmd()\n"); exit_cleanup(RERR_SYNTAX); } - sargs[sargc++] = *argv++; + if (list_only && strncmp(*argv, modname, modlen) == 0 + && argv[0][modlen] == '\0') + sargs[sargc++] = modname; /* we send "modname/" */ + else + sargs[sargc++] = *argv; + argv++; argc--; } @@ -241,10 +259,7 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char if (verbose > 1) print_child_argv("sending daemon args:", sargs); - p = strchr(path, '/'); - if (p) *p = '\0'; - io_printf(f_out, "%s\n", path); - if (p) *p = '/'; + io_printf(f_out, "%.*s\n", modlen, modname); /* Old servers may just drop the connection here, rather than sending a proper EXIT command. Yuck. */ @@ -303,6 +318,8 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char io_start_multiplex_in(); } + free(modname); + return 0; } @@ -338,8 +355,12 @@ static int read_arg_from_pipe(int fd, char *buf, int limit) char *bp = buf, *eob = buf + limit - 1; while (1) { - if (read(fd, bp, 1) != 1) + int got = read(fd, bp, 1); + if (got != 1) { + if (got < 0 && errno == EINTR) + continue; return -1; + } if (*bp == '\0') break; if (bp < eob) @@ -608,6 +629,18 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host) sanitize_paths = 1; } + if ((munge_symlinks = lp_munge_symlinks(i)) < 0) + munge_symlinks = !use_chroot; + if (munge_symlinks) { + STRUCT_STAT st; + if (stat(SYMLINK_PREFIX, &st) == 0 && S_ISDIR(st.st_mode)) { + rprintf(FLOG, "Symlink munging is unsupported when a %s directory exists.\n", + SYMLINK_PREFIX); + io_printf(f_out, "@ERROR: daemon security issue -- contact admin\n", name); + exit_cleanup(RERR_UNSUPPORTED); + } + } + if (am_root) { /* XXXX: You could argue that if the daemon is started * by a non-root user and they explicitly specify a @@ -667,6 +700,8 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host) am_server = 1; /* Don't let someone try to be tricky. */ if (lp_ignore_errors(module_id)) ignore_errors = 1; + if (write_batch < 0) + dry_run = 1; if (lp_fake_super(i)) am_root = -1;