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