* Copyright (C) 1996-2001 Andrew Tridgell <tridge@samba.org>
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
- * Copyright (C) 2003-2008 Wayne Davison
+ * Copyright (C) 2003-2009 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
extern int am_root;
extern int am_server;
extern int am_sender;
-extern int am_generator;
extern int am_daemon;
extern int inc_recurse;
extern int blocking_io;
extern char *filesfrom_host;
extern char *partial_dir;
extern char *dest_option;
-extern char *basis_dir[];
+extern char *basis_dir[MAX_BASIS_DIRS+1];
extern char *rsync_path;
extern char *shell_cmd;
extern char *batch_name;
extern struct filter_list_struct daemon_filter_list;
uid_t our_uid;
+int am_receiver = 0; /* Only set to 1 after the receiver/generator fork. */
+int am_generator = 0; /* Only set to 1 after the receiver/generator fork. */
int local_server = 0;
int daemon_over_rsh = 0;
mode_t orig_umask = 0;
rprintf(FERROR, "internal: args[] overflowed in do_cmd()\n");
exit_cleanup(RERR_SYNTAX);
}
- args[argc++] = *remote_argv++;
+ if (**remote_argv == '-') {
+ if (asprintf(args + argc++, "./%s", *remote_argv++) < 0)
+ out_of_memory("do_cmd");
+ } else
+ args[argc++] = *remote_argv++;
remote_argc--;
}
}
#ifdef ICONV_CONST
setup_iconv();
#endif
- if (protect_args)
+ if (protect_args && !daemon_over_rsh)
send_protected_args(*f_out_p, args);
}
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);
+ /* Treat an empty string as a copy into the current directory. */
+ if (!*dest_path)
+ dest_path = ".";
+
+ if (daemon_filter_list.head) {
+ char *slash = strrchr(dest_path, '/');
+ if (slash && (slash[1] == '\0' || (slash[1] == '.' && slash[2] == '\0')))
+ *slash = '\0';
+ else
+ slash = NULL;
+ if ((*dest_path != '.' || dest_path[1] != '\0')
+ && (check_filter(&daemon_filter_list, FLOG, dest_path, 0) < 0
+ || check_filter(&daemon_filter_list, FLOG, dest_path, 1) < 0)) {
+ rprintf(FERROR, "skipping daemon-excluded destination \"%s\"\n",
+ dest_path);
+ exit_cleanup(RERR_FILESELECT);
+ }
+ if (slash)
+ *slash = '/';
}
/* 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. */
if (S_ISDIR(st.st_mode)) {
- if (!push_dir(dest_path, 0)) {
- rsyserr(FERROR, errno, "push_dir#1 %s failed",
+ if (!change_dir(dest_path, CD_NORMAL)) {
+ rsyserr(FERROR, errno, "change_dir#1 %s failed",
full_fname(dest_path));
exit_cleanup(RERR_FILESELECT);
}
dry_run++;
}
- if (!push_dir(dest_path, dry_run > 1)) {
- rsyserr(FERROR, errno, "push_dir#2 %s failed",
+ if (!change_dir(dest_path, dry_run > 1 ? CD_SKIP_CHDIR : CD_NORMAL)) {
+ rsyserr(FERROR, errno, "change_dir#2 %s failed",
full_fname(dest_path));
exit_cleanup(RERR_FILESELECT);
}
dest_path = "/";
*cp = '\0';
- if (!push_dir(dest_path, 0)) {
- rsyserr(FERROR, errno, "push_dir#3 %s failed",
+ if (!change_dir(dest_path, CD_NORMAL)) {
+ rsyserr(FERROR, errno, "change_dir#3 %s failed",
full_fname(dest_path));
exit_cleanup(RERR_FILESELECT);
}
}
if (!relative_paths) {
- if (!push_dir(dir, 0)) {
- rsyserr(FERROR, errno, "push_dir#3 %s failed",
+ if (!change_dir(dir, CD_NORMAL)) {
+ rsyserr(FERROR, errno, "change_dir#3 %s failed",
full_fname(dir));
exit_cleanup(RERR_FILESELECT);
}
}
if (pid == 0) {
+ am_receiver = 1;
+
close(error_pipe[0]);
if (f_in != f_out)
close(f_out);
char *dir = argv[0];
argc--;
argv++;
- if (!am_daemon && !push_dir(dir, 0)) {
- rsyserr(FERROR, errno, "push_dir#4 %s failed",
+ if (!am_daemon && !change_dir(dir, CD_NORMAL)) {
+ rsyserr(FERROR, errno, "change_dir#4 %s failed",
full_fname(dir));
exit_cleanup(RERR_FILESELECT);
}
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();
char *dir = *dir_p;
if (*dir == '/')
dir += module_dirlen;
- if (check_filter(elp, dir, 1) < 0)
+ if (check_filter(elp, FLOG, dir, 1) < 0)
goto options_rejected;
}
if (partial_dir && *partial_dir == '/'
- && check_filter(elp, partial_dir + module_dirlen, 1) < 0) {
+ && check_filter(elp, FLOG, partial_dir + module_dirlen, 1) < 0) {
options_rejected:
rprintf(FERROR,
"Your options have been rejected by the server.\n");
if (write_batch && !am_server)
start_write_batch(f_out);
flist = send_file_list(f_out, argc, argv);
- set_msg_fd_in(-1);
if (verbose > 3)
rprintf(FINFO,"file list sent\n");
io_start_multiplex_out();
}
- if (argc == 0) {
- list_only |= 1;
- xfer_dirs |= 1;
- }
-
send_filter_list(read_batch ? -1 : f_out);
if (filesfrom_fd >= 0) {
static char *dotarg[1] = { "." };
p = dotarg[0];
remote_argv = dotarg;
- list_only |= 1;
- xfer_dirs |= 1;
}
remote_argc = 1;
rprintf(FERROR, "remote destination is not allowed with --read-batch\n");
exit_cleanup(RERR_SYNTAX);
}
- remote_argv = argv + argc - 1;
- remote_argc = 1;
+ remote_argv = argv += argc - 1;
+ remote_argc = argc = 1;
}
if (am_sender) {
}
remote_argv[i] = arg;
}
- if (argc == 0) {
- list_only |= 1;
- xfer_dirs |= 1;
- }
}
if (daemon_over_rsh < 0)
SIGACTION(SIGXFSZ, SIG_IGN);
#endif
- /* Initialize push_dir here because on some old systems getcwd
+ /* Initialize change_dir() here because on some old systems getcwd
* (implemented by forking "pwd" and reading its output) doesn't
* work when there are other child processes. Also, on all systems
* that implement getcwd that way "pwd" can't be found after chroot. */
- push_dir(NULL, 0);
+ change_dir(NULL, CD_NORMAL);
init_flist();
read_stream_flags(batch_fd);
else
write_stream_flags(batch_fd);
-
}
if (write_batch < 0)
dry_run = 1;