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@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 =============================