00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "rsync.h"
00022
00023 extern int verbose;
00024 extern int backup_dir_len;
00025 extern unsigned int backup_dir_remainder;
00026 extern char backup_dir_buf[MAXPATHLEN];
00027 extern char *backup_suffix;
00028 extern char *backup_dir;
00029
00030 extern int am_root;
00031 extern int preserve_acls;
00032 extern int preserve_xattrs;
00033 extern int preserve_devices;
00034 extern int preserve_specials;
00035 extern int preserve_links;
00036 extern int safe_symlinks;
00037
00038
00039 char *get_backup_name(char *fname)
00040 {
00041 if (backup_dir) {
00042 if (stringjoin(backup_dir_buf + backup_dir_len, backup_dir_remainder,
00043 fname, backup_suffix, NULL) < backup_dir_remainder)
00044 return backup_dir_buf;
00045 } else {
00046 if (stringjoin(backup_dir_buf, MAXPATHLEN,
00047 fname, backup_suffix, NULL) < MAXPATHLEN)
00048 return backup_dir_buf;
00049 }
00050
00051 rprintf(FERROR, "backup filename too long\n");
00052 return NULL;
00053 }
00054
00055
00056 static int make_simple_backup(char *fname)
00057 {
00058 int rename_errno;
00059 char *fnamebak = get_backup_name(fname);
00060
00061 if (!fnamebak)
00062 return 0;
00063
00064 while (1) {
00065 if (do_rename(fname, fnamebak) == 0) {
00066 if (verbose > 1) {
00067 rprintf(FINFO, "backed up %s to %s\n",
00068 fname, fnamebak);
00069 }
00070 break;
00071 }
00072
00073 if (errno == ENOENT || errno == EINVAL)
00074 break;
00075
00076 rename_errno = errno;
00077 if (errno == EISDIR && do_rmdir(fnamebak) == 0)
00078 continue;
00079 if (errno == ENOTDIR && do_unlink(fnamebak) == 0)
00080 continue;
00081
00082 rsyserr(FERROR, rename_errno, "rename %s to backup %s",
00083 fname, fnamebak);
00084 errno = rename_errno;
00085 return 0;
00086 }
00087
00088 return 1;
00089 }
00090
00091
00092
00093
00094
00095
00096 static int make_bak_dir(char *fullpath)
00097 {
00098 STRUCT_STAT st;
00099 char *rel = fullpath + backup_dir_len;
00100 char *end = rel + strlen(rel);
00101 char *p = end;
00102
00103 while (strncmp(fullpath, "./", 2) == 0)
00104 fullpath += 2;
00105
00106
00107 while (1) {
00108 if (--p == fullpath) {
00109 p += strlen(p);
00110 goto failure;
00111 }
00112 if (*p == '/') {
00113 *p = '\0';
00114 if (mkdir_defmode(fullpath) == 0)
00115 break;
00116 if (errno != ENOENT) {
00117 rsyserr(FERROR, errno,
00118 "make_bak_dir mkdir %s failed",
00119 full_fname(fullpath));
00120 goto failure;
00121 }
00122 }
00123 }
00124
00125
00126 while (1) {
00127 if (p >= rel) {
00128
00129
00130 if (do_stat(rel, &st) < 0) {
00131 rsyserr(FERROR, errno,
00132 "make_bak_dir stat %s failed",
00133 full_fname(rel));
00134 } else {
00135 do_lchown(fullpath, st.st_uid, st.st_gid);
00136 do_chmod(fullpath, st.st_mode);
00137 #ifdef SUPPORT_ACLS
00138 if (preserve_acls)
00139 dup_acl(end, fullpath, st.st_mode);
00140 #endif
00141 #ifdef SUPPORT_XATTRS
00142 if (preserve_xattrs)
00143 dup_xattr(end, fullpath );
00144 #endif
00145 }
00146 }
00147 *p = '/';
00148 p += strlen(p);
00149 if (p == end)
00150 break;
00151 if (mkdir_defmode(fullpath) < 0) {
00152 rsyserr(FERROR, errno, "make_bak_dir mkdir %s failed",
00153 full_fname(fullpath));
00154 goto failure;
00155 }
00156 }
00157 return 0;
00158
00159 failure:
00160 while (p != end) {
00161 *p = '/';
00162 p += strlen(p);
00163 }
00164 return -1;
00165 }
00166
00167
00168 static int robust_move(char *src, char *dst)
00169 {
00170 if (robust_rename(src, dst, NULL, 0755) < 0
00171 && (errno != ENOENT || make_bak_dir(dst) < 0
00172 || robust_rename(src, dst, NULL, 0755) < 0))
00173 return -1;
00174 return 0;
00175 }
00176
00177
00178
00179
00180 static int keep_backup(char *fname)
00181 {
00182 STRUCT_STAT st;
00183 struct file_struct *file;
00184 char *buf;
00185 int kept = 0;
00186 int ret_code;
00187
00188
00189 if (do_lstat(fname, &st) < 0)
00190 return 1;
00191
00192 if (!(file = make_file(fname, NULL, NULL, 0, NO_FILTERS)))
00193 return 1;
00194
00195 if (!(buf = get_backup_name(fname)))
00196 return 0;
00197
00198 #ifdef SUPPORT_ACLS
00199 if (preserve_acls)
00200 push_keep_backup_acl(file, fname, buf);
00201 #endif
00202 #ifdef SUPPORT_XATTRS
00203 if (preserve_xattrs)
00204 push_keep_backup_xattr(file, fname, buf);
00205 #endif
00206
00207
00208 if ((am_root && preserve_devices && IS_DEVICE(file->mode))
00209 || (preserve_specials && IS_SPECIAL(file->mode))) {
00210 do_unlink(buf);
00211 if (do_mknod(buf, file->mode, file->u.rdev) < 0
00212 && (errno != ENOENT || make_bak_dir(buf) < 0
00213 || do_mknod(buf, file->mode, file->u.rdev) < 0)) {
00214 rsyserr(FERROR, errno, "mknod %s failed",
00215 full_fname(buf));
00216 } else if (verbose > 2) {
00217 rprintf(FINFO, "make_backup: DEVICE %s successful.\n",
00218 fname);
00219 }
00220 kept = 1;
00221 do_unlink(fname);
00222 }
00223
00224 if (!kept && S_ISDIR(file->mode)) {
00225
00226 if (do_mkdir(buf, file->mode) < 0
00227 && (errno != ENOENT || make_bak_dir(buf) < 0
00228 || do_mkdir(buf, file->mode) < 0)) {
00229 rsyserr(FINFO, errno, "mkdir %s failed",
00230 full_fname(buf));
00231 }
00232
00233 ret_code = do_rmdir(fname);
00234 if (verbose > 2) {
00235 rprintf(FINFO, "make_backup: RMDIR %s returns %i\n",
00236 full_fname(fname), ret_code);
00237 }
00238 kept = 1;
00239 }
00240
00241 #ifdef SUPPORT_LINKS
00242 if (!kept && preserve_links && S_ISLNK(file->mode)) {
00243 if (safe_symlinks && unsafe_symlink(file->u.link, buf)) {
00244 if (verbose) {
00245 rprintf(FINFO, "ignoring unsafe symlink %s -> %s\n",
00246 full_fname(buf), file->u.link);
00247 }
00248 kept = 1;
00249 } else {
00250 do_unlink(buf);
00251 if (do_symlink(file->u.link, buf) < 0
00252 && (errno != ENOENT || make_bak_dir(buf) < 0
00253 || do_symlink(file->u.link, buf) < 0)) {
00254 rsyserr(FERROR, errno, "link %s -> \"%s\"",
00255 full_fname(buf),
00256 file->u.link);
00257 }
00258 do_unlink(fname);
00259 kept = 1;
00260 }
00261 }
00262 #endif
00263
00264 if (!kept && !S_ISREG(file->mode)) {
00265 rprintf(FINFO, "make_bak: skipping non-regular file %s\n",
00266 fname);
00267 return 1;
00268 }
00269
00270
00271 if (!kept) {
00272 if (robust_move(fname, buf) != 0) {
00273 rsyserr(FERROR, errno, "keep_backup failed: %s -> \"%s\"",
00274 full_fname(fname), buf);
00275 } else if (st.st_nlink > 1) {
00276
00277
00278 robust_unlink(fname);
00279 }
00280 }
00281 set_file_attrs(buf, file, NULL, 0);
00282 #ifdef SUPPORT_ACLS
00283 if (preserve_acls)
00284 cleanup_keep_backup_acl();
00285 #endif
00286 #ifdef SUPPORT_XATTRS
00287 if (preserve_xattrs)
00288 cleanup_keep_backup_xattr();
00289 #endif
00290 free(file);
00291
00292 if (verbose > 1) {
00293 rprintf(FINFO, "backed up %s to %s\n",
00294 fname, buf);
00295 }
00296 return 1;
00297 }
00298
00299
00300
00301 int make_backup(char *fname)
00302 {
00303 if (backup_dir)
00304 return keep_backup(fname);
00305 return make_simple_backup(fname);
00306 }