+static int flist_dir_len;
+
+
+/**
+ * Make sure @p flist is big enough to hold at least @p flist->count
+ * entries.
+ **/
+void flist_expand(struct file_list *flist)
+{
+ struct file_struct **new_ptr;
+
+ if (flist->count < flist->malloced)
+ return;
+
+ if (flist->malloced < FLIST_START)
+ flist->malloced = FLIST_START;
+ else if (flist->malloced >= FLIST_LINEAR)
+ flist->malloced += FLIST_LINEAR;
+ else
+ flist->malloced *= 2;
+
+ /*
+ * In case count jumped or we are starting the list
+ * with a known size just set it.
+ */
+ if (flist->malloced < flist->count)
+ flist->malloced = flist->count;
+
+ new_ptr = realloc_array(flist->files, struct file_struct *,
+ flist->malloced);
+
+ if (verbose >= 2 && flist->malloced != FLIST_START) {
+ rprintf(FINFO, "[%s] expand file_list to %.0f bytes, did%s move\n",
+ who_am_i(),
+ (double)sizeof flist->files[0] * flist->malloced,
+ (new_ptr == flist->files) ? " not" : "");
+ }
+
+ flist->files = new_ptr;
+
+ if (!flist->files)
+ out_of_memory("flist_expand");
+}
+
+void send_file_entry(struct file_struct *file, int f, unsigned short base_flags)
+{
+ unsigned short flags;
+ static time_t modtime;
+ static mode_t mode;
+ static int64 dev;
+ static dev_t rdev;
+ static uint32 rdev_major;
+ static uid_t uid;
+ static gid_t gid;
+ static char lastname[MAXPATHLEN];
+ char fname[MAXPATHLEN];
+ int l1, l2;
+
+ if (f < 0)
+ return;
+
+ if (!file) {
+ write_byte(f, 0);
+ modtime = 0, mode = 0;
+ dev = 0, rdev = makedev(0, 0);
+ rdev_major = 0;
+ uid = 0, gid = 0;
+ *lastname = '\0';
+ return;
+ }
+
+ io_write_phase = "send_file_entry";
+
+ f_name_to(file, fname);
+
+ flags = base_flags;
+
+ if (file->mode == mode)
+ flags |= XMIT_SAME_MODE;
+ else
+ mode = file->mode;
+ if (preserve_devices) {
+ if (protocol_version < 28) {
+ if (IS_DEVICE(mode)) {
+ if (file->u.rdev == rdev)
+ flags |= XMIT_SAME_RDEV_pre28;
+ else
+ rdev = file->u.rdev;
+ } else
+ rdev = makedev(0, 0);
+ } else if (IS_DEVICE(mode)) {
+ rdev = file->u.rdev;
+ if ((uint32)major(rdev) == rdev_major)
+ flags |= XMIT_SAME_RDEV_MAJOR;
+ else
+ rdev_major = major(rdev);
+ if ((uint32)minor(rdev) <= 0xFFu)
+ flags |= XMIT_RDEV_MINOR_IS_SMALL;
+ }
+ }
+ if (file->uid == uid)
+ flags |= XMIT_SAME_UID;
+ else
+ uid = file->uid;
+ if (file->gid == gid)
+ flags |= XMIT_SAME_GID;
+ else
+ gid = file->gid;
+ if (file->modtime == modtime)
+ flags |= XMIT_SAME_TIME;
+ else
+ modtime = file->modtime;
+
+#ifdef SUPPORT_HARD_LINKS
+ if (file->link_u.idev) {
+ if (file->F_DEV == dev) {
+ if (protocol_version >= 28)
+ flags |= XMIT_SAME_DEV;
+ } else
+ dev = file->F_DEV;
+ flags |= XMIT_HAS_IDEV_DATA;
+ }
+#endif
+
+ for (l1 = 0;
+ lastname[l1] && (fname[l1] == lastname[l1]) && (l1 < 255);
+ l1++) {}
+ l2 = strlen(fname+l1);
+
+ if (l1 > 0)
+ flags |= XMIT_SAME_NAME;
+ if (l2 > 255)
+ flags |= 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_byte(f, flags);
+ write_byte(f, flags >> 8);
+ } else
+ write_byte(f, flags);
+ } else {
+ if (!(flags & 0xFF) && !S_ISDIR(mode))
+ flags |= XMIT_TOP_DIR;
+ if (!(flags & 0xFF))
+ flags |= XMIT_LONG_NAME;
+ write_byte(f, flags);
+ }
+ if (flags & XMIT_SAME_NAME)
+ write_byte(f, l1);
+ if (flags & XMIT_LONG_NAME)
+ write_int(f, l2);
+ else
+ write_byte(f, l2);
+ write_buf(f, fname + l1, l2);
+
+ write_longint(f, file->length);
+ if (!(flags & XMIT_SAME_TIME))
+ write_int(f, modtime);
+ if (!(flags & XMIT_SAME_MODE))
+ write_int(f, to_wire_mode(mode));
+ if (preserve_uid && !(flags & XMIT_SAME_UID)) {
+ if (!numeric_ids)
+ add_uid(uid);
+ write_int(f, uid);
+ }
+ if (preserve_gid && !(flags & XMIT_SAME_GID)) {
+ if (!numeric_ids)
+ add_gid(gid);
+ write_int(f, gid);
+ }
+ if (preserve_devices && IS_DEVICE(mode)) {
+ if (protocol_version < 28) {
+ if (!(flags & XMIT_SAME_RDEV_pre28))
+ write_int(f, (int)rdev);
+ } else {
+ if (!(flags & XMIT_SAME_RDEV_MAJOR))
+ write_int(f, major(rdev));
+ if (flags & XMIT_RDEV_MINOR_IS_SMALL)
+ write_byte(f, minor(rdev));
+ else
+ write_int(f, minor(rdev));
+ }
+ }