Updated to apply cleanly.
[rsync/rsync-patches.git] / backup-dir-dels.diff
CommitLineData
8af83008 1This patches creates two new command line options as follows:
19a778eb
WD
2 --backup-dir-dels=DIR
3 --suffix-dels=SUFFIX
8af83008 4
19a778eb 5The backup-dir-dels and suffix-dels options give the ability to store
79f132a1
WD
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
8f72c7ae 16--- orig/backup.c 2005-02-22 01:57:58
4877ebcc 17+++ backup.c 2005-02-22 02:11:15
8af83008
WD
18@@ -22,11 +22,17 @@
19
20 extern int verbose;
21 extern int backup_suffix_len;
19a778eb 22+extern int backup_suffix_dels_len;
8af83008 23 extern int backup_dir_len;
19a778eb 24+extern int backup_dir_dels_len;
8af83008 25 extern unsigned int backup_dir_remainder;
19a778eb 26+extern unsigned int backup_dir_dels_remainder;
8af83008 27 extern char backup_dir_buf[MAXPATHLEN];
19a778eb 28+extern char backup_dir_dels_buf[MAXPATHLEN];
8af83008 29 extern char *backup_suffix;
19a778eb 30+extern char *backup_suffix_dels;
8af83008 31 extern char *backup_dir;
19a778eb 32+extern char *backup_dir_dels;
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 {
4877ebcc 45@@ -52,11 +60,28 @@ char *get_backup_name(char *fname)
8af83008
WD
46 return NULL;
47 }
48
49+static char *get_delete_name(char *fname)
50+{
19a778eb
WD
51+ if (backup_dir_dels) {
52+ if (stringjoin(backup_dir_dels_buf + backup_dir_dels_len, backup_dir_dels_remainder,
53+ fname, backup_suffix_dels, NULL) < backup_dir_dels_remainder)
54+ return backup_dir_dels_buf;
8af83008 55+ } else {
19a778eb
WD
56+ if (stringjoin(backup_dir_dels_buf, MAXPATHLEN,
57+ fname, backup_suffix_dels, NULL) < MAXPATHLEN)
58+ return backup_dir_dels_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 {
4877ebcc 68 int rename_errno;
8af83008
WD
69- char *fnamebak = get_backup_name(fname);
70+ char *fnamebak = deleting ? get_delete_name(fname)
71+ : get_backup_name(fname);
72
73 if (!fnamebak)
74 return 0;
4877ebcc 75@@ -97,7 +122,8 @@ path
8af83008
WD
76 static int make_bak_dir(char *fullpath)
77 {
78 STRUCT_STAT st;
79- char *rel = fullpath + backup_dir_len;
19a778eb 80+ int dir_len = deleting ? backup_dir_dels_len : backup_dir_len;
8af83008
WD
81+ char *rel = fullpath + dir_len;
82 char *end = rel + strlen(rel);
83 char *p = end;
84
4877ebcc 85@@ -184,7 +210,8 @@ static int keep_backup(char *fname)
4f9b6a01 86 if (!(file = make_file(fname, NULL, NO_FILTERS)))
8af83008
WD
87 return 1; /* the file could have disappeared */
88
89- if (!(buf = get_backup_name(fname)))
90+ buf = deleting ? get_delete_name(fname) : get_backup_name(fname);
91+ if (!buf)
92 return 0;
93
57e73b72 94 /* Check to see if this is a device file, or link */
4877ebcc 95@@ -277,3 +304,13 @@ int make_backup(char *fname)
44917741
WD
96 return keep_backup(fname);
97 return make_simple_backup(fname);
98 }
8af83008 99+
79f132a1 100+/* backup switch routine called only when backing-up removed file */
8af83008
WD
101+int safe_delete(char *fname)
102+{
44917741 103+ int ret;
8af83008 104+ deleting = 1;
44917741
WD
105+ ret = make_backup(fname);
106+ deleting = 0;
107+ return ret;
108+}
e3e93433 109--- orig/generator.c 2005-03-17 09:05:21
8f72c7ae 110+++ generator.c 2005-03-11 11:22:38
36bbf3d1 111@@ -84,6 +84,9 @@ extern dev_t filesystem_dev;
52f25864
WD
112 extern char *backup_dir;
113 extern char *backup_suffix;
114 extern int backup_suffix_len;
19a778eb
WD
115+extern char *backup_dir_dels;
116+extern char *backup_suffix_dels;
117+extern int backup_suffix_dels_len;
d608ca23 118 extern struct file_list *the_file_list;
e20f0bda 119 extern struct filter_list_struct server_filter_list;
52f25864 120
36bbf3d1 121@@ -92,10 +95,14 @@ int allowed_lull = 0;
52f25864
WD
122 static int deletion_count = 0; /* used to implement --max-delete */
123
e20f0bda 124
d608ca23 125+/* Function now compares both backup_suffix and backup_suffix_dels. */
52f25864
WD
126 static int is_backup_file(char *fn)
127 {
128 int k = strlen(fn) - backup_suffix_len;
129- return k > 0 && strcmp(fn+k, backup_suffix) == 0;
130+ if (k > 0 && strcmp(fn+k, backup_suffix) == 0)
131+ return 1;
19a778eb
WD
132+ k += backup_suffix_len - backup_suffix_dels_len;
133+ return k > 0 && strcmp(fn+k, backup_suffix_dels) == 0;
52f25864
WD
134 }
135
136
36bbf3d1 137@@ -112,8 +119,8 @@ static int delete_item(char *fname, int
e20f0bda 138 if (!S_ISDIR(mode)) {
8f72c7ae
WD
139 if (max_delete && ++deletion_count > max_delete)
140 return 0;
e20f0bda
WD
141- if (make_backups && (backup_dir || !is_backup_file(fname)))
142- ok = make_backup(fname);
143+ if (make_backups && (backup_dir_dels || !is_backup_file(fname)))
144+ ok = safe_delete(fname);
145 else
146 ok = robust_unlink(fname) == 0;
147 if (ok) {
36bbf3d1 148@@ -136,9 +143,9 @@ static int delete_item(char *fname, int
8f72c7ae 149 || (dry_run && zap_dir)) {
4877ebcc
WD
150 ok = 0;
151 errno = ENOTEMPTY;
152- } else if (make_backups && !backup_dir && !is_backup_file(fname)
19a778eb 153+ } else if (make_backups && !backup_dir_dels && !is_backup_file(fname)
91e437b0 154 && !(flags & DEL_FORCE_RECURSE))
52f25864 155- ok = make_backup(fname);
52f25864
WD
156+ ok = safe_delete(fname);
157 else
158 ok = do_rmdir(fname) == 0;
4877ebcc 159 if (ok) {
1dd0573e 160--- orig/options.c 2005-03-24 16:41:46
def2ace9 161+++ options.c 2005-03-01 01:25:39
e20f0bda 162@@ -127,10 +127,14 @@ int no_detach
8af83008
WD
163 int write_batch = 0;
164 int read_batch = 0;
165 int backup_dir_len = 0;
19a778eb 166+int backup_dir_dels_len = 0;
8af83008 167 int backup_suffix_len;
19a778eb 168+int backup_suffix_dels_len;
8af83008 169 unsigned int backup_dir_remainder;
19a778eb 170+unsigned int backup_dir_dels_remainder;
8af83008
WD
171
172 char *backup_suffix = NULL;
19a778eb 173+char *backup_suffix_dels = NULL;
8af83008
WD
174 char *tmpdir = NULL;
175 char *partial_dir = NULL;
daceaa67 176 char *basis_dir[MAX_BASIS_DIRS+1];
e20f0bda 177@@ -140,7 +144,9 @@ char *log_format = NULL;
8af83008
WD
178 char *password_file = NULL;
179 char *rsync_path = RSYNC_PATH;
180 char *backup_dir = NULL;
19a778eb 181+char *backup_dir_dels = NULL;
8af83008 182 char backup_dir_buf[MAXPATHLEN];
19a778eb 183+char backup_dir_dels_buf[MAXPATHLEN];
daceaa67 184 int rsync_port = 0;
c59d6641 185 int compare_dest = 0;
36bbf3d1
WD
186 int copy_dest = 0;
187@@ -271,6 +277,8 @@ void usage(enum logcode F)
8af83008 188 rprintf(F," -b, --backup make backups (see --suffix & --backup-dir)\n");
79f132a1
WD
189 rprintf(F," --backup-dir=DIR make backups into hierarchy based in DIR\n");
190 rprintf(F," --suffix=SUFFIX set backup suffix (default %s w/o --backup-dir)\n",BACKUP_SUFFIX);
19a778eb
WD
191+ rprintf(F," --backup-dir-dels make backups of removed files into current dir\n");
192+ rprintf(F," --suffix-dels=SUFFIX set removed-files suffix (defaults to --suffix)\n");
79f132a1 193 rprintf(F," -u, --update skip files that are newer on the receiver\n");
0b2fb126 194 rprintf(F," --inplace update destination files in-place (SEE MAN PAGE)\n");
fd0e045e 195 rprintf(F," -d, --dirs transfer directories without recursing\n");
36bbf3d1 196@@ -366,6 +374,7 @@ static struct poptOption long_options[]
8af83008 197 /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
57e73b72 198 {"version", 0, POPT_ARG_NONE, 0, OPT_VERSION, 0, 0},
8af83008 199 {"suffix", 0, POPT_ARG_STRING, &backup_suffix, 0, 0, 0 },
19a778eb 200+ {"suffix-dels", 0, POPT_ARG_STRING, &backup_suffix_dels, 0, 0, 0 },
8af83008
WD
201 {"rsync-path", 0, POPT_ARG_STRING, &rsync_path, 0, 0, 0 },
202 {"password-file", 0, POPT_ARG_STRING, &password_file, 0, 0, 0 },
203 {"ignore-times", 'I', POPT_ARG_NONE, &ignore_times, 0, 0, 0 },
36bbf3d1 204@@ -446,6 +455,7 @@ static struct poptOption long_options[]
159b101f 205 {"itemize-changes", 'i', POPT_ARG_NONE, &itemize_changes, 0, 0, 0 },
8af83008 206 {"bwlimit", 0, POPT_ARG_INT, &bwlimit, 0, 0, 0 },
8af83008 207 {"backup-dir", 0, POPT_ARG_STRING, &backup_dir, 0, 0, 0 },
19a778eb 208+ {"backup-dir-dels", 0, POPT_ARG_STRING, &backup_dir_dels, 0, 0, 0 },
8af83008 209 {"hard-links", 'H', POPT_ARG_NONE, &preserve_hard_links, 0, 0, 0 },
57e73b72
WD
210 {"read-batch", 0, POPT_ARG_STRING, &batch_name, OPT_READ_BATCH, 0, 0 },
211 {"write-batch", 0, POPT_ARG_STRING, &batch_name, OPT_WRITE_BATCH, 0, 0 },
1dd0573e 212@@ -1007,6 +1017,8 @@ int parse_arguments(int *argc, const cha
daceaa67 213 partial_dir = sanitize_path(NULL, partial_dir, NULL, 0);
8af83008
WD
214 if (backup_dir)
215 backup_dir = sanitize_path(NULL, backup_dir, NULL, 0);
19a778eb
WD
216+ if (backup_dir_dels)
217+ backup_dir_dels = sanitize_path(NULL, backup_dir_dels, NULL, 0);
8af83008 218 }
def2ace9
WD
219 if (server_filter_list.head && !am_sender) {
220 struct filter_list_struct *elp = &server_filter_list;
1dd0573e 221@@ -1041,6 +1053,14 @@ int parse_arguments(int *argc, const cha
def2ace9
WD
222 return 0;
223 }
8af83008 224 }
19a778eb
WD
225+ /* Clean backup_dir_dels same as for backup_dir */
226+ if (backup_dir_dels) {
def2ace9
WD
227+ if (!*backup_dir_dels)
228+ goto options_rejected;
19a778eb
WD
229+ clean_fname(backup_dir_dels, 1);
230+ if (check_filter(elp, backup_dir_dels, 1) < 0)
8af83008
WD
231+ goto options_rejected;
232+ }
233 }
def2ace9
WD
234
235 if (!backup_suffix)
1dd0573e 236@@ -1052,6 +1072,16 @@ int parse_arguments(int *argc, const cha
8af83008
WD
237 backup_suffix);
238 return 0;
239 }
19a778eb
WD
240+ /* if backup_suffix_dels not supplied, default to backup_suffix */
241+ if (!backup_suffix_dels)
242+ backup_suffix_dels = backup_dir_dels ? "" : backup_suffix;
243+ backup_suffix_dels_len = strlen(backup_suffix_dels);
244+ if (strchr(backup_suffix_dels, '/') != NULL) {
8af83008 245+ snprintf(err_buf, sizeof err_buf,
19a778eb
WD
246+ "--suffix-dels cannot contain slashes: %s\n",
247+ backup_suffix_dels);
8af83008
WD
248+ return 0;
249+ }
250 if (backup_dir) {
251 backup_dir_len = strlcpy(backup_dir_buf, backup_dir, sizeof backup_dir_buf);
252 backup_dir_remainder = sizeof backup_dir_buf - backup_dir_len;
1dd0573e 253@@ -1073,6 +1103,31 @@ int parse_arguments(int *argc, const cha
8af83008
WD
254 "--suffix cannot be a null string without --backup-dir\n");
255 return 0;
256 }
19a778eb
WD
257+ /* If backup_dir_dels not supplied default to backup_dir if it has been supplied */
258+ if (backup_dir && !backup_dir_dels) {
259+ backup_dir_dels = backup_dir;
260+ backup_dir_dels_len = backup_dir_len;
261+ backup_dir_dels_remainder = backup_dir_remainder;
262+ strlcpy(backup_dir_dels_buf, backup_dir_buf, sizeof backup_dir_buf);
263+ } else if (backup_dir_dels) {
264+ backup_dir_dels_len = strlcpy(backup_dir_dels_buf, backup_dir_dels, sizeof backup_dir_dels_buf);
265+ backup_dir_dels_remainder = sizeof backup_dir_dels_buf - backup_dir_dels_len;
266+ if (backup_dir_dels_remainder < 32) {
8af83008 267+ snprintf(err_buf, sizeof err_buf,
19a778eb 268+ "the --backup-dir-dels path is WAY too long.\n");
8af83008
WD
269+ return 0;
270+ }
19a778eb
WD
271+ if (backup_dir_dels_buf[backup_dir_dels_len - 1] != '/') {
272+ backup_dir_dels_buf[backup_dir_dels_len++] = '/';
273+ backup_dir_dels_buf[backup_dir_dels_len] = '\0';
8af83008
WD
274+ }
275+ if (verbose > 1 && !am_sender)
19a778eb
WD
276+ rprintf(FINFO, "backup_dir_dels is %s\n", backup_dir_dels_buf);
277+ } else if (!backup_suffix_dels_len && (!am_server || !am_sender)) {
8af83008 278+ snprintf(err_buf, sizeof err_buf,
19a778eb 279+ "--suffix-dels cannot be a null string without --backup-dir-dels\n");
8af83008
WD
280+ return 0;
281+ }
52f25864
WD
282 if (make_backups && !backup_dir)
283 omit_dir_times = 1;
8af83008 284
1dd0573e 285@@ -1351,6 +1406,10 @@ void server_options(char **args,int *arg
8af83008
WD
286 args[ac++] = "--backup-dir";
287 args[ac++] = backup_dir;
288 }
19a778eb
WD
289+ if (backup_dir_dels) {
290+ args[ac++] = "--backup-dir-dels";
291+ args[ac++] = backup_dir_dels;
8af83008
WD
292+ }
293
294 /* Only send --suffix if it specifies a non-default value. */
295 if (strcmp(backup_suffix, backup_dir ? "" : BACKUP_SUFFIX) != 0) {
1dd0573e 296@@ -1359,7 +1418,13 @@ void server_options(char **args,int *arg
8af83008
WD
297 goto oom;
298 args[ac++] = arg;
299 }
300-
19a778eb
WD
301+ /* Only send --suffix-dels if it specifies a non-default value. */
302+ if (strcmp(backup_suffix_dels, backup_dir_dels ? "" : BACKUP_SUFFIX) != 0) {
8af83008 303+ /* We use the following syntax to avoid weirdness with '~'. */
19a778eb 304+ if (asprintf(&arg, "--suffix-dels=%s", backup_suffix_dels) < 0)
8af83008
WD
305+ goto oom;
306+ args[ac++] = arg;
307+ }
308 if (am_sender) {
309 if (delete_excluded)
310 args[ac++] = "--delete-excluded";