extern int am_root;
extern int am_server;
extern int am_daemon;
+extern int am_sender;
extern int always_checksum;
extern int module_id;
extern int ignore_errors;
static char empty_sum[MD4_SUM_LENGTH];
static unsigned int file_struct_len;
+static struct file_list *received_flist;
static void clean_flist(struct file_list *flist, int strip_root, int no_dups);
static void output_flist(struct file_list *flist);
* @post @p buffer contains information about the link or the
* referrent as appropriate, if they exist.
**/
-int readlink_stat(const char *path, STRUCT_STAT *buffer, char *linkbuf)
+static int readlink_stat(const char *path, STRUCT_STAT *buffer, char *linkbuf)
{
#if SUPPORT_LINKS
if (copy_links)
return do_stat(path, buffer);
- if (link_stat(path, buffer, keep_dirlinks) < 0)
+ if (link_stat(path, buffer, 0) < 0)
return -1;
if (S_ISLNK(buffer->st_mode)) {
int l = readlink((char *)path, linkbuf, MAXPATHLEN - 1);
static uid_t uid;
static gid_t gid;
static char lastname[MAXPATHLEN], *lastdir;
- static int lastdir_len = -1;
+ static int lastdir_depth, lastdir_len = -1;
char thisname[MAXPATHLEN];
unsigned int l1 = 0, l2 = 0;
int alloc_len, basename_len, dirname_len, linkname_len, sum_len;
strlcpy(lastname, thisname, MAXPATHLEN);
- clean_fname(thisname);
+ clean_fname(thisname, 0);
if (sanitize_paths)
- sanitize_path(thisname, thisname, NULL);
+ sanitize_path(thisname, thisname, "", 0);
if ((basename = strrchr(thisname, '/')) != NULL) {
dirname_len = ++basename - thisname; /* counts future '\0' */
memcpy(bp, dirname, dirname_len - 1);
bp += dirname_len;
bp[-1] = '\0';
+ if (sanitize_paths)
+ lastdir_depth = count_dir_elements(lastdir);
} else if (dirname)
file->dirname = dirname;
file->u.link = bp;
read_sbuf(f, bp, linkname_len - 1);
if (sanitize_paths)
- sanitize_path(bp, bp, lastdir);
+ sanitize_path(bp, bp, "", lastdir_depth);
bp += linkname_len;
}
#endif
rprintf(FINFO, "skipping overly long name: %s\n", fname);
return NULL;
}
- clean_fname(thisname);
+ clean_fname(thisname, 0);
if (sanitize_paths)
- sanitize_path(thisname, thisname, NULL);
+ sanitize_path(thisname, thisname, "", 0);
memset(sum, 0, SUM_LENGTH);
file->basedir = flist_dir;
+ /* 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 i = flist_find(received_flist, file);
+ if (i >= 0 && S_ISDIR(received_flist->files[i]->mode)
+ && do_stat(thisname, &st2) == 0 && S_ISDIR(st2.st_mode)) {
+ file->modtime = st2.st_mtime;
+ file->length = st2.st_size;
+ file->mode = st2.st_mode;
+ file->uid = st2.st_uid;
+ file->gid = st2.st_gid;
+ file->u.link = NULL;
+ if (file->link_u.idev) {
+ pool_free(flist->hlink_pool, 0, file->link_u.idev);
+ file->link_u.idev = NULL;
+ }
+ }
+ }
+
if (!S_ISDIR(st.st_mode))
stats.total_size += st.st_size;
if (use_ff_fd) {
if (read_filesfrom_line(filesfrom_fd, fname) == 0)
break;
- sanitize_path(fname, fname, NULL);
+ sanitize_path(fname, fname, "", 0);
} else {
if (argc-- == 0)
break;
strlcpy(fname, *argv++, MAXPATHLEN);
if (sanitize_paths)
- sanitize_path(fname, fname, NULL);
+ sanitize_path(fname, fname, "", 0);
}
l = strlen(fname);
start_read = stats.total_read;
flist = flist_new(WITH_HLINK, "recv_file_list");
+ received_flist = flist;
flist->count = 0;
flist->malloced = 1000;
for (i = 0; i < flist->count; i++) {
file = flist->files[i];
- if (am_root && preserve_uid)
+ if ((am_root || am_sender) && preserve_uid)
sprintf(uidbuf, " uid=%ld", (long)file->uid);
else
*uidbuf = '\0';