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 enum cmd filesymbol=CMD_FILE;
50 : static enum cmd dirsymbol=CMD_DIRECTORY;
51 : #ifdef HAVE_WIN32
52 : static enum cmd metasymbol=CMD_VSS;
53 : static enum cmd vss_trail_symbol=CMD_VSS_T;
54 : #else
55 : static enum cmd metasymbol=CMD_METADATA;
56 : #endif
57 :
58 : static int enable_acl=0;
59 : static int enable_xattr=0;
60 :
61 0 : static int usual_stuff(struct asfd *asfd,
62 : struct cntr *cntr, const char *path, const char *link,
63 : struct sbuf *sb, enum cmd cmd)
64 : {
65 : // When run with ACTION_ESTIMATE, asfd is NULL.
66 0 : if(asfd)
67 : {
68 0 : if(asfd->write_str(asfd, CMD_ATTRIBS, sb->attr.buf)
69 0 : || asfd->write_str(asfd, cmd, path)
70 0 : || ((cmd==CMD_HARD_LINK || cmd==CMD_SOFT_LINK)
71 0 : && asfd->write_str(asfd, cmd, link)))
72 : return -1;
73 : }
74 0 : cntr_add_phase1(cntr, cmd, 1);
75 : return 0;
76 : }
77 :
78 0 : static int maybe_send_extrameta(struct asfd *asfd,
79 : const char *path, enum cmd cmd,
80 : struct sbuf *sb,
81 : struct cntr *cntr, enum cmd symbol)
82 : {
83 : // FIX THIS: should probably initialise extrameta with the desired
84 : // conf parameters so that they do not need to be passed in all the
85 : // time.
86 0 : if(!has_extrameta(path, cmd, enable_acl, enable_xattr))
87 : return 0;
88 0 : return usual_stuff(asfd, cntr, path, NULL, sb, symbol);
89 : }
90 :
91 0 : static int ft_err(struct asfd *asfd,
92 : struct conf **confs, struct FF_PKT *ff, const char *msg)
93 : {
94 : int raise_error;
95 0 : const char *prefix="";
96 0 : raise_error=get_int(confs[OPT_SCAN_PROBLEM_RAISES_ERROR]);
97 0 : if(raise_error) prefix="Err: ";
98 0 : if(logw(asfd, get_cntr(confs), "%s%s %s: %s\n", prefix, msg,
99 0 : ff->fname, strerror(errno))) return -1;
100 0 : if(raise_error) return -1;
101 : return 0;
102 : }
103 :
104 0 : static int do_to_server(struct asfd *asfd,
105 : struct conf **confs, struct FF_PKT *ff, struct sbuf *sb,
106 : enum cmd cmd, int compression)
107 : {
108 : #ifdef HAVE_WIN32
109 : int split_vss=0;
110 : int strip_vss=0;
111 : if(get_protocol(confs)==PROTO_1)
112 : {
113 : split_vss=get_int(confs[OPT_SPLIT_VSS]);
114 : strip_vss=get_int(confs[OPT_STRIP_VSS]);
115 : }
116 : #endif
117 0 : struct cntr *cntr=get_cntr(confs);
118 0 : sb->compression=compression;
119 0 : sb->statp=ff->statp;
120 0 : attribs_encode(sb);
121 :
122 : #ifdef HAVE_WIN32
123 : if(split_vss
124 : && !strip_vss
125 : && cmd!=CMD_EFS_FILE
126 : && maybe_send_extrameta(asfd, ff->fname,
127 : cmd, sb, cntr, metasymbol))
128 : return -1;
129 : #endif
130 :
131 0 : if(usual_stuff(asfd, cntr, ff->fname, ff->link, sb, cmd)) return -1;
132 :
133 0 : if(ff->type==FT_REG)
134 0 : cntr_add_val(cntr, CMD_BYTES_ESTIMATED,
135 0 : (uint64_t)ff->statp.st_size);
136 : #ifdef HAVE_WIN32
137 : if(split_vss
138 : && !strip_vss
139 : && cmd!=CMD_EFS_FILE
140 : // FIX THIS: May have to check that it is not a directory here.
141 : && !S_ISDIR(sb->statp.st_mode) // does this work?
142 : && maybe_send_extrameta(asfd,
143 : ff->fname, cmd, sb, cntr, vss_trail_symbol))
144 : return -1;
145 : return 0;
146 : #else
147 0 : return maybe_send_extrameta(asfd, ff->fname, cmd, sb,
148 : cntr, metasymbol);
149 : #endif
150 : }
151 :
152 0 : static int to_server(struct asfd *asfd, struct conf **confs, struct FF_PKT *ff,
153 : struct sbuf *sb, enum cmd cmd)
154 : {
155 0 : return do_to_server(asfd, confs,
156 : ff, sb, cmd, get_int(confs[OPT_COMPRESSION]));
157 : }
158 :
159 0 : static int burp_send_file(struct asfd *asfd, struct FF_PKT *ff, struct conf **confs)
160 : {
161 : static struct sbuf *sb=NULL;
162 0 : struct cntr *cntr=get_cntr(confs);
163 :
164 0 : if(!sb && !(sb=sbuf_alloc(get_protocol(confs)))) return -1;
165 :
166 : #ifdef HAVE_WIN32
167 : if(ff->winattr & FILE_ATTRIBUTE_ENCRYPTED)
168 : {
169 : if(ff->type==FT_REG
170 : || ff->type==FT_DIR)
171 : return to_server(asfd, confs, ff, sb, CMD_EFS_FILE);
172 : return logw(asfd, cntr,
173 : "EFS type %d not yet supported: %s\n",
174 : ff->type, ff->fname);
175 : }
176 : #endif
177 :
178 0 : switch(ff->type)
179 : {
180 : case FT_REG:
181 : case FT_RAW:
182 : case FT_FIFO:
183 0 : return do_to_server(asfd, confs, ff, sb, filesymbol,
184 : in_exclude_comp(get_strlist(confs[OPT_EXCOM]),
185 0 : ff->fname, get_int(confs[OPT_COMPRESSION])));
186 : case FT_DIR:
187 : case FT_REPARSE:
188 : case FT_JUNCTION:
189 0 : return to_server(asfd, confs, ff, sb, dirsymbol);
190 : case FT_LNK_S:
191 0 : return to_server(asfd, confs, ff, sb, CMD_SOFT_LINK);
192 : case FT_LNK_H:
193 0 : return to_server(asfd, confs, ff, sb, CMD_HARD_LINK);
194 : case FT_SPEC:
195 0 : return to_server(asfd, confs, ff, sb, CMD_SPECIAL);
196 : case FT_NOFSCHG:
197 0 : return ft_err(asfd, confs, ff, "Will not descend: "
198 : "file system change not allowed");
199 : case FT_NOFOLLOW:
200 0 : return ft_err(asfd, confs, ff, "Could not follow link");
201 : case FT_NOSTAT:
202 0 : return ft_err(asfd, confs, ff, "Could not stat");
203 : case FT_NOOPEN:
204 0 : return ft_err(asfd, confs, ff, "Could not open directory");
205 : default:
206 0 : return logw(asfd, cntr,
207 : "Err: Unknown file type %d: %s\n",
208 : ff->type, ff->fname);
209 : }
210 : }
211 :
212 0 : int backup_phase1_client(struct asfd *asfd, struct conf **confs)
213 : {
214 0 : int ret=-1;
215 0 : struct FF_PKT *ff=NULL;
216 0 : struct strlist *l=NULL;
217 0 : enable_acl=get_int(confs[OPT_ACL]);
218 0 : enable_xattr=get_int(confs[OPT_XATTR]);
219 :
220 : // First, tell the server about everything that needs to be backed up.
221 :
222 0 : logp("Phase 1 begin (file system scan)\n");
223 :
224 : // Encryption not yet supported in protocol2.
225 0 : if(get_protocol(confs)==PROTO_1
226 0 : && get_string(confs[OPT_ENCRYPTION_PASSWORD]))
227 : {
228 0 : filesymbol=CMD_ENC_FILE;
229 0 : metasymbol=CMD_ENC_METADATA;
230 : #ifdef HAVE_WIN32
231 : metasymbol=CMD_ENC_VSS;
232 : vss_trail_symbol=CMD_ENC_VSS_T;
233 : #endif
234 : }
235 : #ifdef HAVE_WIN32
236 : dirsymbol=filesymbol;
237 : if(get_protocol(confs)==PROTO_1
238 : && get_int(confs[OPT_STRIP_VSS]))
239 : dirsymbol=CMD_DIRECTORY;
240 : #endif
241 :
242 0 : if(!(ff=find_files_init(burp_send_file))) goto end;
243 0 : for(l=get_strlist(confs[OPT_STARTDIR]); l; l=l->next) if(l->flag)
244 0 : if(find_files_begin(asfd, ff, confs, l->path)) goto end;
245 : ret=0;
246 : end:
247 0 : cntr_print_end_phase1(get_cntr(confs));
248 0 : if(ret) logp("Error in phase 1\n");
249 0 : logp("Phase 1 end (file system scan)\n");
250 0 : find_files_free(&ff);
251 :
252 0 : return ret;
253 : }
|