Protocol 30 now uses MD5 checksums instead of MD4.
[rsync/rsync.git] / flist.c
diff --git a/flist.c b/flist.c
index 700d9f7..abbc6da 100644 (file)
--- a/flist.c
+++ b/flist.c
@@ -22,6 +22,7 @@
 
 #include "rsync.h"
 #include "rounding.h"
+#include "io.h"
 
 extern int verbose;
 extern int list_only;
@@ -41,6 +42,7 @@ extern int filesfrom_fd;
 extern int one_file_system;
 extern int copy_dirlinks;
 extern int keep_dirlinks;
+extern int preserve_acls;
 extern int preserve_links;
 extern int preserve_hard_links;
 extern int preserve_devices;
@@ -83,9 +85,9 @@ static dev_t tmp_rdev;
 #ifdef SUPPORT_HARD_LINKS
 static int64 tmp_dev, tmp_ino;
 #endif
-static char tmp_sum[MD4_SUM_LENGTH];
+static char tmp_sum[MAX_DIGEST_LEN];
 
-static char empty_sum[MD4_SUM_LENGTH];
+static char empty_sum[MAX_DIGEST_LEN];
 static int flist_count_offset; /* for --delete --progress */
 
 static void clean_flist(struct file_list *flist, int strip_root, int no_dups);
@@ -97,7 +99,9 @@ void init_flist(void)
                rprintf(FINFO, "FILE_STRUCT_LEN=%d, EXTRA_LEN=%d\n",
                        (int)FILE_STRUCT_LEN, (int)EXTRA_LEN);
        }
-       checksum_len = protocol_version < 21 ? 2 : MD4_SUM_LENGTH;
+       checksum_len = protocol_version < 21 ? 2
+                    : protocol_version < 30 ? MD4_DIGEST_LEN
+                    : MD5_DIGEST_LEN;
 }
 
 static int show_filelist_p(void)
@@ -152,6 +156,8 @@ static void list_file_entry(struct file_struct *f)
        permstring(permbuf, f->mode);
        len = F_LENGTH(f);
 
+       /* TODO: indicate '+' if the entry has an ACL. */
+
 #ifdef SUPPORT_LINKS
        if (preserve_links && S_ISLNK(f->mode)) {
                rprintf(FINFO, "%s %11.0f %s %s -> %s\n",
@@ -379,8 +385,8 @@ static void send_file_entry(int f, struct file_struct *file, int ndx)
                                flags |= XMIT_SAME_RDEV_MAJOR;
                        else
                                rdev_major = major(rdev);
-                       if ((uint32)minor(rdev) <= 0xFFu)
-                               flags |= XMIT_RDEV_MINOR_IS_SMALL;
+                       if (protocol_version < 30 && (uint32)minor(rdev) <= 0xFFu)
+                               flags |= XMIT_RDEV_MINOR_8_pre30;
                }
        } else if (protocol_version < 28)
                rdev = MAKEDEV(0, 0);
@@ -464,13 +470,13 @@ static void send_file_entry(int f, struct file_struct *file, int ndx)
        if (flags & XMIT_SAME_NAME)
                write_byte(f, l1);
        if (flags & XMIT_LONG_NAME)
-               write_int(f, l2);
+               write_abbrevint30(f, l2);
        else
                write_byte(f, l2);
        write_buf(f, fname + l1, l2);
 
        if (first_hlink_ndx >= 0) {
-               write_int(f, first_hlink_ndx);
+               write_abbrevint30(f, first_hlink_ndx);
                goto the_end;
        }
 
