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 char *backup_suffix;
00025 extern char *backup_dir;
00026
00027
00028 extern int am_root;
00029 extern int preserve_devices;
00030 extern int preserve_links;
00031 extern int preserve_hard_links;
00032
00033
00034 static int make_simple_backup(char *fname)
00035 {
00036 char fnamebak[MAXPATHLEN];
00037 if (strlen(fname) + strlen(backup_suffix) > (MAXPATHLEN-1)) {
00038 rprintf(FERROR,"backup filename too long\n");
00039 return 0;
00040 }
00041
00042 snprintf(fnamebak,sizeof(fnamebak),"%s%s",fname,backup_suffix);
00043 if (do_rename(fname,fnamebak) != 0) {
00044
00045 if (errno != ENOENT && errno != EINVAL) {
00046 rsyserr(FERROR, errno, "rename %s to backup %s", fname, fnamebak);
00047 return 0;
00048 }
00049 } else if (verbose > 1) {
00050 rprintf(FINFO,"backed up %s to %s\n",fname,fnamebak);
00051 }
00052 return 1;
00053 }
00054
00055
00056
00057 static int make_dir(char *name, int mask)
00058 {
00059 char newdir [MAXPATHLEN];
00060 char *p, *d;
00061
00062
00063 for (p = d = newdir; *name; *d++ = *name++)
00064 if (*name == '/')
00065 p = d;
00066 if (p == newdir)
00067 return 0;
00068 *p = 0;
00069
00070
00071 while (do_mkdir (newdir, mask) != 0)
00072 if ((errno != ENOENT) || !make_dir (newdir, mask))
00073 return 0;
00074
00075 return 1;
00076 }
00077
00078
00079
00080
00081
00082
00083 static int make_bak_dir(char *fname,char *bak_path)
00084 {
00085 STRUCT_STAT st;
00086 STRUCT_STAT *st2;
00087 char fullpath[MAXPATHLEN];
00088 extern int orig_umask;
00089 char *p;
00090 char *q;
00091
00092 while(strncmp(bak_path,"./",2)==0) bak_path += 2;
00093
00094 if(bak_path[strlen(bak_path)-1]!='/') {
00095 snprintf(fullpath,sizeof(fullpath),"%s/",bak_path);
00096 } else {
00097 snprintf(fullpath,sizeof(fullpath),"%s",bak_path);
00098 }
00099 p=fullpath;
00100 q=&fullpath[strlen(fullpath)];
00101 strcat(fullpath,fname);
00102
00103
00104 while ((p=strchr(p,'/'))) {
00105 *p = 0;
00106 if(do_lstat(fullpath,&st)!=0) {
00107 do_mkdir(fullpath,0777 & ~orig_umask);
00108 if(p>q) {
00109 if(do_lstat(q,&st)!=0) {
00110 rprintf(FERROR,"make_bak_dir stat %s : %s\n",fullpath,strerror(errno));
00111 } else {
00112 st2=&st;
00113 set_modtime(fullpath,st2->st_mtime);
00114 if(do_lchown(fullpath,st2->st_uid,st2->st_gid)!=0) {
00115 rprintf(FERROR,"make_bak_dir chown %s : %s\n",fullpath,strerror(errno));
00116 };
00117 if(do_chmod(fullpath,st2->st_mode)!=0) {
00118 rprintf(FERROR,"make_bak_dir failed to set permissions on %s : %s\n",fullpath,strerror(errno));
00119 };
00120 };
00121 }
00122 };
00123 *p = '/';
00124 p++;
00125 }
00126 return 0;
00127 }
00128
00129
00130 static int robust_move(char *src, char *dst)
00131 {
00132 int keep_trying = 4;
00133 int keep_path_extfs = 0;
00134 int failed;
00135
00136 while (keep_trying) {
00137 if (keep_path_extfs) {
00138 failed = copy_file(src, dst, 0755);
00139 if (!failed) {
00140 do_unlink(src);
00141 }
00142 } else {
00143 failed = robust_rename (src, dst);
00144 }
00145
00146 if (failed) {
00147 if (verbose > 2)
00148 rprintf (FERROR, "robust_move failed: %s(%d)\n",
00149 strerror (errno), errno);
00150 switch (errno) {
00151
00152 case EXDEV:
00153 keep_path_extfs = 1;
00154 keep_trying--;
00155 break;
00156
00157 case ENOENT:
00158 make_dir (dst, 0755);
00159 keep_trying--;
00160 break;
00161 default:
00162 keep_trying = 0;
00163 }
00164 } else
00165 keep_trying = 0;
00166 }
00167 return (!failed);
00168 }
00169
00170
00171
00172
00173 static int keep_backup(char *fname)
00174 {
00175
00176 static int initialised;
00177
00178 char keep_name [MAXPATHLEN];
00179 STRUCT_STAT st;
00180 struct file_struct *file;
00181
00182 int kept=0;
00183 int ret_code;
00184
00185 if (!initialised) {
00186 if (backup_dir[strlen(backup_dir) - 1] == '/')
00187 backup_dir[strlen(backup_dir) - 1] = 0;
00188 if (verbose > 0)
00189 rprintf (FINFO, "backup_dir is %s\n", backup_dir);
00190 initialised = 1;
00191 }
00192
00193
00194 #if SUPPORT_LINKS
00195 if (do_lstat (fname, &st)) return 1;
00196 #else
00197 if (do_stat (fname, &st)) return 1;
00198 #endif
00199
00200 file = make_file(-1, fname, NULL, 1);
00201
00202
00203 if (!file) return 1;
00204
00205
00206 if (strlen(backup_dir) + strlen(fname) > (MAXPATHLEN - 1)) {
00207 rprintf (FERROR, "keep_backup filename too long\n");
00208 return 0;
00209 }
00210
00211 snprintf(keep_name, sizeof (keep_name), "%s/%s", backup_dir, fname);
00212
00213
00214 #ifdef HAVE_MKNOD
00215
00216 if(IS_DEVICE(file->mode)) {
00217 if(am_root && preserve_devices) {
00218 make_bak_dir(fname,backup_dir);
00219 if(do_mknod(keep_name,file->mode,file->rdev)!=0) {
00220 rprintf(FERROR,"mknod %s : %s\n",keep_name,strerror(errno));
00221 } else {
00222 if(verbose>2)
00223 rprintf(FINFO,"make_backup : DEVICE %s successful.\n",fname);
00224 };
00225 };
00226 kept=1;
00227 do_unlink(fname);
00228 };
00229 #endif
00230
00231 if(!kept && S_ISDIR(file->mode)) {
00232
00233 make_bak_dir(fname,backup_dir);
00234 do_mkdir(keep_name,file->mode);
00235 ret_code=do_rmdir(fname);
00236 if(verbose>2)
00237 rprintf(FINFO,"make_backup : RMDIR %s returns %i\n",fname,ret_code);
00238 kept=1;
00239 };
00240
00241 #if SUPPORT_LINKS
00242 if(!kept && preserve_links && S_ISLNK(file->mode)) {
00243 extern int safe_symlinks;
00244 if (safe_symlinks && unsafe_symlink(file->link, keep_name)) {
00245 if (verbose) {
00246 rprintf(FINFO,"ignoring unsafe symlink %s -> %s\n",
00247 keep_name,file->link);
00248 }
00249 kept=1;
00250 }
00251 make_bak_dir(fname,backup_dir);
00252 if(do_symlink(file->link,keep_name) != 0) {
00253 rprintf(FERROR,"link %s -> %s : %s\n",keep_name,file->link,strerror(errno));
00254 };
00255 do_unlink(fname);
00256 kept=1;
00257 };
00258 #endif
00259 if(!kept && preserve_hard_links && check_hard_link(file)) {
00260 if(verbose > 1) rprintf(FINFO,"%s is a hard link\n",f_name(file));
00261 };
00262
00263 if(!kept && !S_ISREG(file->mode)) {
00264 rprintf(FINFO,"make_bak: skipping non-regular file %s\n",fname);
00265 }
00266
00267
00268 if(!kept) {
00269 if (!robust_move (fname, keep_name))
00270 rprintf(FERROR, "keep_backup failed %s -> %s : %s\n",
00271 fname, keep_name, strerror(errno));
00272 };
00273 set_perms (keep_name, file, NULL, 0);
00274 free_file (file);
00275 free (file);
00276
00277 if (verbose > 1)
00278 rprintf (FINFO, "keep_backup %s -> %s\n", fname, keep_name);
00279 return 1;
00280 }
00281
00282
00283
00284 int make_backup(char *fname)
00285 {
00286 if (backup_dir)
00287 return (keep_backup(fname));
00288 else
00289 return (make_simple_backup(fname));
00290 }
00291