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

1.1       misho       1: /*
                      2:  * Backup handling code.
                      3:  *
                      4:  * Copyright (C) 1999 Andrew Tridgell
1.1.1.4 ! misho       5:  * Copyright (C) 2003-2020 Wayne Davison
1.1       misho       6:  *
                      7:  * This program is free software; you can redistribute it and/or modify
                      8:  * it under the terms of the GNU General Public License as published by
                      9:  * the Free Software Foundation; either version 3 of the License, or
                     10:  * (at your option) any later version.
                     11:  *
                     12:  * This program is distributed in the hope that it will be useful,
                     13:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     14:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     15:  * GNU General Public License for more details.
                     16:  *
                     17:  * You should have received a copy of the GNU General Public License along
                     18:  * with this program; if not, visit the http://fsf.org website.
                     19:  */
                     20: 
                     21: #include "rsync.h"
1.1.1.2   misho      22: #include "ifuncs.h"
1.1       misho      23: 
                     24: extern int am_root;
                     25: extern int preserve_acls;
                     26: extern int preserve_xattrs;
                     27: extern int preserve_devices;
                     28: extern int preserve_specials;
                     29: extern int preserve_links;
                     30: extern int safe_symlinks;
                     31: extern int backup_dir_len;
1.1.1.4 ! misho      32: extern int backup_dir_dels_len;
1.1       misho      33: extern unsigned int backup_dir_remainder;
1.1.1.4 ! misho      34: extern unsigned int backup_dir_dels_remainder;
1.1       misho      35: extern char backup_dir_buf[MAXPATHLEN];
1.1.1.4 ! misho      36: extern char backup_dir_dels_buf[MAXPATHLEN];
1.1       misho      37: extern char *backup_suffix;
1.1.1.4 ! misho      38: extern char *backup_suffix_dels;
1.1       misho      39: extern char *backup_dir;
1.1.1.4 ! misho      40: extern char *backup_dir_dels;
        !            41: 
        !            42: static BOOL deleting;
1.1       misho      43: 
1.1.1.2   misho      44: /* Returns -1 on error, 0 on missing dir, and 1 on present dir. */
1.1.1.4 ! misho      45: static int validate_backup_dir(char *buf)
1.1       misho      46: {
1.1.1.2   misho      47:        STRUCT_STAT st;
1.1       misho      48: 
1.1.1.4 ! misho      49:        if (do_lstat(buf, &st) < 0) {
1.1.1.2   misho      50:                if (errno == ENOENT)
                     51:                        return 0;
1.1.1.4 ! misho      52:                rsyserr(FERROR, errno, "backup lstat %s failed", buf);
1.1.1.2   misho      53:                return -1;
                     54:        }
                     55:        if (!S_ISDIR(st.st_mode)) {
                     56:                int flags = get_del_for_flag(st.st_mode) | DEL_FOR_BACKUP | DEL_RECURSE;
1.1.1.4 ! misho      57:                if (delete_item(buf, st.st_mode, flags) == 0)
1.1.1.2   misho      58:                        return 0;
                     59:                return -1;
1.1       misho      60:        }
                     61:        return 1;
                     62: }
                     63: 
1.1.1.2   misho      64: /* Create a backup path from the given fname, putting the result into
                     65:  * backup_dir_buf.  Any new directories (compared to the prior backup
                     66:  * path) are ensured to exist as directories, replacing anything else
                     67:  * that may be in the way (e.g. a symlink). */
