extern int protocol_version;
extern int preserve_uid;
extern int preserve_gid;
+extern int inc_recurse;
extern int inplace;
+extern int flist_eof;
extern int keep_dirlinks;
extern int make_backups;
extern mode_t orig_umask;
-extern struct stats stats;
-extern struct file_list *the_file_list;
+extern struct file_list *cur_flist, *first_flist, *dir_flist;
extern struct chmod_mode_struct *daemon_chmod_modes;
#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
/* This is used by sender.c with a valid f_out, and by receive.c with
* f_out = -1. */
-int read_item_attrs(int f_in, int f_out, int ndx, uchar *type_ptr,
- char *buf, int *len_ptr)
+int read_ndx_and_attrs(int f_in, int f_out, int *iflag_ptr,
+ uchar *type_ptr, char *buf, int *len_ptr)
{
- int len;
+ int len, iflags = 0;
+ struct file_list *flist;
uchar fnamecmp_type = FNAMECMP_FNAME;
- int iflags = protocol_version >= 29 ? read_shortint(f_in)
+ int verbose_save, ndx;
+
+ read_loop:
+ while (1) {
+ ndx = read_ndx(f_in);
+
+ if (ndx >= 0)
+ break;
+ if (ndx == NDX_DONE)
+ return ndx;
+ if (!inc_recurse || am_sender)
+ goto invalid_ndx;
+ if (ndx == NDX_FLIST_EOF) {
+ flist_eof = 1;
+ send_msg(MSG_FLIST_EOF, "", 0);
+ continue;
+ }
+ ndx = NDX_FLIST_OFFSET - ndx;
+ if (ndx < 0 || ndx >= dir_flist->count) {
+ ndx = NDX_FLIST_OFFSET - ndx;
+ rprintf(FERROR,
+ "Invalid dir index: %d (%d - %d)\n",
+ ndx, NDX_FLIST_OFFSET,
+ NDX_FLIST_OFFSET - dir_flist->count);
+ exit_cleanup(RERR_PROTOCOL);
+ }
+ verbose_save = verbose;
+ verbose = 0; /* TODO allow verbose messages? */
+
+ /* Send everything read from f_in to msg_fd_out. */
+ send_msg_int(MSG_FLIST, ndx);
+ start_flist_forward(f_in);
+ flist = recv_file_list(f_in);
+ flist->parent_ndx = ndx;
+ stop_flist_forward();
+
+ verbose = verbose_save;
+ }
+
+ iflags = protocol_version >= 29 ? read_shortint(f_in)
: ITEM_TRANSFER | ITEM_MISSING_DATA;
- /* Handle the new keep-alive (no-op) packet. */
- if (ndx == the_file_list->count && iflags == ITEM_IS_NEW)
- ;
- else if (ndx < 0 || ndx >= the_file_list->count) {
- rprintf(FERROR, "Invalid file index: %d (count=%d) [%s]\n",
- ndx, the_file_list->count, who_am_i());
- exit_cleanup(RERR_PROTOCOL);
- } else if (iflags == ITEM_IS_NEW) {
- rprintf(FERROR, "Invalid itemized flag word: %x [%s]\n",
- iflags, who_am_i());
+ /* Honor the old-style keep-alive indicator. */
+ if (protocol_version < 30
+ && ndx == cur_flist->count && iflags == ITEM_IS_NEW) {
+ if (am_sender)
+ maybe_send_keepalive();
+ goto read_loop;
+ }
+
+ if (!(flist = flist_for_ndx(ndx))) {
+ invalid_ndx:
+ rprintf(FERROR,
+ "Invalid file index: %d (%d - %d) with iflags %x [%s]\n",
+ ndx, first_flist->ndx_start + first_flist->ndx_start,
+ first_flist->prev->ndx_start + first_flist->ndx_start
+ + first_flist->prev->count - 1, iflags, who_am_i());
exit_cleanup(RERR_PROTOCOL);
}
+ cur_flist = flist;
if (iflags & ITEM_BASIS_TYPE_FOLLOWS)
fnamecmp_type = read_byte(f_in);
*len_ptr = len;
if (iflags & ITEM_TRANSFER) {
- if (!S_ISREG(the_file_list->files[ndx]->mode)) {
+ int i = ndx - cur_flist->ndx_start;
+ if (!S_ISREG(cur_flist->files[i]->mode)) {
rprintf(FERROR,
"received request to transfer non-regular file: %d [%s]\n",
ndx, who_am_i());
fnamecmp_type, buf, len);
}
- return iflags;
+ *iflag_ptr = iflags;
+ return ndx;
}
/*
updated = 1;
}
- change_uid = am_root && preserve_uid && st->st_uid != file->uid;
- change_gid = preserve_gid && file->gid != GID_NONE
- && st->st_gid != file->gid;
+ change_uid = am_root && preserve_uid && st->st_uid != F_UID(file);
+ change_gid = preserve_gid && F_GID(file) != GID_NONE
+ && st->st_gid != F_GID(file);
#if !defined HAVE_LCHOWN && !defined CHOWN_MODIFIES_SYMLINK
if (S_ISLNK(st->st_mode))
;
rprintf(FINFO,
"set uid of %s from %ld to %ld\n",
fname,
- (long)st->st_uid, (long)file->uid);
+ (long)st->st_uid, (long)F_UID(file));
}
if (change_gid) {
rprintf(FINFO,
"set gid of %s from %ld to %ld\n",
fname,
- (long)st->st_gid, (long)file->gid);
+ (long)st->st_gid, (long)F_GID(file));
}
}
if (do_lchown(fname,
- change_uid ? file->uid : st->st_uid,
- change_gid ? file->gid : st->st_gid) != 0) {
+ change_uid ? F_UID(file) : st->st_uid,
+ change_gid ? F_GID(file) : st->st_gid) != 0) {
/* shouldn't have attempted to change uid or gid
* unless have the privilege */
rsyserr(FERROR, errno, "%s %s failed",
if (daemon_chmod_modes && !S_ISLNK(new_mode))
new_mode = tweak_mode(new_mode, daemon_chmod_modes);
#ifdef HAVE_CHMOD
- if ((st->st_mode & CHMOD_BITS) != (new_mode & CHMOD_BITS)) {
+ if (!BITS_EQUAL(st->st_mode, new_mode, CHMOD_BITS)) {
int ret = do_chmod(fname, new_mode);
if (ret < 0) {
rsyserr(FERROR, errno,
goto do_set_file_attrs;
}
- if (make_backups && overwriting_basis && !make_backup(fname))
+ if (make_backups > 0 && overwriting_basis && !make_backup(fname))
return;
/* Change permissions before putting the file into place. */
}
}
+struct file_list *flist_for_ndx(int ndx)
+{
+ struct file_list *flist = cur_flist;
+
+ if (!flist)
+ return NULL;
+
+ while (ndx < flist->ndx_start) {
+ if (flist == first_flist)
+ return NULL;
+ flist = flist->prev;
+ }
+ while (ndx >= flist->ndx_start + flist->count) {
+ if (!(flist = flist->next))
+ return NULL;
+ }
+ return flist;
+}
+
const char *who_am_i(void)
{
if (am_starting_up)