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