X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=client-src%2Fsendbackup.c;h=dacb961e143ab296e4c4e19e3de67a14994795cd;hb=42ff24f2a525d5965e1841b2ebe3ee0f4b918ac6;hp=9f26dafe2e2d3ccf02db171a2da62cc57d227b12;hpb=94a044f90357edefa6f4ae9f0b1d5885b0e34aee;p=debian%2Famanda diff --git a/client-src/sendbackup.c b/client-src/sendbackup.c index 9f26daf..dacb961 100644 --- a/client-src/sendbackup.c +++ b/client-src/sendbackup.c @@ -30,15 +30,15 @@ */ #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" #define sendbackup_debug(i, ...) do { \ if ((i) <= debug_sendbackup) { \ @@ -53,18 +53,19 @@ pid_t dumppid = (pid_t)-1; 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; @@ -72,110 +73,38 @@ static char *amandad_auth = 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, @@ -184,22 +113,20 @@ main( 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; + level_t *alevel; /* initialize */ - /* * Configure program for internationalization: * 1) Only set the message locale for now. @@ -210,6 +137,7 @@ main( textdomain("amanda"); safe_fd(DATA_FD_OFFSET, DATA_FD_COUNT*2); + openbsd_fd_inform(); safe_cd(); @@ -229,10 +157,11 @@ main( 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]); @@ -242,6 +171,7 @@ main( 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); @@ -256,13 +186,9 @@ main( 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') @@ -284,17 +210,31 @@ main( 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++; @@ -303,21 +243,21 @@ main( 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') { @@ -325,14 +265,13 @@ main( 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') { @@ -341,18 +280,17 @@ main( } 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 */ @@ -361,6 +299,9 @@ main( goto err; /* bad level */ } skip_integer(s, ch); + alevel = g_new0(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') { @@ -392,63 +333,98 @@ main( } 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 = (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"); } @@ -462,8 +438,9 @@ main( 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); @@ -484,122 +461,246 @@ main( } 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; + 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*/ - } - if(dup2(datafd, 1) == -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(mesgfd, 2) == -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(indexfd != 0) { - if(dup2(indexfd, 3) == -1) { - error(_("Can't dup2: %s"),strerror(errno)); - /*NOTREACHED*/ - } - fcntl(indexfd, F_SETFD, 0); - fcntl(3, F_SETFD, 0); - safe_fd(3, 1); + } 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 { - safe_fd(-1, 0); + dbprintf(_("pid %ld: %s\n"), (long)comppid, dle->compprog); + } + } 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); } - cmd = vstralloc(DUMPER_DIR, "/", prog, NULL); - i=0; - argvchild[i++] = prog; - argvchild[i++] = "backup"; + 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: + 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")); + } + 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); + } } - argvchild[i] = NULL; - dbprintf(_("%s: running \"%s"), get_pname(), cmd); - for(j=1;jlen - 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); + } + application_api_info_tapeheader(mesgfd, dle->program, dle); + 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) { @@ -616,17 +717,17 @@ main( 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); @@ -640,10 +741,20 @@ main( 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; } @@ -662,6 +773,13 @@ childstr( 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"; } @@ -675,7 +793,8 @@ childstr( int check_status( pid_t pid, - amwait_t w) + amwait_t w, + int mesgfd) { char *thiserr = NULL; char *str, *strX; @@ -698,11 +817,11 @@ check_status( * 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. @@ -713,7 +832,7 @@ check_status( } #endif comppid = -1; - strX = "compress "; + strX = "compress"; } else if(pid == dumppid && tarpid == -1) { /* * Ultrix dump returns 1 sometimes, but it is ok. @@ -724,7 +843,7 @@ check_status( } #endif dumppid = -1; - strX = "dump "; + strX = "dump"; } else if(pid == tarpid) { if (ret == 1) { rc = 0; @@ -738,9 +857,11 @@ check_status( } #endif dumppid = tarpid = -1; - strX = "dump "; + strX = "dump"; + } else if(pid == application_api_pid) { + strX = "Application"; } else { - strX = "unknown "; + strX = "unknown"; } if(rc == 0) { @@ -754,6 +875,8 @@ check_status( 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); @@ -769,12 +892,13 @@ check_status( *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 @@ -785,7 +909,7 @@ info_tapeheader(void) 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); @@ -793,32 +917,32 @@ info_tapeheader(void) } 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 @@ -826,28 +950,29 @@ backup_api_info_tapeheader( "" #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; } @@ -905,35 +1030,25 @@ pipefork( 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) { @@ -948,7 +1063,7 @@ parse_backup_messages( } 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) { @@ -963,10 +1078,34 @@ parse_backup_messages( } 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*/ @@ -975,39 +1114,10 @@ parse_backup_messages( /*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()); } @@ -1057,7 +1167,7 @@ process_dumpline( type, startchr, str); - g_fprintf(stderr, "%c %s\n", startchr, str); + fdprintf(mesgfd, "%c %s\n", startchr, str); } @@ -1161,7 +1271,7 @@ start_index( 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)); @@ -1178,8 +1288,8 @@ start_index( /* 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. */ @@ -1196,8 +1306,8 @@ start_index( 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 {