@@ -480,19 +486,27 @@ static void send_file_entry(int f, struct file_struct *file, int ndx)
        if (!(flags & XMIT_SAME_MODE))
                write_int(f, to_wire_mode(mode));
        if (preserve_uid && !(flags & XMIT_SAME_UID)) {
-               write_int(f, uid);
-               if (flags & XMIT_USER_NAME_FOLLOWS) {
-                       int len = strlen(user_name);
-                       write_byte(f, len);
-                       write_buf(f, user_name, len);
+               if (protocol_version < 30)
+                       write_int(f, uid);
+               else {
+                       write_abbrevint(f, uid);
+                       if (flags & XMIT_USER_NAME_FOLLOWS) {
+                               int len = strlen(user_name);
+                               write_byte(f, len);
+                               write_buf(f, user_name, len);
+                       }
                }
        }
        if (preserve_gid && !(flags & XMIT_SAME_GID)) {
-               write_int(f, gid);
-               if (flags & XMIT_GROUP_NAME_FOLLOWS) {
-                       int len = strlen(group_name);
-                       write_byte(f, len);
-                       write_buf(f, group_name, len);
+               if (protocol_version < 30)
+                       write_int(f, gid);
+               else {
+                       write_abbrevint(f, gid);
+                       if (flags & XMIT_GROUP_NAME_FOLLOWS) {
+                               int len = strlen(group_name);
+                               write_byte(f, len);
+                               write_buf(f, group_name, len);
+                       }
                }
        }
        if ((preserve_devices && IS_DEVICE(mode))
@@ -502,8 +516,10 @@ static void send_file_entry(int f, struct file_struct *file, int ndx)
                                write_int(f, (int)rdev);
                } else {
                        if (!(flags & XMIT_SAME_RDEV_MAJOR))
-                               write_int(f, major(rdev));
-                       if (flags & XMIT_RDEV_MINOR_IS_SMALL)
+                               write_abbrevint30(f, major(rdev));
+                       if (protocol_version >= 30)
+                               write_abbrevint(f, minor(rdev));
+                       else if (flags & XMIT_RDEV_MINOR_8_pre30)
                                write_byte(f, minor(rdev));
                        else
                                write_int(f, minor(rdev));
@@ -514,7 +530,7 @@ static void send_file_entry(int f, struct file_struct *file, int ndx)
        if (preserve_links && S_ISLNK(mode)) {
                const char *sl = F_SYMLINK(file);
                int len = strlen(sl);
-               write_int(f, len);
+               write_abbrevint30(f, len);
                write_buf(f, sl, len);
        }
 #endif
@@ -580,7 +596,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
                l1 = read_byte(f);
 
        if (flags & XMIT_LONG_NAME)
-               l2 = read_int(f);
+               l2 = read_abbrevint30(f);
        else
                l2 = read_byte(f);
 
@@ -619,7 +635,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
        if (protocol_version >= 30
         && BITS_SETnUNSET(flags, XMIT_HLINKED, XMIT_HLINK_FIRST)) {
                struct file_struct *first;
-               first_hlink_ndx = read_int(f);
+               first_hlink_ndx = read_abbrevint30(f);
                if (first_hlink_ndx < 0 || first_hlink_ndx >= flist->count) {
                        rprintf(FERROR,
                                "hard-link reference out of range: %d (%d)\n",
@@ -638,6 +654,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
                 || (preserve_specials && IS_SPECIAL(mode))) {
                        uint32 *devp = F_RDEV_P(first);
                        rdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp));
+                       extra_len += 2 * EXTRA_LEN;
                }
                if (preserve_links && S_ISLNK(mode))
                        linkname_len = strlen(F_SYMLINK(first)) + 1;
@@ -657,18 +674,26 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
                mode = tweak_mode(mode, chmod_modes);
 
        if (preserve_uid && !(flags & XMIT_SAME_UID)) {
-               uid = (uid_t)read_int(f);
-               if (flags & XMIT_USER_NAME_FOLLOWS)
-                       uid = recv_user_name(f, uid);
-               else if (inc_recurse && am_root && !numeric_ids)
-                       uid = match_uid(uid);
+               if (protocol_version < 30)
+                       uid = (uid_t)read_int(f);
+               else {
+                       uid = (uid_t)read_abbrevint(f);
+                       if (flags & XMIT_USER_NAME_FOLLOWS)
+                               uid = recv_user_name(f, uid);
+                       else if (inc_recurse && am_root && !numeric_ids)
+                               uid = match_uid(uid);
+               }
        }
        if (preserve_gid && !(flags & XMIT_SAME_GID)) {
-               gid = (gid_t)read_int(f);
-               if (flags & XMIT_GROUP_NAME_FOLLOWS)
-                       gid = recv_group_name(f, gid);
-               else if (inc_recurse && (!am_root || !numeric_ids))
-                       gid = match_gid(gid);
+               if (protocol_version < 30)
+                       gid = (gid_t)read_int(f);
+               else {
+                       gid = (gid_t)read_abbrevint(f);
+                       if (flags & XMIT_GROUP_NAME_FOLLOWS)
+                               gid = recv_group_name(f, gid);
+                       else if (inc_recurse && (!am_root || !numeric_ids))
+                               gid = match_gid(gid);
+               }
        }
 
        if ((preserve_devices && IS_DEVICE(mode))
@@ -679,8 +704,10 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
                } else {
                        uint32 rdev_minor;
                        if (!(flags & XMIT_SAME_RDEV_MAJOR))
-                               rdev_major = read_int(f);
-                       if (flags & XMIT_RDEV_MINOR_IS_SMALL)
+                               rdev_major = read_abbrevint30(f);
+                       if (protocol_version >= 30)
+                               rdev_minor = read_abbrevint(f);
+                       else if (flags & XMIT_RDEV_MINOR_8_pre30)
                                rdev_minor = read_byte(f);
                        else
                                rdev_minor = read_int(f);
@@ -693,7 +720,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
 
 #ifdef SUPPORT_LINKS
        if (preserve_links && S_ISLNK(mode)) {
-               linkname_len = read_int(f) + 1; /* count the '\0' */
+               linkname_len = read_abbrevint30(f) + 1; /* count the '\0' */
                if (linkname_len <= 0 || linkname_len > MAXPATHLEN) {
                        rprintf(FERROR, "overflow: linkname_len=%d\n",
                                linkname_len - 1);
@@ -714,6 +741,12 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
        }
 #endif
 
+#ifdef SUPPORT_ACLS
+       /* We need one or two index int32s when we're preserving ACLs. */
+       if (preserve_acls)
+               extra_len += (S_ISDIR(mode) ? 2 : 1) * EXTRA_LEN;
+#endif
+
        if (always_checksum && S_ISREG(mode))
                extra_len += SUM_EXTRA_CNT * EXTRA_LEN;
 
@@ -851,6 +884,11 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
                        read_buf(f, bp, checksum_len);
        }
 
+#ifdef SUPPORT_ACLS
+       if (preserve_acls && !S_ISLNK(mode))
+               receive_acl(file, f);
+#endif
+
        if (S_ISREG(mode) || S_ISLNK(mode))
                stats.total_size += file_length;
 
@@ -1122,6 +1160,9 @@ static struct file_struct *send_file_name(int f, struct file_list *flist,
                                          int flags, int filter_flags)
 {
        struct file_struct *file;
+#ifdef SUPPORT_ACLS
+       statx sx;
+#endif
 
        file = make_file(fname, flist, stp, flags, filter_flags);
        if (!file)
@@ -1130,12 +1171,28 @@ static struct file_struct *send_file_name(int f, struct file_list *flist,
        if (chmod_modes && !S_ISLNK(file->mode))
                file->mode = tweak_mode(file->mode, chmod_modes);
 
+#ifdef SUPPORT_ACLS
+       if (preserve_acls && !S_ISLNK(file->mode) && f >= 0) {
+               sx.st.st_mode = file->mode;
+               sx.acc_acl = sx.def_acl = NULL;
+               if (get_acl(fname, &sx) < 0)
+                       return NULL;
+       }
+#endif
+
        maybe_emit_filelist_progress(flist->count + flist_count_offset);
 
        flist_expand(flist);
        flist->files[flist->count++] = file;
-       if (f >= 0)
+       if (f >= 0) {
                send_file_entry(f, file, flist->count - 1);
+#ifdef SUPPORT_ACLS
+               if (preserve_acls && !S_ISLNK(file->mode)) {
+                       send_acl(&sx, f);
+                       free_acl(&sx);
+               }
+#endif
+       }
        return file;
 }