Annotation of embedaddon/rsync/rsync.c, revision 1.1.1.2

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.2 ! misho       6:  * Copyright (C) 2003-2013 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       misho     367:                flist = recv_file_list(f_in);
                    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: #ifdef SUPPORT_XATTRS
                    493:        if (am_root < 0)
                    494:                set_stat_xattr(fname, file, new_mode);
                    495:        if (preserve_xattrs && fnamecmp)
                    496:                set_xattr(fname, file, fnamecmp, sxp);
                    497: #endif
                    498: 
                    499:        if (!preserve_times
                    500:         || (!(preserve_times & PRESERVE_DIR_TIMES) && S_ISDIR(sxp->st.st_mode))
                    501:         || (!(preserve_times & PRESERVE_LINK_TIMES) && S_ISLNK(sxp->st.st_mode)))
                    502:                flags |= ATTRS_SKIP_MTIME;
                    503:        if (!(flags & ATTRS_SKIP_MTIME)
                    504:            && cmp_time(sxp->st.st_mtime, file->modtime) != 0) {
1.1.1.2 ! misho     505:                int ret = set_modtime(fname, file->modtime, F_MOD_NSEC(file), sxp->st.st_mode);
1.1       misho     506:                if (ret < 0) {
                    507:                        rsyserr(FERROR_XFER, errno, "failed to set times on %s",
                    508:                                full_fname(fname));
                    509:                        goto cleanup;
                    510:                }
                    511:                if (ret == 0) /* ret == 1 if symlink could not be set */
                    512:                        updated = 1;
                    513:                else
                    514:                        file->flags |= FLAG_TIME_FAILED;
                    515:        }
                    516: 
                    517:        change_uid = am_root && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file);
                    518:        change_gid = gid_ndx && !(file->flags & FLAG_SKIP_GROUP)
                    519:                  && sxp->st.st_gid != (gid_t)F_GROUP(file);
                    520: #ifndef CAN_CHOWN_SYMLINK
                    521:        if (S_ISLNK(sxp->st.st_mode)) {
                    522:                ;
                    523:        } else
                    524: #endif
                    525:        if (change_uid || change_gid) {
1.1.1.2 ! misho     526:                if (DEBUG_GTE(OWN, 1)) {
1.1       misho     527:                        if (change_uid) {
                    528:                                rprintf(FINFO,
                    529:                                        "set uid of %s from %u to %u\n",
                    530:                                        fname, (unsigned)sxp->st.st_uid, F_OWNER(file));
                    531:                        }
                    532:                        if (change_gid) {
                    533:                                rprintf(FINFO,
                    534:                                        "set gid of %s from %u to %u\n",
                    535:                                        fname, (unsigned)sxp->st.st_gid, F_GROUP(file));
                    536:                        }
                    537:                }
                    538:                if (am_root >= 0) {
                    539:                        uid_t uid = change_uid ? (uid_t)F_OWNER(file) : sxp->st.st_uid;
                    540:                        gid_t gid = change_gid ? (gid_t)F_GROUP(file) : sxp->st.st_gid;
                    541:                        if (do_lchown(fname, uid, gid) != 0) {
                    542:                                /* We shouldn't have attempted to change uid
                    543:                                 * or gid unless have the privilege. */
                    544:                                rsyserr(FERROR_XFER, errno, "%s %s failed",
                    545:                                    change_uid ? "chown" : "chgrp",
                    546:                                    full_fname(fname));
                    547:                                goto cleanup;
                    548:                        }
                    549:                        if (uid == (uid_t)-1 && sxp->st.st_uid != (uid_t)-1)
                    550:                                rprintf(FERROR_XFER, "uid 4294967295 (-1) is impossible to set on %s\n", full_fname(fname));
                    551:                        if (gid == (gid_t)-1 && sxp->st.st_gid != (gid_t)-1)
                    552:                                rprintf(FERROR_XFER, "gid 4294967295 (-1) is impossible to set on %s\n", full_fname(fname));
                    553:                        /* A lchown had been done, so we need to re-stat if
                    554:                         * the destination had the setuid or setgid bits set
                    555:                         * (due to the side effect of the chown call). */
                    556:                        if (sxp->st.st_mode & (S_ISUID | S_ISGID)) {
                    557:                                link_stat(fname, &sxp->st,
                    558:                                          keep_dirlinks && S_ISDIR(sxp->st.st_mode));
                    559:                        }
                    560:                }
                    561:                updated = 1;
                    562:        }
                    563: 
                    564: #ifdef SUPPORT_ACLS
                    565:        /* It's OK to call set_acl() now, even for a dir, as the generator
                    566:         * will enable owner-writability using chmod, if necessary.
                    567:         * 
                    568:         * If set_acl() changes permission bits in the process of setting
                    569:         * an access ACL, it changes sxp->st.st_mode so we know whether we
                    570:         * need to chmod(). */
                    571:        if (preserve_acls && !S_ISLNK(new_mode)) {
                    572:                if (set_acl(fname, file, sxp, new_mode) > 0)
                    573:                        updated = 1;
                    574:        }
                    575: #endif
                    576: 
                    577: #ifdef HAVE_CHMOD
                    578:        if (!BITS_EQUAL(sxp->st.st_mode, new_mode, CHMOD_BITS)) {
                    579:                int ret = am_root < 0 ? 0 : do_chmod(fname, new_mode);
                    580:                if (ret < 0) {
                    581:                        rsyserr(FERROR_XFER, errno,
                    582:                                "failed to set permissions on %s",
                    583:                                full_fname(fname));
                    584:                        goto cleanup;
                    585:                }
                    586:                if (ret == 0) /* ret == 1 if symlink could not be set */
                    587:                        updated = 1;
                    588:        }
                    589: #endif
                    590: 
