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