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

1.1       misho       1: /*
                      2:  * Backup handling code.
                      3:  *
                      4:  * Copyright (C) 1999 Andrew Tridgell
                      5:  * Copyright (C) 2003-2009 Wayne Davison
                      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"
                     22: 
                     23: extern int verbose;
                     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: 
                     37: /* make a complete pathname for backup file */
                     38: char *get_backup_name(const char *fname)
                     39: {
                     40:        if (backup_dir) {
                     41:                if (stringjoin(backup_dir_buf + backup_dir_len, backup_dir_remainder,
                     42:                               fname, backup_suffix, NULL) < backup_dir_remainder)
                     43:                        return backup_dir_buf;
                     44:        } else {
                     45:                if (stringjoin(backup_dir_buf, MAXPATHLEN,
                     46:                               fname, backup_suffix, NULL) < MAXPATHLEN)
                     47:                        return backup_dir_buf;
                     48:        }
                     49: 
                     50:        rprintf(FERROR, "backup filename too long\n");
                     51:        return NULL;
                     52: }
                     53: 
                     54: /* simple backup creates a backup with a suffix in the same directory */
                     55: static int make_simple_backup(const char *fname)
                     56: {
                     57:        int rename_errno;
                     58:        const char *fnamebak = get_backup_name(fname);
                     59: 
                     60:        if (!fnamebak)
                     61:                return 0;
                     62: 
                     63:        while (1) {
                     64:                if (do_rename(fname, fnamebak) == 0) {
                     65:                        if (verbose > 1) {
                     66:                                rprintf(FINFO, "backed up %s to %s\n",
                     67:                                        fname, fnamebak);
                     68:                        }
                     69:                        break;
                     70:                }
                     71:                /* cygwin (at least version b19) reports EINVAL */
                     72:                if (errno == ENOENT || errno == EINVAL)
                     73:                        break;
                     74: 
                     75:                rename_errno = errno;
                     76:                if (errno == EISDIR && do_rmdir(fnamebak) == 0)
                     77:                        continue;
                     78:                if (errno == ENOTDIR && do_unlink(fnamebak) == 0)
                     79:                        continue;
                     80: 
                     81:                rsyserr(FERROR, rename_errno, "rename %s to backup %s",
                     82:                        fname, fnamebak);
                     83:                errno = rename_errno;
                     84:                return 0;
                     85:        }
                     86: 
                     87:        return 1;
                     88: }
                     89: 
                     90: 
                     91: /****************************************************************************
                     92: Create a directory given an absolute path, perms based upon another directory
                     93: path
                     94: ****************************************************************************/
                     95: int make_bak_dir(const char *fullpath)
                     96: {
                     97:        char fbuf[MAXPATHLEN], *rel, *end, *p;
                     98:        struct file_struct *file;
                     99:        int len = backup_dir_len;
                    100:        stat_x sx;
                    101: 
                    102:        while (*fullpath == '.' && fullpath[1] == '/') {
                    103:                fullpath += 2;
                    104:                len -= 2;
                    105:        }
                    106: 
                    107:        if (strlcpy(fbuf, fullpath, sizeof fbuf) >= sizeof fbuf)
                    108:                return -1;
                    109: 
                    110:        rel = fbuf + len;
                    111:        end = p = rel + strlen(rel);
                    112: 
                    113:        /* Try to find an existing dir, starting from the deepest dir. */
                    114:        while (1) {
                    115:                if (--p == fbuf)
                    116:                        return -1;
                    117:                if (*p == '/') {
                    118:                        *p = '\0';
                    119:                        if (mkdir_defmode(fbuf) == 0)
                    120:                                break;
                    121:                        if (errno != ENOENT) {
                    122:                                rsyserr(FERROR, errno,
                    123:                                        "make_bak_dir mkdir %s failed",
                    124:                                        full_fname(fbuf));
                    125:                                return -1;
                    126:                        }
                    127:                }
                    128:        }
                    129: 
                    130:        /* Make all the dirs that we didn't find on the way here. */
                    131:        while (1) {
                    132:                if (p >= rel) {
                    133:                        /* Try to transfer the directory settings of the
                    134:                         * actual dir that the files are coming from. */
                    135:                        if (x_stat(rel, &sx.st, NULL) < 0) {
                    136:                                rsyserr(FERROR, errno,
                    137:                                        "make_bak_dir stat %s failed",
                    138:                                        full_fname(rel));
                    139:                        } else {
                    140: #ifdef SUPPORT_ACLS
                    141:                                sx.acc_acl = sx.def_acl = NULL;
                    142: #endif
                    143: #ifdef SUPPORT_XATTRS
                    144:                                sx.xattr = NULL;
                    145: #endif
                    146:                                if (!(file = make_file(rel, NULL, NULL, 0, NO_FILTERS)))
                    147:                                        continue;
                    148: #ifdef SUPPORT_ACLS
                    149:                                if (preserve_acls && !S_ISLNK(file->mode)) {
                    150:                                        get_acl(rel, &sx);
                    151:                                        cache_tmp_acl(file, &sx);
                    152:                                        free_acl(&sx);
                    153:                                }
                    154: #endif
                    155: #ifdef SUPPORT_XATTRS
                    156:                                if (preserve_xattrs) {
                    157:                                        get_xattr(rel, &sx);
                    158:                                        cache_tmp_xattr(file, &sx);
                    159:                                        free_xattr(&sx);
                    160:                                }
                    161: #endif
                    162:                                set_file_attrs(fbuf, file, NULL, NULL, 0);
                    163:                                unmake_file(file);
                    164: #ifdef SUPPORT_ACLS
                    165:                                uncache_tmp_acls();
                    166: #endif
                    167: #ifdef SUPPORT_XATTRS
                    168:                                uncache_tmp_xattrs();
                    169: #endif
                    170:                        }
                    171:                }
                    172:                *p = '/';
                    173:                p += strlen(p);
                    174:                if (p == end)
                    175:                        break;
                    176:                if (mkdir_defmode(fbuf) < 0) {
                    177:                        rsyserr(FERROR, errno, "make_bak_dir mkdir %s failed",
                    178:                                full_fname(fbuf));
                    179:                        return -1;
                    180:                }
                    181:        }
                    182: 
                    183:        return 0;
                    184: }
                    185: 
                    186: /* robustly move a file, creating new directory structures if necessary */
                    187: static int robust_move(const char *src, char *dst)
                    188: {
                    189:        if (robust_rename(src, dst, NULL, 0755) < 0) {
                    190:                int save_errno = errno ? errno : EINVAL; /* 0 paranoia */
                    191:                if (errno == ENOENT && make_bak_dir(dst) == 0) {
                    192:                        if (robust_rename(src, dst, NULL, 0755) < 0)
                    193:                                save_errno = errno ? errno : save_errno;
                    194:                        else
                    195:                                save_errno = 0;
                    196:                }
                    197:                if (save_errno) {
                    198:                        errno = save_errno;
                    199:                        return -1;
                    200:                }
                    201:        }
                    202:        return 0;
                    203: }
                    204: 
                    205: 
                    206: /* If we have a --backup-dir, then we get here from make_backup().
                    207:  * We will move the file to be deleted into a parallel directory tree. */
                    208: static int keep_backup(const char *fname)
                    209: {
                    210:        stat_x sx;
                    211:        struct file_struct *file;
                    212:        char *buf;
                    213:        int save_preserve_xattrs = preserve_xattrs;
                    214:        int kept = 0;
                    215:        int ret_code;
                    216: 
                    217:        /* return if no file to keep */
                    218:        if (x_lstat(fname, &sx.st, NULL) < 0)
                    219:                return 1;
                    220: #ifdef SUPPORT_ACLS
                    221:        sx.acc_acl = sx.def_acl = NULL;
                    222: #endif
                    223: #ifdef SUPPORT_XATTRS
                    224:        sx.xattr = NULL;
                    225: #endif
                    226: 
                    227:        if (!(file = make_file(fname, NULL, NULL, 0, NO_FILTERS)))
                    228:                return 1; /* the file could have disappeared */
                    229: 
                    230:        if (!(buf = get_backup_name(fname))) {
                    231:                unmake_file(file);
                    232: #ifdef SUPPORT_ACLS
                    233:                uncache_tmp_acls();
                    234: #endif
                    235: #ifdef SUPPORT_XATTRS
                    236:                uncache_tmp_xattrs();
                    237: #endif
                    238:                return 0;
                    239:        }
                    240: 
                    241: #ifdef SUPPORT_ACLS
                    242:        if (preserve_acls && !S_ISLNK(file->mode)) {
                    243:                get_acl(fname, &sx);
                    244:                cache_tmp_acl(file, &sx);
                    245:                free_acl(&sx);
                    246:        }
                    247: #endif
                    248: #ifdef SUPPORT_XATTRS
                    249:        if (preserve_xattrs) {
                    250:                get_xattr(fname, &sx);
                    251:                cache_tmp_xattr(file, &sx);
                    252:                free_xattr(&sx);
                    253:        }
                    254: #endif
                    255: 
                    256:        /* Check to see if this is a device file, or link */
                    257:        if ((am_root && preserve_devices && IS_DEVICE(file->mode))
                    258:         || (preserve_specials && IS_SPECIAL(file->mode))) {
                    259:                int save_errno;
                    260:                do_unlink(buf);
                    261:                if (do_mknod(buf, file->mode, sx.st.st_rdev) < 0) {
                    262:                        save_errno = errno ? errno : EINVAL; /* 0 paranoia */
                    263:                        if (errno == ENOENT && make_bak_dir(buf) == 0) {
                    264:                                if (do_mknod(buf, file->mode, sx.st.st_rdev) < 0)
                    265:                                        save_errno = errno ? errno : save_errno;
                    266:                                else
                    267:                                        save_errno = 0;
                    268:                        }
                    269:                        if (save_errno) {
                    270:                                rsyserr(FERROR, save_errno, "mknod %s failed",
                    271:                                        full_fname(buf));
                    272:                        }
                    273:                } else
                    274:                        save_errno = 0;
                    275:                if (verbose > 2 && save_errno == 0) {
                    276:                        rprintf(FINFO, "make_backup: DEVICE %s successful.\n",
                    277:                                fname);
                    278:                }
                    279:                kept = 1;
                    280:                do_unlink(fname);
                    281:        }
                    282: 
                    283:        if (!kept && S_ISDIR(file->mode)) {
                    284:                /* make an empty directory */
                    285:                if (do_mkdir(buf, file->mode) < 0) {
                    286:                        int save_errno = errno ? errno : EINVAL; /* 0 paranoia */
                    287:                        if (errno == ENOENT && make_bak_dir(buf) == 0) {
                    288:                                if (do_mkdir(buf, file->mode) < 0)
                    289:                                        save_errno = errno ? errno : save_errno;
                    290:                                else
                    291:                                        save_errno = 0;
                    292:                        }
                    293:                        if (save_errno) {
                    294:                                rsyserr(FINFO, save_errno, "mkdir %s failed",
                    295:                                        full_fname(buf));
                    296:                        }
                    297:                }
                    298: 
                    299:                ret_code = do_rmdir(fname);
                    300:                if (verbose > 2) {
                    301:                        rprintf(FINFO, "make_backup: RMDIR %s returns %i\n",
                    302:                                full_fname(fname), ret_code);
                    303:                }
                    304:                kept = 1;
                    305:        }
                    306: 
                    307: #ifdef SUPPORT_LINKS
                    308:        if (!kept && preserve_links && S_ISLNK(file->mode)) {
                    309:                const char *sl = F_SYMLINK(file);
                    310:                if (safe_symlinks && unsafe_symlink(sl, fname)) {
                    311:                        if (verbose) {
                    312:                                rprintf(FINFO, "not backing up unsafe symlink \"%s\" -> \"%s\"\n",
                    313:                                        fname, sl);
                    314:                        }
                    315:                        kept = 1;
                    316:                } else {
                    317:                        do_unlink(buf);
                    318:                        if (do_symlink(sl, buf) < 0) {
                    319:                                int save_errno = errno ? errno : EINVAL; /* 0 paranoia */
                    320:                                if (errno == ENOENT && make_bak_dir(buf) == 0) {
                    321:                                        if (do_symlink(sl, buf) < 0)
                    322:                                                save_errno = errno ? errno : save_errno;
                    323:                                        else
                    324:                                                save_errno = 0;
                    325:                                }
                    326:                                if (save_errno) {
                    327:                                        rsyserr(FERROR, save_errno, "link %s -> \"%s\"",
                    328:                                                full_fname(buf), sl);
                    329:                                }
                    330:                        }
                    331:                        do_unlink(fname);
                    332:                        kept = 1;
                    333:                }
                    334:        }
                    335: #endif
                    336: 
                    337:        if (!kept && !S_ISREG(file->mode)) {
                    338:                rprintf(FINFO, "make_bak: skipping non-regular file %s\n",
                    339:                        fname);
                    340:                unmake_file(file);
                    341: #ifdef SUPPORT_ACLS
                    342:                uncache_tmp_acls();
                    343: #endif
                    344: #ifdef SUPPORT_XATTRS
                    345:                uncache_tmp_xattrs();
                    346: #endif
                    347:                return 1;
                    348:        }
                    349: 
                    350:        /* move to keep tree if a file */
                    351:        if (!kept) {
                    352:                if (robust_move(fname, buf) != 0) {
                    353:                        rsyserr(FERROR, errno, "keep_backup failed: %s -> \"%s\"",
                    354:                                full_fname(fname), buf);
                    355:                } else if (sx.st.st_nlink > 1) {
                    356:                        /* If someone has hard-linked the file into the backup
                    357:                         * dir, rename() might return success but do nothing! */
                    358:                        robust_unlink(fname); /* Just in case... */
                    359:                }
                    360:        }
                    361:        preserve_xattrs = 0;
                    362:        set_file_attrs(buf, file, NULL, fname, 0);
                    363:        preserve_xattrs = save_preserve_xattrs;
                    364:        unmake_file(file);
                    365: #ifdef SUPPORT_ACLS
                    366:        uncache_tmp_acls();
                    367: #endif
                    368: #ifdef SUPPORT_XATTRS
                    369:        uncache_tmp_xattrs();
                    370: #endif
                    371: 
                    372:        if (verbose > 1) {
                    373:                rprintf(FINFO, "backed up %s to %s\n",
                    374:                        fname, buf);
                    375:        }
                    376:        return 1;
                    377: }
                    378: 
                    379: 
                    380: /* main backup switch routine */
                    381: int make_backup(const char *fname)
                    382: {
                    383:        if (backup_dir)
                    384:                return keep_backup(fname);
                    385:        return make_simple_backup(fname);
                    386: }

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