+/* The receiving side operates in one of two modes:
+ *
+ * 1. it receives any number of files into a destination directory,
+ * placing them according to their names in the file-list.
+ *
+ * 2. it receives a single file and saves it using the name in the
+ * destination path instead of its file-list name. This requires a
+ * "local name" for writing out the destination file.
+ *
+ * So, our task is to figure out what mode/local-name we need.
+ * For mode 1, we change into the destination directory and return NULL.
+ * For mode 2, we change into the directory containing the destination
+ * file (if we aren't already there) and return the local-name. */
+static char *get_local_name(struct file_list *flist, char *dest_path)
+{
+ STRUCT_STAT st;
+ int statret;
+ char *cp;
+
+ if (verbose > 2) {
+ rprintf(FINFO, "get_local_name count=%d %s\n",
+ file_total, NS(dest_path));
+ }
+
+ if (!dest_path || list_only)
+ return NULL;
+
+ if (daemon_filter_list.head
+ && (check_filter(&daemon_filter_list, FLOG, dest_path, 0 != 0) < 0
+ || check_filter(&daemon_filter_list, FLOG, dest_path, 1 != 0) < 0)) {
+ rprintf(FERROR, "skipping daemon-excluded destination \"%s\"\n",
+ dest_path);
+ exit_cleanup(RERR_FILESELECT);
+ }
+
+ /* See what currently exists at the destination. */
+ if ((statret = do_stat(dest_path, &st)) == 0) {
+ /* If the destination is a dir, enter it and use mode 1. */
+ if (S_ISDIR(st.st_mode)) {
+ if (!push_dir(dest_path, 0)) {
+ rsyserr(FERROR, errno, "push_dir#1 %s failed",
+ full_fname(dest_path));
+ exit_cleanup(RERR_FILESELECT);
+ }
+ return NULL;
+ }
+ if (file_total > 1) {
+ rprintf(FERROR,
+ "ERROR: destination must be a directory when"
+ " copying more than 1 file\n");
+ exit_cleanup(RERR_FILESELECT);
+ }
+ if (file_total == 1 && S_ISDIR(flist->files[0]->mode)) {
+ rprintf(FERROR,
+ "ERROR: cannot overwrite non-directory"
+ " with a directory\n");
+ exit_cleanup(RERR_FILESELECT);
+ }
+ } else if (errno != ENOENT) {
+ /* If we don't know what's at the destination, fail. */
+ rsyserr(FERROR, errno, "ERROR: cannot stat destination %s",
+ full_fname(dest_path));
+ exit_cleanup(RERR_FILESELECT);
+ }
+
+ cp = strrchr(dest_path, '/');
+
+ /* If we need a destination directory because the transfer is not
+ * of a single non-directory or the user has requested one via a
+ * destination path ending in a slash, create one and use mode 1. */
+ if (file_total > 1 || (cp && !cp[1])) {
+ /* Lop off the final slash (if any). */
+ if (cp && !cp[1])
+ *cp = '\0';
+
+ if (statret == 0) {
+ rprintf(FERROR,
+ "ERROR: destination path is not a directory\n");
+ exit_cleanup(RERR_SYNTAX);
+ }
+
+ if (mkdir_defmode(dest_path) != 0) {
+ rsyserr(FERROR, errno, "mkdir %s failed",
+ full_fname(dest_path));
+ exit_cleanup(RERR_FILEIO);
+ }
+
+ if (flist->high >= flist->low
+ && strcmp(flist->files[flist->low]->basename, ".") == 0)
+ flist->files[0]->flags |= FLAG_DIR_CREATED;
+
+ if (verbose)
+ rprintf(FINFO, "created directory %s\n", dest_path);