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