X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/16edf86595a5a990a942fa045dfb523dae1fe6cb..8fc4033ef08e747c961c1bf6c43995a39bf732f4:/flist.c diff --git a/flist.c b/flist.c index 23def370..a4f3ca27 100644 --- a/flist.c +++ b/flist.c @@ -30,6 +30,7 @@ extern int am_root; extern int am_server; extern int am_daemon; extern int am_sender; +extern int am_generator; extern int inc_recurse; extern int do_progress; extern int always_checksum; @@ -196,12 +197,12 @@ static int readlink_stat(const char *path, STRUCT_STAT *stp, char *linkbuf) rprintf(FINFO,"copying unsafe symlink \"%s\" -> \"%s\"\n", path, linkbuf); } - return do_stat(path, stp); + return x_stat(path, stp, NULL); } } return 0; #else - return do_stat(path, stp); + return x_stat(path, stp, NULL); #endif } @@ -209,17 +210,17 @@ int link_stat(const char *path, STRUCT_STAT *stp, int follow_dirlinks) { #ifdef SUPPORT_LINKS if (copy_links) - return do_stat(path, stp); - if (do_lstat(path, stp) < 0) + return x_stat(path, stp, NULL); + if (x_lstat(path, stp, NULL) < 0) return -1; if (follow_dirlinks && S_ISLNK(stp->st_mode)) { STRUCT_STAT st; - if (do_stat(path, &st) == 0 && S_ISDIR(st.st_mode)) + if (x_stat(path, &st, NULL) == 0 && S_ISDIR(st.st_mode)) *stp = st; } return 0; #else - return do_stat(path, stp); + return x_stat(path, stp, NULL); #endif } @@ -254,31 +255,11 @@ static int is_excluded(char *fname, int is_dir, int filter_level) return 0; } -static int to_wire_mode(mode_t mode) -{ -#ifdef SUPPORT_LINKS -#if _S_IFLNK != 0120000 - if (S_ISLNK(mode)) - return (mode & ~(_S_IFMT)) | 0120000; -#endif -#endif - return mode; -} - -static mode_t from_wire_mode(int mode) -{ -#if _S_IFLNK != 0120000 - if ((mode & (_S_IFMT)) == 0120000) - return (mode & ~(_S_IFMT)) | _S_IFLNK; -#endif - return mode; -} - static void send_directory(int f, struct file_list *flist, int ndx, char *fbuf, int len, int flags); -static const char *flist_dir, *orig_dir; -static int flist_dir_len; +static const char *pathname, *orig_dir; +static int pathname_len; /** @@ -322,15 +303,15 @@ void flist_expand(struct file_list *flist) out_of_memory("flist_expand"); } -int push_flist_dir(const char *dir, int len) +int push_pathname(const char *dir, int len) { - if (dir == flist_dir) + if (dir == pathname) return 1; if (!orig_dir) orig_dir = strdup(curr_dir); - if (flist_dir && !pop_dir(orig_dir)) { + if (pathname && !pop_dir(orig_dir)) { rsyserr(FERROR, errno, "pop_dir %s failed", full_fname(orig_dir)); exit_cleanup(RERR_FILESELECT); @@ -343,8 +324,8 @@ int push_flist_dir(const char *dir, int len) return 0; } - flist_dir = dir; - flist_dir_len = len >= 0 ? len : dir ? (int)strlen(dir) : 0; + pathname = dir; + pathname_len = len >= 0 ? len : dir ? (int)strlen(dir) : 0; return 1; } @@ -471,26 +452,30 @@ 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_abbrevint30(f, l2); + write_varint30(f, l2); else write_byte(f, l2); write_buf(f, fname + l1, l2); if (first_hlink_ndx >= 0) { - write_abbrevint30(f, first_hlink_ndx); + write_varint30(f, first_hlink_ndx); goto the_end; } - write_longint(f, F_LENGTH(file)); - if (!(flags & XMIT_SAME_TIME)) - write_int(f, modtime); + write_varlong30(f, F_LENGTH(file), 3); + if (!(flags & XMIT_SAME_TIME)) { + if (protocol_version >= 30) + write_varlong(f, modtime, 4); + else + write_int(f, modtime); + } if (!(flags & XMIT_SAME_MODE)) write_int(f, to_wire_mode(mode)); if (preserve_uid && !(flags & XMIT_SAME_UID)) { if (protocol_version < 30) write_int(f, uid); else { - write_abbrevint(f, uid); + write_varint(f, uid); if (flags & XMIT_USER_NAME_FOLLOWS) { int len = strlen(user_name); write_byte(f, len); @@ -502,7 +487,7 @@ static void send_file_entry(int f, struct file_struct *file, int ndx) if (protocol_version < 30) write_int(f, gid); else { - write_abbrevint(f, gid); + write_varint(f, gid); if (flags & XMIT_GROUP_NAME_FOLLOWS) { int len = strlen(group_name); write_byte(f, len); @@ -517,9 +502,9 @@ 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_abbrevint30(f, major(rdev)); + write_varint30(f, major(rdev)); if (protocol_version >= 30) - write_abbrevint(f, minor(rdev)); + write_varint(f, minor(rdev)); else if (flags & XMIT_RDEV_MINOR_8_pre30) write_byte(f, minor(rdev)); else @@ -531,7 +516,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_abbrevint30(f, len); + write_varint30(f, len); write_buf(f, sl, len); } #endif @@ -572,7 +557,7 @@ static void send_file_entry(int f, struct file_struct *file, int ndx) static struct file_struct *recv_file_entry(struct file_list *flist, int flags, int f) { - static time_t modtime; + static int64 modtime; static mode_t mode; static int64 dev; static dev_t rdev; @@ -590,14 +575,15 @@ static struct file_struct *recv_file_entry(struct file_list *flist, int first_hlink_ndx = -1; OFF_T file_length; const char *basename; - char *bp; struct file_struct *file; + alloc_pool_t *pool; + char *bp; if (flags & XMIT_SAME_NAME) l1 = read_byte(f); if (flags & XMIT_LONG_NAME) - l2 = read_abbrevint30(f); + l2 = read_varint30(f); else l2 = read_byte(f); @@ -636,7 +622,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_abbrevint30(f); + first_hlink_ndx = read_varint30(f); if (first_hlink_ndx < 0 || first_hlink_ndx >= flist->count) { rprintf(FERROR, "hard-link reference out of range: %d (%d)\n", @@ -665,9 +651,20 @@ static struct file_struct *recv_file_entry(struct file_list *flist, } #endif - file_length = read_longint(f); - if (!(flags & XMIT_SAME_TIME)) - modtime = (time_t)read_int(f); + file_length = read_varlong30(f, 3); + if (!(flags & XMIT_SAME_TIME)) { + if (protocol_version >= 30) { + modtime = read_varlong(f, 4); +#if SIZEOF_TIME_T < SIZEOF_INT64 + if ((modtime > INT_MAX || modtime < INT_MIN) && !am_generator) { + rprintf(FERROR, + "Time value of %s truncated on receiver.\n", + lastname); + } +#endif + } else + modtime = read_int(f); + } if (!(flags & XMIT_SAME_MODE)) mode = from_wire_mode(read_int(f)); @@ -678,7 +675,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist, if (protocol_version < 30) uid = (uid_t)read_int(f); else { - uid = (uid_t)read_abbrevint(f); + uid = (uid_t)read_varint(f); if (flags & XMIT_USER_NAME_FOLLOWS) uid = recv_user_name(f, uid); else if (inc_recurse && am_root && !numeric_ids) @@ -689,7 +686,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist, if (protocol_version < 30) gid = (gid_t)read_int(f); else { - gid = (gid_t)read_abbrevint(f); + gid = (gid_t)read_varint(f); if (flags & XMIT_GROUP_NAME_FOLLOWS) gid = recv_group_name(f, gid); else if (inc_recurse && (!am_root || !numeric_ids)) @@ -705,9 +702,9 @@ static struct file_struct *recv_file_entry(struct file_list *flist, } else { uint32 rdev_minor; if (!(flags & XMIT_SAME_RDEV_MAJOR)) - rdev_major = read_abbrevint30(f); + rdev_major = read_varint30(f); if (protocol_version >= 30) - rdev_minor = read_abbrevint(f); + rdev_minor = read_varint(f); else if (flags & XMIT_RDEV_MINOR_8_pre30) rdev_minor = read_byte(f); else @@ -721,7 +718,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist, #ifdef SUPPORT_LINKS if (preserve_links && S_ISLNK(mode)) { - linkname_len = read_abbrevint30(f) + 1; /* count the '\0' */ + linkname_len = read_varint30(f) + 1; /* count the '\0' */ if (linkname_len <= 0 || linkname_len > MAXPATHLEN) { rprintf(FERROR, "overflow: linkname_len=%d\n", linkname_len - 1); @@ -764,12 +761,13 @@ static struct file_struct *recv_file_entry(struct file_list *flist, /* Room to save the dir's device for -x */ extra_len += 2 * EXTRA_LEN; } - flist = dir_flist; - } + pool = dir_flist->file_pool; + } else + pool = flist->file_pool; alloc_len = FILE_STRUCT_LEN + extra_len + basename_len + linkname_len; - bp = pool_alloc(flist->file_pool, alloc_len, "recv_file_entry"); + bp = pool_alloc(pool, alloc_len, "recv_file_entry"); memset(bp, 0, extra_len + FILE_STRUCT_LEN); bp += extra_len; @@ -783,7 +781,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist, if (flags & XMIT_HLINKED) file->flags |= FLAG_HLINKED; #endif - file->modtime = modtime; + file->modtime = (time_t)modtime; file->len32 = (uint32)file_length; if (file_length > 0xFFFFFFFFu && S_ISREG(mode)) { file->flags |= FLAG_LENGTH64; @@ -930,7 +928,7 @@ struct file_struct *make_file(const char *fname, struct file_list *flist, char *bp; if (strlcpy(thisname, fname, sizeof thisname) - >= sizeof thisname - flist_dir_len) { + >= sizeof thisname - pathname_len) { rprintf(FINFO, "skipping overly long name: %s\n", fname); return NULL; } @@ -954,7 +952,7 @@ struct file_struct *make_file(const char *fname, struct file_list *flist, if (save_errno == ENOENT) { #ifdef SUPPORT_LINKS /* Avoid "vanished" error if symlink points nowhere. */ - if (copy_links && do_lstat(thisname, &st) == 0 + if (copy_links && x_lstat(thisname, &st, NULL) == 0 && S_ISLNK(st.st_mode)) { io_error |= IOERR_GENERAL; rprintf(FERROR, "symlink has no referent: %s\n", @@ -1117,7 +1115,7 @@ struct file_struct *make_file(const char *fname, struct file_list *flist, if (always_checksum && am_sender && S_ISREG(st.st_mode)) file_checksum(thisname, tmp_sum, st.st_size); - F_ROOTDIR(file) = flist_dir; + F_PATHNAME(file) = pathname; /* This code is only used by the receiver when it is building * a list of files for a delete pass. */ @@ -1126,7 +1124,7 @@ struct file_struct *make_file(const char *fname, struct file_list *flist, int save_mode = file->mode; file->mode = S_IFDIR; /* Find a directory with our name. */ if (flist_find(dir_flist, file) >= 0 - && do_stat(thisname, &st2) == 0 && S_ISDIR(st2.st_mode)) { + && x_stat(thisname, &st2, NULL) == 0 && S_ISDIR(st2.st_mode)) { file->modtime = st2.st_mtime; file->len32 = 0; file->mode = st2.st_mode; @@ -1361,8 +1359,8 @@ void send_extra_file_list(int f, int at_least) * files in the upcoming file-lists. */ if (cur_flist->next) { flist = first_flist->prev; /* the newest flist */ - future_cnt = flist->count - + flist->ndx_start - cur_flist->next->ndx_start; + future_cnt = flist->count + flist->ndx_start + - cur_flist->next->ndx_start; } else future_cnt = 0; while (future_cnt < at_least) { @@ -1373,8 +1371,8 @@ void send_extra_file_list(int f, int at_least) f_name(file, fbuf); dlen = strlen(fbuf); - if (F_ROOTDIR(file) != flist_dir) { - if (!push_flist_dir(F_ROOTDIR(file), -1)) + if (F_PATHNAME(file) != pathname) { + if (!push_pathname(F_PATHNAME(file), -1)) exit_cleanup(RERR_FILESELECT); } @@ -1383,7 +1381,8 @@ void send_extra_file_list(int f, int at_least) write_ndx(f, NDX_FLIST_OFFSET - send_dir_ndx); change_local_filter_dir(fbuf, dlen, send_dir_depth); - send_directory(f, flist, send_dir_ndx, fbuf, dlen, FLAG_DIVERT_DIRS | FLAG_XFER_DIR); + send_directory(f, flist, send_dir_ndx, fbuf, dlen, + FLAG_DIVERT_DIRS | FLAG_XFER_DIR); write_byte(f, 0); clean_flist(flist, 0, 0); @@ -1421,7 +1420,9 @@ void send_extra_file_list(int f, int at_least) struct file_list *send_file_list(int f, int argc, char *argv[]) { - int len; + static const char *lastdir; + static int lastdir_len = -1; + int len, dirlen; STRUCT_STAT st; char *p, *dir; char lastpath[MAXPATHLEN] = ""; @@ -1573,23 +1574,18 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) fn = "."; } - if (dir && *dir) { - static const char *lastdir; - static int lastdir_len = -1; - int len = strlen(dir); - - if (len != lastdir_len || memcmp(lastdir, dir, len) != 0) { - if (!push_flist_dir(strdup(dir), len)) - goto push_error; - lastdir = flist_dir; - lastdir_len = flist_dir_len; - } else if (!push_flist_dir(lastdir, lastdir_len)) { - push_error: - io_error |= IOERR_GENERAL; - rsyserr(FERROR, errno, "push_dir %s failed in %s", - full_fname(dir), curr_dir); - continue; - } + dirlen = dir ? strlen(dir) : 0; + if (dirlen != lastdir_len || memcmp(lastdir, dir, dirlen) != 0) { + if (!push_pathname(dir ? strdup(dir) : NULL, dirlen)) + goto push_error; + lastdir = pathname; + lastdir_len = pathname_len; + } else if (!push_pathname(lastdir, lastdir_len)) { + push_error: + io_error |= IOERR_GENERAL; + rsyserr(FERROR, errno, "push_dir %s failed in %s", + full_fname(dir), curr_dir); + continue; } if (fn != fbuf) @@ -1644,9 +1640,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) if (recurse || (xfer_dirs && is_dot_dir)) { struct file_struct *file; - int top_flags = FLAG_TOP_DIR | FLAG_XFER_DIR - | (is_dot_dir ? 0 : flags) - | (inc_recurse ? FLAG_DIVERT_DIRS : 0); + int top_flags = FLAG_TOP_DIR | FLAG_XFER_DIR | flags; file = send_file_name(f, flist, fbuf, &st, top_flags, ALL_FILTERS); if (file && !inc_recurse) @@ -2162,7 +2156,7 @@ static void output_flist(struct file_list *flist) if (!am_sender) snprintf(depthbuf, sizeof depthbuf, "%d", F_DEPTH(file)); if (F_IS_ACTIVE(file)) { - root = am_sender ? NS(F_ROOTDIR(file)) : depthbuf; + root = am_sender ? NS(F_PATHNAME(file)) : depthbuf; if ((dir = file->dirname) == NULL) dir = slash = ""; else