*/
#include "amanda.h"
+#include "match.h"
#include "sendbackup.h"
#include "clock.h"
#include "pipespawn.h"
#include "amfeatures.h"
-#include "amandad.h"
#include "arglist.h"
#include "getfsent.h"
-#include "version.h"
#include "conffile.h"
+#include "amandates.h"
+#include "stream.h"
#define sendbackup_debug(i, ...) do { \
if ((i) <= debug_sendbackup) { \
pid_t tarpid = (pid_t)-1;
pid_t encpid = (pid_t)-1;
pid_t indexpid = (pid_t)-1;
+pid_t application_api_pid = (pid_t)-1;
char *errorstr = NULL;
int datafd;
int mesgfd;
int indexfd;
-option_t *options;
g_option_t *g_options = NULL;
long dump_size = -1;
backup_program_t *program = NULL;
+dle_t *gdle = NULL;
static am_feature_t *our_features = NULL;
static char *our_feature_string = NULL;
/* local functions */
int main(int argc, char **argv);
-char *optionstr(option_t *options);
char *childstr(pid_t pid);
-int check_status(pid_t pid, amwait_t w);
+int check_status(pid_t pid, amwait_t w, int mesgfd);
pid_t pipefork(void (*func)(void), char *fname, int *stdinfd,
int stdoutfd, int stderrfd);
-void parse_backup_messages(int mesgin);
+int check_result(int mesgfd);
+void parse_backup_messages(dle_t *dle, int mesgin);
static void process_dumpline(char *str);
static void save_fd(int *, int);
-void backup_api_info_tapeheader(int mesgfd, char *prog, option_t *options);
+void application_api_info_tapeheader(int mesgfd, char *prog, dle_t *dle);
-double the_num(char *str, int pos);
+int fdprintf(int fd, char *format, ...) G_GNUC_PRINTF(2, 3);
-
-char *
-optionstr(
- option_t * options)
+int
+fdprintf(
+ int fd,
+ char *format,
+ ...)
{
- static char *optstr = NULL;
- char *compress_opt;
- char *encrypt_opt;
- char *decrypt_opt;
- char *record_opt = "";
- char *index_opt = "";
- char *auth_opt;
- char *exclude_file_opt;
- char *exclude_list_opt;
- char *exc = NULL;
- sle_t *excl;
-
- if(options->compress == COMP_BEST)
- compress_opt = stralloc("compress-best;");
- else if(options->compress == COMP_FAST)
- compress_opt = stralloc("compress-fast;");
- else if(options->compress == COMP_SERVER_BEST)
- compress_opt = stralloc("srvcomp-best;");
- else if(options->compress == COMP_SERVER_FAST)
- compress_opt = stralloc("srvcomp-fast;");
- else if(options->compress == COMP_SERVER_CUST)
- compress_opt = vstralloc("srvcomp-cust=", options->srvcompprog, ";", NULL);
- else if(options->compress == COMP_CUST)
- compress_opt = vstralloc("comp-cust=", options->clntcompprog, ";", NULL);
- else
- compress_opt = stralloc("");
-
- if(options->encrypt == ENCRYPT_CUST) {
- encrypt_opt = vstralloc("encrypt-cust=", options->clnt_encrypt, ";", NULL);
- if (options->clnt_decrypt_opt)
- decrypt_opt = vstralloc("client-decrypt-option=", options->clnt_decrypt_opt, ";", NULL);
- else
- decrypt_opt = stralloc("");
- }
- else if(options->encrypt == ENCRYPT_SERV_CUST) {
- encrypt_opt = vstralloc("encrypt-serv-cust=", options->srv_encrypt, ";", NULL);
- if(options->srv_decrypt_opt)
- decrypt_opt = vstralloc("server-decrypt-option=", options->srv_decrypt_opt, ";", NULL);
- else
- decrypt_opt = stralloc("");
- }
- else {
- encrypt_opt = stralloc("");
- decrypt_opt = stralloc("");
- }
+ va_list argp;
+ char *s;
+ int r;
- if(options->no_record) record_opt = "no-record;";
- if(options->auth) auth_opt = vstralloc("auth=", options->auth, ";", NULL);
- else auth_opt = stralloc("");
- if(options->createindex) index_opt = "index;";
+ arglist_start(argp, format);
+ s = g_strdup_vprintf(format, argp);
+ arglist_end(argp);
- exclude_file_opt = stralloc("");
- if(options->exclude_file) {
- for(excl = options->exclude_file->first; excl != NULL; excl=excl->next){
- exc = newvstralloc(exc, "exclude-file=", excl->name, ";", NULL);
- strappend(exclude_file_opt, exc);
- }
- }
- exclude_list_opt = stralloc("");
- if(options->exclude_list) {
- for(excl = options->exclude_list->first; excl != NULL; excl=excl->next){
- exc = newvstralloc(exc, "exclude-list=", excl->name, ";", NULL);
- strappend(exclude_list_opt, exc);
- }
- }
- amfree(exc);
- optstr = newvstralloc(optstr,
- compress_opt,
- encrypt_opt,
- decrypt_opt,
- record_opt,
- index_opt,
- auth_opt,
- exclude_file_opt,
- exclude_list_opt,
- NULL);
- amfree(compress_opt);
- amfree(encrypt_opt);
- amfree(decrypt_opt);
- amfree(auth_opt);
- amfree(exclude_file_opt);
- amfree(exclude_list_opt);
- return optstr;
+ r = full_write(fd, s, strlen(s));
+ amfree(s);
+ return r;
}
-
int
main(
int argc,
int interactive = 0;
int level = 0;
int mesgpipe[2];
- char *prog, *dumpdate, *stroptions;
- int program_is_backup_api;
- char *disk = NULL;
+ dle_t *dle = NULL;
+ char *dumpdate, *stroptions;
char *qdisk = NULL;
- char *amdevice = NULL;
char *qamdevice = NULL;
char *line = NULL;
char *err_extra = NULL;
char *s;
int i;
int ch;
- FILE *toolin;
- int status;
+ GSList *errlist;
+ FILE *mesgstream;
+ am_level_t *alevel;
- /* initialize */
+ if (argc > 1 && argv && argv[1] && g_str_equal(argv[1], "--version")) {
+ printf("sendbackup-%s\n", VERSION);
+ return (0);
+ }
+ /* initialize */
/*
* Configure program for internationalization:
* 1) Only set the message locale for now.
textdomain("amanda");
safe_fd(DATA_FD_OFFSET, DATA_FD_COUNT*2);
+ openbsd_fd_inform();
safe_cd();
interactive = 0;
}
- erroutput_type = (ERR_INTERACTIVE|ERR_SYSLOG);
+ add_amanda_log_handler(amanda_log_stderr);
+ add_amanda_log_handler(amanda_log_syslog);
dbopen(DBG_SUBDIR_CLIENT);
startclock();
- dbprintf(_("Version %s\n"), version());
+ dbprintf(_("Version %s\n"), VERSION);
if(argc > 2 && strcmp(argv[1], "amandad") == 0) {
amandad_auth = stralloc(argv[2]);
our_feature_string = am_feature_to_string(our_features);
config_init(CONFIG_INIT_CLIENT, NULL);
+ /* (check for config errors comes later) */
check_running_as(RUNNING_AS_CLIENT_LOGIN);
fflush(stderr);
}
- prog = NULL;
- disk = NULL;
qdisk = NULL;
- amdevice = NULL;
dumpdate = NULL;
stroptions = NULL;
- program_is_backup_api=0;
for(; (line = agets(stdin)) != NULL; free(line)) {
if (line[0] == '\0')
config_init(CONFIG_INIT_CLIENT | CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_OVERLAY,
g_options->config);
- dbrename(config_name, DBG_SUBDIR_CLIENT);
+ dbrename(get_config_name(), DBG_SUBDIR_CLIENT);
+ }
+
+ /* check for any config errors now */
+ if (config_errors(&errlist) >= CFGERR_ERRORS) {
+ char *errstr = config_errors_to_error_string(errlist);
+ g_printf("%s\n", errstr);
+ dbclose();
+ return 1;
+ }
+
+ if (am_has_feature(g_options->features, fe_req_xml)) {
+ break;
}
continue;
}
- if (prog != NULL) {
+ if (dle && dle->program != NULL) {
err_extra = _("multiple requests");
goto err;
}
dbprintf(_(" sendbackup req: <%s>\n"), line);
+ dle = alloc_dle();
+
s = line;
ch = *s++;
err_extra = _("no program name");
goto err; /* no program name */
}
- prog = s - 1;
+ dle->program = s - 1;
skip_non_whitespace(s, ch);
s[-1] = '\0';
- if(strcmp(prog,"BACKUP")==0) {
- program_is_backup_api=1;
- skip_whitespace(s, ch); /* find dumper name */
- if (ch == '\0') {
- goto err; /* no program */
- }
- prog = s - 1;
- skip_non_whitespace(s, ch);
- s[-1] = '\0';
- }
- prog = stralloc(prog);
+ if (strcmp(dle->program, "APPLICATION")==0) {
+ dle->program_is_application_api=1;
+ skip_whitespace(s, ch); /* find dumper name */
+ if (ch == '\0') {
+ goto err; /* no program */
+ }
+ dle->program = s - 1;
+ skip_non_whitespace(s, ch);
+ s[-1] = '\0';
+ }
+ dle->program = stralloc(dle->program);
skip_whitespace(s, ch); /* find the disk name */
if(ch == '\0') {
goto err; /* no disk name */
}
- amfree(disk);
amfree(qdisk);
qdisk = s - 1;
ch = *qdisk;
skip_quoted_string(s, ch);
s[-1] = '\0';
qdisk = stralloc(qdisk);
- disk = unquote_string(qdisk);
+ dle->disk = unquote_string(qdisk);
skip_whitespace(s, ch); /* find the device or level */
if (ch == '\0') {
}
if(!isdigit((int)s[-1])) {
- amfree(amdevice);
amfree(qamdevice);
qamdevice = s - 1;
ch = *qamdevice;
skip_quoted_string(s, ch);
s[-1] = '\0';
qamdevice = stralloc(qamdevice);
- amdevice = unquote_string(qamdevice);
+ dle->device = unquote_string(qamdevice);
skip_whitespace(s, ch); /* find level number */
}
else {
- amdevice = stralloc(disk);
+ dle->device = stralloc(dle->disk);
qamdevice = stralloc(qdisk);
}
/* find the level number */
goto err; /* bad level */
}
skip_integer(s, ch);
+ alevel = g_new0(am_level_t, 1);
+ alevel->level = level;
+ dle->levellist = g_slist_append(dle->levellist, alevel);
skip_whitespace(s, ch); /* find the dump date */
if(ch == '\0') {
}
amfree(line);
if (g_options == NULL) {
- printf(_("ERROR [Missing OPTIONS line in sendbackup input]\n"));
+ g_printf(_("ERROR [Missing OPTIONS line in sendbackup input]\n"));
error(_("Missing OPTIONS line in sendbackup input\n"));
/*NOTREACHED*/
}
- if (prog == NULL ||
- disk == NULL ||
- amdevice == NULL ||
- dumpdate == NULL ||
- stroptions == NULL) {
+ if (am_has_feature(g_options->features, fe_req_xml)) {
+ char *errmsg = NULL;
+
+ dle = amxml_parse_node_FILE(stdin, &errmsg);
+ if (errmsg) {
+ err_extra = errmsg;
+ goto err;
+ }
+ if (!dle) {
+ err_extra = _("One DLE required");
+ goto err;
+ } else if (dle->next) {
+ err_extra = _("Only one DLE allowed");
+ goto err;
+ }
+
+ qdisk = quote_string(dle->disk);
+ if (dle->device == NULL)
+ dle->device = stralloc(dle->disk);
+ qamdevice = quote_string(dle->device);
+ dumpdate = stralloc("NODATE");
+ stroptions = stralloc("");
+ } else {
+ parse_options(stroptions, dle, g_options->features, 0);
+ }
+ gdle = dle;
+
+ if (dle->program == NULL ||
+ dle->disk == NULL ||
+ dle->device == NULL ||
+ dle->levellist == NULL ||
+ dumpdate == NULL) {
err_extra = _("no valid sendbackup request");
goto err;
}
-
- dbprintf(_(" Parsed request as: program `%s'\n"), prog);
+
+ if (g_slist_length(dle->levellist) != 1) {
+ err_extra = _("Too many level");
+ goto err;
+ }
+
+ alevel = (am_level_t *)dle->levellist->data;
+ level = alevel->level;
+ dbprintf(_(" Parsed request as: program `%s'\n"), dle->program);
dbprintf(_(" disk `%s'\n"), qdisk);
dbprintf(_(" device `%s'\n"), qamdevice);
dbprintf(_(" level %d\n"), level);
dbprintf(_(" since %s\n"), dumpdate);
dbprintf(_(" options `%s'\n"), stroptions);
+ dbprintf(_(" datapath `%s'\n"),
+ data_path_to_string(dle->data_path));
- if(program_is_backup_api==1) {
- /* check that the backup_api exist */
- }
- else {
+ if (dle->program_is_application_api==1) {
+ /* check that the application_api exist */
+ } else {
for(i = 0; programs[i]; i++) {
- if (strcmp(programs[i]->name, prog) == 0) {
+ if (strcmp(programs[i]->name, dle->program) == 0) {
break;
}
}
if (programs[i] == NULL) {
- dbprintf(_("ERROR [%s: unknown program %s]\n"), get_pname(), prog);
- error(_("ERROR [%s: unknown program %s]"), get_pname(), prog);
+ dbprintf(_("ERROR [%s: unknown program %s]\n"), get_pname(),
+ dle->program);
+ error(_("ERROR [%s: unknown program %s]"), get_pname(),
+ dle->program);
/*NOTREACHED*/
}
program = programs[i];
}
- options = parse_options(stroptions, disk, amdevice, g_options->features, 0);
-
if(!interactive) {
datafd = DATA_FD_OFFSET + 0;
mesgfd = DATA_FD_OFFSET + 2;
indexfd = DATA_FD_OFFSET + 4;
}
- if (!options->createindex)
+ if (!dle->create_index)
indexfd = -1;
- if(options->auth && amandad_auth) {
- if(strcasecmp(options->auth, amandad_auth) != 0) {
+ if (dle->auth && amandad_auth) {
+ if(strcasecmp(dle->auth, amandad_auth) != 0) {
g_printf(_("ERROR [client configured for auth=%s while server requested '%s']\n"),
- amandad_auth, options->auth);
+ amandad_auth, dle->auth);
exit(-1);
}
}
- if (options->kencrypt) {
+ if (dle->kencrypt) {
g_printf("KENCRYPT\n");
}
if(am_has_feature(g_options->features, fe_rep_options_hostname)) {
g_printf("hostname=%s;", g_options->hostname);
}
- if(am_has_feature(g_options->features, fe_rep_options_sendbackup_options)) {
- g_printf("%s", optionstr(options));
+ if (!am_has_feature(g_options->features, fe_rep_options_features) &&
+ !am_has_feature(g_options->features, fe_rep_options_hostname)) {
+ g_printf(";");
}
g_printf("\n");
fflush(stdout);
}
if(!interactive) {
- if(datafd == -1 || mesgfd == -1 || (options->createindex && indexfd == -1)) {
+ if(datafd == -1 || mesgfd == -1 || (dle->create_index && indexfd == -1)) {
dbclose();
exit(1);
}
}
- if(program_is_backup_api==1) {
- pid_t backup_api_pid;
- int i, j;
+ if (merge_dles_properties(dle, 1) == 0) {
+ g_debug("merge_dles_properties failed");
+ exit(1);
+ }
+ mesgstream = fdopen(mesgfd,"w");
+ run_client_scripts(EXECUTE_ON_PRE_DLE_BACKUP, g_options, dle, mesgstream);
+ fflush(mesgstream);
+
+ if (dle->program_is_application_api==1) {
+ guint j;
char *cmd=NULL;
- char *argvchild[20];
+ GPtrArray *argv_ptr;
char levelstr[20];
- int property_pipe[2];
backup_support_option_t *bsu;
-
- if (pipe(property_pipe) < 0) {
- error(_("Can't create pipe: %s"),strerror(errno));
- /*NOTREACHED*/
+ char *compopt = NULL;
+ char *encryptopt = skip_argument;
+ int compout, dumpout;
+ GSList *scriptlist;
+ script_t *script;
+ time_t cur_dumptime;
+ int result;
+ GPtrArray *errarray;
+ int errfd[2];
+ FILE *dumperr;
+
+ /* apply client-side encryption here */
+ if ( dle->encrypt == ENCRYPT_CUST ) {
+ encpid = pipespawn(dle->clnt_encrypt, STDIN_PIPE, 0,
+ &compout, &datafd, &mesgfd,
+ dle->clnt_encrypt, encryptopt, NULL);
+ dbprintf(_("encrypt: pid %ld: %s\n"), (long)encpid, dle->clnt_encrypt);
+ } else {
+ compout = datafd;
+ encpid = -1;
}
- bsu = backup_support_option(prog, g_options, disk, amdevice);
- switch(backup_api_pid=fork()) {
- case 0:
- aclose(property_pipe[1]);
- if(dup2(property_pipe[0], 0) == -1) {
- error(_("Can't dup2: %s"),strerror(errno));
- /*NOTREACHED*/
+ /* now do the client-side compression */
+ if(dle->compress == COMP_FAST || dle->compress == COMP_BEST) {
+ compopt = skip_argument;
+#if defined(COMPRESS_BEST_OPT) && defined(COMPRESS_FAST_OPT)
+ if(dle->compress == COMP_BEST) {
+ compopt = COMPRESS_BEST_OPT;
+ } else {
+ compopt = COMPRESS_FAST_OPT;
}
- if(dup2(datafd, 1) == -1) {
- error(_("Can't dup2: %s"),strerror(errno));
- /*NOTREACHED*/
+#endif
+ comppid = pipespawn(COMPRESS_PATH, STDIN_PIPE, 0,
+ &dumpout, &compout, &mesgfd,
+ COMPRESS_PATH, compopt, NULL);
+ if(compopt != skip_argument) {
+ dbprintf(_("compress pid %ld: %s %s\n"),
+ (long)comppid, COMPRESS_PATH, compopt);
+ } else {
+ dbprintf(_("compress pid %ld: %s\n"), (long)comppid, COMPRESS_PATH);
}
- if(dup2(mesgfd, 2) == -1) {
- error(_("Can't dup2: %s"),strerror(errno));
- /*NOTREACHED*/
+ } else if (dle->compress == COMP_CUST) {
+ compopt = skip_argument;
+ comppid = pipespawn(dle->compprog, STDIN_PIPE, 0,
+ &dumpout, &compout, &mesgfd,
+ dle->compprog, compopt, NULL);
+ if(compopt != skip_argument) {
+ dbprintf(_("pid %ld: %s %s\n"),
+ (long)comppid, dle->compprog, compopt);
+ } else {
+ dbprintf(_("pid %ld: %s\n"), (long)comppid, dle->compprog);
}
- if(indexfd != 0) {
- if(dup2(indexfd, 3) == -1) {
- error(_("Can't dup2: %s"),strerror(errno));
- /*NOTREACHED*/
+ } else {
+ dumpout = compout;
+ comppid = -1;
+ }
+
+ cur_dumptime = time(0);
+ bsu = backup_support_option(dle->program, g_options, dle->disk,
+ dle->device, &errarray);
+ if (!bsu) {
+ char *errmsg;
+ char *qerrmsg;
+ guint i;
+ for (i=0; i < errarray->len; i++) {
+ errmsg = g_ptr_array_index(errarray, i);
+ qerrmsg = quote_string(errmsg);
+ fdprintf(mesgfd,
+ _("sendbackup: error [Application '%s': %s]\n"),
+ dle->program, errmsg);
+ dbprintf("aa: %s\n",qerrmsg);
+ amfree(qerrmsg);
+ }
+ if (i == 0) { /* no errarray */
+ errmsg = vstrallocf(_("Can't execute application '%s'"),
+ dle->program);
+ qerrmsg = quote_string(errmsg);
+ fdprintf(mesgfd, _("sendbackup: error [%s]\n"), errmsg);
+ dbprintf(_("ERROR %s\n"), qerrmsg);
+ amfree(qerrmsg);
+ amfree(errmsg);
+ }
+ return 0;
+ }
+
+ if (pipe(errfd) < 0) {
+ char *errmsg;
+ char *qerrmsg;
+ errmsg = vstrallocf(_("Application '%s': can't create pipe"),
+ dle->program);
+ qerrmsg = quote_string(errmsg);
+ fdprintf(mesgfd, _("sendbackup: error [%s]\n"), errmsg);
+ dbprintf(_("ERROR %s\n"), qerrmsg);
+ amfree(qerrmsg);
+ amfree(errmsg);
+ return 0;
+ }
+
+ switch(application_api_pid=fork()) {
+ case 0:
+ application_api_info_tapeheader(mesgfd, dle->program, dle);
+
+ /* find directt-tcp address from indirect direct-tcp */
+ if (dle->data_path == DATA_PATH_DIRECTTCP &&
+ bsu->data_path_set & DATA_PATH_DIRECTTCP &&
+ strncmp(dle->directtcp_list->data, "255.255.255.255:", 16) == 0) {
+ char *indirect_tcp;
+ char *str_port;
+ in_port_t port;
+ int fd;
+ char buffer[32770];
+ int size;
+ char *s, *s1;
+
+ indirect_tcp = g_strdup(dle->directtcp_list->data);
+ g_slist_free(dle->directtcp_list);
+ dle->directtcp_list = NULL;
+ str_port = strchr(indirect_tcp, ':');
+ str_port++;
+ port = atoi(str_port);
+ fd = stream_client("localhost", port, 32768, 32768, NULL, 0);
+ if (fd <= 0) {
+ g_debug("Failed to connect to indirect-direct-tcp port: %s",
+ strerror(errno));
+ exit(1);
}
- fcntl(indexfd, F_SETFD, 0);
- fcntl(3, F_SETFD, 0);
- safe_fd(3, 1);
- } else {
- safe_fd(-1, 0);
+ size = full_read(fd, buffer, 32768);
+ if (size <= 0) {
+ g_debug("Failed to read from indirect-direct-tcp port: %s",
+ strerror(errno));
+ exit(1);
+ }
+ buffer[size++] = ' ';
+ buffer[size] = '\0';
+ s1 = buffer;
+ while ((s = strchr(s1, ' ')) != NULL) {
+ *s++ = '\0';
+ dle->directtcp_list = g_slist_append(dle->directtcp_list, g_strdup(s1));
+ s1 = s;
+ }
+ amfree(indirect_tcp);
}
- cmd = vstralloc(DUMPER_DIR, "/", prog, NULL);
- i=0;
- argvchild[i++] = prog;
- argvchild[i++] = "backup";
+
+ argv_ptr = g_ptr_array_new();
+ cmd = vstralloc(APPLICATION_DIR, "/", dle->program, NULL);
+ g_ptr_array_add(argv_ptr, stralloc(dle->program));
+ g_ptr_array_add(argv_ptr, stralloc("backup"));
if (bsu->message_line == 1) {
- argvchild[i++] = "--message";
- argvchild[i++] = "line";
+ g_ptr_array_add(argv_ptr, stralloc("--message"));
+ g_ptr_array_add(argv_ptr, stralloc("line"));
}
if (g_options->config && bsu->config == 1) {
- argvchild[i++] = "--config";
- argvchild[i++] = g_options->config;
+ g_ptr_array_add(argv_ptr, stralloc("--config"));
+ g_ptr_array_add(argv_ptr, stralloc(g_options->config));
}
if (g_options->hostname && bsu->host == 1) {
- argvchild[i++] = "--host";
- argvchild[i++] = g_options->hostname;
+ g_ptr_array_add(argv_ptr, stralloc("--host"));
+ g_ptr_array_add(argv_ptr, stralloc(g_options->hostname));
}
- if (disk && bsu->disk == 1) {
- argvchild[i++] = "--disk";
- argvchild[i++] = disk;
+ if (dle->disk && bsu->disk == 1) {
+ g_ptr_array_add(argv_ptr, stralloc("--disk"));
+ g_ptr_array_add(argv_ptr, stralloc(dle->disk));
}
- argvchild[i++] = "--device";
- argvchild[i++] = amdevice;
+ g_ptr_array_add(argv_ptr, stralloc("--device"));
+ g_ptr_array_add(argv_ptr, stralloc(dle->device));
if (level <= bsu->max_level) {
- argvchild[i++] = "--level";
+ g_ptr_array_add(argv_ptr, stralloc("--level"));
g_snprintf(levelstr,19,"%d",level);
- argvchild[i++] = levelstr;
+ g_ptr_array_add(argv_ptr, stralloc(levelstr));
}
- if (indexfd != 0 && bsu->index_line == 1) {
- argvchild[i++] = "--index";
- argvchild[i++] = "line";
+ if (indexfd != -1 && bsu->index_line == 1) {
+ g_ptr_array_add(argv_ptr, stralloc("--index"));
+ g_ptr_array_add(argv_ptr, stralloc("line"));
}
- if (!options->no_record && bsu->record == 1) {
- argvchild[i++] = "--record";
+ if (dle->record && bsu->record == 1) {
+ g_ptr_array_add(argv_ptr, stralloc("--record"));
}
- argvchild[i] = NULL;
- dbprintf(_("%s: running \"%s"), get_pname(), cmd);
- for(j=1;j<i;j++) dbprintf(" %s",argvchild[j]);
+ application_property_add_to_argv(argv_ptr, dle, bsu,
+ g_options->features);
+
+ for (scriptlist = dle->scriptlist; scriptlist != NULL;
+ scriptlist = scriptlist->next) {
+ script = (script_t *)scriptlist->data;
+ if (script->result && script->result->proplist) {
+ property_add_to_argv(argv_ptr, script->result->proplist);
+ }
+ }
+
+ g_ptr_array_add(argv_ptr, NULL);
+ dbprintf(_("%s: running \"%s\n"), get_pname(), cmd);
+ for (j = 1; j < argv_ptr->len - 1; j++)
+ dbprintf(" %s\n", (char *)g_ptr_array_index(argv_ptr,j));
dbprintf(_("\"\n"));
- backup_api_info_tapeheader(mesgfd, prog, options);
- execve(cmd, argvchild, safe_env());
+ if(dup2(dumpout, 1) == -1) {
+ error(_("Can't dup2: %s"),strerror(errno));
+ /*NOTREACHED*/
+ }
+ if (dup2(errfd[1], 2) == -1) {
+ error(_("Can't dup2: %s"),strerror(errno));
+ /*NOTREACHED*/
+ }
+ if(dup2(mesgfd, 3) == -1) {
+ error(_("Can't dup2: %s"),strerror(errno));
+ /*NOTREACHED*/
+ }
+ if(indexfd > 0) {
+ if(dup2(indexfd, 4) == -1) {
+ error(_("Can't dup2: %s"),strerror(errno));
+ /*NOTREACHED*/
+ }
+ fcntl(indexfd, F_SETFD, 0);
+ }
+ if (indexfd != 0) {
+ safe_fd(3, 2);
+ } else {
+ safe_fd(3, 1);
+ }
+ execve(cmd, (char **)argv_ptr->pdata, safe_env());
exit(1);
break;
default:
- aclose(property_pipe[0]);
- toolin = fdopen(property_pipe[1],"w");
- if (!toolin) {
- error(_("Can't fdopen: %s"), strerror(errno));
- /*NOTREACHED*/
- }
- output_tool_property(toolin, options);
- fflush(toolin);
- fclose(toolin);
break;
case -1:
error(_("%s: fork returned: %s"), get_pname(), strerror(errno));
}
- amfree(bsu);
- if (waitpid(backup_api_pid, &status, 0) < 0) {
- if (!WIFEXITED(status)) {
- dbprintf(_("Tool exited with signal %d"), WTERMSIG(status));
- } else if (WEXITSTATUS(status) != 0) {
- dbprintf(_("Tool exited with status %d"), WEXITSTATUS(status));
+
+ close(errfd[1]);
+ dumperr = fdopen(errfd[0],"r");
+ if (!dumperr) {
+ error(_("Can't fdopen: %s"), strerror(errno));
+ /*NOTREACHED*/
+ }
+
+ result = 0;
+ while ((line = agets(dumperr)) != NULL) {
+ if (strlen(line) > 0) {
+ fdprintf(mesgfd, "sendbackup: error [%s]\n", line);
+ dbprintf("error: %s\n", line);
+ result = 1;
+ }
+ amfree(line);
+ }
+
+ result |= check_result(mesgfd);
+ if (result == 0) {
+ char *amandates_file;
+
+ amandates_file = getconf_str(CNF_AMANDATES);
+ if(start_amandates(amandates_file, 1)) {
+ amandates_updateone(dle->disk, level, cur_dumptime);
+ finish_amandates();
+ free_amandates();
} else {
- dbprintf(_("waitpid returned negative value"));
+ if (GPOINTER_TO_INT(dle->estimatelist->data) == ES_CALCSIZE &&
+ bsu->calcsize) {
+ error(_("error [opening %s for writing: %s]"),
+ amandates_file, strerror(errno));
+ } else {
+ g_debug(_("non-fatal error opening '%s' for writing: %s]"),
+ amandates_file, strerror(errno));
+ }
}
}
- }
- else {
+ amfree(bsu);
+ } else {
if(!interactive) {
/* redirect stderr */
if(dup2(mesgfd, 2) == -1) {
error(_("error [opening mesg pipe: %s]"), s);
}
- program->start_backup(g_options->hostname, disk, amdevice, level,
- dumpdate, datafd, mesgpipe[1], indexfd);
+ program->start_backup(dle, g_options->hostname,
+ datafd, mesgpipe[1], indexfd);
dbprintf(_("Started backup\n"));
- parse_backup_messages(mesgpipe[0]);
+ parse_backup_messages(dle, mesgpipe[0]);
dbprintf(_("Parsed backup messages\n"));
}
- amfree(prog);
- amfree(disk);
+ run_client_scripts(EXECUTE_ON_POST_DLE_BACKUP, g_options, dle, mesgstream);
+ fflush(mesgstream);
+
amfree(qdisk);
- amfree(amdevice);
amfree(qamdevice);
amfree(dumpdate);
amfree(stroptions);
return 0;
err:
- g_printf(_("FORMAT ERROR IN REQUEST PACKET\n"));
- dbprintf(_("REQ packet is bogus%s%s\n"),
- err_extra ? ": " : "",
- err_extra ? err_extra : "");
+ if (err_extra) {
+ g_printf(_("ERROR FORMAT ERROR IN REQUEST PACKET '%s'\n"), err_extra);
+ dbprintf(_("REQ packet is bogus: %s\n"), err_extra);
+ } else {
+ g_printf(_("ERROR FORMAT ERROR IN REQUEST PACKET\n"));
+ dbprintf(_("REQ packet is bogus\n"));
+ }
+
+ amfree(qdisk);
+ amfree(qamdevice);
+ amfree(dumpdate);
+ amfree(stroptions);
+ amfree(our_feature_string);
+
dbclose();
return 1;
}
if(pid == comppid) return "compress";
if(pid == encpid) return "encrypt";
if(pid == indexpid) return "index";
+ if(pid == application_api_pid) {
+ if (!gdle) {
+ dbprintf("gdle == NULL\n");
+ return "gdle == NULL";
+ }
+ return gdle->program;
+ }
return "unknown";
}
int
check_status(
pid_t pid,
- amwait_t w)
+ amwait_t w,
+ int mesgfd)
{
char *thiserr = NULL;
char *str, *strX;
* but the failure is noted.
*/
if(ret != 0) {
- g_fprintf(stderr, _("? index %s returned %d\n"), str, ret);
+ fdprintf(mesgfd, _("? index %s returned %d\n"), str, ret);
rc = 0;
}
indexpid = -1;
- strX = "index ";
+ strX = "index";
} else if(pid == comppid) {
/*
* compress returns 2 sometimes, but it is ok.
}
#endif
comppid = -1;
- strX = "compress ";
+ strX = "compress";
} else if(pid == dumppid && tarpid == -1) {
/*
* Ultrix dump returns 1 sometimes, but it is ok.
}
#endif
dumppid = -1;
- strX = "dump ";
+ strX = "dump";
} else if(pid == tarpid) {
if (ret == 1) {
rc = 0;
}
#endif
dumppid = tarpid = -1;
- strX = "dump ";
+ strX = "dump";
+ } else if(pid == application_api_pid) {
+ strX = "Application";
} else {
- strX = "unknown ";
+ strX = "unknown";
}
if(rc == 0) {
thiserr = vstrallocf(_("%s (%d) %s returned %d"), strX, (int)pid, str, ret);
}
+ fdprintf(mesgfd, "? %s\n", thiserr);
+
if(errorstr) {
errorstr = newvstrallocf(errorstr, "%s, %s", errorstr, thiserr);
amfree(thiserr);
*Send header info to the message file.
*/
void
-info_tapeheader(void)
+info_tapeheader(
+ dle_t *dle)
{
g_fprintf(stderr, "%s: info BACKUP=%s\n", get_pname(), program->backup_name);
g_fprintf(stderr, "%s: info RECOVER_CMD=", get_pname());
- if (options->compress == COMP_FAST || options->compress == COMP_BEST)
+ if (dle->compress == COMP_FAST || dle->compress == COMP_BEST)
g_fprintf(stderr, "%s %s |", UNCOMPRESS_PATH,
#ifdef UNCOMPRESS_OPT
UNCOMPRESS_OPT
g_fprintf(stderr, "%s -xpGf - ...\n", program->restore_name);
- if (options->compress == COMP_FAST || options->compress == COMP_BEST)
+ if (dle->compress == COMP_FAST || dle->compress == COMP_BEST)
g_fprintf(stderr, "%s: info COMPRESS_SUFFIX=%s\n",
get_pname(), COMPRESS_SUFFIX);
}
void
-backup_api_info_tapeheader(
+application_api_info_tapeheader(
int mesgfd,
char *prog,
- option_t *options)
+ dle_t *dle)
{
char line[1024];
- g_snprintf(line, 1024, "%s: info BACKUP=DUMPER\n", get_pname());
- if (fullwrite(mesgfd, line, strlen(line)) != (ssize_t)strlen(line)) {
+ g_snprintf(line, 1024, "%s: info BACKUP=APPLICATION\n", get_pname());
+ if (full_write(mesgfd, line, strlen(line)) != strlen(line)) {
dbprintf(_("error writing to mesgfd socket: %s"), strerror(errno));
return;
}
- g_snprintf(line, 1024, "%s: info DUMPER=%s\n", get_pname(), prog);
- if (fullwrite(mesgfd, line, strlen(line)) != (ssize_t)strlen(line)) {
+ g_snprintf(line, 1024, "%s: info APPLICATION=%s\n", get_pname(), prog);
+ if (full_write(mesgfd, line, strlen(line)) != strlen(line)) {
dbprintf(_("error writing to mesgfd socket: %s"), strerror(errno));
return;
}
g_snprintf(line, 1024, "%s: info RECOVER_CMD=", get_pname());
- if (fullwrite(mesgfd, line, strlen(line)) != (ssize_t)strlen(line)) {
+ if (full_write(mesgfd, line, strlen(line)) != strlen(line)) {
dbprintf(_("error writing to mesgfd socket: %s"), strerror(errno));
return;
}
- if (options->compress) {
+ if (dle->compress == COMP_FAST || dle->compress == COMP_BEST) {
g_snprintf(line, 1024, "%s %s |", UNCOMPRESS_PATH,
#ifdef UNCOMPRESS_OPT
UNCOMPRESS_OPT
""
#endif
);
- if (fullwrite(mesgfd, line, strlen(line)) != (ssize_t)strlen(line)) {
+ if (full_write(mesgfd, line, strlen(line)) != strlen(line)) {
dbprintf(_("error writing to mesgfd socket: %s"), strerror(errno));
return;
}
}
- g_snprintf(line, 1024, "%s -f... -\n", prog);
- if (fullwrite(mesgfd, line, strlen(line)) != (ssize_t)strlen(line)) {
+ g_snprintf(line, 1024, "%s/%s restore [./file-to-restore]+\n",
+ APPLICATION_DIR, prog);
+ if (full_write(mesgfd, line, strlen(line)) != strlen(line)) {
dbprintf(_("error writing to mesgfd socket: %s"), strerror(errno));
return;
}
- if (options->compress) {
+ if (dle->compress) {
g_snprintf(line, 1024, "%s: info COMPRESS_SUFFIX=%s\n",
get_pname(), COMPRESS_SUFFIX);
- if (fullwrite(mesgfd, line, strlen(line)) != (ssize_t)strlen(line)) {
+ if (full_write(mesgfd, line, strlen(line)) != strlen(line)) {
dbprintf(_("error writing to mesgfd socket: %s"), strerror(errno));
return;
}
}
g_snprintf(line, 1024, "%s: info end\n", get_pname());
- if (fullwrite(mesgfd, line, strlen(line)) != (ssize_t)strlen(line)) {
+ if (full_write(mesgfd, line, strlen(line)) != strlen(line)) {
dbprintf(_("error writing to mesgfd socket: %s"), strerror(errno));
return;
}
return pid;
}
-void
-parse_backup_messages(
- int mesgin)
+int
+check_result(
+ int mesgfd)
{
int goterror;
pid_t wpid;
amwait_t retstat;
- char *line;
goterror = 0;
- amfree(errorstr);
- for(; (line = areads(mesgin)) != NULL; free(line)) {
- process_dumpline(line);
- }
-
- if(errno) {
- error(_("error [read mesg pipe: %s]"), strerror(errno));
- /*NOTREACHED*/
- }
while((wpid = waitpid((pid_t)-1, &retstat, WNOHANG)) > 0) {
- if(check_status(wpid, retstat)) goterror = 1;
+ if(check_status(wpid, retstat, mesgfd)) goterror = 1;
}
if (dumppid != -1) {
sleep(5);
while((wpid = waitpid((pid_t)-1, &retstat, WNOHANG)) > 0) {
- if(check_status(wpid, retstat)) goterror = 1;
+ if(check_status(wpid, retstat, mesgfd)) goterror = 1;
}
}
if (dumppid != -1) {
}
sleep(5);
while((wpid = waitpid((pid_t)-1, &retstat, WNOHANG)) > 0) {
- if(check_status(wpid, retstat)) goterror = 1;
+ if(check_status(wpid, retstat, mesgfd)) goterror = 1;
}
}
if (dumppid != -1) {
}
sleep(5);
while((wpid = waitpid((pid_t)-1, &retstat, WNOHANG)) > 0) {
- if(check_status(wpid, retstat)) goterror = 1;
+ if(check_status(wpid, retstat, mesgfd)) goterror = 1;
}
}
+ return goterror;
+}
+
+void
+parse_backup_messages(
+ dle_t *dle,
+ int mesgin)
+{
+ int goterror;
+ char *line;
+
+ amfree(errorstr);
+
+ for(; (line = areads(mesgin)) != NULL; free(line)) {
+ process_dumpline(line);
+ }
+
+ if(errno) {
+ error(_("error [read mesg pipe: %s]"), strerror(errno));
+ /*NOTREACHED*/
+ }
+
+ goterror = check_result(mesgfd);
+
if(errorstr) {
error(_("error [%s]"), errorstr);
/*NOTREACHED*/
/*NOTREACHED*/
}
- program->end_backup(goterror);
+ program->end_backup(dle, goterror);
- g_fprintf(stderr, _("%s: size %ld\n"), get_pname(), dump_size);
- g_fprintf(stderr, _("%s: end\n"), get_pname());
-}
-
-
-/*
- * Returns the value of the first integer in a string.
- */
-
-double
-the_num(
- char * str,
- int pos)
-{
- char *num;
- int ch;
- double d;
-
- do {
- ch = *str++;
- while(ch && !isdigit(ch)) ch = *str++;
- if (pos == 1) break;
- pos--;
- while(ch && (isdigit(ch) || ch == '.')) ch = *str++;
- } while (ch);
- num = str - 1;
- while(isdigit(ch) || ch == '.') ch = *str++;
- str[-1] = '\0';
- d = atof(num);
- str[-1] = (char)ch;
- return d;
+ fdprintf(mesgfd, _("%s: size %ld\n"), get_pname(), dump_size);
+ fdprintf(mesgfd, _("%s: end\n"), get_pname());
}
type,
startchr,
str);
- g_fprintf(stderr, "%c %s\n", startchr, str);
+ fdprintf(mesgfd, "%c %s\n", startchr, str);
}
char buffer[BUFSIZ], *ptr;
ssize_t bytes_read;
size_t bytes_written;
- ssize_t just_written;
+ size_t just_written;
do {
bytes_read = read(0, buffer, SIZEOF(buffer));
/* write the stuff to the subprocess */
ptr = buffer;
bytes_written = 0;
- just_written = fullwrite(fileno(pipe_fp), ptr, (size_t)bytes_read);
- if (just_written < 0) {
+ just_written = full_write(fileno(pipe_fp), ptr, (size_t)bytes_read);
+ if (just_written < (size_t)bytes_read) {
/*
* just as we waited for write() to complete.
*/
occurs */
ptr = buffer;
bytes_written = 0;
- just_written = fullwrite(3, ptr, (size_t)bytes_read);
- if (just_written < 0) {
+ just_written = full_write(3, ptr, bytes_read);
+ if (just_written < (size_t)bytes_read) {
error(_("index tee cannot write [%s]"), strerror(errno));
/*NOTREACHED*/
} else {