X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/a1a440c23e50c1a711bbe404456234895b8db79d..088aac85971f3f1571c7f90569c95d5025b1fd82:/main.c diff --git a/main.c b/main.c index 63fab0dc..0ed7df38 100644 --- a/main.c +++ b/main.c @@ -2,6 +2,7 @@ Copyright (C) 1996-2001 by Andrew Tridgell Copyright (C) Paul Mackerras 1996 + Copyright (C) 2001, 2002 by Martin Pool 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 @@ -26,6 +27,7 @@ struct stats stats; extern int verbose; +static void show_malloc_stats(void); /**************************************************************************** wait for a process to exit, calling io_flush while waiting @@ -55,6 +57,12 @@ static void report(int f) extern int remote_version; int send_stats; + if (do_stats) { + /* These come out from every process */ + show_malloc_stats(); + show_flist_stats(); + } + if (am_daemon) { log_exit(0, __FILE__, __LINE__); if (f == -1 || !am_sender) return; @@ -125,6 +133,38 @@ static void report(int f) } +/** + * If our C library can get malloc statistics, then show them to FINFO + **/ +static void show_malloc_stats(void) +{ +#ifdef HAVE_MALLINFO + struct mallinfo mi; + extern int am_server; + extern int am_sender; + extern int am_daemon; + + mi = mallinfo(); + + rprintf(FINFO, RSYNC_NAME "[%d] (%s%s%s) heap statistics:\n", + getpid(), + am_server ? "server " : "", + am_daemon ? "daemon " : "", + am_sender ? "sender" : "receiver"); + rprintf(FINFO, " arena: %10d (bytes from sbrk)\n", mi.arena); + rprintf(FINFO, " ordblks: %10d (chunks not in use)\n", mi.ordblks); + rprintf(FINFO, " smblks: %10d\n", mi.smblks); + rprintf(FINFO, " hblks: %10d (chunks from mmap)\n", mi.hblks); + rprintf(FINFO, " hblkhd: %10d (bytes from mmap)\n", mi.hblkhd); + rprintf(FINFO, " usmblks: %10d\n", mi.usmblks); + rprintf(FINFO, " fsmblks: %10d\n", mi.fsmblks); + rprintf(FINFO, " uordblks: %10d (bytes used)\n", mi.uordblks); + rprintf(FINFO, " fordblks: %10d (bytes free)\n", mi.fordblks); + rprintf(FINFO, " keepcost: %10d (bytes in releasable chunk)\n", mi.keepcost); +#endif /* HAVE_MALLINFO */ +} + + /* Start the remote shell. cmd may be NULL to use the default. */ static pid_t do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f_out) { @@ -135,8 +175,9 @@ static pid_t do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int extern int local_server; extern char *rsync_path; extern int blocking_io; + extern int read_batch; - if (!local_server) { + if (!read_batch && !local_server) { if (!cmd) cmd = getenv(RSYNC_RSH_ENV); if (!cmd) @@ -166,10 +207,11 @@ static pid_t do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int args[argc++] = rsync_path; - server_options(args,&argc); + if ((blocking_io == -1) && (strcmp(cmd, RSYNC_RSH) == 0)) + blocking_io = 1; + server_options(args,&argc); - if (strcmp(cmd, RSYNC_RSH) == 0) blocking_io = 1; } args[argc++] = "."; @@ -187,6 +229,8 @@ static pid_t do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int } if (local_server) { + if (read_batch) + create_flist_from_batch(); /* sets batch_flist */ ret = local_child(argc, args, f_in, f_out); } else { ret = piped_child(args,f_in,f_out); @@ -360,7 +404,8 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name) /* finally we go to sleep until our parent kills us with a USR2 signal. We sleep for a short time as on some OSes a signal won't interrupt a sleep! */ - while (1) msleep(20); + while (msleep(20)) + ; } close(recv_pipe[1]); @@ -398,6 +443,8 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[]) extern int am_daemon; extern int module_id; extern int am_sender; + extern int read_batch; + extern struct file_list *batch_flist; if (verbose > 2) rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid()); @@ -423,7 +470,10 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[]) if (delete_mode && !delete_excluded) recv_exclude_list(f_in); - flist = recv_file_list(f_in); + if (read_batch) + flist = batch_flist; + else + flist = recv_file_list(f_in); if (!flist) { rprintf(FERROR,"server_recv: recv_file_list error\n"); exit_cleanup(RERR_FILESELECT); @@ -447,6 +497,7 @@ void start_server(int f_in, int f_out, int argc, char *argv[]) extern int cvs_exclude; extern int am_sender; extern int remote_version; + extern int read_batch; setup_protocol(f_out, f_in); @@ -457,9 +508,11 @@ void start_server(int f_in, int f_out, int argc, char *argv[]) io_start_multiplex_out(f_out); if (am_sender) { - recv_exclude_list(f_in); - if (cvs_exclude) + if (!read_batch) { + recv_exclude_list(f_in); + if (cvs_exclude) add_cvs_excludes(); + } do_server_sender(f_in, f_out, argc, argv); } else { do_server_recv(f_in, f_out, argc, argv); @@ -474,14 +527,19 @@ void start_server(int f_in, int f_out, int argc, char *argv[]) */ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[]) { - struct file_list *flist; + struct file_list *flist = NULL; int status = 0, status2 = 0; char *local_name = NULL; extern int am_sender; extern int remote_version; extern pid_t cleanup_child_pid; + extern int write_batch; + extern int read_batch; + extern struct file_list *batch_flist; cleanup_child_pid = pid; + if (read_batch) + flist = batch_flist; set_nonblocking(f_in); set_nonblocking(f_out); @@ -499,21 +557,22 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[]) add_cvs_excludes(); if (delete_mode && !delete_excluded) send_exclude_list(f_out); - flist = send_file_list(f_out,argc,argv); + if (!read_batch) /* dw -- don't write to pipe */ + flist = send_file_list(f_out,argc,argv); if (verbose > 3) rprintf(FINFO,"file list sent\n"); send_files(flist,f_out,f_in); + if (remote_version >= 24) { + /* final goodbye message */ + read_int(f_in); + } if (pid != -1) { if (verbose > 3) - rprintf(FINFO,"client_run waiting on %d\n",pid); + rprintf(FINFO,"client_run waiting on %d\n", (int) pid); io_flush(); wait_process(pid, &status); } - if (remote_version >= 24) { - /* final goodbye message */ - read_int(f_in); - } report(-1); exit_cleanup(status); } @@ -523,7 +582,8 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[]) list_only = 1; } - send_exclude_list(f_out); + if (!write_batch) + send_exclude_list(f_out); flist = recv_file_list(f_in); if (!flist || flist->count == 0) { @@ -539,7 +599,7 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[]) if (pid != -1) { if (verbose > 3) - rprintf(FINFO,"client_run2 waiting on %d\n",pid); + rprintf(FINFO,"client_run2 waiting on %d\n", (int) pid); io_flush(); wait_process(pid, &status); } @@ -563,6 +623,22 @@ static char *find_colon(char *s) } +static int copy_argv (char *argv[]) +{ + int i; + + for (i = 0; argv[i]; i++) { + if (!(argv[i] = strdup(argv[i]))) { + rprintf (FERROR, "out of memory at %s(%d)\n", + __FILE__, __LINE__); + return RERR_MALLOC; + } + } + + return 0; +} + + /* * Start a client for either type of remote connection. Work out * whether the arguments request a remote shell or rsyncd connection, @@ -582,12 +658,19 @@ static int start_client(int argc, char *argv[]) extern char *shell_cmd; extern int rsync_port; extern int whole_file; - char *argv0 = strdup(argv[0]); + extern int write_batch; + extern int read_batch; + int rc; + + /* Don't clobber argv[] so that ps(1) can still show the right + command line. */ + if ((rc = copy_argv (argv))) + return rc; - if (strncasecmp(URL_PREFIX, argv0, strlen(URL_PREFIX)) == 0) { + if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) { char *host, *path; - host = argv0 + strlen(URL_PREFIX); + host = argv[0] + strlen(URL_PREFIX); p = strchr(host,'/'); if (p) { *p = 0; @@ -603,12 +686,13 @@ static int start_client(int argc, char *argv[]) return start_socket_client(host, path, argc-1, argv+1); } - p = find_colon(argv0); + if (!read_batch) { + p = find_colon(argv[0]); if (p) { if (p[1] == ':') { *p = 0; - return start_socket_client(argv0, p+2, argc-1, argv+1); + return start_socket_client(argv[0], p+2, argc-1, argv+1); } if (argc < 1) { @@ -618,7 +702,7 @@ static int start_client(int argc, char *argv[]) am_sender = 0; *p = 0; - shell_machine = argv0; + shell_machine = argv[0]; shell_path = p+1; argc--; argv++; @@ -628,8 +712,12 @@ static int start_client(int argc, char *argv[]) p = find_colon(argv[argc-1]); if (!p) { local_server = 1; - /* disable "rsync algorithm" when both sides local */ - whole_file = 1; + /* + * disable "rsync algorithm" when both sides local, + * except when creating a batch update + */ + if (!write_batch && whole_file == -1) + whole_file = 1; } else if (p[1] == ':') { *p = 0; return start_socket_client(argv[argc-1], p+2, argc-1, argv); @@ -650,7 +738,12 @@ static int start_client(int argc, char *argv[]) } argc--; } - + } else { + am_sender = 1; + local_server = 1; + shell_path = argv[argc-1]; + } + if (shell_machine) { p = strchr(shell_machine,'@'); if (p) { @@ -700,6 +793,9 @@ static RETSIGTYPE sigusr2_handler(int val) { } static RETSIGTYPE sigchld_handler(int val) { +#ifdef WNOHANG + while (waitpid(-1, NULL, WNOHANG) > 0) ; +#endif } int main(int argc,char *argv[]) @@ -710,6 +806,12 @@ int main(int argc,char *argv[]) extern int am_daemon; extern int am_server; int ret; + extern int write_batch; + int orig_argc; + char **orig_argv; + + orig_argc = argc; + orig_argv = argv; signal(SIGUSR1, sigusr1_handler); signal(SIGUSR2, sigusr2_handler); @@ -747,6 +849,10 @@ int main(int argc,char *argv[]) that implement getcwd that way "pwd" can't be found after chroot. */ push_dir(NULL,0); + if (write_batch && !am_server) { + write_batch_argvs_file(orig_argc, orig_argv); + } + if (am_daemon) { return daemon_main(); } @@ -773,7 +879,9 @@ int main(int argc,char *argv[]) } ret = start_client(argc, argv); - exit_cleanup(ret); + if (ret == -1) + exit_cleanup(RERR_STARTCLIENT); + else + exit_cleanup(ret); return ret; } -