Fixed patch fuzz.
[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+}
52f25864
WD
108--- orig/flist.c 2005-02-21 10:51:51
109+++ flist.c 2005-02-21 11:00:19
110@@ -67,6 +67,9 @@ extern char *log_format;
111 extern char *backup_dir;
112 extern char *backup_suffix;
113 extern int backup_suffix_len;
114+extern char *backup_dir_rm;
115+extern char *backup_suffix_rm;
116+extern int backup_suffix_rm_len;
117
118 extern char curr_dir[MAXPATHLEN];
119
120@@ -1773,10 +1776,14 @@ struct file_list *get_dirlist(const char
121
122 static int deletion_count = 0; /* used to implement --max-delete */
123
124+/* Function now checks if file matches backup- or delete-suffix patterns. */
125 static int is_backup_file(char *fn)
126 {
127 int k = strlen(fn) - backup_suffix_len;
128- return k > 0 && strcmp(fn+k, backup_suffix) == 0;
129+ if (k > 0 && strcmp(fn+k, backup_suffix) == 0)
130+ return 1;
131+ k += backup_suffix_len - backup_suffix_rm_len;
132+ return k > 0 && strcmp(fn+k, backup_suffix_rm) == 0;
133 }
134
135
136@@ -1850,8 +1857,8 @@ int delete_file(char *fname, int mode, i
137 if (max_delete && deletion_count >= max_delete)
138 return -1;
139
140- if (make_backups && !backup_dir && !is_backup_file(fname))
141- ok = make_backup(fname);
142+ if (make_backups && !backup_dir_rm && !is_backup_file(fname))
143+ ok = safe_delete(fname);
144 else
145 ok = do_rmdir(fname) == 0;
146 if (!ok && errno != ENOENT) {
147--- orig/options.c 2005-02-21 10:51:52
148+++ options.c 2005-02-21 11:02:45
149@@ -126,10 +126,14 @@ int no_detach
8af83008
WD
150 int write_batch = 0;
151 int read_batch = 0;
152 int backup_dir_len = 0;
79f132a1 153+int backup_dir_rm_len = 0;
8af83008 154 int backup_suffix_len;
79f132a1 155+int backup_suffix_rm_len;
8af83008 156 unsigned int backup_dir_remainder;
79f132a1 157+unsigned int backup_dir_rm_remainder;
8af83008
WD
158
159 char *backup_suffix = NULL;
79f132a1 160+char *backup_suffix_rm = NULL;
8af83008
WD
161 char *tmpdir = NULL;
162 char *partial_dir = NULL;
daceaa67 163 char *basis_dir[MAX_BASIS_DIRS+1];
52f25864 164@@ -139,7 +143,9 @@ char *log_format = NULL;
8af83008
WD
165 char *password_file = NULL;
166 char *rsync_path = RSYNC_PATH;
167 char *backup_dir = NULL;
79f132a1 168+char *backup_dir_rm = NULL;
8af83008 169 char backup_dir_buf[MAXPATHLEN];
79f132a1 170+char backup_dir_rm_buf[MAXPATHLEN];
daceaa67 171 int rsync_port = 0;
c59d6641 172 int compare_dest = 0;
daceaa67 173 int copy_dest = 0;
52f25864 174@@ -270,6 +276,8 @@ void usage(enum logcode F)
8af83008 175 rprintf(F," -b, --backup make backups (see --suffix & --backup-dir)\n");
79f132a1
WD
176 rprintf(F," --backup-dir=DIR make backups into hierarchy based in DIR\n");
177 rprintf(F," --suffix=SUFFIX set backup suffix (default %s w/o --backup-dir)\n",BACKUP_SUFFIX);
178+ rprintf(F," --backup-dir-rm make backups of removed files into current dir\n");
179+ rprintf(F," --backup-suffix-rm=SUF set removed-files suffix (defaults to --suffix)\n");
180 rprintf(F," -u, --update skip files that are newer on the receiver\n");
0b2fb126 181 rprintf(F," --inplace update destination files in-place (SEE MAN PAGE)\n");
fd0e045e 182 rprintf(F," -d, --dirs transfer directories without recursing\n");
52f25864 183@@ -365,6 +373,7 @@ static struct poptOption long_options[]
8af83008 184 /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
57e73b72 185 {"version", 0, POPT_ARG_NONE, 0, OPT_VERSION, 0, 0},
8af83008 186 {"suffix", 0, POPT_ARG_STRING, &backup_suffix, 0, 0, 0 },
79f132a1 187+ {"backup-suffix-rm", 0, POPT_ARG_STRING, &backup_suffix_rm, 0, 0, 0 },
8af83008
WD
188 {"rsync-path", 0, POPT_ARG_STRING, &rsync_path, 0, 0, 0 },
189 {"password-file", 0, POPT_ARG_STRING, &password_file, 0, 0, 0 },
190 {"ignore-times", 'I', POPT_ARG_NONE, &ignore_times, 0, 0, 0 },
52f25864 191@@ -445,6 +454,7 @@ static struct poptOption long_options[]
159b101f 192 {"itemize-changes", 'i', POPT_ARG_NONE, &itemize_changes, 0, 0, 0 },
8af83008 193 {"bwlimit", 0, POPT_ARG_INT, &bwlimit, 0, 0, 0 },
8af83008 194 {"backup-dir", 0, POPT_ARG_STRING, &backup_dir, 0, 0, 0 },
79f132a1 195+ {"backup-dir-rm", 0, POPT_ARG_STRING, &backup_dir_rm, 0, 0, 0 },
8af83008 196 {"hard-links", 'H', POPT_ARG_NONE, &preserve_hard_links, 0, 0, 0 },
57e73b72
WD
197 {"read-batch", 0, POPT_ARG_STRING, &batch_name, OPT_READ_BATCH, 0, 0 },
198 {"write-batch", 0, POPT_ARG_STRING, &batch_name, OPT_WRITE_BATCH, 0, 0 },
52f25864 199@@ -1013,6 +1023,8 @@ int parse_arguments(int *argc, const cha
daceaa67 200 partial_dir = sanitize_path(NULL, partial_dir, NULL, 0);
8af83008
WD
201 if (backup_dir)
202 backup_dir = sanitize_path(NULL, backup_dir, NULL, 0);
79f132a1
WD
203+ if (backup_dir_rm)
204+ backup_dir_rm = sanitize_path(NULL, backup_dir_rm, NULL, 0);
8af83008
WD
205 if (files_from)
206 files_from = sanitize_path(NULL, files_from, NULL, 0);
207 }
52f25864 208@@ -1045,6 +1057,12 @@ int parse_arguments(int *argc, const cha
4f9b6a01 209 if (check_filter(elp, backup_dir, 1) < 0)
8af83008
WD
210 goto options_rejected;
211 }
79f132a1
WD
212+ /* Clean backup_dir_rm same as for backup_dir */
213+ if (backup_dir_rm) {
214+ clean_fname(backup_dir_rm, 1);
6e93e60a 215+ if (check_filter(elp, backup_dir_rm, 1) < 0)
8af83008
WD
216+ goto options_rejected;
217+ }
218 }
4f9b6a01 219 if (server_filter_list.head && files_from) {
27a7053c 220 if (!*files_from)
52f25864 221@@ -1067,6 +1085,16 @@ int parse_arguments(int *argc, const cha
8af83008
WD
222 backup_suffix);
223 return 0;
224 }
79f132a1
WD
225+ /* if suffix_rm not supplied, default to backup_suffix */
226+ if (!backup_suffix_rm)
227+ backup_suffix_rm = backup_dir_rm ? "" : backup_suffix;
228+ backup_suffix_rm_len = strlen(backup_suffix_rm);
229+ if (strchr(backup_suffix_rm, '/') != NULL) {
8af83008 230+ snprintf(err_buf, sizeof err_buf,
79f132a1
WD
231+ "--backup-suffix-rm cannot contain slashes: %s\n",
232+ backup_suffix_rm);
8af83008
WD
233+ return 0;
234+ }
235 if (backup_dir) {
236 backup_dir_len = strlcpy(backup_dir_buf, backup_dir, sizeof backup_dir_buf);
237 backup_dir_remainder = sizeof backup_dir_buf - backup_dir_len;
52f25864 238@@ -1088,6 +1116,31 @@ int parse_arguments(int *argc, const cha
8af83008
WD
239 "--suffix cannot be a null string without --backup-dir\n");
240 return 0;
241 }
79f132a1
WD
242+ /* If backup_dir_rm not supplied default to backup_dir if it has been supplied */
243+ if (backup_dir && !backup_dir_rm) {
244+ backup_dir_rm = backup_dir;
245+ backup_dir_rm_len = backup_dir_len;
246+ backup_dir_rm_remainder = backup_dir_remainder;
247+ strlcpy(backup_dir_rm_buf, backup_dir_buf, sizeof backup_dir_buf);
248+ } else if (backup_dir_rm) {
249+ backup_dir_rm_len = strlcpy(backup_dir_rm_buf, backup_dir_rm, sizeof backup_dir_rm_buf);
250+ backup_dir_rm_remainder = sizeof backup_dir_rm_buf - backup_dir_rm_len;
251+ if (backup_dir_rm_remainder < 32) {
8af83008 252+ snprintf(err_buf, sizeof err_buf,
79f132a1 253+ "the --backup-dir-rm path is WAY too long.\n");
8af83008
WD
254+ return 0;
255+ }
79f132a1
WD
256+ if (backup_dir_rm_buf[backup_dir_rm_len - 1] != '/') {
257+ backup_dir_rm_buf[backup_dir_rm_len++] = '/';
258+ backup_dir_rm_buf[backup_dir_rm_len] = '\0';
8af83008
WD
259+ }
260+ if (verbose > 1 && !am_sender)
79f132a1
WD
261+ rprintf(FINFO, "backup_dir_rm is %s\n", backup_dir_rm_buf);
262+ } else if (!backup_suffix_rm_len && (!am_server || !am_sender)) {
8af83008 263+ snprintf(err_buf, sizeof err_buf,
79f132a1 264+ "--backup-suffix-rm cannot be a null string without --backup-dir-rm\n");
8af83008
WD
265+ return 0;
266+ }
52f25864
WD
267 if (make_backups && !backup_dir)
268 omit_dir_times = 1;
8af83008 269
52f25864 270@@ -1353,6 +1406,10 @@ void server_options(char **args,int *arg
8af83008
WD
271 args[ac++] = "--backup-dir";
272 args[ac++] = backup_dir;
273 }
79f132a1
WD
274+ if (backup_dir_rm) {
275+ args[ac++] = "--backup-dir-rm";
276+ args[ac++] = backup_dir_rm;
8af83008
WD
277+ }
278
279 /* Only send --suffix if it specifies a non-default value. */
280 if (strcmp(backup_suffix, backup_dir ? "" : BACKUP_SUFFIX) != 0) {
52f25864 281@@ -1361,7 +1418,13 @@ void server_options(char **args,int *arg
8af83008
WD
282 goto oom;
283 args[ac++] = arg;
284 }
285-
79f132a1
WD
286+ /* Only send --backup-suffix-rm if it specifies a non-default value. */
287+ if (strcmp(backup_suffix_rm, backup_dir_rm ? "" : BACKUP_SUFFIX) != 0) {
8af83008 288+ /* We use the following syntax to avoid weirdness with '~'. */
79f132a1 289+ if (asprintf(&arg, "--backup-suffix-rm=%s", backup_suffix_rm) < 0)
8af83008
WD
290+ goto oom;
291+ args[ac++] = arg;
292+ }
293 if (am_sender) {
294 if (delete_excluded)
295 args[ac++] = "--delete-excluded";