Fixed some patch fuzz.
[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
03019e41
WD
16To use this patch, run these commands for a successful build:
17
18 patch -p1 <patches/backup-dir-dels.diff
19 ./configure (optional if already run)
20 make
21
9a7eef96
WD
22--- old/backup.c
23+++ new/backup.c
21158bc6 24@@ -23,10 +23,15 @@
8af83008
WD
25
26 extern int verbose;
8af83008 27 extern int backup_dir_len;
19a778eb 28+extern int backup_dir_dels_len;
8af83008 29 extern unsigned int backup_dir_remainder;
19a778eb 30+extern unsigned int backup_dir_dels_remainder;
8af83008 31 extern char backup_dir_buf[MAXPATHLEN];
19a778eb 32+extern char backup_dir_dels_buf[MAXPATHLEN];
8af83008 33 extern char *backup_suffix;
19a778eb 34+extern char *backup_suffix_dels;
8af83008 35 extern char *backup_dir;
19a778eb 36+extern char *backup_dir_dels;
8af83008
WD
37
38 extern int am_root;
39 extern int preserve_devices;
21158bc6 40@@ -34,6 +39,8 @@ extern int preserve_specials;
d42637db 41 extern int preserve_links;
8af83008
WD
42 extern int safe_symlinks;
43
44+static int deleting;
45+
46 /* make a complete pathname for backup file */
47 char *get_backup_name(char *fname)
48 {
21158bc6 49@@ -51,11 +58,28 @@ char *get_backup_name(char *fname)
8af83008
WD
50 return NULL;
51 }
52
53+static char *get_delete_name(char *fname)
54+{
19a778eb
WD
55+ if (backup_dir_dels) {
56+ if (stringjoin(backup_dir_dels_buf + backup_dir_dels_len, backup_dir_dels_remainder,
57+ fname, backup_suffix_dels, NULL) < backup_dir_dels_remainder)
58+ return backup_dir_dels_buf;
8af83008 59+ } else {
19a778eb
WD
60+ if (stringjoin(backup_dir_dels_buf, MAXPATHLEN,
61+ fname, backup_suffix_dels, NULL) < MAXPATHLEN)
62+ return backup_dir_dels_buf;
8af83008
WD
63+ }
64+
65+ rprintf(FERROR, "delete filename too long\n");
66+ return NULL;
67+}
68+
69 /* simple backup creates a backup with a suffix in the same directory */
70 static int make_simple_backup(char *fname)
71 {
4877ebcc 72 int rename_errno;
8af83008
WD
73- char *fnamebak = get_backup_name(fname);
74+ char *fnamebak = deleting ? get_delete_name(fname)
75+ : get_backup_name(fname);
76
77 if (!fnamebak)
78 return 0;
21158bc6 79@@ -95,7 +119,8 @@ path
8af83008
WD
80 static int make_bak_dir(char *fullpath)
81 {
82 STRUCT_STAT st;
83- char *rel = fullpath + backup_dir_len;
19a778eb 84+ int dir_len = deleting ? backup_dir_dels_len : backup_dir_len;
8af83008
WD
85+ char *rel = fullpath + dir_len;
86 char *end = rel + strlen(rel);
87 char *p = end;
88
21158bc6 89@@ -183,7 +208,8 @@ static int keep_backup(char *fname)
e0e47893 90 if (!(file = make_file(fname, NULL, NULL, 0, NO_FILTERS)))
8af83008
WD
91 return 1; /* the file could have disappeared */
92
93- if (!(buf = get_backup_name(fname)))
94+ buf = deleting ? get_delete_name(fname) : get_backup_name(fname);
95+ if (!buf)
96 return 0;
97
57e73b72 98 /* Check to see if this is a device file, or link */
21158bc6 99@@ -278,3 +304,13 @@ int make_backup(char *fname)
44917741
WD
100 return keep_backup(fname);
101 return make_simple_backup(fname);
102 }
8af83008 103+
79f132a1 104+/* backup switch routine called only when backing-up removed file */
8af83008
WD
105+int safe_delete(char *fname)
106+{
44917741 107+ int ret;
8af83008 108+ deleting = 1;
44917741
WD
109+ ret = make_backup(fname);
110+ deleting = 0;
111+ return ret;
112+}
9a7eef96
WD
113--- old/generator.c
114+++ new/generator.c
d42637db 115@@ -90,6 +90,9 @@ extern dev_t filesystem_dev;
52f25864
WD
116 extern char *backup_dir;
117 extern char *backup_suffix;
118 extern int backup_suffix_len;
19a778eb
WD
119+extern char *backup_dir_dels;
120+extern char *backup_suffix_dels;
121+extern int backup_suffix_dels_len;
d608ca23 122 extern struct file_list *the_file_list;
e20f0bda 123 extern struct filter_list_struct server_filter_list;
52f25864 124
21158bc6 125@@ -100,10 +103,14 @@ static int deletion_count = 0; /* used t
8b9ed461 126 #define DEL_TERSE (1<<3)
52f25864 127
e20f0bda 128
d608ca23 129+/* Function now compares both backup_suffix and backup_suffix_dels. */
52f25864
WD
130 static int is_backup_file(char *fn)
131 {
132 int k = strlen(fn) - backup_suffix_len;
133- return k > 0 && strcmp(fn+k, backup_suffix) == 0;
134+ if (k > 0 && strcmp(fn+k, backup_suffix) == 0)
135+ return 1;
19a778eb
WD
136+ k += backup_suffix_len - backup_suffix_dels_len;
137+ return k > 0 && strcmp(fn+k, backup_suffix_dels) == 0;
52f25864
WD
138 }
139
140
21158bc6 141@@ -124,8 +131,8 @@ static int delete_item(char *fname, int
e20f0bda 142 if (!S_ISDIR(mode)) {
8f72c7ae
WD
143 if (max_delete && ++deletion_count > max_delete)
144 return 0;
e20f0bda
WD
145- if (make_backups && (backup_dir || !is_backup_file(fname)))
146- ok = make_backup(fname);
147+ if (make_backups && (backup_dir_dels || !is_backup_file(fname)))
148+ ok = safe_delete(fname);
149 else
150 ok = robust_unlink(fname) == 0;
151 if (ok) {
21158bc6 152@@ -147,9 +154,9 @@ static int delete_item(char *fname, int
8f72c7ae 153 || (dry_run && zap_dir)) {
4877ebcc
WD
154 ok = 0;
155 errno = ENOTEMPTY;
156- } else if (make_backups && !backup_dir && !is_backup_file(fname)
19a778eb 157+ } else if (make_backups && !backup_dir_dels && !is_backup_file(fname)
91e437b0 158 && !(flags & DEL_FORCE_RECURSE))
52f25864 159- ok = make_backup(fname);
52f25864
WD
160+ ok = safe_delete(fname);
161 else
162 ok = do_rmdir(fname) == 0;
4877ebcc 163 if (ok) {
9a7eef96
WD
164--- old/options.c
165+++ new/options.c
afcb578c 166@@ -138,10 +138,14 @@ int no_detach
8af83008
WD
167 int write_batch = 0;
168 int read_batch = 0;
169 int backup_dir_len = 0;
19a778eb 170+int backup_dir_dels_len = 0;
8af83008 171 int backup_suffix_len;
19a778eb 172+int backup_suffix_dels_len;
8af83008 173 unsigned int backup_dir_remainder;
19a778eb 174+unsigned int backup_dir_dels_remainder;
8af83008
WD
175
176 char *backup_suffix = NULL;
19a778eb 177+char *backup_suffix_dels = NULL;
8af83008
WD
178 char *tmpdir = NULL;
179 char *partial_dir = NULL;
daceaa67 180 char *basis_dir[MAX_BASIS_DIRS+1];
60a8bf36 181@@ -153,7 +157,9 @@ char *stdout_format = NULL;
e0e47893 182 char *password_file = NULL;
8af83008
WD
183 char *rsync_path = RSYNC_PATH;
184 char *backup_dir = NULL;
19a778eb 185+char *backup_dir_dels = NULL;
8af83008 186 char backup_dir_buf[MAXPATHLEN];
19a778eb 187+char backup_dir_dels_buf[MAXPATHLEN];
4a65fe72 188 char *sockopts = NULL;
daceaa67 189 int rsync_port = 0;
c59d6641 190 int compare_dest = 0;
03019e41 191@@ -292,6 +298,8 @@ void usage(enum logcode F)
8af83008 192 rprintf(F," -b, --backup make backups (see --suffix & --backup-dir)\n");
79f132a1
WD
193 rprintf(F," --backup-dir=DIR make backups into hierarchy based in DIR\n");
194 rprintf(F," --suffix=SUFFIX set backup suffix (default %s w/o --backup-dir)\n",BACKUP_SUFFIX);
19a778eb
WD
195+ rprintf(F," --backup-dir-dels make backups of removed files into current dir\n");
196+ rprintf(F," --suffix-dels=SUFFIX set removed-files suffix (defaults to --suffix)\n");
79f132a1 197 rprintf(F," -u, --update skip files that are newer on the receiver\n");
0b2fb126 198 rprintf(F," --inplace update destination files in-place (SEE MAN PAGE)\n");
489b0a72 199 rprintf(F," --append append data onto shorter files\n");
03019e41 200@@ -518,7 +526,9 @@ static struct poptOption long_options[]
8af83008 201 {"bwlimit", 0, POPT_ARG_INT, &bwlimit, 0, 0, 0 },
489b0a72 202 {"backup", 'b', POPT_ARG_NONE, &make_backups, 0, 0, 0 },
8af83008 203 {"backup-dir", 0, POPT_ARG_STRING, &backup_dir, 0, 0, 0 },
19a778eb 204+ {"backup-dir-dels", 0, POPT_ARG_STRING, &backup_dir_dels, 0, 0, 0 },
489b0a72
WD
205 {"suffix", 0, POPT_ARG_STRING, &backup_suffix, 0, 0, 0 },
206+ {"suffix-dels", 0, POPT_ARG_STRING, &backup_suffix_dels, 0, 0, 0 },
207 {"list-only", 0, POPT_ARG_VAL, &list_only, 2, 0, 0 },
57e73b72
WD
208 {"read-batch", 0, POPT_ARG_STRING, &batch_name, OPT_READ_BATCH, 0, 0 },
209 {"write-batch", 0, POPT_ARG_STRING, &batch_name, OPT_WRITE_BATCH, 0, 0 },
03019e41 210@@ -1232,6 +1242,8 @@ int parse_arguments(int *argc, const cha
60a8bf36
WD
211 tmpdir = sanitize_path(NULL, tmpdir, NULL, 0, NULL);
212 if (backup_dir)
21158bc6 213 backup_dir = sanitize_path(NULL, backup_dir, NULL, 0, NULL);
60a8bf36 214+ if (backup_dir_dels)
21158bc6 215+ backup_dir_dels = sanitize_path(NULL, backup_dir_dels, NULL, 0, NULL);
8af83008 216 }
def2ace9
WD
217 if (server_filter_list.head && !am_sender) {
218 struct filter_list_struct *elp = &server_filter_list;
03019e41 219@@ -1253,6 +1265,14 @@ int parse_arguments(int *argc, const cha
def2ace9
WD
220 return 0;
221 }
8af83008 222 }
19a778eb
WD
223+ /* Clean backup_dir_dels same as for backup_dir */
224+ if (backup_dir_dels) {
def2ace9
WD
225+ if (!*backup_dir_dels)
226+ goto options_rejected;
19a778eb
WD
227+ clean_fname(backup_dir_dels, 1);
228+ if (check_filter(elp, backup_dir_dels, 1) < 0)
8af83008
WD
229+ goto options_rejected;
230+ }
231 }
def2ace9
WD
232
233 if (!backup_suffix)
03019e41 234@@ -1264,6 +1284,16 @@ int parse_arguments(int *argc, const cha
8af83008
WD
235 backup_suffix);
236 return 0;
237 }
19a778eb
WD
238+ /* if backup_suffix_dels not supplied, default to backup_suffix */
239+ if (!backup_suffix_dels)
240+ backup_suffix_dels = backup_dir_dels ? "" : backup_suffix;
241+ backup_suffix_dels_len = strlen(backup_suffix_dels);
242+ if (strchr(backup_suffix_dels, '/') != NULL) {
8af83008 243+ snprintf(err_buf, sizeof err_buf,
19a778eb
WD
244+ "--suffix-dels cannot contain slashes: %s\n",
245+ backup_suffix_dels);
8af83008
WD
246+ return 0;
247+ }
248 if (backup_dir) {
249 backup_dir_len = strlcpy(backup_dir_buf, backup_dir, sizeof backup_dir_buf);
250 backup_dir_remainder = sizeof backup_dir_buf - backup_dir_len;
03019e41 251@@ -1287,6 +1317,31 @@ int parse_arguments(int *argc, const cha
e0e47893
WD
252 "P *%s", backup_suffix);
253 parse_rule(&filter_list, backup_dir_buf, 0, 0);
8af83008 254 }
19a778eb
WD
255+ /* If backup_dir_dels not supplied default to backup_dir if it has been supplied */
256+ if (backup_dir && !backup_dir_dels) {
257+ backup_dir_dels = backup_dir;
258+ backup_dir_dels_len = backup_dir_len;
259+ backup_dir_dels_remainder = backup_dir_remainder;
260+ strlcpy(backup_dir_dels_buf, backup_dir_buf, sizeof backup_dir_buf);
261+ } else if (backup_dir_dels) {
262+ backup_dir_dels_len = strlcpy(backup_dir_dels_buf, backup_dir_dels, sizeof backup_dir_dels_buf);
263+ backup_dir_dels_remainder = sizeof backup_dir_dels_buf - backup_dir_dels_len;
264+ if (backup_dir_dels_remainder < 32) {
8af83008 265+ snprintf(err_buf, sizeof err_buf,
19a778eb 266+ "the --backup-dir-dels path is WAY too long.\n");
8af83008
WD
267+ return 0;
268+ }
19a778eb
WD
269+ if (backup_dir_dels_buf[backup_dir_dels_len - 1] != '/') {
270+ backup_dir_dels_buf[backup_dir_dels_len++] = '/';
271+ backup_dir_dels_buf[backup_dir_dels_len] = '\0';
8af83008
WD
272+ }
273+ if (verbose > 1 && !am_sender)
19a778eb
WD
274+ rprintf(FINFO, "backup_dir_dels is %s\n", backup_dir_dels_buf);
275+ } else if (!backup_suffix_dels_len && (!am_server || !am_sender)) {
8af83008 276+ snprintf(err_buf, sizeof err_buf,
19a778eb 277+ "--suffix-dels cannot be a null string without --backup-dir-dels\n");
8af83008
WD
278+ return 0;
279+ }
52f25864
WD
280 if (make_backups && !backup_dir)
281 omit_dir_times = 1;
8af83008 282
03019e41 283@@ -1646,6 +1701,10 @@ void server_options(char **args,int *arg
8af83008
WD
284 args[ac++] = "--backup-dir";
285 args[ac++] = backup_dir;
286 }
37d900d6 287+ if (backup_dir_dels && backup_dir_dels != backup_dir) {
19a778eb
WD
288+ args[ac++] = "--backup-dir-dels";
289+ args[ac++] = backup_dir_dels;
8af83008
WD
290+ }
291
292 /* Only send --suffix if it specifies a non-default value. */
293 if (strcmp(backup_suffix, backup_dir ? "" : BACKUP_SUFFIX) != 0) {
03019e41 294@@ -1654,7 +1713,13 @@ void server_options(char **args,int *arg
8af83008
WD
295 goto oom;
296 args[ac++] = arg;
297 }
298-
19a778eb
WD
299+ /* Only send --suffix-dels if it specifies a non-default value. */
300+ if (strcmp(backup_suffix_dels, backup_dir_dels ? "" : BACKUP_SUFFIX) != 0) {
8af83008 301+ /* We use the following syntax to avoid weirdness with '~'. */
19a778eb 302+ if (asprintf(&arg, "--suffix-dels=%s", backup_suffix_dels) < 0)
8af83008
WD
303+ goto oom;
304+ args[ac++] = arg;
305+ }
306 if (am_sender) {
307 if (delete_excluded)
308 args[ac++] = "--delete-excluded";