Line data Source code
1 : /*
2 : Bacula® - The Network Backup Solution
3 :
4 : Copyright (C) 2000-2009 Free Software Foundation Europe e.V.
5 :
6 : The main author of Bacula is Kern Sibbald, with contributions from
7 : many others, a complete list can be found in the file AUTHORS.
8 : This program is Free Software; you can redistribute it and/or
9 : modify it under the terms of version three of the GNU Affero General Public
10 : License as published by the Free Software Foundation and included
11 : in the file LICENSE.
12 :
13 : This program is distributed in the hope that it will be useful, but
14 : WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 : General Public License for more details.
17 :
18 : You should have received a copy of the GNU Affero General Public License
19 : along with this program; if not, write to the Free Software
20 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 : 02110-1301, USA.
22 :
23 : Bacula® is a registered trademark of Kern Sibbald.
24 : The licensor of Bacula is the Free Software Foundation Europe
25 : (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 : Switzerland, email:ftf@fsfeurope.org.
27 : */
28 : /*
29 : * Traces of * bacula-5.0.3:src/filed/backup.c still exist in this file, hence
30 : * the copyright notice above. Specifically, FF_PKT and the FF_* types. At
31 : * some point, these will be removed in favour of the burp sbuf code.
32 : * Graham Keeling, 2014.
33 : */
34 :
35 : #include "../burp.h"
36 : #include "../alloc.h"
37 : #include "../asfd.h"
38 : #include "../async.h"
39 : #include "../attribs.h"
40 : #include "../cmd.h"
41 : #include "../cntr.h"
42 : #include "../linkhash.h"
43 : #include "../log.h"
44 : #include "../strlist.h"
45 : #include "extrameta.h"
46 : #include "find.h"
47 : #include "backup_phase1.h"
48 :
49 : static int encryption=ENCRYPTION_NONE;
50 : static enum cmd filesymbol=CMD_FILE;
51 : static enum cmd dirsymbol=CMD_DIRECTORY;
52 : #ifdef HAVE_WIN32
53 : static enum cmd metasymbol=CMD_VSS;
54 : static enum cmd vss_trail_symbol=CMD_VSS_T;
55 : #else
56 : static enum cmd metasymbol=CMD_METADATA;
57 : #endif
58 :
59 : static int enable_acl=0;
60 : static int enable_xattr=0;
61 :
62 0 : static int usual_stuff(struct asfd *asfd,
63 : struct cntr *cntr, const char *path, const char *link,
64 : struct sbuf *sb, enum cmd cmd)
65 : {
66 : // When run with ACTION_ESTIMATE, asfd is NULL.
67 0 : if(asfd)
68 : {
69 0 : if(asfd->write_str(asfd, CMD_ATTRIBS, sb->attr.buf)
70 0 : || asfd->write_str(asfd, cmd, path)
71 0 : || ((cmd==CMD_HARD_LINK || cmd==CMD_SOFT_LINK)
72 0 : && asfd->write_str(asfd, cmd, link)))
73 : return -1;
74 : }
75 0 : cntr_add_phase1(cntr, cmd, 1);
76 : return 0;
77 : }
78 :
79 0 : static int maybe_send_extrameta(struct asfd *asfd,
80 : const char *path, enum cmd cmd,
81 : struct sbuf *sb,
82 : struct cntr *cntr, enum cmd symbol)
83 : {
84 : // FIX THIS: should probably initialise extrameta with the desired
85 : // conf parameters so that they do not need to be passed in all the
86 : // time.
87 0 : if(!has_extrameta(path, cmd, enable_acl, enable_xattr))
88 : return 0;
89 0 : return usual_stuff(asfd, cntr, path, NULL, sb, symbol);
90 : }
91 :
92 0 : static int ft_err(struct asfd *asfd,
93 : struct conf **confs, struct FF_PKT *ff, const char *msg)
94 : {
95 : int raise_error;
96 0 : const char *prefix="";
97 0 : raise_error=get_int(confs[OPT_SCAN_PROBLEM_RAISES_ERROR]);
98 0 : if(raise_error) prefix="Err: ";
99 0 : if(logw(asfd, get_cntr(confs), "%s%s %s: %s\n", prefix, msg,
100 0 : ff->fname, strerror(errno))) return -1;
101 0 : if(raise_error) return -1;
102 : return 0;
103 : }
104 :
105 0 : static int do_to_server(struct asfd *asfd,
106 : struct conf **confs, struct FF_PKT *ff, struct sbuf *sb,
107 : enum cmd cmd, int compression)
108 : {
109 : #ifdef HAVE_WIN32
110 : int split_vss=0;
111 : int strip_vss=0;
112 : if(get_protocol(confs)==PROTO_1)
113 : {
114 : split_vss=get_int(confs[OPT_SPLIT_VSS]);
115 : strip_vss=get_int(confs[OPT_STRIP_VSS]);
116 : }
117 : #endif
118 0 : struct cntr *cntr=get_cntr(confs);
119 0 : sb->compression=compression;
120 0 : sb->encryption=encryption;
121 0 : sb->statp=ff->statp;
122 0 : sb->winattr=ff->winattr;
123 0 : attribs_encode(sb);
124 :
125 : #ifdef HAVE_WIN32
126 : if(split_vss
127 : && !strip_vss
128 : && cmd!=CMD_EFS_FILE
129 : && maybe_send_extrameta(asfd, ff->fname,
130 : cmd, sb, cntr, metasymbol))
131 : return -1;
132 : #endif
133 :
134 0 : if(usual_stuff(asfd, cntr, ff->fname, ff->link, sb, cmd)) return -1;
135 :
136 0 : if(ff->type==FT_REG)
137 0 : cntr_add_val(cntr, CMD_BYTES_ESTIMATED,
138 0 : (uint64_t)ff->statp.st_size);
139 : #ifdef HAVE_WIN32
140 : if(split_vss
141 : && !strip_vss
142 : && cmd!=CMD_EFS_FILE
143 : // FIX THIS: May have to check that it is not a directory here.
144 : && !S_ISDIR(sb->statp.st_mode) // does this work?
145 : && maybe_send_extrameta(asfd,
146 : ff->fname, cmd, sb, cntr, vss_trail_symbol))
147 : return -1;
148 : return 0;
149 : #else
150 0 : return maybe_send_extrameta(asfd, ff->fname, cmd, sb,
151 : cntr, metasymbol);
152 : #endif
153 : }
154 :
155 0 : static int to_server(struct asfd *asfd, struct conf **confs, struct FF_PKT *ff,
156 : struct sbuf *sb, enum cmd cmd)
157 : {
158 0 : return do_to_server(asfd, confs,
159 : ff, sb, cmd, get_int(confs[OPT_COMPRESSION]));
160 : }
161 :
162 0 : static int my_send_file(struct asfd *asfd, struct FF_PKT *ff, struct conf **confs)
163 : {
164 : static struct sbuf *sb=NULL;
165 0 : struct cntr *cntr=get_cntr(confs);
166 :
167 0 : if(!sb && !(sb=sbuf_alloc(get_protocol(confs)))) return -1;
168 :
169 : #ifdef HAVE_WIN32
170 : if(ff->winattr & FILE_ATTRIBUTE_ENCRYPTED)
171 : {
172 : if(ff->type==FT_REG
173 : || ff->type==FT_DIR)
174 : return to_server(asfd, confs, ff, sb, CMD_EFS_FILE);
175 : return logw(asfd, cntr,
176 : "EFS type %d not yet supported: %s\n",
177 : ff->type, ff->fname);
178 : }
179 : #endif
180 :
181 0 : switch(ff->type)
182 : {
183 : case FT_REG:
184 : case FT_RAW:
185 : case FT_FIFO:
186 0 : return do_to_server(asfd, confs, ff, sb, filesymbol,
187 : in_exclude_comp(get_strlist(confs[OPT_EXCOM]),
188 0 : ff->fname, get_int(confs[OPT_COMPRESSION])));
189 : case FT_DIR:
190 : case FT_REPARSE:
191 : case FT_JUNCTION:
192 0 : return to_server(asfd, confs, ff, sb, dirsymbol);
193 : case FT_LNK_S:
194 0 : return to_server(asfd, confs, ff, sb, CMD_SOFT_LINK);
195 : case FT_LNK_H:
196 0 : return to_server(asfd, confs, ff, sb, CMD_HARD_LINK);
197 : case FT_SPEC:
198 0 : return to_server(asfd, confs, ff, sb, CMD_SPECIAL);
199 : case FT_NOFSCHG:
200 0 : return ft_err(asfd, confs, ff, "Will not descend: "
201 : "file system change not allowed");
202 : case FT_NOFOLLOW:
203 0 : return ft_err(asfd, confs, ff, "Could not follow link");
204 : case FT_NOSTAT:
205 0 : return ft_err(asfd, confs, ff, "Could not stat");
206 : case FT_NOOPEN:
207 0 : return ft_err(asfd, confs, ff, "Could not open directory");
208 : default:
209 0 : return logw(asfd, cntr,
210 : "Err: Unknown file type %d: %s\n",
211 : ff->type, ff->fname);
212 : }
213 : }
214 :
215 0 : int backup_phase1_client(struct asfd *asfd, struct conf **confs)
216 : {
217 0 : int ret=-1;
218 0 : struct FF_PKT *ff=NULL;
219 0 : struct strlist *l=NULL;
220 0 : enable_acl=get_int(confs[OPT_ACL]);
221 0 : enable_xattr=get_int(confs[OPT_XATTR]);
222 :
223 : // First, tell the server about everything that needs to be backed up.
224 :
225 0 : logp("Phase 1 begin (file system scan)\n");
226 :
227 : // Encryption not yet supported in protocol2.
228 0 : if(get_protocol(confs)==PROTO_1
229 0 : && get_string(confs[OPT_ENCRYPTION_PASSWORD]))
230 : {
231 0 : encryption=ENCRYPTION_KEY_DERIVED;
232 0 : filesymbol=CMD_ENC_FILE;
233 0 : metasymbol=CMD_ENC_METADATA;
234 : #ifdef HAVE_WIN32
235 : metasymbol=CMD_ENC_VSS;
236 : vss_trail_symbol=CMD_ENC_VSS_T;
237 : #endif
238 : }
239 : #ifdef HAVE_WIN32
240 : dirsymbol=filesymbol;
241 : if(get_protocol(confs)==PROTO_1
242 : && get_int(confs[OPT_STRIP_VSS]))
243 : dirsymbol=CMD_DIRECTORY;
244 : #endif
245 :
246 0 : if(!(ff=find_files_init(my_send_file))) goto end;
247 0 : for(l=get_strlist(confs[OPT_STARTDIR]); l; l=l->next) if(l->flag)
248 0 : if(find_files_begin(asfd, ff, confs, l->path)) goto end;
249 : ret=0;
250 : end:
251 0 : cntr_print_end_phase1(get_cntr(confs));
252 0 : if(ret) logp("Error in phase 1\n");
253 0 : logp("Phase 1 end (file system scan)\n");
254 0 : find_files_free(&ff);
255 :
256 0 : return ret;
257 : }
|