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

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

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