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