Added a way for supplementary groups to be specified in the rsyncd.conf
[rsync/rsync.git] / flist.c
diff --git a/flist.c b/flist.c
index 2e449c0..2fdff34 100644 (file)
--- a/flist.c
+++ b/flist.c
@@ -1385,6 +1385,14 @@ static struct file_struct *send_file_name(int f, struct file_list *flist,
                if (preserve_links && S_ISLNK(file->mode)) {
                        symlink_name = F_SYMLINK(file);
                        symlink_len = strlen(symlink_name);
+                       if (symlink_len == 0) {
+                               io_error |= IOERR_GENERAL;
+                               f_name(file, fbuf);
+                               rprintf(FERROR_XFER,
+                                   "skipping symlink with 0-length value: %s\n",
+                                   full_fname(fbuf));
+                               return NULL;
+                       }
                } else {
                        symlink_name = NULL;
                        symlink_len = 0;
@@ -1619,6 +1627,19 @@ static void add_dirs_to_tree(int parent_ndx, struct file_list *from_flist,
                DIR_NEXT_SIBLING(dp) = -1;
 }
 
+static void interpret_stat_error(const char *fname, int is_dir)
+{
+       if (errno == ENOENT) {
+               io_error |= IOERR_VANISHED;
+               rprintf(FWARNING, "%s has vanished: %s\n",
+                       is_dir ? "directory" : "file", full_fname(fname));
+       } else {
+               io_error |= IOERR_GENERAL;
+               rsyserr(FERROR_XFER, errno, "link_stat %s failed",
+                       full_fname(fname));
+       }
+}
+
 /* This function is normally called by the sender, but the receiving side also
  * calls it from get_dirlist() with f set to -1 so that we just construct the
  * file list in memory without sending it over the wire.  Also, get_dirlist()
@@ -1638,8 +1659,11 @@ static void send_directory(int f, struct file_list *flist, char *fbuf, int len,
        assert(flist != NULL);
 
        if (!(d = opendir(fbuf))) {
-               if (errno == ENOENT)
+               if (errno == ENOENT) {
+                       if (am_sender) /* Can abuse this for vanished error w/ENOENT: */
+                               interpret_stat_error(fbuf, True);
                        return;
+               }
                io_error |= IOERR_GENERAL;
                rsyserr(FERROR_XFER, errno, "opendir %s failed", full_fname(fbuf));
                return;
@@ -1811,9 +1835,7 @@ static void send1extra(int f, struct file_struct *file, struct file_list *flist)
                if (one_file_system) {
                        STRUCT_STAT st;
                        if (link_stat(fbuf, &st, copy_dirlinks) != 0) {
-                               io_error |= IOERR_GENERAL;
-                               rsyserr(FERROR_XFER, errno, "link_stat %s failed",
-                                       full_fname(fbuf));
+                               interpret_stat_error(fbuf, True);
                                return;
                        }
                        filesystem_dev = st.st_dev;
@@ -1848,9 +1870,7 @@ static void send1extra(int f, struct file_struct *file, struct file_list *flist)
                if (name_type != NORMAL_NAME) {
                        STRUCT_STAT st;
                        if (link_stat(fbuf, &st, 1) != 0) {
-                               io_error |= IOERR_GENERAL;
-                               rsyserr(FERROR_XFER, errno, "link_stat %s failed",
-                                       full_fname(fbuf));
+                               interpret_stat_error(fbuf, True);
                                continue;
                        }
                        send_file_name(f, flist, fbuf, &st, FLAG_TOP_DIR | flags, ALL_FILTERS);
@@ -1915,7 +1935,7 @@ void send_extra_file_list(int f, int at_least)
                        write_byte(f, 0);
                else {
                        write_shortint(f, XMIT_EXTENDED_FLAGS|XMIT_IO_ERROR_ENDLIST);
-                       write_int(f, io_error);
+                       write_varint(f, io_error);
                }
 
                if (need_unsorted_flist) {
@@ -2218,7 +2238,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
                write_byte(f, 0);
        else {
                write_shortint(f, XMIT_EXTENDED_FLAGS|XMIT_IO_ERROR_ENDLIST);
-               write_int(f, io_error);
+               write_varint(f, io_error);
        }
 
 #ifdef SUPPORT_HARD_LINKS
@@ -2254,6 +2274,8 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
        if (numeric_ids <= 0 && !inc_recurse)
                send_id_list(f);
 
+       set_msg_fd_in(-1);
+
        /* send the io_error flag */
        if (protocol_version < 30)
                write_int(f, ignore_errors ? 0 : io_error);
@@ -2341,7 +2363,7 @@ struct file_list *recv_file_list(int f)
                                rprintf(FERROR, "Invalid flist flag: %x\n", flags);
                                exit_cleanup(RERR_PROTOCOL);
                        }
-                       err = read_int(f);
+                       err = read_varint(f);
                        if (!ignore_errors)
                                io_error |= err;
                        break;