- Added a lock file.
[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 */
5e3c6c93 47 char *get_backup_name(const char *fname)
8af83008 48 {
5e3c6c93 49@@ -51,11 +58,28 @@ char *get_backup_name(const char *fname)
8af83008
WD
50 return NULL;
51 }
52
5e3c6c93 53+static char *get_delete_name(const char *fname)
8af83008 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 */
5e3c6c93 70 static int make_simple_backup(const char *fname)
8af83008 71 {
4877ebcc 72 int rename_errno;
5e3c6c93
WD
73- const char *fnamebak = get_backup_name(fname);
74+ const char *fnamebak = deleting ? get_delete_name(fname)
75+ : get_backup_name(fname);
8af83008
WD
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
5e3c6c93 89@@ -185,7 +210,8 @@ static int keep_backup(const 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 */
5e3c6c93 99@@ -280,3 +306,13 @@ int make_backup(const 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
f813befd 125@@ -115,10 +118,14 @@ enum delret {
87d0091c 126 static enum delret delete_dir_contents(char *fname, int flags);
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
87d0091c 140 /* Delete a file or directory. If DEL_RECURSE is set in the flags, this will
f813befd 141@@ -154,9 +161,9 @@ static enum delret delete_item(char *fbu
87d0091c
WD
142 if (S_ISDIR(mode)) {
143 what = "rmdir";
f813befd
WD
144 ok = do_rmdir(fbuf) == 0;
145- } else if (make_backups && (backup_dir || !is_backup_file(fbuf))) {
146+ } else if (make_backups && (backup_dir_dels || !is_backup_file(fbuf))) {
87d0091c 147 what = "make_backup";
f813befd
WD
148- ok = make_backup(fbuf);
149+ ok = safe_delete(fbuf);
87d0091c
WD
150 } else {
151 what = "unlink";
f813befd 152 ok = robust_unlink(fbuf) == 0;
9a7eef96
WD
153--- old/options.c
154+++ new/options.c
afcb578c 155@@ -138,10 +138,14 @@ int no_detach
8af83008
WD
156 int write_batch = 0;
157 int read_batch = 0;
158 int backup_dir_len = 0;
19a778eb 159+int backup_dir_dels_len = 0;
8af83008 160 int backup_suffix_len;
19a778eb 161+int backup_suffix_dels_len;
8af83008 162 unsigned int backup_dir_remainder;
19a778eb 163+unsigned int backup_dir_dels_remainder;
8af83008
WD
164
165 char *backup_suffix = NULL;
19a778eb 166+char *backup_suffix_dels = NULL;
8af83008
WD
167 char *tmpdir = NULL;
168 char *partial_dir = NULL;
daceaa67 169 char *basis_dir[MAX_BASIS_DIRS+1];
60a8bf36 170@@ -153,7 +157,9 @@ char *stdout_format = NULL;
e0e47893 171 char *password_file = NULL;
8af83008
WD
172 char *rsync_path = RSYNC_PATH;
173 char *backup_dir = NULL;
19a778eb 174+char *backup_dir_dels = NULL;
8af83008 175 char backup_dir_buf[MAXPATHLEN];
19a778eb 176+char backup_dir_dels_buf[MAXPATHLEN];
4a65fe72 177 char *sockopts = NULL;
daceaa67 178 int rsync_port = 0;
c59d6641 179 int compare_dest = 0;
5e3c6c93 180@@ -288,6 +294,8 @@ void usage(enum logcode F)
8af83008 181 rprintf(F," -b, --backup make backups (see --suffix & --backup-dir)\n");
79f132a1
WD
182 rprintf(F," --backup-dir=DIR make backups into hierarchy based in DIR\n");
183 rprintf(F," --suffix=SUFFIX set backup suffix (default %s w/o --backup-dir)\n",BACKUP_SUFFIX);
19a778eb
WD
184+ rprintf(F," --backup-dir-dels make backups of removed files into current dir\n");
185+ rprintf(F," --suffix-dels=SUFFIX set removed-files suffix (defaults to --suffix)\n");
79f132a1 186 rprintf(F," -u, --update skip files that are newer on the receiver\n");
0b2fb126 187 rprintf(F," --inplace update destination files in-place (SEE MAN PAGE)\n");
489b0a72 188 rprintf(F," --append append data onto shorter files\n");
5e3c6c93 189@@ -516,7 +524,9 @@ static struct poptOption long_options[]
8af83008 190 {"bwlimit", 0, POPT_ARG_INT, &bwlimit, 0, 0, 0 },
489b0a72 191 {"backup", 'b', POPT_ARG_NONE, &make_backups, 0, 0, 0 },
8af83008 192 {"backup-dir", 0, POPT_ARG_STRING, &backup_dir, 0, 0, 0 },
19a778eb 193+ {"backup-dir-dels", 0, POPT_ARG_STRING, &backup_dir_dels, 0, 0, 0 },
489b0a72
WD
194 {"suffix", 0, POPT_ARG_STRING, &backup_suffix, 0, 0, 0 },
195+ {"suffix-dels", 0, POPT_ARG_STRING, &backup_suffix_dels, 0, 0, 0 },
196 {"list-only", 0, POPT_ARG_VAL, &list_only, 2, 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 },
5e3c6c93 199@@ -1230,6 +1240,8 @@ int parse_arguments(int *argc, const cha
60a8bf36
WD
200 tmpdir = sanitize_path(NULL, tmpdir, NULL, 0, NULL);
201 if (backup_dir)
21158bc6 202 backup_dir = sanitize_path(NULL, backup_dir, NULL, 0, NULL);
60a8bf36 203+ if (backup_dir_dels)
21158bc6 204+ backup_dir_dels = sanitize_path(NULL, backup_dir_dels, NULL, 0, NULL);
8af83008 205 }
def2ace9
WD
206 if (server_filter_list.head && !am_sender) {
207 struct filter_list_struct *elp = &server_filter_list;
5e3c6c93 208@@ -1247,6 +1259,14 @@ int parse_arguments(int *argc, const cha
fb11cdd7
WD
209 if (check_filter(elp, backup_dir, 1) < 0)
210 goto options_rejected;
8af83008 211 }
19a778eb
WD
212+ /* Clean backup_dir_dels same as for backup_dir */
213+ if (backup_dir_dels) {
def2ace9
WD
214+ if (!*backup_dir_dels)
215+ goto options_rejected;
19a778eb
WD
216+ clean_fname(backup_dir_dels, 1);
217+ if (check_filter(elp, backup_dir_dels, 1) < 0)
8af83008
WD
218+ goto options_rejected;
219+ }
220 }
def2ace9
WD
221
222 if (!backup_suffix)
5e3c6c93 223@@ -1258,6 +1278,16 @@ int parse_arguments(int *argc, const cha
8af83008
WD
224 backup_suffix);
225 return 0;
226 }
19a778eb
WD
227+ /* if backup_suffix_dels not supplied, default to backup_suffix */
228+ if (!backup_suffix_dels)
229+ backup_suffix_dels = backup_dir_dels ? "" : backup_suffix;
230+ backup_suffix_dels_len = strlen(backup_suffix_dels);
231+ if (strchr(backup_suffix_dels, '/') != NULL) {
8af83008 232+ snprintf(err_buf, sizeof err_buf,
19a778eb
WD
233+ "--suffix-dels cannot contain slashes: %s\n",
234+ backup_suffix_dels);
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;
5e3c6c93 240@@ -1281,6 +1311,31 @@ int parse_arguments(int *argc, const cha
e0e47893
WD
241 "P *%s", backup_suffix);
242 parse_rule(&filter_list, backup_dir_buf, 0, 0);
8af83008 243 }
19a778eb
WD
244+ /* If backup_dir_dels not supplied default to backup_dir if it has been supplied */
245+ if (backup_dir && !backup_dir_dels) {
246+ backup_dir_dels = backup_dir;
247+ backup_dir_dels_len = backup_dir_len;
248+ backup_dir_dels_remainder = backup_dir_remainder;
249+ strlcpy(backup_dir_dels_buf, backup_dir_buf, sizeof backup_dir_buf);
250+ } else if (backup_dir_dels) {
251+ backup_dir_dels_len = strlcpy(backup_dir_dels_buf, backup_dir_dels, sizeof backup_dir_dels_buf);
252+ backup_dir_dels_remainder = sizeof backup_dir_dels_buf - backup_dir_dels_len;
253+ if (backup_dir_dels_remainder < 32) {
8af83008 254+ snprintf(err_buf, sizeof err_buf,
19a778eb 255+ "the --backup-dir-dels path is WAY too long.\n");
8af83008
WD
256+ return 0;
257+ }
19a778eb
WD
258+ if (backup_dir_dels_buf[backup_dir_dels_len - 1] != '/') {
259+ backup_dir_dels_buf[backup_dir_dels_len++] = '/';
260+ backup_dir_dels_buf[backup_dir_dels_len] = '\0';
8af83008
WD
261+ }
262+ if (verbose > 1 && !am_sender)
19a778eb
WD
263+ rprintf(FINFO, "backup_dir_dels is %s\n", backup_dir_dels_buf);
264+ } else if (!backup_suffix_dels_len && (!am_server || !am_sender)) {
8af83008 265+ snprintf(err_buf, sizeof err_buf,
19a778eb 266+ "--suffix-dels cannot be a null string without --backup-dir-dels\n");
8af83008
WD
267+ return 0;
268+ }
52f25864
WD
269 if (make_backups && !backup_dir)
270 omit_dir_times = 1;
8af83008 271
5e3c6c93 272@@ -1645,6 +1700,10 @@ void server_options(char **args,int *arg
8af83008
WD
273 args[ac++] = "--backup-dir";
274 args[ac++] = backup_dir;
275 }
37d900d6 276+ if (backup_dir_dels && backup_dir_dels != backup_dir) {
19a778eb
WD
277+ args[ac++] = "--backup-dir-dels";
278+ args[ac++] = backup_dir_dels;
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) {
5e3c6c93 283@@ -1653,7 +1712,13 @@ void server_options(char **args,int *arg
8af83008
WD
284 goto oom;
285 args[ac++] = arg;
286 }
287-
19a778eb
WD
288+ /* Only send --suffix-dels if it specifies a non-default value. */
289+ if (strcmp(backup_suffix_dels, backup_dir_dels ? "" : BACKUP_SUFFIX) != 0) {
8af83008 290+ /* We use the following syntax to avoid weirdness with '~'. */
19a778eb 291+ if (asprintf(&arg, "--suffix-dels=%s", backup_suffix_dels) < 0)
8af83008
WD
292+ goto oom;
293+ args[ac++] = arg;
294+ }
295 if (am_sender) {
296 if (delete_excluded)
297 args[ac++] = "--delete-excluded";