new option suggestion '--backup-only'

Takeru KOMORIYA komoriya at paken.org
Fri Sep 5 17:02:11 EST 2003


Hi,

How about adding now option '--backup-only'  that means making backups
only and don't change any destination files?

(I posted similar patch a month ago, but the patch was made for
 nightly snapshot of 20020808, which was tooo old! Laugh at me...)

I want to use rsync with LVM snapshot to make incremental backups like
below:

  1) Make LVM snapshot of file system and mount it.
  2) Compare it to yesterday's snapshot, and backup files which are
     updated or deleted.
     ex) rsync -a --delete --backup --backup-dir=/backup/backup_on_$DATE
  3) Delete yesterday's snapshot.

The problem is that LVM snapshots are read-only, so I need rsync not
to modefy any destination files.

I made trial patch against latest CVS, and this works fine for me.

With this patch, new options '--backup-only' is added, and the
'--backup-dir' option implies '--backup' for convinience.

How about merging it?

Regards,
-----------------------
Takeru Komoriya
 komoriya at paken.org
 http://www.paken.org/

===================================================================
diff -ur rsync/backup.c rsync-backuponly/backup.c
--- rsync/backup.c	2003-08-22 09:30:46.000000000 +0900
+++ rsync-backuponly/backup.c	2003-09-02 15:29:03.000000000 +0900
@@ -25,6 +25,7 @@
 extern int backup_dir_len;
 extern char *backup_suffix;
 extern char *backup_dir;
+extern int backup_only;
 
 extern int am_root;
 extern int preserve_devices;
@@ -133,21 +134,26 @@
 	int keep_trying = 4;
 	int keep_path_extfs = 0;
 	int failed;
+	int saveerrno;
 
 	while (keep_trying) {
-		if (keep_path_extfs) {
+		if (keep_path_extfs || backup_only) {
 			failed = copy_file(src, dst, 0755);
+			saveerrno = errno;
 			if (!failed) {
 				do_unlink(src);
+				saveerrno = errno;
 			}
 		} else {
 			failed = robust_rename (src, dst);
+			saveerrno = errno;
 		}
 
 		if (failed) {
 			if (verbose > 2)
 				rprintf (FERROR, "robust_move failed: %s(%d)\n",
 				    strerror (errno), errno);
+			errno = saveerrno;
 			switch (errno) {
 				/* external filesystem */
 				case EXDEV:
@@ -225,7 +231,8 @@
 			}
 		}
 		kept = 1;
-		do_unlink(fname);
+		if (!backup_only)
+			do_unlink(fname);
 	}
 #endif
 
@@ -233,11 +240,11 @@
 		/* make an empty directory */
 		make_bak_dir(fname, backup_dir);
 		do_mkdir(keep_name, file->mode);
-		ret_code = do_rmdir(fname);
 
-		if(verbose>2) {
-			rprintf(FINFO, "make_backup : RMDIR %s returns %i\n",
-			    fname, ret_code);
+		if (!backup_only) {
+			ret_code=do_rmdir(fname);
+			if(verbose>2)
+				rprintf(FINFO,"make_backup : RMDIR %s returns %i\n",fname,ret_code);
 		}
 		kept = 1;
 	}
@@ -257,7 +264,8 @@
 			rprintf(FERROR, "link %s -> %s : %s\n",
 			    keep_name, file->link, strerror(errno));
 		}
-		do_unlink(fname);
+		if (!backup_only)
+			do_unlink(fname);
 		kept = 1;
 	}
 #endif
diff -ur rsync/generator.c rsync-backuponly/generator.c
--- rsync/generator.c	2003-08-22 14:42:13.000000000 +0900
+++ rsync-backuponly/generator.c	2003-09-02 15:44:26.000000000 +0900
@@ -41,6 +41,7 @@
 extern int modify_window;
 extern char *compare_dest;
 extern int link_dest;
+extern int backup_only;
 
 
 /* choose whether to skip a particular file */
@@ -295,6 +296,9 @@
 		return;
 	}
 
