version 1.1.1.1, 2012/02/17 15:09:30
|
version 1.1.1.2, 2013/10/14 07:51:14
|
Line 3
|
Line 3
|
* |
* |
* Copyright (C) 1996 Andrew Tridgell |
* Copyright (C) 1996 Andrew Tridgell |
* Copyright (C) 1996 Paul Mackerras |
* Copyright (C) 1996 Paul Mackerras |
* Copyright (C) 2003-2009 Wayne Davison | * Copyright (C) 2003-2013 Wayne Davison |
* |
* |
* This program is free software; you can redistribute it and/or modify |
* This program is free software; you can redistribute it and/or modify |
* it under the terms of the GNU General Public License as published by |
* it under the terms of the GNU General Public License as published by |
Line 27
|
Line 27
|
#include <langinfo.h> |
#include <langinfo.h> |
#endif |
#endif |
|
|
extern int verbose; |
|
extern int dry_run; |
extern int dry_run; |
extern int preserve_acls; |
extern int preserve_acls; |
extern int preserve_xattrs; |
extern int preserve_xattrs; |
Line 36 extern int preserve_executability;
|
Line 35 extern int preserve_executability;
|
extern int preserve_times; |
extern int preserve_times; |
extern int am_root; |
extern int am_root; |
extern int am_server; |
extern int am_server; |
|
extern int am_daemon; |
extern int am_sender; |
extern int am_sender; |
extern int am_receiver; |
extern int am_receiver; |
extern int am_generator; |
extern int am_generator; |
extern int am_starting_up; |
extern int am_starting_up; |
extern int allow_8bit_chars; |
extern int allow_8bit_chars; |
extern int protocol_version; |
extern int protocol_version; |
|
extern int got_kill_signal; |
extern int inc_recurse; |
extern int inc_recurse; |
extern int inplace; |
extern int inplace; |
extern int flist_eof; |
extern int flist_eof; |
|
extern int file_old_total; |
extern int keep_dirlinks; |
extern int keep_dirlinks; |
extern int make_backups; |
extern int make_backups; |
extern struct file_list *cur_flist, *first_flist, *dir_flist; |
extern struct file_list *cur_flist, *first_flist, *dir_flist; |
Line 82 void setup_iconv(void)
|
Line 84 void setup_iconv(void)
|
/* It's OK if this fails... */ |
/* It's OK if this fails... */ |
ic_chck = iconv_open(defset, defset); |
ic_chck = iconv_open(defset, defset); |
|
|
if (verbose > 3) { | if (DEBUG_GTE(ICONV, 2)) { |
if (ic_chck == (iconv_t)-1) { |
if (ic_chck == (iconv_t)-1) { |
rprintf(FINFO, |
rprintf(FINFO, |
"note: iconv_open(\"%s\", \"%s\") failed (%d)" | "msg checking via isprint()" |
" -- using isprint() instead of iconv().\n", | " (iconv_open(\"%s\", \"%s\") errno: %d)\n", |
defset, defset, errno); |
defset, defset, errno); |
} else { |
} else { |
rprintf(FINFO, |
rprintf(FINFO, |
"note: iconv_open(\"%s\", \"%s\") succeeded.\n", | "msg checking charset: %s\n", |
defset, defset); | defset); |
} |
} |
} |
} |
} | } else |
| ic_chck = (iconv_t)-1; |
|
|
# ifdef ICONV_OPTION |
# ifdef ICONV_OPTION |
if (!iconv_opt) |
if (!iconv_opt) |
Line 124 void setup_iconv(void)
|
Line 127 void setup_iconv(void)
|
exit_cleanup(RERR_UNSUPPORTED); |
exit_cleanup(RERR_UNSUPPORTED); |
} |
} |
|
|
if (verbose > 1) { | if (DEBUG_GTE(ICONV, 1)) { |
rprintf(FINFO, "%s charset: %s\n", | rprintf(FINFO, "[%s] charset: %s\n", |
am_server ? "server" : "client", | who_am_i(), *charset ? charset : "[LOCALE]"); |
*charset ? charset : "[LOCALE]"); | |
} |
} |
# endif |
# endif |
} |
} |
|
|
/* This function converts the characters in the "in" xbuf into characters | /* This function converts the chars in the "in" xbuf into characters in the |
* in the "out" xbuf. The "len" of the "in" xbuf is used starting from its | * "out" xbuf. The ".len" chars of the "in" xbuf is used starting from its |
* "pos". The "size" of the "out" xbuf restricts how many characters can be | * ".pos". The ".size" of the "out" xbuf restricts how many characters can |
* stored, starting at its "pos+len" position. Note that the last byte of | * be stored, starting at its ".pos+.len" position. Note that the last byte |
* the buffer is never used, which reserves space for a terminating '\0'. | * of the "out" xbuf is not used, which reserves space for a trailing '\0' |
| * (though it is up to the caller to store a trailing '\0', as needed). |
| * |
* We return a 0 on success or a -1 on error. An error also sets errno to |
* We return a 0 on success or a -1 on error. An error also sets errno to |
* E2BIG, EILSEQ, or EINVAL (see below); otherwise errno will be set to 0. |
* E2BIG, EILSEQ, or EINVAL (see below); otherwise errno will be set to 0. |
* The "in" xbuf is altered to update "pos" and "len". The "out" xbuf has | * The "in" xbuf is altered to update ".pos" and ".len". The "out" xbuf has |
* data appended, and its "len" incremented. If ICB_EXPAND_OUT is set in | * data appended, and its ".len" incremented (see below for a ".size" note). |
* "flags", the "out" xbuf will also be allocated if empty, and expanded if | * |
* too small (so E2BIG will not be returned). If ICB_INCLUDE_BAD is set in | * If ICB_CIRCULAR_OUT is set in "flags", the chars going into the "out" xbuf |
* "flags", any badly-encoded chars are included verbatim in the "out" xbuf, | * can wrap around to the start, and the xbuf may have its ".size" reduced |
* so EILSEQ will not be returned. Likewise for ICB_INCLUDE_INCOMPLETE with | * (presumably by 1 byte) if the iconv code doesn't have space to store a |
* respect to an incomplete multi-byte char at the end, which ensures that | * multi-byte character at the physical end of the ".buf" (though no reducing |
* EINVAL is not returned. Anytime "in.pos" is 0 we will reset the iconv() | * happens if ".pos" is <= 1, since there is no room to wrap around). |
* state prior to processing the characters. */ | * |
| * If ICB_EXPAND_OUT is set in "flags", the "out" xbuf will be allocated if |
| * empty, and (as long as ICB_CIRCULAR_OUT is not set) expanded if too small. |
| * This prevents the return of E2BIG (except for a circular xbuf). |
| * |
| * If ICB_INCLUDE_BAD is set in "flags", any badly-encoded chars are included |
| * verbatim in the "out" xbuf, so EILSEQ will not be returned. |
| * |
| * If ICB_INCLUDE_INCOMPLETE is set in "flags", any incomplete multi-byte |
| * chars are included, which ensures that EINVAL is not returned. |
| * |
| * If ICB_INIT is set, the iconv() conversion state is initialized prior to |
| * processing the characters. */ |
int iconvbufs(iconv_t ic, xbuf *in, xbuf *out, int flags) |
int iconvbufs(iconv_t ic, xbuf *in, xbuf *out, int flags) |
{ |
{ |
ICONV_CONST char *ibuf; |
ICONV_CONST char *ibuf; |
size_t icnt, ocnt; | size_t icnt, ocnt, opos; |
char *obuf; |
char *obuf; |
|
|
if (!out->size && flags & ICB_EXPAND_OUT) | if (!out->size && flags & ICB_EXPAND_OUT) { |
alloc_xbuf(out, 1024); | size_t siz = ROUND_UP_1024(in->len * 2); |
| alloc_xbuf(out, siz); |
| } else if (out->len+1 >= out->size) { |
| /* There is no room to even start storing data. */ |
| if (!(flags & ICB_EXPAND_OUT) || flags & ICB_CIRCULAR_OUT) { |
| errno = E2BIG; |
| return -1; |
| } |
| realloc_xbuf(out, out->size + ROUND_UP_1024(in->len * 2)); |
| } |
|
|
if (!in->pos) | if (flags & ICB_INIT) |
iconv(ic, NULL, 0, NULL, 0); |
iconv(ic, NULL, 0, NULL, 0); |
|
|
ibuf = in->buf + in->pos; |
ibuf = in->buf + in->pos; |
icnt = in->len; |
icnt = in->len; |
|
|
obuf = out->buf + (out->pos + out->len); | opos = out->pos + out->len; |
ocnt = out->size - (out->pos + out->len) - 1; | if (flags & ICB_CIRCULAR_OUT) { |
| if (opos >= out->size) { |
| opos -= out->size; |
| /* We know that out->pos is not 0 due to the "no room" check |
| * above, so this can't go "negative". */ |
| ocnt = out->pos - opos - 1; |
| } else { |
| /* Allow the use of all bytes to the physical end of the buffer |
| * unless pos is 0, in which case we reserve our trailing '\0'. */ |
| ocnt = out->size - opos - (out->pos ? 0 : 1); |
| } |
| } else |
| ocnt = out->size - opos - 1; |
| obuf = out->buf + opos; |
|
|
while (icnt) { |
while (icnt) { |
while (iconv(ic, &ibuf, &icnt, &obuf, &ocnt) == (size_t)-1) { |
while (iconv(ic, &ibuf, &icnt, &obuf, &ocnt) == (size_t)-1) { |
Line 173 int iconvbufs(iconv_t ic, xbuf *in, xbuf *out, int fla
|
Line 211 int iconvbufs(iconv_t ic, xbuf *in, xbuf *out, int fla
|
if (errno == EINVAL) { |
if (errno == EINVAL) { |
if (!(flags & ICB_INCLUDE_INCOMPLETE)) |
if (!(flags & ICB_INCLUDE_INCOMPLETE)) |
goto finish; |
goto finish; |
|
if (!ocnt) |
|
goto e2big; |
} else if (errno == EILSEQ) { |
} else if (errno == EILSEQ) { |
if (!(flags & ICB_INCLUDE_BAD)) |
if (!(flags & ICB_INCLUDE_BAD)) |
goto finish; |
goto finish; |
} else { | if (!ocnt) |
size_t opos = obuf - out->buf; | goto e2big; |
if (!(flags & ICB_EXPAND_OUT)) { | } else if (errno == E2BIG) { |
| size_t siz; |
| e2big: |
| opos = obuf - out->buf; |
| if (flags & ICB_CIRCULAR_OUT && out->pos > 1 && opos > out->pos) { |
| /* We are in a divided circular buffer at the physical |
| * end with room to wrap to the start. If iconv() refused |
| * to use one or more trailing bytes in the buffer, we |
| * set the size to ignore the unused bytes. */ |
| if (opos < out->size) |
| reduce_iobuf_size(out, opos); |
| obuf = out->buf; |
| ocnt = out->pos - 1; |
| continue; |
| } |
| if (!(flags & ICB_EXPAND_OUT) || flags & ICB_CIRCULAR_OUT) { |
errno = E2BIG; |
errno = E2BIG; |
goto finish; |
goto finish; |
} |
} |
realloc_xbuf(out, out->size + 1024); | siz = ROUND_UP_1024(in->len * 2); |
| realloc_xbuf(out, out->size + siz); |
obuf = out->buf + opos; |
obuf = out->buf + opos; |
ocnt += 1024; | ocnt += siz; |
continue; |
continue; |
|
} else { |
|
rsyserr(FERROR, errno, "unexpected error from iconv()"); |
|
exit_cleanup(RERR_UNSUPPORTED); |
} |
} |
*obuf++ = *ibuf++; |
*obuf++ = *ibuf++; |
ocnt--, icnt--; |
ocnt--, icnt--; |
|
if (!icnt) |
|
break; |
} |
} |
} |
} |
|
|
errno = 0; |
errno = 0; |
|
|
finish: |
finish: |
|
opos = obuf - out->buf; |
|
if (flags & ICB_CIRCULAR_OUT && opos < out->pos) |
|
opos += out->size; |
|
out->len = opos - out->pos; |
|
|
in->len = icnt; |
in->len = icnt; |
in->pos = ibuf - in->buf; |
in->pos = ibuf - in->buf; |
out->len = obuf - out->buf - out->pos; |
|
|
|
return errno ? -1 : 0; |
return errno ? -1 : 0; |
} |
} |
Line 216 void send_protected_args(int fd, char *args[])
|
Line 281 void send_protected_args(int fd, char *args[])
|
|
|
for (i = 0; args[i]; i++) {} /* find first NULL */ |
for (i = 0; args[i]; i++) {} /* find first NULL */ |
args[i] = "rsync"; /* set a new arg0 */ |
args[i] = "rsync"; /* set a new arg0 */ |
if (verbose > 1) | if (DEBUG_GTE(CMD, 1)) |
print_child_argv("protected args:", args + i + 1); |
print_child_argv("protected args:", args + i + 1); |
do { |
do { |
if (!args[i][0]) |
if (!args[i][0]) |
Line 225 void send_protected_args(int fd, char *args[])
|
Line 290 void send_protected_args(int fd, char *args[])
|
else if (convert) { |
else if (convert) { |
INIT_XBUF_STRLEN(inbuf, args[i]); |
INIT_XBUF_STRLEN(inbuf, args[i]); |
iconvbufs(ic_send, &inbuf, &outbuf, |
iconvbufs(ic_send, &inbuf, &outbuf, |
ICB_EXPAND_OUT | ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE); | ICB_EXPAND_OUT | ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE | ICB_INIT); |
outbuf.buf[outbuf.len] = '\0'; |
outbuf.buf[outbuf.len] = '\0'; |
write_buf(fd, outbuf.buf, outbuf.len + 1); |
write_buf(fd, outbuf.buf, outbuf.len + 1); |
outbuf.len = 0; |
outbuf.len = 0; |
Line 242 void send_protected_args(int fd, char *args[])
|
Line 307 void send_protected_args(int fd, char *args[])
|
#endif |
#endif |
} |
} |
|
|
int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar *type_ptr, | int read_ndx_and_attrs(int f_in, int f_out, int *iflag_ptr, uchar *type_ptr, |
char *buf, int *len_ptr) |
char *buf, int *len_ptr) |
{ |
{ |
int len, iflags = 0; |
int len, iflags = 0; |
struct file_list *flist; |
struct file_list *flist; |
uchar fnamecmp_type = FNAMECMP_FNAME; |
uchar fnamecmp_type = FNAMECMP_FNAME; |
int ndx, save_verbose = verbose; | int ndx; |
|
|
read_loop: |
read_loop: |
while (1) { |
while (1) { |
Line 258 int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar
|
Line 323 int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar
|
break; |
break; |
if (ndx == NDX_DONE) |
if (ndx == NDX_DONE) |
return ndx; |
return ndx; |
|
if (ndx == NDX_DEL_STATS) { |
|
read_del_stats(f_in); |
|
if (am_sender && am_server) |
|
write_del_stats(f_out); |
|
continue; |
|
} |
if (!inc_recurse || am_sender) { |
if (!inc_recurse || am_sender) { |
int last; |
int last; |
if (first_flist) |
if (first_flist) |
Line 271 int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar
|
Line 342 int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar
|
} |
} |
if (ndx == NDX_FLIST_EOF) { |
if (ndx == NDX_FLIST_EOF) { |
flist_eof = 1; |
flist_eof = 1; |
send_msg(MSG_FLIST_EOF, "", 0, 0); | if (DEBUG_GTE(FLIST, 3)) |
| rprintf(FINFO, "[%s] flist_eof=1\n", who_am_i()); |
| write_int(f_out, NDX_FLIST_EOF); |
continue; |
continue; |
} |
} |
ndx = NDX_FLIST_OFFSET - ndx; |
ndx = NDX_FLIST_OFFSET - ndx; |
Line 285 int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar
|
Line 358 int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar
|
exit_cleanup(RERR_PROTOCOL); |
exit_cleanup(RERR_PROTOCOL); |
} |
} |
|
|
/* Send everything read from f_in to msg_fd_out. */ | if (DEBUG_GTE(FLIST, 2)) { |
if (verbose > 3) { | |
rprintf(FINFO, "[%s] receiving flist for dir %d\n", |
rprintf(FINFO, "[%s] receiving flist for dir %d\n", |
who_am_i(), ndx); |
who_am_i(), ndx); |
} |
} |
verbose = 0; | /* Send all the data we read for this flist to the generator. */ |
send_msg_int(MSG_FLIST, ndx); | start_flist_forward(ndx); |
start_flist_forward(f_in); | |
flist = recv_file_list(f_in); |
flist = recv_file_list(f_in); |
flist->parent_ndx = ndx; |
flist->parent_ndx = ndx; |
stop_flist_forward(); |
stop_flist_forward(); |
verbose = save_verbose; |
|
} |
} |
|
|
iflags = protocol_version >= 29 ? read_shortint(f_in) |
iflags = protocol_version >= 29 ? read_shortint(f_in) |
Line 305 int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar
|
Line 375 int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar
|
/* Support the protocol-29 keep-alive style. */ |
/* Support the protocol-29 keep-alive style. */ |
if (protocol_version < 30 && ndx == cur_flist->used && iflags == ITEM_IS_NEW) { |
if (protocol_version < 30 && ndx == cur_flist->used && iflags == ITEM_IS_NEW) { |
if (am_sender) |
if (am_sender) |
maybe_send_keepalive(); | maybe_send_keepalive(time(NULL), MSK_ALLOW_FLUSH); |
goto read_loop; |
goto read_loop; |
} |
} |
|
|
cur_flist = flist_for_ndx(ndx, "read_ndx_and_attrs"); | flist = flist_for_ndx(ndx, "read_ndx_and_attrs"); |
| if (flist != cur_flist) { |
| cur_flist = flist; |
| if (am_sender) { |
| file_old_total = cur_flist->used; |
| for (flist = first_flist; flist != cur_flist; flist = flist->next) |
| file_old_total += flist->used; |
| } |
| } |
|
|
if (iflags & ITEM_BASIS_TYPE_FOLLOWS) |
if (iflags & ITEM_BASIS_TYPE_FOLLOWS) |
fnamecmp_type = read_byte(f_in); |
fnamecmp_type = read_byte(f_in); |
Line 391 int set_file_attrs(const char *fname, struct file_stru
|
Line 469 int set_file_attrs(const char *fname, struct file_stru
|
full_fname(fname)); |
full_fname(fname)); |
return 0; |
return 0; |
} |
} |
#ifdef SUPPORT_ACLS | init_stat_x(&sx2); |
sx2.acc_acl = sx2.def_acl = NULL; | |
#endif | |
#ifdef SUPPORT_XATTRS | |
sx2.xattr = NULL; | |
#endif | |
sxp = &sx2; |
sxp = &sx2; |
inherit = !preserve_perms; |
inherit = !preserve_perms; |
} else |
} else |
Line 429 int set_file_attrs(const char *fname, struct file_stru
|
Line 502 int set_file_attrs(const char *fname, struct file_stru
|
flags |= ATTRS_SKIP_MTIME; |
flags |= ATTRS_SKIP_MTIME; |
if (!(flags & ATTRS_SKIP_MTIME) |
if (!(flags & ATTRS_SKIP_MTIME) |
&& cmp_time(sxp->st.st_mtime, file->modtime) != 0) { |
&& cmp_time(sxp->st.st_mtime, file->modtime) != 0) { |
int ret = set_modtime(fname, file->modtime, sxp->st.st_mode); | int ret = set_modtime(fname, file->modtime, F_MOD_NSEC(file), sxp->st.st_mode); |
if (ret < 0) { |
if (ret < 0) { |
rsyserr(FERROR_XFER, errno, "failed to set times on %s", |
rsyserr(FERROR_XFER, errno, "failed to set times on %s", |
full_fname(fname)); |
full_fname(fname)); |
Line 450 int set_file_attrs(const char *fname, struct file_stru
|
Line 523 int set_file_attrs(const char *fname, struct file_stru
|
} else |
} else |
#endif |
#endif |
if (change_uid || change_gid) { |
if (change_uid || change_gid) { |
if (verbose > 2) { | if (DEBUG_GTE(OWN, 1)) { |
if (change_uid) { |
if (change_uid) { |
rprintf(FINFO, |
rprintf(FINFO, |
"set uid of %s from %u to %u\n", |
"set uid of %s from %u to %u\n", |
Line 515 int set_file_attrs(const char *fname, struct file_stru
|
Line 588 int set_file_attrs(const char *fname, struct file_stru
|
} |
} |
#endif |
#endif |
|
|
if (verbose > 1 && flags & ATTRS_REPORT) { | if (INFO_GTE(NAME, 2) && flags & ATTRS_REPORT) { |
if (updated) |
if (updated) |
rprintf(FCLIENT, "%s\n", fname); |
rprintf(FCLIENT, "%s\n", fname); |
else |
else |
rprintf(FCLIENT, "%s is uptodate\n", fname); |
rprintf(FCLIENT, "%s is uptodate\n", fname); |
} |
} |
cleanup: |
cleanup: |
if (sxp == &sx2) { | if (sxp == &sx2) |
#ifdef SUPPORT_ACLS | free_stat_x(&sx2); |
if (preserve_acls) | |
free_acl(&sx2); | |
#endif | |
#ifdef SUPPORT_XATTRS | |
if (preserve_xattrs) | |
free_xattr(&sx2); | |
#endif | |
} | |
return updated; |
return updated; |
} |
} |
|
|
RETSIGTYPE sig_int(UNUSED(int val)) | /* This is only called for SIGINT, SIGHUP, and SIGTERM. */ |
| RETSIGTYPE sig_int(int sig_num) |
{ |
{ |
/* KLUGE: if the user hits Ctrl-C while ssh is prompting |
/* KLUGE: if the user hits Ctrl-C while ssh is prompting |
* for a password, then our cleanup's sending of a SIGUSR1 |
* for a password, then our cleanup's sending of a SIGUSR1 |
Line 546 RETSIGTYPE sig_int(UNUSED(int val))
|
Line 612 RETSIGTYPE sig_int(UNUSED(int val))
|
* not ssh waiting for a password, then this tiny delay |
* not ssh waiting for a password, then this tiny delay |
* shouldn't hurt anything. */ |
* shouldn't hurt anything. */ |
msleep(400); |
msleep(400); |
|
|
|
/* If we're an rsync daemon listener (not a daemon server), |
|
* we'll exit with status 0 if we received SIGTERM. */ |
|
if (am_daemon && !am_server && sig_num == SIGTERM) |
|
exit_cleanup(0); |
|
|
|
/* If the signal arrived on the server side (or for the receiver |
|
* process on the client), we want to try to do a controlled shutdown |
|
* that lets the client side (generator process) know what happened. |
|
* To do this, we set a flag and let the normal process handle the |
|
* shutdown. We only attempt this if multiplexed IO is in effect and |
|
* we didn't already set the flag. */ |
|
if (!got_kill_signal && (am_server || am_receiver)) { |
|
got_kill_signal = sig_num; |
|
return; |
|
} |
|
|
exit_cleanup(RERR_SIGNAL); |
exit_cleanup(RERR_SIGNAL); |
} |
} |
|
|
Line 563 int finish_transfer(const char *fname, const char *fna
|
Line 646 int finish_transfer(const char *fname, const char *fna
|
const char *temp_copy_name = partialptr && *partialptr != '/' ? partialptr : NULL; |
const char *temp_copy_name = partialptr && *partialptr != '/' ? partialptr : NULL; |
|
|
if (inplace) { |
if (inplace) { |
if (verbose > 2) | if (DEBUG_GTE(RECV, 1)) |
rprintf(FINFO, "finishing %s\n", fname); |
rprintf(FINFO, "finishing %s\n", fname); |
fnametmp = fname; |
fnametmp = fname; |
goto do_set_file_attrs; |
goto do_set_file_attrs; |
} |
} |
|
|
if (make_backups > 0 && overwriting_basis) { |
if (make_backups > 0 && overwriting_basis) { |
if (!make_backup(fname)) | int ok = make_backup(fname, False); |
| if (!ok) |
return 1; |
return 1; |
if (fnamecmp == fname) | if (ok == 1 && fnamecmp == fname) |
fnamecmp = get_backup_name(fname); |
fnamecmp = get_backup_name(fname); |
} |
} |
|
|
Line 581 int finish_transfer(const char *fname, const char *fna
|
Line 665 int finish_transfer(const char *fname, const char *fna
|
ok_to_set_time ? 0 : ATTRS_SKIP_MTIME); |
ok_to_set_time ? 0 : ATTRS_SKIP_MTIME); |
|
|
/* move tmp file over real file */ |
/* move tmp file over real file */ |
if (verbose > 2) | if (DEBUG_GTE(RECV, 1)) |
rprintf(FINFO, "renaming %s to %s\n", fnametmp, fname); |
rprintf(FINFO, "renaming %s to %s\n", fnametmp, fname); |
ret = robust_rename(fnametmp, fname, temp_copy_name, | ret = robust_rename(fnametmp, fname, temp_copy_name, file->mode); |
file->mode & INITACCESSPERMS); | |
if (ret < 0) { |
if (ret < 0) { |
rsyserr(FERROR_XFER, errno, "%s %s -> \"%s\"", |
rsyserr(FERROR_XFER, errno, "%s %s -> \"%s\"", |
ret == -2 ? "copy" : "rename", |
ret == -2 ? "copy" : "rename", |
full_fname(fnametmp), fname); |
full_fname(fnametmp), fname); |
if (!partialptr || (ret == -2 && temp_copy_name) |
if (!partialptr || (ret == -2 && temp_copy_name) |
|| robust_rename(fnametmp, partialptr, NULL, | || robust_rename(fnametmp, partialptr, NULL, file->mode) < 0) |
file->mode & INITACCESSPERMS) < 0) | |
do_unlink(fnametmp); |
do_unlink(fnametmp); |
return 0; |
return 0; |
} |
} |