From: Kern Sibbald Date: Sat, 12 Mar 2005 15:40:41 +0000 (+0000) Subject: - Implement IBM labels X-Git-Tag: Release-1.38.0~597 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=70e0ff8ca9898a2dde68b0d509bb728f59edeccd;p=bacula%2Fbacula - Implement IBM labels - Implement EOF and EOV labels at the end of a volume. - Fix a rather ugly problem with the PoolId not getting passed correctly. Now the DIR passes the Pool name and Media Type to the SD, who passes them back when requesting the next Volume. The DIR then looks up the correct PoolId. This takes more time, but always works, AND allows wild card Media Types (i.e. the SD can decide). - The DIR <==> SD protocol has changed. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@1885 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/kernstodo b/bacula/kernstodo index 8aa0c23488..4585e5ad2d 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -1,5 +1,5 @@ Kern's ToDo List - 07 March 2005 + 11 March 2005 Major development: Project Developer diff --git a/bacula/src/cats/protos.h b/bacula/src/cats/protos.h index 0022b75d18..2712ed76a6 100644 --- a/bacula/src/cats/protos.h +++ b/bacula/src/cats/protos.h @@ -34,8 +34,8 @@ /* 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); @@ -70,7 +70,7 @@ int db_find_next_volume(JCR *jcr, B_DB *mdb, int index, bool InChanger, MEDIA_DB 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); diff --git a/bacula/src/cats/sql_get.c b/bacula/src/cats/sql_get.c index c7fbea4b8b..da17f30695 100644 --- a/bacula/src/cats/sql_get.c +++ b/bacula/src/cats/sql_get.c @@ -1,8 +1,8 @@ /* * 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 * @@ -33,7 +33,7 @@ /* 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" @@ -65,7 +65,7 @@ extern void split_path_and_file(JCR *jcr, B_DB *mdb, const char *fname); * (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) { @@ -90,7 +90,7 @@ int db_get_file_attributes_record(JCR *jcr, B_DB *mdb, char *fname, JOB_DBR *jr, /* * Get a File record * Returns: 0 on failure - * 1 on success + * 1 on success * * DO NOT use Jmsg in this routine. * @@ -133,21 +133,21 @@ int db_get_file_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr, FILE_DBR *fdbr) 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 { @@ -159,7 +159,7 @@ int db_get_file_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr, FILE_DBR *fdbr) /* 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) */ @@ -177,20 +177,20 @@ static int db_get_filename_record(JCR *jcr, B_DB *mdb) 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); } @@ -203,7 +203,7 @@ static int db_get_filename_record(JCR *jcr, B_DB *mdb) /* 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) */ @@ -227,28 +227,28 @@ static int db_get_path_record(JCR *jcr, B_DB *mdb) 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); } @@ -263,7 +263,7 @@ static int db_get_path_record(JCR *jcr, B_DB *mdb) /* * 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) { @@ -281,18 +281,18 @@ 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]); @@ -317,10 +317,10 @@ int db_get_job_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr) /* * 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 */ @@ -346,22 +346,22 @@ int db_get_job_volume_names(JCR *jcr, B_DB *mdb, JobId_t JobId, POOLMEM **Volume 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 { @@ -374,8 +374,8 @@ int db_get_job_volume_names(JCR *jcr, B_DB *mdb, JobId_t JobId, POOLMEM **Volume /* * 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 */ @@ -393,7 +393,7 @@ int db_get_job_volume_parameters(JCR *jcr, B_DB *mdb, JobId_t JobId, VOL_PARAMS "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)) { @@ -401,29 +401,29 @@ int db_get_job_volume_parameters(JCR *jcr, B_DB *mdb, JobId_t JobId, VOL_PARAMS 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); } @@ -437,7 +437,7 @@ int db_get_job_volume_parameters(JCR *jcr, B_DB *mdb, JobId_t JobId, VOL_PARAMS * 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) { @@ -455,7 +455,7 @@ 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[]) { @@ -470,11 +470,11 @@ 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; @@ -492,7 +492,7 @@ int db_get_pool_ids(JCR *jcr, B_DB *mdb, int *num_ids, uint32_t *ids[]) * 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[]) { @@ -507,11 +507,11 @@ 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; @@ -530,61 +530,61 @@ int db_get_client_ids(JCR *jcr, B_DB *mdb, int *num_ids, uint32_t *ids[]) * 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")); } @@ -593,7 +593,7 @@ int db_get_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pdbr) Mmsg(mdb->errmsg, _("Pool record not found in Catalog.\n")); } db_unlock(mdb); - return stat; + return ok; } /* Get Client Record @@ -601,7 +601,7 @@ int db_get_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pdbr) * 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) { @@ -610,12 +610,12 @@ 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); @@ -625,21 +625,21 @@ int db_get_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cdbr) 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")); } @@ -655,7 +655,7 @@ int db_get_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cdbr) * 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) { @@ -674,24 +674,24 @@ 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 { @@ -707,7 +707,7 @@ int db_get_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr) * 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) { @@ -716,12 +716,12 @@ 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); @@ -730,19 +730,19 @@ int db_get_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr) 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 { @@ -757,7 +757,7 @@ int db_get_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr) * 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) { @@ -777,7 +777,7 @@ 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[]) { @@ -794,11 +794,11 @@ int db_get_media_ids(JCR *jcr, B_DB *mdb, uint32_t PoolId, int *num_ids, uint32_ 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; @@ -815,7 +815,7 @@ int db_get_media_ids(JCR *jcr, B_DB *mdb, uint32_t PoolId, int *num_ids, uint32_ /* 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) { @@ -830,15 +830,15 @@ 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," @@ -852,65 +852,65 @@ int db_get_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) 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; diff --git a/bacula/src/dird/catreq.c b/bacula/src/dird/catreq.c index 44d2683168..6baf7d7f50 100644 --- a/bacula/src/dird/catreq.c +++ b/bacula/src/dird/catreq.c @@ -41,7 +41,7 @@ */ /* 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" @@ -86,7 +86,7 @@ static int send_volume_info_to_storage_daemon(JCR *jcr, BSOCK *sd, MEDIA_DBR *mr 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; } @@ -95,9 +95,10 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg) 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)); @@ -106,7 +107,7 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg) /* * 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); @@ -118,9 +119,14 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *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 */ diff --git a/bacula/src/stored/Makefile.in b/bacula/src/stored/Makefile.in index bb3165c2da..9bd7b28159 100644 --- a/bacula/src/stored/Makefile.in +++ b/bacula/src/stored/Makefile.in @@ -22,7 +22,7 @@ SVRSRCS = stored.c ansi_label.c \ 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 \ @@ -31,7 +31,7 @@ SVROBJS = stored.o ansi_label.o \ 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 \ @@ -39,35 +39,35 @@ SVROBJS = stored.o ansi_label.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 diff --git a/bacula/src/stored/acquire.c b/bacula/src/stored/acquire.c index e14ed0f29c..f8c9e1679d 100644 --- a/bacula/src/stored/acquire.c +++ b/bacula/src/stored/acquire.c @@ -564,6 +564,7 @@ bool release_device(DCR *dcr) { 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"); @@ -600,6 +601,8 @@ bool release_device(DCR *dcr) /* 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 */ diff --git a/bacula/src/stored/ansi_label.c b/bacula/src/stored/ansi_label.c index 85fb30538d..0257a43500 100644 --- a/bacula/src/stored/ansi_label.c +++ b/bacula/src/stored/ansi_label.c @@ -32,6 +32,10 @@ #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); @@ -58,13 +62,14 @@ int read_ansi_ibm_label(DCR *dcr) 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; } @@ -79,7 +84,7 @@ int read_ansi_ibm_label(DCR *dcr) 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); @@ -89,7 +94,7 @@ int read_ansi_ibm_label(DCR *dcr) 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 { @@ -98,13 +103,25 @@ int read_ansi_ibm_label(DCR *dcr) } 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 != '*') { @@ -115,58 +132,128 @@ int read_ansi_ibm_label(DCR *dcr) *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; @@ -191,29 +278,37 @@ bool write_ansi_ibm_label(DCR *dcr, const char *VolName) 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. */ @@ -224,6 +319,9 @@ bool write_ansi_ibm_label(DCR *dcr, const char *VolName) 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; @@ -231,11 +329,18 @@ bool write_ansi_ibm_label(DCR *dcr, const char *VolName) 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; @@ -247,6 +352,16 @@ bool write_ansi_ibm_label(DCR *dcr, const char *VolName) 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")); @@ -280,7 +395,10 @@ static bool same_label_names(char *bacula_name, char *ansi_name) return false; } - +/* + * ANSI date + * ' 'YYDDD + */ static char *ansi_date(time_t td, char *buf) { struct tm *tm; diff --git a/bacula/src/stored/askdir.c b/bacula/src/stored/askdir.c index 1166452d4e..bc361fbde2 100644 --- a/bacula/src/stored/askdir.c +++ b/bacula/src/stored/askdir.c @@ -30,7 +30,7 @@ #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" @@ -232,7 +232,6 @@ bool dir_find_next_appendable_volume(DCR *dcr) { JCR *jcr = dcr->jcr; BSOCK *dir = jcr->dir_bsock; - char ed1[50]; JCR *njcr; Dmsg0(200, "dir_find_next_appendable_volume\n"); @@ -242,7 +241,11 @@ bool dir_find_next_appendable_volume(DCR *dcr) * 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); @@ -401,7 +404,7 @@ bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) 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); } diff --git a/bacula/src/stored/block.c b/bacula/src/stored/block.c index e2c5b69990..14d29d3bf5 100644 --- a/bacula/src/stored/block.c +++ b/bacula/src/stored/block.c @@ -688,6 +688,10 @@ static bool terminate_writing_volume(DCR *dcr) /* 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 */ diff --git a/bacula/src/stored/dev.c b/bacula/src/stored/dev.c index a9f826ad87..5d8d4c6a8b 100644 --- a/bacula/src/stored/dev.c +++ b/bacula/src/stored/dev.c @@ -526,27 +526,27 @@ void DEVICE::set_eot() /* * 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); @@ -554,13 +554,13 @@ eod_dev(DEVICE *dev) 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)) { @@ -568,7 +568,7 @@ eod_dev(DEVICE *dev) /* 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; @@ -589,14 +589,14 @@ eod_dev(DEVICE *dev) 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)) { @@ -604,12 +604,11 @@ eod_dev(DEVICE *dev) 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 { @@ -618,7 +617,7 @@ eod_dev(DEVICE *dev) * 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 @@ -628,7 +627,7 @@ eod_dev(DEVICE *dev) 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 @@ -642,8 +641,7 @@ eod_dev(DEVICE *dev) dev->set_eof(); dev->file = mt_stat.mt_fileno; } - stat = 0; - break; /* we are not progressing, bail out */ + return false; } } } @@ -655,7 +653,7 @@ eod_dev(DEVICE *dev) 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); @@ -665,10 +663,17 @@ eod_dev(DEVICE *dev) } } 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; } /* diff --git a/bacula/src/stored/ebcdic.c b/bacula/src/stored/ebcdic.c index faa8c8ba48..d127e838fe 100644 --- a/bacula/src/stored/ebcdic.c +++ b/bacula/src/stored/ebcdic.c @@ -144,7 +144,7 @@ static char to_ebcdic_table[256] = { /* * 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++]; @@ -155,9 +155,9 @@ asci_to_ebcdic(char *dst, char *src, int count) /* * 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++]; } } diff --git a/bacula/src/stored/label.c b/bacula/src/stored/label.c index 907ee187b5..fa5dafffb9 100644 --- a/bacula/src/stored/label.c +++ b/bacula/src/stored/label.c @@ -392,7 +392,7 @@ bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, const char *Po 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; } @@ -478,7 +478,7 @@ bool rewrite_volume_label(DCR *dcr, bool recycle) 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; } diff --git a/bacula/src/stored/protos.h b/bacula/src/stored/protos.h index 6ec0b722ea..73b7fb96e1 100644 --- a/bacula/src/stored/protos.h +++ b/bacula/src/stored/protos.h @@ -28,183 +28,186 @@ 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, @@ -212,12 +215,12 @@ 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); diff --git a/bacula/src/version.h b/bacula/src/version.h index a6797f12ad..254b637364 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -1,8 +1,8 @@ /* */ #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