Changed one strcpy() into a strlcpy().
[rsync/rsync.git] / flist.c
diff --git a/flist.c b/flist.c
index 476e750..1f11193 100644 (file)
--- a/flist.c
+++ b/flist.c
@@ -480,19 +480,16 @@ void send_file_entry(struct file_struct *file, int f, unsigned short base_flags)
        }
 #endif
 
-       if (always_checksum) {
+       if (always_checksum && (S_ISREG(mode) || protocol_version < 28)) {
                char *sum;
+               int slen = protocol_version < 21 ? 2 : MD4_SUM_LENGTH;
                if (S_ISREG(mode))
                        sum = file->u.sum;
-               else if (protocol_version < 28) {
+               else {
                        /* Prior to 28, we sent a useless set of nulls. */
                        sum = empty_sum;
-               } else
-                       sum = NULL;
-               if (sum) {
-                       write_buf(f, sum,
-                           protocol_version < 21 ? 2 : MD4_SUM_LENGTH);
                }
+               write_buf(f, sum, slen);
        }
 
        strlcpy(lastname, fname, MAXPATHLEN);
@@ -708,20 +705,17 @@ static struct file_struct *receive_file_entry(struct file_list *flist,
        }
 #endif
 
-       if (always_checksum) {
+       if (always_checksum && (sum_len || protocol_version < 28)) {
                char *sum;
+               int slen = protocol_version < 21 ? 2 : MD4_SUM_LENGTH;
                if (sum_len) {
                        file->u.sum = sum = bp;
                        /*bp += sum_len;*/
-               } else if (protocol_version < 28) {
+               } else {
                        /* Prior to 28, we get a useless set of nulls. */
                        sum = empty_sum;
-               } else
-                       sum = NULL;
-               if (sum) {
-                       read_buf(f, sum,
-                           protocol_version < 21 ? 2 : MD4_SUM_LENGTH);
                }
+               read_buf(f, sum, slen);
        }
 
        if (!preserve_perms) {
@@ -1159,42 +1153,20 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
                if (!relative_paths) {
                        p = strrchr(fname, '/');
                        if (p) {
-                               *p = 0;
+                               *p = '\0';
                                if (p == fname)
                                        dir = "/";
                                else
                                        dir = fname;
                                fname = p + 1;
                        }
-               } else if (implied_dirs && (p=strrchr(fname,'/')) && p != fname) {
-                       /* this ensures we send the intermediate directories,
-                          thus getting their permissions right */
-                       char *lp = lastpath, *fn = fname, *slash = fname;
-                       *p = 0;
-                       /* Skip any initial directories in our path that we
-                        * have in common with lastpath. */
-                       while (*fn && *lp == *fn) {
-                               if (*fn == '/')
-                                       slash = fn;
-                               lp++, fn++;
-                       }
-                       *p = '/';
-                       if (fn != p || (*lp && *lp != '/')) {
-                               int save_copy_links = copy_links;
-                               int save_xfer_dirs = xfer_dirs;
-                               copy_links = copy_unsafe_links;
-                               xfer_dirs = 1;
-                               while ((slash = strchr(slash+1, '/')) != 0) {
-                                       *slash = 0;
-                                       send_file_name(f, flist, fname, 0);
-                                       *slash = '/';
-                               }
-                               copy_links = save_copy_links;
-                               xfer_dirs = save_xfer_dirs;
-                               *p = 0;
-                               strlcpy(lastpath, fname, sizeof lastpath);
-                               *p = '/';
-                       }
+               } else if ((p = strstr(fname, "/./")) != NULL) {
+                       *p = '\0';
+                       if (p == fname)
+                               dir = "/";
+                       else
+                               dir = fname;
+                       fname = p + 3;
                }
 
                if (!*fname)
@@ -1204,7 +1176,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
                        static char *lastdir;
                        static int lastdir_len;
 
-                       strcpy(olddir, curr_dir); /* can't overflow */
+                       strlcpy(olddir, curr_dir, sizeof olddir);
 
                        if (!push_dir(dir)) {
                                io_error |= IOERR_GENERAL;
@@ -1222,6 +1194,37 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
                        }
                }
 
+               if (implied_dirs && (p=strrchr(fname,'/')) && p != fname) {
+                       /* Send the implied directories at the start of the
+                        * source spec, so we get their permissions right. */
+                       char *lp = lastpath, *fn = fname, *slash = fname;
+                       *p = '\0';
+                       /* Skip any initial directories in our path that we
+                        * have in common with lastpath. */
+                       while (*fn && *lp == *fn) {
+                               if (*fn == '/')
+                                       slash = fn;
+                               lp++, fn++;
+                       }
+                       *p = '/';
+                       if (fn != p || (*lp && *lp != '/')) {
+                               int save_copy_links = copy_links;
+                               int save_xfer_dirs = xfer_dirs;
+                               copy_links = copy_unsafe_links;
+                               xfer_dirs = 1;
+                               while ((slash = strchr(slash+1, '/')) != 0) {
+                                       *slash = '\0';
+                                       send_file_name(f, flist, fname, 0);
+                                       *slash = '/';
+                               }
+                               copy_links = save_copy_links;
+                               xfer_dirs = save_xfer_dirs;
+                               *p = '\0';
+                               strlcpy(lastpath, fname, sizeof lastpath);
+                               *p = '/';
+                       }
+               }
+
                if (one_file_system)
                        filesystem_dev = st.st_dev;
 
@@ -1235,7 +1238,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
                        flist_dir_len = 0;
                        if (!pop_dir(olddir)) {
                                rsyserr(FERROR, errno, "pop_dir %s failed",
-                                       full_fname(dir));
+                                       full_fname(olddir));
                                exit_cleanup(RERR_FILESELECT);
                        }
                }