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>