1.1.1.4 ! misho      68: static BOOL copy_valid_path(const char *fname, char *buf, int prefix_len, unsigned int remainder, const char *suffix)
1.1       misho      69: {
1.1.1.2   misho      70:        const char *f;
                     71:        int val;
                     72:        BOOL ret = True;
1.1       misho      73:        stat_x sx;
1.1.1.4 ! misho      74:        char *b, *rel = buf + prefix_len, *name = rel;
1.1       misho      75: 
1.1.1.2   misho      76:        for (f = fname, b = rel; *f && *f == *b; f++, b++) {
                     77:                if (*b == '/')
                     78:                        name = b + 1;
1.1       misho      79:        }
                     80: 
1.1.1.4 ! misho      81:        if (stringjoin(rel, remainder, fname, suffix, NULL) >= remainder) {
1.1.1.2   misho      82:                rprintf(FERROR, "backup filename too long\n");
                     83:                *name = '\0';
                     84:                return False;
                     85:        }
1.1       misho      86: 
1.1.1.2   misho      87:        for ( ; ; name = b + 1) {
                     88:                if ((b = strchr(name, '/')) == NULL)
                     89:                        return True;
                     90:                *b = '\0';
1.1       misho      91: 
1.1.1.4 ! misho      92:                val = validate_backup_dir(buf);
1.1.1.2   misho      93:                if (val == 0)
                     94:                        break;
                     95:                if (val < 0) {
                     96:                        *name = '\0';
                     97:                        return False;
1.1       misho      98:                }
1.1.1.2   misho      99: 
                    100:                *b = '/';
1.1       misho     101:        }
                    102: 
1.1.1.2   misho     103:        init_stat_x(&sx);
                    104: 
                    105:        for ( ; b; name = b + 1, b = strchr(name, '/')) {
                    106:                *b = '\0';
                    107: 
1.1.1.4 ! misho     108:                while (do_mkdir(buf, ACCESSPERMS) < 0) {
1.1.1.2   misho     109:                        if (errno == EEXIST) {
1.1.1.4 ! misho     110:                                val = validate_backup_dir(buf);
1.1.1.2   misho     111:                                if (val > 0)
                    112:                                        break;
                    113:                                if (val == 0)
1.1       misho     114:                                        continue;
1.1.1.2   misho     115:                        } else
                    116:                                rsyserr(FERROR, errno, "backup mkdir %s failed", backup_dir_buf);
                    117:                        *name = '\0';
                    118:                        ret = False;
                    119:                        goto cleanup;
                    120:                }
                    121: 
                    122:                /* Try to transfer the directory settings of the actual dir
                    123:                 * that the files are coming from. */
                    124:                if (x_stat(rel, &sx.st, NULL) < 0)
                    125:                        rsyserr(FERROR, errno, "backup stat %s failed", full_fname(rel));
                    126:                else {
                    127:                        struct file_struct *file;
                    128:                        if (!(file = make_file(rel, NULL, NULL, 0, NO_FILTERS)))
                    129:                                continue;
1.1       misho     130: #ifdef SUPPORT_ACLS
1.1.1.2   misho     131:                        if (preserve_acls && !S_ISLNK(file->mode)) {
                    132:                                get_acl(rel, &sx);
                    133:                                cache_tmp_acl(file, &sx);
                    134:                                free_acl(&sx);
                    135:                        }
1.1       misho     136: #endif
                    137: #ifdef SUPPORT_XATTRS
1.1.1.2   misho     138:                        if (preserve_xattrs) {
                    139:                                get_xattr(rel, &sx);
                    140:                                cache_tmp_xattr(file, &sx);
                    141:                                free_xattr(&sx);
                    142:                        }
1.1       misho     143: #endif
1.1.1.4 ! misho     144:                        set_file_attrs(buf, file, NULL, NULL, 0);
1.1.1.2   misho     145:                        unmake_file(file);
                    146:                }
                    147: 
                    148:                *b = '/';
                    149:        }
                    150: 
                    151:   cleanup:
                    152: 
1.1       misho     153: #ifdef SUPPORT_ACLS
1.1.1.2   misho     154:        uncache_tmp_acls();
1.1       misho     155: #endif
                    156: #ifdef SUPPORT_XATTRS
1.1.1.2   misho     157:        uncache_tmp_xattrs();
1.1       misho     158: #endif
1.1.1.2   misho     159: 
                    160:        return ret;
                    161: }
                    162: 
                    163: /* Make a complete pathname for backup file and verify any new path elements. */
                    164: char *get_backup_name(const char *fname)
                    165: {
1.1.1.4 ! misho     166:        char *buf = deleting ? backup_dir_dels_buf : backup_dir_buf;
        !           167:        char *suffix = deleting ? backup_suffix_dels : backup_suffix;
        !           168: 
1.1.1.2   misho     169:        if (backup_dir) {
1.1.1.4 ! misho     170:                int prefix_len = deleting ? backup_dir_dels_len : backup_dir_len;
        !           171:                unsigned int remainder = deleting ? backup_dir_dels_remainder : backup_dir_remainder;
1.1.1.3   misho     172:                static int initialized = 0;
                    173:                if (!initialized) {
                    174:                        int ret;
                    175:                        if (backup_dir_len > 1)
                    176:                                backup_dir_buf[backup_dir_len-1] = '\0';
1.1.1.4 ! misho     177:                        ret = make_path(backup_dir_buf, ACCESSPERMS, 0);
1.1.1.3   misho     178:                        if (backup_dir_len > 1)
                    179:                                backup_dir_buf[backup_dir_len-1] = '/';
                    180:                        if (ret < 0)
                    181:                                return NULL;
                    182:                        initialized = 1;
                    183:                }
1.1.1.2   misho     184:                /* copy fname into backup_dir_buf while validating the dirs. */
1.1.1.4 ! misho     185:                if (copy_valid_path(fname, buf, prefix_len, remainder, suffix))
        !           186:                        return buf;
1.1.1.2   misho     187:                /* copy_valid_path() has printed an error message. */
                    188:                return NULL;
1.1       misho     189:        }
                    190: 
1.1.1.4 ! misho     191:        if (stringjoin(backup_dir_buf, MAXPATHLEN, fname, suffix, NULL) < MAXPATHLEN)
        !           192:                return buf;
1.1.1.2   misho     193: 
                    194:        rprintf(FERROR, "backup filename too long\n");
                    195:        return NULL;
1.1       misho     196: }
                    197: 
