+ extra_len += sizeof (union flist_extras);
+ assert(flist->hlink_pool != NULL);
+ }
+#endif
+
+ sum_len = always_checksum && S_ISREG(mode) ? MD4_SUM_LENGTH : 0;
+
+ alloc_len = file_struct_len + dirname_len + basename_len
+ + linkname_len + sum_len + extra_len;
+ bp = pool_alloc(flist->file_pool, alloc_len, "recv_file_entry");
+
+ memset(bp, 0, file_struct_len + extra_len);
+ bp += extra_len;
+ file = (struct file_struct *)bp;
+ bp += file_struct_len + linkname_len + sum_len;
+
+#ifdef SUPPORT_HARD_LINKS
+ if (flags & XMIT_HAS_IDEV_DATA)
+ file->flags |= FLAG_HLINK_INFO;
+#endif
+ file->modtime = modtime;
+ file->length = file_length;
+ file->mode = mode;
+ if (preserve_uid)
+ F_UID(file) = uid;
+ if (preserve_gid)
+ F_GID(file) = gid;
+
+ if (dirname_len) {
+ file->dirname = lastdir = bp;
+ lastdir_len = dirname_len - 1;
+ memcpy(bp, dirname, dirname_len - 1);
+ bp += dirname_len;
+ bp[-1] = '\0';
+ lastdir_depth = count_dir_elements(lastdir);
+ file->dir.depth = lastdir_depth + 1;
+ } else if (dirname) {
+ file->dirname = dirname; /* we're reusing lastname */
+ file->dir.depth = lastdir_depth + 1;
+ } else
+ file->dir.depth = 1;
+
+ if (S_ISDIR(mode)) {
+ if (basename_len == 1+1 && *basename == '.') /* +1 for '\0' */
+ file->dir.depth--;
+ if (flags & XMIT_TOP_DIR) {
+ in_del_hier = recurse;
+ del_hier_name_len = file->dir.depth == 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_XFER_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_XFER_DIR;
+ else
+ in_del_hier = 0;
+ }
+ }
+
+ file->basename = bp;
+ memcpy(bp, basename, basename_len);
+ bp += basename_len;
+
+ if ((preserve_devices && IS_DEVICE(mode))
+ || (preserve_specials && IS_SPECIAL(mode))) {
+ F_DMAJOR(file) = major(rdev);
+ F_DMINOR(file) = minor(rdev);
+ }
+
+#ifdef SUPPORT_LINKS
+ if (linkname_len) {
+ bp = F_SYMLINK(file);
+ read_sbuf(f, bp, linkname_len - 1);
+ if (sanitize_paths)
+ sanitize_path(bp, bp, "", lastdir_depth, NULL);
+ }
+#endif
+
+#ifdef SUPPORT_HARD_LINKS
+ if (flags & XMIT_HAS_IDEV_DATA) {
+ struct idev *idevp = pool_talloc(flist->hlink_pool, struct idev,
+ 1, "inode_table");
+ F_IDEV(file) = idevp;