1.1.1.2 ! misho     591:        if (INFO_GTE(NAME, 2) && flags & ATTRS_REPORT) {
1.1       misho     592:                if (updated)
                    593:                        rprintf(FCLIENT, "%s\n", fname);
                    594:                else
                    595:                        rprintf(FCLIENT, "%s is uptodate\n", fname);
                    596:        }
                    597:   cleanup:
1.1.1.2 ! misho     598:        if (sxp == &sx2)
        !           599:                free_stat_x(&sx2);
1.1       misho     600:        return updated;
                    601: }
                    602: 
1.1.1.2 ! misho     603: /* This is only called for SIGINT, SIGHUP, and SIGTERM. */
        !           604: RETSIGTYPE sig_int(int sig_num)
1.1       misho     605: {
                    606:        /* KLUGE: if the user hits Ctrl-C while ssh is prompting
                    607:         * for a password, then our cleanup's sending of a SIGUSR1
                    608:         * signal to all our children may kill ssh before it has a
                    609:         * chance to restore the tty settings (i.e. turn echo back
                    610:         * on).  By sleeping for a short time, ssh gets a bigger
                    611:         * chance to do the right thing.  If child processes are
                    612:         * not ssh waiting for a password, then this tiny delay
                    613:         * shouldn't hurt anything. */
                    614:        msleep(400);
1.1.1.2 ! misho     615: 
        !           616:        /* If we're an rsync daemon listener (not a daemon server),
        !           617:         * we'll exit with status 0 if we received SIGTERM. */
        !           618:        if (am_daemon && !am_server && sig_num == SIGTERM)
        !           619:                exit_cleanup(0);
        !           620: 
        !           621:        /* If the signal arrived on the server side (or for the receiver
        !           622:         * process on the client), we want to try to do a controlled shutdown
        !           623:         * that lets the client side (generator process) know what happened.
        !           624:         * To do this, we set a flag and let the normal process handle the
        !           625:         * shutdown.  We only attempt this if multiplexed IO is in effect and
        !           626:         * we didn't already set the flag. */
        !           627:        if (!got_kill_signal && (am_server || am_receiver)) {
        !           628:                got_kill_signal = sig_num;
        !           629:                return;
        !           630:        }
        !           631: 
1.1       misho     632:        exit_cleanup(RERR_SIGNAL);
                    633: }
                    634: 
                    635: /* Finish off a file transfer: renaming the file and setting the file's
                    636:  * attributes (e.g. permissions, ownership, etc.).  If the robust_rename()
                    637:  * call is forced to copy the temp file and partialptr is both non-NULL and
                    638:  * not an absolute path, we stage the file into the partial-dir and then
                    639:  * rename it into place.  This returns 1 on succcess or 0 on failure. */
                    640: int finish_transfer(const char *fname, const char *fnametmp,
                    641:                    const char *fnamecmp, const char *partialptr,
                    642:                    struct file_struct *file, int ok_to_set_time,
                    643:                    int overwriting_basis)
                    644: {
                    645:        int ret;
                    646:        const char *temp_copy_name = partialptr && *partialptr != '/' ? partialptr : NULL;
                    647: 
                    648:        if (inplace) {
1.1.1.2 ! misho     649:                if (DEBUG_GTE(RECV, 1))
1.1       misho     650:                        rprintf(FINFO, "finishing %s\n", fname);
                    651:                fnametmp = fname;
                    652:                goto do_set_file_attrs;
                    653:        }
                    654: 
                    655:        if (make_backups > 0 && overwriting_basis) {
1.1.1.2 ! misho     656:                int ok = make_backup(fname, False);
        !           657:                if (!ok)
1.1       misho     658:                        return 1;
1.1.1.2 ! misho     659:                if (ok == 1 && fnamecmp == fname)
1.1       misho     660:                        fnamecmp = get_backup_name(fname);
                    661:        }
                    662: 
                    663:        /* Change permissions before putting the file into place. */
                    664:        set_file_attrs(fnametmp, file, NULL, fnamecmp,
                    665:                       ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);
                    666: 
                    667:        /* move tmp file over real file */
1.1.1.2 ! misho     668:        if (DEBUG_GTE(RECV, 1))
1.1       misho     669:                rprintf(FINFO, "renaming %s to %s\n", fnametmp, fname);
1.1.1.2 ! misho     670:        ret = robust_rename(fnametmp, fname, temp_copy_name, file->mode);
1.1       misho     671:        if (ret < 0) {
                    672:                rsyserr(FERROR_XFER, errno, "%s %s -> \"%s\"",
                    673:                        ret == -2 ? "copy" : "rename",
                    674:                        full_fname(fnametmp), fname);
                    675:                if (!partialptr || (ret == -2 && temp_copy_name)
1.1.1.2 ! misho     676:                 || robust_rename(fnametmp, partialptr, NULL, file->mode) < 0)
1.1       misho     677:                        do_unlink(fnametmp);
                    678:                return 0;
                    679:        }
                    680:        if (ret == 0) {
                    681:                /* The file was moved into place (not copied), so it's done. */
                    682:                return 1;
                    683:        }
                    684:        /* The file was copied, so tweak the perms of the copied file.  If it
                    685:         * was copied to partialptr, move it into its final destination. */
                    686:        fnametmp = temp_copy_name ? temp_copy_name : fname;
                    687: 
                    688:   do_set_file_attrs:
                    689:        set_file_attrs(fnametmp, file, NULL, fnamecmp,
                    690:                       ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);
                    691: 
                    692:        if (temp_copy_name) {
                    693:                if (do_rename(fnametmp, fname) < 0) {
                    694:                        rsyserr(FERROR_XFER, errno, "rename %s -> \"%s\"",
                    695:                                full_fname(fnametmp), fname);
                    696:                        return 0;
                    697:                }
                    698:                handle_partial_dir(temp_copy_name, PDIR_DELETE);
                    699:        }
                    700:        return 1;
                    701: }
                    702: 
                    703: struct file_list *flist_for_ndx(int ndx, const char *fatal_error_loc)
                    704: {
                    705:        struct file_list *flist = cur_flist;
                    706: 
                    707:        if (!flist && !(flist = first_flist))
                    708:                goto not_found;
                    709: 
                    710:        while (ndx < flist->ndx_start-1) {
                    711:                if (flist == first_flist)
                    712:                        goto not_found;
                    713:                flist = flist->prev;
                    714:        }
                    715:        while (ndx >= flist->ndx_start + flist->used) {
                    716:                if (!(flist = flist->next))
                    717:                        goto not_found;
                    718:        }
                    719:        return flist;
                    720: 
                    721:   not_found:
                    722:        if (fatal_error_loc) {
                    723:                int first, last;
                    724:                if (first_flist) {
                    725:                        first = first_flist->ndx_start - 1;
                    726:                        last = first_flist->prev->ndx_start + first_flist->prev->used - 1;
                    727:                } else {
                    728:                        first = 0;
                    729:                        last = -1;
                    730:                }
                    731:                rprintf(FERROR,
                    732:                        "File-list index %d not in %d - %d (%s) [%s]\n",
                    733:                        ndx, first, last, fatal_error_loc, who_am_i());
                    734:                exit_cleanup(RERR_PROTOCOL);
                    735:        }
                    736:        return NULL;
                    737: }
                    738: 
                    739: const char *who_am_i(void)
                    740: {
                    741:        if (am_starting_up)
                    742:                return am_server ? "server" : "client";
                    743:        return am_sender ? "sender"
                    744:             : am_generator ? "generator"
                    745:             : am_receiver ? "receiver"
                    746:             : "Receiver"; /* pre-forked receiver */
                    747: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>