1.1.1.2   misho     198: /* Has same return codes as make_backup(). */
                    199: static inline int link_or_rename(const char *from, const char *to,
                    200:                                 BOOL prefer_rename, STRUCT_STAT *stp)
1.1       misho     201: {
1.1.1.2   misho     202: #ifdef SUPPORT_HARD_LINKS
                    203:        if (!prefer_rename) {
                    204: #ifndef CAN_HARDLINK_SYMLINK
                    205:                if (S_ISLNK(stp->st_mode))
                    206:                        return 0; /* Use copy code. */
                    207: #endif
                    208: #ifndef CAN_HARDLINK_SPECIAL
                    209:                if (IS_SPECIAL(stp->st_mode) || IS_DEVICE(stp->st_mode))
                    210:                        return 0; /* Use copy code. */
                    211: #endif
                    212:                if (do_link(from, to) == 0) {
                    213:                        if (DEBUG_GTE(BACKUP, 1))
                    214:                                rprintf(FINFO, "make_backup: HLINK %s successful.\n", from);
                    215:                        return 2;
                    216:                }
                    217:                /* We prefer to rename a regular file rather than copy it. */
                    218:                if (!S_ISREG(stp->st_mode) || errno == EEXIST || errno == EISDIR)
                    219:                        return 0;
                    220:        }
                    221: #endif
                    222:        if (do_rename(from, to) == 0) {
                    223:                if (stp->st_nlink > 1 && !S_ISDIR(stp->st_mode)) {
                    224:                        /* If someone has hard-linked the file into the backup
                    225:                         * dir, rename() might return success but do nothing! */
                    226:                        robust_unlink(from); /* Just in case... */
1.1       misho     227:                }
1.1.1.2   misho     228:                if (DEBUG_GTE(BACKUP, 1))
                    229:                        rprintf(FINFO, "make_backup: RENAME %s successful.\n", from);
                    230:                return 1;
1.1       misho     231:        }
                    232:        return 0;
                    233: }
                    234: 
