2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 1991-1999 University of Maryland at College Park
4 * Copyright (c) 2007-2012 Zmanda, Inc. All Rights Reserved.
7 * Permission to use, copy, modify, distribute, and sell this software and its
8 * documentation for any purpose is hereby granted without fee, provided that
9 * the above copyright notice appear in all copies and that both that
10 * copyright notice and this permission notice appear in supporting
11 * documentation, and that the name of U.M. not be used in advertising or
12 * publicity pertaining to distribution of the software without specific,
13 * written prior permission. U.M. makes no representations about the
14 * suitability of this software for any purpose. It is provided "as is"
15 * without express or implied warranty.
17 * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
19 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
21 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
22 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24 * Authors: the Amanda Development Team. Its members are listed in a
25 * file named AUTHORS, in the root directory of this distribution.
27 /* $Id: dumper.c,v 1.190 2006/08/30 19:53:57 martinea Exp $
29 * requests remote amandad processes to dump filesystems
42 #include "fileheader.h"
43 #include "amfeatures.h"
44 #include "server_util.h"
46 #include "timestamp.h"
49 #define dumper_debug(i,x) do { \
50 if ((i) <= debug_dumper) { \
63 #define CONNECT_TIMEOUT 5*60
65 #define STARTUP_TIMEOUT 60
68 int fd; /* file to flush to */
70 char *datain; /* data buffer markers */
73 pid_t compresspid; /* valid if fd is pipe to compress */
74 pid_t encryptpid; /* valid if fd is pipe to encrypt */
77 struct databuf *g_databuf = NULL;
79 typedef struct filter_s {
83 gint64 first; /* first byte used */
84 gint64 size; /* number of byte use in the buffer */
85 gint64 allocated_size ; /* allocated size of the buffer */
86 event_handle_t *event;
89 static char *handle = NULL;
91 static char *errstr = NULL;
92 static off_t dumpbytes;
93 static off_t dumpsize, headersize, origsize;
95 static comp_t srvcompress = COMP_NONE;
96 char *srvcompprog = NULL;
97 char *clntcompprog = NULL;
99 static encrypt_t srvencrypt = ENCRYPT_NONE;
100 char *srv_encrypt = NULL;
101 char *clnt_encrypt = NULL;
102 char *srv_decrypt_opt = NULL;
103 char *clnt_decrypt_opt = NULL;
104 static kencrypt_type dumper_kencrypt;
106 static FILE *errf = NULL;
107 static char *hostname = NULL;
108 am_feature_t *their_features = NULL;
109 static char *diskname = NULL;
110 static char *qdiskname = NULL, *b64disk;
111 static char *device = NULL, *b64device;
112 static char *options = NULL;
113 static char *progname = NULL;
114 static char *amandad_path=NULL;
115 static char *client_username=NULL;
116 static char *client_port=NULL;
117 static char *ssh_keys=NULL;
118 static char *auth=NULL;
119 static data_path_t data_path=DATA_PATH_AMANDA;
120 static char *dataport_list = NULL;
122 static char *dumpdate = NULL;
123 static char *dumper_timestamp = NULL;
124 static time_t conf_dtimeout;
125 static int indexfderror;
126 static int set_datafd;
127 static char *dle_str = NULL;
128 static char *errfname = NULL;
129 static int errf_lines = 0;
130 static int max_warnings = 0;
132 static dumpfile_t file;
136 security_stream_t *fd;
145 #define NSTREAMS (int)(sizeof(streams) / sizeof(streams[0]))
147 static am_feature_t *our_features = NULL;
148 static char *our_feature_string = NULL;
150 /* buffer to keep partial line from the MESG stream */
152 char *buf; /* buffer holding msg data */
153 size_t size; /* size of alloced buffer */
157 /* local functions */
158 int main(int, char **);
159 static int do_dump(struct databuf *);
160 static void check_options(char *);
161 static void xml_check_options(char *optionstr);
162 static void finish_tapeheader(dumpfile_t *);
163 static ssize_t write_tapeheader(int, dumpfile_t *);
164 static void databuf_init(struct databuf *, int);
165 static int databuf_write(struct databuf *, const void *, size_t);
166 static int databuf_flush(struct databuf *);
167 static void process_dumpeof(void);
168 static void process_dumpline(const char *);
169 static void add_msg_data(const char *, size_t);
170 static void parse_info_line(char *);
171 static int log_msgout(logtype_t);
172 static char * dumper_get_security_conf (char *, void *);
174 static int runcompress(int, pid_t *, comp_t, char *);
175 static int runencrypt(int, pid_t *, encrypt_t);
177 static void sendbackup_response(void *, pkt_t *, security_handle_t *);
178 static int startup_dump(const char *, const char *, const char *, int,
179 const char *, const char *, const char *,
180 const char *, const char *, const char *,
181 const char *, const char *);
182 static void stop_dump(void);
184 static void read_indexfd(void *, void *, ssize_t);
185 static void read_datafd(void *, void *, ssize_t);
186 static void read_mesgfd(void *, void *, ssize_t);
187 static void timeout(time_t);
188 static void timeout_callback(void *);
194 char *compmode = NULL;
195 char *compend = NULL;
196 char *encryptmode = NULL;
197 char *encryptend = NULL;
198 char *decryptmode = NULL;
199 char *decryptend = NULL;
201 /* parse the compression option */
202 if (strstr(options, "srvcomp-best;") != NULL)
203 srvcompress = COMP_BEST;
204 else if (strstr(options, "srvcomp-fast;") != NULL)
205 srvcompress = COMP_FAST;
206 else if ((compmode = strstr(options, "srvcomp-cust=")) != NULL) {
207 compend = strchr(compmode, ';');
209 srvcompress = COMP_SERVER_CUST;
211 srvcompprog = stralloc(compmode + strlen("srvcomp-cust="));
214 } else if ((compmode = strstr(options, "comp-cust=")) != NULL) {
215 compend = strchr(compmode, ';');
217 srvcompress = COMP_CUST;
219 clntcompprog = stralloc(compmode + strlen("comp-cust="));
224 srvcompress = COMP_NONE;
228 /* now parse the encryption option */
229 if ((encryptmode = strstr(options, "encrypt-serv-cust=")) != NULL) {
230 encryptend = strchr(encryptmode, ';');
232 srvencrypt = ENCRYPT_SERV_CUST;
234 srv_encrypt = stralloc(encryptmode + strlen("encrypt-serv-cust="));
237 } else if ((encryptmode = strstr(options, "encrypt-cust=")) != NULL) {
238 encryptend = strchr(encryptmode, ';');
240 srvencrypt = ENCRYPT_CUST;
242 clnt_encrypt = stralloc(encryptmode + strlen("encrypt-cust="));
246 srvencrypt = ENCRYPT_NONE;
248 /* get the decryption option parameter */
249 if ((decryptmode = strstr(options, "server-decrypt-option=")) != NULL) {
250 decryptend = strchr(decryptmode, ';');
253 srv_decrypt_opt = stralloc(decryptmode + strlen("server-decrypt-option="));
256 } else if ((decryptmode = strstr(options, "client-decrypt-option=")) != NULL) {
257 decryptend = strchr(decryptmode, ';');
260 clnt_decrypt_opt = stralloc(decryptmode + strlen("client-decrypt-option="));
265 if (strstr(options, "kencrypt;") != NULL) {
266 dumper_kencrypt = KENCRYPT_WILL_DO;
268 dumper_kencrypt = KENCRYPT_NONE;
281 o = oo = vstralloc("<dle>", strchr(optionstr,'<'), "</dle>", NULL);
283 dle = amxml_parse_node_CHAR(o, &errmsg);
285 error("amxml_parse_node_CHAR failed: %s\n", errmsg);
288 if (dle->compress == COMP_SERVER_FAST) {
289 srvcompress = COMP_FAST;
290 } else if (dle->compress == COMP_SERVER_BEST) {
291 srvcompress = COMP_BEST;
292 } else if (dle->compress == COMP_SERVER_CUST) {
293 srvcompress = COMP_SERVER_CUST;
294 srvcompprog = g_strdup(dle->compprog);
295 } else if (dle->compress == COMP_CUST) {
296 srvcompress = COMP_CUST;
297 clntcompprog = g_strdup(dle->compprog);
299 srvcompress = COMP_NONE;
302 if (dle->encrypt == ENCRYPT_CUST) {
303 srvencrypt = ENCRYPT_CUST;
304 clnt_encrypt = g_strdup(dle->clnt_encrypt);
305 clnt_decrypt_opt = g_strdup(dle->clnt_decrypt_opt);
306 } else if (dle->encrypt == ENCRYPT_SERV_CUST) {
307 srvencrypt = ENCRYPT_SERV_CUST;
308 srv_encrypt = g_strdup(dle->srv_encrypt);
309 srv_decrypt_opt = g_strdup(dle->srv_decrypt_opt);
311 srvencrypt = ENCRYPT_NONE;
323 static struct databuf db;
324 struct cmdargs *cmdargs = NULL;
327 in_port_t header_port;
331 config_overrides_t *cfg_ovr = NULL;
332 char *cfg_opt = NULL;
335 if (argc > 1 && argv && argv[1] && g_str_equal(argv[1], "--version")) {
336 printf("dumper-%s\n", VERSION);
341 * Configure program for internationalization:
342 * 1) Only set the message locale for now.
343 * 2) Set textdomain for all amanda related programs to "amanda"
344 * We don't want to be forced to support dozens of message catalogs.
346 setlocale(LC_MESSAGES, "C");
347 textdomain("amanda");
349 /* drop root privileges */
350 dumper_setuid = set_root_privs(0);
356 dbopen(DBG_SUBDIR_SERVER);
358 /* Don't die when child closes pipe */
359 signal(SIGPIPE, SIG_IGN);
361 add_amanda_log_handler(amanda_log_stderr);
362 add_amanda_log_handler(amanda_log_trace_log);
364 cfg_ovr = extract_commandline_config_overrides(&argc, &argv);
367 set_config_overrides(cfg_ovr);
368 config_init(CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_USE_CWD, cfg_opt);
370 if (!dumper_setuid) {
371 error(_("dumper must be run setuid root"));
374 if (config_errors(NULL) >= CFGERR_ERRORS) {
375 g_critical(_("errors processing config file"));
378 safe_cd(); /* do this *after* config_init() */
380 check_running_as(RUNNING_AS_ROOT | RUNNING_AS_UID_ONLY);
382 dbrename(get_config_name(), DBG_SUBDIR_SERVER);
384 our_features = am_init_feature_set();
385 our_feature_string = am_feature_to_string(our_features);
387 log_add(L_INFO, "%s pid %ld", get_pname(), (long)getpid());
389 _("%s: pid %ld executable %s version %s\n"),
390 get_pname(), (long) getpid(),
394 /* now, make sure we are a valid user */
396 signal(SIGPIPE, SIG_IGN);
398 conf_dtimeout = (time_t)getconf_int(CNF_DTIMEOUT);
404 free_cmdargs(cmdargs);
408 switch(cmdargs->cmd) {
410 if(cmdargs->argc < 2)
411 error(_("error [dumper START: not enough args: timestamp]"));
412 dumper_timestamp = newstralloc(dumper_timestamp, cmdargs->argv[1]);
442 a = 1; /* skip "PORT-DUMP" */
444 if(a >= cmdargs->argc) {
445 error(_("error [dumper PORT-DUMP: not enough args: handle]"));
448 handle = newstralloc(handle, cmdargs->argv[a++]);
450 if(a >= cmdargs->argc) {
451 error(_("error [dumper PORT-DUMP: not enough args: port]"));
454 header_port = (in_port_t)atoi(cmdargs->argv[a++]);
456 if(a >= cmdargs->argc) {
457 error(_("error [dumper PORT-DUMP: not enough args: hostname]"));
460 hostname = newstralloc(hostname, cmdargs->argv[a++]);
462 if(a >= cmdargs->argc) {
463 error(_("error [dumper PORT-DUMP: not enough args: features]"));
466 am_release_feature_set(their_features);
467 their_features = am_string_to_feature(cmdargs->argv[a++]);
469 if(a >= cmdargs->argc) {
470 error(_("error [dumper PORT-DUMP: not enough args: diskname]"));
473 diskname = newstralloc(diskname, cmdargs->argv[a++]);
474 if (qdiskname != NULL)
476 qdiskname = quote_string(diskname);
477 b64disk = amxml_format_tag("disk", diskname);
479 if(a >= cmdargs->argc) {
480 error(_("error [dumper PORT-DUMP: not enough args: device]"));
483 device = newstralloc(device, cmdargs->argv[a++]);
484 b64device = amxml_format_tag("diskdevice", device);
485 if(strcmp(device,"NODEVICE") == 0)
488 if(a >= cmdargs->argc) {
489 error(_("error [dumper PORT-DUMP: not enough args: level]"));
492 level = atoi(cmdargs->argv[a++]);
494 if(a >= cmdargs->argc) {
495 error(_("error [dumper PORT-DUMP: not enough args: dumpdate]"));
498 dumpdate = newstralloc(dumpdate, cmdargs->argv[a++]);
500 if(a >= cmdargs->argc) {
501 error(_("error [dumper PORT-DUMP: not enough args: program]"));
504 progname = newstralloc(progname, cmdargs->argv[a++]);
506 if(a >= cmdargs->argc) {
507 error(_("error [dumper PORT-DUMP: not enough args: amandad_path]"));
510 amandad_path = newstralloc(amandad_path, cmdargs->argv[a++]);
512 if(a >= cmdargs->argc) {
513 error(_("error [dumper PORT-DUMP: not enough args: client_username]"));
515 client_username = newstralloc(client_username, cmdargs->argv[a++]);
517 if(a >= cmdargs->argc) {
518 error(_("error [dumper PORT-DUMP: not enough args: client_port]"));
520 client_port = newstralloc(client_port, cmdargs->argv[a++]);
522 if(a >= cmdargs->argc) {
523 error(_("error [dumper PORT-DUMP: not enough args: ssh_keys]"));
525 ssh_keys = newstralloc(ssh_keys, cmdargs->argv[a++]);
527 if(a >= cmdargs->argc) {
528 error(_("error [dumper PORT-DUMP: not enough args: auth]"));
530 auth = newstralloc(auth, cmdargs->argv[a++]);
532 if(a >= cmdargs->argc) {
533 error(_("error [dumper PORT-DUMP: not enough args: data_path]"));
535 data_path = data_path_from_string(cmdargs->argv[a++]);
537 if(a >= cmdargs->argc) {
538 error(_("error [dumper PORT-DUMP: not enough args: dataport_list]"));
540 dataport_list = newstralloc(dataport_list, cmdargs->argv[a++]);
542 if(a >= cmdargs->argc) {
543 error(_("error [dumper PORT-DUMP: not enough args: max_warnings]"));
545 max_warnings = atoi(cmdargs->argv[a++]);
547 if(a >= cmdargs->argc) {
548 error(_("error [dumper PORT-DUMP: not enough args: options]"));
550 options = newstralloc(options, cmdargs->argv[a++]);
552 if(a != cmdargs->argc) {
553 error(_("error [dumper PORT-DUMP: too many args: %d != %d]"),
558 /* Double-check that 'localhost' resolves properly */
559 if ((res = resolve_hostname("localhost", 0, NULL, NULL) != 0)) {
560 errstr = newvstrallocf(errstr,
561 _("could not resolve localhost: %s"),
563 q = quote_string(errstr);
564 putresult(FAILED, "%s %s\n", handle, q);
565 log_add(L_FAIL, "%s %s %s %d [%s]", hostname, qdiskname,
566 dumper_timestamp, level, errstr);
571 /* connect outf to chunker/taper port */
573 g_debug(_("Sending header to localhost:%d\n"), header_port);
574 outfd = stream_client("localhost", header_port,
575 STREAM_BUFSIZE, 0, NULL, 0);
578 errstr = newvstrallocf(errstr, _("port open: %s"),
580 q = quote_string(errstr);
581 putresult(FAILED, "%s %s\n", handle, q);
582 log_add(L_FAIL, "%s %s %s %d [%s]", hostname, qdiskname,
583 dumper_timestamp, level, errstr);
587 databuf_init(&db, outfd);
590 if (am_has_feature(their_features, fe_req_xml))
591 xml_check_options(options); /* note: modifies globals */
593 check_options(options); /* note: modifies globals */
595 rc = startup_dump(hostname,
608 q = quote_string(errstr);
609 putresult(rc == 2? FAILED : TRYAGAIN, "%s %s\n",
612 log_add(L_FAIL, "%s %s %s %d [%s]", hostname, qdiskname,
613 dumper_timestamp, level, errstr);
617 /* try to clean up any defunct processes, since Amanda doesn't
618 wait() for them explicitly */
619 while(waitpid(-1, NULL, WNOHANG)> 0);
622 amfree(amandad_path);
623 amfree(client_username);
633 if(cmdargs->argc >= 1) {
634 q = quote_string(cmdargs->argv[0]);
636 q = stralloc(_("(no input?)"));
638 putresult(BAD_COMMAND, "%s\n", q);
645 } while(cmdargs->cmd != QUIT);
646 free_cmdargs(cmdargs);
648 log_add(L_INFO, "pid-done %ld", (long)getpid());
650 am_release_feature_set(our_features);
651 amfree(our_feature_string);
653 amfree(dumper_timestamp);
662 amfree(clntcompprog);
664 amfree(clnt_encrypt);
665 amfree(srv_decrypt_opt);
666 amfree(clnt_decrypt_opt);
670 return (0); /* exit */
675 * Initialize a databuf. Takes a writeable file descriptor.
684 db->datain = db->dataout = db->datalimit = NULL;
685 db->compresspid = -1;
691 * Updates the buffer pointer for the input data buffer. The buffer is
692 * written regardless of how much data is present, since we know we
693 * are writing to a socket (to chunker) and there is no need to maintain
702 db->buf = (char *)buf;
703 db->datain = db->datalimit = db->buf + size;
704 db->dataout = db->buf;
705 return databuf_flush(db);
709 * Write out the buffer to chunker.
719 * If there's no data, do nothing.
721 if (db->dataout >= db->datain) {
726 * Write out the buffer
728 written = full_write(db->fd, db->dataout,
729 (size_t)(db->datain - db->dataout));
731 db->dataout += written;
732 dumpbytes += (off_t)written;
734 if (dumpbytes >= (off_t)1024) {
735 dumpsize += (dumpbytes / (off_t)1024);
736 dumpbytes %= (off_t)1024;
739 int save_errno = errno;
740 m = vstrallocf(_("data write: %s"), strerror(save_errno));
742 errstr = quote_string(m);
747 db->datain = db->dataout = db->buf;
751 static int dump_result;
753 #define GOT_INFO_ENDLINE (1 << 0)
754 #define GOT_SIZELINE (1 << 1)
755 #define GOT_ENDLINE (1 << 2)
756 #define HEADER_DONE (1 << 3)
760 process_dumpeof(void)
762 /* process any partial line in msgbuf? !!! */
763 add_msg_data(NULL, 0);
764 if(!ISSET(status, GOT_SIZELINE) && dump_result < 2) {
765 /* make a note if there isn't already a failure */
767 _("? %s: strange [missing size line from sendbackup]\n"),
770 errstr = stralloc(_("missing size line from sendbackup"));
772 dump_result = max(dump_result, 2);
775 if(!ISSET(status, GOT_ENDLINE) && dump_result < 2) {
777 _("? %s: strange [missing end line from sendbackup]\n"),
780 errstr = stralloc(_("missing end line from sendbackup"));
782 dump_result = max(dump_result, 2);
787 * Parse an information line from the client.
788 * We ignore unknown parameters and only remember the last
795 static const struct {
800 { "BACKUP", file.program, SIZEOF(file.program) },
801 { "APPLICATION", file.application, SIZEOF(file.application) },
802 { "RECOVER_CMD", file.recover_cmd, SIZEOF(file.recover_cmd) },
803 { "COMPRESS_SUFFIX", file.comp_suffix, SIZEOF(file.comp_suffix) },
804 { "SERVER_CUSTOM_COMPRESS", file.srvcompprog, SIZEOF(file.srvcompprog) },
805 { "CLIENT_CUSTOM_COMPRESS", file.clntcompprog, SIZEOF(file.clntcompprog) },
806 { "SERVER_ENCRYPT", file.srv_encrypt, SIZEOF(file.srv_encrypt) },
807 { "CLIENT_ENCRYPT", file.clnt_encrypt, SIZEOF(file.clnt_encrypt) },
808 { "SERVER_DECRYPT_OPTION", file.srv_decrypt_opt, SIZEOF(file.srv_decrypt_opt) },
809 { "CLIENT_DECRYPT_OPTION", file.clnt_decrypt_opt, SIZEOF(file.clnt_decrypt_opt) }
814 if (strcmp(str, "end") == 0) {
815 SET(status, GOT_INFO_ENDLINE);
819 name = strtok(str, "=");
822 value = strtok(NULL, "");
826 for (i = 0; i < SIZEOF(fields) / SIZEOF(fields[0]); i++) {
827 if (strcmp(name, fields[i].name) == 0) {
828 strncpy(fields[i].value, value, fields[i].len - 1);
829 fields[i].value[fields[i].len - 1] = '\0';
845 /* normal backup output line */
848 /* sendbackup detected something strange */
849 dump_result = max(dump_result, 1);
852 /* a sendbackup line, just check them all since there are only 5 */
853 tok = strtok(buf, " ");
854 if (tok == NULL || strcmp(tok, "sendbackup:") != 0)
857 tok = strtok(NULL, " ");
861 if (strcmp(tok, "start") == 0) {
865 if (strcmp(tok, "size") == 0) {
866 tok = strtok(NULL, "");
868 origsize = OFF_T_ATOI(tok);
869 SET(status, GOT_SIZELINE);
874 if (strcmp(tok, "no-op") == 0) {
879 if (strcmp(tok, "end") == 0) {
880 SET(status, GOT_ENDLINE);
884 if (strcmp(tok, "warning") == 0) {
885 dump_result = max(dump_result, 1);
889 if (strcmp(tok, "error") == 0) {
890 SET(status, GOT_ENDLINE);
891 dump_result = max(dump_result, 2);
893 tok = strtok(NULL, "");
894 if (!errstr) { /* report first error line */
895 if (tok == NULL || *tok != '[') {
896 errstr = newvstrallocf(errstr, _("bad remote error: %s"),
901 tok++; /* skip over '[' */
902 if ((enderr = strchr(tok, ']')) != NULL)
904 errstr = newstralloc(errstr, tok);
910 if (strcmp(tok, "info") == 0) {
911 tok = strtok(NULL, "");
913 parse_info_line(tok);
916 /* else we fall through to bad line */
920 g_fprintf(errf, "??");
921 dump_result = max(dump_result, 1);
924 g_fprintf(errf, "%s\n", str);
938 buflen = strlen(msg.buf);
943 * If our argument is NULL, then we need to flush out any remaining
949 g_fprintf(errf,_("? %s: error [partial line in msgbuf: %zu bytes]\n"),
950 get_pname(), buflen);
951 g_fprintf(errf,_("? %s: error [partial line in msgbuf: \"%s\"]\n"),
952 get_pname(), msg.buf);
958 * Expand the buffer if it can't hold the new contents.
960 if ((buflen + len + 1) > msg.size) {
964 /* round up to next y, where y is a power of 2 */
965 #define ROUND(x, y) (((x) + (y) - 1) & ~((y) - 1))
967 newsize = ROUND(buflen + (ssize_t)len + 1, 256);
968 newbuf = alloc(newsize);
970 if (msg.buf != NULL) {
971 strncpy(newbuf, msg.buf, newsize);
980 * If there was a partial line from the last call, then
981 * append the new data to the end.
983 strncat(msg.buf, str, len);
986 * Process all lines in the buffer
987 * scanning line for unqouted newline.
989 for (ch = line = msg.buf; *ch != '\0'; ch++) {
992 * Found a newline. Terminate and process line.
995 process_dumpline(line);
1001 * If we did not process all of the data, move it to the front
1002 * of the buffer so it is there next time.
1004 if (*line != '\0') {
1005 buflen = strlen(line);
1006 memmove(msg.buf, line, (size_t)buflen + 1);
1022 if (fseeko(errf, 0L, SEEK_SET) < 0) {
1023 dbprintf(_("log_msgout: warning - seek failed: %s\n"), strerror(errno));
1025 while ((line = agets(errf)) != NULL) {
1026 if (max_warnings > 0 && errf_lines >= max_warnings && count >= max_warnings) {
1027 log_add(typ, "Look in the '%s' file for full error messages", errfname);
1031 if (line[0] != '\0') {
1032 log_add(typ, "%s", line);
1045 * Fill in the rest of the tape header
1052 assert(ISSET(status, HEADER_DONE));
1054 file->type = F_DUMPFILE;
1055 strncpy(file->datestamp, dumper_timestamp, sizeof(file->datestamp) - 1);
1056 strncpy(file->name, hostname, SIZEOF(file->name) - 1);
1057 strncpy(file->disk, diskname, SIZEOF(file->disk) - 1);
1058 file->dumplevel = level;
1059 file->blocksize = DISK_BLOCK_BYTES;
1062 * If we're doing the compression here, we need to override what
1063 * sendbackup told us the compression was.
1065 if (srvcompress != COMP_NONE) {
1066 file->compressed = 1;
1067 #ifndef UNCOMPRESS_OPT
1068 #define UNCOMPRESS_OPT ""
1070 if (srvcompress == COMP_SERVER_CUST) {
1071 g_snprintf(file->uncompress_cmd, SIZEOF(file->uncompress_cmd),
1072 " %s %s |", srvcompprog, "-d");
1073 strncpy(file->comp_suffix, "cust", SIZEOF(file->comp_suffix) - 1);
1074 file->comp_suffix[SIZEOF(file->comp_suffix) - 1] = '\0';
1075 strncpy(file->srvcompprog, srvcompprog, SIZEOF(file->srvcompprog) - 1);
1076 file->srvcompprog[SIZEOF(file->srvcompprog) - 1] = '\0';
1077 } else if ( srvcompress == COMP_CUST ) {
1078 g_snprintf(file->uncompress_cmd, SIZEOF(file->uncompress_cmd),
1079 " %s %s |", clntcompprog, "-d");
1080 strncpy(file->comp_suffix, "cust", SIZEOF(file->comp_suffix) - 1);
1081 file->comp_suffix[SIZEOF(file->comp_suffix) - 1] = '\0';
1082 strncpy(file->clntcompprog, clntcompprog, SIZEOF(file->clntcompprog));
1083 file->clntcompprog[SIZEOF(file->clntcompprog) - 1] = '\0';
1085 g_snprintf(file->uncompress_cmd, SIZEOF(file->uncompress_cmd),
1086 " %s %s |", UNCOMPRESS_PATH, UNCOMPRESS_OPT);
1087 strncpy(file->comp_suffix, COMPRESS_SUFFIX,SIZEOF(file->comp_suffix) - 1);
1088 file->comp_suffix[SIZEOF(file->comp_suffix) - 1] = '\0';
1091 if (file->comp_suffix[0] == '\0') {
1092 file->compressed = 0;
1093 assert(SIZEOF(file->comp_suffix) >= 2);
1094 strncpy(file->comp_suffix, "N", SIZEOF(file->comp_suffix) - 1);
1095 file->comp_suffix[SIZEOF(file->comp_suffix) - 1] = '\0';
1097 file->compressed = 1;
1100 /* take care of the encryption header here */
1101 if (srvencrypt != ENCRYPT_NONE) {
1103 if (srvencrypt == ENCRYPT_SERV_CUST) {
1104 if (srv_decrypt_opt) {
1105 g_snprintf(file->decrypt_cmd, SIZEOF(file->decrypt_cmd),
1106 " %s %s |", srv_encrypt, srv_decrypt_opt);
1107 strncpy(file->srv_decrypt_opt, srv_decrypt_opt, SIZEOF(file->srv_decrypt_opt) - 1);
1108 file->srv_decrypt_opt[SIZEOF(file->srv_decrypt_opt) - 1] = '\0';
1110 g_snprintf(file->decrypt_cmd, SIZEOF(file->decrypt_cmd),
1111 " %s |", srv_encrypt);
1112 file->srv_decrypt_opt[0] = '\0';
1114 strncpy(file->encrypt_suffix, "enc", SIZEOF(file->encrypt_suffix) - 1);
1115 file->encrypt_suffix[SIZEOF(file->encrypt_suffix) - 1] = '\0';
1116 strncpy(file->srv_encrypt, srv_encrypt, SIZEOF(file->srv_encrypt) - 1);
1117 file->srv_encrypt[SIZEOF(file->srv_encrypt) - 1] = '\0';
1118 } else if ( srvencrypt == ENCRYPT_CUST ) {
1119 if (clnt_decrypt_opt) {
1120 g_snprintf(file->decrypt_cmd, SIZEOF(file->decrypt_cmd),
1121 " %s %s |", clnt_encrypt, clnt_decrypt_opt);
1122 strncpy(file->clnt_decrypt_opt, clnt_decrypt_opt,
1123 SIZEOF(file->clnt_decrypt_opt));
1124 file->clnt_decrypt_opt[SIZEOF(file->clnt_decrypt_opt) - 1] = '\0';
1126 g_snprintf(file->decrypt_cmd, SIZEOF(file->decrypt_cmd),
1127 " %s |", clnt_encrypt);
1128 file->clnt_decrypt_opt[0] = '\0';
1130 g_snprintf(file->decrypt_cmd, SIZEOF(file->decrypt_cmd),
1131 " %s %s |", clnt_encrypt, clnt_decrypt_opt);
1132 strncpy(file->encrypt_suffix, "enc", SIZEOF(file->encrypt_suffix) - 1);
1133 file->encrypt_suffix[SIZEOF(file->encrypt_suffix) - 1] = '\0';
1134 strncpy(file->clnt_encrypt, clnt_encrypt, SIZEOF(file->clnt_encrypt) - 1);
1135 file->clnt_encrypt[SIZEOF(file->clnt_encrypt) - 1] = '\0';
1138 if (file->encrypt_suffix[0] == '\0') {
1139 file->encrypted = 0;
1140 assert(SIZEOF(file->encrypt_suffix) >= 2);
1141 strncpy(file->encrypt_suffix, "N", SIZEOF(file->encrypt_suffix) - 1);
1142 file->encrypt_suffix[SIZEOF(file->encrypt_suffix) - 1] = '\0';
1148 file->dle_str = stralloc(dle_str);
1150 file->dle_str = NULL;
1154 * Send an Amanda dump header to the output file.
1164 if (debug_dumper > 1)
1165 dump_dumpfile_t(file);
1166 buffer = build_header(file, NULL, DISK_BLOCK_BYTES);
1167 if (!buffer) /* this shouldn't happen */
1168 error(_("header does not fit in %zd bytes"), (size_t)DISK_BLOCK_BYTES);
1170 written = full_write(outfd, buffer, DISK_BLOCK_BYTES);
1172 if(written == DISK_BLOCK_BYTES)
1184 char *indexfile_tmp = NULL;
1185 char *indexfile_real = NULL;
1186 char level_str[NUM_STR_SIZE];
1191 double dumptime; /* Time dump took in secs */
1192 pid_t indexpid = -1;
1198 if (msg.buf) msg.buf[0] = '\0'; /* reset msg buffer */
1201 dumpbytes = dumpsize = headersize = origsize = (off_t)0;
1204 g_snprintf(level_str, SIZEOF(level_str), "%d", level);
1205 time_str = get_timestamp_from_time(0);
1206 fn = sanitise_filename(diskname);
1208 errfname = newvstralloc(errfname,
1210 "/log.error", NULL);
1211 mkdir(errfname, 0700);
1212 errfname = newvstralloc(errfname,
1214 "/log.error/", hostname,
1222 if((errf = fopen(errfname, "w+")) == NULL) {
1223 errstr = newvstrallocf(errstr, "errfile open \"%s\": %s",
1224 errfname, strerror(errno));
1229 if (streams[INDEXFD].fd != NULL) {
1230 indexfile_real = getindexfname(hostname, diskname, dumper_timestamp, level);
1231 indexfile_tmp = stralloc2(indexfile_real, ".tmp");
1233 if (mkpdir(indexfile_tmp, 0755, (uid_t)-1, (gid_t)-1) == -1) {
1234 errstr = newvstrallocf(errstr,
1235 _("err create %s: %s"),
1238 amfree(indexfile_real);
1239 amfree(indexfile_tmp);
1242 indexout = open(indexfile_tmp, O_WRONLY | O_CREAT | O_TRUNC, 0600);
1243 if (indexout == -1) {
1244 errstr = newvstrallocf(errstr, _("err open %s: %s"),
1245 indexfile_tmp, strerror(errno));
1248 if (runcompress(indexout, &indexpid, COMP_BEST, "index compress") < 0) {
1255 * Schedule the indexfd for relaying to the index file
1257 security_stream_read(streams[INDEXFD].fd, read_indexfd, &indexout);
1261 * We only need to process messages initially. Once we have done
1262 * the header, we will start processing data too.
1264 security_stream_read(streams[MESGFD].fd, read_mesgfd, db);
1268 * Setup a read timeout
1270 timeout(conf_dtimeout);
1273 * Start the event loop. This will exit when all three events
1274 * (read the mesgfd, read the datafd, and timeout) are removed.
1278 if (!ISSET(status, HEADER_DONE)) {
1279 dump_result = max(dump_result, 2);
1280 if (!errstr) errstr = stralloc(_("got no header information"));
1283 dumpsize -= headersize; /* don't count the header */
1284 if (dumpsize <= (off_t)0 && data_path == DATA_PATH_AMANDA) {
1285 dumpsize = (off_t)0;
1286 dump_result = max(dump_result, 2);
1287 if (!errstr) errstr = stralloc(_("got no data"));
1290 if (data_path == DATA_PATH_DIRECTTCP) {
1291 dumpsize = origsize;
1294 if (!ISSET(status, HEADER_DONE)) {
1295 dump_result = max(dump_result, 2);
1296 if (!errstr) errstr = stralloc(_("got no header information"));
1299 if (dumpsize == 0 && data_path == DATA_PATH_AMANDA) {
1300 dump_result = max(dump_result, 2);
1301 if (!errstr) errstr = stralloc(_("got no data"));
1304 if (indexfile_tmp) {
1305 amwait_t index_status;
1307 /*@i@*/ aclose(indexout);
1308 waitpid(indexpid,&index_status,0);
1309 log_add(L_INFO, "pid-done %ld", (long)indexpid);
1310 if (rename(indexfile_tmp, indexfile_real) != 0) {
1311 log_add(L_WARNING, _("could not rename \"%s\" to \"%s\": %s"),
1312 indexfile_tmp, indexfile_real, strerror(errno));
1314 amfree(indexfile_tmp);
1315 amfree(indexfile_real);
1318 /* copy the header in a file on the index dir */
1319 if (ISSET(status, HEADER_DONE)) {
1322 char *f = getheaderfname(hostname, diskname, dumper_timestamp, level);
1325 s = build_header(&file, NULL, DISK_BLOCK_BYTES);
1333 if (db->compresspid != -1 && dump_result < 2) {
1334 amwait_t wait_status;
1335 char *errmsg = NULL;
1337 waitpid(db->compresspid, &wait_status, 0);
1338 if (WIFSIGNALED(wait_status)) {
1339 errmsg = g_strdup_printf(_("%s terminated with signal %d"),
1340 "compress", WTERMSIG(wait_status));
1341 } else if (WIFEXITED(wait_status)) {
1342 if (WEXITSTATUS(wait_status) != 0) {
1343 errmsg = g_strdup_printf(_("%s exited with status %d"),
1344 "compress", WEXITSTATUS(wait_status));
1347 errmsg = g_strdup_printf(_("%s got bad exit"),
1351 g_fprintf(errf, _("? %s\n"), errmsg);
1352 g_debug("%s", errmsg);
1353 dump_result = max(dump_result, 2);
1359 log_add(L_INFO, "pid-done %ld", (long)db->compresspid);
1360 db->compresspid = -1;
1363 if (db->encryptpid != -1 && dump_result < 2) {
1364 amwait_t wait_status;
1365 char *errmsg = NULL;
1367 waitpid(db->encryptpid, &wait_status, 0);
1368 if (WIFSIGNALED(wait_status)) {
1369 errmsg = g_strdup_printf(_("%s terminated with signal %d"),
1370 "encrypt", WTERMSIG(wait_status));
1371 } else if (WIFEXITED(wait_status)) {
1372 if (WEXITSTATUS(wait_status) != 0) {
1373 errmsg = g_strdup_printf(_("%s exited with status %d"),
1374 "encrypt", WEXITSTATUS(wait_status));
1377 errmsg = g_strdup_printf(_("%s got bad exit"),
1381 g_fprintf(errf, _("? %s\n"), errmsg);
1382 g_debug("%s", errmsg);
1383 dump_result = max(dump_result, 2);
1389 log_add(L_INFO, "pid-done %ld", (long)db->encryptpid);
1390 db->encryptpid = -1;
1393 if (dump_result > 1)
1396 runtime = stopclock();
1397 dumptime = g_timeval_to_double(runtime);
1400 errstr = alloc(128);
1401 g_snprintf(errstr, 128, _("sec %s kb %lld kps %3.1lf orig-kb %lld"),
1402 walltime_str(runtime),
1403 (long long)dumpsize,
1404 (isnormal(dumptime) ? ((double)dumpsize / (double)dumptime) : 0.0),
1405 (long long)origsize);
1406 m = vstrallocf("[%s]", errstr);
1407 q = quote_string(m);
1409 putresult(DONE, _("%s %lld %lld %lu %s\n"), handle,
1410 (long long)origsize,
1411 (long long)dumpsize,
1412 (unsigned long)((double)dumptime+0.5), q);
1415 switch(dump_result) {
1417 log_add(L_SUCCESS, "%s %s %s %d [%s]", hostname, qdiskname, dumper_timestamp, level, errstr);
1422 log_start_multiline();
1423 log_add(L_STRANGE, "%s %s %d [%s]", hostname, qdiskname, level, errstr);
1424 to_unlink = log_msgout(L_STRANGE);
1425 log_end_multiline();
1438 if (data_path == DATA_PATH_AMANDA)
1442 dumpfile_free_data(&file);
1447 m = vstrallocf("[%s]", errstr);
1448 q = quote_string(m);
1449 putresult(FAILED, "%s %s\n", handle, q);
1454 /* kill all child process */
1455 if (db->compresspid != -1) {
1456 g_fprintf(stderr,_("%s: kill compress command\n"),get_pname());
1457 if (kill(db->compresspid, SIGTERM) < 0) {
1458 if (errno != ESRCH) {
1459 g_fprintf(stderr,_("%s: can't kill compress command: %s\n"),
1460 get_pname(), strerror(errno));
1462 log_add(L_INFO, "pid-done %ld", (long)db->compresspid);
1466 waitpid(db->compresspid,NULL,0);
1467 log_add(L_INFO, "pid-done %ld", (long)db->compresspid);
1471 if (db->encryptpid != -1) {
1472 g_fprintf(stderr,_("%s: kill encrypt command\n"),get_pname());
1473 if (kill(db->encryptpid, SIGTERM) < 0) {
1474 if (errno != ESRCH) {
1475 g_fprintf(stderr,_("%s: can't kill encrypt command: %s\n"),
1476 get_pname(), strerror(errno));
1478 log_add(L_INFO, "pid-done %ld", (long)db->encryptpid);
1482 waitpid(db->encryptpid,NULL,0);
1483 log_add(L_INFO, "pid-done %ld", (long)db->encryptpid);
1487 if (indexpid != -1) {
1488 g_fprintf(stderr,_("%s: kill index command\n"),get_pname());
1489 if (kill(indexpid, SIGTERM) < 0) {
1490 if (errno != ESRCH) {
1491 g_fprintf(stderr,_("%s: can't kill index command: %s\n"),
1492 get_pname(),strerror(errno));
1494 log_add(L_INFO, "pid-done %ld", (long)indexpid);
1498 waitpid(indexpid,NULL,0);
1499 log_add(L_INFO, "pid-done %ld", (long)indexpid);
1503 log_start_multiline();
1504 log_add(L_FAIL, _("%s %s %s %d [%s]"), hostname, qdiskname, dumper_timestamp,
1507 to_unlink = log_msgout(L_FAIL);
1509 log_end_multiline();
1519 if (indexfile_tmp) {
1520 unlink(indexfile_tmp);
1521 amfree(indexfile_tmp);
1522 amfree(indexfile_real);
1526 dumpfile_free_data(&file);
1532 * Callback for reads on the mesgfd stream
1540 struct databuf *db = cookie;
1546 errstr = newvstrallocf(errstr, _("mesg read: %s"),
1547 security_stream_geterror(streams[MESGFD].fd));
1554 * EOF. Just shut down the mesg stream.
1557 security_stream_close(streams[MESGFD].fd);
1558 streams[MESGFD].fd = NULL;
1560 * If the data fd and index fd has also shut down, then we're done.
1562 if ((set_datafd == 0 || streams[DATAFD].fd == NULL) &&
1563 streams[INDEXFD].fd == NULL)
1568 assert(buf != NULL);
1569 add_msg_data(buf, (size_t)size);
1573 if (ISSET(status, GOT_INFO_ENDLINE) && !ISSET(status, HEADER_DONE)) {
1574 /* Use the first in the dataport_list */
1575 in_port_t data_port;
1576 char *data_host = dataport_list;
1579 s = strchr(dataport_list, ',');
1580 if (s) *s = '\0'; /* use first data_port */
1581 s = strrchr(dataport_list, ':');
1584 data_port = atoi(s);
1586 SET(status, HEADER_DONE);
1587 /* time to do the header */
1588 finish_tapeheader(&file);
1589 if (write_tapeheader(db->fd, &file)) {
1590 errstr = newvstrallocf(errstr, _("write_tapeheader: %s"),
1597 if (data_path == DATA_PATH_AMANDA) {
1598 g_debug(_("Sending data to %s:%d\n"), data_host, data_port);
1599 db->fd = stream_client(data_host, data_port,
1600 STREAM_BUFSIZE, 0, NULL, 0);
1602 errstr = newvstrallocf(errstr,
1603 _("Can't open data output stream: %s"),
1611 dumpsize += (off_t)DISK_BLOCK_KB;
1612 headersize += (off_t)DISK_BLOCK_KB;
1614 if (srvencrypt == ENCRYPT_SERV_CUST) {
1615 if (runencrypt(db->fd, &db->encryptpid, srvencrypt) < 0) {
1622 * Now, setup the compress for the data output, and start
1623 * reading the datafd.
1625 if ((srvcompress != COMP_NONE) && (srvcompress != COMP_CUST)) {
1626 if (runcompress(db->fd, &db->compresspid, srvcompress, "data compress") < 0) {
1632 security_stream_read(streams[DATAFD].fd, read_datafd, db);
1637 * Reset the timeout for future reads
1639 timeout(conf_dtimeout);
1643 * Callback for reads on the datafd stream
1651 struct databuf *db = cookie;
1656 * The read failed. Error out
1659 errstr = newvstrallocf(errstr, _("data read: %s"),
1660 security_stream_geterror(streams[DATAFD].fd));
1667 /* The header had better be written at this point */
1668 assert(ISSET(status, HEADER_DONE));
1671 * EOF. Stop and return.
1675 if (dumpbytes != (off_t)0) {
1676 dumpsize += (off_t)1;
1678 security_stream_close(streams[DATAFD].fd);
1679 streams[DATAFD].fd = NULL;
1682 * If the mesg fd and index fd has also shut down, then we're done.
1684 if (streams[MESGFD].fd == NULL && streams[INDEXFD].fd == NULL)
1690 * We read something. Add it to the databuf and reschedule for
1693 assert(buf != NULL);
1694 if (databuf_write(db, buf, (size_t)size) < 0) {
1695 int save_errno = errno;
1696 errstr = newvstrallocf(errstr, _("data write: %s"), strerror(save_errno));
1703 * Reset the timeout for future reads
1705 timeout(conf_dtimeout);
1709 * Callback for reads on the index stream
1719 assert(cookie != NULL);
1720 fd = *(int *)cookie;
1723 errstr = newvstrallocf(errstr, _("index read: %s"),
1724 security_stream_geterror(streams[INDEXFD].fd));
1731 * EOF. Stop and return.
1734 security_stream_close(streams[INDEXFD].fd);
1735 streams[INDEXFD].fd = NULL;
1737 * If the mesg fd has also shut down, then we're done.
1739 if ((set_datafd == 0 || streams[DATAFD].fd == NULL) &&
1740 streams[MESGFD].fd == NULL)
1746 assert(buf != NULL);
1749 * We ignore error while writing to the index file.
1751 if (full_write(fd, buf, (size_t)size) < (size_t)size) {
1752 /* Ignore error, but schedule another read. */
1753 if(indexfderror == 0) {
1755 log_add(L_INFO, _("Index corrupted for %s:%s"), hostname, qdiskname);
1761 handle_filter_stderr(
1764 filter_t *filter = cookie;
1769 if (filter->buffer == NULL) {
1770 /* allocate initial buffer */
1771 filter->buffer = g_malloc(2048);
1774 filter->allocated_size = 2048;
1775 } else if (filter->first > 0) {
1776 if (filter->allocated_size - filter->size - filter->first < 1024) {
1777 memmove(filter->buffer, filter->buffer + filter->first,
1781 } else if (filter->allocated_size - filter->size < 1024) {
1782 /* double the size of the buffer */
1783 filter->allocated_size *= 2;
1784 filter->buffer = g_realloc(filter->buffer, filter->allocated_size);
1787 nread = read(filter->fd, filter->buffer + filter->first + filter->size,
1788 filter->allocated_size - filter->first - filter->size - 2);
1791 event_release(filter->event);
1793 if (filter->size > 0 && filter->buffer[filter->first + filter->size - 1] != '\n') {
1794 /* Add a '\n' at end of buffer */
1795 filter->buffer[filter->first + filter->size] = '\n';
1799 filter->size += nread;
1802 /* process all complete lines */
1803 b = filter->buffer + filter->first;
1804 filter->buffer[filter->first + filter->size] = '\0';
1805 while (b < filter->buffer + filter->first + filter->size &&
1806 (p = strchr(b, '\n')) != NULL) {
1808 g_fprintf(errf, _("? %s: %s\n"), filter->name, b);
1809 if (errstr == NULL) {
1810 errstr = stralloc(b);
1813 filter->first += len;
1814 filter->size -= len;
1816 dump_result = max(dump_result, 1);
1820 g_free(filter->buffer);
1826 * Startup a timeout in the event handler. If the arg is 0,
1827 * then remove the timeout.
1829 static event_handle_t *ev_timeout = NULL;
1830 static time_t timeout_time;
1836 timeout_time = time(NULL) + seconds;
1839 * remove a timeout if seconds is 0
1842 if (ev_timeout != NULL) {
1843 event_release(ev_timeout);
1850 * schedule a timeout if it not already scheduled
1852 if (ev_timeout == NULL) {
1853 ev_timeout = event_register((event_id_t)seconds, EV_TIME,
1854 timeout_callback, NULL);
1859 * This is the callback for timeout(). If this is reached, then we
1860 * have a data timeout.
1866 time_t now = time(NULL);
1867 (void)unused; /* Quiet unused parameter warning */
1869 if (ev_timeout != NULL) {
1870 event_release(ev_timeout);
1874 if (timeout_time > now) { /* not a data timeout yet */
1875 ev_timeout = event_register((event_id_t)(timeout_time-now), EV_TIME,
1876 timeout_callback, NULL);
1880 assert(unused == NULL);
1881 errstr = newstralloc(errstr, _("data timeout"));
1887 * This is called when everything needs to shut down so event_loop()
1894 struct cmdargs *cmdargs = NULL;
1896 /* Check if I have a pending ABORT command */
1897 cmdargs = get_pending_cmd();
1899 if (cmdargs->cmd != ABORT) {
1900 error(_("beurk %d"), cmdargs->cmd);
1903 errstr = stralloc(cmdargs->argv[1]);
1904 free_cmdargs(cmdargs);
1907 for (i = 0; i < NSTREAMS; i++) {
1908 if (streams[i].fd != NULL) {
1909 security_stream_close(streams[i].fd);
1910 streams[i].fd = NULL;
1914 aclose(g_databuf->fd);
1920 * Runs compress with the first arg as its stdout. Returns
1921 * 0 on success or negative if error, and it's pid via the second
1922 * argument. The outfd arg is dup2'd to the pipe to the compress
1932 int outpipe[2], rval;
1937 assert(pid != NULL);
1939 /* outpipe[0] is pipe's stdin, outpipe[1] is stdout. */
1940 if (pipe(outpipe) < 0) {
1941 errstr = newvstrallocf(errstr, _("pipe: %s"), strerror(errno));
1945 /* errpipe[0] is pipe's output, outpipe[1] is input. */
1946 if (pipe(errpipe) < 0) {
1947 errstr = newvstrallocf(errstr, _("pipe: %s"), strerror(errno));
1951 if (comptype != COMP_SERVER_CUST) {
1952 g_debug("execute: %s %s", COMPRESS_PATH,
1953 comptype == COMP_BEST ? COMPRESS_BEST_OPT : COMPRESS_FAST_OPT);
1955 g_debug("execute: %s", srvcompprog);
1957 switch (*pid = fork()) {
1959 errstr = newvstrallocf(errstr, _("couldn't fork: %s"), strerror(errno));
1966 rval = dup2(outpipe[1], outfd);
1968 errstr = newvstrallocf(errstr, _("couldn't dup2: %s"), strerror(errno));
1972 filter = g_new0(filter_t, 1);
1973 filter->fd = errpipe[0];
1974 filter->name = name;
1975 filter->buffer = NULL;
1977 filter->allocated_size = 0;
1978 filter->event = event_register((event_id_t)filter->fd, EV_READFD,
1979 handle_filter_stderr, filter);
1984 if (dup2(outpipe[0], 0) < 0) {
1985 error(_("err dup2 in: %s"), strerror(errno));
1988 if (dup2(outfd, 1) == -1) {
1989 error(_("err dup2 out: %s"), strerror(errno));
1992 if (dup2(errpipe[1], 2) == -1) {
1993 error(_("err dup2 err: %s"), strerror(errno));
1996 if (comptype != COMP_SERVER_CUST) {
1997 char *base = stralloc(COMPRESS_PATH);
1998 log_add(L_INFO, "%s pid %ld", basename(base), (long)getpid());
2002 execlp(COMPRESS_PATH, COMPRESS_PATH, ( comptype == COMP_BEST ?
2003 COMPRESS_BEST_OPT : COMPRESS_FAST_OPT), (char *)NULL);
2004 error(_("error: couldn't exec %s: %s"), COMPRESS_PATH, strerror(errno));
2006 } else if (*srvcompprog) {
2007 char *base = stralloc(srvcompprog);
2008 log_add(L_INFO, "%s pid %ld", basename(base), (long)getpid());
2012 execlp(srvcompprog, srvcompprog, (char *)0);
2013 error(_("error: couldn't exec server custom compression '%s'.\n"), srvcompprog);
2022 * Runs encrypt with the first arg as its stdout. Returns
2023 * 0 on success or negative if error, and it's pid via the second
2024 * argument. The outfd arg is dup2'd to the pipe to the encrypt
2031 encrypt_t encrypttype)
2033 int outpipe[2], rval;
2038 assert(pid != NULL);
2040 /* outpipe[0] is pipe's stdin, outpipe[1] is stdout. */
2041 if (pipe(outpipe) < 0) {
2042 errstr = newvstrallocf(errstr, _("pipe: %s"), strerror(errno));
2046 /* errpipe[0] is pipe's output, outpipe[1] is input. */
2047 if (pipe(errpipe) < 0) {
2048 errstr = newvstrallocf(errstr, _("pipe: %s"), strerror(errno));
2052 g_debug("execute: %s", srv_encrypt);
2053 switch (*pid = fork()) {
2055 errstr = newvstrallocf(errstr, _("couldn't fork: %s"), strerror(errno));
2063 rval = dup2(outpipe[1], outfd);
2065 errstr = newvstrallocf(errstr, _("couldn't dup2: %s"), strerror(errno));
2069 filter = g_new0(filter_t, 1);
2070 filter->fd = errpipe[0];
2071 base = g_strdup(srv_encrypt);
2072 filter->name = g_strdup(basename(base));
2074 filter->buffer = NULL;
2076 filter->allocated_size = 0;
2077 filter->event = event_register((event_id_t)filter->fd, EV_READFD,
2078 handle_filter_stderr, filter);
2083 if (dup2(outpipe[0], 0) < 0) {
2084 error(_("err dup2 in: %s"), strerror(errno));
2087 if (dup2(outfd, 1) < 0 ) {
2088 error(_("err dup2 out: %s"), strerror(errno));
2091 if (dup2(errpipe[1], 2) == -1) {
2092 error(_("err dup2 err: %s"), strerror(errno));
2096 base = stralloc(srv_encrypt);
2097 log_add(L_INFO, "%s pid %ld", basename(base), (long)getpid());
2100 if ((encrypttype == ENCRYPT_SERV_CUST) && *srv_encrypt) {
2102 execlp(srv_encrypt, srv_encrypt, (char *)0);
2103 error(_("error: couldn't exec server custom encryption '%s'.\n"), srv_encrypt);
2113 /* -------------------- */
2116 sendbackup_response(
2119 security_handle_t * sech)
2121 int ports[NSTREAMS], *response_error = datap, i;
2126 assert(response_error != NULL);
2127 assert(sech != NULL);
2129 security_close_connection(sech, hostname);
2132 errstr = newvstrallocf(errstr, _("[request failed: %s]"),
2133 security_geterror(sech));
2134 *response_error = 1;
2139 memset(ports, 0, SIZEOF(ports));
2140 if (pkt->type == P_NAK) {
2141 #if defined(PACKET_DEBUG)
2142 g_fprintf(stderr, _("got nak response:\n----\n%s\n----\n\n"), pkt->body);
2145 tok = strtok(pkt->body, " ");
2146 if (tok == NULL || strcmp(tok, "ERROR") != 0)
2149 tok = strtok(NULL, "\n");
2151 errstr = newvstrallocf(errstr, "NAK: %s", tok);
2152 *response_error = 1;
2155 errstr = newvstrallocf(errstr, "request NAK");
2156 *response_error = 2;
2161 if (pkt->type != P_REP) {
2162 errstr = newvstrallocf(errstr, _("received strange packet type %s: %s"),
2163 pkt_type2str(pkt->type), pkt->body);
2164 *response_error = 1;
2168 dbprintf(_("got response:\n----\n%s\n----\n\n"), pkt->body);
2170 for(i = 0; i < NSTREAMS; i++) {
2172 streams[i].fd = NULL;
2176 while((tok = strtok(p, " \n")) != NULL) {
2180 * Error response packets have "ERROR" followed by the error message
2181 * followed by a newline.
2183 if (strcmp(tok, "ERROR") == 0) {
2184 tok = strtok(NULL, "\n");
2186 tok = _("[bogus error packet]");
2187 errstr = newvstrallocf(errstr, "%s", tok);
2188 *response_error = 2;
2193 * Regular packets have CONNECT followed by three streams
2195 if (strcmp(tok, "CONNECT") == 0) {
2198 * Parse the three stream specifiers out of the packet.
2200 for (i = 0; i < NSTREAMS; i++) {
2201 tok = strtok(NULL, " ");
2202 if (tok == NULL || strcmp(tok, streams[i].name) != 0) {
2204 _("CONNECT token is \"%s\": expected \"%s\""),
2205 tok ? tok : "(null)",
2209 tok = strtok(NULL, " \n");
2210 if (tok == NULL || sscanf(tok, "%d", &ports[i]) != 1) {
2212 _("CONNECT %s token is \"%s\": expected a port number"),
2213 streams[i].name, tok ? tok : "(null)");
2221 * OPTIONS [options string] '\n'
2223 if (strcmp(tok, "OPTIONS") == 0) {
2224 tok = strtok(NULL, "\n");
2226 extra = vstrallocf(_("OPTIONS token is missing"));
2230 while((p = strchr(tok, ';')) != NULL) {
2233 if(strncmp_const_skip(tok, "features=", tok, ch) == 0) {
2234 char *u = strchr(tok, ';');
2238 am_release_feature_set(their_features);
2239 if((their_features = am_string_to_feature(tok)) == NULL) {
2240 errstr = newvstrallocf(errstr,
2241 _("OPTIONS: bad features value: %s"),
2253 extra = vstrallocf(_("next token is \"%s\": expected \"CONNECT\", \"ERROR\" or \"OPTIONS\""),
2254 tok ? tok : "(null)");
2258 if (dumper_kencrypt == KENCRYPT_WILL_DO)
2259 dumper_kencrypt = KENCRYPT_YES;
2262 * Connect the streams to their remote ports
2264 for (i = 0; i < NSTREAMS; i++) {
2267 streams[i].fd = security_stream_client(sech, ports[i]);
2268 if (streams[i].fd == NULL) {
2269 errstr = newvstrallocf(errstr,
2270 _("[could not connect %s stream: %s]"),
2272 security_geterror(sech));
2278 * Authenticate the streams
2280 for (i = 0; i < NSTREAMS; i++) {
2281 if (streams[i].fd == NULL)
2283 if (security_stream_auth(streams[i].fd) < 0) {
2284 errstr = newvstrallocf(errstr,
2285 _("[could not authenticate %s stream: %s]"),
2287 security_stream_geterror(streams[i].fd));
2293 * The MESGFD and DATAFD streams are mandatory. If we didn't get
2296 if (streams[MESGFD].fd == NULL || streams[DATAFD].fd == NULL) {
2297 errstr = newvstrallocf(errstr, _("[couldn't open MESG or INDEX streams]"));
2301 /* everything worked */
2302 *response_error = 0;
2306 errstr = newvstrallocf(errstr,
2307 _("[parse of reply message failed: %s]"),
2308 extra ? extra : _("(no additional information)"));
2310 *response_error = 2;
2315 *response_error = 1;
2319 dumper_get_security_conf(
2323 (void)arg; /* Quiet unused parameter warning */
2325 if(!string || !*string)
2328 if(strcmp(string, "krb5principal")==0) {
2329 return(getconf_str(CNF_KRB5PRINCIPAL));
2330 } else if(strcmp(string, "krb5keytab")==0) {
2331 return(getconf_str(CNF_KRB5KEYTAB));
2332 } else if(strcmp(string, "amandad_path")==0) {
2333 return (amandad_path);
2334 } else if(strcmp(string, "client_username")==0) {
2335 return (client_username);
2336 } else if(strcmp(string, "client_port")==0) {
2337 return (client_port);
2338 } else if(strcmp(string, "ssh_keys")==0) {
2340 } else if(strcmp(string, "kencrypt")==0) {
2341 if (dumper_kencrypt == KENCRYPT_YES)
2351 const char *hostname,
2355 const char *dumpdate,
2356 const char *progname,
2357 const char *amandad_path,
2358 const char *client_username,
2359 const char *client_port,
2360 const char *ssh_keys,
2362 const char *options)
2364 char level_string[NUM_STR_SIZE];
2367 const security_driver_t *secdrv;
2368 char *application_api;
2374 (void)disk; /* Quiet unused parameter warning */
2375 (void)amandad_path; /* Quiet unused parameter warning */
2376 (void)client_username; /* Quiet unused parameter warning */
2377 (void)client_port; /* Quiet unused parameter warning */
2378 (void)ssh_keys; /* Quiet unused parameter warning */
2379 (void)auth; /* Quiet unused parameter warning */
2381 has_features = am_has_feature(their_features, fe_req_options_features);
2382 has_hostname = am_has_feature(their_features, fe_req_options_hostname);
2383 has_config = am_has_feature(their_features, fe_req_options_config);
2384 has_device = am_has_feature(their_features, fe_sendbackup_req_device);
2387 * Default to bsd authentication if none specified. This is gross.
2389 * Options really need to be pre-parsed into some sort of structure
2390 * much earlier, and then flattened out again before transmission.
2393 g_snprintf(level_string, SIZEOF(level_string), "%d", level);
2394 if(strcmp(progname, "DUMP") == 0
2395 || strcmp(progname, "GNUTAR") == 0) {
2396 application_api = "";
2398 application_api = "BACKUP ";
2400 req = vstralloc("SERVICE sendbackup\n",
2402 has_features ? "features=" : "",
2403 has_features ? our_feature_string : "",
2404 has_features ? ";" : "",
2405 has_hostname ? "hostname=" : "",
2406 has_hostname ? hostname : "",
2407 has_hostname ? ";" : "",
2408 has_config ? "config=" : "",
2409 has_config ? get_config_name() : "",
2410 has_config ? ";" : "",
2415 if (am_has_feature(their_features, fe_req_xml)) {
2418 vstrextend(&p, "<dle>\n", NULL);
2419 if (*application_api != '\0') {
2420 vstrextend(&p, " <program>APPLICATION</program>\n", NULL);
2422 vstrextend(&p, " <program>", progname, "</program>\n", NULL);
2424 vstrextend(&p, " ", b64disk, "\n", NULL);
2425 if (device && has_device) {
2426 vstrextend(&p, " ", b64device, "\n",
2429 vstrextend(&p, " <level>", level_string, "</level>\n", NULL);
2430 vstrextend(&p, options+1, "</dle>\n", NULL);
2431 pclean = clean_dle_str_for_client(p, their_features);
2432 vstrextend(&req, pclean, NULL);
2435 } else if (*application_api != '\0') {
2436 errstr = newvstrallocf(errstr,
2437 _("[does not support application-api]"));
2447 " ", device && has_device ? device : "",
2450 " OPTIONS ", options,
2455 dbprintf(_("send request:\n----\n%s\n----\n\n"), req);
2456 secdrv = security_getdriver(auth);
2457 if (secdrv == NULL) {
2458 errstr = newvstrallocf(errstr,
2459 _("[could not find security driver '%s']"), auth);
2464 protocol_sendreq(hostname, secdrv, dumper_get_security_conf, req,
2465 STARTUP_TIMEOUT, sendbackup_response, &response_error);
2470 return (response_error);