+ strlcpy(thisname, lastname, l1 + 1);
+ read_sbuf(f, &thisname[l1], l2);
+ thisname[l1 + l2] = 0;
+
+ strlcpy(lastname, thisname, MAXPATHLEN);
+ lastname[MAXPATHLEN - 1] = 0;
+
+ clean_fname(thisname);
+
+ if (sanitize_paths) {
+ sanitize_path(thisname, NULL);
+ }
+
+ if ((p = strrchr(thisname, '/'))) {
+ static char *lastdir;
+ *p = 0;
+ if (lastdir && strcmp(thisname, lastdir) == 0)
+ file->dirname = lastdir;
+ else {
+ file->dirname = strdup(thisname);
+ lastdir = file->dirname;
+ }
+ file->basename = strdup(p + 1);
+ } else {
+ file->dirname = NULL;
+ file->basename = strdup(thisname);
+ }
+
+ if (!file->basename)
+ out_of_memory("receive_file_entry 1");
+
+ file->flags = flags & XMIT_TOP_DIR ? FLAG_TOP_DIR : 0;
+ file->length = read_longint(f);
+ if (!(flags & XMIT_SAME_TIME))
+ modtime = (time_t)read_int(f);
+ file->modtime = modtime;
+ if (!(flags & XMIT_SAME_MODE))
+ mode = from_wire_mode(read_int(f));
+ file->mode = mode;
+
+ if (preserve_uid) {
+ if (!(flags & XMIT_SAME_UID))
+ uid = (uid_t)read_int(f);
+ file->uid = uid;
+ }
+ if (preserve_gid) {
+ if (!(flags & XMIT_SAME_GID))
+ gid = (gid_t)read_int(f);
+ file->gid = gid;
+ }
+ if (preserve_devices) {
+ if (protocol_version < 28) {
+ if (IS_DEVICE(mode)) {
+ if (!(flags & XMIT_SAME_RDEV_pre28))
+ rdev = (DEV64_T)read_int(f);
+ file->u.rdev = rdev;
+ } else
+ rdev = 0;
+ } else if (IS_DEVICE(mode)) {
+ if (!(flags & XMIT_SAME_HIGH_RDEV)) {
+ rdev = (DEV64_T)read_int(f);
+ rdev_high = rdev & ~0xFF;
+ } else
+ rdev = rdev_high | (DEV64_T)read_byte(f);
+ file->u.rdev = rdev;
+ }
+ }
+
+ if (preserve_links && S_ISLNK(mode)) {
+ int len = read_int(f);
+ if (len < 0 || len >= MAXPATHLEN) {
+ rprintf(FERROR, "overflow: len=%d\n", len);
+ overflow("receive_file_entry");
+ }
+ if (!(file->u.link = new_array(char, len + 1)))
+ out_of_memory("receive_file_entry 2");
+ read_sbuf(f, file->u.link, len);
+ if (sanitize_paths)
+ sanitize_path(file->u.link, file->dirname);
+ }
+#if SUPPORT_HARD_LINKS
+ if (preserve_hard_links && protocol_version < 28 && S_ISREG(mode))
+ flags |= XMIT_HAS_IDEV_DATA;
+ if (flags & XMIT_HAS_IDEV_DATA) {
+ if (!(file->link_u.idev = new(struct idev)))
+ out_of_memory("file inode data");
+ if (protocol_version < 26) {
+ dev = read_int(f);
+ file->F_INODE = read_int(f);
+ } else {
+ if (!(flags & XMIT_SAME_DEV))
+ dev = read_longint(f);
+ file->F_INODE = read_longint(f);
+ }
+ file->F_DEV = dev;
+ }
+#endif
+
+ if (always_checksum) {
+ char *sum;
+ if (S_ISREG(mode)) {
+ sum = file->u.sum = new_array(char, MD4_SUM_LENGTH);
+ if (!sum)
+ out_of_memory("md4 sum");
+ } else if (protocol_version < 28) {
+ /* Prior to 28, we get a useless set of nulls. */
+ sum = empty_sum;
+ } else
+ sum = NULL;
+ if (sum) {
+ read_buf(f, sum, protocol_version < 21? 2
+ : MD4_SUM_LENGTH);
+ }
+ }
+
+ if (!preserve_perms) {
+ extern int orig_umask;
+ /* set an appropriate set of permissions based on original
+ * permissions and umask. This emulates what GNU cp does */
+ file->mode &= ~orig_umask;