]> git.ipfire.org Git - thirdparty/rsync.git/commitdiff
Split code out into separate files and remove some global variables to
authorMartin Pool <mbp@samba.org>
Mon, 8 Apr 2002 04:10:20 +0000 (04:10 +0000)
committerMartin Pool <mbp@samba.org>
Mon, 8 Apr 2002 04:10:20 +0000 (04:10 +0000)
reduce symbol dependencies between files and therefore make it easier
to write unit tests.  The diff is large, but the actual code changes
are pretty small.

.cvsignore
Makefile.in
clientserver.c
generator.c
log.c
main.c
options.c
pipe.c [new file with mode: 0644]
progress.c [new file with mode: 0644]
receiver.c

index a4cd5802d7a09aa3adf511dffd9188ab7e2eb403..cda7639f4778457c00f8958c808d4e5f3cac3e01 100644 (file)
@@ -8,6 +8,7 @@ config.log
 config.status
 conftest.c
 conftest.log
+dox
 gmon.out
 rsync
 shconfig
index 4fcf2c15bdaea64e30ed13ae073921c30df4c428..535dacea7cecd1ccd642d658f91fcff6ff08e9e0 100644 (file)
@@ -32,15 +32,16 @@ ZLIBOBJ=zlib/deflate.o zlib/infblock.o zlib/infcodes.o zlib/inffast.o \
 OBJS1=rsync.o generator.o receiver.o cleanup.o sender.o exclude.o util.o main.o checksum.o match.o syscall.o log.o backup.o
 OBJS2=options.o flist.o io.o compat.o hlink.o token.o uidlist.o socket.o fileio.o batch.o \
        clientname.o
+OBJS3=progress.o pipe.o
 DAEMON_OBJ = params.o loadparm.o clientserver.o access.o connection.o authenticate.o
 popt_OBJS=popt/findme.o  popt/popt.o  popt/poptconfig.o \
        popt/popthelp.o popt/poptparse.o
-OBJS=$(OBJS1) $(OBJS2) $(DAEMON_OBJ) $(LIBOBJ) $(ZLIBOBJ) @BUILD_POPT@
+OBJS=$(OBJS1) $(OBJS2) $(OBJS3) $(DAEMON_OBJ) $(LIBOBJ) $(ZLIBOBJ) @BUILD_POPT@
 
 TLS_OBJ = tls.o syscall.o lib/permstring.o 
 
 # Programs we must have to run the test cases
-CHECK_PROGS = rsync tls getgroups trimslash
+CHECK_PROGS = rsync tls getgroups trimslash t_unsafe
 
 # note that the -I. is needed to handle config.h when using VPATH
 .c.o:
@@ -79,6 +80,10 @@ TRIMSLASH_OBJ = trimslash.o syscall.o
 trimslash: $(TRIMSLASH_OBJ)
        $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(TRIMSLASH_OBJ) $(LIBS)
 
+T_UNSAFE_OBJ = t_unsafe.o syscall.o util.o t_stub.o lib/compat.o
+t_unsafe: $(T_UNSAFE_OBJ)
+       $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(T_UNSAFE_OBJ) $(LIBS)
+
 # I don't like these rules because CVS can skew the timestamps and
 # produce spurious warnings, and also make "make install" fail if the
 # source directory can no longer be found.  Since we don't rebuild
@@ -171,3 +176,12 @@ rsync.ps: rsync.dvi
 
 rsync.pdf: doc/rsync.texinfo
        texi2dvi -o $@ --pdf $<
+
+
+doxygen: 
+       cd $(srcdir) && rm dox/html/* && doxygen
+
+# for maintainers only
+doxygen-upload: 
+       rsync -avzv $(srcdir)/dox/html/ --delete \
+       samba.org:/home/httpd/html/rsync/doxygen/head/
index 40a437685d925ce37449b06f7f0b6482b194c8bb..9cda2a0b17f821f536ac8cd50f1b7109b26a62a0 100644 (file)
@@ -27,7 +27,7 @@ extern int read_only;
 extern int verbose;
 extern int rsync_port;
 char *auth_user;
-int sanitize_paths = 0;
+extern int sanitize_paths;
 
 /**
  * Run a client connected to an rsyncd.  The alternative to this
index c1b94fd80d4025e9545a0e4bd4a4bb6c5ec5b0f9..8e4ede09bdedd1e7df65f5b52c9cfa79730dc665 100644 (file)
@@ -239,6 +239,7 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
        extern int list_only;
        extern int preserve_perms;
        extern int only_existing;
+       extern int orig_umask;
 
        if (list_only) return;
 
@@ -281,7 +282,7 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
                }
                if (statret != 0 && do_mkdir(fname,file->mode) != 0 && errno != EEXIST) {
                        if (!(relative_paths && errno==ENOENT && 
-                             create_directory_path(fname)==0 && 
+                             create_directory_path(fname, orig_umask)==0 && 
                              do_mkdir(fname,file->mode)==0)) {
                                rprintf(FERROR, RSYNC_NAME ": recv_generator: mkdir \"%s\": %s (2)\n",
                                        fname,strerror(errno));
diff --git a/log.c b/log.c
index 411889c194448d1b6484dfe88d058c752db3c9ec..e79bc2205320316e46b00483346eff2e53883df7 100644 (file)
--- a/log.c
+++ b/log.c
@@ -30,6 +30,7 @@
 static char *logfname;
 static FILE *logfile;
 static int log_error_fd = -1;
+struct stats stats;
 
 int log_got_error=0;
 
diff --git a/main.c b/main.c
index 86eca2ca9b62f48ad97125a41555dcec76d507a2..b946e7543d8dce5bd24cd4dc4f374aaed217a38d 100644 (file)
--- a/main.c
+++ b/main.c
@@ -23,8 +23,7 @@
 
 time_t starttime = 0;
 
-struct stats stats;
-
+extern struct stats stats;
 extern int verbose;
 
 static void show_malloc_stats(void);
index 22d332c9877565731a0be899f3c51daaa7ffa192..a928316b3a08c2f377f209dca6615e9e04652035 100644 (file)
--- a/options.c
+++ b/options.c
@@ -88,6 +88,7 @@ int modify_window=0;
 #endif
 int blocking_io=-1;
 
+
 /** Network address family. **/
 #ifdef INET6
 int default_af_hint = 0;       /* Any protocol */
diff --git a/pipe.c b/pipe.c
new file mode 100644 (file)
index 0000000..e2e88ec
--- /dev/null
+++ b/pipe.c
@@ -0,0 +1,127 @@
+#include "rsync.h"
+
+/**
+ * Create a child connected to use on stdin/stdout.
+ *
+ * This is derived from CVS code 
+ * 
+ * Note that in the child STDIN is set to blocking and STDOUT
+ * is set to non-blocking. This is necessary as rsh relies on stdin being blocking
+ *  and ssh relies on stdout being non-blocking
+ *
+ * If blocking_io is set then use blocking io on both fds. That can be
+ * used to cope with badly broken rsh implementations like the one on
+ * Solaris.
+ **/
+pid_t piped_child(char **command, int *f_in, int *f_out)
+{
+       pid_t pid;
+       int to_child_pipe[2];
+       int from_child_pipe[2];
+       extern int blocking_io;
+       
+       if (verbose >= 2) {
+               print_child_argv(command);
+       }
+
+       if (fd_pair(to_child_pipe) < 0 || fd_pair(from_child_pipe) < 0) {
+               rprintf(FERROR, "pipe: %s\n", strerror(errno));
+               exit_cleanup(RERR_IPC);
+       }
+
+
+       pid = do_fork();
+       if (pid == -1) {
+               rprintf(FERROR, "fork: %s\n", strerror(errno));
+               exit_cleanup(RERR_IPC);
+       }
+
+       if (pid == 0) {
+               extern int orig_umask;
+               if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
+                   close(to_child_pipe[1]) < 0 ||
+                   close(from_child_pipe[0]) < 0 ||
+                   dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
+                       rprintf(FERROR, "Failed to dup/close : %s\n",
+                               strerror(errno));
+                       exit_cleanup(RERR_IPC);
+               }
+               if (to_child_pipe[0] != STDIN_FILENO)
+                       close(to_child_pipe[0]);
+               if (from_child_pipe[1] != STDOUT_FILENO)
+                       close(from_child_pipe[1]);
+               umask(orig_umask);
+               set_blocking(STDIN_FILENO);
+               if (blocking_io) {
+                       set_blocking(STDOUT_FILENO);
+               }
+               execvp(command[0], command);
+               rprintf(FERROR, "Failed to exec %s : %s\n",
+                       command[0], strerror(errno));
+               exit_cleanup(RERR_IPC);
+       }
+
+       if (close(from_child_pipe[1]) < 0 || close(to_child_pipe[0]) < 0) {
+               rprintf(FERROR, "Failed to close : %s\n", strerror(errno));
+               exit_cleanup(RERR_IPC);
+       }
+
+       *f_in = from_child_pipe[0];
+       *f_out = to_child_pipe[1];
+
+       return pid;
+}
+
+pid_t local_child(int argc, char **argv,int *f_in,int *f_out,
+                 int (*child_main)(int, char **))
+{
+       pid_t pid;
+       int to_child_pipe[2];
+       int from_child_pipe[2];
+       extern int read_batch;  /* dw */
+
+       if (fd_pair(to_child_pipe) < 0 ||
+           fd_pair(from_child_pipe) < 0) {
+               rprintf(FERROR,"pipe: %s\n",strerror(errno));
+               exit_cleanup(RERR_IPC);
+       }
+
+
+       pid = do_fork();
+       if (pid == -1) {
+               rprintf(FERROR,"fork: %s\n",strerror(errno));
+               exit_cleanup(RERR_IPC);
+       }
+
+       if (pid == 0) {
+               extern int am_sender;
+               extern int am_server;
+
+               am_sender = read_batch ? 0 : !am_sender;
+               am_server = 1;          
+
+               if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
+                   close(to_child_pipe[1]) < 0 ||
+                   close(from_child_pipe[0]) < 0 ||
+                   dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
+                       rprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
+                       exit_cleanup(RERR_IPC);
+               }
+               if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
+               if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
+               child_main(argc, argv);
+       }
+
+       if (close(from_child_pipe[1]) < 0 ||
+           close(to_child_pipe[0]) < 0) {
+               rprintf(FERROR,"Failed to close : %s\n",strerror(errno));   
+               exit_cleanup(RERR_IPC);
+       }
+
+       *f_in = from_child_pipe[0];
+       *f_out = to_child_pipe[1];
+  
+       return pid;
+}
+
+
diff --git a/progress.c b/progress.c
new file mode 100644 (file)
index 0000000..004b5d1
--- /dev/null
@@ -0,0 +1,96 @@
+#include "rsync.h"
+
+static OFF_T  last_ofs;
+static struct timeval print_time;
+static struct timeval start_time;
+static OFF_T  start_ofs;
+
+static unsigned long msdiff(struct timeval *t1, struct timeval *t2)
+{
+    return (t2->tv_sec - t1->tv_sec) * 1000
+        + (t2->tv_usec - t1->tv_usec) / 1000;
+}
+
+
+/**
+ * @param ofs Current position in file
+ * @param size Total size of file
+ * @param is_last True if this is the last time progress will be
+ * printed for this file, so we should output a newline.  (Not
+ * necessarily the same as all bytes being received.)
+ **/
+static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now,
+                           int is_last)
+{
+    int           pct  = (ofs == size) ? 100 : (int)((100.0*ofs)/size);
+    unsigned long diff = msdiff(&start_time, now);
+    double        rate = diff ? (double) (ofs-start_ofs) * 1000.0 / diff / 1024.0 : 0;
+    const char    *units;
+    /* If we've finished transferring this file, show the time taken;
+     * otherwise show expected time to complete.  That's kind of
+     * inconsistent, but people can probably cope.  Hopefully we'll
+     * get more consistent and complete progress reporting soon. --
+     * mbp */
+    double        remain = is_last
+                        ? (double) diff / 1000.0
+                        : rate ? (double) (size-ofs) / rate / 1000.0 : 0.0;
+    int          remain_h, remain_m, remain_s;
+
+    if (rate > 1024*1024) {
+           rate /= 1024.0 * 1024.0;
+           units = "GB/s";
+    } else if (rate > 1024) {
+           rate /= 1024.0;
+           units = "MB/s";
+    } else {
+           units = "kB/s";
+    }
+
+    remain_s = (int) remain % 60;
+    remain_m = (int) (remain / 60.0) % 60;
+    remain_h = (int) (remain / 3600.0);
+    
+    rprintf(FINFO, "%12.0f %3d%% %7.2f%s %4d:%02d:%02d%s",
+           (double) ofs, pct, rate, units,
+           remain_h, remain_m, remain_s,
+           is_last ? "\n" : "\r");
+}
+
+void end_progress(OFF_T size)
+{
+       extern int do_progress, am_server;
+
+       if (do_progress && !am_server) {
+               struct timeval now;
+                gettimeofday(&now, NULL);
+                rprint_progress(size, size, &now, True);
+       }
+       last_ofs   = 0;
+        start_ofs  = 0;
+        print_time.tv_sec  = print_time.tv_usec  = 0;
+        start_time.tv_sec  = start_time.tv_usec  = 0;
+}
+
+void show_progress(OFF_T ofs, OFF_T size)
+{
+       extern int do_progress, am_server;
+        struct timeval now;
+
+        gettimeofday(&now, NULL);
+
+        if (!start_time.tv_sec && !start_time.tv_usec) {
+               start_time.tv_sec  = now.tv_sec;
+                start_time.tv_usec = now.tv_usec;
+                start_ofs          = ofs;
+        }
+
+       if (do_progress
+            && !am_server
+            && ofs > last_ofs + 1000
+            && msdiff(&print_time, &now) > 250) {
+               rprint_progress(ofs, size, &now, False);
+                last_ofs = ofs;
+                print_time.tv_sec  = now.tv_sec;
+                print_time.tv_usec = now.tv_usec;
+       }
+}
index dbd8bfdb5b78bcd825d34c2558282cfae5eef1c2..14282338cbedccf36aa185afd3874d336e348ce5 100644 (file)
@@ -297,9 +297,10 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname,
 }
 
 
-/* main routine for receiver process. Receiver process runs on the
-       same host as the generator process. */
-
+/**
+ * main routine for receiver process.
+ *
+ * Receiver process runs on the same host as the generator process. */
 int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
 {  
        int fd1,fd2;
@@ -317,6 +318,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
        extern struct stats stats;              
        extern int preserve_perms;
        extern int delete_after;
+       extern int orig_umask;
        struct stats initial_stats;
 
        if (verbose > 2) {
@@ -434,7 +436,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
                   because their information should have been previously
                   transferred, but that may not be the case with -R */
                if (fd2 == -1 && relative_paths && errno == ENOENT && 
-                   create_directory_path(fnametmp) == 0) {
+                   create_directory_path(fnametmp, orig_umask) == 0) {
                        strlcpy(fnametmp, template, sizeof(fnametmp));
                        fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
                }