Kern's ToDo List
- 07 March 2005
+ 11 March 2005
Major development:
Project Developer
/* sql.c */
B_DB *db_init_database(JCR *jcr, const char *db_name, const char *db_user, const char *db_password,
- const char *db_address, int db_port, const char *db_socket,
- int mult_db_connections);
+ const char *db_address, int db_port, const char *db_socket,
+ int mult_db_connections);
int db_open_database(JCR *jcr, B_DB *db);
void db_close_database(JCR *jcr, B_DB *db);
void db_escape_string(char *snew, char *old, int len);
bool db_find_failed_job_since(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM *stime, int &JobLevel);
/* get.c */
-int db_get_pool_record(JCR *jcr, B_DB *db, POOL_DBR *pdbr);
+bool db_get_pool_record(JCR *jcr, B_DB *db, POOL_DBR *pdbr);
int db_get_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cr);
int db_get_job_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr);
int db_get_job_volume_names(JCR *jcr, B_DB *mdb, JobId_t JobId, POOLMEM **VolumeNames);
/*
* Bacula Catalog Database Get record interface routines
* Note, these routines generally get a record by id or
- * by name. If more logic is involved, the routine
- * should be in find.c
+ * by name. If more logic is involved, the routine
+ * should be in find.c
*
* Kern Sibbald, March 2000
*
/* The following is necessary so that we do not include
* the dummy external definition of DB.
*/
-#define __SQL_C /* indicate that this is sql.c */
+#define __SQL_C /* indicate that this is sql.c */
#include "bacula.h"
#include "cats.h"
* (with attributes) in the database.
*
* Returns: 0 on failure
- * 1 on success with the File record in FILE_DBR
+ * 1 on success with the File record in FILE_DBR
*/
int db_get_file_attributes_record(JCR *jcr, B_DB *mdb, char *fname, JOB_DBR *jr, FILE_DBR *fdbr)
{
/*
* Get a File record
* Returns: 0 on failure
- * 1 on success
+ * 1 on success
*
* DO NOT use Jmsg in this routine.
*
Dmsg1(050, "get_file_record num_rows=%d\n", (int)mdb->num_rows);
if (mdb->num_rows > 1) {
Mmsg1(&mdb->errmsg, _("get_file_record want 1 got rows=%d\n"),
- mdb->num_rows);
+ mdb->num_rows);
}
if (mdb->num_rows >= 1) {
- if ((row = sql_fetch_row(mdb)) == NULL) {
+ if ((row = sql_fetch_row(mdb)) == NULL) {
Mmsg1(&mdb->errmsg, _("Error fetching row: %s\n"), sql_strerror(mdb));
- } else {
- fdbr->FileId = (FileId_t)str_to_int64(row[0]);
- bstrncpy(fdbr->LStat, row[1], sizeof(fdbr->LStat));
- bstrncpy(fdbr->SIG, row[2], sizeof(fdbr->SIG));
- stat = 1;
- }
+ } else {
+ fdbr->FileId = (FileId_t)str_to_int64(row[0]);
+ bstrncpy(fdbr->LStat, row[1], sizeof(fdbr->LStat));
+ bstrncpy(fdbr->SIG, row[2], sizeof(fdbr->SIG));
+ stat = 1;
+ }
} else {
Mmsg2(&mdb->errmsg, _("File record for PathId=%s FilenameId=%s not found.\n"),
- edit_int64(fdbr->PathId, ed1),
- edit_int64(fdbr->FilenameId, ed2));
+ edit_int64(fdbr->PathId, ed1),
+ edit_int64(fdbr->FilenameId, ed2));
}
sql_free_result(mdb);
} else {
/* Get Filename record
* Returns: 0 on failure
- * FilenameId on success
+ * FilenameId on success
*
* DO NOT use Jmsg in this routine (see notes for get_file_record)
*/
mdb->num_rows = sql_num_rows(mdb);
if (mdb->num_rows > 1) {
Mmsg2(&mdb->errmsg, _("More than one Filename!: %s for file: %s\n"),
- edit_uint64(mdb->num_rows, ed1), mdb->fname);
+ edit_uint64(mdb->num_rows, ed1), mdb->fname);
Jmsg(jcr, M_WARNING, 0, "%s", mdb->errmsg);
}
if (mdb->num_rows >= 1) {
- if ((row = sql_fetch_row(mdb)) == NULL) {
+ if ((row = sql_fetch_row(mdb)) == NULL) {
Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
- } else {
- FilenameId = atoi(row[0]);
- if (FilenameId <= 0) {
+ } else {
+ FilenameId = atoi(row[0]);
+ if (FilenameId <= 0) {
Mmsg2(&mdb->errmsg, _("Get DB Filename record %s found bad record: %d\n"),
- mdb->cmd, FilenameId);
- FilenameId = 0;
- }
- }
+ mdb->cmd, FilenameId);
+ FilenameId = 0;
+ }
+ }
} else {
Mmsg1(&mdb->errmsg, _("Filename record: %s not found.\n"), mdb->fname);
}
/* Get path record
* Returns: 0 on failure
- * PathId on success
+ * PathId on success
*
* DO NOT use Jmsg in this routine (see notes for get_file_record)
*/
mdb->num_rows = sql_num_rows(mdb);
if (mdb->num_rows > 1) {
Mmsg2(&mdb->errmsg, _("More than one Path!: %s for path: %s\n"),
- edit_uint64(mdb->num_rows, ed1), mdb->path);
+ edit_uint64(mdb->num_rows, ed1), mdb->path);
Jmsg(jcr, M_WARNING, 0, "%s", mdb->errmsg);
}
/* Even if there are multiple paths, take the first one */
if (mdb->num_rows >= 1) {
- if ((row = sql_fetch_row(mdb)) == NULL) {
+ if ((row = sql_fetch_row(mdb)) == NULL) {
Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
- } else {
- PathId = atoi(row[0]);
- if (PathId <= 0) {
+ } else {
+ PathId = atoi(row[0]);
+ if (PathId <= 0) {
Mmsg2(&mdb->errmsg, _("Get DB path record %s found bad record: %s\n"),
- mdb->cmd, edit_int64(PathId, ed1));
- PathId = 0;
- } else {
- /* Cache path */
- if (PathId != mdb->cached_path_id) {
- mdb->cached_path_id = PathId;
- mdb->cached_path_len = mdb->pnl;
- pm_strcpy(&mdb->cached_path, mdb->path);
- }
- }
- }
+ mdb->cmd, edit_int64(PathId, ed1));
+ PathId = 0;
+ } else {
+ /* Cache path */
+ if (PathId != mdb->cached_path_id) {
+ mdb->cached_path_id = PathId;
+ mdb->cached_path_len = mdb->pnl;
+ pm_strcpy(&mdb->cached_path, mdb->path);
+ }
+ }
+ }
} else {
Mmsg1(&mdb->errmsg, _("Path record: %s not found.\n"), mdb->path);
}
/*
* Get Job record for given JobId or Job name
* Returns: 0 on failure
- * 1 on success
+ * 1 on success
*/
int db_get_job_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr)
{
"PoolId,StartTime,EndTime,JobFiles,JobBytes,JobTDate,Job,JobStatus,"
"Type,Level,ClientId "
"FROM Job WHERE JobId=%s",
- edit_int64(jr->JobId, ed1));
+ edit_int64(jr->JobId, ed1));
}
if (!QUERY_DB(jcr, mdb, mdb->cmd)) {
db_unlock(mdb);
- return 0; /* failed */
+ return 0; /* failed */
}
if ((row = sql_fetch_row(mdb)) == NULL) {
Mmsg1(&mdb->errmsg, _("No Job found for JobId %s\n"), edit_int64(jr->JobId, ed1));
sql_free_result(mdb);
db_unlock(mdb);
- return 0; /* failed */
+ return 0; /* failed */
}
jr->VolSessionId = str_to_uint64(row[0]);
/*
* Find VolumeNames for a given JobId
* Returns: 0 on error or no Volumes found
- * number of volumes on success
- * Volumes are concatenated in VolumeNames
- * separated by a vertical bar (|) in the order
- * that they were written.
+ * number of volumes on success
+ * Volumes are concatenated in VolumeNames
+ * separated by a vertical bar (|) in the order
+ * that they were written.
*
* Returns: number of volumes on success
*/
Dmsg1(130, "Num rows=%d\n", mdb->num_rows);
if (mdb->num_rows <= 0) {
Mmsg1(&mdb->errmsg, _("No volumes found for JobId=%d\n"), JobId);
- stat = 0;
+ stat = 0;
} else {
- stat = mdb->num_rows;
- for (i=0; i < stat; i++) {
- if ((row = sql_fetch_row(mdb)) == NULL) {
+ stat = mdb->num_rows;
+ for (i=0; i < stat; i++) {
+ if ((row = sql_fetch_row(mdb)) == NULL) {
Mmsg2(&mdb->errmsg, _("Error fetching row %d: ERR=%s\n"), i, sql_strerror(mdb));
Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
- stat = 0;
- break;
- } else {
- if (*VolumeNames[0] != 0) {
+ stat = 0;
+ break;
+ } else {
+ if (*VolumeNames[0] != 0) {
pm_strcat(VolumeNames, "|");
- }
- pm_strcat(VolumeNames, row[0]);
- }
- }
+ }
+ pm_strcat(VolumeNames, row[0]);
+ }
+ }
}
sql_free_result(mdb);
} else {
/*
* Find Volume parameters for a give JobId
* Returns: 0 on error or no Volumes found
- * number of volumes on success
- * List of Volumes and start/end file/blocks (malloced structure!)
+ * number of volumes on success
+ * List of Volumes and start/end file/blocks (malloced structure!)
*
* Returns: number of volumes on success
*/
"JobMedia.EndFile,StartBlock,JobMedia.EndBlock"
" FROM JobMedia,Media WHERE JobMedia.JobId=%s"
" AND JobMedia.MediaId=Media.MediaId ORDER BY VolIndex,JobMediaId",
- edit_int64(JobId, ed1));
+ edit_int64(JobId, ed1));
Dmsg1(130, "VolNam=%s\n", mdb->cmd);
if (QUERY_DB(jcr, mdb, mdb->cmd)) {
Dmsg1(130, "Num rows=%d\n", mdb->num_rows);
if (mdb->num_rows <= 0) {
Mmsg1(&mdb->errmsg, _("No volumes found for JobId=%d\n"), JobId);
- stat = 0;
+ stat = 0;
} else {
- stat = mdb->num_rows;
- if (stat > 0) {
- *VolParams = Vols = (VOL_PARAMS *)malloc(stat * sizeof(VOL_PARAMS));
- }
- for (i=0; i < stat; i++) {
- if ((row = sql_fetch_row(mdb)) == NULL) {
+ stat = mdb->num_rows;
+ if (stat > 0) {
+ *VolParams = Vols = (VOL_PARAMS *)malloc(stat * sizeof(VOL_PARAMS));
+ }
+ for (i=0; i < stat; i++) {
+ if ((row = sql_fetch_row(mdb)) == NULL) {
Mmsg2(&mdb->errmsg, _("Error fetching row %d: ERR=%s\n"), i, sql_strerror(mdb));
Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
- stat = 0;
- break;
- } else {
- bstrncpy(Vols[i].VolumeName, row[0], MAX_NAME_LENGTH);
- bstrncpy(Vols[i].MediaType, row[1], MAX_NAME_LENGTH);
- Vols[i].FirstIndex = str_to_uint64(row[2]);
- Vols[i].LastIndex = str_to_uint64(row[3]);
- Vols[i].StartFile = str_to_uint64(row[4]);
- Vols[i].EndFile = str_to_uint64(row[5]);
- Vols[i].StartBlock = str_to_uint64(row[6]);
- Vols[i].EndBlock = str_to_uint64(row[7]);
- }
- }
+ stat = 0;
+ break;
+ } else {
+ bstrncpy(Vols[i].VolumeName, row[0], MAX_NAME_LENGTH);
+ bstrncpy(Vols[i].MediaType, row[1], MAX_NAME_LENGTH);
+ Vols[i].FirstIndex = str_to_uint64(row[2]);
+ Vols[i].LastIndex = str_to_uint64(row[3]);
+ Vols[i].StartFile = str_to_uint64(row[4]);
+ Vols[i].EndFile = str_to_uint64(row[5]);
+ Vols[i].StartBlock = str_to_uint64(row[6]);
+ Vols[i].EndBlock = str_to_uint64(row[7]);
+ }
+ }
}
sql_free_result(mdb);
}
* Get the number of pool records
*
* Returns: -1 on failure
- * number on success
+ * number on success
*/
int db_get_num_pool_records(JCR *jcr, B_DB *mdb)
{
* The caller must free ids if non-NULL.
*
* Returns 0: on failure
- * 1: on success
+ * 1: on success
*/
int db_get_pool_ids(JCR *jcr, B_DB *mdb, int *num_ids, uint32_t *ids[])
{
if (QUERY_DB(jcr, 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++] = str_to_uint64(row[0]);
- }
- *ids = id;
+ id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
+ while ((row = sql_fetch_row(mdb)) != NULL) {
+ id[i++] = str_to_uint64(row[0]);
+ }
+ *ids = id;
}
sql_free_result(mdb);
stat = 1;
* The caller must free ids if non-NULL.
*
* Returns 0: on failure
- * 1: on success
+ * 1: on success
*/
int db_get_client_ids(JCR *jcr, B_DB *mdb, int *num_ids, uint32_t *ids[])
{
if (QUERY_DB(jcr, 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++] = str_to_uint64(row[0]);
- }
- *ids = id;
+ id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
+ while ((row = sql_fetch_row(mdb)) != NULL) {
+ id[i++] = str_to_uint64(row[0]);
+ }
+ *ids = id;
}
sql_free_result(mdb);
stat = 1;
* If the PoolId is non-zero, we get its record,
* otherwise, we search on the PoolName
*
- * Returns: 0 on failure
- * id on success
+ * Returns: false on failure
+ * true on success
*/
-int db_get_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pdbr)
+bool db_get_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pdbr)
{
SQL_ROW row;
- int stat = 0;
+ bool ok = false;
char ed1[50];
db_lock(mdb);
- if (pdbr->PoolId != 0) { /* find by id */
+ if (pdbr->PoolId != 0) { /* find by id */
Mmsg(mdb->cmd,
"SELECT PoolId,Name,NumVols,MaxVols,UseOnce,UseCatalog,AcceptAnyVolume,"
"AutoPrune,Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,"
"MaxVolBytes,PoolType,LabelType,LabelFormat FROM Pool WHERE Pool.PoolId=%s",
- edit_int64(pdbr->PoolId, ed1));
- } else { /* find by name */
+ edit_int64(pdbr->PoolId, ed1));
+ } else { /* find by name */
Mmsg(mdb->cmd,
"SELECT PoolId,Name,NumVols,MaxVols,UseOnce,UseCatalog,AcceptAnyVolume,"
"AutoPrune,Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,"
"MaxVolBytes,PoolType,LabelType,LabelFormat FROM Pool WHERE Pool.Name='%s'",
- pdbr->Name);
+ pdbr->Name);
}
if (QUERY_DB(jcr, mdb, mdb->cmd)) {
mdb->num_rows = sql_num_rows(mdb);
if (mdb->num_rows > 1) {
- char ed1[30];
+ char ed1[30];
Mmsg1(&mdb->errmsg, _("More than one Pool!: %s\n"),
- edit_uint64(mdb->num_rows, ed1));
+ edit_uint64(mdb->num_rows, ed1));
Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
} else if (mdb->num_rows == 1) {
- if ((row = sql_fetch_row(mdb)) == NULL) {
+ if ((row = sql_fetch_row(mdb)) == NULL) {
Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
- } else {
- pdbr->PoolId = str_to_int64(row[0]);
+ } else {
+ pdbr->PoolId = str_to_int64(row[0]);
bstrncpy(pdbr->Name, row[1]!=NULL?row[1]:"", sizeof(pdbr->Name));
- 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]);
+ 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[14]!=NULL?row[14]:"", sizeof(pdbr->PoolType));
- pdbr->LabelType = str_to_int64(row[15]);
+ pdbr->LabelType = str_to_int64(row[15]);
bstrncpy(pdbr->LabelFormat, row[16]!=NULL?row[16]:"", sizeof(pdbr->LabelFormat));
- stat = pdbr->PoolId;
- }
+ ok = true;
+ }
} else {
Mmsg(mdb->errmsg, _("Pool record not found in Catalog.\n"));
}
Mmsg(mdb->errmsg, _("Pool record not found in Catalog.\n"));
}
db_unlock(mdb);
- return stat;
+ return ok;
}
/* Get Client Record
* otherwise, we search on the Client Name
*
* Returns: 0 on failure
- * 1 on success
+ * 1 on success
*/
int db_get_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cdbr)
{
char ed1[50];
db_lock(mdb);
- if (cdbr->ClientId != 0) { /* find by id */
+ if (cdbr->ClientId != 0) { /* find by id */
Mmsg(mdb->cmd,
"SELECT ClientId,Name,Uname,AutoPrune,FileRetention,JobRetention "
"FROM Client WHERE Client.ClientId=%s",
- edit_int64(cdbr->ClientId, ed1));
- } else { /* find by name */
+ edit_int64(cdbr->ClientId, ed1));
+ } else { /* find by name */
Mmsg(mdb->cmd,
"SELECT ClientId,Name,Uname,AutoPrune,FileRetention,JobRetention "
"FROM Client WHERE Client.Name='%s'", cdbr->Name);
mdb->num_rows = sql_num_rows(mdb);
if (mdb->num_rows > 1) {
Mmsg1(&mdb->errmsg, _("More than one Client!: %s\n"),
- edit_uint64(mdb->num_rows, ed1));
+ edit_uint64(mdb->num_rows, ed1));
Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
} else if (mdb->num_rows == 1) {
- if ((row = sql_fetch_row(mdb)) == NULL) {
+ if ((row = sql_fetch_row(mdb)) == NULL) {
Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
- } else {
- cdbr->ClientId = str_to_int64(row[0]);
+ } 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;
- }
+ cdbr->AutoPrune = str_to_int64(row[3]);
+ cdbr->FileRetention = str_to_int64(row[4]);
+ cdbr->JobRetention = str_to_int64(row[5]);
+ stat = 1;
+ }
} else {
Mmsg(mdb->errmsg, _("Client record not found in Catalog.\n"));
}
* Get Counter Record
*
* Returns: 0 on failure
- * 1 on success
+ * 1 on success
*/
int db_get_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr)
{
Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
}
if (mdb->num_rows >= 1) {
- if ((row = sql_fetch_row(mdb)) == NULL) {
+ if ((row = sql_fetch_row(mdb)) == NULL) {
Mmsg1(&mdb->errmsg, _("error fetching Counter row: %s\n"), sql_strerror(mdb));
Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
- sql_free_result(mdb);
- db_unlock(mdb);
- return 0;
- }
- cr->MinValue = atoi(row[0]);
- cr->MaxValue = atoi(row[1]);
- cr->CurrentValue = atoi(row[2]);
- if (row[3]) {
- bstrncpy(cr->WrapCounter, row[3], sizeof(cr->WrapCounter));
- } else {
- cr->WrapCounter[0] = 0;
- }
- sql_free_result(mdb);
- db_unlock(mdb);
- return 1;
+ sql_free_result(mdb);
+ db_unlock(mdb);
+ return 0;
+ }
+ cr->MinValue = atoi(row[0]);
+ cr->MaxValue = atoi(row[1]);
+ cr->CurrentValue = atoi(row[2]);
+ if (row[3]) {
+ bstrncpy(cr->WrapCounter, row[3], sizeof(cr->WrapCounter));
+ } else {
+ cr->WrapCounter[0] = 0;
+ }
+ sql_free_result(mdb);
+ db_unlock(mdb);
+ return 1;
}
sql_free_result(mdb);
} else {
* otherwise, we search on the name
*
* Returns: 0 on failure
- * id on success
+ * id on success
*/
int db_get_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr)
{
char ed1[50];
db_lock(mdb);
- if (fsr->FileSetId != 0) { /* find by id */
+ if (fsr->FileSetId != 0) { /* find by id */
Mmsg(mdb->cmd,
"SELECT FileSetId,FileSet,MD5,CreateTime FROM FileSet "
"WHERE FileSetId=%s",
- edit_int64(fsr->FileSetId, ed1));
- } else { /* find by name */
+ edit_int64(fsr->FileSetId, ed1));
+ } else { /* find by name */
Mmsg(mdb->cmd,
"SELECT FileSetId,FileSet,CreateTime,MD5 FROM FileSet "
"WHERE FileSet='%s' ORDER BY CreateTime DESC LIMIT 1", fsr->FileSet);
if (QUERY_DB(jcr, mdb, mdb->cmd)) {
mdb->num_rows = sql_num_rows(mdb);
if (mdb->num_rows > 1) {
- char ed1[30];
+ char ed1[30];
Mmsg1(&mdb->errmsg, _("Error got %s FileSets but expected only one!\n"),
- edit_uint64(mdb->num_rows, ed1));
- sql_data_seek(mdb, mdb->num_rows-1);
+ edit_uint64(mdb->num_rows, ed1));
+ sql_data_seek(mdb, mdb->num_rows-1);
}
if ((row = sql_fetch_row(mdb)) == NULL) {
Mmsg1(&mdb->errmsg, _("FileSet record \"%s\" not found.\n"), fsr->FileSet);
} else {
- fsr->FileSetId = str_to_int64(row[0]);
+ fsr->FileSetId = str_to_int64(row[0]);
bstrncpy(fsr->FileSet, row[1]!=NULL?row[1]:"", sizeof(fsr->FileSet));
bstrncpy(fsr->MD5, row[2]!=NULL?row[2]:"", sizeof(fsr->MD5));
bstrncpy(fsr->cCreateTime, row[3]!=NULL?row[3]:"", sizeof(fsr->cCreateTime));
- stat = fsr->FileSetId;
+ stat = fsr->FileSetId;
}
sql_free_result(mdb);
} else {
* Get the number of Media records
*
* Returns: -1 on failure
- * number on success
+ * number on success
*/
int db_get_num_media_records(JCR *jcr, B_DB *mdb)
{
* The caller must free ids if non-NULL.
*
* Returns 0: on failure
- * 1: on success
+ * 1: on success
*/
int db_get_media_ids(JCR *jcr, B_DB *mdb, uint32_t PoolId, int *num_ids, uint32_t *ids[])
{
if (QUERY_DB(jcr, 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;
+ 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;
/* Get Media Record
*
* Returns: 0 on failure
- * id on success
+ * id on success
*/
int db_get_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
{
db_unlock(mdb);
return 1;
}
- if (mr->MediaId != 0) { /* find by id */
+ if (mr->MediaId != 0) { /* find by id */
Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,"
"VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,"
"MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,"
"MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger,"
"EndFile,EndBlock,VolParts,LabelType,LabelDate,StorageId "
"FROM Media WHERE MediaId=%s",
- edit_int64(mr->MediaId, ed1));
- } else { /* find by name */
+ edit_int64(mr->MediaId, ed1));
+ } else { /* find by name */
Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,"
"VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,"
"MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,"
mdb->num_rows = sql_num_rows(mdb);
if (mdb->num_rows > 1) {
Mmsg1(&mdb->errmsg, _("More than one Volume!: %s\n"),
- edit_uint64(mdb->num_rows, ed1));
+ edit_uint64(mdb->num_rows, ed1));
Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
} else if (mdb->num_rows == 1) {
- if ((row = sql_fetch_row(mdb)) == NULL) {
+ if ((row = sql_fetch_row(mdb)) == NULL) {
Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
- } else {
- /* return values */
- mr->MediaId = str_to_int64(row[0]);
+ } else {
+ /* return values */
+ mr->MediaId = str_to_int64(row[0]);
bstrncpy(mr->VolumeName, row[1]!=NULL?row[1]:"", sizeof(mr->VolumeName));
- 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->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 = 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]);
+ 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));
- mr->FirstWritten = (time_t)str_to_utime(mr->cFirstWritten);
+ mr->FirstWritten = (time_t)str_to_utime(mr->cFirstWritten);
bstrncpy(mr->cLastWritten, row[21]!=NULL?row[21]:"", sizeof(mr->cLastWritten));
- mr->LastWritten = (time_t)str_to_utime(mr->cLastWritten);
- mr->InChanger = str_to_uint64(row[22]);
- mr->EndFile = str_to_uint64(row[23]);
- mr->EndBlock = str_to_uint64(row[24]);
- mr->VolParts = str_to_int64(row[25]);
- mr->LabelType = str_to_int64(row[26]);
+ mr->LastWritten = (time_t)str_to_utime(mr->cLastWritten);
+ mr->InChanger = str_to_uint64(row[22]);
+ mr->EndFile = str_to_uint64(row[23]);
+ mr->EndBlock = str_to_uint64(row[24]);
+ mr->VolParts = str_to_int64(row[25]);
+ mr->LabelType = str_to_int64(row[26]);
bstrncpy(mr->cLabelDate, row[27]!=NULL?row[27]:"", sizeof(mr->cLabelDate));
- mr->LabelDate = (time_t)str_to_utime(mr->cLabelDate);
- mr->StorageId = str_to_int64(row[28]);
- stat = mr->MediaId;
- }
+ mr->LabelDate = (time_t)str_to_utime(mr->cLabelDate);
+ mr->StorageId = str_to_int64(row[28]);
+ stat = mr->MediaId;
+ }
} else {
- if (mr->MediaId != 0) {
+ if (mr->MediaId != 0) {
Mmsg1(&mdb->errmsg, _("Media record MediaId=%s not found.\n"),
- edit_int64(mr->MediaId, ed1));
- } else {
+ edit_int64(mr->MediaId, ed1));
+ } else {
Mmsg1(&mdb->errmsg, _("Media record for Volume \"%s\" not found.\n"),
- mr->VolumeName);
- }
+ mr->VolumeName);
+ }
}
sql_free_result(mdb);
} else {
if (mr->MediaId != 0) {
Mmsg(mdb->errmsg, _("Media record for MediaId=%u not found in Catalog.\n"),
- mr->MediaId);
+ mr->MediaId);
} else {
Mmsg(mdb->errmsg, _("Media record for Vol=%s not found in Catalog.\n"),
- mr->VolumeName);
+ mr->VolumeName);
} }
db_unlock(mdb);
return stat;
*/
/* Requests from the Storage daemon */
-static char Find_media[] = "CatReq Job=%127s FindMedia=%d PoolId=%lld\n";
+static char Find_media[] = "CatReq Job=%127s FindMedia=%d pool_name=%127s media_type=%127s\n";
static char Get_Vol_Info[] = "CatReq Job=%127s GetVolInfo VolName=%127s write=%d\n";
static char Update_media[] = "CatReq Job=%127s UpdateMedia VolName=%s"
mr->VolParts,
mr->LabelType);
unbash_spaces(mr->VolumeName);
- Dmsg2(400, "Vol Info for %s: %s", jcr->Job, sd->msg);
+ Dmsg2(100, "Vol Info for %s: %s", jcr->Job, sd->msg);
return stat;
}
MEDIA_DBR mr, sdmr;
JOBMEDIA_DBR jm;
char Job[MAX_NAME_LENGTH];
- int64_t PoolId;
+ char pool_name[MAX_NAME_LENGTH];
int index, ok, label, writing;
POOLMEM *omsg;
+ POOL_DBR pr;
memset(&mr, 0, sizeof(mr));
memset(&sdmr, 0, sizeof(sdmr));
/*
* Request to find next appendable Volume for this Job
*/
- Dmsg1(400, "catreq %s", bs->msg);
+ Dmsg1(100, "catreq %s", bs->msg);
if (!jcr->db) {
omsg = get_memory(bs->msglen+1);
pm_strcpy(omsg, bs->msg);
/*
* Find next appendable medium for SD
*/
- if (sscanf(bs->msg, Find_media, &Job, &index, &PoolId) == 3) {
- mr.PoolId = PoolId;
- ok = find_next_volume_for_append(jcr, &mr, true /*permit create new vol*/);
+ if (sscanf(bs->msg, Find_media, &Job, &index, &pool_name, &mr.MediaType) == 4) {
+ memset(&pr, 0, sizeof(pr));
+ bstrncpy(pr.Name, pool_name, sizeof(pr.Name));
+ ok = db_get_pool_record(jcr, jcr->db, &pr);
+ if (ok) {
+ mr.PoolId = pr.PoolId;
+ ok = find_next_volume_for_append(jcr, &mr, true /*permit create new vol*/);
+ }
/*
* Send Find Media response to Storage daemon
*/
autochanger.c acquire.c append.c \
askdir.c authenticate.c \
block.c butil.c dev.c \
- device.c dircmd.c dvd.c fd_cmds.c job.c \
+ device.c dircmd.c dvd.c ebcdic.c fd_cmds.c job.c \
label.c match_bsr.c mount.c parse_bsr.c \
python.c \
read.c read_record.c record.c \
autochanger.o acquire.o append.o \
askdir.o authenticate.o \
block.o butil.o dev.o \
- device.o dircmd.o dvd.o fd_cmds.o job.o \
+ device.o dircmd.o dvd.o ebcdic.c fd_cmds.o job.o \
label.o match_bsr.o mount.o parse_bsr.o \
python.o \
read.o read_record.o record.o \
# btape
TAPESRCS = btape.c block.c butil.c dev.c device.c label.c \
- ansi_label.c dvd.c \
+ ansi_label.c dvd.c ebcdic.c \
acquire.c mount.c record.c read_record.c \
stored_conf.c match_bsr.c parse_bsr.c spool.c
TAPEOBJS = btape.o block.o butil.o dev.o device.o label.o \
- ansi_label.o dvd.o \
+ ansi_label.o dvd.o ebcdic.o \
autochanger.o acquire.o mount.o record.o read_record.o \
stored_conf.o match_bsr.o parse_bsr.o spool.o
# bls
BLSOBJS = bls.o block.o butil.o device.o dev.o label.o match_bsr.o \
- ansi_label.o dvd.o \
+ ansi_label.o dvd.o ebcdic.o \
autochanger.o acquire.o mount.o parse_bsr.o record.o \
read_record.o stored_conf.o spool.o
# bextract
BEXTOBJS = bextract.o block.o device.o dev.o label.o record.o \
- ansi_label.o dvd.o \
+ ansi_label.o dvd.o ebcdic.o \
autochanger.o acquire.o mount.o match_bsr.o parse_bsr.o butil.o \
read_record.o stored_conf.o spool.o
# bscan
SCNOBJS = bscan.o block.o device.o dev.o label.o \
- ansi_label.o dvd.o \
+ ansi_label.o dvd.o ebcdic.o \
autochanger.o acquire.o mount.o record.o match_bsr.o parse_bsr.o \
butil.o read_record.o stored_conf.o spool.o
# bcopy
COPYOBJS = bcopy.o block.o device.o dev.o label.o \
- ansi_label.o dvd.o \
+ ansi_label.o dvd.o ebcdic.o \
autochanger.o acquire.o mount.o record.o match_bsr.o parse_bsr.o \
butil.o read_record.o stored_conf.o spool.o
{
JCR *jcr = dcr->jcr;
DEVICE *dev = dcr->dev;
+
lock_device(dev);
Dmsg1(100, "release_device device is %s\n", dev_is_tape(dev)?"tape":"disk");
/* Note! do volume update before close, which zaps VolCatInfo */
Dmsg0(100, "dir_update_vol_info. Release0\n");
dir_update_volume_info(dcr, false); /* send Volume info to Director */
+ Dmsg0(100, "==== write ansi eof label \n");
+ write_ansi_ibm_labels(dcr, ANSI_EOF_LABEL, dev->VolHdr.VolName);
}
/* If no writers, close if file or !CAP_ALWAYS_OPEN */
#include "bacula.h" /* pull in global headers */
#include "stored.h" /* pull in Storage Deamon headers */
+/* Imported functions */
+void ascii_to_ebcdic(char *dst, char *src, int count);
+void ebcdic_to_ascii(char *dst, char *src, int count);
+
/* Forward referenced functions */
static char *ansi_date(time_t td, char *buf);
static bool same_label_names(char *bacula_name, char *ansi_name);
char label[80]; /* tape label */
int stat, i;
char *VolName = dcr->VolumeName;
+ bool ok = false;
/*
* Read VOL1, HDR1, HDR2 labels, but ignore the data
* If tape read the following EOF mark, on disk do
* not read.
*/
- Dmsg0(000, "Read ansi label.\n");
+ Dmsg0(100, "Read ansi label.\n");
if (!dev->is_tape()) {
return VOL_OK;
}
if (stat < 0) {
berrno be;
clrerror_dev(dev, -1);
- Dmsg1(000, "Read device got: ERR=%s\n", be.strerror());
+ Dmsg1(100, "Read device got: ERR=%s\n", be.strerror());
Mmsg2(jcr->errmsg, _("Read error on device %s in ANSI label. ERR=%s\n"),
dev->dev_name, be.strerror());
Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
if (stat == 0) {
if (dev->at_eof()) {
dev->state |= ST_EOT;
- Dmsg0(000, "EOM on ANSI label\n");
+ Dmsg0(100, "EOM on ANSI label\n");
Mmsg0(jcr->errmsg, _("Insane! End of tape while reading ANSI label.\n"));
return VOL_LABEL_ERROR; /* at EOM this shouldn't happen */
} else {
}
switch (i) {
case 0: /* Want VOL1 label */
- if (stat != 80 || strncmp("VOL1", label, 4) != 0) {
- Dmsg0(000, "No VOL1 label\n");
- Mmsg0(jcr->errmsg, _("No VOL1 label while reading ANSI label.\n"));
+ if (stat == 80) {
+ if (strncmp("VOL1", label, 4) == 0) {
+ ok = true;
+ dev->label_type = B_ANSI_LABEL;
+ } else {
+ /* Try EBCDIC */
+ ebcdic_to_ascii(label, label, sizeof(label));
+ if (strncmp("VOL1", label, 4) == 0) {
+ ok = true;;
+ dev->label_type = B_IBM_LABEL;
+ }
+ }
+ }
+ if (!ok) {
+ Dmsg0(100, "No VOL1 label\n");
+ Mmsg0(jcr->errmsg, _("No VOL1 label while reading ANSI/IBM label.\n"));
return VOL_NO_LABEL; /* No ANSI label */
}
- dev->label_type = B_ANSI_LABEL;
/* Compare Volume Names allow special wild card */
if (VolName && *VolName && *VolName != '*') {
*q++ = *p++;
}
*q = 0;
- Dmsg2(000, "Wanted ANSI Vol %s got %6s\n", VolName, dev->VolHdr.VolName);
+ Dmsg2(100, "Wanted ANSI Vol %s got %6s\n", VolName, dev->VolHdr.VolName);
Mmsg2(jcr->errmsg, "Wanted ANSI Volume \"%s\" got \"%s\"\n", VolName, dev->VolHdr.VolName);
return VOL_NAME_ERROR;
}
}
break;
case 1:
+ if (dev->label_type == B_IBM_LABEL) {
+ ebcdic_to_ascii(label, label, sizeof(label));
+ }
if (stat != 80 || strncmp("HDR1", label, 4) != 0) {
- Dmsg0(000, "No HDR1 label\n");
+ Dmsg0(100, "No HDR1 label\n");
Mmsg0(jcr->errmsg, _("No HDR1 label while reading ANSI label.\n"));
return VOL_LABEL_ERROR;
}
if (strncmp("BACULA.DATA", &label[4], 11) != 0) {
- Dmsg1(000, "HD1 not Bacula label. Wanted BACULA.DATA got %11s\n",
+ Dmsg1(100, "HD1 not Bacula label. Wanted BACULA.DATA got %11s\n",
&label[4]);
- Mmsg1(jcr->errmsg, _("ANSI Volume \"%s\" does not belong to Bacula.\n"),
+ Mmsg1(jcr->errmsg, _("ANSI/IBM Volume \"%s\" does not belong to Bacula.\n"),
dev->VolHdr.VolName);
return VOL_NAME_ERROR; /* Not a Bacula label */
}
break;
case 2:
+ if (dev->label_type == B_IBM_LABEL) {
+ ebcdic_to_ascii(label, label, sizeof(label));
+ }
if (stat != 80 || strncmp("HDR2", label, 4) != 0) {
- Dmsg0(000, "No HDR2 label\n");
- Mmsg0(jcr->errmsg, _("No HDR2 label while reading ANSI label.\n"));
+ Dmsg0(100, "No HDR2 label\n");
+ Mmsg0(jcr->errmsg, _("No HDR2 label while reading ANSI/IBM label.\n"));
return VOL_LABEL_ERROR;
}
break;
default:
if (stat == 0) {
- Dmsg0(000, "ANSI label OK\n");
+ Dmsg0(100, "ANSI label OK\n");
return VOL_OK;
}
+ if (dev->label_type == B_IBM_LABEL) {
+ ebcdic_to_ascii(label, label, sizeof(label));
+ }
if (stat != 80 || strncmp("HDR", label, 3) != 0) {
- Dmsg0(000, "Unknown or bad ANSI label record.\n");
- Mmsg0(jcr->errmsg, _("Unknown or bad ANSI label record.\n"));
+ Dmsg0(100, "Unknown or bad ANSI/IBM label record.\n");
+ Mmsg0(jcr->errmsg, _("Unknown or bad ANSI/IBM label record.\n"));
return VOL_LABEL_ERROR;
}
break;
}
}
- Dmsg0(000, "Too many records in ANSI label.\n");
- Mmsg0(jcr->errmsg, _("Too many records in while reading ANSI label.\n"));
+ Dmsg0(100, "Too many records in ANSI/IBM label.\n");
+ Mmsg0(jcr->errmsg, _("Too many records in while reading ANSI/IBM label.\n"));
return VOL_LABEL_ERROR;
}
+/*
+ * ANSI/IBM VOL1 label
+ * 80 characters blank filled
+ * Pos count Function What Bacula puts
+ * 0-3 4 "VOL1" VOL1
+ * 4-9 6 Volume name Volume name
+ * 10-10 1 Access code
+ * 11-36 26 Unused
+ *
+ * ANSI
+ * 37-50 14 Owner
+ * 51-78 28 reserved
+ * 79 1 ANSI level 3
+ *
+ * IBM
+ * 37-40 4 reserved
+ * 41-50 10 Owner
+ * 51-79 29 reserved
+
+ *
+ *
+ * ANSI/IBM HDR1 label
+ * 80 characters blank filled
+ * Pos count Function What Bacula puts
+ * 0-3 4 "HDR1" HDR1
+ * 4-20 17 File name BACULA.DATA
+ * 21-26 6 Volume name Volume name
+ * 27-30 4 Vol seq num 0001
+ * 31-34 4 file num 0001
+ * 35-38 4 Generation 0001
+ * 39-40 2 Gen version 00
+ * 41-46 6 Create date bYYDDD yesterday
+ * 47-52 6 Expire date bYYDDD today
+ * 53-53 1 Access
+ * 54-59 6 Block count 000000
+ * 60-72 13 Software name Bacula
+ * 73-79 7 Reserved
+
+ * ANSI/IBM HDR2 label
+ * 80 characters blank filled
+ * Pos count Function What Bacula puts
+ * 0-3 4 "HDR2" HDR2
+ * 4-4 1 Record format D (V if IBM) => variable
+ * 5-9 5 Block length 32000
+ * 10-14 5 Rec length 32000
+ * 15-15 1 Density
+ * 16-16 1 Continued
+ * 17-33 17 Job
+ * 34-35 2 Recording
+ * 36-36 1 cr/lf ctl
+ * 37-37 1 reserved
+ * 38-38 1 Blocked flag
+ * 39-49 11 reserved
+ * 50-51 2 offset
+ * 52-79 28 reserved
+
+ */
+
+static const char *labels[] = {"HDR", "EOF", "EOV"};
+
/*
* Write an ANSI or IBM 80 character tape label
- * Assume we are positioned at the beginning of the tape.
+ * Type determines whether we are writing HDR, EOF, or EOV labels
+ * Assume we are positioned to write the labels
* Returns: true of OK
* false if error
*/
-bool write_ansi_ibm_label(DCR *dcr, const char *VolName)
+bool write_ansi_ibm_labels(DCR *dcr, int type, const char *VolName)
{
DEVICE *dev = dcr->dev;
JCR *jcr = dcr->jcr;
case B_ANSI_LABEL:
case B_IBM_LABEL:
ser_declare;
- Dmsg1(000, "Write ANSI label type=%d\n", label_type);
+ Dmsg1(100, "Write ANSI label type=%d\n", label_type);
len = strlen(VolName);
if (len > 6) {
Jmsg1(jcr, M_FATAL, 0, _("ANSI Volume label name \"%s\" longer than 6 chars.\n"),
VolName);
return false;
}
- memset(label, ' ', sizeof(label));
- ser_begin(label, sizeof(label));
- ser_bytes("VOL1", 4);
- ser_bytes(VolName, len);
- label[79] = '3'; /* ANSI label flag */
- /* Write VOL1 label */
- stat = write(dev->fd, label, sizeof(label));
- if (stat != sizeof(label)) {
- berrno be;
- Jmsg1(jcr, M_FATAL, 0, _("Could not write ANSI VOL1 label. ERR=%s\n"),
- be.strerror());
- return false;
+ if (type == ANSI_VOL_LABEL) {
+ ser_begin(label, sizeof(label));
+ ser_bytes("VOL1", 4);
+ ser_bytes(VolName, len);
+ /* Write VOL1 label */
+ if (label_type == B_IBM_LABEL) {
+ ascii_to_ebcdic(label, label, sizeof(label));
+ } else {
+ label[79] = '3'; /* ANSI label flag */
+ }
+ stat = write(dev->fd, label, sizeof(label));
+ if (stat != sizeof(label)) {
+ berrno be;
+ Jmsg1(jcr, M_FATAL, 0, _("Could not write ANSI VOL1 label. ERR=%s\n"),
+ be.strerror());
+ return false;
+ }
}
+
/* Now construct HDR1 label */
+ memset(label, ' ', sizeof(label));
ser_begin(label, sizeof(label));
- ser_bytes("HDR1", 4);
+ ser_bytes(labels[type], 3);
+ ser_bytes("1", 1);
ser_bytes("BACULA.DATA", 11); /* Filename field */
ser_begin(&label[21], sizeof(label)-21); /* fileset field */
ser_bytes(VolName, len); /* write Vol Ser No. */
ser_bytes(ansi_date(now - 24 * 3600, date), 6); /* created yesterday */
ser_bytes(" 000000Bacula ", 27);
/* Write HDR1 label */
+ if (label_type == B_IBM_LABEL) {
+ ascii_to_ebcdic(label, label, sizeof(label));
+ }
stat = write(dev->fd, label, sizeof(label));
if (stat != sizeof(label)) {
berrno be;
be.strerror());
return false;
}
+
+
/* Now construct HDR2 label */
memset(label, ' ', sizeof(label));
ser_begin(label, sizeof(label));
- ser_bytes("HDR2F3200032000", 15);
- /* Write HDR1 label */
+ ser_bytes(labels[type], 3);
+ ser_bytes("2D3200032000", 12);
+ /* Write HDR2 label */
+ if (label_type == B_IBM_LABEL) {
+ label[4] = 'V';
+ ascii_to_ebcdic(label, label, sizeof(label));
+ }
stat = write(dev->fd, label, sizeof(label));
if (stat != sizeof(label)) {
berrno be;
Jmsg(jcr, M_FATAL, 0, _("Error writing EOF to tape. ERR=%s"), dev->errmsg);
return false;
}
+ /* If this is an EOF label, we must reposition to before it
+ as Bacula does not support these on read.
+ */
+ if (type == ANSI_EOF_LABEL) {
+ if (!bsf_dev(dev, 2) || !fsf_dev(dev, 1)) {
+ Jmsg(jcr, M_FATAL, 0, _("Error repositiong after writing ANSI/IBM EOF labels to tape. ERR=%s"),
+ dev->errmsg);
+ return false;
+ }
+ }
return true;
default:
Jmsg0(jcr, M_ABORT, 0, _("write_ansi_ibm_label called for non-ANSI/IBM type\n"));
return false;
}
-
+/*
+ * ANSI date
+ * ' 'YYDDD
+ */
static char *ansi_date(time_t td, char *buf)
{
struct tm *tm;
#include "stored.h" /* pull in Storage Deamon headers */
/* Requests sent to the Director */
-static char Find_media[] = "CatReq Job=%s FindMedia=%d PoolId=%s\n";
+static char Find_media[] = "CatReq Job=%s FindMedia=%d pool_name=%s media_type=%s\n";
static char Get_Vol_Info[] = "CatReq Job=%s GetVolInfo VolName=%s write=%d\n";
static char Update_media[] = "CatReq Job=%s UpdateMedia VolName=%s"
" VolJobs=%u VolFiles=%u VolBlocks=%u VolBytes=%s VolMounts=%u"
{
JCR *jcr = dcr->jcr;
BSOCK *dir = jcr->dir_bsock;
- char ed1[50];
JCR *njcr;
Dmsg0(200, "dir_find_next_appendable_volume\n");
* drive, so we continue looking for a not in use Volume.
*/
for (int vol_index=1; vol_index < 3; vol_index++) {
- bnet_fsend(dir, Find_media, jcr->Job, vol_index, edit_int64(dcr->PoolId, ed1));
+ bash_spaces(dcr->media_type);
+ bash_spaces(dcr->pool_name);
+ bnet_fsend(dir, Find_media, jcr->Job, vol_index, dcr->pool_name, dcr->media_type);
+ unbash_spaces(dcr->media_type);
+ unbash_spaces(dcr->pool_name);
Dmsg1(100, ">dird: %s", dir->msg);
if (do_get_volume_info(dcr)) {
Dmsg2(300, "JobId=%d got possible Vol=%s\n", jcr->JobId, dcr->VolumeName);
ser_uint32(rec->data_len);
ser_bytes(rec->data, rec->data_len);
dir->msglen = ser_length(dir->msg);
- Dmsg1(100, ">dird: %s", dir->msg);
+ Dmsg1(1800, ">dird: %s\n", dir->msg); /* Attributes */
return bnet_send(dir);
}
/* Set new file/block parameters for current dcr */
set_new_file_parameters(dcr);
+ if (ok) {
+ ok = write_ansi_ibm_labels(dcr, ANSI_EOV_LABEL, dev->VolHdr.VolName);
+ }
+
if (ok && dev_cap(dev, CAP_TWOEOF) && weof_dev(dev, 1) != 0) { /* end the tape */
dev->VolCatInfo.VolCatErrors++;
/* This may not be fatal since we already wrote an EOF */
/*
* Position device to end of medium (end of data)
- * Returns: 1 on succes
- * 0 on error
+ * Returns: true on succes
+ * false on error
*/
-int
+bool
eod_dev(DEVICE *dev)
{
struct mtop mt_com;
struct mtget mt_stat;
- int stat = 0;
+ bool ok = true;
off_t pos;
Dmsg0(29, "eod_dev\n");
if (dev->at_eot()) {
- return 1;
+ return true;
}
dev->state &= ~(ST_EOF); /* remove EOF flags */
dev->block_num = dev->file = 0;
dev->file_size = 0;
dev->file_addr = 0;
if (dev->state & (ST_FIFO | ST_PROG)) {
- return 1;
+ return true;
}
if (!dev->is_tape()) {
pos = lseek_dev(dev, (off_t)0, SEEK_END);
if (pos >= 0) {
update_pos_dev(dev);
dev->state |= ST_EOT;
- return 1;
+ return true;
}
dev->dev_errno = errno;
berrno be;
Mmsg2(&dev->errmsg, _("lseek_dev error on %s. ERR=%s.\n"),
dev->dev_name, be.strerror());
- return 0;
+ return false;
}
#ifdef MTEOM
if (dev_cap(dev, CAP_FASTFSF) && !dev_cap(dev, CAP_EOM)) {
/* If unknown position, rewind */
if (!dev_get_os_pos(dev, &mt_stat)) {
if (!rewind_dev(dev)) {
- return 0;
+ return false;
}
}
mt_com.mt_op = MTFSF;
mt_com.mt_count = 1;
}
- if ((stat=ioctl(dev->fd, MTIOCTOP, (char *)&mt_com)) < 0) {
+ if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) {
berrno be;
clrerror_dev(dev, mt_com.mt_op);
Dmsg1(50, "ioctl error: %s\n", be.strerror());
update_pos_dev(dev);
Mmsg2(&dev->errmsg, _("ioctl MTEOM error on %s. ERR=%s.\n"),
dev->dev_name, be.strerror());
- return 0;
+ return false;
}
if (!dev_get_os_pos(dev, &mt_stat)) {
clrerror_dev(dev, -1);
Mmsg2(&dev->errmsg, _("ioctl MTIOCGET error on %s. ERR=%s.\n"),
dev->dev_name, be.strerror());
- return 0;
+ return false;
}
Dmsg2(100, "EOD file=%d block=%d\n", mt_stat.mt_fileno, mt_stat.mt_blkno);
dev->set_eof();
dev->file = mt_stat.mt_fileno;
-
} else {
#else
{
* Rewind then use FSF until EOT reached
*/
if (!rewind_dev(dev)) {
- return 0;
+ return false;
}
/*
* Move file by file to the end of the tape
Dmsg0(200, "eod_dev: doing fsf 1\n");
if (!fsf_dev(dev, 1)) {
Dmsg0(200, "fsf_dev error.\n");
- return 0;
+ return false;
}
/*
* Avoid infinite loop. ***FIXME*** possibly add code
dev->set_eof();
dev->file = mt_stat.mt_fileno;
}
- stat = 0;
- break; /* we are not progressing, bail out */
+ return false;
}
}
}
if (dev_cap(dev, CAP_BSFATEOM)) {
struct mtget mt_stat;
/* Backup over EOF */
- stat = bsf_dev(dev, 1);
+ ok = bsf_dev(dev, 1);
/* If BSF worked and fileno is known (not -1), set file */
if (dev_get_os_pos(dev, &mt_stat)) {
Dmsg2(100, "BSFATEOF adjust file from %d to %d\n", dev->file , mt_stat.mt_fileno);
}
} else {
update_pos_dev(dev); /* update position */
- stat = 1;
+ }
+ /* If this is an ANSI or IBM labeled tape we must
+ * backspace over EOF label
+ */
+ if (dev->label_type != B_BACULA_LABEL) {
+ if (!bsf_dev(dev, 2) || !fsf_dev(dev, 1)) {
+ ok = false;
+ }
}
Dmsg1(200, "EOD dev->file=%d\n", dev->file);
- return stat;
+ return ok;
}
/*
/*
* Convert from ASCII to EBCDIC
*/
-asci_to_ebcdic(char *dst, char *src, int count)
+void ascii_to_ebcdic(char *dst, char *src, int count)
{
while (count--) {
*dst++ = to_ebcdic_table[0377 & *src++];
/*
* Convert from EBCDIC to ASCII
*/
-ebcdic_to_ascii(char *dst, char *src, int count)
+void ebcdic_to_ascii(char *dst, char *src, int count)
{
while (count--) {
- *dst++ = to_asci_table[0377 & *src++];
+ *dst++ = to_ascii_table[0377 & *src++];
}
}
rewind_dev(dev);
goto bail_out;
}
- } else if (!write_ansi_ibm_label(dcr, VolName)) {
+ } else if (!write_ansi_ibm_labels(dcr, ANSI_VOL_LABEL, VolName)) {
goto bail_out;
}
rewind_dev(dev);
return false;
}
- } else if (!write_ansi_ibm_label(dcr, dev->VolHdr.VolName)) {
+ } else if (!write_ansi_ibm_labels (dcr, ANSI_VOL_LABEL, dev->VolHdr.VolName)) {
return false;
}
uint32_t new_VolSessionId();
/* From acquire.c */
-bool reserve_device_for_append(JCR *jcr, DEVICE *dev);
-DCR *acquire_device_for_append(JCR *jcr, DEVICE *dev);
-bool reserve_device_for_read(JCR *jcr, DEVICE *dev);
-DCR *acquire_device_for_read(JCR *jcr, DEVICE *dev);
-bool release_device(DCR *dcr);
-DCR *new_dcr(JCR *jcr, DEVICE *dev);
-void free_dcr(DCR *dcr);
+bool reserve_device_for_append(JCR *jcr, DEVICE *dev);
+DCR *acquire_device_for_append(JCR *jcr, DEVICE *dev);
+bool reserve_device_for_read(JCR *jcr, DEVICE *dev);
+DCR *acquire_device_for_read(JCR *jcr, DEVICE *dev);
+bool release_device(DCR *dcr);
+DCR *new_dcr(JCR *jcr, DEVICE *dev);
+void free_dcr(DCR *dcr);
/* From askdir.c */
enum get_vol_info_rw {
GET_VOL_INFO_FOR_WRITE,
GET_VOL_INFO_FOR_READ
};
-bool dir_get_volume_info(DCR *dcr, enum get_vol_info_rw);
-bool dir_find_next_appendable_volume(DCR *dcr);
-bool dir_update_volume_info(DCR *dcr, bool label);
-bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr);
-bool dir_ask_sysop_to_mount_volume(DCR *dcr);
-bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec);
-bool dir_send_job_status(JCR *jcr);
-bool dir_create_jobmedia_record(DCR *dcr);
-bool dir_update_device(JCR *jcr, DEVICE *dev);
-bool dir_update_changer(JCR *jcr, AUTOCHANGER *changer);
+bool dir_get_volume_info(DCR *dcr, enum get_vol_info_rw);
+bool dir_find_next_appendable_volume(DCR *dcr);
+bool dir_update_volume_info(DCR *dcr, bool label);
+bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr);
+bool dir_ask_sysop_to_mount_volume(DCR *dcr);
+bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec);
+bool dir_send_job_status(JCR *jcr);
+bool dir_create_jobmedia_record(DCR *dcr);
+bool dir_update_device(JCR *jcr, DEVICE *dev);
+bool dir_update_changer(JCR *jcr, AUTOCHANGER *changer);
/* authenticate.c */
-int authenticate_director(JCR *jcr);
-int authenticate_filed(JCR *jcr);
+int authenticate_director(JCR *jcr);
+int authenticate_filed(JCR *jcr);
/* From autochanger.c */
-int autoload_device(DCR *dcr, int writing, BSOCK *dir);
-bool autochanger_cmd(DCR *dcr, BSOCK *dir, const char *cmd);
-void mark_volume_not_inchanger(DCR *dcr);
-char *edit_device_codes(DCR *dcr, char *omsg, const char *cmd);
+int autoload_device(DCR *dcr, int writing, BSOCK *dir);
+bool autochanger_cmd(DCR *dcr, BSOCK *dir, const char *cmd);
+void mark_volume_not_inchanger(DCR *dcr);
+char *edit_device_codes(DCR *dcr, char *omsg, const char *cmd);
/* From block.c */
-void dump_block(DEV_BLOCK *b, const char *msg);
+void dump_block(DEV_BLOCK *b, const char *msg);
DEV_BLOCK *new_block(DEVICE *dev);
DEV_BLOCK *dup_block(DEV_BLOCK *eblock);
-void init_block_write(DEV_BLOCK *block);
-void empty_block(DEV_BLOCK *block);
-void free_block(DEV_BLOCK *block);
-bool write_block_to_device(DCR *dcr);
-bool write_block_to_dev(DCR *dcr);
-void print_block_read_errors(JCR *jcr, DEV_BLOCK *block);
-void ser_block_header(DEV_BLOCK *block);
+void init_block_write(DEV_BLOCK *block);
+void empty_block(DEV_BLOCK *block);
+void free_block(DEV_BLOCK *block);
+bool write_block_to_device(DCR *dcr);
+bool write_block_to_dev(DCR *dcr);
+void print_block_read_errors(JCR *jcr, DEV_BLOCK *block);
+void ser_block_header(DEV_BLOCK *block);
#define CHECK_BLOCK_NUMBERS true
#define NO_BLOCK_NUMBER_CHECK false
-bool read_block_from_device(DCR *dcr, bool check_block_numbers);
-bool read_block_from_dev(DCR *dcr, bool check_block_numbers);
+bool read_block_from_device(DCR *dcr, bool check_block_numbers);
+bool read_block_from_dev(DCR *dcr, bool check_block_numbers);
/* From butil.c -- utilities for SD tool programs */
-void print_ls_output(const char *fname, const char *link, int type, struct stat *statp);
+void print_ls_output(const char *fname, const char *link, int type, struct stat *statp);
JCR *setup_jcr(const char *name, char *dev_name, BSR *bsr,
- const char *VolumeName, int mode);
-void display_tape_error_status(JCR *jcr, DEVICE *dev);
+ const char *VolumeName, int mode);
+void display_tape_error_status(JCR *jcr, DEVICE *dev);
/* From dev.c */
-DEVICE *init_dev(JCR *jcr, DEVICE *dev, DEVRES *device);
-int open_dev(DEVICE *dev, char *VolName, int mode);
-off_t lseek_dev(DEVICE *dev, off_t offset, int whence);
-int open_first_part(DEVICE *dev);
-int open_next_part(DEVICE *dev);
-int open_guess_name_dev(DEVICE *dev);
-void close_dev(DEVICE *dev);
-void force_close_dev(DEVICE *dev);
-bool truncate_dev(DEVICE *dev);
-void term_dev(DEVICE *dev);
-char * strerror_dev(DEVICE *dev);
-void clrerror_dev(DEVICE *dev, int func);
-bool update_pos_dev(DEVICE *dev);
-bool rewind_dev(DEVICE *dev);
-bool load_dev(DEVICE *dev);
-bool offline_dev(DEVICE *dev);
-int flush_dev(DEVICE *dev);
-int weof_dev(DEVICE *dev, int num);
-int write_block(DEVICE *dev);
+DEVICE *init_dev(JCR *jcr, DEVICE *dev, DEVRES *device);
+int open_dev(DEVICE *dev, char *VolName, int mode);
+off_t lseek_dev(DEVICE *dev, off_t offset, int whence);
+int open_first_part(DEVICE *dev);
+int open_next_part(DEVICE *dev);
+int open_guess_name_dev(DEVICE *dev);
+void close_dev(DEVICE *dev);
+void force_close_dev(DEVICE *dev);
+bool truncate_dev(DEVICE *dev);
+void term_dev(DEVICE *dev);
+char * strerror_dev(DEVICE *dev);
+void clrerror_dev(DEVICE *dev, int func);
+bool update_pos_dev(DEVICE *dev);
+bool rewind_dev(DEVICE *dev);
+bool load_dev(DEVICE *dev);
+bool offline_dev(DEVICE *dev);
+int flush_dev(DEVICE *dev);
+int weof_dev(DEVICE *dev, int num);
+int write_block(DEVICE *dev);
uint32_t status_dev(DEVICE *dev);
-int eod_dev(DEVICE *dev);
-bool fsf_dev(DEVICE *dev, int num);
-bool fsr_dev(DEVICE *dev, int num);
-bool bsf_dev(DEVICE *dev, int num);
-bool bsr_dev(DEVICE *dev, int num);
-void attach_jcr_to_device(DEVICE *dev, JCR *jcr);
-void detach_jcr_from_device(DEVICE *dev, JCR *jcr);
-JCR *next_attached_jcr(DEVICE *dev, JCR *jcr);
-bool dev_can_write(DEVICE *dev);
-bool offline_or_rewind_dev(DEVICE *dev);
-bool reposition_dev(DEVICE *dev, uint32_t file, uint32_t block);
-void init_dev_wait_timers(DEVICE *dev);
-bool double_dev_wait_time(DEVICE *dev);
+bool eod_dev(DEVICE *dev);
+bool fsf_dev(DEVICE *dev, int num);
+bool fsr_dev(DEVICE *dev, int num);
+bool bsf_dev(DEVICE *dev, int num);
+bool bsr_dev(DEVICE *dev, int num);
+void attach_jcr_to_device(DEVICE *dev, JCR *jcr);
+void detach_jcr_from_device(DEVICE *dev, JCR *jcr);
+JCR *next_attached_jcr(DEVICE *dev, JCR *jcr);
+bool dev_can_write(DEVICE *dev);
+bool offline_or_rewind_dev(DEVICE *dev);
+bool reposition_dev(DEVICE *dev, uint32_t file, uint32_t block);
+void init_dev_wait_timers(DEVICE *dev);
+bool double_dev_wait_time(DEVICE *dev);
/* Get info about device */
-char * dev_vol_name(DEVICE *dev);
+char * dev_vol_name(DEVICE *dev);
uint32_t dev_block(DEVICE *dev);
uint32_t dev_file(DEVICE *dev);
-bool dev_is_tape(DEVICE *dev);
+bool dev_is_tape(DEVICE *dev);
/* From device.c */
-bool open_device(DCR *dcr);
-bool first_open_device(DEVICE *dev);
-bool fixup_device_block_write_error(DCR *dcr);
-void _lock_device(const char *file, int line, DEVICE *dev);
-void _unlock_device(const char *file, int line, DEVICE *dev);
-void _block_device(const char *file, int line, DEVICE *dev, int state);
-void _unblock_device(const char *file, int line, DEVICE *dev);
-void _steal_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold, int state);
-void _give_back_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold);
-void set_new_volume_parameters(DCR *dcr);
-void set_new_file_parameters(DCR *dcr);
-bool device_is_unmounted(DEVICE *dev);
-void dev_lock(DEVICE *dev);
-void dev_unlock(DEVICE *dev);
+bool open_device(DCR *dcr);
+bool first_open_device(DEVICE *dev);
+bool fixup_device_block_write_error(DCR *dcr);
+void _lock_device(const char *file, int line, DEVICE *dev);
+void _unlock_device(const char *file, int line, DEVICE *dev);
+void _block_device(const char *file, int line, DEVICE *dev, int state);
+void _unblock_device(const char *file, int line, DEVICE *dev);
+void _steal_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold, int state);
+void _give_back_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold);
+void set_new_volume_parameters(DCR *dcr);
+void set_new_file_parameters(DCR *dcr);
+bool device_is_unmounted(DEVICE *dev);
+void dev_lock(DEVICE *dev);
+void dev_unlock(DEVICE *dev);
const char *edit_blocked_reason(DEVICE *dev);
/* From dircmd.c */
-void *handle_connection_request(void *arg);
+void *handle_connection_request(void *arg);
/* From fd_cmds.c */
-void run_job(JCR *jcr);
-bool bootstrap_cmd(JCR *jcr);
+void run_job(JCR *jcr);
+bool bootstrap_cmd(JCR *jcr);
/* From job.c */
-void stored_free_jcr(JCR *jcr);
-void connection_from_filed(void *arg);
-void handle_filed_connection(BSOCK *fd, char *job_name);
+void stored_free_jcr(JCR *jcr);
+void connection_from_filed(void *arg);
+void handle_filed_connection(BSOCK *fd, char *job_name);
/* From label.c */
-int read_dev_volume_label(DCR *dcr);
-int read_dev_volume_label_guess(DCR *dcr, bool write);
-void create_session_label(DCR *dcr, DEV_RECORD *rec, int label);
-void create_volume_label(DEVICE *dev, const char *VolName, const char *PoolName);
-bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, const char *PoolName);
-bool write_ansi_ibm_label(DCR *dcr, const char *VolName);
-int read_ansi_ibm_label(DCR *dcr);
-bool write_session_label(DCR *dcr, int label);
-bool write_volume_label_to_block(DCR *dcr);
-bool rewrite_volume_label(DCR *dcr, bool recycle);
-void dump_volume_label(DEVICE *dev);
-void dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose);
-bool unser_volume_label(DEVICE *dev, DEV_RECORD *rec);
-bool unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec);
+int read_dev_volume_label(DCR *dcr);
+int read_dev_volume_label_guess(DCR *dcr, bool write);
+void create_session_label(DCR *dcr, DEV_RECORD *rec, int label);
+void create_volume_label(DEVICE *dev, const char *VolName, const char *PoolName);
+bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, const char *PoolName);
+#define ANSI_VOL_LABEL 0
+#define ANSI_EOF_LABEL 1
+#define ANSI_EOV_LABEL 2
+bool write_ansi_ibm_labels(DCR *dcr, int type, const char *VolName);
+int read_ansi_ibm_label(DCR *dcr);
+bool write_session_label(DCR *dcr, int label);
+bool write_volume_label_to_block(DCR *dcr);
+bool rewrite_volume_label(DCR *dcr, bool recycle);
+void dump_volume_label(DEVICE *dev);
+void dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose);
+bool unser_volume_label(DEVICE *dev, DEV_RECORD *rec);
+bool unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec);
/* From match_bsr.c */
-int match_bsr(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec,
- SESSION_LABEL *sesrec);
-int match_bsr_block(BSR *bsr, DEV_BLOCK *block);
-void position_bsr_block(BSR *bsr, DEV_BLOCK *block);
-BSR *find_next_bsr(BSR *root_bsr, DEVICE *dev);
-bool match_set_eof(BSR *bsr, DEV_RECORD *rec);
+int match_bsr(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec,
+ SESSION_LABEL *sesrec);
+int match_bsr_block(BSR *bsr, DEV_BLOCK *block);
+void position_bsr_block(BSR *bsr, DEV_BLOCK *block);
+BSR *find_next_bsr(BSR *root_bsr, DEVICE *dev);
+bool match_set_eof(BSR *bsr, DEV_RECORD *rec);
/* From mount.c */
-bool mount_next_write_volume(DCR *dcr, bool release);
-bool mount_next_read_volume(DCR *dcr);
-void release_volume(DCR *ddr);
-void mark_volume_in_error(DCR *dcr);
+bool mount_next_write_volume(DCR *dcr, bool release);
+bool mount_next_read_volume(DCR *dcr);
+void release_volume(DCR *ddr);
+void mark_volume_in_error(DCR *dcr);
/* From parse_bsr.c */
-BSR *parse_bsr(JCR *jcr, char *lf);
-void dump_bsr(BSR *bsr, bool recurse);
-void free_bsr(BSR *bsr);
+BSR *parse_bsr(JCR *jcr, char *lf);
+void dump_bsr(BSR *bsr, bool recurse);
+void free_bsr(BSR *bsr);
VOL_LIST *new_vol();
-int add_vol(JCR *jcr, VOL_LIST *vol);
-void free_vol_list(JCR *jcr);
-void create_vol_list(JCR *jcr);
+int add_vol(JCR *jcr, VOL_LIST *vol);
+void free_vol_list(JCR *jcr);
+void create_vol_list(JCR *jcr);
/* From record.c */
const char *FI_to_ascii(int fi);
const char *stream_to_ascii(int stream, int fi);
-bool write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
-bool can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
-bool read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec);
+bool write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
+bool can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
+bool read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec);
DEV_RECORD *new_record();
-void free_record(DEV_RECORD *rec);
-void empty_record(DEV_RECORD *rec);
+void free_record(DEV_RECORD *rec);
+void empty_record(DEV_RECORD *rec);
/* From read_record.c */
bool read_records(DCR *dcr,
bool mount_cb(DCR *dcr));
/* From spool.c */
-bool begin_data_spool (DCR *dcr);
-bool discard_data_spool (DCR *dcr);
-bool commit_data_spool (DCR *dcr);
-bool are_attributes_spooled (JCR *jcr);
-bool begin_attribute_spool (JCR *jcr);
-bool discard_attribute_spool (JCR *jcr);
-bool commit_attribute_spool (JCR *jcr);
-bool write_block_to_spool_file (DCR *dcr);
-void list_spool_stats (BSOCK *bs);
+bool begin_data_spool (DCR *dcr);
+bool discard_data_spool (DCR *dcr);
+bool commit_data_spool (DCR *dcr);
+bool are_attributes_spooled (JCR *jcr);
+bool begin_attribute_spool (JCR *jcr);
+bool discard_attribute_spool (JCR *jcr);
+bool commit_attribute_spool (JCR *jcr);
+bool write_block_to_spool_file (DCR *dcr);
+void list_spool_stats (BSOCK *bs);
/* */
#undef VERSION
-#define VERSION "1.37.6"
-#define BDATE "11 March 2005"
-#define LSMDATE "11Mar05"
+#define VERSION "1.37.7"
+#define BDATE "12 March 2005"
+#define LSMDATE "12Mar05"
/* Debug flags */
#undef DEBUG