Line data Source code
1 : #include "../../burp.h"
2 : #include "../../action.h"
3 : #include "../../alloc.h"
4 : #include "../../asfd.h"
5 : #include "../../async.h"
6 : #include "../../attribs.h"
7 : #include "../../bfile.h"
8 : #include "../../cmd.h"
9 : #include "../../cntr.h"
10 : #include "../../fsops.h"
11 : #include "../../handy.h"
12 : #include "../../log.h"
13 : #include "../../protocol1/msg.h"
14 : #include "../extrameta.h"
15 : #include "../restore.h"
16 : #include "restore.h"
17 :
18 4 : static int do_restore_file_or_get_meta(struct asfd *asfd, struct BFILE *bfd,
19 : struct sbuf *sb, const char *fname,
20 : char **metadata, size_t *metalen,
21 : struct cntr *cntr, const char *rpath,
22 : const char *encryption_password)
23 : {
24 4 : int ret=-1;
25 4 : int enccompressed=0;
26 4 : uint64_t rcvdbytes=0;
27 4 : uint64_t sentbytes=0;
28 4 : const char *encpassword=NULL;
29 4 : int key_deriv=0;
30 :
31 4 : if(sbuf_is_encrypted(sb))
32 : {
33 2 : encpassword=encryption_password;
34 2 : if(sb->encryption==ENCRYPTION_KEY_DERIVED)
35 0 : key_deriv=1;
36 : }
37 4 : enccompressed=dpth_protocol1_is_compressed(sb->compression,
38 4 : sb->protocol1->datapth.buf);
39 :
40 : /*
41 : if(encpassword && !enccompressed)
42 : printf("encrypted and not compressed\n");
43 : else if(!encpassword && enccompressed)
44 : printf("not encrypted and compressed\n");
45 : else if(!encpassword && !enccompressed)
46 : printf("not encrypted and not compressed\n");
47 : else if(encpassword && enccompressed)
48 : printf("encrypted and compressed\n");
49 : */
50 :
51 4 : if(metadata)
52 : {
53 0 : ret=transfer_gzfile_inl(asfd,
54 : #ifdef HAVE_WIN32
55 : sb,
56 : #endif
57 : NULL,
58 : &rcvdbytes, &sentbytes, encpassword,
59 : enccompressed, cntr, metadata,
60 0 : key_deriv, sb->protocol1->salt);
61 0 : *metalen=sentbytes;
62 : // skip setting cntr, as we do not actually
63 : // restore until a bit later
64 : }
65 : else
66 : {
67 4 : ret=transfer_gzfile_inl(asfd,
68 : #ifdef HAVE_WIN32
69 : sb,
70 : #endif
71 : bfd,
72 : &rcvdbytes, &sentbytes,
73 : encpassword, enccompressed,
74 4 : cntr, NULL, key_deriv, sb->protocol1->salt);
75 : #ifndef HAVE_WIN32
76 4 : if(bfd && bfd->close(bfd, asfd))
77 : {
78 0 : logp("error closing %s in %s\n",
79 : fname, __func__);
80 0 : ret=-1;
81 : }
82 : // For Windows, only set the attribs when it closes the file,
83 : // so that trailing vss does not get blocked after having set
84 : // a read-only attribute.
85 4 : if(!ret) attribs_set(asfd, rpath,
86 : &sb->statp, sb->winattr, cntr);
87 : #endif
88 : }
89 4 : if(ret)
90 : {
91 0 : char msg[256]="";
92 0 : snprintf(msg, sizeof(msg),
93 : "Could not transfer file in: %s", rpath);
94 0 : return restore_interrupt(asfd, sb, msg, cntr, PROTO_1);
95 : }
96 : return 0;
97 : }
98 :
99 4 : static int restore_file_or_get_meta(struct asfd *asfd, struct BFILE *bfd,
100 : struct sbuf *sb, const char *fname, enum action act,
101 : char **metadata, size_t *metalen, enum vss_restore vss_restore,
102 : struct cntr *cntr, const char *encyption_password)
103 : {
104 4 : int ret=0;
105 4 : char *rpath=NULL;
106 :
107 4 : if(act==ACTION_VERIFY)
108 : {
109 0 : cntr_add(cntr, sb->path.cmd, 1);
110 0 : goto end;
111 : }
112 :
113 4 : if(build_path(fname, "", &rpath, NULL))
114 : {
115 0 : char msg[256]="";
116 : // failed - do a warning
117 0 : snprintf(msg, sizeof(msg), "build path failed: %s", fname);
118 0 : if(restore_interrupt(asfd, sb, msg, cntr, PROTO_1))
119 0 : ret=-1;
120 : goto end;
121 : }
122 :
123 : #ifndef HAVE_WIN32
124 : // We always want to open the file if it is on Windows. Otherwise,
125 : // only open it if we are not doing metadata.
126 4 : if(!metadata)
127 : {
128 : #endif
129 4 : switch(open_for_restore(asfd,
130 : bfd, rpath, sb, vss_restore, cntr, PROTO_1))
131 : {
132 : case OFR_OK: break;
133 : case OFR_CONTINUE: goto end;
134 0 : default: ret=-1; goto end;
135 : }
136 : #ifndef HAVE_WIN32
137 : }
138 : #endif
139 :
140 4 : if(!(ret=do_restore_file_or_get_meta(asfd, bfd, sb, fname,
141 : metadata, metalen, cntr, rpath, encyption_password)))
142 : {
143 : // Only add to counters if we are not doing metadata. The
144 : // actual metadata restore comes a bit later.
145 4 : if(!metadata)
146 4 : cntr_add(cntr, sb->path.cmd, 1);
147 : }
148 : end:
149 4 : free_w(&rpath);
150 4 : if(ret) logp("restore_file error\n");
151 4 : return ret;
152 : }
153 :
154 0 : static int restore_metadata(struct asfd *asfd,
155 : struct BFILE *bfd, struct sbuf *sb,
156 : const char *fname, enum action act,
157 : enum vss_restore vss_restore,
158 : struct cntr *cntr, const char *encryption_password)
159 : {
160 0 : int ret=-1;
161 0 : size_t metalen=0;
162 0 : char *metadata=NULL;
163 :
164 : // If it is directory metadata, try to make sure the directory
165 : // exists. Pass in NULL as the cntr, so no counting is done.
166 : // The actual directory entry will be coming after the metadata,
167 : // annoyingly. This is because of the way that the server is queuing
168 : // up directories to send after file data, so that the stat info on
169 : // them gets set correctly.
170 0 : if(act==ACTION_VERIFY)
171 : {
172 0 : cntr_add(cntr, sb->path.cmd, 1);
173 0 : ret=0;
174 0 : goto end;
175 : }
176 :
177 : // Create the directory, but do not add to the counts.
178 0 : if(S_ISDIR(sb->statp.st_mode)
179 0 : && restore_dir(asfd, sb, fname, act, /*cntr*/NULL, PROTO_1))
180 : goto end;
181 :
182 : // Read in the metadata...
183 0 : if(restore_file_or_get_meta(asfd, bfd, sb, fname, act,
184 : &metadata, &metalen, vss_restore, cntr, encryption_password))
185 : goto end;
186 0 : if(metadata)
187 : {
188 0 : if(!set_extrameta(asfd,
189 : #ifdef HAVE_WIN32
190 : bfd,
191 : #endif
192 : fname,
193 : metadata, metalen, cntr))
194 : {
195 : #ifndef HAVE_WIN32
196 : // Set file times again, since we just diddled with the
197 : // file. Do not set all attributes, as it will wipe
198 : // out any security attributes (eg getcap /usr/bin/ping)
199 0 : if(attribs_set_file_times(asfd, fname,
200 : &sb->statp, cntr))
201 : return -1;
202 0 : cntr_add(cntr, sb->path.cmd, 1);
203 : #endif
204 : }
205 : // Carry on if we could not set_extrameta.
206 : }
207 : ret=0;
208 : end:
209 0 : free_w(&metadata);
210 0 : return ret;
211 : }
212 :
213 5 : int restore_switch_protocol1(struct asfd *asfd, struct sbuf *sb,
214 : const char *fullpath, enum action act,
215 : struct BFILE *bfd, enum vss_restore vss_restore, struct cntr *cntr,
216 : const char *encryption_password)
217 : {
218 5 : switch(sb->path.cmd)
219 : {
220 : case CMD_FILE:
221 : case CMD_VSS_T:
222 : case CMD_ENC_FILE:
223 : case CMD_ENC_VSS_T:
224 : case CMD_EFS_FILE:
225 5 : if(!sb->protocol1->datapth.buf)
226 : {
227 : char msg[256];
228 1 : snprintf(msg, sizeof(msg),
229 : "datapth not supplied for %s in %s\n",
230 : iobuf_to_printable(&sb->path),
231 : __func__);
232 1 : log_and_send(asfd, msg);
233 : return -1;
234 : }
235 4 : return restore_file_or_get_meta(asfd, bfd, sb,
236 : fullpath, act,
237 : NULL, NULL, vss_restore, cntr,
238 : encryption_password);
239 : case CMD_METADATA:
240 : case CMD_VSS:
241 : case CMD_ENC_METADATA:
242 : case CMD_ENC_VSS:
243 0 : return restore_metadata(asfd, bfd, sb,
244 : fullpath, act,
245 : vss_restore, cntr, encryption_password);
246 : default:
247 : // Other cases (dir/links/etc) are handled in the
248 : // calling function.
249 0 : logp("unknown cmd: %s\n",
250 : iobuf_to_printable(&sb->path));
251 0 : return -1;
252 : }
253 : }
|