X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Ffiled%2Fjob.c;h=96365bff361bd1841a0ce3cf2fa0c96494c59f51;hb=7313af1d71e8bc6c95792526d437973369ab5a35;hp=6f0d401ba49a16e3268a57aef3bc2a7aa88f05b6;hpb=5eaf8edcf7dbbd371c9384680bb31ccb02b8ed82;p=bacula%2Fbacula diff --git a/bacula/src/filed/job.c b/bacula/src/filed/job.c index 6f0d401ba4..96365bff36 100644 --- a/bacula/src/filed/job.c +++ b/bacula/src/filed/job.c @@ -7,31 +7,32 @@ * */ /* - Copyright (C) 2000-2005 Kern Sibbald + Copyright (C) 2000-2006 Kern Sibbald This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. + modify it under the terms of the GNU General Public License + version 2 as amended with additional clauses defined in the + file LICENSE in the main source directory. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public - License along with this program; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + the file LICENSE for additional details. */ #include "bacula.h" #include "filed.h" +#ifdef WIN32_VSS +#include "vss.h" +static pthread_mutex_t vss_mutex = PTHREAD_MUTEX_INITIALIZER; +#endif extern char my_name[]; extern CLIENT *me; /* our client resource */ +int enable_vss = 0; /* set to use vss */ + /* Imported functions */ extern int status_cmd(JCR *jcr); extern int qstatus_cmd(JCR *jcr); @@ -54,9 +55,10 @@ static int response(JCR *jcr, BSOCK *sd, char *resp, const char *cmd); static void filed_free_jcr(JCR *jcr); static int open_sd_read_session(JCR *jcr); static int send_bootstrap_file(JCR *jcr); +static int runscript_cmd(JCR *jcr); static int runbefore_cmd(JCR *jcr); static int runafter_cmd(JCR *jcr); -static bool run_cmd(JCR *jcr, char *cmd, const char *name); +static int runbeforenow_cmd(JCR *jcr); static void set_options(findFOPTS *fo, const char *opts); @@ -87,8 +89,10 @@ static struct s_cmds cmds[] = { {"storage ", storage_cmd, 0}, {"verify", verify_cmd, 0}, {"bootstrap", bootstrap_cmd, 0}, + {"RunBeforeNow", runbeforenow_cmd, 0}, {"RunBeforeJob", runbefore_cmd, 0}, {"RunAfterJob", runafter_cmd, 0}, + {"Run", runscript_cmd, 0}, {NULL, NULL} /* list terminator */ }; @@ -102,7 +106,7 @@ static char verifycmd[] = "verify level=%30s\n"; static char estimatecmd[] = "estimate listing=%d\n"; static char runbefore[] = "RunBeforeJob %s\n"; static char runafter[] = "RunAfterJob %s\n"; - +static char runscript[] = "Run OnSuccess=%u OnFailure=%u AbortOnError=%u When=%u Command=%s\n"; /* Responses sent to Director */ static char errmsg[] = "2999 Invalid command\n"; static char no_auth[] = "2998 No Authorization\n"; @@ -121,7 +125,10 @@ static char OKsetdebug[] = "2000 OK setdebug=%d\n"; static char BADjob[] = "2901 Bad Job\n"; static char EndJob[] = "2800 End Job TermCode=%d JobFiles=%u ReadBytes=%s JobBytes=%s Errors=%u\n"; static char OKRunBefore[] = "2000 OK RunBefore\n"; +static char OKRunBeforeNow[] = "2000 OK RunBeforeNow\n"; static char OKRunAfter[] = "2000 OK RunAfter\n"; +static char OKRunScript[] = "2000 OK RunScript\n"; + /* Responses received from Storage Daemon */ static char OK_end[] = "3000 OK end\n"; @@ -129,7 +136,7 @@ static char OK_close[] = "3000 OK close Status = %d\n"; static char OK_open[] = "3000 OK open ticket = %d\n"; static char OK_data[] = "3000 OK data\n"; static char OK_append[] = "3000 OK append data\n"; -static char OKSDbootstrap[] = "3000 OK bootstrap\n"; +static char OKSDbootstrap[]= "3000 OK bootstrap\n"; /* Commands sent to Storage Daemon */ @@ -169,10 +176,16 @@ void *handle_client_request(void *dirp) jcr->dir_bsock = dir; jcr->ff = init_find_files(); jcr->start_time = time(NULL); + jcr->RunScripts = New(alist(10, not_owned_by_alist)); jcr->last_fname = get_pool_memory(PM_FNAME); jcr->last_fname[0] = 0; jcr->client_name = get_memory(strlen(my_name) + 1); pm_strcpy(jcr->client_name, my_name); + jcr->pki_sign = me->pki_sign; + jcr->pki_encrypt = me->pki_encrypt; + jcr->pki_keypair = me->pki_keypair; + jcr->pki_signers = me->pki_signers; + jcr->pki_recipients = me->pki_recipients; dir->jcr = jcr; enable_backup_privileges(NULL, 1 /* ignore_errors */); @@ -221,9 +234,9 @@ void *handle_client_request(void *dirp) bnet_sig(jcr->store_bsock, BNET_TERMINATE); } - if (jcr->RunAfterJob && !job_canceled(jcr)) { - run_cmd(jcr, jcr->RunAfterJob, "ClientRunAfterJob"); - } + /* run after job */ + run_scripts(jcr, jcr->RunScripts, "ClientAfterJob"); + generate_daemon_event(jcr, "JobEnd"); dequeue_messages(jcr); /* send any queued messages */ @@ -232,7 +245,7 @@ void *handle_client_request(void *dirp) bnet_sig(dir, BNET_TERMINATE); /* Clean up fileset */ - FF_PKT *ff = (FF_PKT *)jcr->ff; + FF_PKT *ff = jcr->ff; findFILESET *fileset = ff->fileset; if (fileset) { int i, j, k; @@ -286,7 +299,7 @@ void *handle_client_request(void *dirp) } ff->fileset = NULL; Dmsg0(100, "Calling term_find_files\n"); - term_find_files((FF_PKT *)jcr->ff); + term_find_files(jcr->ff); jcr->ff = NULL; Dmsg0(100, "Done with term_find_files\n"); free_jcr(jcr); /* destroy JCR record */ @@ -320,19 +333,12 @@ static int cancel_cmd(JCR *jcr) if (sscanf(dir->msg, "cancel Job=%127s", Job) == 1) { if (!(cjcr=get_jcr_by_full_name(Job))) { - bnet_fsend(dir, "2901 Job %s not found.\n", Job); + bnet_fsend(dir, _("2901 Job %s not found.\n"), Job); } else { if (cjcr->store_bsock) { - P(cjcr->mutex); cjcr->store_bsock->timed_out = 1; cjcr->store_bsock->terminated = 1; -/* - * #if !defined(HAVE_CYGWIN) && !defined(HAVE_WIN32) - */ -#if !defined(HAVE_CYGWIN) pthread_kill(cjcr->my_thread_id, TIMEOUT_SIGNAL); -#endif - V(cjcr->mutex); } set_jcr_job_status(cjcr, JS_Canceled); free_jcr(cjcr); @@ -358,7 +364,7 @@ static int setdebug_cmd(JCR *jcr) Dmsg1(110, "setdebug_cmd: %s", dir->msg); if (sscanf(dir->msg, "setdebug=%d trace=%d", &level, &trace_flag) != 2 || level < 0) { pm_strcpy(jcr->errmsg, dir->msg); - bnet_fsend(dir, "2991 Bad setdebug command: %s\n", jcr->errmsg); + bnet_fsend(dir, _("2991 Bad setdebug command: %s\n"), jcr->errmsg); return 0; } debug_level = level; @@ -375,7 +381,7 @@ static int estimate_cmd(JCR *jcr) if (sscanf(dir->msg, estimatecmd, &jcr->listing) != 1) { pm_strcpy(jcr->errmsg, dir->msg); Jmsg(jcr, M_FATAL, 0, _("Bad estimate command: %s"), jcr->errmsg); - bnet_fsend(dir, "2992 Bad estimate command.\n"); + bnet_fsend(dir, _("2992 Bad estimate command.\n")); return 0; } make_estimate(jcr); @@ -414,85 +420,102 @@ static int runbefore_cmd(JCR *jcr) bool ok; BSOCK *dir = jcr->dir_bsock; POOLMEM *cmd = get_memory(dir->msglen+1); + RUNSCRIPT *script; Dmsg1(100, "runbefore_cmd: %s", dir->msg); if (sscanf(dir->msg, runbefore, cmd) != 1) { pm_strcpy(jcr->errmsg, dir->msg); Jmsg1(jcr, M_FATAL, 0, _("Bad RunBeforeJob command: %s\n"), jcr->errmsg); - bnet_fsend(dir, "2905 Bad RunBeforeJob command.\n"); + bnet_fsend(dir, _("2905 Bad RunBeforeJob command.\n")); free_memory(cmd); return 0; } unbash_spaces(cmd); /* Run the command now */ - ok = run_cmd(jcr, cmd, "ClientRunBeforeJob"); + script = new_runscript(); + script->set_command(cmd); + script->when = SCRIPT_Before; + ok = script->run(jcr, "ClientRunBeforeJob"); + free_runscript(script); + free_memory(cmd); if (ok) { bnet_fsend(dir, OKRunBefore); return 1; } else { - bnet_fsend(dir, "2905 Bad RunBeforeJob command.\n"); + bnet_fsend(dir, _("2905 Bad RunBeforeJob command.\n")); return 0; } } +static int runbeforenow_cmd(JCR *jcr) +{ + BSOCK *dir = jcr->dir_bsock; + + run_scripts(jcr, jcr->RunScripts, "ClientBeforeJob"); + return bnet_fsend(dir, OKRunBeforeNow); +} + static int runafter_cmd(JCR *jcr) { BSOCK *dir = jcr->dir_bsock; POOLMEM *msg = get_memory(dir->msglen+1); + RUNSCRIPT *cmd; Dmsg1(100, "runafter_cmd: %s", dir->msg); if (sscanf(dir->msg, runafter, msg) != 1) { pm_strcpy(jcr->errmsg, dir->msg); Jmsg1(jcr, M_FATAL, 0, _("Bad RunAfter command: %s\n"), jcr->errmsg); - bnet_fsend(dir, "2905 Bad RunAfterJob command.\n"); + bnet_fsend(dir, _("2905 Bad RunAfterJob command.\n")); free_memory(msg); return 0; } unbash_spaces(msg); - if (jcr->RunAfterJob) { - free_pool_memory(jcr->RunAfterJob); - } - jcr->RunAfterJob = get_pool_memory(PM_FNAME); - pm_strcpy(jcr->RunAfterJob, msg); + + cmd = new_runscript(); + cmd->set_command(msg); + cmd->on_success = true; + cmd->on_failure = false; + cmd->when = SCRIPT_After; + + jcr->RunScripts->append(cmd); + free_pool_memory(msg); return bnet_fsend(dir, OKRunAfter); } -static bool run_cmd(JCR *jcr, char *cmd, const char *name) +static int runscript_cmd(JCR *jcr) { - POOLMEM *ecmd = get_pool_memory(PM_FNAME); - int status; - BPIPE *bpipe; - char line[MAXSTRING]; + BSOCK *dir = jcr->dir_bsock; + POOLMEM *msg = get_memory(dir->msglen+1); - ecmd = edit_job_codes(jcr, ecmd, cmd, ""); - bpipe = open_bpipe(ecmd, 0, "r"); - free_pool_memory(ecmd); - if (bpipe == NULL) { - berrno be; - Jmsg(jcr, M_FATAL, 0, _("%s could not execute. ERR=%s\n"), name, - be.strerror()); - return false; - } - while (fgets(line, sizeof(line), bpipe->rfd)) { - int len = strlen(line); - if (len > 0 && line[len-1] == '\n') { - line[len-1] = 0; - } - Jmsg(jcr, M_INFO, 0, _("%s: %s\n"), name, line); - } - status = close_bpipe(bpipe); - if (status != 0) { - berrno be; - Jmsg(jcr, M_FATAL, 0, _("%s returned non-zero status=%d. ERR=%s\n"), name, - status, be.strerror(status)); - return false; + RUNSCRIPT *cmd = new_runscript() ; + + Dmsg1(100, "runscript_cmd: '%s'\n", dir->msg); + if (sscanf(dir->msg, runscript, &cmd->on_success, + &cmd->on_failure, + &cmd->abort_on_error, + &cmd->when, + msg) != 5) { + pm_strcpy(jcr->errmsg, dir->msg); + Jmsg1(jcr, M_FATAL, 0, _("Bad RunScript command: %s\n"), jcr->errmsg); + bnet_fsend(dir, _("2905 Bad RunScript command.\n")); + free_runscript(cmd); + free_memory(msg); + return 0; } - return true; + unbash_spaces(msg); + + cmd->set_command(msg); + cmd->debug(); + jcr->RunScripts->append(cmd); + + free_pool_memory(msg); + return bnet_fsend(dir, OKRunScript); } + static bool init_fileset(JCR *jcr) { FF_PKT *ff; @@ -501,7 +524,7 @@ static bool init_fileset(JCR *jcr) if (!jcr->ff) { return false; } - ff = (FF_PKT *)jcr->ff; + ff = jcr->ff; if (ff->fileset) { return false; } @@ -579,7 +602,7 @@ static void add_file_to_fileset(JCR *jcr, const char *fname, findFILESET *filese case '<': Dmsg0(100, "Doing < include on client.\n"); p++; /* skip over < */ - if ((ffd = fopen(p, "r")) == NULL) { + if ((ffd = fopen(p, "rb")) == NULL) { berrno be; Jmsg(jcr, M_FATAL, 0, _("Cannot open FileSet input file: %s. ERR=%s\n"), p, be.strerror()); @@ -601,7 +624,7 @@ static void add_file_to_fileset(JCR *jcr, const char *fname, findFILESET *filese static void add_fileset(JCR *jcr, const char *item) { - FF_PKT *ff = (FF_PKT *)jcr->ff; + FF_PKT *ff = jcr->ff; findFILESET *fileset = ff->fileset; int state = fileset->state; findFOPTS *current_opts; @@ -675,7 +698,7 @@ static void add_fileset(JCR *jcr, const char *item) regerror(rc, preg, prbuf, sizeof(prbuf)); regfree(preg); free(preg); - Jmsg(jcr, M_FATAL, 0, "REGEX %s compile error. ERR=%s\n", item, prbuf); + Jmsg(jcr, M_FATAL, 0, _("REGEX %s compile error. ERR=%s\n"), item, prbuf); state = state_error; break; } @@ -729,7 +752,7 @@ static void add_fileset(JCR *jcr, const char *item) state = state_options; break; default: - Jmsg(jcr, M_FATAL, 0, "Invalid FileSet command: %s\n", item); + Jmsg(jcr, M_FATAL, 0, _("Invalid FileSet command: %s\n"), item); state = state_error; break; } @@ -738,7 +761,9 @@ static void add_fileset(JCR *jcr, const char *item) static bool term_fileset(JCR *jcr) { - FF_PKT *ff = (FF_PKT *)jcr->ff; + FF_PKT *ff = jcr->ff; + +#ifdef xxx findFILESET *fileset = ff->fileset; int i, j, k; @@ -816,6 +841,7 @@ static bool term_fileset(JCR *jcr) Dmsg1(400, "F %s\n", (char *)incexe->name_list.get(j)); } } +#endif return ff->fileset->state != state_error; } @@ -865,7 +891,32 @@ static void set_options(findFOPTS *fo, const char *opts) fo->flags |= FO_READFIFO; break; case 'S': - fo->flags |= FO_SHA1; + switch(*(p + 1)) { + case ' ': + /* Old director did not specify SHA variant */ + fo->flags |= FO_SHA1; + break; + case '1': + fo->flags |= FO_SHA1; + p++; + break; +#ifdef HAVE_SHA2 + case '2': + fo->flags |= FO_SHA256; + p++; + break; + case '3': + fo->flags |= FO_SHA512; + p++; + break; +#endif + default: + /* Automatically downgrade to SHA-1 if an unsupported + * SHA variant is specified */ + fo->flags |= FO_SHA1; + p++; + break; + } break; case 's': fo->flags |= FO_SPARSE; @@ -897,8 +948,11 @@ static void set_options(findFOPTS *fo, const char *opts) fo->GZIP_level = *++p - '0'; Dmsg1(200, "Compression level=%d\n", fo->GZIP_level); break; + case 'K': + fo->flags |= FO_NOATIME; + break; default: - Emsg1(M_ERROR, 0, "Unknown include/exclude option: %c\n", *p); + Emsg1(M_ERROR, 0, _("Unknown include/exclude option: %c\n"), *p); break; } } @@ -911,13 +965,17 @@ static void set_options(findFOPTS *fo, const char *opts) static int fileset_cmd(JCR *jcr) { BSOCK *dir = jcr->dir_bsock; + int vss = 0; + + sscanf(dir->msg, "fileset vss=%d", &vss); + enable_vss = vss; if (!init_fileset(jcr)) { return 0; } while (bnet_recv(dir) >= 0) { strip_trailing_junk(dir->msg); - Dmsg1(400, "Fileset: %s\n", dir->msg); + Dmsg1(500, "Fileset: %s\n", dir->msg); add_fileset(jcr, dir->msg); } if (!term_fileset(jcr)) { @@ -926,6 +984,15 @@ static int fileset_cmd(JCR *jcr) return bnet_fsend(dir, OKinc); } +static void free_bootstrap(JCR *jcr) +{ + if (jcr->RestoreBootstrap) { + unlink(jcr->RestoreBootstrap); + free_pool_memory(jcr->RestoreBootstrap); + jcr->RestoreBootstrap = NULL; + } +} + /* * The Director sends us the bootstrap file, which @@ -937,28 +1004,23 @@ static int bootstrap_cmd(JCR *jcr) POOLMEM *fname = get_pool_memory(PM_FNAME); FILE *bs; - if (jcr->RestoreBootstrap) { - unlink(jcr->RestoreBootstrap); - free_pool_memory(jcr->RestoreBootstrap); - } + free_bootstrap(jcr); Mmsg(fname, "%s/%s.%s.bootstrap", me->working_directory, me->hdr.name, jcr->Job); Dmsg1(400, "bootstrap=%s\n", fname); jcr->RestoreBootstrap = fname; - bs = fopen(fname, "a+"); /* create file */ + bs = fopen(fname, "a+b"); /* create file */ if (!bs) { berrno be; + Jmsg(jcr, M_FATAL, 0, _("Could not create bootstrap file %s: ERR=%s\n"), + jcr->RestoreBootstrap, be.strerror()); /* * Suck up what he is sending to us so that he will then * read our error message. */ while (bnet_recv(dir) >= 0) { } - - Jmsg(jcr, M_FATAL, 0, _("Could not create bootstrap file %s: ERR=%s\n"), - jcr->RestoreBootstrap, be.strerror()); - free_pool_memory(jcr->RestoreBootstrap); - jcr->RestoreBootstrap = NULL; + free_bootstrap(jcr); set_jcr_job_status(jcr, JS_ErrorTerminated); return 0; } @@ -968,7 +1030,10 @@ static int bootstrap_cmd(JCR *jcr) fputs(dir->msg, bs); } fclose(bs); - + /* + * Note, do not free the bootstrap yet -- it needs to be + * sent to the SD + */ return bnet_fsend(dir, OKbootstrap); } @@ -1018,6 +1083,7 @@ static int level_cmd(JCR *jcr) goto bail_out; } since_time = str_to_uint64(buf); /* this is the since time */ + Dmsg1(100, "since_time=%d\n", (int)since_time); char ed1[50], ed2[50]; /* * Sync clocks by polling him for the time. We take @@ -1037,8 +1103,10 @@ static int level_cmd(JCR *jcr) } his_time = str_to_uint64(buf); rt = get_current_btime() - bt_start; /* compute round trip time */ - bt_adj -= his_time - bt_start - rt/2; - Dmsg2(200, "rt=%s adj=%s\n", edit_uint64(rt, ed1), edit_uint64(bt_adj, ed2)); + Dmsg2(100, "Dirtime=%s FDtime=%s\n", edit_uint64(his_time, ed1), + edit_uint64(bt_start, ed2)); + bt_adj += bt_start - his_time - rt/2; + Dmsg2(100, "rt=%s adj=%s\n", edit_uint64(rt, ed1), edit_uint64(bt_adj, ed2)); } bt_adj = bt_adj / 8; /* compute average time */ @@ -1054,7 +1122,7 @@ static int level_cmd(JCR *jcr) jcr->incremental = 1; /* set incremental or decremental backup */ jcr->mtime = (time_t)since_time; /* set since time */ } else { - Jmsg1(jcr, M_FATAL, 0, "Unknown backup level: %s\n", level); + Jmsg1(jcr, M_FATAL, 0, _("Unknown backup level: %s\n"), level); free_memory(level); return 0; } @@ -1087,7 +1155,7 @@ static int session_cmd(JCR *jcr) &jcr->StartFile, &jcr->EndFile, &jcr->StartBlock, &jcr->EndBlock) != 7) { pm_strcpy(jcr->errmsg, dir->msg); - Jmsg(jcr, M_FATAL, 0, "Bad session command: %s", jcr->errmsg); + Jmsg(jcr, M_FATAL, 0, _("Bad session command: %s"), jcr->errmsg); return 0; } @@ -1150,9 +1218,21 @@ static int backup_cmd(JCR *jcr) int SDJobStatus; char ed1[50], ed2[50]; +#ifdef WIN32_VSS + // capture state here, if client is backed up by multiple directors + // and one enables vss and the other does not then enable_vss can change + // between here and where its evaluated after the job completes. + bool bDoVSS = false; + + bDoVSS = g_pVSSClient && enable_vss; + if (bDoVSS) + /* Run only one at a time */ + P(vss_mutex); +#endif + set_jcr_job_status(jcr, JS_Blocked); jcr->JobType = JT_BACKUP; - Dmsg1(100, "begin backup ff=%p\n", (FF_PKT *)jcr->ff); + Dmsg1(100, "begin backup ff=%p\n", jcr->ff); if (sd == NULL) { Jmsg(jcr, M_FATAL, 0, _("Cannot contact Storage daemon\n")); @@ -1195,9 +1275,46 @@ static int backup_cmd(JCR *jcr) if (!response(jcr, sd, OK_data, "Append Data")) { goto cleanup; } - + generate_daemon_event(jcr, "JobStart"); +#ifdef WIN32_VSS + /* START VSS ON WIN 32 */ + if (bDoVSS) { + if (g_pVSSClient->InitializeForBackup()) { + /* tell vss which drives to snapshot */ + char szWinDriveLetters[27]; + if (get_win32_driveletters(jcr->ff, szWinDriveLetters)) { + Jmsg(jcr, M_INFO, 0, _("Generate VSS snapshots. Driver=\"%s\", Drive(s)=\"%s\"\n"), g_pVSSClient->GetDriverName(), szWinDriveLetters); + if (!g_pVSSClient->CreateSnapshots(szWinDriveLetters)) { + Jmsg(jcr, M_WARNING, 0, _("Generate VSS snapshots failed.\n")); + jcr->Errors++; + } else { + /* tell user if snapshot creation of a specific drive failed */ + size_t i; + for (i=0; iErrors++; + } + } + /* inform user about writer states */ + for (i=0; iGetWriterCount(); i++) + if (g_pVSSClient->GetWriterState(i) < 1) { + Jmsg(jcr, M_WARNING, 0, _("VSS Writer (PrepareForBackup): %s\n"), g_pVSSClient->GetWriterInfo(i)); + jcr->Errors++; + } + } + } else { + Jmsg(jcr, M_INFO, 0, _("No drive letters found for generating VSS snapshots.\n")); + } + } else { + berrno be; + Jmsg(jcr, M_WARNING, 0, _("VSS was not initialized properly. VSS support is disabled. ERR=%s\n"), be.strerror()); + } + } +#endif + /* * Send Files to Storage daemon */ @@ -1209,6 +1326,10 @@ static int backup_cmd(JCR *jcr) Dmsg0(110, "Error in blast_data.\n"); } else { set_jcr_job_status(jcr, JS_Terminated); + + /* run shortly after end of data transmission */ + run_scripts(jcr, jcr->RunScripts, "ClientAfterJobShort"); + if (jcr->JobStatus != JS_Terminated) { bnet_suppress_error_messages(sd, 1); goto cleanup; /* bail out now */ @@ -1252,11 +1373,30 @@ static int backup_cmd(JCR *jcr) } cleanup: +#ifdef WIN32_VSS + /* STOP VSS ON WIN 32 */ + /* tell vss to close the backup session */ + if (bDoVSS) { + if (g_pVSSClient->CloseBackup()) { + /* inform user about writer states */ + for (size_t i=0; iGetWriterCount(); i++) { + int msg_type = M_INFO; + if (g_pVSSClient->GetWriterState(i) < 1) { + msg_type = M_WARNING; + jcr->Errors++; + } + Jmsg(jcr, msg_type, 0, _("VSS Writer (BackupComplete): %s\n"), g_pVSSClient->GetWriterInfo(i)); + } + } + V(vss_mutex); + } +#endif + bnet_fsend(dir, EndJob, jcr->JobStatus, jcr->JobFiles, edit_uint64(jcr->ReadBytes, ed1), edit_uint64(jcr->JobBytes, ed2), jcr->Errors); Dmsg1(110, "End FD msg: %s\n", dir->msg); - + return 0; /* return and stop command loop */ } @@ -1272,7 +1412,7 @@ static int verify_cmd(JCR *jcr) jcr->JobType = JT_VERIFY; if (sscanf(dir->msg, verifycmd, level) != 1) { - bnet_fsend(dir, "2994 Bad verify command: %s\n", dir->msg); + bnet_fsend(dir, _("2994 Bad verify command: %s\n"), dir->msg); return 0; } @@ -1287,7 +1427,7 @@ static int verify_cmd(JCR *jcr) } else if (strcasecmp(level, "disk_to_catalog") == 0) { jcr->JobLevel = L_VERIFY_DISK_TO_CATALOG; } else { - bnet_fsend(dir, "2994 Bad verify level: %s\n", dir->msg); + bnet_fsend(dir, _("2994 Bad verify level: %s\n"), dir->msg); return 0; } @@ -1326,7 +1466,7 @@ static int verify_cmd(JCR *jcr) do_verify(jcr); break; default: - bnet_fsend(dir, "2994 Bad verify level: %s\n", dir->msg); + bnet_fsend(dir, _("2994 Bad verify level: %s\n"), dir->msg); return 0; } @@ -1452,7 +1592,7 @@ static int open_sd_read_session(JCR *jcr) /* * Open Read Session with Storage daemon */ - bnet_fsend(sd, read_open, jcr->VolumeName, + bnet_fsend(sd, read_open, "DummyVolume", jcr->VolSessionId, jcr->VolSessionTime, jcr->StartFile, jcr->EndFile, jcr->StartBlock, jcr->EndBlock); Dmsg1(110, ">stored: %s", sd->msg); @@ -1500,18 +1640,12 @@ static void filed_free_jcr(JCR *jcr) if (jcr->store_bsock) { bnet_close(jcr->store_bsock); } - if (jcr->RestoreBootstrap) { - unlink(jcr->RestoreBootstrap); - free_pool_memory(jcr->RestoreBootstrap); - jcr->RestoreBootstrap = NULL; - } + free_bootstrap(jcr); if (jcr->last_fname) { free_pool_memory(jcr->last_fname); } - if (jcr->RunAfterJob) { - free_pool_memory(jcr->RunAfterJob); - } - + free_runscripts(jcr->RunScripts); + delete jcr->RunScripts; return; } @@ -1559,7 +1693,7 @@ static int send_bootstrap_file(JCR *jcr) if (!jcr->RestoreBootstrap) { return 1; } - bs = fopen(jcr->RestoreBootstrap, "r"); + bs = fopen(jcr->RestoreBootstrap, "rb"); if (!bs) { berrno be; Jmsg(jcr, M_FATAL, 0, _("Could not open bootstrap file %s: ERR=%s\n"), @@ -1582,11 +1716,6 @@ static int send_bootstrap_file(JCR *jcr) stat = 1; bail_out: - if (jcr->RestoreBootstrap) { - unlink(jcr->RestoreBootstrap); - free_pool_memory(jcr->RestoreBootstrap); - jcr->RestoreBootstrap = NULL; - } - + free_bootstrap(jcr); return stat; }