Annotation of embedaddon/rsync/rsync.c, revision 1.1.1.3
1.1 misho 1: /*
2: * Routines common to more than one of the rsync processes.
3: *
4: * Copyright (C) 1996 Andrew Tridgell
5: * Copyright (C) 1996 Paul Mackerras
1.1.1.3 ! misho 6: * Copyright (C) 2003-2015 Wayne Davison
1.1 misho 7: *
8: * This program is free software; you can redistribute it and/or modify
9: * it under the terms of the GNU General Public License as published by
10: * the Free Software Foundation; either version 3 of the License, or
11: * (at your option) any later version.
12: *
13: * This program is distributed in the hope that it will be useful,
14: * but WITHOUT ANY WARRANTY; without even the implied warranty of
15: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16: * GNU General Public License for more details.
17: *
18: * You should have received a copy of the GNU General Public License along
19: * with this program; if not, visit the http://fsf.org website.
20: */
21:
22: #include "rsync.h"
23: #include "ifuncs.h"
24: #if defined HAVE_LIBCHARSET_H && defined HAVE_LOCALE_CHARSET
25: #include <libcharset.h>
26: #elif defined HAVE_LANGINFO_H && defined HAVE_NL_LANGINFO
27: #include <langinfo.h>
28: #endif
29:
30: extern int dry_run;
31: extern int preserve_acls;
32: extern int preserve_xattrs;
33: extern int preserve_perms;
34: extern int preserve_executability;
35: extern int preserve_times;
36: extern int am_root;
37: extern int am_server;
1.1.1.2 misho 38: extern int am_daemon;
1.1 misho 39: extern int am_sender;
40: extern int am_receiver;
41: extern int am_generator;
42: extern int am_starting_up;
43: extern int allow_8bit_chars;
44: extern int protocol_version;
1.1.1.2 misho 45: extern int got_kill_signal;
1.1 misho 46: extern int inc_recurse;
47: extern int inplace;
48: extern int flist_eof;
1.1.1.2 misho 49: extern int file_old_total;
1.1 misho 50: extern int keep_dirlinks;
51: extern int make_backups;
52: extern struct file_list *cur_flist, *first_flist, *dir_flist;
53: extern struct chmod_mode_struct *daemon_chmod_modes;
54: #ifdef ICONV_OPTION
55: extern char *iconv_opt;
56: #endif
57:
58: #ifdef ICONV_CONST
59: iconv_t ic_chck = (iconv_t)-1;
60: # ifdef ICONV_OPTION
61: iconv_t ic_send = (iconv_t)-1, ic_recv = (iconv_t)-1;
62: # endif
63:
64: static const char *default_charset(void)
65: {
66: # if defined HAVE_LIBCHARSET_H && defined HAVE_LOCALE_CHARSET
67: return locale_charset();
68: # elif defined HAVE_LANGINFO_H && defined HAVE_NL_LANGINFO
69: return nl_langinfo(CODESET);
70: # else
71: return ""; /* Works with (at the very least) gnu iconv... */
72: # endif
73: }
74:
75: void setup_iconv(void)
76: {
77: const char *defset = default_charset();
78: # ifdef ICONV_OPTION
79: const char *charset;
80: char *cp;
81: # endif
82:
83: if (!am_server && !allow_8bit_chars) {
84: /* It's OK if this fails... */
85: ic_chck = iconv_open(defset, defset);
86:
1.1.1.2 misho 87: if (DEBUG_GTE(ICONV, 2)) {
1.1 misho 88: if (ic_chck == (iconv_t)-1) {
89: rprintf(FINFO,
1.1.1.2 misho 90: "msg checking via isprint()"
91: " (iconv_open(\"%s\", \"%s\") errno: %d)\n",
1.1 misho 92: defset, defset, errno);
93: } else {
94: rprintf(FINFO,
1.1.1.2 misho 95: "msg checking charset: %s\n",
96: defset);
1.1 misho 97: }
98: }
1.1.1.2 misho 99: } else
100: ic_chck = (iconv_t)-1;
1.1 misho 101:
102: # ifdef ICONV_OPTION
103: if (!iconv_opt)
104: return;
105:
106: if ((cp = strchr(iconv_opt, ',')) != NULL) {
107: if (am_server) /* A local transfer needs this. */
108: iconv_opt = cp + 1;
109: else
110: *cp = '\0';
111: }
112:
113: if (!*iconv_opt || (*iconv_opt == '.' && iconv_opt[1] == '\0'))
114: charset = defset;
115: else
116: charset = iconv_opt;
117:
118: if ((ic_send = iconv_open(UTF8_CHARSET, charset)) == (iconv_t)-1) {
119: rprintf(FERROR, "iconv_open(\"%s\", \"%s\") failed\n",
120: UTF8_CHARSET, charset);
121: exit_cleanup(RERR_UNSUPPORTED);
122: }
123:
124: if ((ic_recv = iconv_open(charset, UTF8_CHARSET)) == (iconv_t)-1) {
125: rprintf(FERROR, "iconv_open(\"%s\", \"%s\") failed\n",
126: charset, UTF8_CHARSET);
127: exit_cleanup(RERR_UNSUPPORTED);
128: }
129:
1.1.1.2 misho 130: if (DEBUG_GTE(ICONV, 1)) {
131: rprintf(FINFO, "[%s] charset: %s\n",
132: who_am_i(), *charset ? charset : "[LOCALE]");
1.1 misho 133: }
134: # endif
135: }
136:
1.1.1.2 misho 137: /* This function converts the chars in the "in" xbuf into characters in the
138: * "out" xbuf. The ".len" chars of the "in" xbuf is used starting from its
139: * ".pos". The ".size" of the "out" xbuf restricts how many characters can
140: * be stored, starting at its ".pos+.len" position. Note that the last byte
141: * of the "out" xbuf is not used, which reserves space for a trailing '\0'
142: * (though it is up to the caller to store a trailing '\0', as needed).
143: *
1.1 misho 144: * We return a 0 on success or a -1 on error. An error also sets errno to
145: * E2BIG, EILSEQ, or EINVAL (see below); otherwise errno will be set to 0.
1.1.1.2 misho 146: * The "in" xbuf is altered to update ".pos" and ".len". The "out" xbuf has
147: * data appended, and its ".len" incremented (see below for a ".size" note).
148: *
149: * If ICB_CIRCULAR_OUT is set in "flags", the chars going into the "out" xbuf
150: * can wrap around to the start, and the xbuf may have its ".size" reduced
151: * (presumably by 1 byte) if the iconv code doesn't have space to store a
152: * multi-byte character at the physical end of the ".buf" (though no reducing
153: * happens if ".pos" is <= 1, since there is no room to wrap around).
154: *
155: * If ICB_EXPAND_OUT is set in "flags", the "out" xbuf will be allocated if
156: * empty, and (as long as ICB_CIRCULAR_OUT is not set) expanded if too small.
157: * This prevents the return of E2BIG (except for a circular xbuf).
158: *
159: * If ICB_INCLUDE_BAD is set in "flags", any badly-encoded chars are included
160: * verbatim in the "out" xbuf, so EILSEQ will not be returned.
161: *
162: * If ICB_INCLUDE_INCOMPLETE is set in "flags", any incomplete multi-byte
163: * chars are included, which ensures that EINVAL is not returned.
164: *
165: * If ICB_INIT is set, the iconv() conversion state is initialized prior to
166: * processing the characters. */
1.1 misho 167: int iconvbufs(iconv_t ic, xbuf *in, xbuf *out, int flags)
168: {
169: ICONV_CONST char *ibuf;
1.1.1.2 misho 170: size_t icnt, ocnt, opos;
1.1 misho 171: char *obuf;
172:
1.1.1.2 misho 173: if (!out->size && flags & ICB_EXPAND_OUT) {
174: size_t siz = ROUND_UP_1024(in->len * 2);
175: alloc_xbuf(out, siz);
176: } else if (out->len+1 >= out->size) {
177: /* There is no room to even start storing data. */
178: if (!(flags & ICB_EXPAND_OUT) || flags & ICB_CIRCULAR_OUT) {
179: errno = E2BIG;
180: return -1;
181: }
182: realloc_xbuf(out, out->size + ROUND_UP_1024(in->len * 2));
183: }
1.1 misho 184:
1.1.1.2 misho 185: if (flags & ICB_INIT)
1.1 misho 186: iconv(ic, NULL, 0, NULL, 0);
187:
188: ibuf = in->buf + in->pos;
189: icnt = in->len;
190:
1.1.1.2 misho 191: opos = out->pos + out->len;
192: if (flags & ICB_CIRCULAR_OUT) {
193: if (opos >= out->size) {
194: opos -= out->size;
195: /* We know that out->pos is not 0 due to the "no room" check
196: * above, so this can't go "negative". */
197: ocnt = out->pos - opos - 1;
198: } else {
199: /* Allow the use of all bytes to the physical end of the buffer
200: * unless pos is 0, in which case we reserve our trailing '\0'. */
201: ocnt = out->size - opos - (out->pos ? 0 : 1);
202: }
203: } else
204: ocnt = out->size - opos - 1;
205: obuf = out->buf + opos;
1.1 misho 206:
207: while (icnt) {
208: while (iconv(ic, &ibuf, &icnt, &obuf, &ocnt) == (size_t)-1) {
209: if (errno == EINTR)
210: continue;
211: if (errno == EINVAL) {
212: if (!(flags & ICB_INCLUDE_INCOMPLETE))
213: goto finish;
1.1.1.2 misho 214: if (!ocnt)
215: goto e2big;
1.1 misho 216: } else if (errno == EILSEQ) {
217: if (!(flags & ICB_INCLUDE_BAD))
218: goto finish;
1.1.1.2 misho 219: if (!ocnt)
220: goto e2big;
221: } else if (errno == E2BIG) {
222: size_t siz;
223: e2big:
224: opos = obuf - out->buf;
225: if (flags & ICB_CIRCULAR_OUT && out->pos > 1 && opos > out->pos) {
226: /* We are in a divided circular buffer at the physical
227: * end with room to wrap to the start. If iconv() refused
228: * to use one or more trailing bytes in the buffer, we
229: * set the size to ignore the unused bytes. */
230: if (opos < out->size)
231: reduce_iobuf_size(out, opos);
232: obuf = out->buf;
233: ocnt = out->pos - 1;
234: continue;
235: }
236: if (!(flags & ICB_EXPAND_OUT) || flags & ICB_CIRCULAR_OUT) {
1.1 misho 237: errno = E2BIG;
238: goto finish;
239: }
1.1.1.2 misho 240: siz = ROUND_UP_1024(in->len * 2);
241: realloc_xbuf(out, out->size + siz);
1.1 misho 242: obuf = out->buf + opos;
1.1.1.2 misho 243: ocnt += siz;
1.1 misho 244: continue;
1.1.1.2 misho 245: } else {
246: rsyserr(FERROR, errno, "unexpected error from iconv()");
247: exit_cleanup(RERR_UNSUPPORTED);
1.1 misho 248: }
249: *obuf++ = *ibuf++;
250: ocnt--, icnt--;
1.1.1.2 misho 251: if (!icnt)
252: break;
1.1 misho 253: }
254: }
255:
256: errno = 0;
257:
258: finish:
1.1.1.2 misho 259: opos = obuf - out->buf;
260: if (flags & ICB_CIRCULAR_OUT && opos < out->pos)
261: opos += out->size;
262: out->len = opos - out->pos;
263:
1.1 misho 264: in->len = icnt;
265: in->pos = ibuf - in->buf;
266:
267: return errno ? -1 : 0;
268: }
269: #endif
270:
271: void send_protected_args(int fd, char *args[])
272: {
273: int i;
274: #ifdef ICONV_OPTION
275: int convert = ic_send != (iconv_t)-1;
276: xbuf outbuf, inbuf;
277:
278: if (convert)
279: alloc_xbuf(&outbuf, 1024);
280: #endif
281:
282: for (i = 0; args[i]; i++) {} /* find first NULL */
283: args[i] = "rsync"; /* set a new arg0 */
1.1.1.2 misho 284: if (DEBUG_GTE(CMD, 1))
1.1 misho 285: print_child_argv("protected args:", args + i + 1);
286: do {
287: if (!args[i][0])
288: write_buf(fd, ".", 2);
289: #ifdef ICONV_OPTION
290: else if (convert) {
291: INIT_XBUF_STRLEN(inbuf, args[i]);
292: iconvbufs(ic_send, &inbuf, &outbuf,
1.1.1.2 misho 293: ICB_EXPAND_OUT | ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE | ICB_INIT);
1.1 misho 294: outbuf.buf[outbuf.len] = '\0';
295: write_buf(fd, outbuf.buf, outbuf.len + 1);
296: outbuf.len = 0;
297: }
298: #endif
299: else
300: write_buf(fd, args[i], strlen(args[i]) + 1);
301: } while (args[++i]);
302: write_byte(fd, 0);
303:
304: #ifdef ICONV_OPTION
305: if (convert)
306: free(outbuf.buf);
307: #endif
308: }
309:
1.1.1.2 misho 310: int read_ndx_and_attrs(int f_in, int f_out, int *iflag_ptr, uchar *type_ptr,
1.1 misho 311: char *buf, int *len_ptr)
312: {
313: int len, iflags = 0;
314: struct file_list *flist;
315: uchar fnamecmp_type = FNAMECMP_FNAME;
1.1.1.2 misho 316: int ndx;
1.1 misho 317:
318: read_loop:
319: while (1) {
320: ndx = read_ndx(f_in);
321:
322: if (ndx >= 0)
323: break;
324: if (ndx == NDX_DONE)
325: return ndx;
1.1.1.2 misho 326: if (ndx == NDX_DEL_STATS) {
327: read_del_stats(f_in);
328: if (am_sender && am_server)
329: write_del_stats(f_out);
330: continue;
331: }
1.1 misho 332: if (!inc_recurse || am_sender) {
333: int last;
334: if (first_flist)
335: last = first_flist->prev->ndx_start + first_flist->prev->used - 1;
336: else
337: last = -1;
338: rprintf(FERROR,
339: "Invalid file index: %d (%d - %d) [%s]\n",
340: ndx, NDX_DONE, last, who_am_i());
341: exit_cleanup(RERR_PROTOCOL);
342: }
343: if (ndx == NDX_FLIST_EOF) {
344: flist_eof = 1;
1.1.1.2 misho 345: if (DEBUG_GTE(FLIST, 3))
346: rprintf(FINFO, "[%s] flist_eof=1\n", who_am_i());
347: write_int(f_out, NDX_FLIST_EOF);
1.1 misho 348: continue;
349: }
350: ndx = NDX_FLIST_OFFSET - ndx;
351: if (ndx < 0 || ndx >= dir_flist->used) {
352: ndx = NDX_FLIST_OFFSET - ndx;
353: rprintf(FERROR,
354: "Invalid dir index: %d (%d - %d) [%s]\n",
355: ndx, NDX_FLIST_OFFSET,
356: NDX_FLIST_OFFSET - dir_flist->used + 1,
357: who_am_i());
358: exit_cleanup(RERR_PROTOCOL);
359: }
360:
1.1.1.2 misho 361: if (DEBUG_GTE(FLIST, 2)) {
1.1 misho 362: rprintf(FINFO, "[%s] receiving flist for dir %d\n",
363: who_am_i(), ndx);
364: }
1.1.1.2 misho 365: /* Send all the data we read for this flist to the generator. */
366: start_flist_forward(ndx);
1.1.1.3 ! misho 367: flist = recv_file_list(f_in, ndx);
1.1 misho 368: flist->parent_ndx = ndx;
369: stop_flist_forward();
370: }
371:
372: iflags = protocol_version >= 29 ? read_shortint(f_in)
373: : ITEM_TRANSFER | ITEM_MISSING_DATA;
374:
375: /* Support the protocol-29 keep-alive style. */
376: if (protocol_version < 30 && ndx == cur_flist->used && iflags == ITEM_IS_NEW) {
377: if (am_sender)
1.1.1.2 misho 378: maybe_send_keepalive(time(NULL), MSK_ALLOW_FLUSH);
1.1 misho 379: goto read_loop;
380: }
381:
1.1.1.2 misho 382: flist = flist_for_ndx(ndx, "read_ndx_and_attrs");
383: if (flist != cur_flist) {
384: cur_flist = flist;
385: if (am_sender) {
386: file_old_total = cur_flist->used;
387: for (flist = first_flist; flist != cur_flist; flist = flist->next)
388: file_old_total += flist->used;
389: }
390: }
1.1 misho 391:
392: if (iflags & ITEM_BASIS_TYPE_FOLLOWS)
393: fnamecmp_type = read_byte(f_in);
394: *type_ptr = fnamecmp_type;
395:
396: if (iflags & ITEM_XNAME_FOLLOWS) {
397: if ((len = read_vstring(f_in, buf, MAXPATHLEN)) < 0)
398: exit_cleanup(RERR_PROTOCOL);
399: } else {
400: *buf = '\0';
401: len = -1;
402: }
403: *len_ptr = len;
404:
405: if (iflags & ITEM_TRANSFER) {
406: int i = ndx - cur_flist->ndx_start;
407: if (i < 0 || !S_ISREG(cur_flist->files[i]->mode)) {
408: rprintf(FERROR,
409: "received request to transfer non-regular file: %d [%s]\n",
410: ndx, who_am_i());
411: exit_cleanup(RERR_PROTOCOL);
412: }
413: }
414:
415: *iflag_ptr = iflags;
416: return ndx;
417: }
418:
419: /*
420: free a sums struct
421: */
422: void free_sums(struct sum_struct *s)
423: {
424: if (s->sums) free(s->sums);
425: free(s);
426: }
427:
428: /* This is only called when we aren't preserving permissions. Figure out what
429: * the permissions should be and return them merged back into the mode. */
430: mode_t dest_mode(mode_t flist_mode, mode_t stat_mode, int dflt_perms,
431: int exists)
432: {
433: int new_mode;
434: /* If the file already exists, we'll return the local permissions,
435: * possibly tweaked by the --executability option. */
436: if (exists) {
437: new_mode = (flist_mode & ~CHMOD_BITS) | (stat_mode & CHMOD_BITS);
438: if (preserve_executability && S_ISREG(flist_mode)) {
439: /* If the source file is executable, grant execute
440: * rights to everyone who can read, but ONLY if the
441: * file isn't already executable. */
442: if (!(flist_mode & 0111))
443: new_mode &= ~0111;
444: else if (!(stat_mode & 0111))
445: new_mode |= (new_mode & 0444) >> 2;
446: }
447: } else {
448: /* Apply destination default permissions and turn
449: * off special permissions. */
450: new_mode = flist_mode & (~CHMOD_BITS | dflt_perms);
451: }
452: return new_mode;
453: }
454:
455: int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
456: const char *fnamecmp, int flags)
457: {
458: int updated = 0;
459: stat_x sx2;
460: int change_uid, change_gid;
461: mode_t new_mode = file->mode;
462: int inherit;
463:
464: if (!sxp) {
465: if (dry_run)
466: return 1;
467: if (link_stat(fname, &sx2.st, 0) < 0) {
468: rsyserr(FERROR_XFER, errno, "stat %s failed",
469: full_fname(fname));
470: return 0;
471: }
1.1.1.2 misho 472: init_stat_x(&sx2);
1.1 misho 473: sxp = &sx2;
474: inherit = !preserve_perms;
475: } else
476: inherit = !preserve_perms && file->flags & FLAG_DIR_CREATED;
477:
478: if (inherit && S_ISDIR(new_mode) && sxp->st.st_mode & S_ISGID) {
479: /* We just created this directory and its setgid
480: * bit is on, so make sure it stays on. */
481: new_mode |= S_ISGID;
482: }
483:
484: if (daemon_chmod_modes && !S_ISLNK(new_mode))
485: new_mode = tweak_mode(new_mode, daemon_chmod_modes);
486:
487: #ifdef SUPPORT_ACLS
488: if (preserve_acls && !S_ISLNK(file->mode) && !ACL_READY(*sxp))
489: get_acl(fname, sxp);
490: #endif
491:
492: change_uid = am_root && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file);
493: change_gid = gid_ndx && !(file->flags & FLAG_SKIP_GROUP)
494: && sxp->st.st_gid != (gid_t)F_GROUP(file);
495: #ifndef CAN_CHOWN_SYMLINK
496: if (S_ISLNK(sxp->st.st_mode)) {
497: ;
498: } else
499: #endif
500: if (change_uid || change_gid) {
1.1.1.2 misho 501: if (DEBUG_GTE(OWN, 1)) {
1.1 misho 502: if (change_uid) {
503: rprintf(FINFO,
504: "set uid of %s from %u to %u\n",
505: fname, (unsigned)sxp->st.st_uid, F_OWNER(file));
506: }
507: if (change_gid) {
508: rprintf(FINFO,
509: "set gid of %s from %u to %u\n",
510: fname, (unsigned)sxp->st.st_gid, F_GROUP(file));
511: }
512: }
513: if (am_root >= 0) {
514: uid_t uid = change_uid ? (uid_t)F_OWNER(file) : sxp->st.st_uid;
515: gid_t gid = change_gid ? (gid_t)F_GROUP(file) : sxp->st.st_gid;
516: if (do_lchown(fname, uid, gid) != 0) {
517: /* We shouldn't have attempted to change uid
518: * or gid unless have the privilege. */
519: rsyserr(FERROR_XFER, errno, "%s %s failed",
520: change_uid ? "chown" : "chgrp",
521: full_fname(fname));
522: goto cleanup;
523: }
524: if (uid == (uid_t)-1 && sxp->st.st_uid != (uid_t)-1)
525: rprintf(FERROR_XFER, "uid 4294967295 (-1) is impossible to set on %s\n", full_fname(fname));
526: if (gid == (gid_t)-1 && sxp->st.st_gid != (gid_t)-1)
527: rprintf(FERROR_XFER, "gid 4294967295 (-1) is impossible to set on %s\n", full_fname(fname));
528: /* A lchown had been done, so we need to re-stat if
529: * the destination had the setuid or setgid bits set
530: * (due to the side effect of the chown call). */
531: if (sxp->st.st_mode & (S_ISUID | S_ISGID)) {
532: link_stat(fname, &sxp->st,
533: keep_dirlinks && S_ISDIR(sxp->st.st_mode));
534: }
535: }
536: updated = 1;
537: }
538:
1.1.1.3 ! misho 539: #ifdef SUPPORT_XATTRS
! 540: if (am_root < 0)
! 541: set_stat_xattr(fname, file, new_mode);
! 542: if (preserve_xattrs && fnamecmp)
! 543: set_xattr(fname, file, fnamecmp, sxp);
! 544: #endif
! 545:
! 546: if (!preserve_times
! 547: || (!(preserve_times & PRESERVE_DIR_TIMES) && S_ISDIR(sxp->st.st_mode))
! 548: || (!(preserve_times & PRESERVE_LINK_TIMES) && S_ISLNK(sxp->st.st_mode)))
! 549: flags |= ATTRS_SKIP_MTIME;
! 550: if (!(flags & ATTRS_SKIP_MTIME)
! 551: && (sxp->st.st_mtime != file->modtime
! 552: #ifdef ST_MTIME_NSEC
! 553: || (NSEC_BUMP(file) && (uint32)sxp->st.ST_MTIME_NSEC != F_MOD_NSEC(file))
! 554: #endif
! 555: )) {
! 556: int ret = set_modtime(fname, file->modtime, F_MOD_NSEC(file), sxp->st.st_mode);
! 557: if (ret < 0) {
! 558: rsyserr(FERROR_XFER, errno, "failed to set times on %s",
! 559: full_fname(fname));
! 560: goto cleanup;
! 561: }
! 562: if (ret == 0) /* ret == 1 if symlink could not be set */
1.1 misho 563: updated = 1;
1.1.1.3 ! misho 564: else
! 565: file->flags |= FLAG_TIME_FAILED;
1.1 misho 566: }
567:
568: #ifdef HAVE_CHMOD
569: if (!BITS_EQUAL(sxp->st.st_mode, new_mode, CHMOD_BITS)) {
570: int ret = am_root < 0 ? 0 : do_chmod(fname, new_mode);
571: if (ret < 0) {
572: rsyserr(FERROR_XFER, errno,
573: "failed to set permissions on %s",
574: full_fname(fname));
575: goto cleanup;
576: }
577: if (ret == 0) /* ret == 1 if symlink could not be set */
578: updated = 1;
579: }
580: #endif
581:
1.1.1.3 ! misho 582: #ifdef SUPPORT_ACLS
! 583: /* It's OK to call set_acl() now, even for a dir, as the generator
! 584: * will enable owner-writability using chmod, if necessary.
! 585: *
! 586: * If set_acl() changes permission bits in the process of setting
! 587: * an access ACL, it changes sxp->st.st_mode so we know whether we
! 588: * need to chmod(). */
! 589: if (preserve_acls && !S_ISLNK(new_mode)) {
! 590: if (set_acl(fname, file, sxp, new_mode) > 0)
! 591: updated = 1;
! 592: }
! 593: #endif
! 594:
1.1.1.2 misho 595: if (INFO_GTE(NAME, 2) && flags & ATTRS_REPORT) {
1.1 misho 596: if (updated)
597: rprintf(FCLIENT, "%s\n", fname);
598: else
599: rprintf(FCLIENT, "%s is uptodate\n", fname);
600: }
601: cleanup:
1.1.1.2 misho 602: if (sxp == &sx2)
603: free_stat_x(&sx2);
1.1 misho 604: return updated;
605: }
606:
1.1.1.2 misho 607: /* This is only called for SIGINT, SIGHUP, and SIGTERM. */
1.1.1.3 ! misho 608: void sig_int(int sig_num)
1.1 misho 609: {
610: /* KLUGE: if the user hits Ctrl-C while ssh is prompting
611: * for a password, then our cleanup's sending of a SIGUSR1
612: * signal to all our children may kill ssh before it has a
613: * chance to restore the tty settings (i.e. turn echo back
614: * on). By sleeping for a short time, ssh gets a bigger
615: * chance to do the right thing. If child processes are
616: * not ssh waiting for a password, then this tiny delay
617: * shouldn't hurt anything. */
618: msleep(400);
1.1.1.2 misho 619:
620: /* If we're an rsync daemon listener (not a daemon server),
621: * we'll exit with status 0 if we received SIGTERM. */
622: if (am_daemon && !am_server && sig_num == SIGTERM)
623: exit_cleanup(0);
624:
625: /* If the signal arrived on the server side (or for the receiver
626: * process on the client), we want to try to do a controlled shutdown
627: * that lets the client side (generator process) know what happened.
628: * To do this, we set a flag and let the normal process handle the
629: * shutdown. We only attempt this if multiplexed IO is in effect and
630: * we didn't already set the flag. */
631: if (!got_kill_signal && (am_server || am_receiver)) {
632: got_kill_signal = sig_num;
633: return;
634: }
635:
1.1 misho 636: exit_cleanup(RERR_SIGNAL);
637: }
638:
639: /* Finish off a file transfer: renaming the file and setting the file's
640: * attributes (e.g. permissions, ownership, etc.). If the robust_rename()
641: * call is forced to copy the temp file and partialptr is both non-NULL and
642: * not an absolute path, we stage the file into the partial-dir and then
643: * rename it into place. This returns 1 on succcess or 0 on failure. */
644: int finish_transfer(const char *fname, const char *fnametmp,
645: const char *fnamecmp, const char *partialptr,
646: struct file_struct *file, int ok_to_set_time,
647: int overwriting_basis)
648: {
649: int ret;
650: const char *temp_copy_name = partialptr && *partialptr != '/' ? partialptr : NULL;
651:
652: if (inplace) {
1.1.1.2 misho 653: if (DEBUG_GTE(RECV, 1))
1.1 misho 654: rprintf(FINFO, "finishing %s\n", fname);
655: fnametmp = fname;
656: goto do_set_file_attrs;
657: }
658:
659: if (make_backups > 0 && overwriting_basis) {
1.1.1.2 misho 660: int ok = make_backup(fname, False);
661: if (!ok)
1.1 misho 662: return 1;
1.1.1.2 misho 663: if (ok == 1 && fnamecmp == fname)
1.1 misho 664: fnamecmp = get_backup_name(fname);
665: }
666:
667: /* Change permissions before putting the file into place. */
668: set_file_attrs(fnametmp, file, NULL, fnamecmp,
669: ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);
670:
671: /* move tmp file over real file */
1.1.1.2 misho 672: if (DEBUG_GTE(RECV, 1))
1.1 misho 673: rprintf(FINFO, "renaming %s to %s\n", fnametmp, fname);
1.1.1.2 misho 674: ret = robust_rename(fnametmp, fname, temp_copy_name, file->mode);
1.1 misho 675: if (ret < 0) {
676: rsyserr(FERROR_XFER, errno, "%s %s -> \"%s\"",
677: ret == -2 ? "copy" : "rename",
678: full_fname(fnametmp), fname);
679: if (!partialptr || (ret == -2 && temp_copy_name)
1.1.1.2 misho 680: || robust_rename(fnametmp, partialptr, NULL, file->mode) < 0)
1.1 misho 681: do_unlink(fnametmp);
682: return 0;
683: }
684: if (ret == 0) {
685: /* The file was moved into place (not copied), so it's done. */
686: return 1;
687: }
688: /* The file was copied, so tweak the perms of the copied file. If it
689: * was copied to partialptr, move it into its final destination. */
690: fnametmp = temp_copy_name ? temp_copy_name : fname;
691:
692: do_set_file_attrs:
693: set_file_attrs(fnametmp, file, NULL, fnamecmp,
694: ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);
695:
696: if (temp_copy_name) {
697: if (do_rename(fnametmp, fname) < 0) {
698: rsyserr(FERROR_XFER, errno, "rename %s -> \"%s\"",
699: full_fname(fnametmp), fname);
700: return 0;
701: }
702: handle_partial_dir(temp_copy_name, PDIR_DELETE);
703: }
704: return 1;
705: }
706:
707: struct file_list *flist_for_ndx(int ndx, const char *fatal_error_loc)
708: {
709: struct file_list *flist = cur_flist;
710:
711: if (!flist && !(flist = first_flist))
712: goto not_found;
713:
714: while (ndx < flist->ndx_start-1) {
715: if (flist == first_flist)
716: goto not_found;
717: flist = flist->prev;
718: }
719: while (ndx >= flist->ndx_start + flist->used) {
720: if (!(flist = flist->next))
721: goto not_found;
722: }
723: return flist;
724:
725: not_found:
726: if (fatal_error_loc) {
727: int first, last;
728: if (first_flist) {
729: first = first_flist->ndx_start - 1;
730: last = first_flist->prev->ndx_start + first_flist->prev->used - 1;
731: } else {
732: first = 0;
733: last = -1;
734: }
735: rprintf(FERROR,
736: "File-list index %d not in %d - %d (%s) [%s]\n",
737: ndx, first, last, fatal_error_loc, who_am_i());
738: exit_cleanup(RERR_PROTOCOL);
739: }
740: return NULL;
741: }
742:
743: const char *who_am_i(void)
744: {
745: if (am_starting_up)
746: return am_server ? "server" : "client";
747: return am_sender ? "sender"
748: : am_generator ? "generator"
749: : am_receiver ? "receiver"
750: : "Receiver"; /* pre-forked receiver */
751: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>