📄 flist.c
字号:
} xflags |= XMIT_HLINKED; }#endif for (l1 = 0; lastname[l1] && (fname[l1] == lastname[l1]) && (l1 < 255); l1++) {} l2 = strlen(fname+l1); if (l1 > 0) xflags |= XMIT_SAME_NAME; if (l2 > 255) 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 (!xflags && !S_ISDIR(mode)) xflags |= XMIT_TOP_DIR; if ((xflags & 0xFF00) || !xflags) { xflags |= XMIT_EXTENDED_FLAGS; write_shortint(f, xflags); } else write_byte(f, xflags); } else { if (!(xflags & 0xFF)) xflags |= S_ISDIR(mode) ? XMIT_LONG_NAME : XMIT_TOP_DIR; write_byte(f, xflags); } if (xflags & XMIT_SAME_NAME) write_byte(f, l1); if (xflags & XMIT_LONG_NAME) write_varint30(f, l2); else write_byte(f, l2); write_buf(f, fname + l1, l2); if (first_hlink_ndx >= 0) { write_varint(f, first_hlink_ndx); if (first_hlink_ndx >= first_ndx) goto the_end; } write_varlong30(f, F_LENGTH(file), 3); if (!(xflags & XMIT_SAME_TIME)) { if (protocol_version >= 30) write_varlong(f, modtime, 4); else write_int(f, modtime); } if (!(xflags & XMIT_SAME_MODE)) write_int(f, to_wire_mode(mode)); if (preserve_uid && !(xflags & XMIT_SAME_UID)) { if (protocol_version < 30) write_int(f, uid); else { write_varint(f, uid); if (xflags & XMIT_USER_NAME_FOLLOWS) { int len = strlen(user_name); write_byte(f, len); write_buf(f, user_name, len); } } } if (preserve_gid && !(xflags & XMIT_SAME_GID)) { if (protocol_version < 30) write_int(f, gid); else { write_varint(f, gid); if (xflags & 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)) || (preserve_specials && IS_SPECIAL(mode))) { if (protocol_version < 28) { if (!(xflags & XMIT_SAME_RDEV_pre28)) write_int(f, (int)rdev); } else { if (!(xflags & XMIT_SAME_RDEV_MAJOR)) write_varint30(f, major(rdev)); if (protocol_version >= 30) write_varint(f, minor(rdev)); else if (xflags & XMIT_RDEV_MINOR_8_pre30) write_byte(f, minor(rdev)); else write_int(f, minor(rdev)); } }#ifdef SUPPORT_LINKS if (symlink_len) { write_varint30(f, symlink_len); write_buf(f, symlink_name, symlink_len); }#endif#ifdef SUPPORT_HARD_LINKS if (tmp_dev != 0 && protocol_version < 30) { if (protocol_version < 26) { /* 32-bit dev_t and ino_t */ write_int(f, (int32)dev); write_int(f, (int32)tmp_ino); } else { /* 64-bit dev_t and ino_t */ if (!(xflags & XMIT_SAME_DEV_pre30)) write_longint(f, dev); write_longint(f, tmp_ino); } }#endif if (always_checksum && (S_ISREG(mode) || protocol_version < 28)) { const char *sum; if (S_ISREG(mode)) sum = tmp_sum; else { /* Prior to 28, we sent a useless set of nulls. */ sum = empty_sum; } write_buf(f, sum, checksum_len); } the_end: strlcpy(lastname, fname, MAXPATHLEN); if (S_ISREG(mode) || S_ISLNK(mode)) stats.total_size += F_LENGTH(file);}static struct file_struct *recv_file_entry(struct file_list *flist, int xflags, int f){ static int64 modtime; static mode_t mode;#ifdef SUPPORT_HARD_LINKS static int64 dev;#endif static dev_t rdev; static uint32 rdev_major; static uid_t uid; static gid_t gid; static uint16 gid_flags; static char lastname[MAXPATHLEN], *lastdir; static int lastdir_depth, lastdir_len = -1; static unsigned int del_hier_name_len = 0; static int in_del_hier = 0; char thisname[MAXPATHLEN]; unsigned int l1 = 0, l2 = 0; int alloc_len, basename_len, linkname_len; int extra_len = file_extra_cnt * EXTRA_LEN; int first_hlink_ndx = -1; int64 file_length; const char *basename; struct file_struct *file; alloc_pool_t *pool; char *bp; if (xflags & XMIT_SAME_NAME) l1 = read_byte(f); if (xflags & XMIT_LONG_NAME) l2 = read_varint30(f); else l2 = read_byte(f); if (l2 >= MAXPATHLEN - l1) { rprintf(FERROR, "overflow: xflags=0x%x l1=%d l2=%d lastname=%s [%s]\n", xflags, l1, l2, lastname, who_am_i()); overflow_exit("recv_file_entry"); } strlcpy(thisname, lastname, l1 + 1); read_sbuf(f, &thisname[l1], l2); thisname[l1 + l2] = 0; /* Abuse basename_len for a moment... */ basename_len = strlcpy(lastname, thisname, MAXPATHLEN);#ifdef ICONV_OPTION if (ic_recv != (iconv_t)-1) { xbuf outbuf, inbuf; INIT_CONST_XBUF(outbuf, thisname); INIT_XBUF(inbuf, lastname, basename_len, -1); if (iconvbufs(ic_recv, &inbuf, &outbuf, 0) < 0) { io_error |= IOERR_GENERAL; rprintf(FERROR_UTF8, "[%s] cannot convert filename: %s (%s)\n", who_am_i(), lastname, strerror(errno)); outbuf.len = 0; } thisname[outbuf.len] = '\0'; }#endif if (*thisname) clean_fname(thisname, 0); if (sanitize_paths) sanitize_path(thisname, thisname, "", 0, SP_DEFAULT); if ((basename = strrchr(thisname, '/')) != NULL) { int len = basename++ - thisname; if (len != lastdir_len || memcmp(thisname, lastdir, len) != 0) { lastdir = new_array(char, len + 1); memcpy(lastdir, thisname, len); lastdir[len] = '\0'; lastdir_len = len; lastdir_depth = count_dir_elements(lastdir); } } else basename = thisname; basename_len = strlen(basename) + 1; /* count the '\0' */#ifdef SUPPORT_HARD_LINKS if (protocol_version >= 30 && BITS_SETnUNSET(xflags, XMIT_HLINKED, XMIT_HLINK_FIRST)) { first_hlink_ndx = read_varint(f); if (first_hlink_ndx < 0 || first_hlink_ndx >= flist->ndx_start + flist->used) { rprintf(FERROR, "hard-link reference out of range: %d (%d)\n", first_hlink_ndx, flist->ndx_start + flist->used); exit_cleanup(RERR_PROTOCOL); } if (first_hlink_ndx >= flist->ndx_start) { struct file_struct *first = flist->files[first_hlink_ndx - flist->ndx_start]; file_length = F_LENGTH(first); modtime = first->modtime; mode = first->mode; if (preserve_uid) uid = F_OWNER(first); if (preserve_gid) gid = F_GROUP(first); if ((preserve_devices && IS_DEVICE(mode)) || (preserve_specials && IS_SPECIAL(mode))) { uint32 *devp = F_RDEV_P(first); rdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp)); extra_len += DEV_EXTRA_CNT * EXTRA_LEN; } if (preserve_links && S_ISLNK(mode)) linkname_len = strlen(F_SYMLINK(first)) + 1; else linkname_len = 0; goto create_object; } }#endif file_length = read_varlong30(f, 3); if (!(xflags & XMIT_SAME_TIME)) { if (protocol_version >= 30) { modtime = read_varlong(f, 4);#if SIZEOF_TIME_T < SIZEOF_INT64 if (!am_generator && (int64)(time_t)modtime != modtime) { rprintf(FERROR_XFER, "Time value of %s truncated on receiver.\n", lastname); }#endif } else modtime = read_int(f); } if (!(xflags & XMIT_SAME_MODE)) mode = from_wire_mode(read_int(f)); if (chmod_modes && !S_ISLNK(mode)) mode = tweak_mode(mode, chmod_modes); if (preserve_uid && !(xflags & XMIT_SAME_UID)) { if (protocol_version < 30) uid = (uid_t)read_int(f); else { uid = (uid_t)read_varint(f); if (xflags & 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 && !(xflags & XMIT_SAME_GID)) { if (protocol_version < 30) gid = (gid_t)read_int(f); else { gid = (gid_t)read_varint(f); gid_flags = 0; if (xflags & XMIT_GROUP_NAME_FOLLOWS) gid = recv_group_name(f, gid, &gid_flags); else if (inc_recurse && (!am_root || !numeric_ids)) gid = match_gid(gid, &gid_flags); } } if ((preserve_devices && IS_DEVICE(mode)) || (preserve_specials && IS_SPECIAL(mode))) { if (protocol_version < 28) { if (!(xflags & XMIT_SAME_RDEV_pre28)) rdev = (dev_t)read_int(f); } else { uint32 rdev_minor; if (!(xflags & XMIT_SAME_RDEV_MAJOR)) rdev_major = read_varint30(f); if (protocol_version >= 30) rdev_minor = read_varint(f); else if (xflags & XMIT_RDEV_MINOR_8_pre30) rdev_minor = read_byte(f); else rdev_minor = read_int(f); rdev = MAKEDEV(rdev_major, rdev_minor); } extra_len += DEV_EXTRA_CNT * EXTRA_LEN; file_length = 0; } else if (protocol_version < 28) rdev = MAKEDEV(0, 0);#ifdef SUPPORT_LINKS if (preserve_links && S_ISLNK(mode)) { 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); overflow_exit("recv_file_entry"); }#ifdef ICONV_OPTION /* We don't know how much extra room we need to convert * the as-yet-unread symlink data, so let's hope that a * double-size buffer is plenty. */ if (sender_symlink_iconv) linkname_len *= 2;#endif if (munge_symlinks) linkname_len += SYMLINK_PREFIX_LEN; } else#endif linkname_len = 0;#ifdef SUPPORT_HARD_LINKS create_object: if (preserve_hard_links) { if (protocol_version < 28 && S_ISREG(mode)) xflags |= XMIT_HLINKED; if (xflags & XMIT_HLINKED) extra_len += (inc_recurse+1) * EXTRA_LEN; }#endif#ifdef SUPPORT_ACLS /* Directories need an extra int32 for the default ACL. */ if (preserve_acls && S_ISDIR(mode)) extra_len += EXTRA_LEN;#endif 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) { /* Room to save the dir's device for -x */ extra_len += DEV_EXTRA_CNT * EXTRA_LEN; } pool = dir_flist->file_pool; } else pool = flist->file_pool;#if EXTRA_ROUNDING > 0 if (extra_len & (EXTRA_ROUNDING * EXTRA_LEN)) extra_len = (extra_len | (EXTRA_ROUNDING * EXTRA_LEN)) + EXTRA_LEN;#endif alloc_len = FILE_STRUCT_LEN + extra_len + basename_len + linkname_len; bp = pool_alloc(pool, alloc_len, "recv_file_entry"); memset(bp, 0, extra_len + FILE_STRUCT_LEN); bp += extra_len; file = (struct file_struct *)bp; bp += FILE_STRUCT_LEN; memcpy(bp, basename, basename_len);#ifdef SUPPORT_HARD_LINKS if (xflags & XMIT_HLINKED) file->flags |= FLAG_HLINKED;#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; if (preserve_gid) { F_GROUP(file) = gid; file->flags |= gid_flags; } if (unsort_ndx) F_NDX(file) = flist->used + flist->ndx_start; if (basename != thisname) { file->dirname = lastdir; F_DEPTH(file) = lastdir_depth + 1; } else F_DEPTH(file) = 1; if (S_ISDIR(mode)) { if (basename_len == 1+1 && *basename == '.') /* +1 for '\0' */ F_DEPTH(file)--; if (protocol_version >= 30) { if (!(xflags & XMIT_NO_CONTENT_DIR)) { if (xflags & XMIT_TOP_DIR) file->flags |= FLAG_TOP_DIR; file->flags |= FLAG_CONTENT_DIR; } else if (xflags & XMIT_TOP_DIR) file->flags |= FLAG_IMPLIED_DIR; } else if (xflags & XMIT_TOP_DIR) { in_del_hier = recurse; del_hier_name_len = F_DEPTH(file) == 0 ? 0 : l1 + l2; if (relative_paths && del_hier_name_len > 2 && lastname[del_hier_name_len-1] == '.' && lastname[del_hier_name_len-2] == '/') del_hier_name_len -= 2; file->flags |= FLAG_TOP_DIR | FLAG_CONTENT_DIR; } else if (in_del_hier) { if (!relative_paths || !del_hier_name_len || (l1 >= del_hier_name_len && lastname[del_hier_name_len] == '/')) file->flags |= FLAG_CONTENT_DIR; else in_del_hier = 0; } } if ((preserve_devices && IS_DEVICE(mode)) || (preserve_specials && IS_SPECIAL(mode))) { uint32 *devp = F_RDEV_P(file); DEV_MAJOR(devp) = major(rdev); DEV_MINOR(devp) = minor(rdev); }#ifdef SUPPORT_LINKS if (linkname_len) { bp += basename_len; if (first_hlink_ndx >= flist->ndx_start) { struct file_struct *first = flist->files[first_hlink_ndx - flist->ndx_start]; memcpy(bp, F_SYMLINK(first), linkname_len); } else { if (munge_symlinks) { strlcpy(bp, SYMLINK_PREFIX, linkname_len); bp += SYMLINK_PREFIX_LEN; linkname_len -= SYMLINK_PREFIX_LEN; }#ifdef ICONV_OPTION if (sender_symlink_iconv) { xbuf outbuf, inbuf; alloc_len = linkname_len; linkname_len /= 2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -