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 : printf("%s \n", fname);
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, int 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 : int vss_restore, struct cntr *cntr, const char *encryption_password)
158 : {
159 0 : int ret=-1;
160 0 : size_t metalen=0;
161 0 : char *metadata=NULL;
162 :
163 : // If it is directory metadata, try to make sure the directory
164 : // exists. Pass in NULL as the cntr, so no counting is done.
165 : // The actual directory entry will be coming after the metadata,
166 : // annoyingly. This is because of the way that the server is queuing
167 : // up directories to send after file data, so that the stat info on
168 : // them gets set correctly.
169 0 : if(act==ACTION_VERIFY)
170 : {
171 0 : cntr_add(cntr, sb->path.cmd, 1);
172 0 : ret=0;
173 0 : goto end;
174 : }
175 :
176 : // Create the directory, but do not add to the counts.
177 0 : if(S_ISDIR(sb->statp.st_mode)
178 0 : && restore_dir(asfd, sb, fname, act, /*cntr*/NULL, PROTO_1))
179 : goto end;
180 :
181 : // Read in the metadata...
182 0 : if(restore_file_or_get_meta(asfd, bfd, sb, fname, act,
183 : &metadata, &metalen, vss_restore, cntr, encryption_password))
184 : goto end;
185 0 : if(metadata)
186 : {
187 0 : if(!set_extrameta(asfd,
188 : #ifdef HAVE_WIN32
189 : bfd,
190 : #endif
191 : fname,
192 : metadata, metalen, cntr))
193 : {
194 : #ifndef HAVE_WIN32
195 : // Set file times again, since we just diddled with the
196 : // file. Do not set all attributes, as it will wipe
197 : // out any security attributes (eg getcap /usr/bin/ping)
198 0 : if(attribs_set_file_times(asfd, fname,
199 : &sb->statp, cntr))
200 : return -1;
201 0 : cntr_add(cntr, sb->path.cmd, 1);
202 : #endif
203 : }
204 : // Carry on if we could not set_extrameta.
205 : }
206 : ret=0;
207 : end:
208 0 : free_w(&metadata);
209 0 : return ret;
210 : }
211 :
212 5 : int restore_switch_protocol1(struct asfd *asfd, struct sbuf *sb,
213 : const char *fullpath, enum action act,
214 : struct BFILE *bfd, int vss_restore, struct cntr *cntr,
215 : const char *encryption_password)
216 : {
217 5 : switch(sb->path.cmd)
218 : {
219 : case CMD_FILE:
220 : case CMD_VSS_T:
221 : case CMD_ENC_FILE:
222 : case CMD_ENC_VSS_T:
223 : case CMD_EFS_FILE:
224 5 : if(!sb->protocol1->datapth.buf)
225 : {
226 : char msg[256];
227 1 : snprintf(msg, sizeof(msg),
228 : "datapth not supplied for %s in %s\n",
229 : iobuf_to_printable(&sb->path),
230 : __func__);
231 1 : log_and_send(asfd, msg);
232 : return -1;
233 : }
234 4 : return restore_file_or_get_meta(asfd, bfd, sb,
235 : fullpath, act,
236 : NULL, NULL, vss_restore, cntr,
237 : encryption_password);
238 : case CMD_METADATA:
239 : case CMD_VSS:
240 : case CMD_ENC_METADATA:
241 : case CMD_ENC_VSS:
242 0 : return restore_metadata(asfd, bfd, sb,
243 : fullpath, act,
244 : vss_restore, cntr, encryption_password);
245 : default:
246 : // Other cases (dir/links/etc) are handled in the
247 : // calling function.
248 0 : logp("unknown cmd: %s\n",
249 : iobuf_to_printable(&sb->path));
250 0 : return -1;
251 : }
252 : }
|