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