Tweaked some whitespace to match the latest version from autoconf.
[rsync/rsync.git] / main.c
diff --git a/main.c b/main.c
index 9d8723b..3acdfd3 100644 (file)
--- a/main.c
+++ b/main.c
@@ -40,8 +40,8 @@ extern int kluge_around_eof;
 extern int do_stats;
 extern int log_got_error;
 extern int module_id;
-extern int orig_umask;
 extern int copy_links;
+extern int copy_dirlinks;
 extern int keep_dirlinks;
 extern int preserve_hard_links;
 extern int protocol_version;
@@ -62,6 +62,7 @@ extern char *shell_cmd;
 extern char *batch_name;
 
 int local_server = 0;
+mode_t orig_umask = 0;
 struct file_list *the_file_list;
 
 /* There's probably never more than at most 2 outstanding child processes,
@@ -437,8 +438,8 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char *path,
 
 /* The receiving side operates in one of two modes:
  *
- * 1. it enters a directory and receives one or more files, placing them
- * according to their names in the file-list.
+ * 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
@@ -479,6 +480,17 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
                                " copying more than 1 file\n");
                        exit_cleanup(RERR_FILESELECT);
                }
+               /* Caution: flist->count could be 0! */
+               if (flist->count == 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) {
+               rsyserr(FERROR, errno, "cannot stat destination %s",
+                       full_fname(dest_path));
+               exit_cleanup(RERR_FILESELECT);
        }
 
        cp = strrchr(dest_path, '/');
@@ -491,13 +503,11 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
                if (cp && !cp[1])
                        *cp = '\0';
 
-               umask(orig_umask);
-               if (do_mkdir(dest_path, 0777) != 0) {
+               if (mkdir_defmode(dest_path) != 0) {
                        rsyserr(FERROR, errno, "mkdir %s failed",
                                full_fname(dest_path));
                        exit_cleanup(RERR_FILEIO);
                }
-               umask(0);
 
                if (verbose)
                        rprintf(FINFO, "created directory %s\n", dest_path);
@@ -627,7 +637,7 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
 
        /* The receiving side mustn't obey this, or an existing symlink that
         * points to an identical file won't be replaced by the referent. */
-       copy_links = 0;
+       copy_links = copy_dirlinks = 0;
 
        if (preserve_hard_links)
                init_hard_links();
@@ -1208,7 +1218,7 @@ int main(int argc,char *argv[])
 
        /* we set a 0 umask so that correct file permissions can be
         * carried across */
-       orig_umask = (int)umask(0);
+       orig_umask = umask(0);
 
 #if defined CONFIG_LOCALE && defined HAVE_SETLOCALE
        setlocale(LC_CTYPE, "");