int db_get_pool_record(B_DB *db, POOL_DBR *pdbr);
int db_get_client_record(B_DB *mdb, CLIENT_DBR *cr);
int db_get_job_record(B_DB *mdb, JOB_DBR *jr);
-int db_get_job_volume_names(B_DB *mdb, uint32_t JobId, char *VolumeNames);
+int db_get_job_volume_names(B_DB *mdb, uint32_t JobId, POOLMEM **VolumeNames);
int db_get_file_attributes_record(B_DB *mdb, char *fname, FILE_DBR *fdbr);
int db_get_fileset_record(B_DB *mdb, FILESET_DBR *fsr);
int db_get_media_record(B_DB *mdb, MEDIA_DBR *mr);
* Volumes are concatenated in VolumeNames
* separated by a vertical bar (|).
*/
-int db_get_job_volume_names(B_DB *mdb, uint32_t JobId, char *VolumeNames)
+int db_get_job_volume_names(B_DB *mdb, uint32_t JobId, POOLMEM **VolumeNames)
{
SQL_ROW row;
int stat = 0;
AND JobMedia.MediaId=Media.MediaId", JobId);
Dmsg1(130, "VolNam=%s\n", mdb->cmd);
- VolumeNames[0] = 0;
+ *VolumeNames[0] = 0;
if (QUERY_DB(mdb, mdb->cmd)) {
mdb->num_rows = sql_num_rows(mdb);
Dmsg1(130, "Num rows=%d\n", mdb->num_rows);
stat = 0;
break;
} else {
- if (VolumeNames[0] != 0) {
- strcat(VolumeNames, "|");
+ if (*VolumeNames[0] != 0) {
+ pm_strcat(VolumeNames, "|");
}
- strcat(VolumeNames, row[0]);
+ pm_strcat(VolumeNames, row[0]);
}
}
}
}
bstrftime(sdt, sizeof(sdt), jcr->jr.StartTime);
bstrftime(edt, sizeof(edt), jcr->jr.EndTime);
- if (!db_get_job_volume_names(jcr->db, jcr->jr.JobId, jcr->VolumeName)) {
+ if (!db_get_job_volume_names(jcr->db, jcr->jr.JobId, &jcr->VolumeName)) {
jcr->VolumeName[0] = 0; /* none */
}
{
int stat, errstat;
- init_msg(jcr, jcr->msgs);
+ init_msg(jcr, jcr->messages);
create_unique_job_name(jcr, jcr->job->hdr.name);
jcr->jr.SchedTime = jcr->sched_time;
jcr->jr.StartTime = jcr->start_time;
jcr->pool = job->pool;
jcr->catalog = job->client->catalog;
jcr->fileset = job->fileset;
- jcr->msgs = job->messages;
+ jcr->messages = job->messages;
if (jcr->RestoreBootstrap) {
free(jcr->RestoreBootstrap);
}
*/
static char *edit_run_codes(JCR *jcr, char *omsg, char *imsg)
{
- char *p, *o;
+ char *p;
const char *str;
char add[20];
+ *omsg = 0;
Dmsg1(200, "edit_run_codes: %s\n", imsg);
- add[2] = 0;
- o = omsg;
for (p=imsg; *p; p++) {
if (*p == '%') {
switch (*++p) {
case '%':
- add[0] = '%';
- add[1] = 0;
- str = add;
+ str = "%";
break;
case 'c':
str = jcr->client_name;
default:
add[0] = '%';
add[1] = *p;
+ add[2] = 0;
str = add;
break;
}
str = add;
}
Dmsg1(200, "add_str %s\n", str);
- add_str_to_pool_mem(&omsg, &o, (char *)str);
- *o = 0;
+ pm_strcat(&omsg, (char *)str);
Dmsg1(200, "omsg=%s\n", omsg);
}
- *o = 0;
return omsg;
}
* Now find the Volumes we will need for the Restore
*/
jcr->VolumeName[0] = 0;
- if (!db_get_job_volume_names(jcr->db, rjr.JobId, jcr->VolumeName) ||
+ if (!db_get_job_volume_names(jcr->db, rjr.JobId, &jcr->VolumeName) ||
jcr->VolumeName[0] == 0) {
Jmsg(jcr, M_FATAL, 0, _("Cannot find Volume Name for restore Job %d. %s"),
rjr.JobId, db_strerror(jcr->db));
jcr->store = run->storage; /* override storage */
}
if (run->msgs) {
- jcr->msgs = run->msgs; /* override messages */
+ jcr->messages = run->msgs; /* override messages */
}
Dmsg0(200, "Leave wait_for_next_job()\n");
return jcr;
continue;
}
VolumeName = get_pool_memory(PM_FNAME);
- n = db_get_job_volume_names(ua->db, jobid, VolumeName);
+ n = db_get_job_volume_names(ua->db, jobid, &VolumeName);
bsendmsg(ua, _("Jobid %d used %d Volume(s): %s\n"), jobid, n, VolumeName);
- free_memory(VolumeName);
+ free_pool_memory(VolumeName);
done = TRUE;
}
/* if no job or jobid keyword found, then we list all media */
if (bsr->JobId) {
complete_bsr(ua, bsr); /* find Vol, SessId, SessTime from JobIds */
- print_bsr(ua, bsr);
+// print_bsr(ua, bsr);
write_bsr_file(ua, bsr);
} else {
bsendmsg(ua, _("No files selected to restore.\n"));
static int complete_bsr(UAContext *ua, RBSR *bsr)
{
JOB_DBR jr;
- char VolumeNames[1000]; /* ****FIXME**** */
+ POOLMEM *VolumeNames;
if (bsr) {
+ VolumeNames = get_pool_memory(PM_MESSAGE);
memset(&jr, 0, sizeof(jr));
jr.JobId = bsr->JobId;
if (!db_get_job_record(ua->db, &jr)) {
}
bsr->VolSessionId = jr.VolSessionId;
bsr->VolSessionTime = jr.VolSessionTime;
- if (!db_get_job_volume_names(ua->db, bsr->JobId, VolumeNames)) {
+ if (!db_get_job_volume_names(ua->db, bsr->JobId, &VolumeNames)) {
bsendmsg(ua, _("Unable to get Job Volumes. ERR=%s\n"), db_strerror(ua->db));
+ free_pool_memory(VolumeNames);
return 0;
}
bsr->VolumeName = bstrdup(VolumeNames);
+ free_pool_memory(VolumeNames);
return complete_bsr(ua, bsr->next);
}
return 1;
{
if (bsr) {
if (bsr->VolumeName) {
- fprintf(fd, "Volume=%s\n", bsr->VolumeName);
+ fprintf(fd, "Volume=\"%s\"\n", bsr->VolumeName);
}
fprintf(fd, "VolSessionId=%u\n", bsr->VolSessionId);
fprintf(fd, "VolSessionTime=%u\n", bsr->VolSessionTime);
{
if (bsr) {
if (bsr->VolumeName) {
- bsendmsg(ua, "Volume=%s\n", bsr->VolumeName);
+ bsendmsg(ua, "Volume=\"%s\"\n", bsr->VolumeName);
}
bsendmsg(ua, "VolSessionId=%u\n", bsr->VolSessionId);
bsendmsg(ua, "VolSessionTime=%u\n", bsr->VolSessionTime);
/* Create JCR to run job */
jcr = new_jcr(sizeof(JCR), dird_free_jcr);
set_jcr_defaults(jcr, job);
- init_msg(jcr, jcr->msgs); /* start message handler */
jcr->store = store;
jcr->client = client;
* Now find the Volumes we will need for the Verify
*/
jcr->VolumeName[0] = 0;
- if (!db_get_job_volume_names(jcr->db, jr.JobId, jcr->VolumeName) ||
+ if (!db_get_job_volume_names(jcr->db, jr.JobId, &jcr->VolumeName) ||
jcr->VolumeName[0] == 0) {
Jmsg(jcr, M_FATAL, 0, _("Cannot find Volume Name for verify JobId=%d. %s"),
jr.JobId, db_strerror(jcr->db));
POOLMEM *client_name; /* client name */
char *RestoreBootstrap; /* Bootstrap file to restore */
char *sd_auth_key; /* SD auth key */
- MSGS *msgs; /* Message resource */
+ MSGS *jcr_msgs; /* Copy of message resource -- actually used */
/* Daemon specific part of JCR */
/* This should be empty in the library */
POOL *pool; /* Pool resource */
FILESET *fileset; /* FileSet resource */
CAT *catalog; /* Catalog resource */
+ MSGS *messages; /* Default message handler */
int SDJobStatus; /* Storage Job Status */
int mode; /* manual/auto run */
B_DB *db; /* database pointer */
/*
* Initialize message handler for a daemon or a Job
+ * We make a copy of the MSGS resource passed, so it belows
+ * to the job or daemon and thus can be modified.
*
* NULL for jcr -> initialize global messages for daemon
* non-NULL -> initialize jcr using Message resource
}
if (jcr) {
- jcr->msgs = (MSGS *)malloc(sizeof(MSGS));
- memset(jcr->msgs, 0, sizeof(MSGS));
- jcr->msgs->dest_chain = temp_chain;
- memcpy(jcr->msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
+ jcr->jcr_msgs = (MSGS *)malloc(sizeof(MSGS));
+ memset(jcr->jcr_msgs, 0, sizeof(MSGS));
+ jcr->jcr_msgs->dest_chain = temp_chain;
+ memcpy(jcr->jcr_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
} else {
daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
memset(daemon_msgs, 0, sizeof(MSGS));
*/
static char *edit_job_codes(JCR *jcr, char *omsg, char *imsg, char *to)
{
- char *p, *o, *str;
+ char *p, *str;
char add[20];
+ *omsg = 0;
Dmsg1(200, "edit_job_codes: %s\n", imsg);
- add[2] = 0;
- o = omsg;
for (p=imsg; *p; p++) {
if (*p == '%') {
switch (*++p) {
case '%':
- add[0] = '%';
- add[1] = 0;
- str = add;
+ str = "%";
break;
case 'c':
str = jcr->client_name;
default:
add[0] = '%';
add[1] = *p;
+ add[2] = 0;
str = add;
break;
}
str = add;
}
Dmsg1(200, "add_str %s\n", str);
- add_str_to_pool_mem(&omsg, &o, str);
- *o = 0;
+ pm_strcat(&omsg, str);
Dmsg1(200, "omsg=%s\n", omsg);
}
- *o = 0;
return omsg;
}
/*
* Open a mail pipe
*/
-static FILE *open_mail_pipe(JCR *jcr, char **cmd, DEST *d)
+static FILE *open_mail_pipe(JCR *jcr, POOLMEM **cmd, DEST *d)
{
FILE *pfd;
msgs = daemon_msgs;
daemon_msgs = NULL;
} else {
- msgs = jcr->msgs;
- jcr->msgs = NULL;
+ msgs = jcr->jcr_msgs;
+ jcr->jcr_msgs = NULL;
}
if (msgs == NULL) {
return;
/* Now figure out where to send the message */
msgs = NULL;
if (jcr) {
- msgs = jcr->msgs;
+ msgs = jcr->jcr_msgs;
}
if (msgs == NULL) {
msgs = daemon_msgs;
msgs = NULL;
job = NULL;
if (jcr) {
- msgs = jcr->msgs;
+ msgs = jcr->jcr_msgs;
job = jcr->Job;
}
if (!msgs) {
int string_to_btime (char *str, btime_t *value);
char *edit_btime (btime_t val, char *buf);
void jobstatus_to_ascii (int JobStatus, char *msg, int maxlen);
-void add_str_to_pool_mem (POOLMEM **base, char **msg, char *str);
+void pm_strcat (POOLMEM **pm, char *str);
+void pm_strcpy (POOLMEM **pm, char *str);
int run_program (char *prog, int wait, POOLMEM *results);
char * job_type_to_str (int type);
char * job_status_to_str (int stat);
}
/*
- * Concatenate a string (str) onto a poolmem message (msg)
- * return new message pointer. The base of the pool memory
- * is base.
+ * Concatenate a string (str) onto a pool memory buffer pm
*/
-void add_str_to_pool_mem(POOLMEM **base, char **msg, char *str)
+void pm_strcat(POOLMEM **pm, char *str)
{
+ int pmlen = strlen(*pm);
int len = strlen(str) + 1;
- char *b, *m;
- b = *base;
- *base = check_pool_memory_size(*base, len);
- m = *base - b + *msg;
- while (*str) {
- *m++ = *str++;
- }
- *msg = m;
+ *pm = check_pool_memory_size(*pm, pmlen + len);
+ memcpy(*pm+pmlen, str, len);
+}
+
+
+/*
+ * Copy a string (str) into a pool memory buffer pm
+ */
+void pm_strcpy(POOLMEM **pm, char *str)
+{
+ int len = strlen(str) + 1;
+
+ *pm = check_pool_memory_size(*pm, len);
+ memcpy(*pm, str, len);
}
switch (ch) {
case 'b': /* bootstrap file */
bsr = parse_bsr(NULL, optarg);
- dump_bsr(bsr);
+// dump_bsr(bsr);
break;
case 'd': /* debug level */
/*
* !!!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- * !!! !!!
- * !!! All records must have a pointer to !!!
- * !!! the next item as the first item defined. !!!
- * !!! !!!
+ * !!! !!!
+ * !!! All records must have a pointer to !!!
+ * !!! the next item as the first item defined. !!!
+ * !!! !!!
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/
+typedef struct s_bsr_volume {
+ struct s_bsr_volume *next;
+ char VolumeName[MAX_NAME_LENGTH];
+} BSR_VOLUME;
+
typedef struct s_bsr_client {
struct s_bsr_client *next;
char ClientName[MAX_NAME_LENGTH];
typedef struct s_bsr_volfile {
struct s_bsr_volfile *next;
- uint32_t sfile; /* start file */
- uint32_t efile; /* end file */
+ uint32_t sfile; /* start file */
+ uint32_t efile; /* end file */
int found;
} BSR_VOLFILE;
typedef struct s_bsr_findex {
struct s_bsr_findex *next;
- int32_t findex; /* start file index */
- int32_t findex2; /* end file index */
+ int32_t findex; /* start file index */
+ int32_t findex2; /* end file index */
int found;
} BSR_FINDEX;
typedef struct s_bsr_stream {
struct s_bsr_stream *next;
- int32_t stream; /* stream desired */
+ int32_t stream; /* stream desired */
int found;
} BSR_STREAM;
typedef struct s_bsr {
- struct s_bsr *next; /* pointer to next one */
- int done; /* set when everything found */
- char *VolumeName;
- int32_t Slot; /* Slot */
- BSR_VOLFILE *volfile;
+ struct s_bsr *next; /* pointer to next one */
+ int done; /* set when everything found */
+ BSR_VOLUME *volume;
+ int32_t Slot; /* Slot */
+ BSR_VOLFILE *volfile;
BSR_SESSTIME *sesstime;
- BSR_SESSID *sessid;
- BSR_JOBID *JobId;
- BSR_JOB *job;
- BSR_CLIENT *client;
- BSR_FINDEX *FileIndex;
- BSR_JOBTYPE *JobType;
+ BSR_SESSID *sessid;
+ BSR_JOBID *JobId;
+ BSR_JOB *job;
+ BSR_CLIENT *client;
+ BSR_FINDEX *FileIndex;
+ BSR_JOBTYPE *JobType;
BSR_JOBLEVEL *JobLevel;
- BSR_STREAM *stream;
-// FF_PKT *ff; /* include/exclude */
+ BSR_STREAM *stream;
+// FF_PKT *ff; /* include/exclude */
} BSR;
*/
static char *edit_device_codes(JCR *jcr, char *omsg, char *imsg, char *cmd)
{
- char *p, *o;
+ char *p;
const char *str;
char add[20];
+ *omsg = 0;
Dmsg1(200, "edit_device_codes: %s\n", imsg);
- add[2] = 0;
- o = omsg;
for (p=imsg; *p; p++) {
if (*p == '%') {
switch (*++p) {
case '%':
- add[0] = '%';
- add[1] = 0;
- str = add;
+ str = "%";
break;
case 'a':
str = jcr->device->dev->dev_name;
str = jcr->Job;
break;
case 'v':
- str = jcr->VolumeName;
- if (!str) {
- str = "";
- }
+ str = NPRT(jcr->VolumeName);
break;
case 'f':
- str = jcr->client_name;
- if (!str) {
- str = "";
- }
+ str = NPRT(jcr->client_name);
break;
default:
add[0] = '%';
add[1] = *p;
+ add[2] = 0;
str = add;
break;
}
str = add;
}
Dmsg1(200, "add_str %s\n", str);
- add_str_to_pool_mem(&omsg, &o, (char *)str);
- *o = 0;
+ pm_strcat(&omsg, (char *)str);
Dmsg1(200, "omsg=%s\n", omsg);
}
- *o = 0;
return omsg;
}
goto bail_out;
}
while (bnet_recv(fd) > 0) {
- Dmsg1(000, "stored<filed: bootstrap file %s\n", fd->msg);
+ Dmsg1(400, "stored<filed: bootstrap file %s\n", fd->msg);
fputs(fd->msg, bs);
}
fclose(bs);
#include <fnmatch.h>
/* Forward references */
+static int match_volume(BSR_VOLUME *volume, VOLUME_LABEL *volrec);
static int match_sesstime(BSR_SESSTIME *sesstime, DEV_RECORD *rec);
static int match_sessid(BSR_SESSID *sessid, DEV_RECORD *rec);
static int match_client(BSR_CLIENT *client, SESSION_LABEL *sessrec);
static int match_one_bsr(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec, SESSION_LABEL *sessrec)
{
- if (strcmp(bsr->VolumeName, volrec->VolName) != 0) {
+ if (!match_volume(bsr->volume, volrec)) {
return 0;
}
if (!match_volfile(bsr->volfile, rec)) {
return 1;
}
+static int match_volume(BSR_VOLUME *volume, VOLUME_LABEL *volrec)
+{
+ if (!volume) {
+ return 0; /* Volume must match */
+ }
+ if (strcmp(volume->VolumeName, volrec->VolName) == 0) {
+ return 1;
+ }
+ if (volume->next) {
+ return match_volume(volume->next, volrec);
+ }
+ return 0;
+}
+
static int match_client(BSR_CLIENT *client, SESSION_LABEL *sessrec)
{
if (!client) {
ITEM_HANDLER *handler;
};
+/*
+ * List of all keywords permitted in bsr files and their handlers
+ */
struct kw_items items[] = {
{"volume", store_vol},
{"client", store_client},
};
+/*
+ * Create a BSR record
+ */
static BSR *new_bsr()
{
BSR *bsr = (BSR *)malloc(sizeof(BSR));
static BSR *store_vol(LEX *lc, BSR *bsr)
{
int token;
+ BSR_VOLUME *volume;
+ char *p, *n;
- token = lex_get_token(lc, T_NAME);
+ token = lex_get_token(lc, T_STRING);
if (token == T_ERROR) {
return NULL;
}
- if (bsr->VolumeName) {
- bsr->next = new_bsr();
- bsr = bsr->next;
+ /* This may actually be more than one volume separated by a |
+ * If so, separate them.
+ */
+ for (p=lc->str; p && *p; ) {
+ n = strchr(p, '|');
+ if (n) {
+ *n++ = 0;
+ }
+ volume = (BSR_VOLUME *)malloc(sizeof(BSR_VOLUME));
+ memset(volume, 0, sizeof(BSR_VOLUME));
+ strcpy(volume->VolumeName, p);
+ /* Add it to the end of the volume chain */
+ if (!bsr->volume) {
+ bsr->volume = volume;
+ } else {
+ BSR_VOLUME *bc = bsr->volume;
+ for ( ;bc->next; bc=bc->next)
+ { }
+ bc->next = volume;
+ }
+ p = n;
}
- bsr->VolumeName = bstrdup(lc->str);
- scan_to_eol(lc);
return bsr;
}
}
}
+void dump_volume(BSR_VOLUME *volume)
+{
+ if (volume) {
+ Dmsg1(-1, "VolumeName : %s\n", volume->VolumeName);
+ dump_volume(volume->next);
+ }
+}
+
void dump_client(BSR_CLIENT *client)
{
Dmsg0(-1, "BSR is NULL\n");
return;
}
- Dmsg2(-1,
-"Next : 0x%x\n"
-"VolumeName : %s\n",
- bsr->next,
- bsr->VolumeName ? bsr->VolumeName : "*None*");
+ Dmsg1(-1,
+"Next : 0x%x\n", bsr->next);
+ dump_volume(bsr->volume);
dump_sessid(bsr->sessid);
dump_sesstime(bsr->sesstime);
dump_volfile(bsr->volfile);
if (!bsr) {
return;
}
+ free_bsr_item((BSR *)bsr->volume);
free_bsr_item((BSR *)bsr->client);
free_bsr_item((BSR *)bsr->sessid);
free_bsr_item((BSR *)bsr->sesstime);
free_bsr_item((BSR *)bsr->FileIndex);
free_bsr_item((BSR *)bsr->JobType);
free_bsr_item((BSR *)bsr->JobLevel);
- if (bsr->VolumeName) {
- free(bsr->VolumeName);
- }
free_bsr(bsr->next);
free(bsr);
}
jcr->CurVolume = 1;
if (jcr->bsr) {
BSR *bsr = jcr->bsr;
- strcpy(jcr->VolumeName, bsr->VolumeName); /* setup first volume */
+ strcpy(jcr->VolumeName, bsr->volume->VolumeName); /* setup first volume */
for ( ; bsr; bsr=bsr->next) {
- vol = new_vol();
- strcpy(vol->VolumeName, bsr->VolumeName);
- if (add_vol(jcr, vol)) {
- jcr->NumVolumes++;
- Dmsg1(400, "Added volume %s\n", vol->VolumeName);
- } else {
- Dmsg1(400, "Duplicate volume %s\n", vol->VolumeName);
- free((char *)vol);
+ BSR_VOLUME *bsrvol = bsr->volume;
+ for ( ; bsrvol; bsrvol=bsrvol->next) {
+ vol = new_vol();
+ strcpy(vol->VolumeName, bsrvol->VolumeName);
+ if (add_vol(jcr, vol)) {
+ jcr->NumVolumes++;
+ Dmsg1(400, "Added volume %s\n", vol->VolumeName);
+ } else {
+ Dmsg1(400, "Duplicate volume %s\n", vol->VolumeName);
+ free((char *)vol);
+ }
}
}
} else {