Line data Source code
1 : #include "burp.h"
2 : #include "sbuf.h"
3 : #include "alloc.h"
4 : #include "asfd.h"
5 : #include "attribs.h"
6 : #include "cmd.h"
7 : #include "conf.h"
8 : #include "handy.h"
9 : #include "log.h"
10 : #include "msg.h"
11 : #include "protocol2/blk.h"
12 : #include "server/protocol2/rblk.h"
13 :
14 64548 : struct sbuf *sbuf_alloc(enum protocol protocol)
15 : {
16 : struct sbuf *sb;
17 64548 : if(!(sb=(struct sbuf *)calloc_w(1, sizeof(struct sbuf), __func__)))
18 0 : return NULL;
19 64548 : iobuf_init(&sb->path);
20 64548 : iobuf_init(&sb->attr);
21 64548 : sb->attr.cmd=CMD_ATTRIBS;
22 64548 : iobuf_init(&sb->link);
23 64548 : iobuf_init(&sb->endfile);
24 64548 : sb->compression=-1;
25 64548 : if(protocol==PROTO_1)
26 : {
27 31747 : if(!(sb->protocol1=sbuf_protocol1_alloc())) return NULL;
28 : }
29 : else
30 : {
31 32801 : if(!(sb->protocol2=sbuf_protocol2_alloc())) return NULL;
32 : }
33 64548 : return sb;
34 : }
35 :
36 125926 : void sbuf_free_content(struct sbuf *sb)
37 : {
38 125926 : iobuf_free_content(&sb->path);
39 125926 : iobuf_free_content(&sb->attr);
40 125926 : iobuf_free_content(&sb->link);
41 125926 : iobuf_free_content(&sb->endfile);
42 125926 : memset(&(sb->statp), 0, sizeof(sb->statp));
43 125926 : sb->compression=-1;
44 125926 : sb->winattr=0;
45 125926 : sb->flags=0;
46 125926 : sbuf_protocol1_free_content(sb->protocol1);
47 125926 : sbuf_protocol2_free_content(sb->protocol2);
48 125926 : }
49 :
50 64548 : void sbuf_free(struct sbuf **sb)
51 : {
52 129096 : if(!sb || !*sb) return;
53 64548 : sbuf_free_content(*sb);
54 64548 : free_v((void **)&((*sb)->protocol1));
55 64548 : free_v((void **)&((*sb)->protocol2));
56 64548 : free_v((void **)sb);
57 : }
58 :
59 0 : int sbuf_is_link(struct sbuf *sb)
60 : {
61 0 : return iobuf_is_link(&sb->path);
62 : }
63 :
64 58208 : int sbuf_is_filedata(struct sbuf *sb)
65 : {
66 58208 : return iobuf_is_filedata(&sb->path);
67 : }
68 :
69 10408 : int sbuf_is_vssdata(struct sbuf *sb)
70 : {
71 10408 : return iobuf_is_vssdata(&sb->path);
72 : }
73 :
74 0 : int sbuf_is_encrypted(struct sbuf *sb)
75 : {
76 0 : return iobuf_is_encrypted(&sb->path);
77 : }
78 :
79 0 : int sbuf_is_metadata(struct sbuf *sb)
80 : {
81 0 : return iobuf_is_metadata(&sb->path);
82 : }
83 :
84 23944 : int sbuf_to_manifest(struct sbuf *sb, struct fzp *fzp)
85 : {
86 23944 : if(!sb->path.buf) return 0;
87 :
88 23944 : if(sb->protocol1)
89 : {
90 11472 : if(sb->protocol1->datapth.buf
91 11472 : && iobuf_send_msg_fzp(&(sb->protocol1->datapth), fzp))
92 0 : return -1;
93 :
94 11472 : if(iobuf_send_msg_fzp(&sb->attr, fzp))
95 0 : return -1;
96 : }
97 : else
98 : {
99 : // Hackity hack: Strip the file index from the beginning of
100 : // the attribs so that manifests where nothing changed are
101 : // identical to each other. Better would be to preserve the
102 : // index.
103 : char *cp;
104 12472 : if(!(cp=strchr(sb->attr.buf, ' ')))
105 : {
106 0 : logp("Strange attributes: %s\n", sb->attr.buf);
107 0 : return -1;
108 : }
109 12472 : if(send_msg_fzp(fzp, CMD_ATTRIBS,
110 12472 : cp, sb->attr.len-(cp-sb->attr.buf)))
111 0 : return -1;
112 : }
113 23944 : if(iobuf_send_msg_fzp(&sb->path, fzp))
114 0 : return -1;
115 23944 : if(sb->link.buf
116 23944 : && iobuf_send_msg_fzp(&sb->link, fzp))
117 0 : return -1;
118 23944 : if(sb->endfile.buf
119 23944 : && iobuf_send_msg_fzp(&sb->endfile, fzp))
120 0 : return -1;
121 :
122 23944 : return 0;
123 : }
124 :
125 : // Like pathcmp, but sort entries that have the same paths so that metadata
126 : // comes later, and vss comes earlier, and trailing vss comes later.
127 0 : int sbuf_pathcmp(struct sbuf *a, struct sbuf *b)
128 : {
129 0 : return iobuf_pathcmp(&a->path, &b->path);
130 : }
131 :
132 0 : int sbuf_open_file(struct sbuf *sb, struct asfd *asfd, struct conf **confs)
133 : {
134 0 : BFILE *bfd=&sb->protocol2->bfd;
135 : #ifdef HAVE_WIN32
136 : if(win32_lstat(sb->path.buf, &sb->statp, &sb->winattr))
137 : #else
138 0 : if(lstat(sb->path.buf, &sb->statp))
139 : #endif
140 : {
141 : // This file is no longer available.
142 0 : logw(asfd, get_cntr(confs), "%s has vanished\n", sb->path.buf);
143 0 : return -1;
144 : }
145 0 : sb->compression=get_int(confs[OPT_COMPRESSION]);
146 : // Encryption not yet implemented in protocol2.
147 : //sb->protocol2->encryption=conf->protocol2->encryption_password?1:0;
148 0 : if(attribs_encode(sb)) return -1;
149 :
150 0 : if(bfd->open_for_send(bfd, asfd,
151 : sb->path.buf, sb->winattr,
152 0 : get_int(confs[OPT_ATIME]), get_cntr(confs), PROTO_2))
153 : {
154 : logw(asfd, get_cntr(confs),
155 0 : "Could not open %s\n", sb->path.buf);
156 0 : return -1;
157 : }
158 0 : return 0;
159 : }
160 :
161 0 : void sbuf_close_file(struct sbuf *sb, struct asfd *asfd)
162 : {
163 0 : BFILE *bfd=&sb->protocol2->bfd;
164 0 : bfd->close(bfd, asfd);
165 0 : }
166 :
167 0 : ssize_t sbuf_read(struct sbuf *sb, char *buf, size_t bufsize)
168 : {
169 0 : BFILE *bfd=&sb->protocol2->bfd;
170 0 : return (ssize_t)bfd->read(bfd, buf, bufsize);
171 : }
172 :
173 : enum parse_ret
174 : {
175 : PARSE_RET_ERROR=-1,
176 : PARSE_RET_NEED_MORE=0,
177 : PARSE_RET_COMPLETE=1,
178 : PARSE_RET_FINISHED=2,
179 : };
180 :
181 280047 : static parse_ret parse_cmd(struct sbuf *sb, struct asfd *asfd,
182 : struct iobuf *rbuf, struct blk *blk,
183 : const char *datpath, struct cntr *cntr)
184 : {
185 280047 : switch(rbuf->cmd)
186 : {
187 : case CMD_ATTRIBS:
188 26578 : if(sb->protocol2)
189 13288 : sbuf_free_content(sb);
190 : else
191 : {
192 13290 : if(sb->protocol1->datapth.buf)
193 : // protocol 1 phase 2+ file data
194 : // starts with datapth.
195 9080 : iobuf_free_content(&sb->attr);
196 : else
197 : // protocol 1 phase 1 or non file data
198 : // starts with attribs
199 4210 : sbuf_free_content(sb);
200 : }
201 26578 : iobuf_move(&sb->attr, rbuf);
202 26578 : attribs_decode(sb);
203 26578 : return PARSE_RET_NEED_MORE;
204 :
205 : case CMD_FILE:
206 : case CMD_DIRECTORY:
207 : case CMD_SOFT_LINK:
208 : case CMD_HARD_LINK:
209 : case CMD_SPECIAL:
210 : // Stuff not currently supported in burp-2, but OK
211 : // to find in burp-1.
212 : case CMD_ENC_FILE:
213 : case CMD_METADATA:
214 : case CMD_ENC_METADATA:
215 : case CMD_EFS_FILE:
216 : case CMD_VSS:
217 : case CMD_ENC_VSS:
218 : case CMD_VSS_T:
219 : case CMD_ENC_VSS_T:
220 29066 : if(!sb->attr.buf)
221 : {
222 0 : log_and_send(asfd, "read cmd with no attribs");
223 0 : return PARSE_RET_NEED_MORE;
224 : }
225 29066 : if(sb->flags & SBUF_NEED_LINK)
226 : {
227 2508 : if(cmd_is_link(rbuf->cmd))
228 : {
229 2508 : iobuf_free_content(&sb->link);
230 2508 : iobuf_move(&sb->link, rbuf);
231 2508 : sb->flags &= ~SBUF_NEED_LINK;
232 2508 : return PARSE_RET_COMPLETE;
233 : }
234 : else
235 : {
236 0 : log_and_send(asfd, "got non-link after link in manifest");
237 0 : return PARSE_RET_NEED_MORE;
238 : }
239 : }
240 : else
241 : {
242 26558 : iobuf_free_content(&sb->path);
243 26558 : iobuf_move(&sb->path, rbuf);
244 26558 : if(cmd_is_link(rbuf->cmd))
245 : {
246 2508 : sb->flags |= SBUF_NEED_LINK;
247 2508 : return PARSE_RET_NEED_MORE;
248 : }
249 24050 : else if(sb->protocol1
250 11972 : && sb->protocol1->datapth.buf)
251 : {
252 : // Protocol1 client restore reads
253 : // CMD_APPEND and CMD_END_FILE in the
254 : // calling function, so pretend it is
255 : // complete if we have the hack flag.
256 9080 : if(sb->flags & SBUF_CLIENT_RESTORE_HACK)
257 0 : return PARSE_RET_COMPLETE;
258 9080 : return PARSE_RET_NEED_MORE;
259 : }
260 14970 : return PARSE_RET_COMPLETE;
261 : }
262 : #ifndef HAVE_WIN32
263 : case CMD_SIG:
264 : // Fill in the sig/block, if the caller provided
265 : // a pointer for one. Server only.
266 198058 : if(!blk) return PARSE_RET_NEED_MORE;
267 :
268 : // Just fill in the sig details.
269 46104 : if(blk_set_from_iobuf_sig_and_savepath(blk, rbuf))
270 0 : return PARSE_RET_ERROR;
271 46104 : blk->got_save_path=1;
272 46104 : iobuf_free_content(rbuf);
273 46104 : if(datpath && rblk_retrieve_data(datpath, blk))
274 : {
275 0 : logp("Could not retrieve blk data.\n");
276 0 : return PARSE_RET_ERROR;
277 : }
278 46104 : return PARSE_RET_COMPLETE;
279 : #endif
280 : case CMD_DATA:
281 : // Need to write the block to disk.
282 : // Client only.
283 0 : if(!blk) return PARSE_RET_NEED_MORE;
284 0 : blk->data=rbuf->buf;
285 0 : blk->length=rbuf->len;
286 0 : rbuf->buf=NULL;
287 0 : return PARSE_RET_COMPLETE;
288 : case CMD_MESSAGE:
289 : case CMD_WARNING:
290 0 : log_recvd(rbuf, cntr, 1);
291 0 : return PARSE_RET_NEED_MORE;
292 : case CMD_GEN:
293 25 : if(!strcmp(rbuf->buf, "restoreend")
294 24 : || !strcmp(rbuf->buf, "phase1end")
295 0 : || !strcmp(rbuf->buf, "backupphase2")
296 : // Think these are protocol1 things.
297 0 : || !strcmp(rbuf->buf, "backupend")
298 0 : || !strcmp(rbuf->buf, "estimateend"))
299 25 : return PARSE_RET_FINISHED;
300 0 : iobuf_log_unexpected(rbuf, __func__);
301 0 : return PARSE_RET_ERROR;
302 : case CMD_FINGERPRINT:
303 36 : if(blk && blk_set_from_iobuf_fingerprint(blk, rbuf))
304 0 : return PARSE_RET_ERROR;
305 : // Fall through.
306 : case CMD_MANIFEST:
307 52 : iobuf_free_content(&sb->path);
308 52 : iobuf_move(&sb->path, rbuf);
309 52 : return PARSE_RET_COMPLETE;
310 : case CMD_ERROR:
311 0 : logp("got error: %s\n", rbuf->buf);
312 0 : return PARSE_RET_ERROR;
313 : case CMD_DATAPTH:
314 9080 : if(!sb->protocol1)
315 : {
316 0 : iobuf_log_unexpected(rbuf, __func__);
317 0 : return PARSE_RET_ERROR;
318 : }
319 9080 : if(sb->flags & SBUF_CLIENT_RESTORE_HACK)
320 : {
321 0 : sbuf_free_content(sb);
322 0 : sb->flags |= SBUF_CLIENT_RESTORE_HACK;
323 : }
324 : else
325 9080 : sbuf_free_content(sb);
326 :
327 9080 : iobuf_move(&sb->protocol1->datapth, rbuf);
328 9080 : return PARSE_RET_NEED_MORE;
329 : case CMD_END_FILE:
330 17188 : iobuf_free_content(&sb->endfile);
331 17188 : iobuf_move(&sb->endfile, rbuf);
332 17188 : if(sb->protocol1)
333 : {
334 18100 : if(!sb->attr.buf
335 9050 : || !sb->protocol1->datapth.buf
336 18100 : || (!sbuf_is_filedata(sb)
337 124 : && !sbuf_is_vssdata(sb)))
338 : {
339 0 : logp("got unexpected cmd_endfile");
340 0 : return PARSE_RET_ERROR;
341 : }
342 : }
343 17188 : return PARSE_RET_COMPLETE;
344 : default:
345 0 : iobuf_log_unexpected(rbuf, __func__);
346 0 : return PARSE_RET_ERROR;
347 : }
348 : logp("Fell out of switch unexpectedly in %s()\n", __func__);
349 : return PARSE_RET_ERROR;
350 : }
351 :
352 81184 : static int sbuf_fill(struct sbuf *sb, struct asfd *asfd, struct fzp *fzp,
353 : struct blk *blk, const char *datpath, struct cntr *cntr)
354 : {
355 : static struct iobuf *rbuf;
356 : static struct iobuf localrbuf;
357 81184 : int ret=-1;
358 :
359 81184 : if(asfd) rbuf=asfd->rbuf;
360 : else
361 : {
362 : // If not given asfd, use our own iobuf.
363 81182 : memset(&localrbuf, 0, sizeof(struct iobuf));
364 81182 : rbuf=&localrbuf;
365 : }
366 : while(1)
367 : {
368 280384 : iobuf_free_content(rbuf);
369 280384 : if(fzp)
370 : {
371 280382 : if((ret=iobuf_fill_from_fzp(rbuf, fzp)))
372 336 : goto end;
373 : }
374 : else
375 : {
376 2 : if(asfd->read(asfd))
377 : {
378 1 : logp("error in async_read\n");
379 1 : break;
380 : }
381 : }
382 280047 : switch(parse_cmd(sb, asfd, rbuf, blk, datpath, cntr))
383 : {
384 : case PARSE_RET_NEED_MORE:
385 199200 : continue;
386 : case PARSE_RET_COMPLETE:
387 80822 : return 0;
388 : case PARSE_RET_FINISHED:
389 25 : ret=1;
390 25 : goto end;
391 : case PARSE_RET_ERROR:
392 : default:
393 0 : ret=-1;
394 0 : goto end;
395 : }
396 : }
397 : end:
398 362 : iobuf_free_content(rbuf);
399 199562 : return ret;
400 : }
401 :
402 2 : int sbuf_fill_from_net(struct sbuf *sb, struct asfd *asfd,
403 : struct blk *blk, const char *datpath, struct cntr *cntr)
404 : {
405 2 : return sbuf_fill(sb, asfd, NULL, blk, datpath, cntr);
406 : }
407 :
408 81182 : int sbuf_fill_from_file(struct sbuf *sb, struct fzp *fzp,
409 : struct blk *blk, const char *datpath)
410 : {
411 81182 : return sbuf_fill(sb, NULL, fzp, blk, datpath, NULL);
412 : }
|