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

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

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