Change clean_fname() to keep "//" at the start for cygwin.
[rsync/rsync.git] / flist.c
diff --git a/flist.c b/flist.c
index 2f08850..d105422 100644 (file)
--- a/flist.c
+++ b/flist.c
@@ -678,7 +678,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
 
                if (iconvbufs(ic_recv, &inbuf, &outbuf, 0) < 0) {
                        io_error |= IOERR_GENERAL;
-                       rprintf(FERROR_XFER,
+                       rprintf(FERROR_UTF8,
                            "[%s] cannot convert filename: %s (%s)\n",
                            who_am_i(), lastname, strerror(errno));
                        outbuf.len = 0;
@@ -816,10 +816,10 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
                }
 #ifdef ICONV_OPTION
                /* We don't know how much extra room we need to convert
-                * the as-yet-unread symlink name when converting it,
-                * so let's hope that a double-size buffer is plenty. */
+                * the as-yet-unread symlink data, so let's hope that a
+                * double-size buffer is plenty. */
                if (sender_symlink_iconv)
-                       linkname_len = linkname_len * 2 + 1;
+                       linkname_len *= 2;
 #endif
                if (munge_symlinks)
                        linkname_len += SYMLINK_PREFIX_LEN;
@@ -966,9 +966,9 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
                                xbuf outbuf, inbuf;
 
                                alloc_len = linkname_len;
-                               linkname_len /= 2; /* (linkname_len-1) / 2 for odd values. */
+                               linkname_len /= 2;
 
-                               /* Read the symlink name into the end of our double-sized
+                               /* Read the symlink data into the end of our double-sized
                                 * buffer and then convert it into the right spot. */
                                INIT_XBUF(inbuf, bp + alloc_len - linkname_len,
                                          linkname_len - 1, (size_t)-1);
@@ -978,7 +978,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
                                if (iconvbufs(ic_recv, &inbuf, &outbuf, 0) < 0) {
                                        io_error |= IOERR_GENERAL;
                                        rprintf(FERROR_XFER,
-                                           "[%s] cannot convert symlink name for: %s (%s)\n",
+                                           "[%s] cannot convert symlink data for: %s (%s)\n",
                                            who_am_i(), full_fname(thisname), strerror(errno));
                                        bp = (char*)file->basename;
                                        *bp++ = '\0';
@@ -1126,7 +1126,7 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
                        }
                } else {
                        io_error |= IOERR_GENERAL;
-                       rsyserr(FERROR_XFER, save_errno, "readlink %s failed",
+                       rsyserr(FERROR_XFER, save_errno, "readlink_stat(%s) failed",
                                full_fname(thisname));
                }
                return NULL;
@@ -1294,25 +1294,6 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
        else if (!pool)
                F_DEPTH(file) = extra_len / EXTRA_LEN;
 
-       /* This code is only used by the receiver when it is building
-        * a list of files for a delete pass. */
-       if (keep_dirlinks && linkname_len && flist) {
-               STRUCT_STAT st2;
-               int save_mode = file->mode;
-               file->mode = S_IFDIR; /* Find a directory with our name. */
-               if (flist_find(dir_flist, file) >= 0
-                && x_stat(thisname, &st2, NULL) == 0 && S_ISDIR(st2.st_mode)) {
-                       file->modtime = st2.st_mtime;
-                       file->len32 = 0;
-                       file->mode = st2.st_mode;
-                       if (uid_ndx)
-                               F_OWNER(file) = st2.st_uid;
-                       if (gid_ndx)
-                               F_GROUP(file) = st2.st_gid;
-               } else
-                       file->mode = save_mode;
-       }
-
        if (basename_len == 0+1) {
                if (!pool)
                        unmake_file(file);
@@ -1401,7 +1382,7 @@ static struct file_struct *send_file_name(int f, struct file_list *flist,
                                        io_error |= IOERR_GENERAL;
                                        f_name(file, fbuf);
                                        rprintf(FERROR_XFER,
-                                           "[%s] cannot convert symlink name for: %s (%s)\n",
+                                           "[%s] cannot convert symlink data for: %s (%s)\n",
                                            who_am_i(), full_fname(fbuf), strerror(errno));
                                        return NULL;
                                }
@@ -1962,9 +1943,6 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
        start_write = stats.total_written;
        gettimeofday(&start_tv, NULL);
 
-       if (!orig_dir)
-               orig_dir = strdup(curr_dir);
-
        if (relative_paths && protocol_version >= 30)
                implied_dirs = 1; /* We send flagged implied dirs */
 
@@ -1990,6 +1968,9 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
                use_ff_fd = 1;
        }
 
+       if (!orig_dir)
+               orig_dir = strdup(curr_dir);
+
        while (1) {
                char fbuf[MAXPATHLEN], *fn, name_type;
 
@@ -2459,6 +2440,28 @@ int flist_find(struct file_list *flist, struct file_struct *f)
        return -1;
 }
 
+/* Search for an identically-named item in the file list.  Differs from
+ * flist_find in that an item that agrees with "f" in directory-ness is
+ * preferred but one that does not is still found. */
+int flist_find_ignore_dirness(struct file_list *flist, struct file_struct *f)
+{
+       mode_t save_mode;
+       int ndx;
+
+       /* First look for an item that agrees in directory-ness. */
+       ndx = flist_find(flist, f);
+       if (ndx >= 0)
+               return ndx;
+
+       /* Temporarily flip f->mode to look for an item of opposite
+        * directory-ness. */
+       save_mode = f->mode;
+       f->mode = S_ISDIR(f->mode) ? S_IFREG : S_IFDIR;
+       ndx = flist_find(flist, f);
+       f->mode = save_mode;
+       return ndx;
+}
+
 /*
  * Free up any resources a file_struct has allocated
  * and clear the file.