X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/ce27f36d927ba68d62d3b4539cfd5e0f758e20fb..d48810ba5b0b8d09b272092a70da1255c2346ab8:/main.c diff --git a/main.c b/main.c index b2dcb523..5985f808 100644 --- a/main.c +++ b/main.c @@ -4,7 +4,7 @@ * Copyright (C) 1996-2001 Andrew Tridgell * Copyright (C) 1996 Paul Mackerras * Copyright (C) 2001, 2002 Martin Pool - * Copyright (C) 2003-2007 Wayne Davison + * Copyright (C) 2003-2008 Wayne Davison * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -45,6 +45,7 @@ extern int got_xfer_error; extern int module_id; extern int copy_links; extern int copy_dirlinks; +extern int copy_unsafe_links; extern int keep_dirlinks; extern int preserve_hard_links; extern int protocol_version; @@ -65,6 +66,7 @@ extern int batch_fd; extern int filesfrom_fd; extern int connect_timeout; extern pid_t cleanup_child_pid; +extern unsigned int module_dirlen; extern struct stats stats; extern char *filesfrom_host; extern char *partial_dir; @@ -76,11 +78,9 @@ extern char *batch_name; extern char *password_file; extern char curr_dir[MAXPATHLEN]; extern struct file_list *first_flist; -extern struct filter_list_struct server_filter_list; -#ifdef ICONV_OPTION -extern iconv_t ic_send; -#endif +extern struct filter_list_struct daemon_filter_list; +uid_t our_uid; int local_server = 0; int daemon_over_rsh = 0; mode_t orig_umask = 0; @@ -277,7 +277,7 @@ static void output_summary(void) rprintf(FINFO, "total size is %s speedup is %.2f%s\n", human_num(stats.total_size), (double)stats.total_size / (total_written+total_read), - dry_run ? " (DRY RUN)" : ""); + write_batch < 0 ? " (BATCH ONLY)" : dry_run ? " (DRY RUN)" : ""); } fflush(stdout); @@ -331,8 +331,7 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in { int i, argc = 0; char *args[MAX_ARGS]; - pid_t ret; - char *dir = NULL; + pid_t pid; int dash_l_set = 0; if (!read_batch && !local_server) { @@ -342,7 +341,7 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in cmd = rsh_env; if (!cmd) cmd = RSYNC_RSH; - cmd = strdup(cmd); + cmd = strdup(cmd); /* MEMORY LEAK */ if (!cmd) goto oom; @@ -451,7 +450,7 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in batch_gen_fd = from_gen_pipe[0]; *f_out_p = from_gen_pipe[1]; *f_in_p = batch_fd; - ret = -1; /* no child pid */ + pid = (pid_t)-1; /* no child pid */ #ifdef ICONV_CONST setup_iconv(); #endif @@ -461,57 +460,20 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in if (whole_file < 0 && !write_batch) whole_file = 1; set_allow_inc_recurse(); - ret = local_child(argc, args, f_in_p, f_out_p, child_main); + pid = local_child(argc, args, f_in_p, f_out_p, child_main); #ifdef ICONV_CONST setup_iconv(); #endif } else { + pid = piped_child(args, f_in_p, f_out_p); #ifdef ICONV_CONST setup_iconv(); #endif - if (protect_args) { - int fd; -#ifdef ICONV_OPTION - int convert = ic_send != (iconv_t)-1; - xbuf outbuf, inbuf; - - if (convert) - alloc_xbuf(&outbuf, 1024); -#endif - - ret = piped_child(args, f_in_p, f_out_p); - - for (i = 0; args[i]; i++) {} /* find first NULL */ - args[i] = "rsync"; /* set a new arg0 */ - if (verbose > 1) - print_child_argv("protected args:", args + i + 1); - fd = *f_out_p; - do { -#ifdef ICONV_OPTION - if (convert) { - INIT_XBUF_STRLEN(inbuf, args[i]); - iconvbufs(ic_send, &inbuf, &outbuf, - ICB_EXPAND_OUT | ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE); - outbuf.buf[outbuf.len] = '\0'; - write_buf(fd, outbuf.buf, outbuf.len + 1); - outbuf.len = 0; - } else -#endif - write_buf(fd, args[i], strlen(args[i]) + 1); - } while (args[++i]); - write_byte(fd, 0); -#ifdef ICONV_OPTION - if (convert) - free(outbuf.buf); -#endif - } else - ret = piped_child(args, f_in_p, f_out_p); + if (protect_args) + send_protected_args(*f_out_p, args); } - if (dir) - free(dir); - - return ret; + return pid; oom: out_of_memory("do_cmd"); @@ -545,6 +507,14 @@ static char *get_local_name(struct file_list *flist, char *dest_path) if (!dest_path || list_only) return NULL; + if (daemon_filter_list.head + && (check_filter(&daemon_filter_list, dest_path, 0 != 0) < 0 + || check_filter(&daemon_filter_list, dest_path, 1 != 0) < 0)) { + rprintf(FERROR, "skipping daemon-excluded destination \"%s\"\n", + dest_path); + exit_cleanup(RERR_FILESELECT); + } + /* See what currently exists at the destination. */ if ((statret = do_stat(dest_path, &st)) == 0) { /* If the destination is a dir, enter it and use mode 1. */ @@ -643,7 +613,7 @@ static char *get_local_name(struct file_list *flist, char *dest_path) * dry-run mode and the destination dir does not yet exist, we'll try to * tweak any dest-relative paths to make them work for a dry-run (the * destination dir must be in curr_dir[] when this function is called). - * We also report if any arg that is non-existent or not a directory. */ + * We also warn about any arg that is non-existent or not a directory. */ static void check_alt_basis_dirs(void) { STRUCT_STAT st; @@ -761,7 +731,7 @@ static int do_recv(int f_in, int f_out, char *local_name) /* The receiving side mustn't obey this, or an existing symlink that * points to an identical file won't be replaced by the referent. */ - copy_links = copy_dirlinks = 0; + copy_links = copy_dirlinks = copy_unsafe_links = 0; #ifdef SUPPORT_HARD_LINKS if (preserve_hard_links && !inc_recurse) @@ -869,7 +839,6 @@ static void do_server_recv(int f_in, int f_out, int argc, char *argv[]) int exit_code; struct file_list *flist; char *local_name = NULL; - char *dir = NULL; int save_verbose = verbose; if (filesfrom_fd >= 0) { @@ -890,7 +859,7 @@ static void do_server_recv(int f_in, int f_out, int argc, char *argv[]) } if (argc > 0) { - dir = argv[0]; + char *dir = argv[0]; argc--; argv++; if (!am_daemon && !push_dir(dir, 0)) { @@ -933,22 +902,25 @@ static void do_server_recv(int f_in, int f_out, int argc, char *argv[]) if (sanitize_paths) { char **dir_p; for (dir_p = basis_dir; *dir_p; dir_p++) - *dir_p = sanitize_path(NULL, *dir_p, NULL, curr_dir_depth); + *dir_p = sanitize_path(NULL, *dir_p, NULL, curr_dir_depth, SP_DEFAULT); if (partial_dir) - partial_dir = sanitize_path(NULL, partial_dir, NULL, curr_dir_depth); + partial_dir = sanitize_path(NULL, partial_dir, NULL, curr_dir_depth, SP_DEFAULT); } check_alt_basis_dirs(); - if (server_filter_list.head) { - char **dir; - struct filter_list_struct *elp = &server_filter_list; + if (daemon_filter_list.head) { + char **dir_p; + struct filter_list_struct *elp = &daemon_filter_list; - for (dir = basis_dir; *dir; dir++) { - if (check_filter(elp, *dir, 1) < 0) + for (dir_p = basis_dir; *dir_p; dir_p++) { + char *dir = *dir_p; + if (*dir == '/') + dir += module_dirlen; + if (check_filter(elp, dir, 1) < 0) goto options_rejected; } if (partial_dir && *partial_dir == '/' - && check_filter(elp, partial_dir, 1) < 0) { + && check_filter(elp, partial_dir + module_dirlen, 1) < 0) { options_rejected: rprintf(FERROR, "Your options have been rejected by the server.\n"); @@ -1428,7 +1400,8 @@ int main(int argc,char *argv[]) #endif starttime = time(NULL); - am_root = (MY_UID() == 0); + our_uid = MY_UID(); + am_root = our_uid == 0; memset(&stats, 0, sizeof(stats)); @@ -1445,7 +1418,7 @@ int main(int argc,char *argv[]) setlocale(LC_CTYPE, ""); #endif - if (!parse_arguments(&argc, (const char ***) &argv, 1)) { + if (!parse_arguments(&argc, (const char ***) &argv)) { /* FIXME: We ought to call the same error-handling * code here, rather than relying on getopt. */ option_error(); @@ -1510,7 +1483,7 @@ int main(int argc,char *argv[]) char buf[MAXPATHLEN]; protect_args = 2; read_args(STDIN_FILENO, NULL, buf, sizeof buf, 1, &argv, &argc, NULL); - if (!parse_arguments(&argc, (const char ***) &argv, 1)) { + if (!parse_arguments(&argc, (const char ***) &argv)) { option_error(); exit_cleanup(RERR_SYNTAX); }