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

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
                      6:  * Copyright (C) 2003-2009 Wayne Davison
                      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 verbose;
                     31: extern int dry_run;
                     32: extern int preserve_acls;
                     33: extern int preserve_xattrs;
                     34: extern int preserve_perms;
                     35: extern int preserve_executability;
                     36: extern int preserve_times;
                     37: extern int am_root;
                     38: extern int am_server;
                     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;
                     45: extern int inc_recurse;
                     46: extern int inplace;
                     47: extern int flist_eof;
                     48: extern int keep_dirlinks;
                     49: extern int make_backups;
                     50: extern struct file_list *cur_flist, *first_flist, *dir_flist;
                     51: extern struct chmod_mode_struct *daemon_chmod_modes;
                     52: #ifdef ICONV_OPTION
                     53: extern char *iconv_opt;
                     54: #endif
                     55: 
                     56: #ifdef ICONV_CONST
                     57: iconv_t ic_chck = (iconv_t)-1;
                     58: # ifdef ICONV_OPTION
                     59: iconv_t ic_send = (iconv_t)-1, ic_recv = (iconv_t)-1;
                     60: # endif
                     61: 
                     62: static const char *default_charset(void)
                     63: {
                     64: # if defined HAVE_LIBCHARSET_H && defined HAVE_LOCALE_CHARSET
                     65:        return locale_charset();
                     66: # elif defined HAVE_LANGINFO_H && defined HAVE_NL_LANGINFO
                     67:        return nl_langinfo(CODESET);
                     68: # else
                     69:        return ""; /* Works with (at the very least) gnu iconv... */
                     70: # endif
                     71: }
                     72: 
                     73: void setup_iconv(void)
                     74: {
                     75:        const char *defset = default_charset();
                     76: # ifdef ICONV_OPTION
                     77:        const char *charset;
                     78:        char *cp;
                     79: # endif
                     80: 
                     81:        if (!am_server && !allow_8bit_chars) {
                     82:                /* It's OK if this fails... */
                     83:                ic_chck = iconv_open(defset, defset);
                     84: 
                     85:                if (verbose > 3) {
                     86:                        if (ic_chck == (iconv_t)-1) {
                     87:                                rprintf(FINFO,
                     88:                                        "note: iconv_open(\"%s\", \"%s\") failed (%d)"
                     89:                                        " -- using isprint() instead of iconv().\n",
                     90:                                        defset, defset, errno);
                     91:                        } else {
                     92:                                rprintf(FINFO,
                     93:                                        "note: iconv_open(\"%s\", \"%s\") succeeded.\n",
                     94:                                        defset, defset);
                     95:                        }
                     96:                }
                     97:        }
                     98: 
                     99: # ifdef ICONV_OPTION
                    100:        if (!iconv_opt)
                    101:                return;
                    102: 
                    103:        if ((cp = strchr(iconv_opt, ',')) != NULL) {
                    104:                if (am_server) /* A local transfer needs this. */
                    105:                        iconv_opt = cp + 1;
                    106:                else
                    107:                        *cp = '\0';
                    108:        }
                    109: 
                    110:        if (!*iconv_opt || (*iconv_opt == '.' && iconv_opt[1] == '\0'))
                    111:                charset = defset;
                    112:        else
                    113:                charset = iconv_opt;
                    114: 
                    115:        if ((ic_send = iconv_open(UTF8_CHARSET, charset)) == (iconv_t)-1) {
                    116:                rprintf(FERROR, "iconv_open(\"%s\", \"%s\") failed\n",
                    117:                        UTF8_CHARSET, charset);
                    118:                exit_cleanup(RERR_UNSUPPORTED);
                    119:        }
                    120: 
                    121:        if ((ic_recv = iconv_open(charset, UTF8_CHARSET)) == (iconv_t)-1) {
                    122:                rprintf(FERROR, "iconv_open(\"%s\", \"%s\") failed\n",
                    123:                        charset, UTF8_CHARSET);
                    124:                exit_cleanup(RERR_UNSUPPORTED);
                    125:        }
                    126: 
                    127:        if (verbose > 1) {
                    128:                rprintf(FINFO, "%s charset: %s\n",
                    129:                        am_server ? "server" : "client",
                    130:                        *charset ? charset : "[LOCALE]");
                    131:        }
                    132: # endif
                    133: }
                    134: 
                    135: /* This function converts the characters in the "in" xbuf into characters
                    136:  * in the "out" xbuf.  The "len" of the "in" xbuf is used starting from its
                    137:  * "pos".  The "size" of the "out" xbuf restricts how many characters can be
                    138:  * stored, starting at its "pos+len" position.  Note that the last byte of
                    139:  * the buffer is never used, which reserves space for a terminating '\0'.
                    140:  * We return a 0 on success or a -1 on error.  An error also sets errno to
                    141:  * E2BIG, EILSEQ, or EINVAL (see below); otherwise errno will be set to 0.
                    142:  * The "in" xbuf is altered to update "pos" and "len".  The "out" xbuf has
                    143:  * data appended, and its "len" incremented.   If ICB_EXPAND_OUT is set in
                    144:  * "flags", the "out" xbuf will also be allocated if empty, and expanded if
                    145:  * too small (so E2BIG will not be returned).  If ICB_INCLUDE_BAD is set in
                    146:  * "flags", any badly-encoded chars are included verbatim in the "out" xbuf,
                    147:  * so EILSEQ will not be returned.  Likewise for ICB_INCLUDE_INCOMPLETE with
                    148:  * respect to an incomplete multi-byte char at the end, which ensures that
                    149:  * EINVAL is not returned.  Anytime "in.pos" is 0 we will reset the iconv()
                    150:  * state prior to processing the characters. */
                    151: int iconvbufs(iconv_t ic, xbuf *in, xbuf *out, int flags)
                    152: {
                    153:        ICONV_CONST char *ibuf;
                    154:        size_t icnt, ocnt;
                    155:        char *obuf;
                    156: 
                    157:        if (!out->size && flags & ICB_EXPAND_OUT)
                    158:                alloc_xbuf(out, 1024);
                    159: 
                    160:        if (!in->pos)
                    161:                iconv(ic, NULL, 0, NULL, 0);
                    162: 
                    163:        ibuf = in->buf + in->pos;
                    164:        icnt = in->len;
                    165: 
                    166:        obuf = out->buf + (out->pos + out->len);
                    167:        ocnt = out->size - (out->pos + out->len) - 1;
                    168: 
                    169:        while (icnt) {
                    170:                while (iconv(ic, &ibuf, &icnt, &obuf, &ocnt) == (size_t)-1) {
                    171:                        if (errno == EINTR)
                    172:                                continue;
                    173:                        if (errno == EINVAL) {
                    174:                                if (!(flags & ICB_INCLUDE_INCOMPLETE))
                    175:                                        goto finish;
                    176:                        } else if (errno == EILSEQ) {
                    177:                                if (!(flags & ICB_INCLUDE_BAD))
                    178:                                        goto finish;
                    179:                        } else {
                    180:                                size_t opos = obuf - out->buf;
                    181:                                if (!(flags & ICB_EXPAND_OUT)) {
                    182:                                        errno = E2BIG;
                    183:                                        goto finish;
                    184:                                }
                    185:                                realloc_xbuf(out, out->size + 1024);
                    186:                                obuf = out->buf + opos;
                    187:                                ocnt += 1024;
                    188:                                continue;
                    189:                        }
                    190:                        *obuf++ = *ibuf++;
                    191:                        ocnt--, icnt--;
                    192:                }
                    193:        }
                    194: 
                    195:        errno = 0;
                    196: 
                    197:   finish:
                    198:        in->len = icnt;
                    199:        in->pos = ibuf - in->buf;
                    200:        out->len = obuf - out->buf - out->pos;
                    201: 
                    202:        return errno ? -1 : 0;
                    203: }
                    204: #endif
                    205: 
                    206: void send_protected_args(int fd, char *args[])
                    207: {
                    208:        int i;
                    209: #ifdef ICONV_OPTION
                    210:        int convert = ic_send != (iconv_t)-1;
                    211:        xbuf outbuf, inbuf;
                    212: 
                    213:        if (convert)
                    214:                alloc_xbuf(&outbuf, 1024);
                    215: #endif
                    216: 
                    217:        for (i = 0; args[i]; i++) {} /* find first NULL */
                    218:        args[i] = "rsync"; /* set a new arg0 */
                    219:        if (verbose > 1)
                    220:                print_child_argv("protected args:", args + i + 1);
                    221:        do {
                    222:                if (!args[i][0])
                    223:                        write_buf(fd, ".", 2);
                    224: #ifdef ICONV_OPTION
                    225:                else if (convert) {
                    226:                        INIT_XBUF_STRLEN(inbuf, args[i]);
                    227:                        iconvbufs(ic_send, &inbuf, &outbuf,
                    228:                                  ICB_EXPAND_OUT | ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE);
                    229:                        outbuf.buf[outbuf.len] = '\0';
                    230:                        write_buf(fd, outbuf.buf, outbuf.len + 1);
                    231:                        outbuf.len = 0;
                    232:                }
                    233: #endif
                    234:                else
                    235:                        write_buf(fd, args[i], strlen(args[i]) + 1);
                    236:        } while (args[++i]);
                    237:        write_byte(fd, 0);
                    238: 
                    239: #ifdef ICONV_OPTION
                    240:        if (convert)
                    241:                free(outbuf.buf);
                    242: #endif
                    243: }
                    244: 
                    245: int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar *type_ptr,
                    246:                       char *buf, int *len_ptr)
                    247: {
                    248:        int len, iflags = 0;
                    249:        struct file_list *flist;
                    250:        uchar fnamecmp_type = FNAMECMP_FNAME;
                    251:        int ndx, save_verbose = verbose;
                    252: 
                    253:   read_loop:
                    254:        while (1) {
                    255:                ndx = read_ndx(f_in);
                    256: 
                    257:                if (ndx >= 0)
                    258:                        break;
                    259:                if (ndx == NDX_DONE)
                    260:                        return ndx;
                    261:                if (!inc_recurse || am_sender) {
                    262:                        int last;
                    263:                        if (first_flist)
                    264:                                last = first_flist->prev->ndx_start + first_flist->prev->used - 1;
                    265:                        else
                    266:                                last = -1;
                    267:                        rprintf(FERROR,
                    268:                                "Invalid file index: %d (%d - %d) [%s]\n",
                    269:                                ndx, NDX_DONE, last, who_am_i());
                    270:                        exit_cleanup(RERR_PROTOCOL);
                    271:                }
                    272:                if (ndx == NDX_FLIST_EOF) {
                    273:                        flist_eof = 1;
                    274:                        send_msg(MSG_FLIST_EOF, "", 0, 0);
                    275:                        continue;
                    276:                }
                    277:                ndx = NDX_FLIST_OFFSET - ndx;
                    278:                if (ndx < 0 || ndx >= dir_flist->used) {
                    279:                        ndx = NDX_FLIST_OFFSET - ndx;
                    280:                        rprintf(FERROR,
                    281:                                "Invalid dir index: %d (%d - %d) [%s]\n",
                    282:                                ndx, NDX_FLIST_OFFSET,
                    283:                                NDX_FLIST_OFFSET - dir_flist->used + 1,
                    284:                                who_am_i());
                    285:                        exit_cleanup(RERR_PROTOCOL);
                    286:                }
                    287: 
                    288:                /* Send everything read from f_in to msg_fd_out. */
                    289:                if (verbose > 3) {
                    290:                        rprintf(FINFO, "[%s] receiving flist for dir %d\n",
                    291:                                who_am_i(), ndx);
                    292:                }
                    293:                verbose = 0;
                    294:                send_msg_int(MSG_FLIST, ndx);
                    295:                start_flist_forward(f_in);
                    296:                flist = recv_file_list(f_in);
                    297:                flist->parent_ndx = ndx;
                    298:                stop_flist_forward();
                    299:                verbose = save_verbose;
                    300:        }
                    301: 
                    302:        iflags = protocol_version >= 29 ? read_shortint(f_in)
                    303:                   : ITEM_TRANSFER | ITEM_MISSING_DATA;
                    304: 
                    305:        /* Support the protocol-29 keep-alive style. */
                    306:        if (protocol_version < 30 && ndx == cur_flist->used && iflags == ITEM_IS_NEW) {
                    307:                if (am_sender)
                    308:                        maybe_send_keepalive();
                    309:                goto read_loop;
                    310:        }
                    311: 
                    312:        cur_flist = flist_for_ndx(ndx, "read_ndx_and_attrs");
                    313: 
                    314:        if (iflags & ITEM_BASIS_TYPE_FOLLOWS)
                    315:                fnamecmp_type = read_byte(f_in);
                    316:        *type_ptr = fnamecmp_type;
                    317: 
                    318:        if (iflags & ITEM_XNAME_FOLLOWS) {
                    319:                if ((len = read_vstring(f_in, buf, MAXPATHLEN)) < 0)
                    320:                        exit_cleanup(RERR_PROTOCOL);
                    321:        } else {
                    322:                *buf = '\0';
                    323:                len = -1;
                    324:        }
                    325:        *len_ptr = len;
                    326: 
                    327:        if (iflags & ITEM_TRANSFER) {
                    328:                int i = ndx - cur_flist->ndx_start;
                    329:                if (i < 0 || !S_ISREG(cur_flist->files[i]->mode)) {
                    330:                        rprintf(FERROR,
                    331:                                "received request to transfer non-regular file: %d [%s]\n",
                    332:                                ndx, who_am_i());
                    333:                        exit_cleanup(RERR_PROTOCOL);
                    334:                }
                    335:        }
                    336: 
                    337:        *iflag_ptr = iflags;
                    338:        return ndx;
                    339: }
                    340: 
                    341: /*
                    342:   free a sums struct
                    343:   */
                    344: void free_sums(struct sum_struct *s)
                    345: {
                    346:        if (s->sums) free(s->sums);
                    347:        free(s);
                    348: }
                    349: 
                    350: /* This is only called when we aren't preserving permissions.  Figure out what
                    351:  * the permissions should be and return them merged back into the mode. */
                    352: mode_t dest_mode(mode_t flist_mode, mode_t stat_mode, int dflt_perms,
                    353:                 int exists)
                    354: {
                    355:        int new_mode;
                    356:        /* If the file already exists, we'll return the local permissions,
                    357:         * possibly tweaked by the --executability option. */
                    358:        if (exists) {
                    359:                new_mode = (flist_mode & ~CHMOD_BITS) | (stat_mode & CHMOD_BITS);
                    360:                if (preserve_executability && S_ISREG(flist_mode)) {
                    361:                        /* If the source file is executable, grant execute
                    362:                         * rights to everyone who can read, but ONLY if the
                    363:                         * file isn't already executable. */
                    364:                        if (!(flist_mode & 0111))
                    365:                                new_mode &= ~0111;
                    366:                        else if (!(stat_mode & 0111))
                    367:                                new_mode |= (new_mode & 0444) >> 2;
                    368:                }
                    369:        } else {
                    370:                /* Apply destination default permissions and turn
                    371:                 * off special permissions. */
                    372:                new_mode = flist_mode & (~CHMOD_BITS | dflt_perms);
                    373:        }
                    374:        return new_mode;
                    375: }
                    376: 
                    377: int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
                    378:                   const char *fnamecmp, int flags)
                    379: {
                    380:        int updated = 0;
                    381:        stat_x sx2;
                    382:        int change_uid, change_gid;
                    383:        mode_t new_mode = file->mode;
                    384:        int inherit;
                    385: 
                    386:        if (!sxp) {
                    387:                if (dry_run)
                    388:                        return 1;
                    389:                if (link_stat(fname, &sx2.st, 0) < 0) {
                    390:                        rsyserr(FERROR_XFER, errno, "stat %s failed",
                    391:                                full_fname(fname));
                    392:                        return 0;
                    393:                }
                    394: #ifdef SUPPORT_ACLS
                    395:                sx2.acc_acl = sx2.def_acl = NULL;
                    396: #endif
                    397: #ifdef SUPPORT_XATTRS
                    398:                sx2.xattr = NULL;
                    399: #endif
                    400:                sxp = &sx2;
                    401:                inherit = !preserve_perms;
                    402:        } else
                    403:                inherit = !preserve_perms && file->flags & FLAG_DIR_CREATED;
                    404: 
                    405:        if (inherit && S_ISDIR(new_mode) && sxp->st.st_mode & S_ISGID) {
                    406:                /* We just created this directory and its setgid
                    407:                 * bit is on, so make sure it stays on. */
                    408:                new_mode |= S_ISGID;
                    409:        }
                    410: 
                    411:        if (daemon_chmod_modes && !S_ISLNK(new_mode))
                    412:                new_mode = tweak_mode(new_mode, daemon_chmod_modes);
                    413: 
                    414: #ifdef SUPPORT_ACLS
                    415:        if (preserve_acls && !S_ISLNK(file->mode) && !ACL_READY(*sxp))
                    416:                get_acl(fname, sxp);
                    417: #endif
                    418: 
                    419: #ifdef SUPPORT_XATTRS
                    420:        if (am_root < 0)
                    421:                set_stat_xattr(fname, file, new_mode);
                    422:        if (preserve_xattrs && fnamecmp)
                    423:                set_xattr(fname, file, fnamecmp, sxp);
                    424: #endif
                    425: 
                    426:        if (!preserve_times
                    427:         || (!(preserve_times & PRESERVE_DIR_TIMES) && S_ISDIR(sxp->st.st_mode))
                    428:         || (!(preserve_times & PRESERVE_LINK_TIMES) && S_ISLNK(sxp->st.st_mode)))
                    429:                flags |= ATTRS_SKIP_MTIME;
                    430:        if (!(flags & ATTRS_SKIP_MTIME)
                    431:            && cmp_time(sxp->st.st_mtime, file->modtime) != 0) {
                    432:                int ret = set_modtime(fname, file->modtime, sxp->st.st_mode);
                    433:                if (ret < 0) {
                    434:                        rsyserr(FERROR_XFER, errno, "failed to set times on %s",
                    435:                                full_fname(fname));
                    436:                        goto cleanup;
                    437:                }
                    438:                if (ret == 0) /* ret == 1 if symlink could not be set */
                    439:                        updated = 1;
                    440:                else
                    441:                        file->flags |= FLAG_TIME_FAILED;
                    442:        }
                    443: 
                    444:        change_uid = am_root && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file);
                    445:        change_gid = gid_ndx && !(file->flags & FLAG_SKIP_GROUP)
                    446:                  && sxp->st.st_gid != (gid_t)F_GROUP(file);
                    447: #ifndef CAN_CHOWN_SYMLINK
                    448:        if (S_ISLNK(sxp->st.st_mode)) {
                    449:                ;
                    450:        } else
                    451: #endif
                    452:        if (change_uid || change_gid) {
                    453:                if (verbose > 2) {
                    454:                        if (change_uid) {
                    455:                                rprintf(FINFO,
                    456:                                        "set uid of %s from %u to %u\n",
                    457:                                        fname, (unsigned)sxp->st.st_uid, F_OWNER(file));
                    458:                        }
                    459:                        if (change_gid) {
                    460:                                rprintf(FINFO,
                    461:                                        "set gid of %s from %u to %u\n",
                    462:                                        fname, (unsigned)sxp->st.st_gid, F_GROUP(file));
                    463:                        }
                    464:                }
                    465:                if (am_root >= 0) {
                    466:                        uid_t uid = change_uid ? (uid_t)F_OWNER(file) : sxp->st.st_uid;
                    467:                        gid_t gid = change_gid ? (gid_t)F_GROUP(file) : sxp->st.st_gid;
                    468:                        if (do_lchown(fname, uid, gid) != 0) {
                    469:                                /* We shouldn't have attempted to change uid
                    470:                                 * or gid unless have the privilege. */
                    471:                                rsyserr(FERROR_XFER, errno, "%s %s failed",
                    472:                                    change_uid ? "chown" : "chgrp",
                    473:                                    full_fname(fname));
                    474:                                goto cleanup;
                    475:                        }
                    476:                        if (uid == (uid_t)-1 && sxp->st.st_uid != (uid_t)-1)
                    477:                                rprintf(FERROR_XFER, "uid 4294967295 (-1) is impossible to set on %s\n", full_fname(fname));
                    478:                        if (gid == (gid_t)-1 && sxp->st.st_gid != (gid_t)-1)
                    479:                                rprintf(FERROR_XFER, "gid 4294967295 (-1) is impossible to set on %s\n", full_fname(fname));
                    480:                        /* A lchown had been done, so we need to re-stat if
                    481:                         * the destination had the setuid or setgid bits set
                    482:                         * (due to the side effect of the chown call). */
                    483:                        if (sxp->st.st_mode & (S_ISUID | S_ISGID)) {
                    484:                                link_stat(fname, &sxp->st,
                    485:                                          keep_dirlinks && S_ISDIR(sxp->st.st_mode));
                    486:                        }
                    487:                }
                    488:                updated = 1;
                    489:        }
                    490: 
                    491: #ifdef SUPPORT_ACLS
                    492:        /* It's OK to call set_acl() now, even for a dir, as the generator
                    493:         * will enable owner-writability using chmod, if necessary.
                    494:         * 
                    495:         * If set_acl() changes permission bits in the process of setting
                    496:         * an access ACL, it changes sxp->st.st_mode so we know whether we
                    497:         * need to chmod(). */
                    498:        if (preserve_acls && !S_ISLNK(new_mode)) {
                    499:                if (set_acl(fname, file, sxp, new_mode) > 0)
                    500:                        updated = 1;
                    501:        }
                    502: #endif
                    503: 
                    504: #ifdef HAVE_CHMOD
                    505:        if (!BITS_EQUAL(sxp->st.st_mode, new_mode, CHMOD_BITS)) {
                    506:                int ret = am_root < 0 ? 0 : do_chmod(fname, new_mode);
                    507:                if (ret < 0) {
                    508:                        rsyserr(FERROR_XFER, errno,
                    509:                                "failed to set permissions on %s",
                    510:                                full_fname(fname));
                    511:                        goto cleanup;
                    512:                }
                    513:                if (ret == 0) /* ret == 1 if symlink could not be set */
                    514:                        updated = 1;
                    515:        }
                    516: #endif
                    517: 
                    518:        if (verbose > 1 && flags & ATTRS_REPORT) {
                    519:                if (updated)
                    520:                        rprintf(FCLIENT, "%s\n", fname);
                    521:                else
                    522:                        rprintf(FCLIENT, "%s is uptodate\n", fname);
                    523:        }
                    524:   cleanup:
                    525:        if (sxp == &sx2) {
                    526: #ifdef SUPPORT_ACLS
                    527:                if (preserve_acls)
                    528:                        free_acl(&sx2);
                    529: #endif
                    530: #ifdef SUPPORT_XATTRS
                    531:                if (preserve_xattrs)
                    532:                        free_xattr(&sx2);
                    533: #endif
                    534:        }
                    535:        return updated;
                    536: }
                    537: 
                    538: RETSIGTYPE sig_int(UNUSED(int val))
                    539: {
                    540:        /* KLUGE: if the user hits Ctrl-C while ssh is prompting
                    541:         * for a password, then our cleanup's sending of a SIGUSR1
                    542:         * signal to all our children may kill ssh before it has a
                    543:         * chance to restore the tty settings (i.e. turn echo back
                    544:         * on).  By sleeping for a short time, ssh gets a bigger
                    545:         * chance to do the right thing.  If child processes are
                    546:         * not ssh waiting for a password, then this tiny delay
                    547:         * shouldn't hurt anything. */
                    548:        msleep(400);
                    549:        exit_cleanup(RERR_SIGNAL);
                    550: }
                    551: 
                    552: /* Finish off a file transfer: renaming the file and setting the file's
                    553:  * attributes (e.g. permissions, ownership, etc.).  If the robust_rename()
                    554:  * call is forced to copy the temp file and partialptr is both non-NULL and
                    555:  * not an absolute path, we stage the file into the partial-dir and then
                    556:  * rename it into place.  This returns 1 on succcess or 0 on failure. */
                    557: int finish_transfer(const char *fname, const char *fnametmp,
                    558:                    const char *fnamecmp, const char *partialptr,
                    559:                    struct file_struct *file, int ok_to_set_time,
                    560:                    int overwriting_basis)
                    561: {
                    562:        int ret;
                    563:        const char *temp_copy_name = partialptr && *partialptr != '/' ? partialptr : NULL;
                    564: 
                    565:        if (inplace) {
                    566:                if (verbose > 2)
                    567:                        rprintf(FINFO, "finishing %s\n", fname);
                    568:                fnametmp = fname;
                    569:                goto do_set_file_attrs;
                    570:        }
                    571: 
                    572:        if (make_backups > 0 && overwriting_basis) {
                    573:                if (!make_backup(fname))
                    574:                        return 1;
                    575:                if (fnamecmp == fname)
                    576:                        fnamecmp = get_backup_name(fname);
                    577:        }
                    578: 
                    579:        /* Change permissions before putting the file into place. */
                    580:        set_file_attrs(fnametmp, file, NULL, fnamecmp,
                    581:                       ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);
                    582: 
                    583:        /* move tmp file over real file */
                    584:        if (verbose > 2)
                    585:                rprintf(FINFO, "renaming %s to %s\n", fnametmp, fname);
                    586:        ret = robust_rename(fnametmp, fname, temp_copy_name,
                    587:                            file->mode & INITACCESSPERMS);
                    588:        if (ret < 0) {
                    589:                rsyserr(FERROR_XFER, errno, "%s %s -> \"%s\"",
                    590:                        ret == -2 ? "copy" : "rename",
                    591:                        full_fname(fnametmp), fname);
                    592:                if (!partialptr || (ret == -2 && temp_copy_name)
                    593:                 || robust_rename(fnametmp, partialptr, NULL,
                    594:                                  file->mode & INITACCESSPERMS) < 0)
                    595:                        do_unlink(fnametmp);
                    596:                return 0;
                    597:        }
                    598:        if (ret == 0) {
                    599:                /* The file was moved into place (not copied), so it's done. */
                    600:                return 1;
                    601:        }
                    602:        /* The file was copied, so tweak the perms of the copied file.  If it
                    603:         * was copied to partialptr, move it into its final destination. */
                    604:        fnametmp = temp_copy_name ? temp_copy_name : fname;
                    605: 
                    606:   do_set_file_attrs:
                    607:        set_file_attrs(fnametmp, file, NULL, fnamecmp,
                    608:                       ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);
                    609: 
                    610:        if (temp_copy_name) {
                    611:                if (do_rename(fnametmp, fname) < 0) {
                    612:                        rsyserr(FERROR_XFER, errno, "rename %s -> \"%s\"",
                    613:                                full_fname(fnametmp), fname);
                    614:                        return 0;
                    615:                }
                    616:                handle_partial_dir(temp_copy_name, PDIR_DELETE);
                    617:        }
                    618:        return 1;
                    619: }
                    620: 
                    621: struct file_list *flist_for_ndx(int ndx, const char *fatal_error_loc)
                    622: {
                    623:        struct file_list *flist = cur_flist;
                    624: 
                    625:        if (!flist && !(flist = first_flist))
                    626:                goto not_found;
                    627: 
                    628:        while (ndx < flist->ndx_start-1) {
                    629:                if (flist == first_flist)
                    630:                        goto not_found;
                    631:                flist = flist->prev;
                    632:        }
                    633:        while (ndx >= flist->ndx_start + flist->used) {
                    634:                if (!(flist = flist->next))
                    635:                        goto not_found;
                    636:        }
                    637:        return flist;
                    638: 
                    639:   not_found:
                    640:        if (fatal_error_loc) {
                    641:                int first, last;
                    642:                if (first_flist) {
                    643:                        first = first_flist->ndx_start - 1;
                    644:                        last = first_flist->prev->ndx_start + first_flist->prev->used - 1;
                    645:                } else {
                    646:                        first = 0;
                    647:                        last = -1;
                    648:                }
                    649:                rprintf(FERROR,
                    650:                        "File-list index %d not in %d - %d (%s) [%s]\n",
                    651:                        ndx, first, last, fatal_error_loc, who_am_i());
                    652:                exit_cleanup(RERR_PROTOCOL);
                    653:        }
                    654:        return NULL;
                    655: }
                    656: 
                    657: const char *who_am_i(void)
                    658: {
                    659:        if (am_starting_up)
                    660:                return am_server ? "server" : "client";
                    661:        return am_sender ? "sender"
                    662:             : am_generator ? "generator"
                    663:             : am_receiver ? "receiver"
                    664:             : "Receiver"; /* pre-forked receiver */
                    665: }

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