* 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-2013 Wayne Davison
+ * Copyright (C) 2003-2018 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 unsigned int module_dirlen;
extern BOOL flist_receiving_enabled;
extern BOOL shutting_down;
+extern int backup_dir_len;
extern int basis_dir_cnt;
extern struct stats stats;
extern char *stdout_format;
return waited_pid;
}
+int shell_exec(const char *cmd)
+{
+ char *shell = getenv("RSYNC_SHELL");
+ int status;
+ pid_t pid;
+
+ if (!shell)
+ return system(cmd);
+
+ if ((pid = fork()) < 0)
+ return -1;
+
+ if (pid == 0) {
+ execlp(shell, shell, "-c", cmd, NULL);
+ _exit(1);
+ }
+
+ int ret = wait_process(pid, &status, 0);
+ return ret < 0 ? -1 : status;
+}
+
/* Wait for a process to exit, calling io_flush while waiting. */
static void wait_process_with_flush(pid_t pid, int *exit_code_ptr)
{
rprintf(FINFO, "%s: %s%s\n", prefix, comma_num(total), buf);
}
+static const char *bytes_per_sec_human_dnum(void)
+{
+ if (starttime == (time_t)-1 || endtime == (time_t)-1)
+ return "UNKNOWN";
+ return human_dnum((total_written + total_read) / (0.5 + (endtime - starttime)), 2);
+}
+
static void output_summary(void)
{
if (INFO_GTE(STATS, 2)) {
rprintf(FINFO,
"sent %s bytes received %s bytes %s bytes/sec\n",
human_num(total_written), human_num(total_read),
- human_dnum((total_written + total_read)/(0.5 + (endtime - starttime)), 2));
+ bytes_per_sec_human_dnum());
rprintf(FINFO, "total size is %s speedup is %s%s\n",
human_num(stats.total_size),
comma_dnum((double)stats.total_size / (total_written+total_read), 2),
static void do_server_sender(int f_in, int f_out, int argc, char *argv[])
{
struct file_list *flist;
- char *dir = argv[0];
+ char *dir;
if (DEBUG_GTE(SEND, 1))
rprintf(FINFO, "server_sender starting pid=%d\n", (int)getpid());
if (am_daemon && lp_write_only(module_id)) {
rprintf(FERROR, "ERROR: module is write only\n");
exit_cleanup(RERR_SYNTAX);
- return;
}
if (am_daemon && read_only && remove_source_files) {
rprintf(FERROR,
- "ERROR: --remove-%s-files cannot be used with a read-only module\n",
- remove_source_files == 1 ? "source" : "sent");
+ "ERROR: --remove-%s-files cannot be used with a read-only module\n",
+ remove_source_files == 1 ? "source" : "sent");
+ exit_cleanup(RERR_SYNTAX);
+ }
+ if (argc < 1) {
+ rprintf(FERROR, "ERROR: do_server_sender called without args\n");
exit_cleanup(RERR_SYNTAX);
- return;
}
+ dir = argv[0];
if (!relative_paths) {
if (!change_dir(dir, CD_NORMAL)) {
rsyserr(FERROR, errno, "change_dir#3 %s failed",
}
if (backup_dir) {
- int ret = make_path(backup_dir_buf, MKP_DROP_NAME); /* drops trailing slash */
- if (ret < 0)
- exit_cleanup(RERR_SYNTAX);
- if (ret)
- rprintf(FINFO, "Created backup_dir %s\n", backup_dir_buf);
- else if (INFO_GTE(BACKUP, 1))
+ STRUCT_STAT st;
+ int ret;
+ if (backup_dir_len > 1)
+ backup_dir_buf[backup_dir_len-1] = '\0';
+ ret = do_stat(backup_dir_buf, &st);
+ if (ret != 0 || !S_ISDIR(st.st_mode)) {
+ if (ret == 0) {
+ rprintf(FERROR, "The backup-dir is not a directory: %s\n", backup_dir_buf);
+ exit_cleanup(RERR_SYNTAX);
+ }
+ if (errno != ENOENT) {
+ rprintf(FERROR, "Failed to stat %s: %s\n", backup_dir_buf, strerror(errno));
+ exit_cleanup(RERR_FILEIO);
+ }
+ if (INFO_GTE(BACKUP, 1))
+ rprintf(FINFO, "(new) backup_dir is %s\n", backup_dir_buf);
+ } else if (INFO_GTE(BACKUP, 1))
rprintf(FINFO, "backup_dir is %s\n", backup_dir_buf);
+ if (backup_dir_len > 1)
+ backup_dir_buf[backup_dir_len-1] = '/';
}
io_flush(FULL_FLUSH);
filesfrom_fd = -1;
}
- flist = recv_file_list(f_in);
+ flist = recv_file_list(f_in, -1);
if (!flist) {
rprintf(FERROR,"server_recv: recv_file_list error\n");
exit_cleanup(RERR_FILESELECT);
if (write_batch && !am_server)
start_write_batch(f_in);
- flist = recv_file_list(f_in);
+ flist = recv_file_list(f_in, -1);
if (inc_recurse && file_total == 1)
recv_additional_file_list(f_in);
}
-static RETSIGTYPE sigusr1_handler(UNUSED(int val))
+static void sigusr1_handler(UNUSED(int val))
{
exit_cleanup(RERR_SIGNAL1);
}
-static RETSIGTYPE sigusr2_handler(UNUSED(int val))
+static void sigusr2_handler(UNUSED(int val))
{
if (!am_server)
output_summary();
_exit(0);
}
-RETSIGTYPE remember_children(UNUSED(int val))
+void remember_children(UNUSED(int val))
{
#ifdef WNOHANG
int cnt, status;
if (cmd_fmt)
return cmd_fmt;
- else
- return "xterm -display :0 -T Panic -n Panic "
- "-e gdb /proc/%d/exe %d";
+ return "xterm -display :0 -T Panic -n Panic -e gdb /proc/%d/exe %d";
}
* should just look at the environment variable, but I'm a bit leery
* of a signal sending us into a busy loop.
**/
-static RETSIGTYPE rsync_panic_handler(UNUSED(int whatsig))
+static void rsync_panic_handler(UNUSED(int whatsig))
{
char cmd_buf[300];
int ret, pid_int = getpid();
/* Unless we failed to execute gdb, we allow the process to
* continue. I'm not sure if that's right. */
- ret = system(cmd_buf);
+ ret = shell_exec(cmd_buf);
if (ret)
_exit(ret);
}
* that implement getcwd that way "pwd" can't be found after chroot. */
change_dir(NULL, CD_NORMAL);
- init_flist();
-
if ((write_batch || read_batch) && !am_server) {
if (write_batch)
write_batch_shell_file(orig_argc, orig_argv, argc);