b69baa6abe4ac05ae1678fa2cc5483946a0a1aee
[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 #include "version.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
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
148     g_snprintf(level_str, SIZEOF(level_str), "%d", GPOINTER_TO_INT(dle->level->data));
149
150     qdisk = quote_string(dle->disk);
151     dbprintf(_("start: %s:%s lev %d\n"), host, qdisk, GPOINTER_TO_INT(dle->level->data));
152
153     g_fprintf(stderr, _("%s: start [%s:%s level %d]\n"),
154             get_pname(), host, qdisk, GPOINTER_TO_INT(dle->level->data));
155     amfree(qdisk);
156
157     /*  apply client-side encryption here */
158     if (dle->encrypt == ENCRYPT_CUST ) {
159         encpid = pipespawn(dle->clnt_encrypt, STDIN_PIPE, 0,
160                            &compout, &dataf, &mesgf,
161                            dle->clnt_encrypt, encryptopt, NULL);
162         dbprintf(_("gnutar: pid %ld: %s\n"), (long)encpid, dle->clnt_encrypt);
163     } else {
164         compout = dataf;
165         encpid = -1;
166     }
167     /*  now do the client-side compression */
168
169
170     if(dle->compress == COMP_FAST || dle->compress == COMP_BEST) {
171         compopt = skip_argument;
172
173 #if defined(COMPRESS_BEST_OPT) && defined(COMPRESS_FAST_OPT)
174         if(dle->compress == COMP_BEST) {
175             compopt = COMPRESS_BEST_OPT;
176         } else {
177             compopt = COMPRESS_FAST_OPT;
178         }
179 #endif
180         comppid = pipespawn(COMPRESS_PATH, STDIN_PIPE, 0,
181                             &dumpout, &compout, &mesgf,
182                             COMPRESS_PATH, compopt, NULL);
183         dbprintf(_("dump: pid %ld: %s"), (long)comppid, COMPRESS_PATH);
184         if(compopt != skip_argument) {
185             dbprintf(" %s", compopt);
186         }
187         dbprintf("\n");
188      } else if (dle->compress == COMP_CUST) {
189         compopt = skip_argument;
190         comppid = pipespawn(dle->compprog, STDIN_PIPE, 0,
191                             &dumpout, &compout, &mesgf,
192                             dle->compprog, compopt, NULL);
193         dbprintf(_("gnutar-cust: pid %ld: %s"),
194                 (long)comppid, dle->compprog);
195         if(compopt != skip_argument) {
196             dbprintf(" %s", compopt);
197         }
198         dbprintf("\n");
199     } else {
200         dumpout = compout;
201         comppid = -1;
202     }
203
204     /* invoke dump */
205     device = amname_to_devname(dle->device);
206     fstype = amname_to_fstype(dle->device);
207
208     dbprintf(_("dumping device '%s' with '%s'\n"), device, fstype);
209
210 #if defined(USE_RUNDUMP) || !defined(DUMP)
211     cmd = vstralloc(amlibexecdir, "/", "rundump", versionsuffix(), NULL);
212     cmdX = cmd;
213     if (g_options->config)
214         config = g_options->config;
215     else
216         config = "NOCONFIG";
217 #else
218     cmd = stralloc(DUMP);
219     cmdX = skip_argument;
220     config = skip_argument;
221 #endif
222
223 #ifndef AIX_BACKUP                                      /* { */
224     /* normal dump */
225 #ifdef XFSDUMP                                          /* { */
226 #ifdef DUMP                                             /* { */
227     if (strcmp(amname_to_fstype(dle->device), "xfs") == 0)
228 #else                                                   /* } { */
229     if (1)
230 #endif                                                  /* } */
231     {
232         char *progname = cmd = newvstralloc(cmd, amlibexecdir, "/", "rundump",
233                                             versionsuffix(), NULL);
234         cmdX = cmd;
235         if (g_options->config)
236             config = g_options->config;
237         else
238             config = "NOCONFIG";
239
240         program->backup_name  = XFSDUMP;
241         program->restore_name = XFSRESTORE;
242
243         indexcmd = vstralloc(XFSRESTORE,
244                              " -t",
245                              " -v", " silent",
246                              " -",
247                              " 2>/dev/null",
248                              " | sed",
249                              " -e", " \'s/^/\\//\'",
250                              NULL);
251         info_tapeheader(dle);
252
253         start_index(dle->create_index, dumpout, mesgf, indexf, indexcmd);
254
255         dumpkeys = stralloc(level_str);
256         dumppid = pipespawn(progname, STDIN_PIPE, 0,
257                             &dumpin, &dumpout, &mesgf,
258                             cmdX, config,
259                             "xfsdump",
260                             !dle->record ? "-J" : skip_argument,
261                             "-F",
262                             "-l", dumpkeys,
263                             "-",
264                             device,
265                             NULL);
266     }
267     else
268 #endif                                                  /* } */
269 #ifdef VXDUMP                                           /* { */
270 #ifdef DUMP
271     if (strcmp(amname_to_fstype(dle->device), "vxfs") == 0)
272 #else
273     if (1)
274 #endif
275     {
276 #ifdef USE_RUNDUMP
277         char *progname = cmd = newvstralloc(cmd, amlibexecdir, "/", "rundump",
278                                             versionsuffix(), NULL);
279         cmdX = cmd;
280         if (g_options->config)
281             config = g_options->config;
282         else
283             config = "NOCONFIG";
284 #else
285         char *progname = cmd = newvstralloc(cmd, VXDUMP, NULL);
286         cmdX = skip_argument;
287         config = skip_argument;
288 #endif
289         program->backup_name  = VXDUMP;
290         program->restore_name = VXRESTORE;
291
292         dumpkeys = vstralloc(level_str,
293                              !dle->record ? "" : "u",
294                              "s",
295                              "f",
296                              NULL);
297
298         indexcmd = vstralloc(VXRESTORE,
299                              " -tvf", " -",
300                              " 2>/dev/null",
301                              " | ",
302                              LEAF_AND_DIRS,
303                              NULL);
304         info_tapeheader(dle);
305
306         start_index(dle->create_index, dumpout, mesgf, indexf, indexcmd);
307
308         dumppid = pipespawn(progname, STDIN_PIPE, 0,
309                             &dumpin, &dumpout, &mesgf, 
310                             cmdX, config,
311                             "vxdump",
312                             dumpkeys,
313                             "1048576",
314                             "-",
315                             device,
316                             NULL);
317     }
318     else
319 #endif                                                  /* } */
320
321 #ifdef VDUMP                                            /* { */
322 #ifdef DUMP
323     if (strcmp(amname_to_fstype(dle->device), "advfs") == 0)
324 #else
325     if (1)
326 #endif
327     {
328         cmd = newvstralloc(cmd, amlibexecdir, "/", "rundump",
329                                             versionsuffix(), 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 };