X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/0d9eba0312d01b7c893e74f585b8214845610145..2171b9395b75cb33543655d85279a6178f2b77d9:/flist.c diff --git a/flist.c b/flist.c index f485aca4..9b69d921 100644 --- 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