+	if (backup_only && statret == -1 && errno == ENOENT)
+		return;
+
 	if (statret == 0 &&
 	    !preserve_perms &&
 	    (S_ISDIR(st.st_mode) == S_ISDIR(file->mode))) {
@@ -313,6 +317,8 @@
 
 		if (dry_run) return; /* XXXX -- might cause inaccuracies?? -- mbp */
 		if (statret == 0 && !S_ISDIR(st.st_mode)) {
+			if (backup_only)
+				return;
 			if (robust_unlink(fname) != 0) {
 				rprintf(FERROR, RSYNC_NAME
 					": recv_generator: unlink \"%s\" to make room for directory: %s\n",
@@ -321,6 +327,8 @@
 			}
 			statret = -1;
 		}
+		if (backup_only)
+			return;
 		if (statret != 0 && do_mkdir(fname,file->mode) != 0 && errno != EEXIST) {
 			if (!(relative_paths && errno==ENOENT &&
 			      create_directory_path(fname, orig_umask)==0 &&
@@ -357,6 +365,8 @@
 				 * right place -- no further action
 				 * required. */
 				if (strcmp(lnk,file->link) == 0) {
+					if (backup_only)
+						return;
 					set_perms(fname,file,&st,1);
 					return;
 				}
@@ -364,8 +374,12 @@
 			/* Not a symlink, so delete whatever's
 			 * already there and put a new symlink
 			 * in place. */
+			if (backup_only)
+				return;
 			delete_file(fname);
 		}
+		if (backup_only)
+			return;
 		if (do_symlink(file->link,fname) != 0) {
 			rprintf(FERROR,RSYNC_NAME": symlink \"%s\" -> \"%s\": %s\n",
 				fname,file->link,strerror(errno));
@@ -384,6 +398,8 @@
 		if (statret != 0 ||
 		    st.st_mode != file->mode ||
 		    (DEV64_T)st.st_rdev != file->rdev) {
+			if (backup_only)
+				return;
 			delete_file(fname);
 			if (verbose > 2)
 				rprintf(FINFO,"mknod(%s,0%o,0x%x)\n",
@@ -396,6 +412,8 @@
 					rprintf(FINFO,"%s\n",fname);
 			}
 		} else {
+			if (backup_only)
+				return;
 			set_perms(fname,file,&st,1);
 		}
 		return;
@@ -454,6 +472,8 @@
 	}
 
 	if (!S_ISREG(st.st_mode)) {
+		if (backup_only)
+			return;
 		if (delete_file(fname) != 0) {
 			return;
 		}
@@ -477,7 +497,7 @@
 	}
 
 	if (skip_file(fname, file, &st)) {
-		if (fnamecmp == fname)
+		if ((fnamecmp == fname) && !backup_only)
 			set_perms(fname,file,&st,1);
 		return;
 	}
@@ -487,6 +507,11 @@
 		return;
 	}
 
+	if (backup_only) {
+		make_backup(fname);
+		return;
+	}
+
 	if (disable_deltas_p()) {
 		write_int(f_out,i);
 		write_sum_head(f_out, NULL);
diff -ur rsync/options.c rsync-backuponly/options.c
--- rsync/options.c	2003-08-06 15:45:14.000000000 +0900
+++ rsync-backuponly/options.c	2003-09-02 15:53:10.000000000 +0900
@@ -119,6 +119,7 @@
 char *backup_dir = NULL;
 int rsync_port = RSYNC_PORT;
 int link_dest = 0;
+int backup_only = 0;
 
 int verbose = 0;
 int quiet = 0;
@@ -222,6 +223,7 @@
   rprintf(F," -b, --backup                make backups (default %s suffix)\n",BACKUP_SUFFIX);
   rprintf(F,"     --backup-dir            make backups into this directory\n");
   rprintf(F,"     --suffix=SUFFIX         override backup suffix\n");
+  rprintf(F,"     --backup-only           make backups only, keeping destination files unchanged\n");
   rprintf(F," -u, --update                update only (don't overwrite newer files)\n");
   rprintf(F," -l, --links                 copy symlinks as symlinks\n");
   rprintf(F," -L, --copy-links            copy the referent of symlinks\n");
@@ -297,7 +299,7 @@
 enum {OPT_VERSION = 1000, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
       OPT_DELETE_AFTER, OPT_DELETE_EXCLUDED, OPT_LINK_DEST,
       OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW,
-      OPT_READ_BATCH, OPT_WRITE_BATCH};
+      OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_BACKUP_DIR};
 
 static struct poptOption long_options[] = {
   /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
@@ -369,13 +371,14 @@
   {"log-format",       0,  POPT_ARG_STRING, &log_format, 0, 0, 0 },
   {"bwlimit",          0,  POPT_ARG_INT,    &bwlimit, 0, 0, 0 },
   {"address",          0,  POPT_ARG_STRING, &bind_address, 0, 0, 0 },
-  {"backup-dir",       0,  POPT_ARG_STRING, &backup_dir, 0, 0, 0 },
+  {"backup-dir",       0,  POPT_ARG_STRING, &backup_dir, OPT_BACKUP_DIR, 0, 0 },
   {"hard-links",      'H', POPT_ARG_NONE,   &preserve_hard_links, 0, 0, 0 },
   {"read-batch",       0,  POPT_ARG_STRING, &batch_prefix,  OPT_READ_BATCH, 0, 0 },
   {"write-batch",      0,  POPT_ARG_STRING, &batch_prefix,  OPT_WRITE_BATCH, 0, 0 },
   {"files-from",       0,  POPT_ARG_STRING, &files_from, 0, 0, 0 },
   {"from0",           '0', POPT_ARG_NONE,   &eol_nulls, 0, 0, 0},
   {"no-implied-dirs",  0,  POPT_ARG_VAL,    &implied_dirs, 0, 0, 0 },
+  {"backup-only",      0,  POPT_ARG_NONE,   &backup_only , 0, 0, 0 },
 #ifdef INET6
   {0,		      '4', POPT_ARG_VAL,    &default_af_hint, AF_INET, 0, 0 },
   {0,		      '6', POPT_ARG_VAL,    &default_af_hint, AF_INET6, 0, 0 },
@@ -584,6 +587,11 @@
 			return 0;
 #endif
 
+		case OPT_BACKUP_DIR:
+			/* --backup-dir implies --backup */
+			make_backups = 1;
+			break;
+
 
 		default:
 			/* FIXME: If --daemon is specified, then errors for later
@@ -644,6 +652,12 @@
 	if (do_progress && !verbose)
 		verbose = 1;
 
+	if (backup_only && !backup_dir) {
+		rprintf(FERROR,
+			"--backup-dir must be specified with --backup-only\n");
+		exit_cleanup(RERR_SYNTAX);
+	}
+
 	*argv = poptGetArgs(pc);
 	if (*argv)
 		*argc = count_args(*argv);
@@ -879,6 +893,9 @@
 		args[ac++] = tmpdir;
 	}
 
+	if (backup_only && am_sender)
+		args[ac++] = "--backup-only";
+
 	if (compare_dest && am_sender) {
 		/* the server only needs this option if it is not the sender,
 		 *   and it may be an older version that doesn't know this
diff -ur rsync/receiver.c rsync-backuponly/receiver.c
--- rsync/receiver.c	2003-09-05 14:53:55.000000000 +0900
+++ rsync-backuponly/receiver.c	2003-09-05 15:06:37.000000000 +0900
@@ -39,6 +39,7 @@
 extern char *backup_dir;
 extern char *backup_suffix;
 extern int backup_suffix_len;
+extern int backup_only;
 
 static struct delete_list {
 	DEV64_T dev;
@@ -159,13 +160,14 @@
 				char *f = f_name(local_file_list->files[i]);
 				if (make_backups && (backup_dir || !is_backup_file(f))) {
 					(void) make_backup(f);
-					if (verbose)
+					if (verbose && !backup_only)
 						rprintf(FINFO, "deleting %s\n", f);
 				} else {
 					int mode = local_file_list->files[i]->mode;
 					delete_one(f, S_ISDIR(mode) != 0);
 				}
-				deletion_count++;
+				if (!backup_only)
+					deletion_count++;
 			}
 		}
 		flist_free(local_file_list);
@@ -535,15 +537,17 @@
 		}
 	}
 
-	if (preserve_hard_links)
-		do_hard_links();
-
-	/* now we need to fix any directory permissions that were 
-	   modified during the transfer */
-	for (i = 0; i < flist->count; i++) {
-		file = flist->files[i];
-		if (!file->basename || !S_ISDIR(file->mode)) continue;
-		recv_generator(local_name?local_name:f_name(file),flist,i,-1);
+	if (!backup_only) {
+		if (preserve_hard_links)
+			do_hard_links();
+
+		/* now we need to fix any directory permissions that were 
+		   modified during the transfer */
+		for (i = 0; i < flist->count; i++) {
+			file = flist->files[i];
+			if (!file->basename || !S_ISDIR(file->mode)) continue;
+			recv_generator(local_name?local_name:f_name(file),flist,i,-1);
+		}
 	}
 
 	if (verbose > 2)
diff -ur rsync/rsync.c rsync-backuponly/rsync.c
--- rsync/rsync.c	2003-02-19 03:07:36.000000000 +0900
+++ rsync-backuponly/rsync.c	2003-09-02 16:12:51.000000000 +0900
@@ -30,6 +30,7 @@
 extern int preserve_gid;
 extern int preserve_perms;
 extern int make_backups;
+extern int backup_only;
 
 
 /*
@@ -237,6 +238,9 @@
 	if (make_backups && !make_backup(fname))
 		return;
 
+	if (backup_only)
+		return;
+
 	/* move tmp file over real file */
 	if (robust_rename(fnametmp,fname) != 0) {
 		if (errno == EXDEV) {
diff -ur rsync/util.c rsync-backuponly/util.c
--- rsync/util.c	2003-07-02 06:45:31.000000000 +0900
+++ rsync-backuponly/util.c	2003-09-02 16:06:44.000000000 +0900
@@ -268,18 +268,23 @@
 
 	ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode);
 	if (ofd == -1) {
-		rprintf(FERROR,"open %s: %s\n",
-			dest,strerror(errno));
-		close(ifd);
+		int saveerrno = errno;
+		if (verbose > 2)
+			rprintf(FERROR,"open %s: %s\n",
+				dest,strerror(errno));
+ 		close(ifd);
+		errno = saveerrno;
 		return -1;
 	}
 
 	while ((len = safe_read(ifd, buf, sizeof(buf))) > 0) {
 		if (full_write(ofd, buf, len) < 0) {
+			int saveerrno = errno;
 			rprintf(FERROR,"write %s: %s\n",
 				dest,strerror(errno));
 			close(ifd);
 			close(ofd);
+			errno = saveerrno;
 			return -1;
 		}
 	}
===================== end of the patch =============================



More information about the rsync mailing list