0e10dc702224320282e8304fee284c136f47fbcb
[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.2.2 2006/11/24 18:10:38 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),
45   AM_SIZE_RE("dump: Actual: [0-9][0-9]* tape blocks", 1024),
46   AM_SIZE_RE("backup: There are [0-9][0-9]* tape blocks on [0-9][0-9]* tapes",
47              1024),
48   AM_SIZE_RE("backup: [0-9][0-9]* tape blocks on [0-9][0-9]* tape\\(s\\)",
49              1024),
50   AM_SIZE_RE("backup: [0-9][0-9]* 1k blocks on [0-9][0-9]* volume\\(s\\)",
51              1024),
52   AM_SIZE_RE("DUMP: [0-9][0-9]* blocks \\([0-9][0-9]*KB\\) on [0-9][0-9]* volume",
53              512),
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),
56   AM_SIZE_RE("DUMP: [0-9][0-9]* blocks", 512),
57   AM_SIZE_RE("DUMP: [0-9][0-9]* bytes were dumped", 1),
58   /* OSF's vdump */
59   AM_SIZE_RE("vdump: Dumped  [0-9][0-9]* of [0-9][0-9]* bytes", 1),
60   /* DU 4.0a dump */
61   AM_SIZE_RE("dump: Actual: [0-9][0-9]* blocks output to pipe", 1024),
62   /* DU 4.0 vdump */
63   AM_SIZE_RE("dump: Dumped  [0-9][0-9]* of [0-9][0-9]* bytes", 1),
64   /* HPUX dump */
65   AM_SIZE_RE("DUMP: [0-9][0-9]* KB actual output", 1024),
66   /* HPUX 10.20 and above vxdump */
67   AM_SIZE_RE("vxdump: [0-9][0-9]* tape blocks", 1024),
68   /* UnixWare vxdump */
69   AM_SIZE_RE("vxdump: [0-9][0-9]* blocks", 1024),
70   /* SINIX vxdump */
71   AM_SIZE_RE("   VXDUMP: [0-9][0-9]* blocks", 512),
72   /* SINIX ufsdump */
73   AM_SIZE_RE("   UFSDUMP: [0-9][0-9]* blocks", 512),
74   /* Irix 6.2 xfs dump */
75   AM_SIZE_RE("xfsdump: media file size [0-9][0-9]* bytes", 1),
76   /* NetApp dump */
77   AM_SIZE_RE("DUMP: [0-9][0-9]* KB", 1024),
78
79   /* strange dump lines */
80   AM_STRANGE_RE("should not happen"),
81   AM_STRANGE_RE("Cannot open"),
82   AM_STRANGE_RE("[Ee]rror"),
83   AM_STRANGE_RE("[Ff]ail"),
84   /* XXX add more ERROR entries here by scanning dump sources? */
85
86   /* any blank or non-strange DUMP: lines are marked as normal */
87   AM_NORMAL_RE("^ *DUMP:"),
88   AM_NORMAL_RE("^dump:"),                                       /* OSF/1 */
89   AM_NORMAL_RE("^vdump:"),                                      /* OSF/1 */
90   AM_NORMAL_RE("^ *vxdump:"),                                   /* HPUX10 */
91   AM_NORMAL_RE("^ *vxfs *vxdump:"),                             /* Solaris */
92   AM_NORMAL_RE("^Dumping .* to stdout"),                        /* Sol vxdump */
93   AM_NORMAL_RE("^xfsdump:"),                                    /* IRIX xfs */
94   AM_NORMAL_RE("^ *VXDUMP:"),                                   /* Sinix */
95   AM_NORMAL_RE("^ *UFSDUMP:"),                                  /* Sinix */
96
97 #ifdef VDUMP    /* this is for OSF/1 3.2's vdump for advfs */
98   AM_NORMAL_RE("^The -s option is ignored"),                    /* OSF/1 */
99   AM_NORMAL_RE("^path"),                                        /* OSF/1 */
100   AM_NORMAL_RE("^dev/fset"),                                    /* OSF/1 */
101   AM_NORMAL_RE("^type"),                                        /* OSF/1 */
102   AM_NORMAL_RE("^advfs id"),                                    /* OSF/1 */
103   AM_NORMAL_RE("^[A-Z][a-z][a-z] [A-Z][a-z][a-z] .[0-9] [0-9]"), /* OSF/1 */
104 #endif
105
106   AM_NORMAL_RE("^backup:"),                                     /* AIX */
107   AM_NORMAL_RE("^        Use the umount command to unmount the filesystem"),
108
109   AM_NORMAL_RE("^[ \t]*$"),
110
111   /* catch-all; DMP_STRANGE is returned for all other lines */
112   AM_STRANGE_RE(NULL)
113 };
114
115 static void start_backup(char *host, char *disk, char *amdevice, int level,
116                 char *dumpdate, int dataf, int mesgf, int indexf);
117 static void end_backup(int status);
118
119 /*
120  *  doing similar to $ dump | compression | encryption
121  */
122
123 static void
124 start_backup(
125     char *      host,
126     char *      disk,
127     char *      amdevice,
128     int         level,
129     char *      dumpdate,
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
147     (void)dumpdate;     /* Quiet unused parameter warning */
148
149     snprintf(level_str, SIZEOF(level_str), "%d", level);
150
151     qdisk = quote_string(disk);
152     dbprintf(("%s: start: %s:%s lev %d\n",
153               get_pname(), host, qdisk, level));
154
155     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 ( options->encrypt == ENCRYPT_CUST ) {
161         encpid = pipespawn(options->clnt_encrypt, STDIN_PIPE,
162                        &compout, &dataf, &mesgf,
163                        options->clnt_encrypt, encryptopt, NULL);
164         dbprintf(("%s: pid %ld: %s\n",
165                  debug_prefix_time("-gnutar"), (long)encpid, options->clnt_encrypt));
166     } else {
167         compout = dataf;
168         encpid = -1;
169     }
170     /*  now do the client-side compression */
171
172
173     if(options->compress == COMPR_FAST || options->compress == COMPR_BEST) {
174         compopt = skip_argument;
175
176 #if defined(COMPRESS_BEST_OPT) && defined(COMPRESS_FAST_OPT)
177         if(options->compress == COMPR_BEST) {
178             compopt = COMPRESS_BEST_OPT;
179         } else {
180             compopt = COMPRESS_FAST_OPT;
181         }
182 #endif
183         comppid = pipespawn(COMPRESS_PATH, STDIN_PIPE,
184                             &dumpout, &compout, &mesgf,
185                             COMPRESS_PATH, compopt, NULL);
186         dbprintf(("%s: pid %ld: %s",
187                   debug_prefix_time("-dump"), (long)comppid, COMPRESS_PATH));
188         if(compopt != skip_argument) {
189             dbprintf((" %s", compopt));
190         }
191         dbprintf(("\n"));
192      } else if (options->compress == COMPR_CUST) {
193         compopt = skip_argument;
194         comppid = pipespawn(options->clntcompprog, STDIN_PIPE,
195                             &dumpout, &compout, &mesgf,
196                             options->clntcompprog, compopt, NULL);
197         dbprintf(("%s: pid %ld: %s",
198                   debug_prefix_time("-gnutar-cust"), (long)comppid, options->clntcompprog));
199         if(compopt != skip_argument) {
200             dbprintf((" %s", compopt));
201         }
202         dbprintf(("\n"));
203     } else {
204         dumpout = compout;
205         comppid = -1;
206     }
207
208     /* invoke dump */
209     device = amname_to_devname(amdevice);
210     fstype = amname_to_fstype(amdevice);
211
212     dbprintf(("%s: dumping device '%s' with '%s'\n",
213               debug_prefix_time(NULL), device, fstype));
214
215 #if defined(USE_RUNDUMP) || !defined(DUMP)
216     cmd = vstralloc(libexecdir, "/", "rundump", versionsuffix(), NULL);
217     cmdX = cmd;
218     if (g_options->config)
219         config = g_options->config;
220     else
221         config = "NOCONFIG";
222 #else
223     cmd = stralloc(DUMP);
224     cmdX = skip_argument;
225     config = skip_argument;
226 #endif
227
228 #ifndef AIX_BACKUP                                      /* { */
229     /* normal dump */
230 #ifdef XFSDUMP                                          /* { */
231 #ifdef DUMP                                             /* { */
232     if (strcmp(amname_to_fstype(amdevice), "xfs") == 0)
233 #else                                                   /* } { */
234     if (1)
235 #endif                                                  /* } */
236     {
237         char *progname = cmd = newvstralloc(cmd, libexecdir, "/", "rundump",
238                                             versionsuffix(), NULL);
239         cmdX = cmd;
240         if (g_options->config)
241             config = g_options->config;
242         else
243             config = "NOCONFIG";
244
245         program->backup_name  = XFSDUMP;
246         program->restore_name = XFSRESTORE;
247
248         indexcmd = vstralloc(XFSRESTORE,
249                              " -t",
250                              " -v", " silent",
251                              " -",
252                              " 2>/dev/null",
253                              " | sed",
254                              " -e", " \'s/^/\\//\'",
255                              NULL);
256         info_tapeheader();
257
258         start_index(options->createindex, dumpout, mesgf, indexf, indexcmd);
259
260         dumpkeys = stralloc(level_str);
261         dumppid = pipespawn(progname, STDIN_PIPE,
262                             &dumpin, &dumpout, &mesgf,
263                             cmdX, config,
264                             "xfsdump",
265                             options->no_record ? "-J" : skip_argument,
266                             "-F",
267                             "-l", dumpkeys,
268                             "-",
269                             device,
270                             NULL);
271     }
272     else
273 #endif                                                  /* } */
274 #ifdef VXDUMP                                           /* { */
275 #ifdef DUMP
276     if (strcmp(amname_to_fstype(amdevice), "vxfs") == 0)
277 #else
278     if (1)
279 #endif
280     {
281 #ifdef USE_RUNDUMP
282         char *progname = cmd = newvstralloc(cmd, libexecdir, "/", "rundump",
283                                             versionsuffix(), NULL);
284         cmdX = cmd;
285         if (g_options->config)
286             config = g_options->config;
287         else
288             config = "NOCONFIG";
289 #else
290         char *progname = cmd = newvstralloc(cmd, VXDUMP, NULL);
291         cmdX = skip_argument;
292         config = skip_argument;
293 #endif
294         program->backup_name  = VXDUMP;
295         program->restore_name = VXRESTORE;
296
297         dumpkeys = vstralloc(level_str,
298                              options->no_record ? "" : "u",
299                              "s",
300                              "f",
301                              NULL);
302
303         indexcmd = vstralloc(VXRESTORE,
304                              " -tvf", " -",
305                              " 2>/dev/null",
306                              " | ",
307                              LEAF_AND_DIRS,
308                              NULL);
309         info_tapeheader();
310
311         start_index(options->createindex, dumpout, mesgf, indexf, indexcmd);
312
313         dumppid = pipespawn(progname, STDIN_PIPE,
314                             &dumpin, &dumpout, &mesgf, 
315                             cmdX, config,
316                             "vxdump",
317                             dumpkeys,
318                             "1048576",
319                             "-",
320                             device,
321                             NULL);
322     }
323     else
324 #endif                                                  /* } */
325
326 #ifdef VDUMP                                            /* { */
327 #ifdef DUMP
328     if (strcmp(amname_to_fstype(amdevice), "advfs") == 0)
329 #else
330     if (1)
331 #endif
332     {
333         char *progname = cmd = newvstralloc(cmd, libexecdir, "/", "rundump",
334                                             versionsuffix(), NULL);
335         cmdX = cmd;
336         if (g_options->config)
337             config = g_options->config;
338         else
339             config = "NOCONFIG";
340         device = newstralloc(device, amname_to_dirname(amdevice));
341         program->backup_name  = VDUMP;
342         program->restore_name = VRESTORE;
343
344         dumpkeys = vstralloc(level_str,
345                              options->no_record ? "" : "u",
346                              "b",
347                              "f",
348                              NULL);
349
350         indexcmd = vstralloc(VRESTORE,
351                              " -tvf", " -",
352                              " 2>/dev/null",
353                              " | ",
354                              "sed -e \'\n/^\\./ {\ns/^\\.//\ns/, [0-9]*$//\ns/^\\.//\ns/ @-> .*$//\nt\n}\nd\n\'",
355                              NULL);
356         info_tapeheader();
357
358         start_index(options->createindex, dumpout, mesgf, indexf, indexcmd);
359
360         dumppid = pipespawn(cmd, STDIN_PIPE,
361                             &dumpin, &dumpout, &mesgf, 
362                             cmdX, config,
363                             "vdump",
364                             dumpkeys,
365                             "60",
366                             "-",
367                             device,
368                             NULL);
369     }
370     else
371 #endif                                                  /* } */
372
373     {
374 #ifndef RESTORE
375 #define RESTORE "restore"
376 #endif
377
378 #ifdef HAVE_HONOR_NODUMP
379 #  define PARAM_HONOR_NODUMP "h"
380 #else
381 #  define PARAM_HONOR_NODUMP ""
382 #endif
383         dumpkeys = vstralloc(level_str,
384                              options->no_record ? "" : "u",
385                              "s",
386                              PARAM_HONOR_NODUMP,
387                              "f",
388                              NULL);
389
390         indexcmd = vstralloc(RESTORE,
391                              " -tvf", " -",
392                              " 2>&1",
393                              /* not to /dev/null because of DU's dump */
394                              " | ",
395                              LEAF_AND_DIRS,
396                              NULL);
397         info_tapeheader();
398
399         start_index(options->createindex, dumpout, mesgf, indexf, indexcmd);
400
401         dumppid = pipespawn(cmd, STDIN_PIPE,
402                             &dumpin, &dumpout, &mesgf, 
403                             cmdX, config,
404                             "dump",
405                             dumpkeys,
406                             "1048576",
407 #ifdef HAVE_HONOR_NODUMP
408                             "0",
409 #endif
410                             "-",
411                             device,
412                             NULL);
413     }
414 #else                                                   /* } { */
415     /* AIX backup program */
416     dumpkeys = vstralloc("-",
417                          level_str,
418                          options->no_record ? "" : "u",
419                          "f",
420                          NULL);
421
422     indexcmd = vstralloc(RESTORE,
423                          " -B",
424                          " -tvf", " -",
425                          " 2>/dev/null",
426                          " | ",
427                          LEAF_AND_DIRS,
428                          NULL);
429     info_tapeheader();
430
431     start_index(options->createindex, dumpout, mesgf, indexf, indexcmd);
432
433     dumppid = pipespawn(cmd, STDIN_PIPE,
434                         &dumpin, &dumpout, &mesgf, 
435                         cmdX, config,
436                         "backup",
437                         dumpkeys,
438                         "-",
439                         device,
440                         NULL);
441 #endif                                                  /* } */
442
443     amfree(dumpkeys);
444     amfree(fstype);
445     amfree(device);
446     amfree(cmd);
447     amfree(indexcmd);
448
449     /* close the write ends of the pipes */
450
451     aclose(dumpin);
452     aclose(dumpout);
453     aclose(compout);
454     aclose(dataf);
455     aclose(mesgf);
456     if (options->createindex)
457         aclose(indexf);
458 }
459
460 static void
461 end_backup(
462     int         status)
463 {
464     (void)status;       /* Quiet unused parameter warning */
465
466     /* don't need to do anything for dump */
467 }
468
469 backup_program_t dump_program = {
470   "DUMP",
471 #ifdef DUMP
472   DUMP
473 #else
474   "dump"
475 #endif
476   ,
477   RESTORE
478   ,
479   re_table, start_backup, end_backup
480 };