Imported Upstream version 2.5.2p1
[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(char *host, char *disk, char *amdevice, int level,
120                 char *dumpdate, int dataf, int mesgf, int indexf);
121 static void end_backup(int status);
122
123 /*
124  *  doing similar to $ dump | compression | encryption
125  */
126
127 static void
128 start_backup(
129     char *      host,
130     char *      disk,
131     char *      amdevice,
132     int         level,
133     char *      dumpdate,
134     int         dataf,
135     int         mesgf,
136     int         indexf)
137 {
138     int dumpin, dumpout, compout;
139     char *dumpkeys = NULL;
140     char *device = NULL;
141     char *fstype = NULL;
142     char *cmd = NULL;
143     char *cmdX = NULL;
144     char *indexcmd = NULL;
145     char level_str[NUM_STR_SIZE];
146     char *compopt  = NULL;
147     char *encryptopt = skip_argument;
148     char *qdisk;
149     char *config;
150
151     (void)dumpdate;     /* Quiet unused parameter warning */
152
153     snprintf(level_str, SIZEOF(level_str), "%d", level);
154
155     qdisk = quote_string(disk);
156     dbprintf(("%s: start: %s:%s lev %d\n",
157               get_pname(), host, qdisk, level));
158
159     fprintf(stderr, "%s: start [%s:%s level %d]\n",
160             get_pname(), host, qdisk, level);
161     amfree(qdisk);
162
163     /*  apply client-side encryption here */
164     if ( options->encrypt == ENCRYPT_CUST ) {
165         encpid = pipespawn(options->clnt_encrypt, STDIN_PIPE,
166                        &compout, &dataf, &mesgf,
167                        options->clnt_encrypt, encryptopt, NULL);
168         dbprintf(("%s: pid %ld: %s\n",
169                  debug_prefix_time("-gnutar"), (long)encpid, options->clnt_encrypt));
170     } else {
171         compout = dataf;
172         encpid = -1;
173     }
174     /*  now do the client-side compression */
175
176
177     if(options->compress == COMP_FAST || options->compress == COMP_BEST) {
178         compopt = skip_argument;
179
180 #if defined(COMPRESS_BEST_OPT) && defined(COMPRESS_FAST_OPT)
181         if(options->compress == COMP_BEST) {
182             compopt = COMPRESS_BEST_OPT;
183         } else {
184             compopt = COMPRESS_FAST_OPT;
185         }
186 #endif
187         comppid = pipespawn(COMPRESS_PATH, STDIN_PIPE,
188                             &dumpout, &compout, &mesgf,
189                             COMPRESS_PATH, compopt, NULL);
190         dbprintf(("%s: pid %ld: %s",
191                   debug_prefix_time("-dump"), (long)comppid, COMPRESS_PATH));
192         if(compopt != skip_argument) {
193             dbprintf((" %s", compopt));
194         }
195         dbprintf(("\n"));
196      } else if (options->compress == COMP_CUST) {
197         compopt = skip_argument;
198         comppid = pipespawn(options->clntcompprog, STDIN_PIPE,
199                             &dumpout, &compout, &mesgf,
200                             options->clntcompprog, compopt, NULL);
201         dbprintf(("%s: pid %ld: %s",
202                   debug_prefix_time("-gnutar-cust"), (long)comppid, options->clntcompprog));
203         if(compopt != skip_argument) {
204             dbprintf((" %s", compopt));
205         }
206         dbprintf(("\n"));
207     } else {
208         dumpout = compout;
209         comppid = -1;
210     }
211
212     /* invoke dump */
213     device = amname_to_devname(amdevice);
214     fstype = amname_to_fstype(amdevice);
215
216     dbprintf(("%s: dumping device '%s' with '%s'\n",
217               debug_prefix_time(NULL), device, fstype));
218
219 #if defined(USE_RUNDUMP) || !defined(DUMP)
220     cmd = vstralloc(libexecdir, "/", "rundump", versionsuffix(), NULL);
221     cmdX = cmd;
222     if (g_options->config)
223         config = g_options->config;
224     else
225         config = "NOCONFIG";
226 #else
227     cmd = stralloc(DUMP);
228     cmdX = skip_argument;
229     config = skip_argument;
230 #endif
231
232 #ifndef AIX_BACKUP                                      /* { */
233     /* normal dump */
234 #ifdef XFSDUMP                                          /* { */
235 #ifdef DUMP                                             /* { */
236     if (strcmp(amname_to_fstype(amdevice), "xfs") == 0)
237 #else                                                   /* } { */
238     if (1)
239 #endif                                                  /* } */
240     {
241         char *progname = cmd = newvstralloc(cmd, libexecdir, "/", "rundump",
242                                             versionsuffix(), NULL);
243         cmdX = cmd;
244         if (g_options->config)
245             config = g_options->config;
246         else
247             config = "NOCONFIG";
248
249         program->backup_name  = XFSDUMP;
250         program->restore_name = XFSRESTORE;
251
252         indexcmd = vstralloc(XFSRESTORE,
253                              " -t",
254                              " -v", " silent",
255                              " -",
256                              " 2>/dev/null",
257                              " | sed",
258                              " -e", " \'s/^/\\//\'",
259                              NULL);
260         info_tapeheader();
261
262         start_index(options->createindex, dumpout, mesgf, indexf, indexcmd);
263
264         dumpkeys = stralloc(level_str);
265         dumppid = pipespawn(progname, STDIN_PIPE,
266                             &dumpin, &dumpout, &mesgf,
267                             cmdX, config,
268                             "xfsdump",
269                             options->no_record ? "-J" : skip_argument,
270                             "-F",
271                             "-l", dumpkeys,
272                             "-",
273                             device,
274                             NULL);
275     }
276     else
277 #endif                                                  /* } */
278 #ifdef VXDUMP                                           /* { */
279 #ifdef DUMP
280     if (strcmp(amname_to_fstype(amdevice), "vxfs") == 0)
281 #else
282     if (1)
283 #endif
284     {
285 #ifdef USE_RUNDUMP
286         char *progname = cmd = newvstralloc(cmd, libexecdir, "/", "rundump",
287                                             versionsuffix(), NULL);
288         cmdX = cmd;
289         if (g_options->config)
290             config = g_options->config;
291         else
292             config = "NOCONFIG";
293 #else
294         char *progname = cmd = newvstralloc(cmd, VXDUMP, NULL);
295         cmdX = skip_argument;
296         config = skip_argument;
297 #endif
298         program->backup_name  = VXDUMP;
299         program->restore_name = VXRESTORE;
300
301         dumpkeys = vstralloc(level_str,
302                              options->no_record ? "" : "u",
303                              "s",
304                              "f",
305                              NULL);
306
307         indexcmd = vstralloc(VXRESTORE,
308                              " -tvf", " -",
309                              " 2>/dev/null",
310                              " | ",
311                              LEAF_AND_DIRS,
312                              NULL);
313         info_tapeheader();
314
315         start_index(options->createindex, dumpout, mesgf, indexf, indexcmd);
316
317         dumppid = pipespawn(progname, STDIN_PIPE,
318                             &dumpin, &dumpout, &mesgf, 
319                             cmdX, config,
320                             "vxdump",
321                             dumpkeys,
322                             "1048576",
323                             "-",
324                             device,
325                             NULL);
326     }
327     else
328 #endif                                                  /* } */
329
330 #ifdef VDUMP                                            /* { */
331 #ifdef DUMP
332     if (strcmp(amname_to_fstype(amdevice), "advfs") == 0)
333 #else
334     if (1)
335 #endif
336     {
337         char *progname = cmd = newvstralloc(cmd, libexecdir, "/", "rundump",
338                                             versionsuffix(), NULL);
339         cmdX = cmd;
340         if (g_options->config)
341             config = g_options->config;
342         else
343             config = "NOCONFIG";
344         device = newstralloc(device, amname_to_dirname(amdevice));
345         program->backup_name  = VDUMP;
346         program->restore_name = VRESTORE;
347
348         dumpkeys = vstralloc(level_str,
349                              options->no_record ? "" : "u",
350                              "b",
351                              "f",
352                              NULL);
353
354         indexcmd = vstralloc(VRESTORE,
355                              " -tvf", " -",
356                              " 2>/dev/null",
357                              " | ",
358                              "sed -e \'\n/^\\./ {\ns/^\\.//\ns/, [0-9]*$//\ns/^\\.//\ns/ @-> .*$//\nt\n}\nd\n\'",
359                              NULL);
360         info_tapeheader();
361
362         start_index(options->createindex, dumpout, mesgf, indexf, indexcmd);
363
364         dumppid = pipespawn(cmd, STDIN_PIPE,
365                             &dumpin, &dumpout, &mesgf, 
366                             cmdX, config,
367                             "vdump",
368                             dumpkeys,
369                             "60",
370                             "-",
371                             device,
372                             NULL);
373     }
374     else
375 #endif                                                  /* } */
376
377     {
378 #ifndef RESTORE
379 #define RESTORE "restore"
380 #endif
381
382 #ifdef HAVE_HONOR_NODUMP
383 #  define PARAM_HONOR_NODUMP "h"
384 #else
385 #  define PARAM_HONOR_NODUMP ""
386 #endif
387         dumpkeys = vstralloc(level_str,
388                              options->no_record ? "" : "u",
389                              "s",
390                              PARAM_HONOR_NODUMP,
391                              "f",
392                              NULL);
393
394         indexcmd = vstralloc(RESTORE,
395                              " -tvf", " -",
396                              " 2>&1",
397                              /* not to /dev/null because of DU's dump */
398                              " | ",
399                              LEAF_AND_DIRS,
400                              NULL);
401         info_tapeheader();
402
403         start_index(options->createindex, dumpout, mesgf, indexf, indexcmd);
404
405         dumppid = pipespawn(cmd, STDIN_PIPE,
406                             &dumpin, &dumpout, &mesgf, 
407                             cmdX, config,
408                             "dump",
409                             dumpkeys,
410                             "1048576",
411 #ifdef HAVE_HONOR_NODUMP
412                             "0",
413 #endif
414                             "-",
415                             device,
416                             NULL);
417     }
418 #else                                                   /* } { */
419     /* AIX backup program */
420     dumpkeys = vstralloc("-",
421                          level_str,
422                          options->no_record ? "" : "u",
423                          "f",
424                          NULL);
425
426     indexcmd = vstralloc(RESTORE,
427                          " -B",
428                          " -tvf", " -",
429                          " 2>/dev/null",
430                          " | ",
431                          LEAF_AND_DIRS,
432                          NULL);
433     info_tapeheader();
434
435     start_index(options->createindex, dumpout, mesgf, indexf, indexcmd);
436
437     dumppid = pipespawn(cmd, STDIN_PIPE,
438                         &dumpin, &dumpout, &mesgf, 
439                         cmdX, config,
440                         "backup",
441                         dumpkeys,
442                         "-",
443                         device,
444                         NULL);
445 #endif                                                  /* } */
446
447     amfree(dumpkeys);
448     amfree(fstype);
449     amfree(device);
450     amfree(cmd);
451     amfree(indexcmd);
452
453     /* close the write ends of the pipes */
454
455     aclose(dumpin);
456     aclose(dumpout);
457     aclose(compout);
458     aclose(dataf);
459     aclose(mesgf);
460     if (options->createindex)
461         aclose(indexf);
462 }
463
464 static void
465 end_backup(
466     int         status)
467 {
468     (void)status;       /* Quiet unused parameter warning */
469
470     /* don't need to do anything for dump */
471 }
472
473 backup_program_t dump_program = {
474   "DUMP",
475 #ifdef DUMP
476   DUMP
477 #else
478   "dump"
479 #endif
480   ,
481   RESTORE
482   ,
483   re_table, start_backup, end_backup
484 };