- Document query file format.
Testing to do: (painful)
-- that restore options work in FD.
+- that restore options work in FD (mostly done).
- that console command line options work
- blocksize recognition code.
-- Test new BSR code
+- Test new BSR code (mostly done).
For 1.28 release:
- Get rid of bscan.c:534 error message (one time only).
- Print some statistics when get EOF on device in bscan -- feedback
to let user know it is working.
-- Add code to put VolFile in bsr for restore command.
- Add code to reject whole blocks if not wanted on restore.
- Add watchdog timeout for child processes start_child_timer()
end_child_timer();
- Make BSR accept count (total files to be restored).
- Add code to fast seek to proper place on tape/file when doing Restore.
- Replace popen() and pclose() -- fail safe and timeout, no SIG dep.
+- Add code to put VolFile in bsr for restore command.
+- Volumes can be listed multiple times in Restore volume list.
+
int db_get_job_volume_parameters(B_DB *mdb, uint32_t JobId, VOL_PARAMS **VolParams)
{ return 0; }
+int db_get_client_ids(B_DB *mdb, int *num_ids, uint32_t *ids[])
+{ return 0; }
+
+
+int db_get_client_record(B_DB *mdb, CLIENT_DBR *cdbr)
+{ return 0; }
#endif /* HAVE_BACULA_DB */
int db_get_num_media_records(B_DB *mdb);
int db_get_num_pool_records(B_DB *mdb);
int db_get_pool_ids(B_DB *mdb, int *num_ids, uint32_t **ids);
+int db_get_client_ids(B_DB *mdb, int *num_ids, uint32_t **ids);
int db_get_media_ids(B_DB *mdb, int *num_ids, uint32_t **ids);
int db_get_job_volume_parameters(B_DB *mdb, uint32_t JobId, VOL_PARAMS **VolParams);
+int db_get_client_record(B_DB *mdb, CLIENT_DBR *cdbr);
/* list.c */
del->JobId = (JobId_t *)brealloc(del->JobId, sizeof(JobId_t) *
del->max_ids);
}
- del->JobId[del->num_ids++] = (JobId_t)strtod(row[0], NULL);
+ del->JobId[del->num_ids++] = (JobId_t)str_to_int64(row[0]);
return 0;
}
}
/* Return fields in Media Record */
- mr->MediaId = atoi(row[0]);
+ mr->MediaId = str_to_int64(row[0]);
bstrncpy(mr->VolumeName, row[1], sizeof(mr->VolumeName));
- mr->VolJobs = atoi(row[2]);
- mr->VolFiles = atoi(row[3]);
- mr->VolBlocks = atoi(row[4]);
- mr->VolBytes = (uint64_t)strtod(row[5], NULL);
- mr->VolMounts = atoi(row[6]);
- mr->VolErrors = atoi(row[7]);
- mr->VolWrites = atoi(row[8]);
- mr->MaxVolBytes = (uint64_t)strtod(row[9], NULL);
- mr->VolCapacityBytes = (uint64_t)strtod(row[10], NULL);
- mr->VolRetention = (utime_t)strtod(row[11], NULL);
- mr->VolUseDuration = (utime_t)strtod(row[12], NULL);
- mr->MaxVolJobs = atoi(row[13]);
- mr->MaxVolFiles = atoi(row[14]);
- mr->Recycle = atoi(row[15]);
- mr->Slot = atoi(row[16]);
+ mr->VolJobs = str_to_int64(row[2]);
+ mr->VolFiles = str_to_int64(row[3]);
+ mr->VolBlocks = str_to_int64(row[4]);
+ mr->VolBytes = str_to_uint64(row[5]);
+ mr->VolMounts = str_to_int64(row[6]);
+ mr->VolErrors = str_to_int64(row[7]);
+ mr->VolWrites = str_to_int64(row[8]);
+ mr->MaxVolBytes = str_to_uint64(row[9]);
+ mr->VolCapacityBytes = str_to_uint64(row[10]);
+ mr->VolRetention = str_to_uint64(row[11]);
+ mr->VolUseDuration = str_to_uint64(row[12]);
+ mr->MaxVolJobs = str_to_int64(row[13]);
+ mr->MaxVolFiles = str_to_int64(row[14]);
+ mr->Recycle = str_to_int64(row[15]);
+ mr->Slot = str_to_int64(row[16]);
bstrncpy(mr->cFirstWritten, row[17]!=NULL?row[17]:"", sizeof(mr->cFirstWritten));
sql_free_result(mdb);
if ((row = sql_fetch_row(mdb)) == NULL) {
Mmsg1(&mdb->errmsg, _("Error fetching row: %s\n"), sql_strerror(mdb));
} else {
- fdbr->FileId = (FileId_t)strtod(row[0], NULL);
+ fdbr->FileId = (FileId_t)str_to_int64(row[0]);
strncpy(fdbr->LStat, row[1], sizeof(fdbr->LStat));
fdbr->LStat[sizeof(fdbr->LStat)] = 0;
strncpy(fdbr->MD5, row[2], sizeof(fdbr->MD5));
return 0; /* failed */
}
- jr->VolSessionId = atol(row[0]);
- jr->VolSessionTime = atol(row[1]);
+ jr->VolSessionId = str_to_uint64(row[0]);
+ jr->VolSessionTime = str_to_uint64(row[1]);
jr->PoolId = atoi(row[2]);
bstrncpy(jr->cStartTime, row[3]!=NULL?row[3]:"", sizeof(jr->cStartTime));
bstrncpy(jr->cEndTime, row[4]!=NULL?row[4]:"", sizeof(jr->cEndTime));
jr->JobFiles = atol(row[5]);
- jr->JobBytes = (uint64_t)strtod(row[6], NULL);
- jr->JobTDate = (utime_t)strtod(row[7], NULL);
+ jr->JobBytes = str_to_int64(row[6]);
+ jr->JobTDate = str_to_int64(row[7]);
bstrncpy(jr->Job, row[8]!=NULL?row[8]:"", sizeof(jr->Job));
jr->JobStatus = (int)*row[9];
jr->Type = (int)*row[10];
return stat;
}
+/*
+ * This function returns a list of all the Client record ids.
+ * The caller must free ids if non-NULL.
+ *
+ * Returns 0: on failure
+ * 1: on success
+ */
+int db_get_client_ids(B_DB *mdb, int *num_ids, uint32_t *ids[])
+{
+ SQL_ROW row;
+ int stat = 0;
+ int i = 0;
+ uint32_t *id;
+
+ db_lock(mdb);
+ *ids = NULL;
+ Mmsg(&mdb->cmd, "SELECT ClientId FROM Client");
+ if (QUERY_DB(mdb, mdb->cmd)) {
+ *num_ids = sql_num_rows(mdb);
+ if (*num_ids > 0) {
+ id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
+ while ((row = sql_fetch_row(mdb)) != NULL) {
+ id[i++] = (uint32_t)atoi(row[0]);
+ }
+ *ids = id;
+ }
+ sql_free_result(mdb);
+ stat = 1;
+ } else {
+ Mmsg(&mdb->errmsg, _("Client id select failed: ERR=%s\n"), sql_strerror(mdb));
+ Jmsg(mdb->jcr, M_ERROR, 0, "%s", mdb->errmsg);
+ stat = 0;
+ }
+ db_unlock(mdb);
+ return stat;
+}
+
+
/* Get Pool Record
* If the PoolId is non-zero, we get its record,
Mmsg(&mdb->cmd,
"SELECT PoolId,Name,NumVols,MaxVols,UseOnce,UseCatalog,AcceptAnyVolume,\
AutoPrune,Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,\
-MaxVolBytes,PoolType,LabelFormat FROM Pool WHERE Pool.PoolId=%d", pdbr->PoolId);
+MaxVolBytes,PoolType,LabelFormat FROM Pool WHERE Pool.PoolId=%u", pdbr->PoolId);
} else { /* find by name */
Mmsg(&mdb->cmd,
"SELECT PoolId,Name,NumVols,MaxVols,UseOnce,UseCatalog,AcceptAnyVolume,\
Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
Jmsg(mdb->jcr, M_ERROR, 0, "%s", mdb->errmsg);
} else {
- pdbr->PoolId = atoi(row[0]);
+ pdbr->PoolId = str_to_int64(row[0]);
bstrncpy(pdbr->Name, row[1]!=NULL?row[1]:"", sizeof(pdbr->Name));
- pdbr->NumVols = atoi(row[2]);
- pdbr->MaxVols = atoi(row[3]);
- pdbr->UseOnce = atoi(row[4]);
- pdbr->UseCatalog = atoi(row[5]);
- pdbr->AcceptAnyVolume = atoi(row[6]);
- pdbr->AutoPrune = atoi(row[7]);
- pdbr->Recycle = atoi(row[8]);
- pdbr->VolRetention = (utime_t)strtod(row[9], NULL);
- pdbr->VolUseDuration = (utime_t)strtod(row[10], NULL);
- pdbr->MaxVolJobs = atoi(row[11]);
- pdbr->MaxVolFiles = atoi(row[12]);
- pdbr->MaxVolBytes = (uint64_t)strtod(row[13], NULL);
+ pdbr->NumVols = str_to_int64(row[2]);
+ pdbr->MaxVols = str_to_int64(row[3]);
+ pdbr->UseOnce = str_to_int64(row[4]);
+ pdbr->UseCatalog = str_to_int64(row[5]);
+ pdbr->AcceptAnyVolume = str_to_int64(row[6]);
+ pdbr->AutoPrune = str_to_int64(row[7]);
+ pdbr->Recycle = str_to_int64(row[8]);
+ pdbr->VolRetention = str_to_int64(row[9]);
+ pdbr->VolUseDuration = str_to_int64(row[10]);
+ pdbr->MaxVolJobs = str_to_int64(row[11]);
+ pdbr->MaxVolFiles = str_to_int64(row[12]);
+ pdbr->MaxVolBytes = str_to_uint64(row[13]);
bstrncpy(pdbr->PoolType, row[13]!=NULL?row[14]:"", sizeof(pdbr->PoolType));
bstrncpy(pdbr->LabelFormat, row[14]!=NULL?row[15]:"", sizeof(pdbr->LabelFormat));
stat = pdbr->PoolId;
return stat;
}
+/* Get Client Record
+ * If the ClientId is non-zero, we get its record,
+ * otherwise, we search on the Client Name
+ *
+ * Returns: 0 on failure
+ * 1 on success
+ */
+int db_get_client_record(B_DB *mdb, CLIENT_DBR *cdbr)
+{
+ SQL_ROW row;
+ int stat = 0;
+
+ db_lock(mdb);
+ if (cdbr->ClientId != 0) { /* find by id */
+ Mmsg(&mdb->cmd,
+"SELECT ClientId,Name,Uname,AutoPrune,FileRetention,JobRetention "
+"FROM Client WHERE Client.ClientId=%u", cdbr->ClientId);
+ } else { /* find by name */
+ Mmsg(&mdb->cmd,
+"SELECT ClientId,Name,Uname,AutoPrune,FileRetention,JobRetention "
+"FROM Client WHERE Client.Name='%s'", cdbr->Name);
+ }
+
+ if (QUERY_DB(mdb, mdb->cmd)) {
+ mdb->num_rows = sql_num_rows(mdb);
+ if (mdb->num_rows > 1) {
+ char ed1[30];
+ Mmsg1(&mdb->errmsg, _("More than one Client!: %s\n"),
+ edit_uint64(mdb->num_rows, ed1));
+ Jmsg(mdb->jcr, M_ERROR, 0, "%s", mdb->errmsg);
+ } else if (mdb->num_rows == 1) {
+ if ((row = sql_fetch_row(mdb)) == NULL) {
+ Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
+ Jmsg(mdb->jcr, M_ERROR, 0, "%s", mdb->errmsg);
+ } else {
+ cdbr->ClientId = str_to_int64(row[0]);
+ bstrncpy(cdbr->Name, row[1]!=NULL?row[1]:"", sizeof(cdbr->Name));
+ bstrncpy(cdbr->Uname, row[2]!=NULL?row[1]:"", sizeof(cdbr->Uname));
+ cdbr->AutoPrune = str_to_int64(row[3]);
+ cdbr->FileRetention = str_to_int64(row[4]);
+ cdbr->JobRetention = str_to_int64(row[5]);
+ stat = 1;
+ }
+ }
+ sql_free_result(mdb);
+ }
+ db_unlock(mdb);
+ return stat;
+}
+
+
/* Get FileSet Record
* If the FileSetId is non-zero, we get its record,
* otherwise, we search on the name
Jmsg(mdb->jcr, M_ERROR, 0, "%s", mdb->errmsg);
} else {
/* return values */
- mr->MediaId = atoi(row[0]);
+ mr->MediaId = str_to_int64(row[0]);
bstrncpy(mr->VolumeName, row[1]!=NULL?row[1]:"", sizeof(mr->VolumeName));
- mr->VolJobs = atoi(row[2]);
- mr->VolFiles = atoi(row[3]);
- mr->VolBlocks = atoi(row[4]);
- mr->VolBytes = (uint64_t)strtod(row[5], NULL);
- mr->VolMounts = atoi(row[6]);
- mr->VolErrors = atoi(row[7]);
- mr->VolWrites = atoi(row[8]);
- mr->MaxVolBytes = (uint64_t)strtod(row[9], NULL);
- mr->VolCapacityBytes = (uint64_t)strtod(row[10], NULL);
+ mr->VolJobs = str_to_int64(row[2]);
+ mr->VolFiles = str_to_int64(row[3]);
+ mr->VolBlocks = str_to_int64(row[4]);
+ mr->VolBytes = str_to_uint64(row[5]);
+ mr->VolMounts = str_to_int64(row[6]);
+ mr->VolErrors = str_to_int64(row[7]);
+ mr->VolWrites = str_to_int64(row[8]);
+ mr->MaxVolBytes = str_to_uint64(row[9]);
+ mr->VolCapacityBytes = str_to_uint64(row[10]);
bstrncpy(mr->MediaType, row[11]!=NULL?row[11]:"", sizeof(mr->MediaType));
bstrncpy(mr->VolStatus, row[12]!=NULL?row[12]:"", sizeof(mr->VolStatus));
- mr->PoolId = atoi(row[13]);
- mr->VolRetention = (utime_t)strtod(row[14], NULL);
- mr->VolUseDuration = (utime_t)strtod(row[15], NULL);
- mr->MaxVolJobs = atoi(row[16]);
- mr->MaxVolFiles = atoi(row[17]);
- mr->Recycle = atoi(row[18]);
- mr->Slot = atoi(row[19]);
+ mr->PoolId = str_to_int64(row[13]);
+ mr->VolRetention = str_to_uint64(row[14]);
+ mr->VolUseDuration = str_to_uint64(row[15]);
+ mr->MaxVolJobs = str_to_int64(row[16]);
+ mr->MaxVolFiles = str_to_int64(row[17]);
+ mr->Recycle = str_to_int64(row[18]);
+ mr->Slot = str_to_int64(row[19]);
bstrncpy(mr->cFirstWritten, row[20]!=NULL?row[20]:"", sizeof(mr->cFirstWritten));
stat = mr->MediaId;
}
char *select_job =
"SELECT JobId from Job "
"WHERE JobTDate < %s "
- "AND ClientId=%d "
+ "AND ClientId=%u "
"AND PurgedFiles=0";
/* Delete temp tables and indexes */
"INSERT INTO DelCandidates "
"SELECT JobId, PurgedFiles, FileSetId FROM Job "
"WHERE JobTDate < %s "
- "AND ClientId=%d";
+ "AND ClientId=%u";
/* Select files from the DelCandidates table that have a
* more recent backup -- i.e. are not the only backup.
"SELECT DelCandidates.JobId "
"FROM Job,DelCandidates "
"WHERE Job.JobTDate >= %s "
- "AND Job.ClientId=%d "
+ "AND Job.ClientId=%u "
"AND Job.JobType='B' "
"AND Job.Level='F' "
"AND Job.JobStatus='T' "
"SELECT DelCandidates.JobId "
"FROM Job,DelCandidates "
"WHERE Job.JobTDate >= %s "
- "AND Job.ClientId=%d "
+ "AND Job.ClientId=%u "
"AND Job.JobType='V' "
"AND Job.Level='V' "
"AND Job.JobStatus='T' "
"SELECT DelCandidates.JobId "
"FROM Job,DelCandidates "
"WHERE Job.JobTDate >= %s "
- "AND Job.ClientId=%d "
+ "AND Job.ClientId=%u "
"AND Job.JobType='R'";
char *uar_create_temp1 =
"CREATE TABLE temp1 (JobId INTEGER UNSIGNED NOT NULL,"
- "JobTDate BIGINT UNSIGNED,"
- "ClientId INTEGER UNSIGNED)";
+ "JobTDate BIGINT UNSIGNED)";
char *uar_last_full =
- "INSERT INTO temp1 SELECT Job.JobId,JobTdate,Job.ClientId "
- "FROM Client,Job,JobMedia,Media WHERE Client.Name='%s' "
- "AND Client.ClientId=Job.ClientId "
+ "INSERT INTO temp1 SELECT Job.JobId,JobTdate "
+ "FROM Client,Job,JobMedia,Media WHERE Client.ClientId=%u "
+ "AND Job.ClientId=%u "
"AND Level='F' AND JobStatus='T' "
"AND JobMedia.JobId=Job.JobId "
"AND JobMedia.MediaId=Media.MediaId "
"Job.Level,Job.JobFiles,Job.StartTime,Media.VolumeName,JobMedia.StartFile,"
"Job.VolSessionId,Job.VolSessionTime "
"FROM Job,JobMedia,Media "
- "WHERE Job.JobTDate>%d AND Job.ClientId=%u "
+ "WHERE Job.JobTDate>%s AND Job.ClientId=%u "
"AND JobMedia.JobId=Job.JobId "
"AND JobMedia.MediaId=Media.MediaId "
"AND Job.Level='I' AND JobStatus='T' "
char *uar_sel_fileset =
"SELECT FileSet.FileSetId,FileSet.FileSet,FileSet.MD5 FROM Job,"
"Client,FileSet WHERE Job.FileSetId=FileSet.FileSetId "
- "AND Job.ClientId=Client.ClientId AND Client.Name='%s' "
+ "AND Job.ClientId=%u AND Client.ClientId=%u "
"GROUP BY FileSet.FileSetId";
/* Find MediaType used by this Job */
JCR *jcr;
B_DB *db;
CAT *catalog;
- POOLMEM *cmd; /* return command/name buffer */
- POOLMEM *args; /* command line arguments */
- char *argk[MAX_ARGS]; /* argument keywords */
- char *argv[MAX_ARGS]; /* argument values */
- int argc; /* number of arguments */
- char **prompt; /* list of prompts */
- int max_prompts; /* max size of list */
- int num_prompts; /* current number in list */
- int auto_display_messages; /* if set, display messages */
+ POOLMEM *cmd; /* return command/name buffer */
+ POOLMEM *args; /* command line arguments */
+ char *argk[MAX_ARGS]; /* argument keywords */
+ char *argv[MAX_ARGS]; /* argument values */
+ int argc; /* number of arguments */
+ char **prompt; /* list of prompts */
+ int max_prompts; /* max size of list */
+ int num_prompts; /* current number in list */
+ int auto_display_messages; /* if set, display messages */
int user_notified_msg_pending; /* set when user notified */
- int automount; /* if set, mount after label */
- int quit; /* if set, quit */
- int verbose; /* set for normal UA verbosity */
+ int automount; /* if set, mount after label */
+ int quit; /* if set, quit */
+ int verbose; /* set for normal UA verbosity */
} UAContext;
/* ua_cmds.c */
void bsendmsg(void *sock, char *fmt, ...);
/* ua_select.c */
-STORE *select_storage_resource(UAContext *ua);
-JOB *select_job_resource(UAContext *ua);
-JOB *select_restore_job_resource(UAContext *ua);
-CLIENT *select_client_resource(UAContext *ua);
+STORE *select_storage_resource(UAContext *ua);
+JOB *select_job_resource(UAContext *ua);
+JOB *select_restore_job_resource(UAContext *ua);
+CLIENT *select_client_resource(UAContext *ua);
FILESET *select_fileset_resource(UAContext *ua);
-int select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr);
-int select_pool_dbr(UAContext *ua, POOL_DBR *pr);
+int select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr);
+int select_pool_dbr(UAContext *ua, POOL_DBR *pr);
+int select_client_dbr(UAContext *ua, CLIENT_DBR *cr);
-void start_prompt(UAContext *ua, char *msg);
-void add_prompt(UAContext *ua, char *prompt);
-int do_prompt(UAContext *ua, char *msg, char *prompt, int max_prompt);
-CAT *get_catalog_resource(UAContext *ua);
+void start_prompt(UAContext *ua, char *msg);
+void add_prompt(UAContext *ua, char *prompt);
+int do_prompt(UAContext *ua, char *msg, char *prompt, int max_prompt);
+CAT *get_catalog_resource(UAContext *ua);
STORE *get_storage_resource(UAContext *ua, char *cmd);
-int get_media_type(UAContext *ua, char *MediaType, int max_media);
-int get_pool_dbr(UAContext *ua, POOL_DBR *pr);
+int get_media_type(UAContext *ua, char *MediaType, int max_media);
+int get_pool_dbr(UAContext *ua, POOL_DBR *pr);
+int get_client_dbr(UAContext *ua, CLIENT_DBR *cr);
POOL *get_pool_resource(UAContext *ua);
CLIENT *get_client_resource(UAContext *ua);
-int get_job_dbr(UAContext *ua, JOB_DBR *jr);
+int get_job_dbr(UAContext *ua, JOB_DBR *jr);
int find_arg_keyword(UAContext *ua, char **list);
int do_keyword_prompt(UAContext *ua, char *msg, char **list);
del->JobId = (JobId_t *)brealloc(del->JobId, sizeof(JobId_t) * del->max_ids);
del->PurgedFiles = (char *)brealloc(del->PurgedFiles, del->max_ids);
}
- del->JobId[del->num_ids] = (JobId_t)strtod(row[0], NULL);
- del->PurgedFiles[del->num_ids++] = (char)atoi(row[0]);
+ del->JobId[del->num_ids] = (JobId_t)str_to_int64(row[0]);
+ del->PurgedFiles[del->num_ids++] = (char)str_to_int64(row[0]);
return 0;
}
del->JobId = (JobId_t *)brealloc(del->JobId, sizeof(JobId_t) *
del->max_ids);
}
- del->JobId[del->num_ids++] = (JobId_t)strtod(row[0], NULL);
+ del->JobId[del->num_ids++] = (JobId_t)str_to_int64(row[0]);
return 0;
}
del->JobId = (JobId_t *)brealloc(del->JobId, sizeof(JobId_t) * del->max_ids);
del->PurgedFiles = (char *)brealloc(del->PurgedFiles, del->max_ids);
}
- del->JobId[del->num_ids] = (JobId_t)strtod(row[0], NULL);
- del->PurgedFiles[del->num_ids++] = (char)atoi(row[0]);
+ del->JobId[del->num_ids] = (JobId_t)str_to_int64(row[0]);
+ del->PurgedFiles[del->num_ids++] = (char)str_to_int64(row[0]);
return 0;
}
del->JobId = (JobId_t *)brealloc(del->JobId, sizeof(JobId_t) *
del->max_ids);
}
- del->JobId[del->num_ids++] = (JobId_t)strtod(row[0], NULL);
+ del->JobId[del->num_ids++] = (JobId_t)str_to_int64(row[0]);
return 0;
}
/* Main structure for obtaining JobIds */
typedef struct s_jobids {
utime_t JobTDate;
- uint32_t ClientId;
uint32_t TotalFiles;
+ char ClientName[MAX_NAME_LENGTH];
char JobIds[200];
- CLIENT *client;
STORE *store;
} JobIds;
uint32_t JobId; /* JobId this bsr */
uint32_t VolSessionId;
uint32_t VolSessionTime;
- uint32_t StartFile;
- uint32_t EndFile;
- uint32_t StartBlock;
- uint32_t EndBlock;
- char *VolumeName; /* Volume name */
+ int VolCount; /* Volume parameter count */
+ VOL_PARAMS *VolParams; /* Volume, start/end file/blocks */
RBSR_FINDEX *fi; /* File indexes this JobId */
} RBSR;
return 0;
}
- if (ji.client) {
+ if (ji.ClientName[0]) {
Mmsg(&ua->cmd,
"run job=\"%s\" client=\"%s\" storage=\"%s\" bootstrap=\"%s/restore.bsr\"",
- job->hdr.name, ji.client->hdr.name, ji.store?ji.store->hdr.name:"",
+ job->hdr.name, ji.ClientName, ji.store?ji.store->hdr.name:"",
working_directory);
} else {
Mmsg(&ua->cmd,
static int user_select_jobids(UAContext *ua, JobIds *ji)
{
char fileset_name[MAX_NAME_LENGTH];
- char *p;
+ char *p, ed1[50];
FILESET_DBR fsr;
+ CLIENT_DBR cr;
JobId_t JobId;
JOB_DBR jr;
POOLMEM *query;
bsendmsg(ua, "%s\n", db_strerror(ua->db));
}
/*
- * Select Client
+ * Select Client from the Catalog
*/
- if (!(ji->client = get_client_resource(ua))) {
+ memset(&cr, 0, sizeof(cr));
+ if (!get_client_dbr(ua, &cr)) {
+ free_pool_memory(query);
+ db_sql_query(ua->db, uar_del_temp, NULL, NULL);
+ db_sql_query(ua->db, uar_del_temp1, NULL, NULL);
return 0;
}
+ bstrncpy(ji->ClientName, cr.Name, sizeof(ji->ClientName));
/*
* Select FileSet
*/
- Mmsg(&query, uar_sel_fileset, ji->client->hdr.name);
+ Mmsg(&query, uar_sel_fileset, cr.ClientId, cr.ClientId);
start_prompt(ua, _("The defined FileSet resources are:\n"));
if (!db_sql_query(ua->db, query, fileset_handler, (void *)ua)) {
bsendmsg(ua, "%s\n", db_strerror(ua->db));
if (do_prompt(ua, _("Select FileSet resource"),
fileset_name, sizeof(fileset_name)) < 0) {
free_pool_memory(query);
+ db_sql_query(ua->db, uar_del_temp, NULL, NULL);
+ db_sql_query(ua->db, uar_del_temp1, NULL, NULL);
return 0;
}
fsr.FileSetId = atoi(fileset_name); /* Id is first part of name */
}
/* Find JobId of last Full backup for this client, fileset */
- Mmsg(&query, uar_last_full, ji->client->hdr.name, fsr.FileSetId);
+ Mmsg(&query, uar_last_full, cr.ClientId, cr.ClientId, fsr.FileSetId);
if (!db_sql_query(ua->db, query, NULL, NULL)) {
bsendmsg(ua, "%s\n", db_strerror(ua->db));
}
bsendmsg(ua, "%s\n", db_strerror(ua->db));
}
/* Now find all Incremental Jobs */
- Mmsg(&query, uar_inc, (uint32_t)ji->JobTDate, ji->ClientId, fsr.FileSetId);
+ Mmsg(&query, uar_inc, edit_uint64(ji->JobTDate, ed1), cr.ClientId, fsr.FileSetId);
if (!db_sql_query(ua->db, query, NULL, NULL)) {
bsendmsg(ua, "%s\n", db_strerror(ua->db));
}
{
JobIds *ji = (JobIds *)ctx;
- ji->JobTDate = atoi(row[1]);
- ji->ClientId = atoi(row[2]);
+ ji->JobTDate = strtoll(row[1], NULL, 10);
return 0;
}
if (bsr) {
free_findex(bsr->fi);
free_bsr(bsr->next);
- if (bsr->VolumeName) {
- free(bsr->VolumeName);
+ if (bsr->VolParams) {
+ free(bsr->VolParams);
}
free(bsr);
}
static int complete_bsr(UAContext *ua, RBSR *bsr)
{
JOB_DBR jr;
- VOL_PARAMS *VolParams;
- int count = 0;
if (bsr) {
memset(&jr, 0, sizeof(jr));
}
bsr->VolSessionId = jr.VolSessionId;
bsr->VolSessionTime = jr.VolSessionTime;
- if ((count=db_get_job_volume_parameters(ua->db, bsr->JobId, &VolParams)) == 0) {
+ if ((bsr->VolCount=db_get_job_volume_parameters(ua->db, bsr->JobId,
+ &(bsr->VolParams))) == 0) {
bsendmsg(ua, _("Unable to get Job Volume Parameters. ERR=%s\n"), db_strerror(ua->db));
- free((char *)VolParams);
+ if (bsr->VolParams) {
+ free(bsr->VolParams);
+ }
return 0;
}
- bsr->VolumeName = bstrdup(VolParams[0].VolumeName);
- bsr->StartFile = VolParams[0].StartFile;
- bsr->EndFile = VolParams[0].EndFile;
- bsr->StartBlock = VolParams[0].StartBlock;
- bsr->EndBlock = VolParams[0].EndBlock;
- free((char *)VolParams);
return complete_bsr(ua, bsr->next);
}
return 1;
fclose(fd);
bsendmsg(ua, _("Bootstrap records written to %s\n"), fname);
bsendmsg(ua, _("\nThe restore job will require the following Volumes:\n"));
+ /* Create Unique list of Volumes using prompt list */
+ start_prompt(ua, "");
for (nbsr=bsr; nbsr; nbsr=nbsr->next) {
- if (nbsr->VolumeName) {
- bsendmsg(ua, " %s\n", nbsr->VolumeName);
+ for (int i=0; i < nbsr->VolCount; i++) {
+ add_prompt(ua, nbsr->VolParams[i].VolumeName);
}
}
+ for (int i=1; i < ua->num_prompts; i++) {
+ bsendmsg(ua, " %s\n", ua->prompt[i]);
+ free(ua->prompt[i]);
+ }
+ ua->num_prompts = 0;
bsendmsg(ua, "\n");
free_pool_memory(fname);
return stat;
static void write_bsr(UAContext *ua, RBSR *bsr, FILE *fd)
{
if (bsr) {
- if (bsr->VolumeName) {
- fprintf(fd, "Volume=\"%s\"\n", bsr->VolumeName);
+ for (int i=0; i < bsr->VolCount; i++) {
+ fprintf(fd, "Volume=\"%s\"\n", bsr->VolParams[i].VolumeName);
+ fprintf(fd, "VolSessionId=%u\n", bsr->VolSessionId);
+ fprintf(fd, "VolSessionTime=%u\n", bsr->VolSessionTime);
+ fprintf(fd, "VolFile=%u-%u\n", bsr->VolParams[i].StartFile,
+ bsr->VolParams[i].EndFile);
+ fprintf(fd, "VolBlock=%u-%u\n", bsr->VolParams[i].StartBlock,
+ bsr->VolParams[i].EndBlock);
+ write_findex(ua, bsr->fi, fd);
}
- fprintf(fd, "VolSessionId=%u\n", bsr->VolSessionId);
- fprintf(fd, "VolSessionTime=%u\n", bsr->VolSessionTime);
- fprintf(fd, "VolFile=%u-%u\n", bsr->StartFile, bsr->EndFile);
- write_findex(ua, bsr->fi, fd);
write_bsr(ua, bsr->next, fd);
}
}
static void print_bsr(UAContext *ua, RBSR *bsr)
{
if (bsr) {
- if (bsr->VolumeName) {
- bsendmsg(ua, "Volume=\"%s\"\n", bsr->VolumeName);
+ for (int i=0; i < bsr->VolCount; i++) {
+ bsendmsg(ua, "Volume=\"%s\"\n", bsr->VolParams[i].VolumeName);
+ bsendmsg(ua, "VolSessionId=%u\n", bsr->VolSessionId);
+ bsendmsg(ua, "VolSessionTime=%u\n", bsr->VolSessionTime);
+ bsendmsg(ua, "VolFile=%u-%u\n", bsr->VolParams[i].StartFile,
+ bsr->VolParams[i].EndFile);
+ bsendmsg(ua, "VolBlock=%u-%u\n", bsr->VolParams[i].StartBlock,
+ bsr->VolParams[i].EndBlock);
+ print_findex(ua, bsr->fi);
}
- bsendmsg(ua, "VolSessionId=%u\n", bsr->VolSessionId);
- bsendmsg(ua, "VolSessionTime=%u\n", bsr->VolSessionTime);
- print_findex(ua, bsr->fi);
print_bsr(ua, bsr->next);
}
}
return select_client_resource(ua);
}
+/* Scan what the user has entered looking for:
+ *
+ * client=<client-name>
+ *
+ * if error or not found, put up a list of client DBRs
+ * to choose from.
+ *
+ * returns: 0 on error
+ * 1 on success and fills in CLIENT_DBR
+ */
+int get_client_dbr(UAContext *ua, CLIENT_DBR *cr)
+{
+ int i;
+
+ if (cr->Name[0]) { /* If name already supplied */
+ if (db_get_client_record(ua->db, cr)) {
+ return 1;
+ }
+ bsendmsg(ua, _("Could not find Client %s: ERR=%s"), cr->Name, db_strerror(ua->db));
+ }
+ for (i=1; i<ua->argc; i++) {
+ if (strcasecmp(ua->argk[i], _("client")) == 0 && ua->argv[i]) {
+ bstrncpy(cr->Name, ua->argv[i], sizeof(cr->Name));
+ if (!db_get_client_record(ua->db, cr)) {
+ bsendmsg(ua, _("Could not find Client %s: ERR=%s"), ua->argv[i],
+ db_strerror(ua->db));
+ cr->ClientId = 0;
+ break;
+ }
+ return 1;
+ }
+ }
+ if (!select_client_dbr(ua, cr)) { /* try once more by proposing a list */
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * Select a Client record from the catalog
+ * Returns 1 on success
+ * 0 on failure
+ */
+int select_client_dbr(UAContext *ua, CLIENT_DBR *cr)
+{
+ CLIENT_DBR ocr;
+ char name[MAX_NAME_LENGTH];
+ int num_clients, i;
+ uint32_t *ids;
+
+
+ cr->ClientId = 0;
+ if (!db_get_client_ids(ua->db, &num_clients, &ids)) {
+ bsendmsg(ua, _("Error obtaining client ids. ERR=%s\n"), db_strerror(ua->db));
+ return 0;
+ }
+ if (num_clients <= 0) {
+ bsendmsg(ua, _("No clients defined. Run a job to create one.\n"));
+ return 0;
+ }
+
+ start_prompt(ua, _("Defined Clients:\n"));
+ for (i=0; i < num_clients; i++) {
+ ocr.ClientId = ids[i];
+ if (!db_get_client_record(ua->db, &ocr)) {
+ continue;
+ }
+ add_prompt(ua, ocr.Name);
+ }
+ free(ids);
+ if (do_prompt(ua, _("Select the Client"), name, sizeof(name)) < 0) {
+ return 0;
+ }
+ memset(&ocr, 0, sizeof(ocr));
+ bstrncpy(ocr.Name, name, sizeof(ocr.Name));
+
+ if (!db_get_client_record(ua->db, &ocr)) {
+ bsendmsg(ua, _("Could not find Client %s: ERR=%s"), name, db_strerror(ua->db));
+ return 0;
+ }
+ memcpy(cr, &ocr, sizeof(ocr));
+ return 1;
+}
+
+
+
/* Scan what the user has entered looking for:
*
* pool=<pool-name>
* to choose from.
*
* returns: 0 on error
- * poolid on success and fills in POOL_DBR
+ * 1 on success and fills in POOL_DBR
*/
int get_pool_dbr(UAContext *ua, POOL_DBR *pr)
{
if (!select_pool_dbr(ua, pr)) { /* try once more */
return 0;
}
- return pr->PoolId;
+ return 1;
}
/*
if (do_prompt(ua, _("Select the Pool"), name, sizeof(name)) < 0) {
return 0;
}
- memset(&opr, 0, sizeof(pr));
+ memset(&opr, 0, sizeof(opr));
bstrncpy(opr.Name, name, sizeof(opr.Name));
if (!db_get_pool_record(ua->db, &opr)) {
return 0;
}
memcpy(pr, &opr, sizeof(opr));
- return opr.PoolId;
+ return 1;
}
/*
LIBSRCS = alloc.c base64.c bmisc.c bnet.c bnet_server.c \
bpipe.c bshm.c btime.c \
- cram-md5.c crc32.c daemon.c fnmatch.c \
+ cram-md5.c crc32.c daemon.c edit.c fnmatch.c \
hmac.c idcache.c jcr.c lex.c \
md5.c message.c mem_pool.c parse_conf.c \
queue.c rwlock.c serial.c \
LIBOBJS = alloc.o base64.o bmisc.o bnet.o bnet_server.o \
bpipe.o bshm.o btime.o \
- cram-md5.o crc32.o daemon.o fnmatch.o \
+ cram-md5.o crc32.o daemon.o edit.o fnmatch.o \
hmac.o idcache.o jcr.o lex.o \
md5.o message.o mem_pool.o parse_conf.o \
queue.o rwlock.o serial.o \
--- /dev/null
+/*
+ * edit.c edit string to ascii, and ascii to internal
+ *
+ * Kern Sibbald, December MMII
+ *
+ * Version $Id$
+ */
+
+/*
+ Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+
+ 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.
+
+ 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.
+
+ */
+
+#include "bacula.h"
+
+/* We assume ASCII input and don't worry about overflow */
+uint64_t str_to_uint64(char *str)
+{
+ register char *p = str;
+ register uint64_t value = 0;
+
+ while (B_ISSPACE(*p)) {
+ p++;
+ }
+ if (*p == '+') {
+ p++;
+ }
+ while (B_ISDIGIT(*p)) {
+ value = value * 10 + *p - '0';
+ p++;
+ }
+ return value;
+}
+
+int64_t str_to_int64(char *str)
+{
+ register char *p = str;
+ register int64_t value;
+ int negative = FALSE;
+
+ while (B_ISSPACE(*p)) {
+ p++;
+ }
+ if (*p == '+') {
+ p++;
+ } else if (*p == '-') {
+ negative = TRUE;
+ p++;
+ }
+ value = str_to_uint64(p);
+ if (negative) {
+ value = -value;
+ }
+ return value;
+}
+
+
+
+/*
+ * Edit an integer number with commas, the supplied buffer
+ * must be at least 27 bytes long. The incoming number
+ * is always widened to 64 bits.
+ */
+char *edit_uint64_with_commas(uint64_t val, char *buf)
+{
+ sprintf(buf, "%" lld, val);
+ return add_commas(buf, buf);
+}
+
+/*
+ * Edit an integer number, the supplied buffer
+ * must be at least 27 bytes long. The incoming number
+ * is always widened to 64 bits.
+ */
+char *edit_uint64(uint64_t val, char *buf)
+{
+ sprintf(buf, "%" lld, val);
+ return buf;
+}
+
+
+/*
+ * Convert a string duration to utime_t (64 bit seconds)
+ * Returns 0: if error
+ 1: if OK, and value stored in value
+ */
+int duration_to_utime(char *str, utime_t *value)
+{
+ int i, ch, len;
+ double val;
+ static int mod[] = {'*', 's', 'n', 'h', 'd', 'w', 'm', 'q', 'y', 0};
+ static int mult[] = {1, 1, 60, 60*60, 60*60*24, 60*60*24*7, 60*60*24*30,
+ 60*60*24*91, 60*60*24*365};
+
+ /* Look for modifier */
+ len = strlen(str);
+ ch = str[len - 1];
+ i = 0;
+ if (B_ISALPHA(ch)) {
+ if (B_ISUPPER(ch)) {
+ ch = tolower(ch);
+ }
+ while (mod[++i] != 0) {
+ if (ch == mod[i]) {
+ len--;
+ str[len] = 0; /* strip modifier */
+ break;
+ }
+ }
+ }
+ if (mod[i] == 0 || !is_a_number(str)) {
+ return 0;
+ }
+ val = strtod(str, NULL);
+ if (errno != 0 || val < 0) {
+ return 0;
+ }
+ *value = (utime_t)(val * mult[i]);
+ return 1;
+
+}
+
+/*
+ * Edit a utime "duration" into ASCII
+ */
+char *edit_utime(utime_t val, char *buf)
+{
+ char mybuf[30];
+ static int mult[] = {60*60*24*365, 60*60*24*30, 60*60*24, 60*60, 60};
+ static char *mod[] = {"year", "month", "day", "hour", "min"};
+ int i;
+ uint32_t times;
+
+ *buf = 0;
+ for (i=0; i<5; i++) {
+ times = val / mult[i];
+ if (times > 0) {
+ val = val - (utime_t)times * mult[i];
+ sprintf(mybuf, "%d %s%s ", times, mod[i], times>1?"s":"");
+ strcat(buf, mybuf);
+ }
+ }
+ if (val == 0 && strlen(buf) == 0) {
+ strcat(buf, "0 secs");
+ } else if (val != 0) {
+ sprintf(mybuf, "%d sec%s", (uint32_t)val, val>1?"s":"");
+ strcat(buf, mybuf);
+ }
+ return buf;
+}
+
+/*
+ * Convert a size size in bytes to uint64_t
+ * Returns 0: if error
+ 1: if OK, and value stored in value
+ */
+int size_to_uint64(char *str, int str_len, uint64_t *rtn_value)
+{
+ int i, ch;
+ double value;
+ int mod[] = {'*', 'k', 'm', 'g', 0}; /* first item * not used */
+ uint64_t mult[] = {1, /* byte */
+ 1024, /* kilobyte */
+ 1048576, /* megabyte */
+ 1073741824}; /* gigabyte */
+
+#ifdef we_have_a_compiler_that_works
+ int mod[] = {'*', 'k', 'm', 'g', 't', 0};
+ uint64_t mult[] = {1, /* byte */
+ 1024, /* kilobyte */
+ 1048576, /* megabyte */
+ 1073741824, /* gigabyte */
+ 1099511627776};/* terabyte */
+#endif
+
+ Dmsg0(400, "Enter sized to uint64\n");
+
+ /* Look for modifier */
+ ch = str[str_len - 1];
+ i = 0;
+ if (B_ISALPHA(ch)) {
+ if (B_ISUPPER(ch)) {
+ ch = tolower(ch);
+ }
+ while (mod[++i] != 0) {
+ if (ch == mod[i]) {
+ str_len--;
+ str[str_len] = 0; /* strip modifier */
+ break;
+ }
+ }
+ }
+ if (mod[i] == 0 || !is_a_number(str)) {
+ return 0;
+ }
+ Dmsg3(400, "size str=:%s: %f i=%d\n", str, strtod(str, NULL), i);
+
+ value = (uint64_t)strtod(str, NULL);
+ Dmsg1(400, "Int value = %d\n", (int)value);
+ if (errno != 0 || value < 0) {
+ return 0;
+ }
+ *rtn_value = (uint64_t)(value * mult[i]);
+ Dmsg2(400, "Full value = %f %" lld "\n", strtod(str, NULL) * mult[i],
+ value *mult[i]);
+ return 1;
+}
+
+/*
+ * Check if specified string is a number or not.
+ * Taken from SQLite, cool, thanks.
+ */
+int is_a_number(const char *n)
+{
+ int digit_seen = 0;
+
+ if( *n == '-' || *n == '+' ) {
+ n++;
+ }
+ while (B_ISDIGIT(*n)) {
+ digit_seen = 1;
+ n++;
+ }
+ if (digit_seen && *n == '.') {
+ n++;
+ while (B_ISDIGIT(*n)) { n++; }
+ }
+ if (digit_seen && (*n == 'e' || *n == 'E')
+ && (B_ISDIGIT(n[1]) || ((n[1]=='-' || n[1] == '+') && B_ISDIGIT(n[2])))) {
+ n += 2; /* skip e- or e+ or e digit */
+ while (B_ISDIGIT(*n)) { n++; }
+ }
+ return digit_seen && *n==0;
+}
+
+/*
+ * Add commas to a string, which is presumably
+ * a number.
+ */
+char *add_commas(char *val, char *buf)
+{
+ int len, nc;
+ char *p, *q;
+ int i;
+
+ if (val != buf) {
+ strcpy(buf, val);
+ }
+ len = strlen(buf);
+ if (len < 1) {
+ len = 1;
+ }
+ nc = (len - 1) / 3;
+ p = buf+len;
+ q = p + nc;
+ *q-- = *p--;
+ for ( ; nc; nc--) {
+ for (i=0; i < 3; i++) {
+ *q-- = *p--;
+ }
+ *q-- = ',';
+ }
+ return buf;
+}
*/
/* base64.c */
-void base64_init (void);
-int to_base64 (intmax_t value, char *where);
-int from_base64 (intmax_t *value, char *where);
-int bin_to_base64 (char *buf, char *bin, int len);
+void base64_init (void);
+int to_base64 (intmax_t value, char *where);
+int from_base64 (intmax_t *value, char *where);
+int bin_to_base64 (char *buf, char *bin, int len);
/* bmisc.c */
-char *bstrncpy (char *dest, const char *src, int maxlen);
-char *bstrncat (char *dest, const char *src, int maxlen);
-void *b_malloc (char *file, int line, size_t size);
+char *bstrncpy (char *dest, const char *src, int maxlen);
+char *bstrncat (char *dest, const char *src, int maxlen);
+void *b_malloc (char *file, int line, size_t size);
#ifndef DEBUG
-void *bmalloc (size_t size);
+void *bmalloc (size_t size);
#endif
-void *brealloc (void *buf, size_t size);
-void *bcalloc (size_t size1, size_t size2);
-int bsnprintf (char *str, size_t size, const char *format, ...);
-int bvsnprintf (char *str, size_t size, const char *format, va_list ap);
-int pool_sprintf (char *pool_buf, char *fmt, ...);
-void create_pid_file (char *dir, char *progname, int port);
-int delete_pid_file (char *dir, char *progname, int port);
+void *brealloc (void *buf, size_t size);
+void *bcalloc (size_t size1, size_t size2);
+int bsnprintf (char *str, size_t size, const char *format, ...);
+int bvsnprintf (char *str, size_t size, const char *format, va_list ap);
+int pool_sprintf (char *pool_buf, char *fmt, ...);
+void create_pid_file (char *dir, char *progname, int port);
+int delete_pid_file (char *dir, char *progname, int port);
/* bnet.c */
-int32_t bnet_recv (BSOCK *bsock);
-int bnet_send (BSOCK *bsock);
-int bnet_fsend (BSOCK *bs, char *fmt, ...);
-int bnet_set_buffer_size (BSOCK *bs, uint32_t size, int rw);
-int bnet_sig (BSOCK *bs, int sig);
-BSOCK * bnet_connect (void *jcr, int retry_interval,
- int max_retry_time, char *name, char *host, char *service,
- int port, int verbose);
-int bnet_wait_data (BSOCK *bsock, int sec);
-void bnet_close (BSOCK *bsock);
-BSOCK * init_bsock (void *jcr, int sockfd, char *who, char *ip, int port);
-BSOCK * dup_bsock (BSOCK *bsock);
-void term_bsock (BSOCK *bsock);
-char * bnet_strerror (BSOCK *bsock);
-char * bnet_sig_to_ascii (BSOCK *bsock);
-int bnet_wait_data (BSOCK *bsock, int sec);
-int bnet_despool (BSOCK *bsock);
-int is_bnet_stop (BSOCK *bsock);
-int is_bnet_error (BSOCK *bsock);
+int32_t bnet_recv (BSOCK *bsock);
+int bnet_send (BSOCK *bsock);
+int bnet_fsend (BSOCK *bs, char *fmt, ...);
+int bnet_set_buffer_size (BSOCK *bs, uint32_t size, int rw);
+int bnet_sig (BSOCK *bs, int sig);
+BSOCK * bnet_connect (void *jcr, int retry_interval,
+ int max_retry_time, char *name, char *host, char *service,
+ int port, int verbose);
+int bnet_wait_data (BSOCK *bsock, int sec);
+void bnet_close (BSOCK *bsock);
+BSOCK * init_bsock (void *jcr, int sockfd, char *who, char *ip, int port);
+BSOCK * dup_bsock (BSOCK *bsock);
+void term_bsock (BSOCK *bsock);
+char * bnet_strerror (BSOCK *bsock);
+char * bnet_sig_to_ascii (BSOCK *bsock);
+int bnet_wait_data (BSOCK *bsock, int sec);
+int bnet_despool (BSOCK *bsock);
+int is_bnet_stop (BSOCK *bsock);
+int is_bnet_error (BSOCK *bsock);
/* cram-md5.c */
int cram_md5_get_auth(BSOCK *bs, char *password);
int cram_md5_auth(BSOCK *bs, char *password);
void hmac_md5(uint8_t* text, int text_len, uint8_t* key,
- int key_len, uint8_t *hmac);
+ int key_len, uint8_t *hmac);
/* crc32.c */
uint32_t bcrc32(uint8_t *buf, int len);
/* daemon.c */
-void daemon_start ();
+void daemon_start ();
+
+/* edit.c */
+uint64_t str_to_uint64(char *str);
+int64_t str_to_int64(char *str);
+char * edit_uint64_with_commas (uint64_t val, char *buf);
+char * add_commas (char *val, char *buf);
+char * edit_uint64 (uint64_t val, char *buf);
+int duration_to_utime (char *str, utime_t *value);
+int size_to_uint64(char *str, int str_len, uint64_t *rtn_value);
+char *edit_utime (utime_t val, char *buf);
+int is_a_number (const char *num);
/* lex.c */
-LEX * lex_close_file (LEX *lf);
-LEX * lex_open_file (LEX *lf, char *fname, LEX_ERROR_HANDLER *scan_error);
-int lex_get_char (LEX *lf);
-void lex_unget_char (LEX *lf);
-char * lex_tok_to_str (int token);
-int lex_get_token (LEX *lf, int expect);
+LEX * lex_close_file (LEX *lf);
+LEX * lex_open_file (LEX *lf, char *fname, LEX_ERROR_HANDLER *scan_error);
+int lex_get_char (LEX *lf);
+void lex_unget_char (LEX *lf);
+char * lex_tok_to_str (int token);
+int lex_get_token (LEX *lf, int expect);
/* message.c */
-void my_name_is (int argc, char *argv[], char *name);
-void init_msg (void *jcr, MSGS *msg);
-void term_msg (void);
-void close_msg (void *jcr);
-void add_msg_dest (MSGS *msg, int dest, int type, char *where, char *dest_code);
-void rem_msg_dest (MSGS *msg, int dest, int type, char *where);
-void Jmsg (void *jcr, int type, int level, char *fmt, ...);
-void dispatch_message (void *jcr, int type, int level, char *buf);
-void init_console_msg (char *wd);
-void free_msgs_res (MSGS *msgs);
-int open_spool_file (void *jcr, BSOCK *bs);
-int close_spool_file (void *vjcr, BSOCK *bs);
+void my_name_is (int argc, char *argv[], char *name);
+void init_msg (void *jcr, MSGS *msg);
+void term_msg (void);
+void close_msg (void *jcr);
+void add_msg_dest (MSGS *msg, int dest, int type, char *where, char *dest_code);
+void rem_msg_dest (MSGS *msg, int dest, int type, char *where);
+void Jmsg (void *jcr, int type, int level, char *fmt, ...);
+void dispatch_message (void *jcr, int type, int level, char *buf);
+void init_console_msg (char *wd);
+void free_msgs_res (MSGS *msgs);
+int open_spool_file (void *jcr, BSOCK *bs);
+int close_spool_file (void *vjcr, BSOCK *bs);
/* bnet_server.c */
-void bnet_thread_server(char *bind_addr, int port, int max_clients, workq_t *client_wq,
- void handle_client_request(void *bsock));
-void bnet_server (int port, void handle_client_request(BSOCK *bsock));
-int net_connect (int port);
-BSOCK * bnet_bind (int port);
-BSOCK * bnet_accept (BSOCK *bsock, char *who);
+void bnet_thread_server(char *bind_addr, int port, int max_clients, workq_t *client_wq,
+ void handle_client_request(void *bsock));
+void bnet_server (int port, void handle_client_request(BSOCK *bsock));
+int net_connect (int port);
+BSOCK * bnet_bind (int port);
+BSOCK * bnet_accept (BSOCK *bsock, char *who);
/* signal.c */
-void init_signals (void terminate(int sig));
-void init_stack_dump (void);
+void init_signals (void terminate(int sig));
+void init_stack_dump (void);
/* util.c */
-void lcase (char *str);
-void bash_spaces (char *str);
-void unbash_spaces (char *str);
-void strip_trailing_junk (char *str);
-void strip_trailing_slashes (char *dir);
-int skip_spaces (char **msg);
-int skip_nonspaces (char **msg);
-int fstrsch (char *a, char *b);
-char * encode_time (time_t time, char *buf);
-char * encode_mode (mode_t mode, char *buf);
-char * edit_uint64_with_commas (uint64_t val, char *buf);
-char * add_commas (char *val, char *buf);
-char * edit_uint64 (uint64_t val, char *buf);
-int do_shell_expansion (char *name);
-int is_a_number (const char *num);
-int is_buf_zero (char *buf, int len);
-int duration_to_utime (char *str, utime_t *value);
-int size_to_uint64(char *str, int str_len, uint64_t *rtn_value);
-char *edit_utime (utime_t val, char *buf);
-void jobstatus_to_ascii (int JobStatus, char *msg, int maxlen);
-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);
-char * job_level_to_str (int level);
-void makeSessionKey (char *key, char *seed, int mode);
-BPIPE * open_bpipe(char *prog, int wait, char *mode);
-int close_wpipe(BPIPE *bpipe);
-int close_bpipe(BPIPE *bpipe);
+void lcase (char *str);
+void bash_spaces (char *str);
+void unbash_spaces (char *str);
+void strip_trailing_junk (char *str);
+void strip_trailing_slashes (char *dir);
+int skip_spaces (char **msg);
+int skip_nonspaces (char **msg);
+int fstrsch (char *a, char *b);
+char * encode_time (time_t time, char *buf);
+char * encode_mode (mode_t mode, char *buf);
+int do_shell_expansion (char *name);
+int is_buf_zero (char *buf, int len);
+void jobstatus_to_ascii (int JobStatus, char *msg, int maxlen);
+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);
+char * job_level_to_str (int level);
+void makeSessionKey (char *key, char *seed, int mode);
+BPIPE * open_bpipe(char *prog, int wait, char *mode);
+int close_wpipe(BPIPE *bpipe);
+int close_bpipe(BPIPE *bpipe);
/* watchdog.c */
return 1;
}
-/*
- * Convert a string duration to utime_t (64 bit seconds)
- * Returns 0: if error
- 1: if OK, and value stored in value
- */
-int duration_to_utime(char *str, utime_t *value)
-{
- int i, ch, len;
- double val;
- static int mod[] = {'*', 's', 'n', 'h', 'd', 'w', 'm', 'q', 'y', 0};
- static int mult[] = {1, 1, 60, 60*60, 60*60*24, 60*60*24*7, 60*60*24*30,
- 60*60*24*91, 60*60*24*365};
-
- /* Look for modifier */
- len = strlen(str);
- ch = str[len - 1];
- i = 0;
- if (B_ISALPHA(ch)) {
- if (B_ISUPPER(ch)) {
- ch = tolower(ch);
- }
- while (mod[++i] != 0) {
- if (ch == mod[i]) {
- len--;
- str[len] = 0; /* strip modifier */
- break;
- }
- }
- }
- if (mod[i] == 0 || !is_a_number(str)) {
- return 0;
- }
- val = strtod(str, NULL);
- if (errno != 0 || val < 0) {
- return 0;
- }
- *value = (utime_t)(val * mult[i]);
- return 1;
-
-}
-
-/*
- * Edit a utime "duration" into ASCII
- */
-char *edit_utime(utime_t val, char *buf)
-{
- char mybuf[30];
- static int mult[] = {60*60*24*365, 60*60*24*30, 60*60*24, 60*60, 60};
- static char *mod[] = {"year", "month", "day", "hour", "min"};
- int i;
- uint32_t times;
-
- *buf = 0;
- for (i=0; i<5; i++) {
- times = val / mult[i];
- if (times > 0) {
- val = val - (utime_t)times * mult[i];
- sprintf(mybuf, "%d %s%s ", times, mod[i], times>1?"s":"");
- strcat(buf, mybuf);
- }
- }
- if (val == 0 && strlen(buf) == 0) {
- strcat(buf, "0 secs");
- } else if (val != 0) {
- sprintf(mybuf, "%d sec%s", (uint32_t)val, val>1?"s":"");
- strcat(buf, mybuf);
- }
- return buf;
-}
-
-/*
- * Convert a size size in bytes to uint64_t
- * Returns 0: if error
- 1: if OK, and value stored in value
- */
-int size_to_uint64(char *str, int str_len, uint64_t *rtn_value)
-{
- int i, ch;
- double value;
- int mod[] = {'*', 'k', 'm', 'g', 0}; /* first item * not used */
- uint64_t mult[] = {1, /* byte */
- 1024, /* kilobyte */
- 1048576, /* megabyte */
- 1073741824}; /* gigabyte */
-
-#ifdef we_have_a_compiler_that_works
- int mod[] = {'*', 'k', 'm', 'g', 't', 0};
- uint64_t mult[] = {1, /* byte */
- 1024, /* kilobyte */
- 1048576, /* megabyte */
- 1073741824, /* gigabyte */
- 1099511627776};/* terabyte */
-#endif
-
- Dmsg0(400, "Enter sized to uint64\n");
-
- /* Look for modifier */
- ch = str[str_len - 1];
- i = 0;
- if (B_ISALPHA(ch)) {
- if (B_ISUPPER(ch)) {
- ch = tolower(ch);
- }
- while (mod[++i] != 0) {
- if (ch == mod[i]) {
- str_len--;
- str[str_len] = 0; /* strip modifier */
- break;
- }
- }
- }
- if (mod[i] == 0 || !is_a_number(str)) {
- return 0;
- }
- Dmsg3(400, "size str=:%s: %f i=%d\n", str, strtod(str, NULL), i);
-
- value = (uint64_t)strtod(str, NULL);
- Dmsg1(400, "Int value = %d\n", (int)value);
- if (errno != 0 || value < 0) {
- return 0;
- }
- *rtn_value = (uint64_t)(value * mult[i]);
- Dmsg2(400, "Full value = %f %" lld "\n", strtod(str, NULL) * mult[i],
- value *mult[i]);
- return 1;
-}
-
-/*
- * Check if specified string is a number or not.
- * Taken from SQLite, cool, thanks.
- */
-int is_a_number(const char *n)
-{
- int digit_seen = 0;
-
- if( *n == '-' || *n == '+' ) {
- n++;
- }
- while (B_ISDIGIT(*n)) {
- digit_seen = 1;
- n++;
- }
- if (digit_seen && *n == '.') {
- n++;
- while (B_ISDIGIT(*n)) { n++; }
- }
- if (digit_seen && (*n == 'e' || *n == 'E')
- && (B_ISDIGIT(n[1]) || ((n[1]=='-' || n[1] == '+') && B_ISDIGIT(n[2])))) {
- n += 2; /* skip e- or e+ or e digit */
- while (B_ISDIGIT(*n)) { n++; }
- }
- return digit_seen && *n==0;
-}
-
-
-/*
- * Edit an integer number with commas, the supplied buffer
- * must be at least 27 bytes long. The incoming number
- * is always widened to 64 bits.
- */
-char *edit_uint64_with_commas(uint64_t val, char *buf)
-{
- sprintf(buf, "%" lld, val);
- return add_commas(buf, buf);
-}
-
-/*
- * Edit an integer number, the supplied buffer
- * must be at least 27 bytes long. The incoming number
- * is always widened to 64 bits.
- */
-char *edit_uint64(uint64_t val, char *buf)
-{
- sprintf(buf, "%" lld, val);
- return buf;
-}
-
-
-/*
- * Add commas to a string, which is presumably
- * a number.
- */
-char *add_commas(char *val, char *buf)
-{
- int len, nc;
- char *p, *q;
- int i;
-
- if (val != buf) {
- strcpy(buf, val);
- }
- len = strlen(buf);
- if (len < 1) {
- len = 1;
- }
- nc = (len - 1) / 3;
- p = buf+len;
- q = p + nc;
- *q-- = *p--;
- for ( ; nc; nc--) {
- for (i=0; i < 3; i++) {
- *q-- = *p--;
- }
- *q-- = ',';
- }
- return buf;
-}
-
/* Convert a string in place to lower case */
void lcase(char *str)
attach_jcr_to_device(dev, jcr); /* attach jcr to device */
stat = 1; /* good return */
if ((dev->state & ST_TAPE) && vol->start_file > 0) {
- Dmsg1(100, "====== Got start_file = %d\n", vol->start_file);
+ Dmsg1(200, "====== Got start_file = %d\n", vol->start_file);
fsf_dev(dev, vol->start_file);
}
} else {
block->buf_len = dev->max_block_size;
}
+ block->dev = dev;
block->block_len = block->buf_len; /* default block size */
block->buf = get_memory(block->buf_len);
if (block->buf == NULL) {
*/
typedef struct s_dev_block {
struct s_dev_block *next; /* pointer to next one */
+ void *dev; /* pointer to device (DEVICE not defined yet) */
/* binbuf is the number of bytes remaining
* in the buffer. For writes, it is bytes not yet written.
* For reads, it is remaining bytes not yet read.
/*
* !!!!!!!!!!!!!!!!!! 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. !!!
+ * !!! !!!
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/
struct s_bsr_sessid *next;
uint32_t sessid;
uint32_t sessid2;
- int done; /* local done */
+ int done; /* local done */
} BSR_SESSID;
typedef struct s_bsr_sesstime {
struct s_bsr_sesstime *next;
uint32_t sesstime;
- int done; /* local done */
+ int done; /* local done */
} BSR_SESSTIME;
typedef struct s_bsr_volfile {
struct s_bsr_volfile *next;
- uint32_t sfile; /* start file */
- uint32_t efile; /* end file */
- int done; /* local done */
+ uint32_t sfile; /* start file */
+ uint32_t efile; /* end file */
+ int done; /* local done */
} BSR_VOLFILE;
+typedef struct s_bsr_volblock {
+ struct s_bsr_volblock *next;
+ uint32_t sblock; /* start block */
+ uint32_t eblock; /* end block */
+ int done; /* local done */
+} BSR_VOLBLOCK;
+
+
typedef struct s_bsr_findex {
struct s_bsr_findex *next;
- int32_t findex; /* start file index */
- int32_t findex2; /* end file index */
- int done; /* local done */
+ int32_t findex; /* start file index */
+ int32_t findex2; /* end file index */
+ int done; /* local done */
} BSR_FINDEX;
typedef struct s_bsr_jobid {
typedef struct s_bsr_stream {
struct s_bsr_stream *next;
- int32_t stream; /* stream desired */
+ int32_t stream; /* stream desired */
} BSR_STREAM;
typedef struct s_bsr {
- struct s_bsr *next; /* pointer to next one */
- int done; /* set when everything found */
- BSR_VOLUME *volume;
- int32_t Slot; /* Slot */
- uint32_t count; /* count of files to restore this bsr */
- uint32_t found; /* count of restored files this bsr */
- BSR_VOLFILE *volfile;
+ struct s_bsr *next; /* pointer to next one */
+ int done; /* set when everything found */
+ BSR_VOLUME *volume;
+ int32_t Slot; /* Slot */
+ uint32_t count; /* count of files to restore this bsr */
+ uint32_t found; /* count of restored files this bsr */
+ BSR_VOLFILE *volfile;
+ BSR_VOLBLOCK *volblock;
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;
if (!match_volume(bsr, bsr->volume, volrec, 1)) {
goto no_match;
}
- /* Not yet working */
-// if (!match_volfile(bsr, bsr->volfile, rec, 1)) {
-// goto no_match;
-// }
+ if (!match_volfile(bsr, bsr->volfile, rec, 1)) {
+ goto no_match;
+ }
if (!match_sesstime(bsr, bsr->sesstime, rec, 1)) {
goto no_match;
}
if (!volfile) {
return 1; /* no specification matches all */
}
+ /* For the moment, these tests work only with tapes. */
+ if (!(rec->state & REC_ISTAPE)) {
+ return 1; /* All File records OK for this match */
+ }
+// Dmsg3(000, "match_volfile: sfile=%d efile=%d recfile=%d\n",
+// volfile->sfile, volfile->efile, rec->File);
if (volfile->sfile <= rec->File && volfile->efile >= rec->File) {
return 1;
}
static BSR *store_findex(LEX *lc, BSR *bsr);
static BSR *store_sessid(LEX *lc, BSR *bsr);
static BSR *store_volfile(LEX *lc, BSR *bsr);
+static BSR *store_volblock(LEX *lc, BSR *bsr);
static BSR *store_sesstime(LEX *lc, BSR *bsr);
static BSR *store_include(LEX *lc, BSR *bsr);
static BSR *store_exclude(LEX *lc, BSR *bsr);
{"include", store_include},
{"exclude", store_exclude},
{"volfile", store_volfile},
+ {"volblock", store_volblock},
{"stream", store_stream},
{"slot", store_slot},
{NULL, NULL}
}
+/*
+ * Routine to handle Volume start/end Block
+ */
+static BSR *store_volblock(LEX *lc, BSR *bsr)
+{
+ int token;
+ BSR_VOLBLOCK *volblock;
+
+ for (;;) {
+ token = lex_get_token(lc, T_PINT32_RANGE);
+ if (token == T_ERROR) {
+ return NULL;
+ }
+ volblock = (BSR_VOLBLOCK *)malloc(sizeof(BSR_VOLBLOCK));
+ memset(volblock, 0, sizeof(BSR_VOLBLOCK));
+ volblock->sblock = lc->pint32_val;
+ volblock->eblock = lc->pint32_val2;
+ /* Add it to the end of the chain */
+ if (!bsr->volblock) {
+ bsr->volblock = volblock;
+ } else {
+ /* Add to end of chain */
+ BSR_VOLBLOCK *bs = bsr->volblock;
+ for ( ;bs->next; bs=bs->next)
+ { }
+ bs->next = volblock;
+ }
+ token = lex_get_token(lc, T_ALL);
+ if (token != T_COMMA) {
+ break;
+ }
+ }
+ return bsr;
+}
+
static BSR *store_sessid(LEX *lc, BSR *bsr)
{
}
}
+void dump_volblock(BSR_VOLBLOCK *volblock)
+{
+ if (volblock) {
+ Dmsg2(-1, "VolBlock : %u-%u\n", volblock->sblock, volblock->eblock);
+ dump_volblock(volblock->next);
+ }
+}
+
+
void dump_findex(BSR_FINDEX *FileIndex)
{
if (FileIndex) {
dump_sessid(bsr->sessid);
dump_sesstime(bsr->sesstime);
dump_volfile(bsr->volfile);
+ dump_volblock(bsr->volblock);
dump_client(bsr->client);
dump_jobid(bsr->JobId);
dump_job(bsr->job);
free_bsr_item((BSR *)bsr->sessid);
free_bsr_item((BSR *)bsr->sesstime);
free_bsr_item((BSR *)bsr->volfile);
+ free_bsr_item((BSR *)bsr->volblock);
free_bsr_item((BSR *)bsr->JobId);
free_bsr_item((BSR *)bsr->job);
free_bsr_item((BSR *)bsr->FileIndex);
read_block_from_device(dev, block);
read_record_from_block(block, trec);
get_session_record(dev, trec, &sessrec);
- trec->File = dev->file;
record_cb(jcr, dev, block, trec);
free_record(trec);
goto next_record;
block->BlockNumber, rec->remainder);
break;
}
- rec->File = dev->file;
Dmsg3(10, "read-OK. stat=%s blk=%d rem=%d\n", rec_state_to_str(rec),
block->BlockNumber, rec->remainder);
/*
remlen = block->binbuf;
rec->Block = block->BlockNumber;
+ rec->File = ((DEVICE *)block->dev)->file;
- /* Clear state flags */
+ /* Clear state flags */
rec->state = 0;
+ if (((DEVICE *)block->dev)->state & ST_TAPE) {
+ rec->state |= REC_ISTAPE;
+ }
+
/*
* Get the header. There is always a full header,
#define REC_BLOCK_EMPTY 0x04 /* not enough data in block */
#define REC_NO_MATCH 0x08 /* No match on continuation data */
#define REC_CONTINUATION 0x10 /* Continuation record found */
+#define REC_ISTAPE 0x20 /* Set if device is tape */
#define is_partial_record(r) ((r)->state & REC_PARTIAL_RECORD)
#define is_block_empty(r) ((r)->state & REC_BLOCK_EMPTY)
$(CXX) $(LDFLAGS) -L../lib -o $@ smtp.o -lbac -lm $(LIBS) $(DLIB)
dbcheck: dbcheck.o ../lib/libbac.a ../cats/libsql.a
- $(CXX) $(LDFLAGS) -L../lib -L../cats -o $@ dbcheck.o -lbac -lsql -lm $(LIBS) $(DB_LIBS)
+ $(CXX) $(LDFLAGS) -L../lib -L../cats -o $@ dbcheck.o -lsql -lbac -lm $(LIBS) $(DB_LIBS)
testfind: ../findlib/libfind.a ../lib/libbac.a $(FINDOBJS)
$(CXX) -g $(LDFLAGS) -L. -L../lib -L../findlib -o $@ $(FINDOBJS) \
/* */
#define VERSION "1.28"
#define VSTRING "1"
-#define DATE "2 December 2002"
-#define LSMDATE "02Dec02"
+#define DATE "4 December 2002"
+#define LSMDATE "04Dec02"
/* Debug flags */
#define DEBUG 1