+ if (!(flist = flist_for_ndx(ndx))) {
+ invalid_ndx:
+ rprintf(FERROR,
+ "Invalid file index: %d (%d - %d) with iflags %x [%s]\n",
+ ndx, first_flist->ndx_start - 1, first_flist->prev->ndx_end,
+ iflags, who_am_i());
+ exit_cleanup(RERR_PROTOCOL);
+ }
+ cur_flist = flist;
+
+ if (iflags & ITEM_BASIS_TYPE_FOLLOWS)
+ fnamecmp_type = read_byte(f_in);
+ *type_ptr = fnamecmp_type;
+
+ if (iflags & ITEM_XNAME_FOLLOWS) {
+ if ((len = read_vstring(f_in, buf, MAXPATHLEN)) < 0)
+ exit_cleanup(RERR_PROTOCOL);
+ } else {
+ *buf = '\0';
+ len = -1;
+ }
+ *len_ptr = len;
+
+ if (iflags & ITEM_TRANSFER) {
+ int i = ndx - cur_flist->ndx_start;
+ if (i < 0 || !S_ISREG(cur_flist->files[i]->mode)) {
+ rprintf(FERROR,
+ "received request to transfer non-regular file: %d [%s]\n",
+ ndx, who_am_i());
+ exit_cleanup(RERR_PROTOCOL);
+ }
+ }
+
+ *iflag_ptr = iflags;
+ return ndx;
+}
+
+/*
+ free a sums struct
+ */
+void free_sums(struct sum_struct *s)
+{
+ if (s->sums) free(s->sums);
+ free(s);
+}
+
+/* This is only called when we aren't preserving permissions. Figure out what
+ * the permissions should be and return them merged back into the mode. */
+mode_t dest_mode(mode_t flist_mode, mode_t stat_mode, int dflt_perms,
+ int exists)
+{
+ int new_mode;
+ /* If the file already exists, we'll return the local permissions,
+ * possibly tweaked by the --executability option. */
+ if (exists) {
+ new_mode = (flist_mode & ~CHMOD_BITS) | (stat_mode & CHMOD_BITS);
+ if (preserve_executability && S_ISREG(flist_mode)) {
+ /* If the source file is executable, grant execute
+ * rights to everyone who can read, but ONLY if the
+ * file isn't already executable. */
+ if (!(flist_mode & 0111))
+ new_mode &= ~0111;
+ else if (!(stat_mode & 0111))
+ new_mode |= (new_mode & 0444) >> 2;
+ }
+ } else {
+ /* Apply destination default permissions and turn
+ * off special permissions. */
+ new_mode = flist_mode & (~CHMOD_BITS | dflt_perms);
+ }
+ return new_mode;