* 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-2020 Wayne Davison
+ * Copyright (C) 2003-2021 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 backup_dir_len;
extern int basis_dir_cnt;
extern int default_af_hint;
+extern int stdout_format_has_i;
extern struct stats stats;
extern char *stdout_format;
extern char *logfile_format;
extern char *password_file;
extern char *backup_dir;
extern char *copy_as;
+extern char *tmpdir;
extern char curr_dir[MAXPATHLEN];
extern char backup_dir_buf[MAXPATHLEN];
extern char *basis_dir[MAX_BASIS_DIRS+1];
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;
+int daemon_connection = 0; /* 0 = no daemon, 1 = daemon via remote shell, -1 = daemon via socket */
mode_t orig_umask = 0;
int batch_gen_fd = -1;
int sender_keeps_checksum = 0;
**/
static void show_malloc_stats(void)
{
-#ifdef HAVE_MALLINFO
- struct mallinfo mi;
-
- mi = mallinfo();
+#ifdef MEM_ALLOC_INFO
+ struct MEM_ALLOC_INFO mi = MEM_ALLOC_INFO(); /* mallinfo or mallinfo2 */
rprintf(FCLIENT, "\n");
rprintf(FINFO, RSYNC_NAME "[%d] (%s%s%s) heap statistics:\n",
(int)getpid(), am_server ? "server " : "",
am_daemon ? "daemon " : "", who_am_i());
- rprintf(FINFO, " arena: %10ld (bytes from sbrk)\n",
- (long)mi.arena);
- rprintf(FINFO, " ordblks: %10ld (chunks not in use)\n",
- (long)mi.ordblks);
- rprintf(FINFO, " smblks: %10ld\n",
- (long)mi.smblks);
- rprintf(FINFO, " hblks: %10ld (chunks from mmap)\n",
- (long)mi.hblks);
- rprintf(FINFO, " hblkhd: %10ld (bytes from mmap)\n",
- (long)mi.hblkhd);
- rprintf(FINFO, " allmem: %10ld (bytes from sbrk + mmap)\n",
- (long)mi.arena + mi.hblkhd);
- rprintf(FINFO, " usmblks: %10ld\n",
- (long)mi.usmblks);
- rprintf(FINFO, " fsmblks: %10ld\n",
- (long)mi.fsmblks);
- rprintf(FINFO, " uordblks: %10ld (bytes used)\n",
- (long)mi.uordblks);
- rprintf(FINFO, " fordblks: %10ld (bytes free)\n",
- (long)mi.fordblks);
- rprintf(FINFO, " keepcost: %10ld (bytes in releasable chunk)\n",
- (long)mi.keepcost);
-#endif /* HAVE_MALLINFO */
+
+#define PRINT_ALLOC_NUM(title, descr, num) \
+ rprintf(FINFO, " %-11s%10" SIZE_T_FMT_MOD "d (" descr ")\n", \
+ title ":", (SIZE_T_FMT_CAST)(num));
+
+ PRINT_ALLOC_NUM("arena", "bytes from sbrk", mi.arena);
+ PRINT_ALLOC_NUM("ordblks", "chunks not in use", mi.ordblks);
+ PRINT_ALLOC_NUM("smblks", "free fastbin blocks", mi.smblks);
+ PRINT_ALLOC_NUM("hblks", "chunks from mmap", mi.hblks);
+ PRINT_ALLOC_NUM("hblkhd", "bytes from mmap", mi.hblkhd);
+ PRINT_ALLOC_NUM("allmem", "bytes from sbrk + mmap", mi.arena + mi.hblkhd);
+ PRINT_ALLOC_NUM("usmblks", "always 0", mi.usmblks);
+ PRINT_ALLOC_NUM("fsmblks", "bytes in freed fastbin blocks", mi.fsmblks);
+ PRINT_ALLOC_NUM("uordblks", "bytes used", mi.uordblks);
+ PRINT_ALLOC_NUM("fordblks", "bytes free", mi.fordblks);
+ PRINT_ALLOC_NUM("keepcost", "bytes in releasable chunk", mi.keepcost);
+
+#undef PRINT_ALLOC_NUM
+
+#endif /* MEM_ALLOC_INFO */
}
#ifdef HAVE_REMSH
/* remsh (on HPUX) takes the arguments the other way around */
args[argc++] = machine;
- if (user && !(daemon_over_rsh && dash_l_set)) {
+ if (user && !(daemon_connection && dash_l_set)) {
args[argc++] = "-l";
args[argc++] = user;
}
#else
- if (user && !(daemon_over_rsh && dash_l_set)) {
+ if (user && !(daemon_connection && dash_l_set)) {
args[argc++] = "-l";
args[argc++] = user;
}
if (blocking_io < 0 && (strcmp(t, "rsh") == 0 || strcmp(t, "remsh") == 0))
blocking_io = 1;
- server_options(args, &argc);
+ if (daemon_connection > 0) {
+ args[argc++] = "--server";
+ args[argc++] = "--daemon";
+ } else
+ server_options(args, &argc);
if (argc >= MAX_ARGS - 2)
goto arg_overflow;
args[argc++] = ".";
- if (!daemon_over_rsh) {
+ if (!daemon_connection) {
while (remote_argc > 0) {
if (argc >= MAX_ARGS - 1) {
arg_overflow:
rprintf(FERROR, "internal: args[] overflowed in do_cmd()\n");
exit_cleanup(RERR_SYNTAX);
}
- if (**remote_argv == '-') {
- if (asprintf(args + argc++, "./%s", *remote_argv++) < 0)
- out_of_memory("do_cmd");
- } else
- args[argc++] = *remote_argv++;
+ args[argc++] = safe_arg(NULL, *remote_argv++);
remote_argc--;
}
}
#ifdef ICONV_CONST
setup_iconv();
#endif
- if (protect_args && !daemon_over_rsh)
+ if (protect_args && !daemon_connection)
send_protected_args(*f_out_p, args);
}
trailing_slash = cp && !cp[1];
if (mkpath_dest_arg && statret < 0 && (cp || file_total > 1)) {
+ int save_errno = errno;
int ret = make_path(dest_path, file_total > 1 && !trailing_slash ? 0 : MKP_DROP_NAME);
if (ret < 0)
goto mkdir_error;
- if (INFO_GTE(NAME, 1)) {
+ if (ret && (INFO_GTE(NAME, 1) || stdout_format_has_i)) {
if (file_total == 1 || trailing_slash)
*cp = '\0';
rprintf(FINFO, "created %d director%s for %s\n", ret, ret == 1 ? "y" : "ies", dest_path);
if (file_total == 1 || trailing_slash)
*cp = '/';
}
- if (file_total > 1 || trailing_slash)
+ if (ret)
statret = do_stat(dest_path, &st);
+ else
+ errno = save_errno;
}
if (statret == 0) {
&& strcmp(flist->files[flist->low]->basename, ".") == 0)
flist->files[0]->flags |= FLAG_DIR_CREATED;
- if (INFO_GTE(NAME, 1))
+ if (INFO_GTE(NAME, 1) || stdout_format_has_i)
rprintf(FINFO, "created directory %s\n", dest_path);
if (dry_run) {
backup_dir_buf[backup_dir_len-1] = '/';
}
+ if (tmpdir) {
+ STRUCT_STAT st;
+ int ret = do_stat(tmpdir, &st);
+ if (ret < 0 || !S_ISDIR(st.st_mode)) {
+ if (ret == 0) {
+ rprintf(FERROR, "The temp-dir is not a directory: %s\n", tmpdir);
+ exit_cleanup(RERR_SYNTAX);
+ }
+ if (errno == ENOENT) {
+ rprintf(FERROR, "The temp-dir does not exist: %s\n", tmpdir);
+ exit_cleanup(RERR_SYNTAX);
+ }
+ rprintf(FERROR, "Failed to stat temp-dir %s: %s\n", tmpdir, strerror(errno));
+ exit_cleanup(RERR_FILEIO);
+ }
+ }
+
io_flush(FULL_FLUSH);
if ((pid = do_fork()) == -1) {
}
am_sender = 0;
if (rsync_port)
- daemon_over_rsh = shell_cmd ? 1 : -1;
+ daemon_connection = shell_cmd ? 1 : -1;
} else { /* source is local, check dest arg */
am_sender = 1;
} else { /* hostspec was found, so dest is remote */
argv[argc] = path;
if (rsync_port)
- daemon_over_rsh = shell_cmd ? 1 : -1;
+ daemon_connection = shell_cmd ? 1 : -1;
}
}
} else { /* read_batch */
char *dummy_host;
int dummy_port = rsync_port;
int i;
+ if (!argv[0][0])
+ goto invalid_empty;
/* For local source, extra source args must not have hostspec. */
for (i = 1; i < argc; i++) {
+ if (!argv[i][0]) {
+ invalid_empty:
+ rprintf(FERROR, "Empty source arg specified.\n");
+ exit_cleanup(RERR_SYNTAX);
+ }
if (check_for_hostspec(argv[i], &dummy_host, &dummy_port)) {
rprintf(FERROR, "Unexpected remote arg: %s\n", argv[i]);
exit_cleanup(RERR_SYNTAX);
else
env_port = rsync_port;
- if (daemon_over_rsh < 0)
+ if (daemon_connection < 0)
return start_socket_client(shell_machine, remote_argc, remote_argv, argc, argv);
- if (password_file && !daemon_over_rsh) {
+ if (password_file && !daemon_connection) {
rprintf(FERROR, "The --password-file option may only be "
"used when accessing an rsync daemon.\n");
exit_cleanup(RERR_SYNTAX);
}
#ifdef HAVE_PUTENV
- if (daemon_over_rsh)
+ if (daemon_connection)
set_env_num("RSYNC_PORT", env_port);
+#else
+ (void)env_port;
#endif
pid = do_cmd(shell_cmd, shell_machine, shell_user, remote_argv, remote_argc, &f_in, &f_out);
/* if we're running an rsync server on the remote host over a
* remote shell command, we need to do the RSYNCD protocol first */
- if (daemon_over_rsh) {
+ if (daemon_connection) {
int tmpret;
tmpret = start_inband_exchange(f_in, f_out, shell_user, remote_argc, remote_argv);
if (tmpret < 0)
#endif
}
-
/**
* This routine catches signals and tries to send them to gdb.
*
return "xterm -display :0 -T Panic -n Panic -e gdb /proc/%d/exe %d";
}
-
/**
* Handle a fatal signal by launching a debugger, controlled by $RSYNC_PANIC_ACTION.
*
}
#endif
+static void unset_env_var(const char *var)
+{
+#ifdef HAVE_UNSETENV
+ unsetenv(var);
+#else
+#ifdef HAVE_PUTENV
+ char *mem;
+ if (asprintf(&mem, "%s=", var) < 0)
+ out_of_memory("unset_env_var");
+ putenv(mem);
+#else
+ (void)var;
+#endif
+#endif
+}
+
int main(int argc,char *argv[])
{
our_gid = MY_GID();
am_root = our_uid == ROOT_UID;
+ unset_env_var("DISPLAY");
+
memset(&stats, 0, sizeof(stats));
/* Even a non-daemon runs needs the default config values to be set, e.g.
#if defined CONFIG_LOCALE && defined HAVE_SETLOCALE
setlocale(LC_CTYPE, "");
+ setlocale(LC_NUMERIC, "");
#endif
if (!parse_arguments(&argc, (const char ***) &argv)) {