Line data Source code
1 : #include "../../burp.h"
2 : #include "../../action.h"
3 : #include "../../asfd.h"
4 : #include "../../async.h"
5 : #include "../../cmd.h"
6 : #include "../../cntr.h"
7 : #include "../../handy.h"
8 : #include "../../hexmap.h"
9 : #include "../../log.h"
10 : #include "../../prepend.h"
11 : #include "../../protocol2/blk.h"
12 : #include "../../protocol2/rabin/rconf.h"
13 : #include "../../regexp.h"
14 : #include "../../sbuf.h"
15 : #include "../../slist.h"
16 : #include "../../server/protocol1/restore.h"
17 : #include "../manio.h"
18 : #include "../sdirs.h"
19 : #include "champ_chooser/hash.h"
20 :
21 : /* This function reads the manifest to determine whether it may be more
22 : efficient to just copy the data files across and unpack them on the other
23 : side. If it thinks it is, it will then do it.
24 : Return -1 on error, 1 if it copied the data across, 0 if it did not. */
25 4 : int maybe_restore_spool(struct asfd *asfd, const char *manifest,
26 : struct sdirs *sdirs, struct bu *bu, int srestore, regex_t *regex,
27 : struct conf **confs, struct slist *slist,
28 : enum action act, enum cntr_status cntr_status)
29 : {
30 : int ars;
31 4 : int ret=-1;
32 4 : struct sbuf *sb=NULL;
33 4 : struct blk *blk=NULL;
34 4 : struct manio *manio=NULL;
35 4 : uint64_t blkcount=0;
36 4 : uint64_t datcount=0;
37 : struct hash_weak *tmpw;
38 : struct hash_weak *hash_weak;
39 : uint64_t estimate_blks;
40 : uint64_t estimate_dats;
41 : uint64_t estimate_one_dat;
42 4 : struct sbuf *need_data=NULL;
43 4 : int last_ent_was_dir=0;
44 4 : char sig[128]="";
45 4 : const char *restore_spool=get_string(confs[OPT_RESTORE_SPOOL]);
46 :
47 : // If the client has no restore_spool directory, we have to fall back
48 : // to the stream style restore.
49 4 : if(!restore_spool) return 0;
50 :
51 0 : if(!(manio=manio_open(manifest, "rb", PROTO_2))
52 0 : || !(need_data=sbuf_alloc(PROTO_2))
53 0 : || !(sb=sbuf_alloc(PROTO_2))
54 0 : || !(blk=blk_alloc()))
55 : goto end;
56 :
57 : while(1)
58 : {
59 0 : if((ars=manio_read_with_blk(manio, sb, blk, NULL))<0)
60 : {
61 : logp("Error from manio_read_async() in %s\n",
62 0 : __func__);
63 0 : goto end; // Error;
64 : }
65 0 : else if(ars>0)
66 : break; // Finished OK.
67 :
68 0 : if(!blk->got_save_path)
69 : {
70 0 : sbuf_free_content(sb);
71 0 : continue;
72 : }
73 :
74 0 : if(want_to_restore(srestore, sb, regex, confs))
75 : {
76 0 : blkcount++;
77 0 : if(!hash_weak_find((uint64_t)blk->savepath))
78 : {
79 0 : if(!hash_weak_add((uint64_t)blk->savepath))
80 : goto end;
81 0 : datcount++;
82 : }
83 : }
84 :
85 0 : sbuf_free_content(sb);
86 : }
87 :
88 : // FIX THIS: should read rabin_avg of a struct rconf.
89 0 : estimate_blks=blkcount*RABIN_AVG;
90 0 : estimate_one_dat=DATA_FILE_SIG_MAX*RABIN_AVG;
91 0 : estimate_dats=datcount*estimate_one_dat;
92 : printf("%" PRIu64 " blocks = %" PRIu64 " bytes in stream approx\n",
93 : blkcount, estimate_blks);
94 : printf("%" PRIu64 " data files = %" PRIu64 " bytes approx\n",
95 : datcount, estimate_dats);
96 :
97 0 : if(estimate_blks < estimate_one_dat)
98 : {
99 : printf("Stream is less than the size of a data file.\n");
100 : printf("Use restore stream\n");
101 0 : return 0;
102 : }
103 0 : else if(estimate_dats >= 90*(estimate_blks/100))
104 : {
105 : printf("Stream is more than 90%% size of data files.\n");
106 : printf("Use restore stream\n");
107 0 : return 0;
108 : }
109 : else
110 : {
111 : printf("Data files are less than 90%% size of stream.\n");
112 : printf("Use data files\n");
113 : }
114 :
115 : printf("Client is using restore_spool: %s\n", restore_spool);
116 :
117 0 : if(asfd->write_str(asfd, CMD_GEN, "restore_spool")
118 0 : || asfd_read_expect(asfd, CMD_GEN, "restore_spool_ok"))
119 : goto end;
120 :
121 : // Send each of the data files that we found to the client.
122 0 : HASH_ITER(hh, hash_table, hash_weak, tmpw)
123 : {
124 : char msg[32];
125 : char path[32];
126 0 : char *fdatpath=NULL;
127 0 : snprintf(path, sizeof(path), "%014" PRIX64, hash_weak->weak);
128 0 : path[4]='/';
129 0 : path[9]='/';
130 : snprintf(msg, sizeof(msg), "dat=%s", path);
131 : printf("got: %s\n", msg);
132 0 : if(asfd->write_str(asfd, CMD_GEN, msg)) goto end;
133 0 : if(!(fdatpath=prepend_s(sdirs->data, path)))
134 : goto end;
135 0 : if(send_a_file(asfd, fdatpath, get_cntr(confs)))
136 : {
137 0 : free_w(&fdatpath);
138 0 : goto end;
139 : }
140 0 : free_w(&fdatpath);
141 : }
142 :
143 0 : if(asfd->write_str(asfd, CMD_GEN, "datfilesend")
144 0 : || asfd_read_expect(asfd, CMD_GEN, "datfilesend_ok"))
145 : goto end;
146 :
147 0 : manio_close(&manio);
148 : // Send the manifest to the client.
149 0 : if(manio_open(manifest, "rb", PROTO_2))
150 : goto end;
151 0 : blk->got_save_path=0;
152 : while(1)
153 : {
154 0 : if((ars=manio_read_with_blk(manio, sb, blk, NULL))<0)
155 : {
156 : logp("Error from manio_read_async() in %s\n",
157 0 : __func__);
158 0 : goto end; // Error;
159 : }
160 0 : else if(ars>0)
161 : break; // Finished OK.
162 :
163 0 : if(blk->got_save_path)
164 : {
165 : //if(async_write(asfd, CMD_DATA, blk->data, blk->length))
166 : // return -1;
167 : // FIX THIS: Need to send this stuff unconverted.
168 : snprintf(sig, sizeof(sig),
169 : "%016" PRIX64 "%s%s",
170 : blk->fingerprint,
171 : bytes_to_md5str(blk->md5sum),
172 0 : uint64_to_savepathstr_with_sig(blk->savepath));
173 0 : if(asfd->write_str(asfd, CMD_SIG, sig))
174 : goto end;
175 0 : blk->got_save_path=0;
176 0 : continue;
177 : }
178 :
179 0 : sbuf_free_content(need_data);
180 :
181 0 : if(want_to_restore(srestore, sb, regex, confs))
182 : {
183 0 : if(restore_ent(asfd, &sb, slist, bu, act,
184 : sdirs, cntr_status, confs,
185 0 : need_data, &last_ent_was_dir, manifest))
186 : goto end;
187 : }
188 :
189 0 : sbuf_free_content(sb);
190 : }
191 :
192 : ret=1;
193 : end:
194 0 : blk_free(&blk);
195 0 : sbuf_free(&sb);
196 0 : sbuf_free(&need_data);
197 0 : manio_close(&manio);
198 0 : hash_delete_all();
199 0 : return ret;
200 : }
|