Made my last change a little better.
[rsync/rsync.git] / flist.c
diff --git a/flist.c b/flist.c
index a6f38f9..cd5aa14 100644 (file)
--- a/flist.c
+++ b/flist.c
@@ -1,18 +1,18 @@
-/* 
+/*
    Copyright (C) Andrew Tridgell 1996
    Copyright (C) Paul Mackerras 1996
    Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
-   
+
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
@@ -41,6 +41,8 @@ extern int always_checksum;
 extern int cvs_exclude;
 
 extern int recurse;
+extern char *files_from;
+extern int filesfrom_fd;
 
 extern int one_file_system;
 extern int make_backups;
@@ -52,6 +54,7 @@ extern int preserve_uid;
 extern int preserve_gid;
 extern int preserve_times;
 extern int relative_paths;
+extern int implied_dirs;
 extern int copy_links;
 extern int copy_unsafe_links;
 extern int remote_version;
@@ -70,7 +73,7 @@ static void clean_flist(struct file_list *flist, int strip_root, int no_dups);
 
 static int show_filelist_p(void)
 {
-       return verbose && recurse && !am_server;
+       return verbose && (recurse || files_from) && !am_server;
 }
 
 static void start_filelist_progress(char *kind)
@@ -216,12 +219,12 @@ int readlink_stat(const char *path, STRUCT_STAT * buffer, char *linkbuf)
        if (S_ISLNK(buffer->st_mode)) {
                int l;
                l = readlink((char *) path, linkbuf, MAXPATHLEN - 1);
-               if (l == -1) 
+               if (l == -1)
                        return -1;
                linkbuf[l] = 0;
                if (copy_unsafe_links && unsafe_symlink(linkbuf, path)) {
                        if (verbose > 1) {
-                               rprintf(FINFO,"copying unsafe symlink \"%s\" -> \"%s\"\n", 
+                               rprintf(FINFO,"copying unsafe symlink \"%s\" -> \"%s\"\n",
                                        path, linkbuf);
                        }
                        return do_stat(path, buffer);
@@ -307,14 +310,14 @@ static void flist_expand(struct file_list *flist)
        if (flist->count >= flist->malloced) {
                size_t new_bytes;
                void *new_ptr;
-               
+
                if (flist->malloced < 1000)
                        flist->malloced += 1000;
                else
                        flist->malloced *= 2;
 
                new_bytes = sizeof(flist->files[0]) * flist->malloced;
-               
+
                if (flist->files)
                        new_ptr = realloc(flist->files, new_bytes);
                else
@@ -325,7 +328,7 @@ static void flist_expand(struct file_list *flist)
                                (double) new_bytes,
                                (new_ptr == flist->files) ? " not" : "");
                }
-               
+
                flist->files = (struct file_struct **) new_ptr;
 
                if (!flist->files)
@@ -374,7 +377,7 @@ static void send_file_entry(struct file_struct *file, int f,
 
        for (l1 = 0;
             lastname[l1] && (fname[l1] == lastname[l1]) && (l1 < 255);
-            l1++);
+            l1++) {}
        l2 = strlen(fname) - l1;
 
        if (l1 > 0)
@@ -662,7 +665,7 @@ struct file_struct *make_file(int f, char *fname, struct string_area **ap,
        if (readlink_stat(fname, &st, linkbuf) != 0) {
                int save_errno = errno;
                if ((errno == ENOENT) && !noexcludes) {
-                       /* either symlink pointing nowhere or file that 
+                       /* either symlink pointing nowhere or file that
                         * was removed during rsync run; see if excluded
                         * before reporting an error */
                        memset((char *) &st, 0, sizeof(st));