1.1.1.3   misho     235: /* Hard-link, rename, or copy an item to the backup name.  Returns 0 for
                    236:  * failure, 1 if item was moved, 2 if item was duplicated or hard linked
                    237:  * into backup area, or 3 if item doesn't exist or isn't a regular file. */
1.1.1.2   misho     238: int make_backup(const char *fname, BOOL prefer_rename)
1.1       misho     239: {
                    240:        stat_x sx;
                    241:        struct file_struct *file;
1.1.1.2   misho     242:        int save_preserve_xattrs;
1.1.1.3   misho     243:        char *buf;
1.1.1.2   misho     244:        int ret = 0;
1.1       misho     245: 
1.1.1.2   misho     246:        init_stat_x(&sx);
                    247:        /* Return success if no file to keep. */
1.1       misho     248:        if (x_lstat(fname, &sx.st, NULL) < 0)
1.1.1.3   misho     249:                return 3;
                    250: 
                    251:        if (!(buf = get_backup_name(fname)))
                    252:                return 0;
1.1       misho     253: 
1.1.1.2   misho     254:        /* Try a hard-link or a rename first.  Using rename is not atomic, but
                    255:         * is more efficient than forcing a copy for larger files when no hard-
                    256:         * linking is possible. */
                    257:        if ((ret = link_or_rename(fname, buf, prefer_rename, &sx.st)) != 0)
                    258:                goto success;
                    259:        if (errno == EEXIST || errno == EISDIR) {
                    260:                STRUCT_STAT bakst;
                    261:                if (do_lstat(buf, &bakst) == 0) {
                    262:                        int flags = get_del_for_flag(bakst.st_mode) | DEL_FOR_BACKUP | DEL_RECURSE;
                    263:                        if (delete_item(buf, bakst.st_mode, flags) != 0)
                    264:                                return 0;
                    265:                }
                    266:                if ((ret = link_or_rename(fname, buf, prefer_rename, &sx.st)) != 0)
                    267:                        goto success;
1.1       misho     268:        }
                    269: 
1.1.1.2   misho     270:        /* Fall back to making a copy. */
                    271:        if (!(file = make_file(fname, NULL, &sx.st, 0, NO_FILTERS)))
1.1.1.3   misho     272:                return 3; /* the file could have disappeared */
1.1.1.2   misho     273: 
1.1       misho     274: #ifdef SUPPORT_ACLS
                    275:        if (preserve_acls && !S_ISLNK(file->mode)) {
                    276:                get_acl(fname, &sx);
                    277:                cache_tmp_acl(file, &sx);
                    278:                free_acl(&sx);
                    279:        }
                    280: #endif
                    281: #ifdef SUPPORT_XATTRS
                    282:        if (preserve_xattrs) {
                    283:                get_xattr(fname, &sx);
                    284:                cache_tmp_xattr(file, &sx);
                    285:                free_xattr(&sx);
                    286:        }
                    287: #endif
                    288: 
                    289:        /* Check to see if this is a device file, or link */
                    290:        if ((am_root && preserve_devices && IS_DEVICE(file->mode))
                    291:         || (preserve_specials && IS_SPECIAL(file->mode))) {
1.1.1.2   misho     292:                if (do_mknod(buf, file->mode, sx.st.st_rdev) < 0)
                    293:                        rsyserr(FERROR, errno, "mknod %s failed", full_fname(buf));
                    294:                else if (DEBUG_GTE(BACKUP, 1))
                    295:                        rprintf(FINFO, "make_backup: DEVICE %s successful.\n", fname);
                    296:                ret = 2;
1.1       misho     297:        }
                    298: 
                    299: #ifdef SUPPORT_LINKS
1.1.1.2   misho     300:        if (!ret && preserve_links && S_ISLNK(file->mode)) {
1.1       misho     301:                const char *sl = F_SYMLINK(file);
                    302:                if (safe_symlinks && unsafe_symlink(sl, fname)) {
1.1.1.2   misho     303:                        if (INFO_GTE(SYMSAFE, 1)) {
1.1       misho     304:                                rprintf(FINFO, "not backing up unsafe symlink \"%s\" -> \"%s\"\n",
                    305:                                        fname, sl);
                    306:                        }
1.1.1.2   misho     307:                        ret = 2;
1.1       misho     308:                } else {
1.1.1.2   misho     309:                        if (do_symlink(sl, buf) < 0)
                    310:                                rsyserr(FERROR, errno, "link %s -> \"%s\"", full_fname(buf), sl);
                    311:                        else if (DEBUG_GTE(BACKUP, 1))
                    312:                                rprintf(FINFO, "make_backup: SYMLINK %s successful.\n", fname);
                    313:                        ret = 2;
1.1       misho     314:                }
                    315:        }
                    316: #endif
                    317: 
1.1.1.2   misho     318:        if (!ret && !S_ISREG(file->mode)) {
                    319:                rprintf(FINFO, "make_bak: skipping non-regular file %s\n", fname);
1.1       misho     320:                unmake_file(file);
                    321: #ifdef SUPPORT_ACLS
                    322:                uncache_tmp_acls();
                    323: #endif
                    324: #ifdef SUPPORT_XATTRS
                    325:                uncache_tmp_xattrs();
                    326: #endif
1.1.1.3   misho     327:                return 3;
1.1       misho     328:        }
                    329: 
1.1.1.2   misho     330:        /* Copy to backup tree if a file. */
                    331:        if (!ret) {
                    332:                if (copy_file(fname, buf, -1, file->mode) < 0) {
1.1       misho     333:                        rsyserr(FERROR, errno, "keep_backup failed: %s -> \"%s\"",
                    334:                                full_fname(fname), buf);
1.1.1.2   misho     335:                        unmake_file(file);
                    336: #ifdef SUPPORT_ACLS
                    337:                        uncache_tmp_acls();
                    338: #endif
                    339: #ifdef SUPPORT_XATTRS
                    340:                        uncache_tmp_xattrs();
                    341: #endif
                    342:                        return 0;
1.1       misho     343:                }
1.1.1.2   misho     344:                if (DEBUG_GTE(BACKUP, 1))
                    345:                        rprintf(FINFO, "make_backup: COPY %s successful.\n", fname);
                    346:                ret = 2;
1.1       misho     347:        }
1.1.1.2   misho     348: 
                    349:        save_preserve_xattrs = preserve_xattrs;
1.1       misho     350:        preserve_xattrs = 0;
1.1.1.4 ! misho     351:        set_file_attrs(buf, file, NULL, fname, ATTRS_ACCURATE_TIME);
1.1       misho     352:        preserve_xattrs = save_preserve_xattrs;
1.1.1.2   misho     353: 
1.1       misho     354:        unmake_file(file);
                    355: #ifdef SUPPORT_ACLS
                    356:        uncache_tmp_acls();
                    357: #endif
                    358: #ifdef SUPPORT_XATTRS
                    359:        uncache_tmp_xattrs();
                    360: #endif
                    361: 
1.1.1.2   misho     362:   success:
                    363:        if (INFO_GTE(BACKUP, 1))
                    364:                rprintf(FINFO, "backed up %s to %s\n", fname, buf);
                    365:        return ret;
1.1       misho     366: }
1.1.1.4 ! misho     367: 
        !           368: /* backup switch routine called only when backing-up removed file */
        !           369: int safe_delete(const char *fname)
        !           370: {
        !           371:        int ret;
        !           372:        deleting = 1;
        !           373:        ret = make_backup(fname, True);
        !           374:        deleting = 0;
        !           375:        return ret;
        !           376: }

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