X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fdird%2Ffd_cmds.c;h=3f7be74d69aa35e71849d324043f33e9dde17fee;hb=7ebf8f564b27ca8448a9a7365ba73b130ae69c21;hp=2d08770bc42209224d74752cb3f26b10f58cfe97;hpb=71025c877b28da7326d650dd3598b9bd64d00e23;p=bacula%2Fbacula diff --git a/bacula/src/dird/fd_cmds.c b/bacula/src/dird/fd_cmds.c index 2d08770bc4..3f7be74d69 100644 --- a/bacula/src/dird/fd_cmds.c +++ b/bacula/src/dird/fd_cmds.c @@ -39,12 +39,19 @@ static char inc[] = "include\n"; static char exc[] = "exclude\n"; static char jobcmd[] = "JobId=%d Job=%s SDid=%u SDtime=%u Authorization=%s\n"; +static char levelcmd[] = "level = %s%s mtime_only=%d\n"; +static char runbefore[] = "RunBeforeJob %s\n"; +static char runafter[] = "RunAfterJob %s\n"; /* Responses received from File daemon */ -static char OKinc[] = "2000 OK include\n"; -static char OKexc[] = "2000 OK exclude\n"; -static char OKjob[] = "2000 OK Job"; +static char OKinc[] = "2000 OK include\n"; +static char OKexc[] = "2000 OK exclude\n"; +static char OKjob[] = "2000 OK Job"; +static char OKbootstrap[] = "2000 OK bootstrap\n"; +static char OKlevel[] = "2000 OK level\n"; +static char OKRunBefore[] = "2000 OK RunBefore\n"; +static char OKRunAfter[] = "2000 OK RunAfter\n"; /* Forward referenced functions */ @@ -58,7 +65,8 @@ extern int FDConnectTimeout; /* * Open connection with File daemon. - * Try connecting every 10 seconds, give up after 1 hour. + * Try connecting every retry_interval (default 10 sec), and + * give up after max_retry_time (default 30 mins). */ int connect_to_file_daemon(JCR *jcr, int retry_interval, int max_retry_time, @@ -92,14 +100,14 @@ int connect_to_file_daemon(JCR *jcr, int retry_interval, int max_retry_time, memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key)); } Dmsg1(100, ">filed: %s", fd->msg); - if (bnet_recv(fd) > 0) { + if (bget_dirmsg(fd) > 0) { Dmsg1(110, "msg); if (strncmp(fd->msg, OKjob, strlen(OKjob)) != 0) { Jmsg(jcr, M_FATAL, 0, _("File daemon \"%s\" rejected Job command: %s\n"), jcr->client->hdr.name, fd->msg); set_jcr_job_status(jcr, JS_ErrorTerminated); return 0; - } else { + } else if (jcr->db) { CLIENT_DBR cr; memset(&cr, 0, sizeof(cr)); bstrncpy(cr.Name, jcr->client->hdr.name, sizeof(cr.Name)); @@ -121,6 +129,88 @@ int connect_to_file_daemon(JCR *jcr, int retry_interval, int max_retry_time, return 1; } +/* + * This subroutine edits the last job start time into a + * "since=date/time" buffer that is returned in the + * variable since. This is used for display purposes in + * the job report. The time in jcr->stime is later + * passed to tell the File daemon what to do. + */ +void get_level_since_time(JCR *jcr, char *since, int since_len) +{ + /* Lookup the last + * FULL backup job to get the time/date for a + * differential or incremental save. + */ + if (!jcr->stime) { + jcr->stime = get_pool_memory(PM_MESSAGE); + } + jcr->stime[0] = 0; + since[0] = 0; + switch (jcr->JobLevel) { + case L_DIFFERENTIAL: + case L_INCREMENTAL: + /* Look up start time of last job */ + jcr->jr.JobId = 0; + if (!db_find_job_start_time(jcr, jcr->db, &jcr->jr, &jcr->stime)) { + Jmsg(jcr, M_INFO, 0, "%s", db_strerror(jcr->db)); + Jmsg(jcr, M_INFO, 0, _("No prior or suitable Full backup found. Doing FULL backup.\n")); + bsnprintf(since, since_len, " (upgraded from %s)", + level_to_str(jcr->JobLevel)); + jcr->JobLevel = jcr->jr.Level = L_FULL; + } else { + bstrncpy(since, ", since=", since_len); + bstrncat(since, jcr->stime, since_len); + } + Dmsg1(100, "Last start time = %s\n", jcr->stime); + break; + } +} + + +/* + * Send level command to FD. + * Used for backup jobs and estimate command. + */ +int send_level_command(JCR *jcr) +{ + BSOCK *fd = jcr->file_bsock; + utime_t stime; + char ed1[50]; + /* + * Send Level command to File daemon + */ + switch (jcr->JobLevel) { + case L_BASE: + bnet_fsend(fd, levelcmd, "base", " ", 0); + break; + /* L_NONE is the console, sending something off to the FD */ + case L_NONE: + case L_FULL: + bnet_fsend(fd, levelcmd, "full", " ", 0); + break; + case L_DIFFERENTIAL: + case L_INCREMENTAL: +// bnet_fsend(fd, levelcmd, "since ", jcr->stime, 0); /* old code, deprecated */ + stime = str_to_utime(jcr->stime); + bnet_fsend(fd, levelcmd, "since_utime ", edit_uint64(stime, ed1), 0); + while (bget_dirmsg(fd) >= 0) { /* allow him to poll us to sync clocks */ + Jmsg(jcr, M_INFO, 0, "%s\n", fd->msg); + } + break; + case L_SINCE: + default: + Jmsg2(jcr, M_FATAL, 0, _("Unimplemented backup level %d %c\n"), + jcr->JobLevel, jcr->JobLevel); + return 0; + } + Dmsg1(120, ">filed: %s", fd->msg); + if (!response(jcr, fd, OKlevel, "Level", DISPLAY_ERROR)) { + return 0; + } + return 1; +} + /* * Send either an Included or an Excluded list to FD @@ -147,16 +237,23 @@ static int send_list(JCR *jcr, int list) char *p; int optlen, stat; INCEXE *ie; + FOPTS *fo; + if (list == INC_LIST) { ie = fileset->include_items[i]; } else { ie = fileset->exclude_items[i]; } - for (int j=0; jnum_names; j++) { - p = ie->name_list[j]; + fo = ie->opts_list[0]; + for (int j=0; jmatch.size(); j++) { + Dmsg1(100, "Match=%s\n", fo->match.get(j)); + } + for (int j=0; jname_list.size(); j++) { + p = (char *)ie->name_list.get(j); switch (*p) { case '|': + p++; /* skip over the | */ fd->msg = edit_job_codes(jcr, fd->msg, p, ""); bpipe = open_bpipe(fd->msg, 0, "r"); if (!bpipe) { @@ -166,11 +263,12 @@ static int send_list(JCR *jcr, int list) } /* Copy File options */ if (ie->num_opts) { - strcpy(buf, ie->opts_list[0]->opts); - strcat(buf, " "); + bstrncpy(buf, ie->opts_list[0]->opts, sizeof(buf)); + bstrncat(buf, " ", sizeof(buf)); } else { - strcpy(buf, "0 "); + bstrncpy(buf, "0 ", sizeof(buf)); } + Dmsg1(100, "Opts=%s\n", buf); optlen = strlen(buf); while (fgets(buf+optlen, sizeof(buf)-optlen, bpipe->rfd)) { fd->msglen = Mmsg(&fd->msg, "%s", buf); @@ -195,11 +293,12 @@ static int send_list(JCR *jcr, int list) } /* Copy File options */ if (ie->num_opts) { - strcpy(buf, ie->opts_list[0]->opts); - strcat(buf, " "); + bstrncpy(buf, ie->opts_list[0]->opts, sizeof(buf)); + bstrncat(buf, " ", sizeof(buf)); } else { - strcpy(buf, "0 "); + bstrncpy(buf, "0 ", sizeof(buf)); } + Dmsg1(100, "Opts=%s\n", buf); optlen = strlen(buf); while (fgets(buf+optlen, sizeof(buf)-optlen, ffd)) { fd->msglen = Mmsg(&fd->msg, "%s", buf); @@ -214,15 +313,15 @@ static int send_list(JCR *jcr, int list) p++; /* skip over \ */ /* Note, fall through wanted */ default: + Dmsg2(100, "numopts=%d opts=%s\n", ie->num_opts, NPRT(ie->opts_list[0]->opts)); if (ie->num_opts) { pm_strcpy(&fd->msg, ie->opts_list[0]->opts); pm_strcat(&fd->msg, " "); } else { pm_strcpy(&fd->msg, "0 "); } - pm_strcat(&fd->msg, p); + fd->msglen = pm_strcat(&fd->msg, p); Dmsg1(100, "Inc/Exc name=%s\n", fd->msg); - fd->msglen = strlen(fd->msg); if (!bnet_send(fd)) { Jmsg(jcr, M_FATAL, 0, _(">filed: write error on socket\n")); goto bail_out; @@ -253,7 +352,7 @@ bail_out: int send_include_list(JCR *jcr) { BSOCK *fd = jcr->file_bsock; - fd->msglen = sprintf(fd->msg, inc); + fd->msglen = pm_strcpy(&fd->msg, inc); bnet_send(fd); return send_list(jcr, INC_LIST); } @@ -265,12 +364,79 @@ int send_include_list(JCR *jcr) int send_exclude_list(JCR *jcr) { BSOCK *fd = jcr->file_bsock; - fd->msglen = sprintf(fd->msg, exc); + fd->msglen = pm_strcpy(&fd->msg, exc); bnet_send(fd); return send_list(jcr, EXC_LIST); } +/* + * Send bootstrap file if any to the File daemon. + * This is used for restore and verify VolumeToCatalog + */ +int send_bootstrap_file(JCR *jcr) +{ + FILE *bs; + char buf[1000]; + BSOCK *fd = jcr->file_bsock; + char *bootstrap = "bootstrap\n"; + + Dmsg1(400, "send_bootstrap_file: %s\n", jcr->RestoreBootstrap); + if (!jcr->RestoreBootstrap) { + return 1; + } + bs = fopen(jcr->RestoreBootstrap, "r"); + if (!bs) { + Jmsg(jcr, M_FATAL, 0, _("Could not open bootstrap file %s: ERR=%s\n"), + jcr->RestoreBootstrap, strerror(errno)); + set_jcr_job_status(jcr, JS_ErrorTerminated); + return 0; + } + bnet_fsend(fd, bootstrap); + while (fgets(buf, sizeof(buf), bs)) { + bnet_fsend(fd, "%s", buf); + } + bnet_sig(fd, BNET_EOD); + fclose(bs); + if (!response(jcr, fd, OKbootstrap, "Bootstrap", DISPLAY_ERROR)) { + set_jcr_job_status(jcr, JS_ErrorTerminated); + return 0; + } + return 1; +} + +/* + * Send ClientRunBeforeJob and ClientRunAfterJob to File daemon + */ +int send_run_before_and_after_commands(JCR *jcr) +{ + POOLMEM *msg = get_pool_memory(PM_FNAME); + BSOCK *fd = jcr->file_bsock; + if (jcr->job->ClientRunBeforeJob) { + pm_strcpy(&msg, jcr->job->ClientRunBeforeJob); + bash_spaces(msg); + bnet_fsend(fd, runbefore, msg); + if (!response(jcr, fd, OKRunBefore, "ClientRunBeforeJob", DISPLAY_ERROR)) { + set_jcr_job_status(jcr, JS_ErrorTerminated); + free_pool_memory(msg); + return 0; + } + } + if (jcr->job->ClientRunAfterJob) { + fd->msglen = pm_strcpy(&msg, jcr->job->ClientRunAfterJob); + bash_spaces(msg); + bnet_fsend(fd, runafter, msg); + if (!response(jcr, fd, OKRunAfter, "ClientRunAfterJob", DISPLAY_ERROR)) { + set_jcr_job_status(jcr, JS_ErrorTerminated); + free_pool_memory(msg); + return 0; + } + } + free_pool_memory(msg); + return 1; +} + + /* * Read the attributes from the File daemon for * a Verify job and store them in the catalog. @@ -321,7 +487,7 @@ msglen=%d msg=%s\n"), len, fd->msglen, fd->msg); *fn = *p++; /* term filename and point to attribs */ attr = p; - if (stream == STREAM_UNIX_ATTRIBUTES || stream == STREAM_WIN32_ATTRIBUTES) { + if (stream == STREAM_UNIX_ATTRIBUTES || stream == STREAM_UNIX_ATTRIBUTES_EX) { jcr->JobFiles++; jcr->FileIndex = file_index; ar.attr = attr;