1 /*
2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 1991-1999 University of Maryland at College Park
4 * Copyright (c) 2007-2013 Zmanda, Inc. All Rights Reserved.
5 * All Rights Reserved.
6 *
7 * Permission to use, copy, modify, distribute, and sell this software and its
8 * documentation for any purpose is hereby granted without fee, provided that
9 * the above copyright notice appear in all copies and that both that
10 * copyright notice and this permission notice appear in supporting
11 * documentation, and that the name of U.M. not be used in advertising or
12 * publicity pertaining to distribution of the software without specific,
13 * written prior permission. U.M. makes no representations about the
14 * suitability of this software for any purpose. It is provided "as is"
15 * without express or implied warranty.
16 *
17 * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
19 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
21 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
22 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 *
24 * Authors: the Amanda Development Team. Its members are listed in a
25 * file named AUTHORS, in the root directory of this distribution.
26 */
27 /*
28 * $Id: sendbackup-dump.c,v 1.90 2006/07/25 18:10:07 martinea Exp $
29 *
30 * send backup data using BSD dump
31 */
32
33 #include "amanda.h"
34 #include "sendbackup.h"
35 #include "getfsent.h"
36 #include "clock.h"
37
38 #define LEAF_AND_DIRS "sed -e \'\ns/^leaf[ \t]*[0-9]*[ \t]*\\.//\nt\n/^dir[ \t]/ {\ns/^dir[ \t]*[0-9]*[ \t]*\\.//\ns%$%/%\nt\n}\nd\n\'"
39
40 static amregex_t re_table[] = {
41 /* the various encodings of dump size */
42 /* this should also match BSDI pre-3.0's buggy dump program, that
43 produced doubled DUMP: DUMP: messages */
44 AM_SIZE_RE("DUMP: [0-9][0-9]* tape blocks", 1024, 1),
45 AM_SIZE_RE("dump: Actual: [0-9][0-9]* tape blocks", 1024, 1),
46 AM_SIZE_RE("backup: There are [0-9][0-9]* tape blocks on [0-9][0-9]* tapes",
47 1024, 1),
48 AM_SIZE_RE("backup: [0-9][0-9]* tape blocks on [0-9][0-9]* tape\\(s\\)",
49 1024, 1),
50 AM_SIZE_RE("backup: [0-9][0-9]* 1k blocks on [0-9][0-9]* volume\\(s\\)",
51 1024, 1),
52 AM_SIZE_RE("DUMP: [0-9][0-9]* blocks \\([0-9][0-9]*KB\\) on [0-9][0-9]* volume",
53 512, 1),
54 AM_SIZE_RE("DUMP: [0-9][0-9]* blocks \\([0-9][0-9]*\\.[0-9][0-9]*MB\\) on [0-9][0-9]* volume",
55 512, 1),
56 AM_SIZE_RE("DUMP: [0-9][0-9]* blocks \\([0-9][0-9]*KB\\)",
57 1024, 2),
58 AM_SIZE_RE("DUMP: [0-9][0-9]* blocks \\([0-9][0-9]*\\.[0-9][0-9]*MB\\)",
59 1048576, 2),
60 AM_SIZE_RE("DUMP: [0-9][0-9]* blocks", 512, 1),
61 AM_SIZE_RE("DUMP: [0-9][0-9]* bytes were dumped", 1, 1),
62 /* OSF's vdump */
63 AM_SIZE_RE("vdump: Dumped [0-9][0-9]* of [0-9][0-9]* bytes", 1, 1),
64 /* DU 4.0a dump */
65 AM_SIZE_RE("dump: Actual: [0-9][0-9]* blocks output to pipe", 1024, 1),
66 /* DU 4.0 vdump */
67 AM_SIZE_RE("dump: Dumped [0-9][0-9]* of [0-9][0-9]* bytes", 1, 1),
68 /* HPUX dump */
69 AM_SIZE_RE("DUMP: [0-9][0-9]* KB actual output", 1024, 1),
70 /* HPUX 10.20 and above vxdump */
71 AM_SIZE_RE("vxdump: [0-9][0-9]* tape blocks", 1024, 1),
72 /* UnixWare vxdump */
73 AM_SIZE_RE("vxdump: [0-9][0-9]* blocks", 1024, 1),
74 /* SINIX vxdump */
75 AM_SIZE_RE(" VXDUMP: [0-9][0-9]* blocks", 512, 1),
76 /* SINIX ufsdump */
77 AM_SIZE_RE(" UFSDUMP: [0-9][0-9]* blocks", 512, 1),
78 /* Irix 6.2 xfs dump */
79 AM_SIZE_RE("xfsdump: media file size [0-9][0-9]* bytes", 1, 1),
80 /* NetApp dump */
81 AM_SIZE_RE("DUMP: [0-9][0-9]* KB", 1024, 1),
82
83 /* strange dump lines */
84 AM_STRANGE_RE("should not happen"),
85 AM_STRANGE_RE("Cannot open"),
86 AM_STRANGE_RE("[Ee]rror"),
87 AM_STRANGE_RE("[Ff]ail"),
88 /* XXX add more ERROR entries here by scanning dump sources? */
89
90 /* any blank or non-strange DUMP: lines are marked as normal */
91 AM_NORMAL_RE("^ *DUMP:"),
92 AM_NORMAL_RE("^dump:"), /* OSF/1 */
93 AM_NORMAL_RE("^vdump:"), /* OSF/1 */
94 AM_NORMAL_RE("^ *vxdump:"), /* HPUX10 */
95 AM_NORMAL_RE("^ *vxfs *vxdump:"), /* Solaris */
96 AM_NORMAL_RE("^Dumping .* to stdout"), /* Sol vxdump */
97 AM_NORMAL_RE("^xfsdump:"), /* IRIX xfs */
98 AM_NORMAL_RE("^ *VXDUMP:"), /* Sinix */
99 AM_NORMAL_RE("^ *UFSDUMP:"), /* Sinix */
100
101 #ifdef VDUMP /* this is for OSF/1 3.2's vdump for advfs */
102 AM_NORMAL_RE("^The -s option is ignored"), /* OSF/1 */
103 AM_NORMAL_RE("^path"), /* OSF/1 */
104 AM_NORMAL_RE("^dev/fset"), /* OSF/1 */
105 AM_NORMAL_RE("^type"), /* OSF/1 */
106 AM_NORMAL_RE("^advfs id"), /* OSF/1 */
107 AM_NORMAL_RE("^[A-Z][a-z][a-z] [A-Z][a-z][a-z] .[0-9] [0-9]"), /* OSF/1 */
108 #endif
109
110 AM_NORMAL_RE("^backup:"), /* AIX */
111 AM_NORMAL_RE("^ Use the umount command to unmount the filesystem"),
112
113 AM_NORMAL_RE("^[ \t]*$"),
114
115 /* catch-all; DMP_STRANGE is returned for all other lines */
116 AM_STRANGE_RE(NULL)
117 };
118
119 static void start_backup(dle_t *dle, char *host,
120 int dataf, int mesgf, int indexf);
121 static void end_backup(dle_t *dle, int status);
122
123 /*
124 * doing similar to $ dump | compression | encryption
125 */
126
127 static void
start_backup(dle_t * dle,char * host,int dataf,int mesgf,int indexf)128 start_backup(
129 dle_t *dle,
130 char *host,
131 int dataf,
132 int mesgf,
133 int indexf)
134 {
135 int dumpin, dumpout, compout;
136 char *dumpkeys = NULL;
137 char *device = NULL;
138 char *fstype = NULL;
139 char *cmd = NULL;
140 char *cmdX = NULL;
141 char *indexcmd = NULL;
142 char level_str[NUM_STR_SIZE];
143 char *compopt = NULL;
144 char *encryptopt = skip_argument;
145 char *qdisk;
146 char *config;
147 am_level_t *alevel = (am_level_t *)dle->levellist->data;
148 int level = alevel->level;
149
150 g_snprintf(level_str, SIZEOF(level_str), "%d", level);
151
152 qdisk = quote_string(dle->disk);
153 dbprintf(_("start: %s:%s lev %d\n"), host, qdisk, level);
154
155 g_fprintf(stderr, _("%s: start [%s:%s level %d]\n"),
156 get_pname(), host, qdisk, level);
157 amfree(qdisk);
158
159 /* apply client-side encryption here */
160 if (dle->encrypt == ENCRYPT_CUST ) {
161 encpid = pipespawn(dle->clnt_encrypt, STDIN_PIPE, 0,
162 &compout, &dataf, &mesgf,
163 dle->clnt_encrypt, encryptopt, NULL);
164 dbprintf(_("gnutar: pid %ld: %s\n"), (long)encpid, dle->clnt_encrypt);
165 } else {
166 compout = dataf;
167 encpid = -1;
168 }
169 /* now do the client-side compression */
170
171
172 if(dle->compress == COMP_FAST || dle->compress == COMP_BEST) {
173 compopt = skip_argument;
174
175 #if defined(COMPRESS_BEST_OPT) && defined(COMPRESS_FAST_OPT)
176 if(dle->compress == COMP_BEST) {
177 compopt = COMPRESS_BEST_OPT;
178 } else {
179 compopt = COMPRESS_FAST_OPT;
180 }
181 #endif
182 comppid = pipespawn(COMPRESS_PATH, STDIN_PIPE, 0,
183 &dumpout, &compout, &mesgf,
184 COMPRESS_PATH, compopt, NULL);
185 dbprintf(_("dump: pid %ld: %s"), (long)comppid, COMPRESS_PATH);
186 if(compopt != skip_argument) {
187 dbprintf(" %s", compopt);
188 }
189 dbprintf("\n");
190 } else if (dle->compress == COMP_CUST) {
191 compopt = skip_argument;
192 comppid = pipespawn(dle->compprog, STDIN_PIPE, 0,
193 &dumpout, &compout, &mesgf,
194 dle->compprog, compopt, NULL);
195 dbprintf(_("gnutar-cust: pid %ld: %s"),
196 (long)comppid, dle->compprog);
197 if(compopt != skip_argument) {
198 dbprintf(" %s", compopt);
199 }
200 dbprintf("\n");
201 } else {
202 dumpout = compout;
203 comppid = -1;
204 }
205
206 /* invoke dump */
207 device = amname_to_devname(dle->device);
208 fstype = amname_to_fstype(dle->device);
209
210 dbprintf(_("dumping device '%s' with '%s'\n"), device, fstype);
211
212 #if defined(USE_RUNDUMP) || !defined(DUMP)
213 cmd = vstralloc(amlibexecdir, "/", "rundump", NULL);
214 cmdX = cmd;
215 if (g_options->config)
216 config = g_options->config;
217 else
218 config = "NOCONFIG";
219 #else
220 cmd = stralloc(DUMP);
221 cmdX = skip_argument;
222 config = skip_argument;
223 #endif
224
225 #ifndef AIX_BACKUP /* { */
226 /* normal dump */
227 #ifdef XFSDUMP /* { */
228 #ifdef DUMP /* { */
229 if (strcmp(amname_to_fstype(dle->device), "xfs") == 0)
230 #else /* } { */
231 if (1)
232 #endif /* } */
233 {
234 char *progname = cmd = newvstralloc(cmd, amlibexecdir, "/", "rundump",
235 NULL);
236 cmdX = cmd;
237 if (g_options->config)
238 config = g_options->config;
239 else
240 config = "NOCONFIG";
241
242 program->backup_name = XFSDUMP;
243 program->restore_name = XFSRESTORE;
244
245 indexcmd = vstralloc(XFSRESTORE,
246 " -t",
247 " -v", " silent",
248 " -",
249 " 2>/dev/null",
250 " | sed",
251 " -e", " \'s/^/\\//\'",
252 NULL);
253 info_tapeheader(dle);
254
255 start_index(dle->create_index, dumpout, mesgf, indexf, indexcmd);
256
257 dumpkeys = stralloc(level_str);
258 dumppid = pipespawn(progname, STDIN_PIPE, 0,
259 &dumpin, &dumpout, &mesgf,
260 cmdX, config,
261 "xfsdump",
262 !dle->record ? "-J" : skip_argument,
263 "-F",
264 "-l", dumpkeys,
265 "-",
266 device,
267 NULL);
268 }
269 else
270 #endif /* } */
271 #ifdef VXDUMP /* { */
272 #ifdef DUMP
273 if (strcmp(amname_to_fstype(dle->device), "vxfs") == 0)
274 #else
275 if (1)
276 #endif
277 {
278 #ifdef USE_RUNDUMP
279 char *progname = cmd = newvstralloc(cmd, amlibexecdir, "/", "rundump",
280 NULL);
281 cmdX = cmd;
282 if (g_options->config)
283 config = g_options->config;
284 else
285 config = "NOCONFIG";
286 #else
287 char *progname = cmd = newvstralloc(cmd, VXDUMP, NULL);
288 cmdX = skip_argument;
289 config = skip_argument;
290 #endif
291 program->backup_name = VXDUMP;
292 program->restore_name = VXRESTORE;
293
294 dumpkeys = vstralloc(level_str,
295 !dle->record ? "" : "u",
296 "s",
297 "f",
298 NULL);
299
300 indexcmd = vstralloc(VXRESTORE,
301 " -tvf", " -",
302 " 2>/dev/null",
303 " | ",
304 LEAF_AND_DIRS,
305 NULL);
306 info_tapeheader(dle);
307
308 start_index(dle->create_index, dumpout, mesgf, indexf, indexcmd);
309
310 dumppid = pipespawn(progname, STDIN_PIPE, 0,
311 &dumpin, &dumpout, &mesgf,
312 cmdX, config,
313 "vxdump",
314 dumpkeys,
315 "1048576",
316 "-",
317 device,
318 NULL);
319 }
320 else
321 #endif /* } */
322
323 #ifdef VDUMP /* { */
324 #ifdef DUMP
325 if (strcmp(amname_to_fstype(dle->device), "advfs") == 0)
326 #else
327 if (1)
328 #endif
329 {
330 cmd = newvstralloc(cmd, amlibexecdir, "/", "rundump", NULL);
331 cmdX = cmd;
332 if (g_options->config)
333 config = g_options->config;
334 else
335 config = "NOCONFIG";
336 device = newstralloc(device, amname_to_dirname(dle->device));
337 program->backup_name = VDUMP;
338 program->restore_name = VRESTORE;
339
340 dumpkeys = vstralloc(level_str,
341 !dle->record ? "" : "u",
342 "b",
343 "f",
344 NULL);
345
346 indexcmd = vstralloc(VRESTORE,
347 " -tvf", " -",
348 " 2>/dev/null",
349 " | ",
350 "sed -e \'\n/^\\./ {\ns/^\\.//\ns/, [0-9]*$//\ns/^\\.//\ns/ @-> .*$//\nt\n}\nd\n\'",
351 NULL);
352 info_tapeheader(dle);
353
354 start_index(dle->create_index, dumpout, mesgf, indexf, indexcmd);
355
356 dumppid = pipespawn(cmd, STDIN_PIPE, 0,
357 &dumpin, &dumpout, &mesgf,
358 cmdX, config,
359 "vdump",
360 dumpkeys,
361 "60",
362 "-",
363 device,
364 NULL);
365 }
366 else
367 #endif /* } */
368
369 {
370 #ifndef RESTORE
371 #define RESTORE "restore"
372 #endif
373
374 #ifdef HAVE_HONOR_NODUMP
375 # define PARAM_HONOR_NODUMP "h"
376 #else
377 # define PARAM_HONOR_NODUMP ""
378 #endif
379
380 #ifdef __FreeBSD__
381 # if defined(__FreeBSD_version) && (__FreeBSD_version >= 500043) && !defined(FreeBSD_NO_SNAPSHOT_DUMP)
382 # define FREEBSD_EXTRA_KEYS "bL"
383 # else
384 # define FREEBSD_EXTRA_KEYS "b"
385 # endif
386 #else
387 # define FREEBSD_EXTRA_KEYS ""
388 #endif
389
390 dumpkeys = vstralloc(level_str,
391 !dle->record ? "" : "u",
392 FREEBSD_EXTRA_KEYS,
393 "s",
394 PARAM_HONOR_NODUMP,
395 "f",
396 NULL);
397
398 indexcmd = vstralloc(RESTORE,
399 " -tvf", " -",
400 " 2>&1",
401 /* not to /dev/null because of DU's dump */
402 " | ",
403 LEAF_AND_DIRS,
404 NULL);
405 info_tapeheader(dle);
406
407 start_index(dle->create_index, dumpout, mesgf, indexf, indexcmd);
408
409 dumppid = pipespawn(cmd, STDIN_PIPE, 0,
410 &dumpin, &dumpout, &mesgf,
411 cmdX, config,
412 "dump",
413 dumpkeys,
414 #ifdef __FreeBSD__
415 "64",
416 #endif
417 "1048576",
418 #ifdef HAVE_HONOR_NODUMP
419 "0",
420 #endif
421 "-",
422 device,
423 NULL);
424 }
425 #else /* } { */
426 /* AIX backup program */
427 dumpkeys = vstralloc("-",
428 level_str,
429 !dle->record ? "" : "u",
430 "f",
431 NULL);
432
433 indexcmd = vstralloc(RESTORE,
434 " -B",
435 " -tvf", " -",
436 " 2>/dev/null",
437 " | ",
438 LEAF_AND_DIRS,
439 NULL);
440 info_tapeheader(dle);
441
442 start_index(dle->create_index, dumpout, mesgf, indexf, indexcmd);
443
444 dumppid = pipespawn(cmd, STDIN_PIPE, 0,
445 &dumpin, &dumpout, &mesgf,
446 cmdX, config,
447 "backup",
448 dumpkeys,
449 "-",
450 device,
451 NULL);
452 #endif /* } */
453
454 amfree(dumpkeys);
455 amfree(fstype);
456 amfree(device);
457 amfree(cmd);
458 amfree(indexcmd);
459
460 /* close the write ends of the pipes */
461
462 aclose(dumpin);
463 aclose(dumpout);
464 aclose(compout);
465 aclose(dataf);
466 aclose(mesgf);
467 if (dle->create_index)
468 aclose(indexf);
469 }
470
471 static void
end_backup(dle_t * dle,int status)472 end_backup(
473 dle_t *dle,
474 int status)
475 {
476 (void)dle;
477 (void)status; /* Quiet unused parameter warning */
478
479 /* don't need to do anything for dump */
480 }
481
482 backup_program_t dump_program = {
483 "DUMP",
484 #ifdef DUMP
485 DUMP
486 #else
487 "dump"
488 #endif
489 ,
490 RESTORE
491 ,
492 re_table, start_backup, end_backup
493 };
494