return 1;
}
-static void send_file_entry(int f, struct file_struct *file, int ndx, int first_ndx)
+static void send_file_entry(int f, const char *fname, struct file_struct *file, int ndx, int first_ndx)
{
static time_t modtime;
static mode_t mode;
static gid_t gid;
static const char *user_name, *group_name;
static char lastname[MAXPATHLEN];
- char fname[MAXPATHLEN];
int first_hlink_ndx = -1;
int l1, l2;
int xflags;
-#ifdef ICONV_OPTION
- if (ic_send != (iconv_t)-1) {
- xbuf outbuf, inbuf;
-
- INIT_CONST_XBUF(outbuf, fname);
-
- if (file->dirname) {
- INIT_XBUF_STRLEN(inbuf, (char*)file->dirname);
- outbuf.size -= 2; /* Reserve room for '/' & 1 more char. */
- if (iconvbufs(ic_send, &inbuf, &outbuf, 0) < 0)
- goto convert_error;
- outbuf.size += 2;
- outbuf.buf[outbuf.len++] = '/';
- }
-
- INIT_XBUF_STRLEN(inbuf, (char*)file->basename);
- if (iconvbufs(ic_send, &inbuf, &outbuf, 0) < 0) {
- convert_error:
- io_error |= IOERR_GENERAL;
- rprintf(FINFO,
- "[%s] cannot convert filename: %s (%s)\n",
- who_am_i(), f_name(file, fname), strerror(errno));
- return;
- }
- outbuf.buf[outbuf.len] = '\0';
- } else
-#endif
- f_name(file, fname);
-
/* Initialize starting value of xflags. */
if (protocol_version >= 30 && S_ISDIR(file->mode)) {
dir_count++;
}
} else if (protocol_version < 28)
rdev = MAKEDEV(0, 0);
- if (preserve_uid) {
- if ((uid_t)F_OWNER(file) == uid && *lastname)
- xflags |= XMIT_SAME_UID;
- else {
- uid = F_OWNER(file);
- if (!numeric_ids) {
- user_name = add_uid(uid);
- if (inc_recurse && user_name)
- xflags |= XMIT_USER_NAME_FOLLOWS;
- }
+ if (!preserve_uid || ((uid_t)F_OWNER(file) == uid && *lastname))
+ xflags |= XMIT_SAME_UID;
+ else {
+ uid = F_OWNER(file);
+ if (!numeric_ids) {
+ user_name = add_uid(uid);
+ if (inc_recurse && user_name)
+ xflags |= XMIT_USER_NAME_FOLLOWS;
}
}
- if (preserve_gid) {
- if ((gid_t)F_GROUP(file) == gid && *lastname)
- xflags |= XMIT_SAME_GID;
- else {
- gid = F_GROUP(file);
- if (!numeric_ids) {
- group_name = add_gid(gid);
- if (inc_recurse && group_name)
- xflags |= XMIT_GROUP_NAME_FOLLOWS;
- }
+ if (!preserve_gid || ((gid_t)F_GROUP(file) == gid && *lastname))
+ xflags |= XMIT_SAME_GID;
+ else {
+ gid = F_GROUP(file);
+ if (!numeric_ids) {
+ group_name = add_gid(gid);
+ if (inc_recurse && group_name)
+ xflags |= XMIT_GROUP_NAME_FOLLOWS;
}
}
if (file->modtime == modtime)
np->data = (void*)(long)(first_ndx + ndx + 1);
xflags |= XMIT_HLINK_FIRST;
}
- xflags |= XMIT_HLINKED;
} else {
if (tmp_dev == dev) {
if (protocol_version >= 28)
xflags |= XMIT_SAME_DEV_pre30;
} else
dev = tmp_dev;
- xflags |= XMIT_HLINKED;
}
+ xflags |= XMIT_HLINKED;
}
#endif
}
#endif
- clean_fname(thisname, 0);
+ if (*thisname)
+ clean_fname(thisname, 0);
if (sanitize_paths)
sanitize_path(thisname, thisname, "", 0, SP_DEFAULT);
}
static struct file_struct *send_file_name(int f, struct file_list *flist,
- char *fname, STRUCT_STAT *stp,
+ const char *fname, STRUCT_STAT *stp,
int flags, int filter_level)
{
struct file_struct *file;
-#if defined SUPPORT_ACLS || defined SUPPORT_XATTRS
- stat_x sx;
-#endif
file = make_file(fname, flist, stp, flags, filter_level);
if (!file)
if (chmod_modes && !S_ISLNK(file->mode))
file->mode = tweak_mode(file->mode, chmod_modes);
+ if (f >= 0) {
+ char fbuf[MAXPATHLEN];
+#if defined SUPPORT_ACLS || defined SUPPORT_XATTRS
+ stat_x sx;
+#endif
+
+#ifdef ICONV_OPTION
+ if (ic_send != (iconv_t)-1) {
+ xbuf outbuf, inbuf;
+
+ INIT_CONST_XBUF(outbuf, fbuf);
+
+ if (file->dirname) {
+ INIT_XBUF_STRLEN(inbuf, (char*)file->dirname);
+ outbuf.size -= 2; /* Reserve room for '/' & 1 more char. */
+ if (iconvbufs(ic_send, &inbuf, &outbuf, 0) < 0)
+ goto convert_error;
+ outbuf.size += 2;
+ outbuf.buf[outbuf.len++] = '/';
+ }
+
+ INIT_XBUF_STRLEN(inbuf, (char*)file->basename);
+ if (iconvbufs(ic_send, &inbuf, &outbuf, 0) < 0) {
+ convert_error:
+ io_error |= IOERR_GENERAL;
+ rprintf(FINFO,
+ "[%s] cannot convert filename: %s (%s)\n",
+ who_am_i(), f_name(file, fbuf), strerror(errno));
+ return NULL;
+ }
+ outbuf.buf[outbuf.len] = '\0';
+ } else
+#endif
+ f_name(file, fbuf);
+
#ifdef SUPPORT_ACLS
- if (preserve_acls && !S_ISLNK(file->mode) && f >= 0) {
- sx.st.st_mode = file->mode;
- sx.acc_acl = sx.def_acl = NULL;
- if (get_acl(fname, &sx) < 0)
- return NULL;
- }
+ if (preserve_acls && !S_ISLNK(file->mode)) {
+ sx.st.st_mode = file->mode;
+ sx.acc_acl = sx.def_acl = NULL;
+ if (get_acl(fname, &sx) < 0)
+ return NULL;
+ }
#endif
#ifdef SUPPORT_XATTRS
- if (preserve_xattrs && f >= 0) {
- sx.xattr = NULL;
- if (get_xattr(fname, &sx) < 0)
- return NULL;
- }
+ if (preserve_xattrs) {
+ sx.xattr = NULL;
+ if (get_xattr(fname, &sx) < 0)
+ return NULL;
+ }
#endif
- maybe_emit_filelist_progress(flist->used + flist_count_offset);
+ send_file_entry(f, fbuf, file, flist->used, flist->ndx_start);
- flist_expand(flist, 1);
- flist->files[flist->used++] = file;
- if (f >= 0) {
- send_file_entry(f, file, flist->used - 1, flist->ndx_start);
#ifdef SUPPORT_ACLS
if (preserve_acls && !S_ISLNK(file->mode)) {
send_acl(&sx, f);
}
#endif
}
+
+ maybe_emit_filelist_progress(flist->used + flist_count_offset);
+
+ flist_expand(flist, 1);
+ flist->files[flist->used++] = file;
+
return file;
}
}
}
-static char lastpath[MAXPATHLEN] = "";
-static int lastpath_len = 0;
-static struct file_struct *lastpath_struct;
-
static void send_implied_dirs(int f, struct file_list *flist, char *fname,
char *start, char *limit, int flags, char name_type)
{
+ static char lastpath[MAXPATHLEN] = "";
+ static int lastpath_len = 0;
+ static struct file_struct *lastpath_struct = NULL;
struct file_struct *file;
item_list *relname_list;
relnamecache **rnpp;
- char *slash;
- int len, need_new_dir;
+ int len, need_new_dir, depth = 0;
struct filter_list_struct save_filter_list = filter_list;
flags = (flags | FLAG_IMPLIED_DIR) & ~(FLAG_TOP_DIR | FLAG_CONTENT_DIR);
need_new_dir = 0;
else
need_new_dir = 1;
- } else
+ } else {
+ char *tp = fname, *lp = lastpath;
+ /* Skip any initial directories in our path that we
+ * have in common with lastpath. */
+ assert(start == fname);
+ for ( ; ; tp++, lp++) {
+ if (tp == limit) {
+ if (*lp == '/' || *lp == '\0')
+ goto done;
+ break;
+ }
+ if (*lp != *tp)
+ break;
+ if (*tp == '/') {
+ start = tp;
+ depth++;
+ }
+ }
need_new_dir = 1;
+ }
if (need_new_dir) {
int save_copy_links = copy_links;
int save_xfer_dirs = xfer_dirs;
+ char *slash;
copy_links = xfer_dirs = 1;
for (slash = start; (slash = strchr(slash+1, '/')) != NULL; ) {
*slash = '\0';
- send_file_name(f, flist, fname, NULL, flags, ALL_FILTERS);
+ file = send_file_name(f, flist, fname, NULL, flags, ALL_FILTERS);
+ depth++;
+ if (!inc_recurse && file && S_ISDIR(file->mode))
+ change_local_filter_dir(fname, strlen(fname), depth);
*slash = '/';
}
if (file && !S_ISDIR(file->mode))
file = NULL;
lastpath_struct = file;
- }
+ } else if (file && S_ISDIR(file->mode))
+ change_local_filter_dir(fname, strlen(fname), ++depth);
strlcpy(lastpath, fname, sizeof lastpath);
lastpath_len = limit - fname;
} else if (implied_dirs && (p=strrchr(fbuf,'/')) && p != fbuf) {
/* Send the implied directories at the start of the
* source spec, so we get their permissions right. */
- char *lp = lastpath, *slash = fbuf;
- *p = '\0';
- /* Skip any initial directories in our path that we
- * have in common with lastpath. */
- for (fn = fbuf; *fn && *lp == *fn; lp++, fn++) {
- if (*fn == '/')
- slash = fn;
- }
- *p = '/';
- if (fn != p || (*lp && *lp != '/'))
- send_implied_dirs(f, flist, fbuf, slash, p, flags, 0);
+ send_implied_dirs(f, flist, fbuf, fbuf, p, flags, 0);
}
if (one_file_system)