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+}
c968d24c
WD
108--- orig/flist.c 2005-02-19 09:27:48
109+++ flist.c 2005-02-19 09:29:36
27a7053c 110@@ -46,6 +46,8 @@ extern char curr_dir[MAXPATHLEN];
ac23c334 111 extern unsigned int curr_dir_len;
fd0e045e
WD
112 extern char *backup_dir;
113 extern char *backup_suffix;
79f132a1
WD
114+extern char *backup_dir_rm;
115+extern char *backup_suffix_rm;
fd0e045e
WD
116 extern int filesfrom_fd;
117
118 extern int one_file_system;
27a7053c 119@@ -60,6 +62,7 @@ extern int relative_paths;
fd0e045e
WD
120 extern int implied_dirs;
121 extern int make_backups;
122 extern int backup_suffix_len;
79f132a1 123+extern int backup_suffix_rm_len;
fd0e045e
WD
124 extern int copy_links;
125 extern int copy_unsafe_links;
126 extern int protocol_version;
c968d24c 127@@ -1751,10 +1754,14 @@ char *f_name(struct file_struct *f)
fd0e045e
WD
128 }
129
7dcd266d 130
fd0e045e
WD
131+/* Function now checks if file matches backup or delete suffix patterns */
132 static int is_backup_file(char *fn)
133 {
134 int k = strlen(fn) - backup_suffix_len;
135- return k > 0 && strcmp(fn+k, backup_suffix) == 0;
136+ if (k > 0 && strcmp(fn+k, backup_suffix) == 0)
137+ return 1;
79f132a1
WD
138+ k += backup_suffix_len - backup_suffix_rm_len;
139+ return k > 0 && strcmp(fn+k, backup_suffix_rm) == 0;
fd0e045e
WD
140 }
141
159b101f 142 struct file_list *get_dirlist(const char *dirname, int ignore_filter_rules)
c968d24c 143@@ -1860,9 +1867,10 @@ void delete_missing(struct file_list *fu
ed1e6fe4
WD
144 mode = dir_list->files[i]->mode;
145 if (flist_find(full_list, dir_list->files[i]) < 0) {
7dcd266d 146 char *f = f_name(dir_list->files[i]);
fd0e045e
WD
147- if (make_backups && (backup_dir || !is_backup_file(f))
148+ int backup_file = is_backup_file(f);
79f132a1 149+ if (make_backups && (backup_dir_rm || !backup_file)
fd0e045e
WD
150 && !S_ISDIR(mode)) {
151- make_backup(f);
152+ safe_delete(f);
c968d24c
WD
153 if (verbose || log_format)
154 log_delete(f, mode);
27a7053c 155 } else if (S_ISDIR(mode))
c968d24c 156--- orig/options.c 2005-02-19 09:27:48
79f132a1 157+++ options.c 2005-01-28 19:17:35
159b101f 158@@ -119,10 +119,14 @@ int no_detach = 0;
8af83008
WD
159 int write_batch = 0;
160 int read_batch = 0;
161 int backup_dir_len = 0;
79f132a1 162+int backup_dir_rm_len = 0;
8af83008 163 int backup_suffix_len;
79f132a1 164+int backup_suffix_rm_len;
8af83008 165 unsigned int backup_dir_remainder;
79f132a1 166+unsigned int backup_dir_rm_remainder;
8af83008
WD
167
168 char *backup_suffix = NULL;
79f132a1 169+char *backup_suffix_rm = NULL;
8af83008
WD
170 char *tmpdir = NULL;
171 char *partial_dir = NULL;
daceaa67 172 char *basis_dir[MAX_BASIS_DIRS+1];
159b101f 173@@ -132,7 +136,9 @@ char *log_format = NULL;
8af83008
WD
174 char *password_file = NULL;
175 char *rsync_path = RSYNC_PATH;
176 char *backup_dir = NULL;
79f132a1 177+char *backup_dir_rm = NULL;
8af83008 178 char backup_dir_buf[MAXPATHLEN];
79f132a1 179+char backup_dir_rm_buf[MAXPATHLEN];
daceaa67 180 int rsync_port = 0;
c59d6641 181 int compare_dest = 0;
daceaa67 182 int copy_dest = 0;
c968d24c 183@@ -262,6 +268,8 @@ void usage(enum logcode F)
8af83008 184 rprintf(F," -b, --backup make backups (see --suffix & --backup-dir)\n");
79f132a1
WD
185 rprintf(F," --backup-dir=DIR make backups into hierarchy based in DIR\n");
186 rprintf(F," --suffix=SUFFIX set backup suffix (default %s w/o --backup-dir)\n",BACKUP_SUFFIX);
187+ rprintf(F," --backup-dir-rm make backups of removed files into current dir\n");
188+ rprintf(F," --backup-suffix-rm=SUF set removed-files suffix (defaults to --suffix)\n");
189 rprintf(F," -u, --update skip files that are newer on the receiver\n");
0b2fb126 190 rprintf(F," --inplace update destination files in-place (SEE MAN PAGE)\n");
fd0e045e 191 rprintf(F," -d, --dirs transfer directories without recursing\n");
c968d24c 192@@ -356,6 +364,7 @@ static struct poptOption long_options[]
8af83008 193 /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
57e73b72 194 {"version", 0, POPT_ARG_NONE, 0, OPT_VERSION, 0, 0},
8af83008 195 {"suffix", 0, POPT_ARG_STRING, &backup_suffix, 0, 0, 0 },
79f132a1 196+ {"backup-suffix-rm", 0, POPT_ARG_STRING, &backup_suffix_rm, 0, 0, 0 },
8af83008
WD
197 {"rsync-path", 0, POPT_ARG_STRING, &rsync_path, 0, 0, 0 },
198 {"password-file", 0, POPT_ARG_STRING, &password_file, 0, 0, 0 },
199 {"ignore-times", 'I', POPT_ARG_NONE, &ignore_times, 0, 0, 0 },
c968d24c 200@@ -435,6 +444,7 @@ static struct poptOption long_options[]
159b101f 201 {"itemize-changes", 'i', POPT_ARG_NONE, &itemize_changes, 0, 0, 0 },
8af83008 202 {"bwlimit", 0, POPT_ARG_INT, &bwlimit, 0, 0, 0 },
8af83008 203 {"backup-dir", 0, POPT_ARG_STRING, &backup_dir, 0, 0, 0 },
79f132a1 204+ {"backup-dir-rm", 0, POPT_ARG_STRING, &backup_dir_rm, 0, 0, 0 },
8af83008 205 {"hard-links", 'H', POPT_ARG_NONE, &preserve_hard_links, 0, 0, 0 },
57e73b72
WD
206 {"read-batch", 0, POPT_ARG_STRING, &batch_name, OPT_READ_BATCH, 0, 0 },
207 {"write-batch", 0, POPT_ARG_STRING, &batch_name, OPT_WRITE_BATCH, 0, 0 },
c968d24c 208@@ -980,6 +990,8 @@ int parse_arguments(int *argc, const cha
daceaa67 209 partial_dir = sanitize_path(NULL, partial_dir, NULL, 0);
8af83008
WD
210 if (backup_dir)
211 backup_dir = sanitize_path(NULL, backup_dir, NULL, 0);
79f132a1
WD
212+ if (backup_dir_rm)
213+ backup_dir_rm = sanitize_path(NULL, backup_dir_rm, NULL, 0);
8af83008
WD
214 if (files_from)
215 files_from = sanitize_path(NULL, files_from, NULL, 0);
216 }
c968d24c 217@@ -1012,6 +1024,12 @@ int parse_arguments(int *argc, const cha
4f9b6a01 218 if (check_filter(elp, backup_dir, 1) < 0)
8af83008
WD
219 goto options_rejected;
220 }
79f132a1
WD
221+ /* Clean backup_dir_rm same as for backup_dir */
222+ if (backup_dir_rm) {
223+ clean_fname(backup_dir_rm, 1);
224+ if (check_exclude(elp, backup_dir_rm, 1) < 0)
8af83008
WD
225+ goto options_rejected;
226+ }
227 }
4f9b6a01 228 if (server_filter_list.head && files_from) {
27a7053c 229 if (!*files_from)
c968d24c 230@@ -1034,6 +1052,16 @@ int parse_arguments(int *argc, const cha
8af83008
WD
231 backup_suffix);
232 return 0;
233 }
79f132a1
WD
234+ /* if suffix_rm not supplied, default to backup_suffix */
235+ if (!backup_suffix_rm)
236+ backup_suffix_rm = backup_dir_rm ? "" : backup_suffix;
237+ backup_suffix_rm_len = strlen(backup_suffix_rm);
238+ if (strchr(backup_suffix_rm, '/') != NULL) {
8af83008 239+ snprintf(err_buf, sizeof err_buf,
79f132a1
WD
240+ "--backup-suffix-rm cannot contain slashes: %s\n",
241+ backup_suffix_rm);
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;
c968d24c 247@@ -1055,6 +1083,31 @@ int parse_arguments(int *argc, const cha
8af83008
WD
248 "--suffix cannot be a null string without --backup-dir\n");
249 return 0;
250 }
79f132a1
WD
251+ /* If backup_dir_rm not supplied default to backup_dir if it has been supplied */
252+ if (backup_dir && !backup_dir_rm) {
253+ backup_dir_rm = backup_dir;
254+ backup_dir_rm_len = backup_dir_len;
255+ backup_dir_rm_remainder = backup_dir_remainder;
256+ strlcpy(backup_dir_rm_buf, backup_dir_buf, sizeof backup_dir_buf);
257+ } else if (backup_dir_rm) {
258+ backup_dir_rm_len = strlcpy(backup_dir_rm_buf, backup_dir_rm, sizeof backup_dir_rm_buf);
259+ backup_dir_rm_remainder = sizeof backup_dir_rm_buf - backup_dir_rm_len;
260+ if (backup_dir_rm_remainder < 32) {
8af83008 261+ snprintf(err_buf, sizeof err_buf,
79f132a1 262+ "the --backup-dir-rm path is WAY too long.\n");
8af83008
WD
263+ return 0;
264+ }
79f132a1
WD
265+ if (backup_dir_rm_buf[backup_dir_rm_len - 1] != '/') {
266+ backup_dir_rm_buf[backup_dir_rm_len++] = '/';
267+ backup_dir_rm_buf[backup_dir_rm_len] = '\0';
8af83008
WD
268+ }
269+ if (verbose > 1 && !am_sender)
79f132a1
WD
270+ rprintf(FINFO, "backup_dir_rm is %s\n", backup_dir_rm_buf);
271+ } else if (!backup_suffix_rm_len && (!am_server || !am_sender)) {
8af83008 272+ snprintf(err_buf, sizeof err_buf,
79f132a1 273+ "--backup-suffix-rm cannot be a null string without --backup-dir-rm\n");
8af83008
WD
274+ return 0;
275+ }
276
5a56905b
WD
277 if (log_format) {
278 if (strstr(log_format, "%i") != NULL)
c968d24c 279@@ -1318,6 +1371,10 @@ void server_options(char **args,int *arg
8af83008
WD
280 args[ac++] = "--backup-dir";
281 args[ac++] = backup_dir;
282 }
79f132a1
WD
283+ if (backup_dir_rm) {
284+ args[ac++] = "--backup-dir-rm";
285+ args[ac++] = backup_dir_rm;
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) {
c968d24c 290@@ -1326,7 +1383,13 @@ void server_options(char **args,int *arg
8af83008
WD
291 goto oom;
292 args[ac++] = arg;
293 }
294-
79f132a1
WD
295+ /* Only send --backup-suffix-rm if it specifies a non-default value. */
296+ if (strcmp(backup_suffix_rm, backup_dir_rm ? "" : BACKUP_SUFFIX) != 0) {
8af83008 297+ /* We use the following syntax to avoid weirdness with '~'. */
79f132a1 298+ if (asprintf(&arg, "--backup-suffix-rm=%s", backup_suffix_rm) < 0)
8af83008
WD
299+ goto oom;
300+ args[ac++] = arg;
301+ }
302 if (am_sender) {
303 if (delete_excluded)
304 args[ac++] = "--delete-excluded";