@@ -681,7 +684,7 @@ struct file_struct *make_file(int f, char *fname, struct string_area **ap,
        if (noexcludes)
                goto skip_excludes;
 
-       if (S_ISDIR(st.st_mode) && !recurse) {
+       if (S_ISDIR(st.st_mode) && !recurse && !files_from) {
                rprintf(FINFO, "skipping directory %s\n", fname);
                return NULL;
        }
@@ -877,12 +880,13 @@ static void send_directory(int f, struct file_list *flist, char *dir)
  **/
 struct file_list *send_file_list(int f, int argc, char *argv[])
 {
-       int i, l;
+       int l;
        STRUCT_STAT st;
        char *p, *dir, *olddir;
        char lastpath[MAXPATHLEN] = "";
        struct file_list *flist;
        int64 start_write;
+       int use_ff_fd = 0;
 
        if (show_filelist_p() && f != -1)
                start_filelist_progress("building file list");
@@ -893,13 +897,31 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
 
        if (f != -1) {
                io_start_buffering(f);
+               if (filesfrom_fd >= 0) {
+                       if (argv[0] && !push_dir(argv[0], 0)) {
+                               rprintf(FERROR, "push_dir %s : %s\n",
+                                       argv[0], strerror(errno));
+                               exit_cleanup(RERR_FILESELECT);
+                       }
+                       use_ff_fd = 1;
+               }
        }
 
-       for (i = 0; i < argc; i++) {
+       while (1) {
                char fname2[MAXPATHLEN];
                char *fname = fname2;
 
-               strlcpy(fname, argv[i], MAXPATHLEN);
+               if (use_ff_fd) {
+                       if (read_filesfrom_line(filesfrom_fd, fname) == 0)
+                               break;
+                       sanitize_path(fname, NULL);
+               } else {
+                       if (argc-- == 0)
+                               break;
+                       strlcpy(fname, *argv++, MAXPATHLEN);
+                       if (sanitize_paths)
+                               sanitize_path(fname, NULL);
+               }
 
                l = strlen(fname);
                if (l != 1 && fname[l - 1] == '/') {
@@ -924,7 +946,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
                        continue;
                }
 
-               if (S_ISDIR(st.st_mode) && !recurse) {
+               if (S_ISDIR(st.st_mode) && !recurse && !files_from) {
                        rprintf(FINFO, "skipping directory %s\n", fname);
                        continue;
                }
@@ -942,7 +964,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
                                        dir = fname;
                                fname = p + 1;
                        }
-               } else if (f != -1 && (p=strrchr(fname,'/')) && p != fname) {
+               } else if (f != -1 && implied_dirs && (p=strrchr(fname,'/')) && p != fname) {
                        /* this ensures we send the intermediate directories,
                           thus getting their permissions right */
                        char *lp = lastpath, *fn = fname, *slash = fname;
@@ -1020,12 +1042,12 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
 
        /* now send the uid/gid list. This was introduced in protocol
           version 15 */
-       if (f != -1 && remote_version >= 15) {
+       if (f != -1) {
                send_uid_list(f);
        }
 
-       /* if protocol version is >= 17 then send the io_error flag */
-       if (f != -1 && remote_version >= 17) {
+       /* send the io_error flag */
+       if (f != -1) {
                extern int module_id;
                write_int(f, lp_ignore_errors(module_id) ? 0 : io_error);
        }
@@ -1072,7 +1094,7 @@ struct file_list *recv_file_list(int f)
 
        for (flags = read_byte(f); flags; flags = read_byte(f)) {
                int i = flist->count;
-               
+
                flist_expand(flist);
 
                receive_file_entry(&flist->files[i], flags, f);
@@ -1100,12 +1122,12 @@ struct file_list *recv_file_list(int f)
        }
 
        /* now recv the uid/gid list. This was introduced in protocol version 15 */
-       if (f != -1 && remote_version >= 15) {
+       if (f != -1) {
                recv_uid_list(f, flist);
        }
 
-       /* if protocol version is >= 17 then recv the io_error flag */
-       if (f != -1 && remote_version >= 17 && !read_batch) {   /* dw-added readbatch */
+       /* recv the io_error flag */
+       if (f != -1 && !read_batch) {   /* dw-added readbatch */
                extern int module_id;
                extern int ignore_errors;
                if (lp_ignore_errors(module_id) || ignore_errors) {
@@ -1250,7 +1272,7 @@ void flist_free(struct file_list *flist)
 
 /*
  * This routine ensures we don't have any duplicate names in our file list.
- * duplicate names can cause corruption because of the pipelining 
+ * duplicate names can cause corruption because of the pipelining
  */
 static void clean_flist(struct file_list *flist, int strip_root, int no_dups)
 {