The sender now sets IOERR_GENERAL in more skipped-file instances.
[rsync/rsync.git] / flist.c
diff --git a/flist.c b/flist.c
index f485aca..9b69d92 100644 (file)
--- a/flist.c
+++ b/flist.c
@@ -638,7 +638,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
        int alloc_len, basename_len, linkname_len;
        int extra_len = file_extra_cnt * EXTRA_LEN;
        int first_hlink_ndx = -1;
-       OFF_T file_length;
+       int64 file_length;
        const char *basename;
        struct file_struct *file;
        alloc_pool_t *pool;
@@ -837,8 +837,14 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
        if (always_checksum && S_ISREG(mode))
                extra_len += SUM_EXTRA_CNT * EXTRA_LEN;
 
+#if SIZEOF_INT64 >= 8
        if (file_length > 0xFFFFFFFFu && S_ISREG(mode))
                extra_len += EXTRA_LEN;
+#endif
+       if (file_length < 0) {
+               rprintf(FERROR, "Offset underflow: file-length is negative\n");
+               exit_cleanup(RERR_UNSUPPORTED);
+       }
 
        if (inc_recurse && S_ISDIR(mode)) {
                if (one_file_system) {
@@ -871,10 +877,17 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
 #endif
        file->modtime = (time_t)modtime;
        file->len32 = (uint32)file_length;
+#if SIZEOF_INT64 >= 8
        if (file_length > 0xFFFFFFFFu && S_ISREG(mode)) {
+#if SIZEOF_CAPITAL_OFF_T < 8
+               rprintf(FERROR, "Offset overflow: attempted 64-bit file-length\n");
+               exit_cleanup(RERR_UNSUPPORTED);
+#else
                file->flags |= FLAG_LENGTH64;
                OPT_EXTRA(file, 0)->unum = (uint32)(file_length >> 32);
+#endif
        }
+#endif
        file->mode = mode;
        if (preserve_uid)
                F_OWNER(file) = uid;
@@ -1009,7 +1022,12 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
  * and performing extensive checks against global options.
  *
  * Returns a pointer to the new file struct, or NULL if there was an error
- * or this file should be excluded. */
+ * or this file should be excluded.
+ *
+ * Note: Any error (here or in send_file_name) that results in the omission of
+ * an existent source file from the file list should set
+ * "io_error |= IOERR_GENERAL" to avoid deletion of the file from the
+ * destination if --delete is on. */
 struct file_struct *make_file(const char *fname, struct file_list *flist,
                              STRUCT_STAT *stp, int flags, int filter_level)
 {
@@ -1026,6 +1044,7 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
        char *bp;
 
        if (strlcpy(thisname, fname, sizeof thisname) >= sizeof thisname) {
+               io_error |= IOERR_GENERAL;
                rprintf(FINFO, "skipping overly long name: %s\n", fname);
                return NULL;
        }
@@ -1163,8 +1182,10 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
        linkname_len = 0;
 #endif
 
+#if SIZEOF_CAPITAL_OFF_T >= 8
        if (st.st_size > 0xFFFFFFFFu && S_ISREG(st.st_mode))
                extra_len += EXTRA_LEN;
+#endif
 
 #if EXTRA_ROUNDING > 0
        if (extra_len & (EXTRA_ROUNDING * EXTRA_LEN))
@@ -1209,10 +1230,12 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
        file->flags = flags;
        file->modtime = st.st_mtime;
        file->len32 = (uint32)st.st_size;
+#if SIZEOF_CAPITAL_OFF_T >= 8
        if (st.st_size > 0xFFFFFFFFu && S_ISREG(st.st_mode)) {
                file->flags |= FLAG_LENGTH64;
                OPT_EXTRA(file, 0)->unum = (uint32)(st.st_size >> 32);
        }
+#endif
        file->mode = st.st_mode;
        if (uid_ndx) /* Check uid_ndx instead of preserve_uid for del support */
                F_OWNER(file) = st.st_uid;
@@ -1324,15 +1347,19 @@ static struct file_struct *send_file_name(int f, struct file_list *flist,
                if (preserve_acls && !S_ISLNK(file->mode)) {
                        sx.st.st_mode = file->mode;
                        sx.acc_acl = sx.def_acl = NULL;
-                       if (get_acl(fname, &sx) < 0)
+                       if (get_acl(fname, &sx) < 0) {
+                               io_error |= IOERR_GENERAL;
                                return NULL;
+                       }
                }
 #endif
 #ifdef SUPPORT_XATTRS
                if (preserve_xattrs) {
                        sx.xattr = NULL;
-                       if (get_xattr(fname, &sx) < 0)
+                       if (get_xattr(fname, &sx) < 0) {
+                               io_error |= IOERR_GENERAL;
                                return NULL;
+                       }
                }
 #endif