Fixed failing hunk.
[rsync/rsync-patches.git] / backup-dir-dels.diff
CommitLineData
8af83008 1This patches creates two new command line options as follows:
79f132a1
WD
2 --backup-dir-rm
3 --backup-suffix-rm=SUFFIX
8af83008 4
79f132a1
WD
5The backup-dir-rm and backup-suffix-rm options give the ability to store
6backup of removed files on the receiver in different directories or with
7different suffix than the backup of files that have been changed but that
8are still on the source drive. Both commands can be combined.
8af83008
WD
9
10The default behaviour if one or both of the options are not specified
11is the previous behaviour, both backups use the same directory or
12suffix.
13
14Marc St-Onge
15
159b101f 16--- orig/backup.c 2005-02-14 02:45:09
44917741 17+++ backup.c 2004-09-22 02:36:06
8af83008
WD
18@@ -22,11 +22,17 @@
19
20 extern int verbose;
21 extern int backup_suffix_len;
79f132a1 22+extern int backup_suffix_rm_len;
8af83008 23 extern int backup_dir_len;
79f132a1 24+extern int backup_dir_rm_len;
8af83008 25 extern unsigned int backup_dir_remainder;
79f132a1 26+extern unsigned int backup_dir_rm_remainder;
8af83008 27 extern char backup_dir_buf[MAXPATHLEN];
79f132a1 28+extern char backup_dir_rm_buf[MAXPATHLEN];
8af83008 29 extern char *backup_suffix;
79f132a1 30+extern char *backup_suffix_rm;
8af83008 31 extern char *backup_dir;
79f132a1 32+extern char *backup_dir_rm;
8af83008
WD
33
34 extern int am_root;
35 extern int preserve_devices;
36@@ -35,6 +41,8 @@ extern int preserve_hard_links;
37 extern int orig_umask;
38 extern int safe_symlinks;
39
40+static int deleting;
41+
42 /* make a complete pathname for backup file */
43 char *get_backup_name(char *fname)
44 {
45@@ -52,10 +60,27 @@ char *get_backup_name(char *fname)
46 return NULL;
47 }
48
49+static char *get_delete_name(char *fname)
50+{
79f132a1
WD
51+ if (backup_dir_rm) {
52+ if (stringjoin(backup_dir_rm_buf + backup_dir_rm_len, backup_dir_rm_remainder,
53+ fname, backup_suffix_rm, NULL) < backup_dir_rm_remainder)
54+ return backup_dir_rm_buf;
8af83008 55+ } else {
79f132a1
WD
56+ if (stringjoin(backup_dir_rm_buf, MAXPATHLEN,
57+ fname, backup_suffix_rm, NULL) < MAXPATHLEN)
58+ return backup_dir_rm_buf;
8af83008
WD
59+ }
60+
61+ rprintf(FERROR, "delete filename too long\n");
62+ return NULL;
63+}
64+
65 /* simple backup creates a backup with a suffix in the same directory */
66 static int make_simple_backup(char *fname)
67 {
68- char *fnamebak = get_backup_name(fname);
69+ char *fnamebak = deleting ? get_delete_name(fname)
70+ : get_backup_name(fname);
71
72 if (!fnamebak)
73 return 0;
27a7053c 74@@ -83,7 +108,8 @@ path
8af83008
WD
75 static int make_bak_dir(char *fullpath)
76 {
77 STRUCT_STAT st;
78- char *rel = fullpath + backup_dir_len;
79f132a1 79+ int dir_len = deleting ? backup_dir_rm_len : backup_dir_len;
8af83008
WD
80+ char *rel = fullpath + dir_len;
81 char *end = rel + strlen(rel);
82 char *p = end;
83
27a7053c 84@@ -170,7 +196,8 @@ static int keep_backup(char *fname)
4f9b6a01 85 if (!(file = make_file(fname, NULL, NO_FILTERS)))
8af83008
WD
86 return 1; /* the file could have disappeared */
87
88- if (!(buf = get_backup_name(fname)))
89+ buf = deleting ? get_delete_name(fname) : get_backup_name(fname);
90+ if (!buf)
91 return 0;
92
57e73b72 93 /* Check to see if this is a device file, or link */
27a7053c 94@@ -263,3 +290,13 @@ int make_backup(char *fname)
44917741
WD
95 return keep_backup(fname);
96 return make_simple_backup(fname);
97 }
8af83008 98+
79f132a1 99+/* backup switch routine called only when backing-up removed file */
8af83008
WD
100+int safe_delete(char *fname)
101+{
44917741 102+ int ret;
8af83008 103+ deleting = 1;
44917741
WD
104+ ret = make_backup(fname);
105+ deleting = 0;
106+ return ret;
107+}
6e93e60a
WD
108--- orig/options.c 2005-02-20 01:12:42
109+++ options.c 2005-02-20 03:09:33
110@@ -121,10 +121,14 @@ int no_detach = 0;
8af83008
WD
111 int write_batch = 0;
112 int read_batch = 0;
113 int backup_dir_len = 0;
79f132a1 114+int backup_dir_rm_len = 0;
8af83008 115 int backup_suffix_len;
79f132a1 116+int backup_suffix_rm_len;
8af83008 117 unsigned int backup_dir_remainder;
79f132a1 118+unsigned int backup_dir_rm_remainder;
8af83008
WD
119
120 char *backup_suffix = NULL;
79f132a1 121+char *backup_suffix_rm = NULL;
8af83008
WD
122 char *tmpdir = NULL;
123 char *partial_dir = NULL;
daceaa67 124 char *basis_dir[MAX_BASIS_DIRS+1];
6e93e60a 125@@ -134,7 +138,9 @@ char *log_format = NULL;
8af83008
WD
126 char *password_file = NULL;
127 char *rsync_path = RSYNC_PATH;
128 char *backup_dir = NULL;
79f132a1 129+char *backup_dir_rm = NULL;
8af83008 130 char backup_dir_buf[MAXPATHLEN];
79f132a1 131+char backup_dir_rm_buf[MAXPATHLEN];
daceaa67 132 int rsync_port = 0;
c59d6641 133 int compare_dest = 0;
daceaa67 134 int copy_dest = 0;
6e93e60a 135@@ -265,6 +271,8 @@ void usage(enum logcode F)
8af83008 136 rprintf(F," -b, --backup make backups (see --suffix & --backup-dir)\n");
79f132a1
WD
137 rprintf(F," --backup-dir=DIR make backups into hierarchy based in DIR\n");
138 rprintf(F," --suffix=SUFFIX set backup suffix (default %s w/o --backup-dir)\n",BACKUP_SUFFIX);
139+ rprintf(F," --backup-dir-rm make backups of removed files into current dir\n");
140+ rprintf(F," --backup-suffix-rm=SUF set removed-files suffix (defaults to --suffix)\n");
141 rprintf(F," -u, --update skip files that are newer on the receiver\n");
0b2fb126 142 rprintf(F," --inplace update destination files in-place (SEE MAN PAGE)\n");
fd0e045e 143 rprintf(F," -d, --dirs transfer directories without recursing\n");
6e93e60a 144@@ -360,6 +368,7 @@ static struct poptOption long_options[]
8af83008 145 /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
57e73b72 146 {"version", 0, POPT_ARG_NONE, 0, OPT_VERSION, 0, 0},
8af83008 147 {"suffix", 0, POPT_ARG_STRING, &backup_suffix, 0, 0, 0 },
79f132a1 148+ {"backup-suffix-rm", 0, POPT_ARG_STRING, &backup_suffix_rm, 0, 0, 0 },
8af83008
WD
149 {"rsync-path", 0, POPT_ARG_STRING, &rsync_path, 0, 0, 0 },
150 {"password-file", 0, POPT_ARG_STRING, &password_file, 0, 0, 0 },
151 {"ignore-times", 'I', POPT_ARG_NONE, &ignore_times, 0, 0, 0 },
6e93e60a 152@@ -440,6 +449,7 @@ static struct poptOption long_options[]
159b101f 153 {"itemize-changes", 'i', POPT_ARG_NONE, &itemize_changes, 0, 0, 0 },
8af83008 154 {"bwlimit", 0, POPT_ARG_INT, &bwlimit, 0, 0, 0 },
8af83008 155 {"backup-dir", 0, POPT_ARG_STRING, &backup_dir, 0, 0, 0 },
79f132a1 156+ {"backup-dir-rm", 0, POPT_ARG_STRING, &backup_dir_rm, 0, 0, 0 },
8af83008 157 {"hard-links", 'H', POPT_ARG_NONE, &preserve_hard_links, 0, 0, 0 },
57e73b72
WD
158 {"read-batch", 0, POPT_ARG_STRING, &batch_name, OPT_READ_BATCH, 0, 0 },
159 {"write-batch", 0, POPT_ARG_STRING, &batch_name, OPT_WRITE_BATCH, 0, 0 },
6e93e60a 160@@ -1006,6 +1016,8 @@ int parse_arguments(int *argc, const cha
daceaa67 161 partial_dir = sanitize_path(NULL, partial_dir, NULL, 0);
8af83008
WD
162 if (backup_dir)
163 backup_dir = sanitize_path(NULL, backup_dir, NULL, 0);
79f132a1
WD
164+ if (backup_dir_rm)
165+ backup_dir_rm = sanitize_path(NULL, backup_dir_rm, NULL, 0);
8af83008
WD
166 if (files_from)
167 files_from = sanitize_path(NULL, files_from, NULL, 0);
168 }
6e93e60a 169@@ -1038,6 +1050,12 @@ int parse_arguments(int *argc, const cha
4f9b6a01 170 if (check_filter(elp, backup_dir, 1) < 0)
8af83008
WD
171 goto options_rejected;
172 }
79f132a1
WD
173+ /* Clean backup_dir_rm same as for backup_dir */
174+ if (backup_dir_rm) {
175+ clean_fname(backup_dir_rm, 1);
6e93e60a 176+ if (check_filter(elp, backup_dir_rm, 1) < 0)
8af83008
WD
177+ goto options_rejected;
178+ }
179 }
4f9b6a01 180 if (server_filter_list.head && files_from) {
27a7053c 181 if (!*files_from)
6e93e60a 182@@ -1060,6 +1078,16 @@ int parse_arguments(int *argc, const cha
8af83008
WD
183 backup_suffix);
184 return 0;
185 }
79f132a1
WD
186+ /* if suffix_rm not supplied, default to backup_suffix */
187+ if (!backup_suffix_rm)
188+ backup_suffix_rm = backup_dir_rm ? "" : backup_suffix;
189+ backup_suffix_rm_len = strlen(backup_suffix_rm);
190+ if (strchr(backup_suffix_rm, '/') != NULL) {
8af83008 191+ snprintf(err_buf, sizeof err_buf,
79f132a1
WD
192+ "--backup-suffix-rm cannot contain slashes: %s\n",
193+ backup_suffix_rm);
8af83008
WD
194+ return 0;
195+ }
196 if (backup_dir) {
197 backup_dir_len = strlcpy(backup_dir_buf, backup_dir, sizeof backup_dir_buf);
198 backup_dir_remainder = sizeof backup_dir_buf - backup_dir_len;
6e93e60a 199@@ -1081,6 +1109,31 @@ int parse_arguments(int *argc, const cha
8af83008
WD
200 "--suffix cannot be a null string without --backup-dir\n");
201 return 0;
202 }
79f132a1
WD
203+ /* If backup_dir_rm not supplied default to backup_dir if it has been supplied */
204+ if (backup_dir && !backup_dir_rm) {
205+ backup_dir_rm = backup_dir;
206+ backup_dir_rm_len = backup_dir_len;
207+ backup_dir_rm_remainder = backup_dir_remainder;
208+ strlcpy(backup_dir_rm_buf, backup_dir_buf, sizeof backup_dir_buf);
209+ } else if (backup_dir_rm) {
210+ backup_dir_rm_len = strlcpy(backup_dir_rm_buf, backup_dir_rm, sizeof backup_dir_rm_buf);
211+ backup_dir_rm_remainder = sizeof backup_dir_rm_buf - backup_dir_rm_len;
212+ if (backup_dir_rm_remainder < 32) {
8af83008 213+ snprintf(err_buf, sizeof err_buf,
79f132a1 214+ "the --backup-dir-rm path is WAY too long.\n");
8af83008
WD
215+ return 0;
216+ }
79f132a1
WD
217+ if (backup_dir_rm_buf[backup_dir_rm_len - 1] != '/') {
218+ backup_dir_rm_buf[backup_dir_rm_len++] = '/';
219+ backup_dir_rm_buf[backup_dir_rm_len] = '\0';
8af83008
WD
220+ }
221+ if (verbose > 1 && !am_sender)
79f132a1
WD
222+ rprintf(FINFO, "backup_dir_rm is %s\n", backup_dir_rm_buf);
223+ } else if (!backup_suffix_rm_len && (!am_server || !am_sender)) {
8af83008 224+ snprintf(err_buf, sizeof err_buf,
79f132a1 225+ "--backup-suffix-rm cannot be a null string without --backup-dir-rm\n");
8af83008
WD
226+ return 0;
227+ }
228
5a56905b
WD
229 if (log_format) {
230 if (strstr(log_format, "%i") != NULL)
6e93e60a 231@@ -1344,6 +1397,10 @@ void server_options(char **args,int *arg
8af83008
WD
232 args[ac++] = "--backup-dir";
233 args[ac++] = backup_dir;
234 }
79f132a1
WD
235+ if (backup_dir_rm) {
236+ args[ac++] = "--backup-dir-rm";
237+ args[ac++] = backup_dir_rm;
8af83008
WD
238+ }
239
240 /* Only send --suffix if it specifies a non-default value. */
241 if (strcmp(backup_suffix, backup_dir ? "" : BACKUP_SUFFIX) != 0) {
6e93e60a 242@@ -1352,7 +1409,13 @@ void server_options(char **args,int *arg
8af83008
WD
243 goto oom;
244 args[ac++] = arg;
245 }
246-
79f132a1
WD
247+ /* Only send --backup-suffix-rm if it specifies a non-default value. */
248+ if (strcmp(backup_suffix_rm, backup_dir_rm ? "" : BACKUP_SUFFIX) != 0) {
8af83008 249+ /* We use the following syntax to avoid weirdness with '~'. */
79f132a1 250+ if (asprintf(&arg, "--backup-suffix-rm=%s", backup_suffix_rm) < 0)
8af83008
WD
251+ goto oom;
252+ args[ac++] = arg;
253+ }
254 if (am_sender) {
255 if (delete_excluded)
256 args[ac++] = "--delete-excluded";
1d15f8d9 257--- orig/rsync.c 2005-02-20 00:02:23
6e93e60a 258+++ rsync.c 2005-02-20 03:08:42
1d15f8d9
WD
259@@ -44,12 +44,19 @@ extern char *backup_dir;
260 extern char *log_format;
261 extern char *backup_suffix;
262 extern int backup_suffix_len;
263+extern char *backup_dir_rm;
264+extern char *backup_suffix_rm;
265+extern int backup_suffix_rm_len;
266
267
268+/* Function now checks if file matches backup or delete suffix patterns */
269 static int is_backup_file(char *fn)
270 {
271 int k = strlen(fn) - backup_suffix_len;
272- return k > 0 && strcmp(fn+k, backup_suffix) == 0;
273+ if (k > 0 && strcmp(fn+k, backup_suffix) == 0)
274+ return 1;
275+ k += backup_suffix_len - backup_suffix_rm_len;
276+ return k > 0 && strcmp(fn+k, backup_suffix_rm) == 0;
277 }
278
279
280@@ -82,8 +89,9 @@ int delete_file(char *fname, int mode, i
281
282 if (!S_ISDIR(mode)) {
283 int ok;
284- if (make_backups && (backup_dir || !is_backup_file(fname)))
285- ok = make_backup(fname);
6e93e60a 286+ int backup_file = is_backup_file(fname);
1d15f8d9
WD
287+ if (make_backups && (backup_dir_rm || !backup_file))
288+ ok = safe_delete(fname);
289 else
290 ok = robust_unlink(fname) == 0;
291 if (ok) {