X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/569e6f432b6ba46d3a57a89ef4d9834825a18e49..2f188c8d96c8a0c887fb73bf3288168825af0401:/flist.c diff --git a/flist.c b/flist.c index 87a15b10..c7607f03 100644 --- a/flist.c +++ b/flist.c @@ -296,7 +296,7 @@ static void flist_expand(struct file_list *flist, int extra) flist->malloced); if (verbose >= 2 && flist->malloced != FLIST_START) { - rprintf(FCLIENT, "[%s] expand file_list to %.0f bytes, did%s move\n", + rprintf(FCLIENT, "[%s] expand file_list pointer array to %.0f bytes, did%s move\n", who_am_i(), (double)sizeof flist->files[0] * flist->malloced, (new_ptr == flist->files) ? " not" : ""); @@ -358,7 +358,7 @@ static void send_file_entry(int f, struct file_struct *file, int ndx) char fname[MAXPATHLEN]; int first_hlink_ndx = -1; int l1, l2; - int flags; + int xflags; #ifdef ICONV_OPTION if (ic_send != (iconv_t)-1) { @@ -390,56 +390,60 @@ static void send_file_entry(int f, struct file_struct *file, int ndx) #endif f_name(file, fname); - flags = file->flags & FLAG_TOP_DIR; /* FLAG_TOP_DIR == XMIT_TOP_DIR */ + xflags = file->flags & FLAG_TOP_DIR; /* FLAG_TOP_DIR == XMIT_TOP_DIR */ if (file->mode == mode) - flags |= XMIT_SAME_MODE; + xflags |= XMIT_SAME_MODE; else mode = file->mode; + + if (protocol_version >= 30 && S_ISDIR(mode) && !(file->flags & FLAG_XFER_DIR)) + xflags |= XMIT_NON_XFER_DIR; + if ((preserve_devices && IS_DEVICE(mode)) || (preserve_specials && IS_SPECIAL(mode))) { if (protocol_version < 28) { if (tmp_rdev == rdev) - flags |= XMIT_SAME_RDEV_pre28; + xflags |= XMIT_SAME_RDEV_pre28; else rdev = tmp_rdev; } else { rdev = tmp_rdev; if ((uint32)major(rdev) == rdev_major) - flags |= XMIT_SAME_RDEV_MAJOR; + xflags |= XMIT_SAME_RDEV_MAJOR; else rdev_major = major(rdev); if (protocol_version < 30 && (uint32)minor(rdev) <= 0xFFu) - flags |= XMIT_RDEV_MINOR_8_pre30; + xflags |= XMIT_RDEV_MINOR_8_pre30; } } else if (protocol_version < 28) rdev = MAKEDEV(0, 0); if (uid_ndx) { if ((uid_t)F_OWNER(file) == uid && *lastname) - flags |= XMIT_SAME_UID; + xflags |= XMIT_SAME_UID; else { uid = F_OWNER(file); if (uid_ndx && !numeric_ids) { user_name = add_uid(uid); if (inc_recurse && user_name) - flags |= XMIT_USER_NAME_FOLLOWS; + xflags |= XMIT_USER_NAME_FOLLOWS; } } } if (gid_ndx) { if ((gid_t)F_GROUP(file) == gid && *lastname) - flags |= XMIT_SAME_GID; + xflags |= XMIT_SAME_GID; else { gid = F_GROUP(file); if (gid_ndx && !numeric_ids) { group_name = add_gid(gid); if (inc_recurse && group_name) - flags |= XMIT_GROUP_NAME_FOLLOWS; + xflags |= XMIT_GROUP_NAME_FOLLOWS; } } } if (file->modtime == modtime) - flags |= XMIT_SAME_TIME; + xflags |= XMIT_SAME_TIME; else modtime = file->modtime; @@ -450,16 +454,16 @@ static void send_file_entry(int f, struct file_struct *file, int ndx) first_hlink_ndx = (int32)(long)np->data - 1; if (first_hlink_ndx < 0) { np->data = (void*)(long)(ndx + 1); - flags |= XMIT_HLINK_FIRST; + xflags |= XMIT_HLINK_FIRST; } - flags |= XMIT_HLINKED; + xflags |= XMIT_HLINKED; } else { if (tmp_dev == dev) { if (protocol_version >= 28) - flags |= XMIT_SAME_DEV_pre30; + xflags |= XMIT_SAME_DEV_pre30; } else dev = tmp_dev; - flags |= XMIT_HLINKED; + xflags |= XMIT_HLINKED; } } #endif @@ -470,30 +474,30 @@ static void send_file_entry(int f, struct file_struct *file, int ndx) l2 = strlen(fname+l1); if (l1 > 0) - flags |= XMIT_SAME_NAME; + xflags |= XMIT_SAME_NAME; if (l2 > 255) - flags |= XMIT_LONG_NAME; + xflags |= XMIT_LONG_NAME; /* We must make sure we don't send a zero flag byte or the * other end will terminate the flist transfer. Note that * the use of XMIT_TOP_DIR on a non-dir has no meaning, so * it's harmless way to add a bit to the first flag byte. */ if (protocol_version >= 28) { - if (!flags && !S_ISDIR(mode)) - flags |= XMIT_TOP_DIR; - if ((flags & 0xFF00) || !flags) { - flags |= XMIT_EXTENDED_FLAGS; - write_shortint(f, flags); + if (!xflags && !S_ISDIR(mode)) + xflags |= XMIT_TOP_DIR; + if ((xflags & 0xFF00) || !xflags) { + xflags |= XMIT_EXTENDED_FLAGS; + write_shortint(f, xflags); } else - write_byte(f, flags); + write_byte(f, xflags); } else { - if (!(flags & 0xFF)) - flags |= S_ISDIR(mode) ? XMIT_LONG_NAME : XMIT_TOP_DIR; - write_byte(f, flags); + if (!(xflags & 0xFF)) + xflags |= S_ISDIR(mode) ? XMIT_LONG_NAME : XMIT_TOP_DIR; + write_byte(f, xflags); } - if (flags & XMIT_SAME_NAME) + if (xflags & XMIT_SAME_NAME) write_byte(f, l1); - if (flags & XMIT_LONG_NAME) + if (xflags & XMIT_LONG_NAME) write_varint30(f, l2); else write_byte(f, l2); @@ -505,32 +509,32 @@ static void send_file_entry(int f, struct file_struct *file, int ndx) } write_varlong30(f, F_LENGTH(file), 3); - if (!(flags & XMIT_SAME_TIME)) { + if (!(xflags & XMIT_SAME_TIME)) { if (protocol_version >= 30) write_varlong(f, modtime, 4); else write_int(f, modtime); } - if (!(flags & XMIT_SAME_MODE)) + if (!(xflags & XMIT_SAME_MODE)) write_int(f, to_wire_mode(mode)); - if (uid_ndx && !(flags & XMIT_SAME_UID)) { + if (uid_ndx && !(xflags & XMIT_SAME_UID)) { if (protocol_version < 30) write_int(f, uid); else { write_varint(f, uid); - if (flags & XMIT_USER_NAME_FOLLOWS) { + if (xflags & XMIT_USER_NAME_FOLLOWS) { int len = strlen(user_name); write_byte(f, len); write_buf(f, user_name, len); } } } - if (gid_ndx && !(flags & XMIT_SAME_GID)) { + if (gid_ndx && !(xflags & XMIT_SAME_GID)) { if (protocol_version < 30) write_int(f, gid); else { write_varint(f, gid); - if (flags & XMIT_GROUP_NAME_FOLLOWS) { + if (xflags & XMIT_GROUP_NAME_FOLLOWS) { int len = strlen(group_name); write_byte(f, len); write_buf(f, group_name, len); @@ -540,14 +544,14 @@ static void send_file_entry(int f, struct file_struct *file, int ndx) if ((preserve_devices && IS_DEVICE(mode)) || (preserve_specials && IS_SPECIAL(mode))) { if (protocol_version < 28) { - if (!(flags & XMIT_SAME_RDEV_pre28)) + if (!(xflags & XMIT_SAME_RDEV_pre28)) write_int(f, (int)rdev); } else { - if (!(flags & XMIT_SAME_RDEV_MAJOR)) + if (!(xflags & XMIT_SAME_RDEV_MAJOR)) write_varint30(f, major(rdev)); if (protocol_version >= 30) write_varint(f, minor(rdev)); - else if (flags & XMIT_RDEV_MINOR_8_pre30) + else if (xflags & XMIT_RDEV_MINOR_8_pre30) write_byte(f, minor(rdev)); else write_int(f, minor(rdev)); @@ -571,7 +575,7 @@ static void send_file_entry(int f, struct file_struct *file, int ndx) write_int(f, (int32)tmp_ino); } else { /* 64-bit dev_t and ino_t */ - if (!(flags & XMIT_SAME_DEV_pre30)) + if (!(xflags & XMIT_SAME_DEV_pre30)) write_longint(f, dev); write_longint(f, tmp_ino); } @@ -885,6 +889,9 @@ static struct file_struct *recv_file_entry(struct file_list *flist, && lastname[del_hier_name_len-2] == '/') del_hier_name_len -= 2; file->flags |= FLAG_TOP_DIR | FLAG_XFER_DIR; + } else if (protocol_version >= 30) { + if (!(xflags & XMIT_NON_XFER_DIR)) + file->flags |= FLAG_XFER_DIR; } else if (in_del_hier) { if (!relative_paths || !del_hier_name_len || (l1 >= del_hier_name_len @@ -973,34 +980,24 @@ static struct file_struct *recv_file_entry(struct file_list *flist, return file; } -/** - * Create a file_struct for a named file by reading its stat() - * information and performing extensive checks against global - * options. +/* Create a file_struct for a named file by reading its stat() information + * and performing extensive checks against global options. * - * @return the new file, or NULL if there was an error or this file - * should be excluded. - * - * @todo There is a small optimization opportunity here to avoid - * stat()ing the file in some circumstances, which has a certain cost. - * We are called immediately after doing readdir(), and so we may - * already know the d_type of the file. We could for example avoid - * statting directories if we're not recursing, but this is not a very - * important case. Some systems may not have d_type. - **/ + * Returns a pointer to the new file struct, or NULL if there was an error + * or this file should be excluded. */ struct file_struct *make_file(const char *fname, struct file_list *flist, STRUCT_STAT *stp, int flags, int filter_level) { static char *lastdir; static int lastdir_len = -1; struct file_struct *file; - STRUCT_STAT st; char thisname[MAXPATHLEN]; char linkname[MAXPATHLEN]; int alloc_len, basename_len, linkname_len; int extra_len = file_extra_cnt * EXTRA_LEN; const char *basename; alloc_pool_t *pool; + STRUCT_STAT st; char *bp; if (strlcpy(thisname, fname, sizeof thisname) >= sizeof thisname) { @@ -1053,10 +1050,13 @@ struct file_struct *make_file(const char *fname, struct file_list *flist, if (filter_level == NO_FILTERS) goto skip_filters; - if (S_ISDIR(st.st_mode) && !xfer_dirs) { - rprintf(FINFO, "skipping directory %s\n", thisname); - return NULL; - } + if (S_ISDIR(st.st_mode)) { + if (!xfer_dirs) { + rprintf(FINFO, "skipping directory %s\n", thisname); + return NULL; + } + } else + flags &= ~FLAG_XFER_DIR; /* -x only affects directories because we need to avoid recursing * into a mount-point directory, not to avoid copying a symlinked @@ -1469,6 +1469,13 @@ static void send_directory(int f, struct file_list *flist, char *fbuf, int len, full_fname(fbuf)); continue; } + if (dname[0] == '\0') { + io_error |= IOERR_GENERAL; + rprintf(FINFO, + "cannot send file with empty name in %s\n", + full_fname(fbuf)); + continue; + } send_file_name(f, flist, fbuf, NULL, flags, filter_level); } @@ -1637,10 +1644,10 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) flist = cur_flist = flist_new(0, "send_file_list"); if (inc_recurse) { dir_flist = flist_new(FLIST_TEMP, "send_file_list"); - flags = FLAG_DIVERT_DIRS; + flags = FLAG_DIVERT_DIRS | FLAG_XFER_DIR; } else { dir_flist = cur_flist; - flags = 0; + flags = FLAG_XFER_DIR; } disable_buffering = io_start_buffering_out(f); @@ -1806,7 +1813,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) if (fn != p || (*lp && *lp != '/')) { int save_copy_links = copy_links; int save_xfer_dirs = xfer_dirs; - int dir_flags = inc_recurse ? FLAG_DIVERT_DIRS : 0; + int dir_flags = flags & ~FLAG_XFER_DIR; copy_links |= copy_unsafe_links; xfer_dirs = 1; while ((slash = strchr(slash+1, '/')) != 0) { @@ -1828,7 +1835,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 | flags; + int top_flags = FLAG_TOP_DIR | flags; file = send_file_name(f, flist, fbuf, &st, top_flags, ALL_FILTERS); if (file && !inc_recurse)