Line data Source code
1 : #include "../burp.h"
2 : #include "../alloc.h"
3 : #include "../asfd.h"
4 : #include "../async.h"
5 : #include "../bu.h"
6 : #include "../conf.h"
7 : #include "../cmd.h"
8 : #include "../cntr.h"
9 : #include "../cstat.h"
10 : #include "../log.h"
11 : #include "../prepend.h"
12 : #include "../sbuf.h"
13 : #include "bu_get.h"
14 : #include "child.h"
15 : #include "manio.h"
16 : #include "diff.h"
17 :
18 : static char *get_manifest_path(const char *fullpath, enum protocol protocol)
19 : {
20 0 : return prepend_s(fullpath, protocol==PROTO_1?"manifest.gz":"manifest");
21 : }
22 :
23 0 : static int send_diff(struct asfd *asfd, const char *symbol, struct sbuf *sb)
24 : {
25 0 : int ret=-1;
26 0 : char *dpath=NULL;
27 0 : if(!(dpath=prepend_s(symbol, sb->path.buf))
28 0 : || asfd->write(asfd, &sb->attr)
29 0 : || asfd->write_str(asfd, sb->path.cmd, dpath))
30 : goto end;
31 0 : if(sbuf_is_link(sb)
32 0 : && asfd->write(asfd, &sb->link))
33 : goto end;
34 : ret=0;
35 : end:
36 0 : free_w(&dpath);
37 0 : return ret;
38 : }
39 :
40 : static int send_deletion(struct asfd *asfd, struct sbuf *sb)
41 : {
42 0 : return send_diff(asfd, "- ", sb);
43 : }
44 :
45 : static int send_addition(struct asfd *asfd, struct sbuf *sb)
46 : {
47 0 : return send_diff(asfd, "+ ", sb);
48 : }
49 :
50 0 : static int diff_manifests(struct asfd *asfd, const char *fullpath1,
51 : const char *fullpath2, enum protocol protocol)
52 : {
53 0 : int ret=-1;
54 : int pcmp;
55 0 : struct sbuf *sb1=NULL;
56 0 : struct sbuf *sb2=NULL;
57 0 : struct manio *manio1=NULL;
58 0 : struct manio *manio2=NULL;
59 0 : char *manifest_dir1=NULL;
60 0 : char *manifest_dir2=NULL;
61 :
62 0 : if(!(manifest_dir1=get_manifest_path(fullpath1, protocol))
63 0 : || !(manifest_dir2=get_manifest_path(fullpath2, protocol))
64 0 : || !(manio1=manio_open(manifest_dir1, "rb", protocol))
65 0 : || !(manio2=manio_open(manifest_dir2, "rb", protocol))
66 0 : || !(sb1=sbuf_alloc(protocol))
67 0 : || !(sb2=sbuf_alloc(protocol)))
68 : {
69 0 : log_and_send_oom(asfd);
70 0 : goto end;
71 : }
72 :
73 0 : while(manio1 || manio2)
74 : {
75 0 : if(manio1
76 0 : && !sb1->path.buf)
77 : {
78 0 : switch(manio_read(manio1, sb1))
79 : {
80 : case -1: goto end;
81 0 : case 1: manio_close(&manio1);
82 : }
83 : }
84 :
85 0 : if(manio2
86 0 : && !sb2->path.buf)
87 : {
88 0 : switch(manio_read(manio2, sb2))
89 : {
90 : case -1: goto end;
91 0 : case 1: manio_close(&manio2);
92 : }
93 : }
94 :
95 0 : if(sb1->path.buf && !sb2->path.buf)
96 : {
97 0 : if(send_deletion(asfd, sb1))
98 : goto end;
99 0 : sbuf_free_content(sb1);
100 : }
101 0 : else if(!sb1->path.buf && sb2->path.buf)
102 : {
103 0 : if(send_addition(asfd, sb2))
104 : goto end;
105 0 : sbuf_free_content(sb2);
106 : }
107 0 : else if(!sb1->path.buf && !sb2->path.buf)
108 : {
109 0 : continue;
110 : }
111 0 : else if(!(pcmp=sbuf_pathcmp(sb1, sb2)))
112 : {
113 0 : if(sb1->statp.st_mtime!=sb2->statp.st_mtime)
114 : {
115 0 : if(send_deletion(asfd, sb1)
116 0 : || send_addition(asfd, sb2))
117 : goto end;
118 : }
119 0 : sbuf_free_content(sb1);
120 0 : sbuf_free_content(sb2);
121 : }
122 0 : else if(pcmp<0)
123 : {
124 0 : if(send_deletion(asfd, sb1))
125 : goto end;
126 0 : sbuf_free_content(sb1);
127 : }
128 : else
129 : {
130 0 : if(send_addition(asfd, sb2))
131 : goto end;
132 0 : sbuf_free_content(sb2);
133 : }
134 : }
135 :
136 : ret=0;
137 : end:
138 0 : sbuf_free(&sb1);
139 0 : sbuf_free(&sb2);
140 0 : free_w(&manifest_dir1);
141 0 : free_w(&manifest_dir2);
142 0 : manio_close(&manio1);
143 0 : manio_close(&manio2);
144 0 : return ret;
145 : }
146 :
147 0 : static int send_backup_name_to_client(struct asfd *asfd, struct bu *bu)
148 : {
149 0 : char msg[64]="";
150 0 : snprintf(msg, sizeof(msg), "%s", bu->timestamp);
151 0 : return asfd->write_str(asfd, CMD_TIMESTAMP, msg);
152 : }
153 :
154 1 : int do_diff_server(struct asfd *asfd, struct sdirs *sdirs, struct cntr *cntr,
155 : enum protocol protocol, const char *backup1, const char *backup2)
156 : {
157 1 : int ret=-1;
158 1 : unsigned long bno1=0;
159 1 : unsigned long bno2=0;
160 1 : struct bu *bu1=NULL;
161 1 : struct bu *bu2=NULL;
162 1 : struct bu *bu_list=NULL;
163 :
164 : //printf("in do_diff_server\n");
165 :
166 1 : if(bu_get_list(sdirs, &bu_list))
167 : goto end;
168 :
169 1 : if(backup2 && *backup2)
170 0 : bno2=strtoul(backup2, NULL, 10);
171 1 : if(backup1 && *backup1)
172 0 : bno1=strtoul(backup1, NULL, 10);
173 :
174 1 : if(!bno1 || !bno2 || bno1==bno2)
175 : {
176 1 : asfd->write_str(asfd, CMD_ERROR,
177 : "you need to specify two backups");
178 1 : goto end;
179 : }
180 :
181 0 : for(bu1=bu_list; bu1; bu1=bu1->next)
182 0 : if(bu1->bno==bno1) break;
183 0 : for(bu2=bu_list; bu2; bu2=bu2->next)
184 0 : if(bu2->bno==bno2) break;
185 0 : if(!bu1 || !bu2)
186 : {
187 0 : asfd->write_str(asfd, CMD_ERROR,
188 : "could not find specified backups");
189 0 : goto end;
190 : }
191 :
192 0 : if(send_backup_name_to_client(asfd, bu1)
193 0 : || send_backup_name_to_client(asfd, bu2))
194 : goto end;
195 :
196 0 : cntr->bno=(int)bu2->bno;
197 0 : if(write_status(CNTR_STATUS_DIFFING, NULL, cntr))
198 : goto end;
199 :
200 0 : if(diff_manifests(asfd, bu1->path, bu2->path, protocol))
201 : goto end;
202 :
203 0 : ret=0;
204 : end:
205 1 : bu_list_free(&bu_list);
206 1 : return ret;
207 : }
|