From 669660ef3da87f94461c1410e892fae02bd50e22 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Sat, 7 Dec 2002 17:05:34 +0000 Subject: [PATCH] restore + SQL editing cleanups git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@233 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/kernstodo | 8 +- bacula/src/cats/bdb_get.c | 6 + bacula/src/cats/protos.h | 2 + bacula/src/cats/sql_delete.c | 2 +- bacula/src/cats/sql_find.c | 32 ++-- bacula/src/cats/sql_get.c | 161 +++++++++++++----- bacula/src/dird/sql_cmds.c | 23 ++- bacula/src/dird/ua.h | 52 +++--- bacula/src/dird/ua_prune.c | 6 +- bacula/src/dird/ua_purge.c | 6 +- bacula/src/dird/ua_restore.c | 96 ++++++----- bacula/src/dird/ua_select.c | 94 ++++++++++- bacula/src/lib/Makefile.in | 4 +- bacula/src/lib/edit.c | 279 ++++++++++++++++++++++++++++++++ bacula/src/lib/protos.h | 188 ++++++++++----------- bacula/src/lib/util.c | 208 ------------------------ bacula/src/stored/acquire.c | 2 +- bacula/src/stored/block.c | 1 + bacula/src/stored/block.h | 1 + bacula/src/stored/bsr.h | 65 ++++---- bacula/src/stored/match_bsr.c | 13 +- bacula/src/stored/parse_bsr.c | 48 ++++++ bacula/src/stored/read_record.c | 2 - bacula/src/stored/record.c | 7 +- bacula/src/stored/record.h | 1 + bacula/src/tools/Makefile.in | 2 +- bacula/src/version.h | 4 +- 27 files changed, 827 insertions(+), 486 deletions(-) create mode 100644 bacula/src/lib/edit.c diff --git a/bacula/kernstodo b/bacula/kernstodo index 36180a4071..3dab6db373 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -7,10 +7,10 @@ Documentation to do: (a little bit at a time) - Document query file format. Testing to do: (painful) -- that restore options work in FD. +- that restore options work in FD (mostly done). - that console command line options work - blocksize recognition code. -- Test new BSR code +- Test new BSR code (mostly done). For 1.28 release: @@ -21,7 +21,6 @@ For 1.28 release: - Get rid of bscan.c:534 error message (one time only). - Print some statistics when get EOF on device in bscan -- feedback to let user know it is working. -- Add code to put VolFile in bsr for restore command. - Add code to reject whole blocks if not wanted on restore. - Add watchdog timeout for child processes start_child_timer() end_child_timer(); @@ -621,3 +620,6 @@ Done: (see kernsdone for more) - Make BSR accept count (total files to be restored). - Add code to fast seek to proper place on tape/file when doing Restore. - Replace popen() and pclose() -- fail safe and timeout, no SIG dep. +- Add code to put VolFile in bsr for restore command. +- Volumes can be listed multiple times in Restore volume list. + diff --git a/bacula/src/cats/bdb_get.c b/bacula/src/cats/bdb_get.c index 0b96eb5e12..60dc10c5c0 100644 --- a/bacula/src/cats/bdb_get.c +++ b/bacula/src/cats/bdb_get.c @@ -497,5 +497,11 @@ int db_get_file_attributes_record(B_DB *mdb, char *fname, FILE_DBR *fdbr) int db_get_job_volume_parameters(B_DB *mdb, uint32_t JobId, VOL_PARAMS **VolParams) { return 0; } +int db_get_client_ids(B_DB *mdb, int *num_ids, uint32_t *ids[]) +{ return 0; } + + +int db_get_client_record(B_DB *mdb, CLIENT_DBR *cdbr) +{ return 0; } #endif /* HAVE_BACULA_DB */ diff --git a/bacula/src/cats/protos.h b/bacula/src/cats/protos.h index a6a19b3828..0d38ed6563 100644 --- a/bacula/src/cats/protos.h +++ b/bacula/src/cats/protos.h @@ -73,8 +73,10 @@ int db_get_media_record(B_DB *mdb, MEDIA_DBR *mr); int db_get_num_media_records(B_DB *mdb); int db_get_num_pool_records(B_DB *mdb); int db_get_pool_ids(B_DB *mdb, int *num_ids, uint32_t **ids); +int db_get_client_ids(B_DB *mdb, int *num_ids, uint32_t **ids); int db_get_media_ids(B_DB *mdb, int *num_ids, uint32_t **ids); int db_get_job_volume_parameters(B_DB *mdb, uint32_t JobId, VOL_PARAMS **VolParams); +int db_get_client_record(B_DB *mdb, CLIENT_DBR *cdbr); /* list.c */ diff --git a/bacula/src/cats/sql_delete.c b/bacula/src/cats/sql_delete.c index 74076eb651..e2a8ee658f 100644 --- a/bacula/src/cats/sql_delete.c +++ b/bacula/src/cats/sql_delete.c @@ -141,7 +141,7 @@ static int delete_handler(void *ctx, int num_fields, char **row) del->JobId = (JobId_t *)brealloc(del->JobId, sizeof(JobId_t) * del->max_ids); } - del->JobId[del->num_ids++] = (JobId_t)strtod(row[0], NULL); + del->JobId[del->num_ids++] = (JobId_t)str_to_int64(row[0]); return 0; } diff --git a/bacula/src/cats/sql_find.c b/bacula/src/cats/sql_find.c index 89901505e0..b0dc4277f4 100644 --- a/bacula/src/cats/sql_find.c +++ b/bacula/src/cats/sql_find.c @@ -235,23 +235,23 @@ ORDER BY MediaId", mr->PoolId, mr->MediaType, mr->VolStatus); } /* Return fields in Media Record */ - mr->MediaId = atoi(row[0]); + mr->MediaId = str_to_int64(row[0]); bstrncpy(mr->VolumeName, row[1], sizeof(mr->VolumeName)); - mr->VolJobs = atoi(row[2]); - mr->VolFiles = atoi(row[3]); - mr->VolBlocks = atoi(row[4]); - mr->VolBytes = (uint64_t)strtod(row[5], NULL); - mr->VolMounts = atoi(row[6]); - mr->VolErrors = atoi(row[7]); - mr->VolWrites = atoi(row[8]); - mr->MaxVolBytes = (uint64_t)strtod(row[9], NULL); - mr->VolCapacityBytes = (uint64_t)strtod(row[10], NULL); - mr->VolRetention = (utime_t)strtod(row[11], NULL); - mr->VolUseDuration = (utime_t)strtod(row[12], NULL); - mr->MaxVolJobs = atoi(row[13]); - mr->MaxVolFiles = atoi(row[14]); - mr->Recycle = atoi(row[15]); - mr->Slot = atoi(row[16]); + mr->VolJobs = str_to_int64(row[2]); + mr->VolFiles = str_to_int64(row[3]); + mr->VolBlocks = str_to_int64(row[4]); + mr->VolBytes = str_to_uint64(row[5]); + mr->VolMounts = str_to_int64(row[6]); + mr->VolErrors = str_to_int64(row[7]); + mr->VolWrites = str_to_int64(row[8]); + mr->MaxVolBytes = str_to_uint64(row[9]); + mr->VolCapacityBytes = str_to_uint64(row[10]); + mr->VolRetention = str_to_uint64(row[11]); + mr->VolUseDuration = str_to_uint64(row[12]); + mr->MaxVolJobs = str_to_int64(row[13]); + mr->MaxVolFiles = str_to_int64(row[14]); + mr->Recycle = str_to_int64(row[15]); + mr->Slot = str_to_int64(row[16]); bstrncpy(mr->cFirstWritten, row[17]!=NULL?row[17]:"", sizeof(mr->cFirstWritten)); sql_free_result(mdb); diff --git a/bacula/src/cats/sql_get.c b/bacula/src/cats/sql_get.c index 2bd972912a..0e054c5e16 100644 --- a/bacula/src/cats/sql_get.c +++ b/bacula/src/cats/sql_get.c @@ -185,7 +185,7 @@ File.FilenameId=%u", fdbr->JobId, fdbr->PathId, fdbr->FilenameId); if ((row = sql_fetch_row(mdb)) == NULL) { Mmsg1(&mdb->errmsg, _("Error fetching row: %s\n"), sql_strerror(mdb)); } else { - fdbr->FileId = (FileId_t)strtod(row[0], NULL); + fdbr->FileId = (FileId_t)str_to_int64(row[0]); strncpy(fdbr->LStat, row[1], sizeof(fdbr->LStat)); fdbr->LStat[sizeof(fdbr->LStat)] = 0; strncpy(fdbr->MD5, row[2], sizeof(fdbr->MD5)); @@ -342,14 +342,14 @@ FROM Job WHERE JobId=%u", jr->JobId); return 0; /* failed */ } - jr->VolSessionId = atol(row[0]); - jr->VolSessionTime = atol(row[1]); + jr->VolSessionId = str_to_uint64(row[0]); + jr->VolSessionTime = str_to_uint64(row[1]); jr->PoolId = atoi(row[2]); bstrncpy(jr->cStartTime, row[3]!=NULL?row[3]:"", sizeof(jr->cStartTime)); bstrncpy(jr->cEndTime, row[4]!=NULL?row[4]:"", sizeof(jr->cEndTime)); jr->JobFiles = atol(row[5]); - jr->JobBytes = (uint64_t)strtod(row[6], NULL); - jr->JobTDate = (utime_t)strtod(row[7], NULL); + jr->JobBytes = str_to_int64(row[6]); + jr->JobTDate = str_to_int64(row[7]); bstrncpy(jr->Job, row[8]!=NULL?row[8]:"", sizeof(jr->Job)); jr->JobStatus = (int)*row[9]; jr->Type = (int)*row[10]; @@ -520,6 +520,44 @@ int db_get_pool_ids(B_DB *mdb, int *num_ids, uint32_t *ids[]) return stat; } +/* + * This function returns a list of all the Client record ids. + * The caller must free ids if non-NULL. + * + * Returns 0: on failure + * 1: on success + */ +int db_get_client_ids(B_DB *mdb, int *num_ids, uint32_t *ids[]) +{ + SQL_ROW row; + int stat = 0; + int i = 0; + uint32_t *id; + + db_lock(mdb); + *ids = NULL; + Mmsg(&mdb->cmd, "SELECT ClientId FROM Client"); + if (QUERY_DB(mdb, mdb->cmd)) { + *num_ids = sql_num_rows(mdb); + if (*num_ids > 0) { + id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t)); + while ((row = sql_fetch_row(mdb)) != NULL) { + id[i++] = (uint32_t)atoi(row[0]); + } + *ids = id; + } + sql_free_result(mdb); + stat = 1; + } else { + Mmsg(&mdb->errmsg, _("Client id select failed: ERR=%s\n"), sql_strerror(mdb)); + Jmsg(mdb->jcr, M_ERROR, 0, "%s", mdb->errmsg); + stat = 0; + } + db_unlock(mdb); + return stat; +} + + /* Get Pool Record * If the PoolId is non-zero, we get its record, @@ -538,7 +576,7 @@ int db_get_pool_record(B_DB *mdb, POOL_DBR *pdbr) Mmsg(&mdb->cmd, "SELECT PoolId,Name,NumVols,MaxVols,UseOnce,UseCatalog,AcceptAnyVolume,\ AutoPrune,Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,\ -MaxVolBytes,PoolType,LabelFormat FROM Pool WHERE Pool.PoolId=%d", pdbr->PoolId); +MaxVolBytes,PoolType,LabelFormat FROM Pool WHERE Pool.PoolId=%u", pdbr->PoolId); } else { /* find by name */ Mmsg(&mdb->cmd, "SELECT PoolId,Name,NumVols,MaxVols,UseOnce,UseCatalog,AcceptAnyVolume,\ @@ -558,20 +596,20 @@ MaxVolBytes,PoolType,LabelFormat FROM Pool WHERE Pool.Name='%s'", pdbr->Name); Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb)); Jmsg(mdb->jcr, M_ERROR, 0, "%s", mdb->errmsg); } else { - pdbr->PoolId = atoi(row[0]); + pdbr->PoolId = str_to_int64(row[0]); bstrncpy(pdbr->Name, row[1]!=NULL?row[1]:"", sizeof(pdbr->Name)); - pdbr->NumVols = atoi(row[2]); - pdbr->MaxVols = atoi(row[3]); - pdbr->UseOnce = atoi(row[4]); - pdbr->UseCatalog = atoi(row[5]); - pdbr->AcceptAnyVolume = atoi(row[6]); - pdbr->AutoPrune = atoi(row[7]); - pdbr->Recycle = atoi(row[8]); - pdbr->VolRetention = (utime_t)strtod(row[9], NULL); - pdbr->VolUseDuration = (utime_t)strtod(row[10], NULL); - pdbr->MaxVolJobs = atoi(row[11]); - pdbr->MaxVolFiles = atoi(row[12]); - pdbr->MaxVolBytes = (uint64_t)strtod(row[13], NULL); + pdbr->NumVols = str_to_int64(row[2]); + pdbr->MaxVols = str_to_int64(row[3]); + pdbr->UseOnce = str_to_int64(row[4]); + pdbr->UseCatalog = str_to_int64(row[5]); + pdbr->AcceptAnyVolume = str_to_int64(row[6]); + pdbr->AutoPrune = str_to_int64(row[7]); + pdbr->Recycle = str_to_int64(row[8]); + pdbr->VolRetention = str_to_int64(row[9]); + pdbr->VolUseDuration = str_to_int64(row[10]); + pdbr->MaxVolJobs = str_to_int64(row[11]); + pdbr->MaxVolFiles = str_to_int64(row[12]); + pdbr->MaxVolBytes = str_to_uint64(row[13]); bstrncpy(pdbr->PoolType, row[13]!=NULL?row[14]:"", sizeof(pdbr->PoolType)); bstrncpy(pdbr->LabelFormat, row[14]!=NULL?row[15]:"", sizeof(pdbr->LabelFormat)); stat = pdbr->PoolId; @@ -583,6 +621,57 @@ MaxVolBytes,PoolType,LabelFormat FROM Pool WHERE Pool.Name='%s'", pdbr->Name); return stat; } +/* Get Client Record + * If the ClientId is non-zero, we get its record, + * otherwise, we search on the Client Name + * + * Returns: 0 on failure + * 1 on success + */ +int db_get_client_record(B_DB *mdb, CLIENT_DBR *cdbr) +{ + SQL_ROW row; + int stat = 0; + + db_lock(mdb); + if (cdbr->ClientId != 0) { /* find by id */ + Mmsg(&mdb->cmd, +"SELECT ClientId,Name,Uname,AutoPrune,FileRetention,JobRetention " +"FROM Client WHERE Client.ClientId=%u", cdbr->ClientId); + } else { /* find by name */ + Mmsg(&mdb->cmd, +"SELECT ClientId,Name,Uname,AutoPrune,FileRetention,JobRetention " +"FROM Client WHERE Client.Name='%s'", cdbr->Name); + } + + if (QUERY_DB(mdb, mdb->cmd)) { + mdb->num_rows = sql_num_rows(mdb); + if (mdb->num_rows > 1) { + char ed1[30]; + Mmsg1(&mdb->errmsg, _("More than one Client!: %s\n"), + edit_uint64(mdb->num_rows, ed1)); + Jmsg(mdb->jcr, M_ERROR, 0, "%s", mdb->errmsg); + } else if (mdb->num_rows == 1) { + if ((row = sql_fetch_row(mdb)) == NULL) { + Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb)); + Jmsg(mdb->jcr, M_ERROR, 0, "%s", mdb->errmsg); + } else { + cdbr->ClientId = str_to_int64(row[0]); + bstrncpy(cdbr->Name, row[1]!=NULL?row[1]:"", sizeof(cdbr->Name)); + bstrncpy(cdbr->Uname, row[2]!=NULL?row[1]:"", sizeof(cdbr->Uname)); + cdbr->AutoPrune = str_to_int64(row[3]); + cdbr->FileRetention = str_to_int64(row[4]); + cdbr->JobRetention = str_to_int64(row[5]); + stat = 1; + } + } + sql_free_result(mdb); + } + db_unlock(mdb); + return stat; +} + + /* Get FileSet Record * If the FileSetId is non-zero, we get its record, * otherwise, we search on the name @@ -729,26 +818,26 @@ FROM Media WHERE VolumeName='%s'", mr->VolumeName); Jmsg(mdb->jcr, M_ERROR, 0, "%s", mdb->errmsg); } else { /* return values */ - mr->MediaId = atoi(row[0]); + mr->MediaId = str_to_int64(row[0]); bstrncpy(mr->VolumeName, row[1]!=NULL?row[1]:"", sizeof(mr->VolumeName)); - mr->VolJobs = atoi(row[2]); - mr->VolFiles = atoi(row[3]); - mr->VolBlocks = atoi(row[4]); - mr->VolBytes = (uint64_t)strtod(row[5], NULL); - mr->VolMounts = atoi(row[6]); - mr->VolErrors = atoi(row[7]); - mr->VolWrites = atoi(row[8]); - mr->MaxVolBytes = (uint64_t)strtod(row[9], NULL); - mr->VolCapacityBytes = (uint64_t)strtod(row[10], NULL); + mr->VolJobs = str_to_int64(row[2]); + mr->VolFiles = str_to_int64(row[3]); + mr->VolBlocks = str_to_int64(row[4]); + mr->VolBytes = str_to_uint64(row[5]); + mr->VolMounts = str_to_int64(row[6]); + mr->VolErrors = str_to_int64(row[7]); + mr->VolWrites = str_to_int64(row[8]); + mr->MaxVolBytes = str_to_uint64(row[9]); + mr->VolCapacityBytes = str_to_uint64(row[10]); bstrncpy(mr->MediaType, row[11]!=NULL?row[11]:"", sizeof(mr->MediaType)); bstrncpy(mr->VolStatus, row[12]!=NULL?row[12]:"", sizeof(mr->VolStatus)); - mr->PoolId = atoi(row[13]); - mr->VolRetention = (utime_t)strtod(row[14], NULL); - mr->VolUseDuration = (utime_t)strtod(row[15], NULL); - mr->MaxVolJobs = atoi(row[16]); - mr->MaxVolFiles = atoi(row[17]); - mr->Recycle = atoi(row[18]); - mr->Slot = atoi(row[19]); + mr->PoolId = str_to_int64(row[13]); + mr->VolRetention = str_to_uint64(row[14]); + mr->VolUseDuration = str_to_uint64(row[15]); + mr->MaxVolJobs = str_to_int64(row[16]); + mr->MaxVolFiles = str_to_int64(row[17]); + mr->Recycle = str_to_int64(row[18]); + mr->Slot = str_to_int64(row[19]); bstrncpy(mr->cFirstWritten, row[20]!=NULL?row[20]:"", sizeof(mr->cFirstWritten)); stat = mr->MediaId; } diff --git a/bacula/src/dird/sql_cmds.c b/bacula/src/dird/sql_cmds.c index 5c8b006871..c1bf44d086 100644 --- a/bacula/src/dird/sql_cmds.c +++ b/bacula/src/dird/sql_cmds.c @@ -45,7 +45,7 @@ char *sel_JobMedia = "SELECT JobId FROM JobMedia WHERE MediaId=%u"; char *select_job = "SELECT JobId from Job " "WHERE JobTDate < %s " - "AND ClientId=%d " + "AND ClientId=%u " "AND PurgedFiles=0"; /* Delete temp tables and indexes */ @@ -70,7 +70,7 @@ char *insert_delcand = "INSERT INTO DelCandidates " "SELECT JobId, PurgedFiles, FileSetId FROM Job " "WHERE JobTDate < %s " - "AND ClientId=%d"; + "AND ClientId=%u"; /* Select files from the DelCandidates table that have a * more recent backup -- i.e. are not the only backup. @@ -80,7 +80,7 @@ char *select_backup_del = "SELECT DelCandidates.JobId " "FROM Job,DelCandidates " "WHERE Job.JobTDate >= %s " - "AND Job.ClientId=%d " + "AND Job.ClientId=%u " "AND Job.JobType='B' " "AND Job.Level='F' " "AND Job.JobStatus='T' " @@ -94,7 +94,7 @@ char *select_verify_del = "SELECT DelCandidates.JobId " "FROM Job,DelCandidates " "WHERE Job.JobTDate >= %s " - "AND Job.ClientId=%d " + "AND Job.ClientId=%u " "AND Job.JobType='V' " "AND Job.Level='V' " "AND Job.JobStatus='T' " @@ -108,7 +108,7 @@ char *select_restore_del = "SELECT DelCandidates.JobId " "FROM Job,DelCandidates " "WHERE Job.JobTDate >= %s " - "AND Job.ClientId=%d " + "AND Job.ClientId=%u " "AND Job.JobType='R'"; @@ -169,13 +169,12 @@ char *uar_create_temp = char *uar_create_temp1 = "CREATE TABLE temp1 (JobId INTEGER UNSIGNED NOT NULL," - "JobTDate BIGINT UNSIGNED," - "ClientId INTEGER UNSIGNED)"; + "JobTDate BIGINT UNSIGNED)"; char *uar_last_full = - "INSERT INTO temp1 SELECT Job.JobId,JobTdate,Job.ClientId " - "FROM Client,Job,JobMedia,Media WHERE Client.Name='%s' " - "AND Client.ClientId=Job.ClientId " + "INSERT INTO temp1 SELECT Job.JobId,JobTdate " + "FROM Client,Job,JobMedia,Media WHERE Client.ClientId=%u " + "AND Job.ClientId=%u " "AND Level='F' AND JobStatus='T' " "AND JobMedia.JobId=Job.JobId " "AND JobMedia.MediaId=Media.MediaId " @@ -196,7 +195,7 @@ char *uar_inc = "Job.Level,Job.JobFiles,Job.StartTime,Media.VolumeName,JobMedia.StartFile," "Job.VolSessionId,Job.VolSessionTime " "FROM Job,JobMedia,Media " - "WHERE Job.JobTDate>%d AND Job.ClientId=%u " + "WHERE Job.JobTDate>%s AND Job.ClientId=%u " "AND JobMedia.JobId=Job.JobId " "AND JobMedia.MediaId=Media.MediaId " "AND Job.Level='I' AND JobStatus='T' " @@ -215,7 +214,7 @@ char *uar_sel_all_temp1 = "SELECT * FROM temp1"; char *uar_sel_fileset = "SELECT FileSet.FileSetId,FileSet.FileSet,FileSet.MD5 FROM Job," "Client,FileSet WHERE Job.FileSetId=FileSet.FileSetId " - "AND Job.ClientId=Client.ClientId AND Client.Name='%s' " + "AND Job.ClientId=%u AND Client.ClientId=%u " "GROUP BY FileSet.FileSetId"; /* Find MediaType used by this Job */ diff --git a/bacula/src/dird/ua.h b/bacula/src/dird/ua.h index 1d2b2938c3..98c53dfcea 100644 --- a/bacula/src/dird/ua.h +++ b/bacula/src/dird/ua.h @@ -33,19 +33,19 @@ typedef struct s_ua_context { JCR *jcr; B_DB *db; CAT *catalog; - POOLMEM *cmd; /* return command/name buffer */ - POOLMEM *args; /* command line arguments */ - char *argk[MAX_ARGS]; /* argument keywords */ - char *argv[MAX_ARGS]; /* argument values */ - int argc; /* number of arguments */ - char **prompt; /* list of prompts */ - int max_prompts; /* max size of list */ - int num_prompts; /* current number in list */ - int auto_display_messages; /* if set, display messages */ + POOLMEM *cmd; /* return command/name buffer */ + POOLMEM *args; /* command line arguments */ + char *argk[MAX_ARGS]; /* argument keywords */ + char *argv[MAX_ARGS]; /* argument values */ + int argc; /* number of arguments */ + char **prompt; /* list of prompts */ + int max_prompts; /* max size of list */ + int num_prompts; /* current number in list */ + int auto_display_messages; /* if set, display messages */ int user_notified_msg_pending; /* set when user notified */ - int automount; /* if set, mount after label */ - int quit; /* if set, quit */ - int verbose; /* set for normal UA verbosity */ + int automount; /* if set, mount after label */ + int quit; /* if set, quit */ + int verbose; /* set for normal UA verbosity */ } UAContext; /* ua_cmds.c */ @@ -67,24 +67,26 @@ void prtit(void *ctx, char *msg); void bsendmsg(void *sock, char *fmt, ...); /* ua_select.c */ -STORE *select_storage_resource(UAContext *ua); -JOB *select_job_resource(UAContext *ua); -JOB *select_restore_job_resource(UAContext *ua); -CLIENT *select_client_resource(UAContext *ua); +STORE *select_storage_resource(UAContext *ua); +JOB *select_job_resource(UAContext *ua); +JOB *select_restore_job_resource(UAContext *ua); +CLIENT *select_client_resource(UAContext *ua); FILESET *select_fileset_resource(UAContext *ua); -int select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr); -int select_pool_dbr(UAContext *ua, POOL_DBR *pr); +int select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr); +int select_pool_dbr(UAContext *ua, POOL_DBR *pr); +int select_client_dbr(UAContext *ua, CLIENT_DBR *cr); -void start_prompt(UAContext *ua, char *msg); -void add_prompt(UAContext *ua, char *prompt); -int do_prompt(UAContext *ua, char *msg, char *prompt, int max_prompt); -CAT *get_catalog_resource(UAContext *ua); +void start_prompt(UAContext *ua, char *msg); +void add_prompt(UAContext *ua, char *prompt); +int do_prompt(UAContext *ua, char *msg, char *prompt, int max_prompt); +CAT *get_catalog_resource(UAContext *ua); STORE *get_storage_resource(UAContext *ua, char *cmd); -int get_media_type(UAContext *ua, char *MediaType, int max_media); -int get_pool_dbr(UAContext *ua, POOL_DBR *pr); +int get_media_type(UAContext *ua, char *MediaType, int max_media); +int get_pool_dbr(UAContext *ua, POOL_DBR *pr); +int get_client_dbr(UAContext *ua, CLIENT_DBR *cr); POOL *get_pool_resource(UAContext *ua); CLIENT *get_client_resource(UAContext *ua); -int get_job_dbr(UAContext *ua, JOB_DBR *jr); +int get_job_dbr(UAContext *ua, JOB_DBR *jr); int find_arg_keyword(UAContext *ua, char **list); int do_keyword_prompt(UAContext *ua, char *msg, char **list); diff --git a/bacula/src/dird/ua_prune.c b/bacula/src/dird/ua_prune.c index 52a336fa86..994ae3ded8 100644 --- a/bacula/src/dird/ua_prune.c +++ b/bacula/src/dird/ua_prune.c @@ -131,8 +131,8 @@ static int job_delete_handler(void *ctx, int num_fields, char **row) del->JobId = (JobId_t *)brealloc(del->JobId, sizeof(JobId_t) * del->max_ids); del->PurgedFiles = (char *)brealloc(del->PurgedFiles, del->max_ids); } - del->JobId[del->num_ids] = (JobId_t)strtod(row[0], NULL); - del->PurgedFiles[del->num_ids++] = (char)atoi(row[0]); + del->JobId[del->num_ids] = (JobId_t)str_to_int64(row[0]); + del->PurgedFiles[del->num_ids++] = (char)str_to_int64(row[0]); return 0; } @@ -148,7 +148,7 @@ static int file_delete_handler(void *ctx, int num_fields, char **row) del->JobId = (JobId_t *)brealloc(del->JobId, sizeof(JobId_t) * del->max_ids); } - del->JobId[del->num_ids++] = (JobId_t)strtod(row[0], NULL); + del->JobId[del->num_ids++] = (JobId_t)str_to_int64(row[0]); return 0; } diff --git a/bacula/src/dird/ua_purge.c b/bacula/src/dird/ua_purge.c index e45b89d334..970872ca50 100644 --- a/bacula/src/dird/ua_purge.c +++ b/bacula/src/dird/ua_purge.c @@ -132,8 +132,8 @@ static int job_delete_handler(void *ctx, int num_fields, char **row) del->JobId = (JobId_t *)brealloc(del->JobId, sizeof(JobId_t) * del->max_ids); del->PurgedFiles = (char *)brealloc(del->PurgedFiles, del->max_ids); } - del->JobId[del->num_ids] = (JobId_t)strtod(row[0], NULL); - del->PurgedFiles[del->num_ids++] = (char)atoi(row[0]); + del->JobId[del->num_ids] = (JobId_t)str_to_int64(row[0]); + del->PurgedFiles[del->num_ids++] = (char)str_to_int64(row[0]); return 0; } @@ -149,7 +149,7 @@ static int file_delete_handler(void *ctx, int num_fields, char **row) del->JobId = (JobId_t *)brealloc(del->JobId, sizeof(JobId_t) * del->max_ids); } - del->JobId[del->num_ids++] = (JobId_t)strtod(row[0], NULL); + del->JobId[del->num_ids++] = (JobId_t)str_to_int64(row[0]); return 0; } diff --git a/bacula/src/dird/ua_restore.c b/bacula/src/dird/ua_restore.c index c85a4aa2ce..2898990345 100644 --- a/bacula/src/dird/ua_restore.c +++ b/bacula/src/dird/ua_restore.c @@ -59,10 +59,9 @@ typedef struct s_tree_ctx { /* Main structure for obtaining JobIds */ typedef struct s_jobids { utime_t JobTDate; - uint32_t ClientId; uint32_t TotalFiles; + char ClientName[MAX_NAME_LENGTH]; char JobIds[200]; - CLIENT *client; STORE *store; } JobIds; @@ -80,11 +79,8 @@ typedef struct s_rbsr { uint32_t JobId; /* JobId this bsr */ uint32_t VolSessionId; uint32_t VolSessionTime; - uint32_t StartFile; - uint32_t EndFile; - uint32_t StartBlock; - uint32_t EndBlock; - char *VolumeName; /* Volume name */ + int VolCount; /* Volume parameter count */ + VOL_PARAMS *VolParams; /* Volume, start/end file/blocks */ RBSR_FINDEX *fi; /* File indexes this JobId */ } RBSR; @@ -255,10 +251,10 @@ int restorecmd(UAContext *ua, char *cmd) return 0; } - if (ji.client) { + if (ji.ClientName[0]) { Mmsg(&ua->cmd, "run job=\"%s\" client=\"%s\" storage=\"%s\" bootstrap=\"%s/restore.bsr\"", - job->hdr.name, ji.client->hdr.name, ji.store?ji.store->hdr.name:"", + job->hdr.name, ji.ClientName, ji.store?ji.store->hdr.name:"", working_directory); } else { Mmsg(&ua->cmd, @@ -284,8 +280,9 @@ int restorecmd(UAContext *ua, char *cmd) static int user_select_jobids(UAContext *ua, JobIds *ji) { char fileset_name[MAX_NAME_LENGTH]; - char *p; + char *p, ed1[50]; FILESET_DBR fsr; + CLIENT_DBR cr; JobId_t JobId; JOB_DBR jr; POOLMEM *query; @@ -351,16 +348,21 @@ static int user_select_jobids(UAContext *ua, JobIds *ji) bsendmsg(ua, "%s\n", db_strerror(ua->db)); } /* - * Select Client + * Select Client from the Catalog */ - if (!(ji->client = get_client_resource(ua))) { + memset(&cr, 0, sizeof(cr)); + if (!get_client_dbr(ua, &cr)) { + free_pool_memory(query); + db_sql_query(ua->db, uar_del_temp, NULL, NULL); + db_sql_query(ua->db, uar_del_temp1, NULL, NULL); return 0; } + bstrncpy(ji->ClientName, cr.Name, sizeof(ji->ClientName)); /* * Select FileSet */ - Mmsg(&query, uar_sel_fileset, ji->client->hdr.name); + Mmsg(&query, uar_sel_fileset, cr.ClientId, cr.ClientId); start_prompt(ua, _("The defined FileSet resources are:\n")); if (!db_sql_query(ua->db, query, fileset_handler, (void *)ua)) { bsendmsg(ua, "%s\n", db_strerror(ua->db)); @@ -368,6 +370,8 @@ static int user_select_jobids(UAContext *ua, JobIds *ji) if (do_prompt(ua, _("Select FileSet resource"), fileset_name, sizeof(fileset_name)) < 0) { free_pool_memory(query); + db_sql_query(ua->db, uar_del_temp, NULL, NULL); + db_sql_query(ua->db, uar_del_temp1, NULL, NULL); return 0; } fsr.FileSetId = atoi(fileset_name); /* Id is first part of name */ @@ -378,7 +382,7 @@ static int user_select_jobids(UAContext *ua, JobIds *ji) } /* Find JobId of last Full backup for this client, fileset */ - Mmsg(&query, uar_last_full, ji->client->hdr.name, fsr.FileSetId); + Mmsg(&query, uar_last_full, cr.ClientId, cr.ClientId, fsr.FileSetId); if (!db_sql_query(ua->db, query, NULL, NULL)) { bsendmsg(ua, "%s\n", db_strerror(ua->db)); } @@ -393,7 +397,7 @@ static int user_select_jobids(UAContext *ua, JobIds *ji) bsendmsg(ua, "%s\n", db_strerror(ua->db)); } /* Now find all Incremental Jobs */ - Mmsg(&query, uar_inc, (uint32_t)ji->JobTDate, ji->ClientId, fsr.FileSetId); + Mmsg(&query, uar_inc, edit_uint64(ji->JobTDate, ed1), cr.ClientId, fsr.FileSetId); if (!db_sql_query(ua->db, query, NULL, NULL)) { bsendmsg(ua, "%s\n", db_strerror(ua->db)); } @@ -487,8 +491,7 @@ static int last_full_handler(void *ctx, int num_fields, char **row) { JobIds *ji = (JobIds *)ctx; - ji->JobTDate = atoi(row[1]); - ji->ClientId = atoi(row[2]); + ji->JobTDate = strtoll(row[1], NULL, 10); return 0; } @@ -644,8 +647,8 @@ static void free_bsr(RBSR *bsr) if (bsr) { free_findex(bsr->fi); free_bsr(bsr->next); - if (bsr->VolumeName) { - free(bsr->VolumeName); + if (bsr->VolParams) { + free(bsr->VolParams); } free(bsr); } @@ -658,8 +661,6 @@ static void free_bsr(RBSR *bsr) static int complete_bsr(UAContext *ua, RBSR *bsr) { JOB_DBR jr; - VOL_PARAMS *VolParams; - int count = 0; if (bsr) { memset(&jr, 0, sizeof(jr)); @@ -670,17 +671,14 @@ static int complete_bsr(UAContext *ua, RBSR *bsr) } bsr->VolSessionId = jr.VolSessionId; bsr->VolSessionTime = jr.VolSessionTime; - if ((count=db_get_job_volume_parameters(ua->db, bsr->JobId, &VolParams)) == 0) { + if ((bsr->VolCount=db_get_job_volume_parameters(ua->db, bsr->JobId, + &(bsr->VolParams))) == 0) { bsendmsg(ua, _("Unable to get Job Volume Parameters. ERR=%s\n"), db_strerror(ua->db)); - free((char *)VolParams); + if (bsr->VolParams) { + free(bsr->VolParams); + } return 0; } - bsr->VolumeName = bstrdup(VolParams[0].VolumeName); - bsr->StartFile = VolParams[0].StartFile; - bsr->EndFile = VolParams[0].EndFile; - bsr->StartBlock = VolParams[0].StartBlock; - bsr->EndBlock = VolParams[0].EndBlock; - free((char *)VolParams); return complete_bsr(ua, bsr->next); } return 1; @@ -709,11 +707,18 @@ static int write_bsr_file(UAContext *ua, RBSR *bsr) fclose(fd); bsendmsg(ua, _("Bootstrap records written to %s\n"), fname); bsendmsg(ua, _("\nThe restore job will require the following Volumes:\n")); + /* Create Unique list of Volumes using prompt list */ + start_prompt(ua, ""); for (nbsr=bsr; nbsr; nbsr=nbsr->next) { - if (nbsr->VolumeName) { - bsendmsg(ua, " %s\n", nbsr->VolumeName); + for (int i=0; i < nbsr->VolCount; i++) { + add_prompt(ua, nbsr->VolParams[i].VolumeName); } } + for (int i=1; i < ua->num_prompts; i++) { + bsendmsg(ua, " %s\n", ua->prompt[i]); + free(ua->prompt[i]); + } + ua->num_prompts = 0; bsendmsg(ua, "\n"); free_pool_memory(fname); return stat; @@ -722,13 +727,16 @@ static int write_bsr_file(UAContext *ua, RBSR *bsr) static void write_bsr(UAContext *ua, RBSR *bsr, FILE *fd) { if (bsr) { - if (bsr->VolumeName) { - fprintf(fd, "Volume=\"%s\"\n", bsr->VolumeName); + for (int i=0; i < bsr->VolCount; i++) { + fprintf(fd, "Volume=\"%s\"\n", bsr->VolParams[i].VolumeName); + fprintf(fd, "VolSessionId=%u\n", bsr->VolSessionId); + fprintf(fd, "VolSessionTime=%u\n", bsr->VolSessionTime); + fprintf(fd, "VolFile=%u-%u\n", bsr->VolParams[i].StartFile, + bsr->VolParams[i].EndFile); + fprintf(fd, "VolBlock=%u-%u\n", bsr->VolParams[i].StartBlock, + bsr->VolParams[i].EndBlock); + write_findex(ua, bsr->fi, fd); } - fprintf(fd, "VolSessionId=%u\n", bsr->VolSessionId); - fprintf(fd, "VolSessionTime=%u\n", bsr->VolSessionTime); - fprintf(fd, "VolFile=%u-%u\n", bsr->StartFile, bsr->EndFile); - write_findex(ua, bsr->fi, fd); write_bsr(ua, bsr->next, fd); } } @@ -736,12 +744,16 @@ static void write_bsr(UAContext *ua, RBSR *bsr, FILE *fd) static void print_bsr(UAContext *ua, RBSR *bsr) { if (bsr) { - if (bsr->VolumeName) { - bsendmsg(ua, "Volume=\"%s\"\n", bsr->VolumeName); + for (int i=0; i < bsr->VolCount; i++) { + bsendmsg(ua, "Volume=\"%s\"\n", bsr->VolParams[i].VolumeName); + bsendmsg(ua, "VolSessionId=%u\n", bsr->VolSessionId); + bsendmsg(ua, "VolSessionTime=%u\n", bsr->VolSessionTime); + bsendmsg(ua, "VolFile=%u-%u\n", bsr->VolParams[i].StartFile, + bsr->VolParams[i].EndFile); + bsendmsg(ua, "VolBlock=%u-%u\n", bsr->VolParams[i].StartBlock, + bsr->VolParams[i].EndBlock); + print_findex(ua, bsr->fi); } - bsendmsg(ua, "VolSessionId=%u\n", bsr->VolSessionId); - bsendmsg(ua, "VolSessionTime=%u\n", bsr->VolSessionTime); - print_findex(ua, bsr->fi); print_bsr(ua, bsr->next); } } diff --git a/bacula/src/dird/ua_select.c b/bacula/src/dird/ua_select.c index 0e982291e1..25aaa746c1 100644 --- a/bacula/src/dird/ua_select.c +++ b/bacula/src/dird/ua_select.c @@ -254,6 +254,92 @@ CLIENT *get_client_resource(UAContext *ua) return select_client_resource(ua); } +/* Scan what the user has entered looking for: + * + * client= + * + * if error or not found, put up a list of client DBRs + * to choose from. + * + * returns: 0 on error + * 1 on success and fills in CLIENT_DBR + */ +int get_client_dbr(UAContext *ua, CLIENT_DBR *cr) +{ + int i; + + if (cr->Name[0]) { /* If name already supplied */ + if (db_get_client_record(ua->db, cr)) { + return 1; + } + bsendmsg(ua, _("Could not find Client %s: ERR=%s"), cr->Name, db_strerror(ua->db)); + } + for (i=1; iargc; i++) { + if (strcasecmp(ua->argk[i], _("client")) == 0 && ua->argv[i]) { + bstrncpy(cr->Name, ua->argv[i], sizeof(cr->Name)); + if (!db_get_client_record(ua->db, cr)) { + bsendmsg(ua, _("Could not find Client %s: ERR=%s"), ua->argv[i], + db_strerror(ua->db)); + cr->ClientId = 0; + break; + } + return 1; + } + } + if (!select_client_dbr(ua, cr)) { /* try once more by proposing a list */ + return 0; + } + return 1; +} + +/* + * Select a Client record from the catalog + * Returns 1 on success + * 0 on failure + */ +int select_client_dbr(UAContext *ua, CLIENT_DBR *cr) +{ + CLIENT_DBR ocr; + char name[MAX_NAME_LENGTH]; + int num_clients, i; + uint32_t *ids; + + + cr->ClientId = 0; + if (!db_get_client_ids(ua->db, &num_clients, &ids)) { + bsendmsg(ua, _("Error obtaining client ids. ERR=%s\n"), db_strerror(ua->db)); + return 0; + } + if (num_clients <= 0) { + bsendmsg(ua, _("No clients defined. Run a job to create one.\n")); + return 0; + } + + start_prompt(ua, _("Defined Clients:\n")); + for (i=0; i < num_clients; i++) { + ocr.ClientId = ids[i]; + if (!db_get_client_record(ua->db, &ocr)) { + continue; + } + add_prompt(ua, ocr.Name); + } + free(ids); + if (do_prompt(ua, _("Select the Client"), name, sizeof(name)) < 0) { + return 0; + } + memset(&ocr, 0, sizeof(ocr)); + bstrncpy(ocr.Name, name, sizeof(ocr.Name)); + + if (!db_get_client_record(ua->db, &ocr)) { + bsendmsg(ua, _("Could not find Client %s: ERR=%s"), name, db_strerror(ua->db)); + return 0; + } + memcpy(cr, &ocr, sizeof(ocr)); + return 1; +} + + + /* Scan what the user has entered looking for: * * pool= @@ -262,7 +348,7 @@ CLIENT *get_client_resource(UAContext *ua) * to choose from. * * returns: 0 on error - * poolid on success and fills in POOL_DBR + * 1 on success and fills in POOL_DBR */ int get_pool_dbr(UAContext *ua, POOL_DBR *pr) { @@ -289,7 +375,7 @@ int get_pool_dbr(UAContext *ua, POOL_DBR *pr) if (!select_pool_dbr(ua, pr)) { /* try once more */ return 0; } - return pr->PoolId; + return 1; } /* @@ -325,7 +411,7 @@ int select_pool_dbr(UAContext *ua, POOL_DBR *pr) if (do_prompt(ua, _("Select the Pool"), name, sizeof(name)) < 0) { return 0; } - memset(&opr, 0, sizeof(pr)); + memset(&opr, 0, sizeof(opr)); bstrncpy(opr.Name, name, sizeof(opr.Name)); if (!db_get_pool_record(ua->db, &opr)) { @@ -333,7 +419,7 @@ int select_pool_dbr(UAContext *ua, POOL_DBR *pr) return 0; } memcpy(pr, &opr, sizeof(opr)); - return opr.PoolId; + return 1; } /* diff --git a/bacula/src/lib/Makefile.in b/bacula/src/lib/Makefile.in index 6375186ee0..1cc8a4b6b3 100644 --- a/bacula/src/lib/Makefile.in +++ b/bacula/src/lib/Makefile.in @@ -33,7 +33,7 @@ dummy: LIBSRCS = alloc.c base64.c bmisc.c bnet.c bnet_server.c \ bpipe.c bshm.c btime.c \ - cram-md5.c crc32.c daemon.c fnmatch.c \ + cram-md5.c crc32.c daemon.c edit.c fnmatch.c \ hmac.c idcache.c jcr.c lex.c \ md5.c message.c mem_pool.c parse_conf.c \ queue.c rwlock.c serial.c \ @@ -43,7 +43,7 @@ LIBSRCS = alloc.c base64.c bmisc.c bnet.c bnet_server.c \ LIBOBJS = alloc.o base64.o bmisc.o bnet.o bnet_server.o \ bpipe.o bshm.o btime.o \ - cram-md5.o crc32.o daemon.o fnmatch.o \ + cram-md5.o crc32.o daemon.o edit.o fnmatch.o \ hmac.o idcache.o jcr.o lex.o \ md5.o message.o mem_pool.o parse_conf.o \ queue.o rwlock.o serial.o \ diff --git a/bacula/src/lib/edit.c b/bacula/src/lib/edit.c new file mode 100644 index 0000000000..cf9b044c07 --- /dev/null +++ b/bacula/src/lib/edit.c @@ -0,0 +1,279 @@ +/* + * edit.c edit string to ascii, and ascii to internal + * + * Kern Sibbald, December MMII + * + * Version $Id$ + */ + +/* + Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + */ + +#include "bacula.h" + +/* We assume ASCII input and don't worry about overflow */ +uint64_t str_to_uint64(char *str) +{ + register char *p = str; + register uint64_t value = 0; + + while (B_ISSPACE(*p)) { + p++; + } + if (*p == '+') { + p++; + } + while (B_ISDIGIT(*p)) { + value = value * 10 + *p - '0'; + p++; + } + return value; +} + +int64_t str_to_int64(char *str) +{ + register char *p = str; + register int64_t value; + int negative = FALSE; + + while (B_ISSPACE(*p)) { + p++; + } + if (*p == '+') { + p++; + } else if (*p == '-') { + negative = TRUE; + p++; + } + value = str_to_uint64(p); + if (negative) { + value = -value; + } + return value; +} + + + +/* + * Edit an integer number with commas, the supplied buffer + * must be at least 27 bytes long. The incoming number + * is always widened to 64 bits. + */ +char *edit_uint64_with_commas(uint64_t val, char *buf) +{ + sprintf(buf, "%" lld, val); + return add_commas(buf, buf); +} + +/* + * Edit an integer number, the supplied buffer + * must be at least 27 bytes long. The incoming number + * is always widened to 64 bits. + */ +char *edit_uint64(uint64_t val, char *buf) +{ + sprintf(buf, "%" lld, val); + return buf; +} + + +/* + * Convert a string duration to utime_t (64 bit seconds) + * Returns 0: if error + 1: if OK, and value stored in value + */ +int duration_to_utime(char *str, utime_t *value) +{ + int i, ch, len; + double val; + static int mod[] = {'*', 's', 'n', 'h', 'd', 'w', 'm', 'q', 'y', 0}; + static int mult[] = {1, 1, 60, 60*60, 60*60*24, 60*60*24*7, 60*60*24*30, + 60*60*24*91, 60*60*24*365}; + + /* Look for modifier */ + len = strlen(str); + ch = str[len - 1]; + i = 0; + if (B_ISALPHA(ch)) { + if (B_ISUPPER(ch)) { + ch = tolower(ch); + } + while (mod[++i] != 0) { + if (ch == mod[i]) { + len--; + str[len] = 0; /* strip modifier */ + break; + } + } + } + if (mod[i] == 0 || !is_a_number(str)) { + return 0; + } + val = strtod(str, NULL); + if (errno != 0 || val < 0) { + return 0; + } + *value = (utime_t)(val * mult[i]); + return 1; + +} + +/* + * Edit a utime "duration" into ASCII + */ +char *edit_utime(utime_t val, char *buf) +{ + char mybuf[30]; + static int mult[] = {60*60*24*365, 60*60*24*30, 60*60*24, 60*60, 60}; + static char *mod[] = {"year", "month", "day", "hour", "min"}; + int i; + uint32_t times; + + *buf = 0; + for (i=0; i<5; i++) { + times = val / mult[i]; + if (times > 0) { + val = val - (utime_t)times * mult[i]; + sprintf(mybuf, "%d %s%s ", times, mod[i], times>1?"s":""); + strcat(buf, mybuf); + } + } + if (val == 0 && strlen(buf) == 0) { + strcat(buf, "0 secs"); + } else if (val != 0) { + sprintf(mybuf, "%d sec%s", (uint32_t)val, val>1?"s":""); + strcat(buf, mybuf); + } + return buf; +} + +/* + * Convert a size size in bytes to uint64_t + * Returns 0: if error + 1: if OK, and value stored in value + */ +int size_to_uint64(char *str, int str_len, uint64_t *rtn_value) +{ + int i, ch; + double value; + int mod[] = {'*', 'k', 'm', 'g', 0}; /* first item * not used */ + uint64_t mult[] = {1, /* byte */ + 1024, /* kilobyte */ + 1048576, /* megabyte */ + 1073741824}; /* gigabyte */ + +#ifdef we_have_a_compiler_that_works + int mod[] = {'*', 'k', 'm', 'g', 't', 0}; + uint64_t mult[] = {1, /* byte */ + 1024, /* kilobyte */ + 1048576, /* megabyte */ + 1073741824, /* gigabyte */ + 1099511627776};/* terabyte */ +#endif + + Dmsg0(400, "Enter sized to uint64\n"); + + /* Look for modifier */ + ch = str[str_len - 1]; + i = 0; + if (B_ISALPHA(ch)) { + if (B_ISUPPER(ch)) { + ch = tolower(ch); + } + while (mod[++i] != 0) { + if (ch == mod[i]) { + str_len--; + str[str_len] = 0; /* strip modifier */ + break; + } + } + } + if (mod[i] == 0 || !is_a_number(str)) { + return 0; + } + Dmsg3(400, "size str=:%s: %f i=%d\n", str, strtod(str, NULL), i); + + value = (uint64_t)strtod(str, NULL); + Dmsg1(400, "Int value = %d\n", (int)value); + if (errno != 0 || value < 0) { + return 0; + } + *rtn_value = (uint64_t)(value * mult[i]); + Dmsg2(400, "Full value = %f %" lld "\n", strtod(str, NULL) * mult[i], + value *mult[i]); + return 1; +} + +/* + * Check if specified string is a number or not. + * Taken from SQLite, cool, thanks. + */ +int is_a_number(const char *n) +{ + int digit_seen = 0; + + if( *n == '-' || *n == '+' ) { + n++; + } + while (B_ISDIGIT(*n)) { + digit_seen = 1; + n++; + } + if (digit_seen && *n == '.') { + n++; + while (B_ISDIGIT(*n)) { n++; } + } + if (digit_seen && (*n == 'e' || *n == 'E') + && (B_ISDIGIT(n[1]) || ((n[1]=='-' || n[1] == '+') && B_ISDIGIT(n[2])))) { + n += 2; /* skip e- or e+ or e digit */ + while (B_ISDIGIT(*n)) { n++; } + } + return digit_seen && *n==0; +} + +/* + * Add commas to a string, which is presumably + * a number. + */ +char *add_commas(char *val, char *buf) +{ + int len, nc; + char *p, *q; + int i; + + if (val != buf) { + strcpy(buf, val); + } + len = strlen(buf); + if (len < 1) { + len = 1; + } + nc = (len - 1) / 3; + p = buf+len; + q = p + nc; + *q-- = *p--; + for ( ; nc; nc--) { + for (i=0; i < 3; i++) { + *q-- = *p--; + } + *q-- = ','; + } + return buf; +} diff --git a/bacula/src/lib/protos.h b/bacula/src/lib/protos.h index d82ffab399..d996455aec 100644 --- a/bacula/src/lib/protos.h +++ b/bacula/src/lib/protos.h @@ -24,127 +24,131 @@ */ /* base64.c */ -void base64_init (void); -int to_base64 (intmax_t value, char *where); -int from_base64 (intmax_t *value, char *where); -int bin_to_base64 (char *buf, char *bin, int len); +void base64_init (void); +int to_base64 (intmax_t value, char *where); +int from_base64 (intmax_t *value, char *where); +int bin_to_base64 (char *buf, char *bin, int len); /* bmisc.c */ -char *bstrncpy (char *dest, const char *src, int maxlen); -char *bstrncat (char *dest, const char *src, int maxlen); -void *b_malloc (char *file, int line, size_t size); +char *bstrncpy (char *dest, const char *src, int maxlen); +char *bstrncat (char *dest, const char *src, int maxlen); +void *b_malloc (char *file, int line, size_t size); #ifndef DEBUG -void *bmalloc (size_t size); +void *bmalloc (size_t size); #endif -void *brealloc (void *buf, size_t size); -void *bcalloc (size_t size1, size_t size2); -int bsnprintf (char *str, size_t size, const char *format, ...); -int bvsnprintf (char *str, size_t size, const char *format, va_list ap); -int pool_sprintf (char *pool_buf, char *fmt, ...); -void create_pid_file (char *dir, char *progname, int port); -int delete_pid_file (char *dir, char *progname, int port); +void *brealloc (void *buf, size_t size); +void *bcalloc (size_t size1, size_t size2); +int bsnprintf (char *str, size_t size, const char *format, ...); +int bvsnprintf (char *str, size_t size, const char *format, va_list ap); +int pool_sprintf (char *pool_buf, char *fmt, ...); +void create_pid_file (char *dir, char *progname, int port); +int delete_pid_file (char *dir, char *progname, int port); /* bnet.c */ -int32_t bnet_recv (BSOCK *bsock); -int bnet_send (BSOCK *bsock); -int bnet_fsend (BSOCK *bs, char *fmt, ...); -int bnet_set_buffer_size (BSOCK *bs, uint32_t size, int rw); -int bnet_sig (BSOCK *bs, int sig); -BSOCK * bnet_connect (void *jcr, int retry_interval, - int max_retry_time, char *name, char *host, char *service, - int port, int verbose); -int bnet_wait_data (BSOCK *bsock, int sec); -void bnet_close (BSOCK *bsock); -BSOCK * init_bsock (void *jcr, int sockfd, char *who, char *ip, int port); -BSOCK * dup_bsock (BSOCK *bsock); -void term_bsock (BSOCK *bsock); -char * bnet_strerror (BSOCK *bsock); -char * bnet_sig_to_ascii (BSOCK *bsock); -int bnet_wait_data (BSOCK *bsock, int sec); -int bnet_despool (BSOCK *bsock); -int is_bnet_stop (BSOCK *bsock); -int is_bnet_error (BSOCK *bsock); +int32_t bnet_recv (BSOCK *bsock); +int bnet_send (BSOCK *bsock); +int bnet_fsend (BSOCK *bs, char *fmt, ...); +int bnet_set_buffer_size (BSOCK *bs, uint32_t size, int rw); +int bnet_sig (BSOCK *bs, int sig); +BSOCK * bnet_connect (void *jcr, int retry_interval, + int max_retry_time, char *name, char *host, char *service, + int port, int verbose); +int bnet_wait_data (BSOCK *bsock, int sec); +void bnet_close (BSOCK *bsock); +BSOCK * init_bsock (void *jcr, int sockfd, char *who, char *ip, int port); +BSOCK * dup_bsock (BSOCK *bsock); +void term_bsock (BSOCK *bsock); +char * bnet_strerror (BSOCK *bsock); +char * bnet_sig_to_ascii (BSOCK *bsock); +int bnet_wait_data (BSOCK *bsock, int sec); +int bnet_despool (BSOCK *bsock); +int is_bnet_stop (BSOCK *bsock); +int is_bnet_error (BSOCK *bsock); /* cram-md5.c */ int cram_md5_get_auth(BSOCK *bs, char *password); int cram_md5_auth(BSOCK *bs, char *password); void hmac_md5(uint8_t* text, int text_len, uint8_t* key, - int key_len, uint8_t *hmac); + int key_len, uint8_t *hmac); /* crc32.c */ uint32_t bcrc32(uint8_t *buf, int len); /* daemon.c */ -void daemon_start (); +void daemon_start (); + +/* edit.c */ +uint64_t str_to_uint64(char *str); +int64_t str_to_int64(char *str); +char * edit_uint64_with_commas (uint64_t val, char *buf); +char * add_commas (char *val, char *buf); +char * edit_uint64 (uint64_t val, char *buf); +int duration_to_utime (char *str, utime_t *value); +int size_to_uint64(char *str, int str_len, uint64_t *rtn_value); +char *edit_utime (utime_t val, char *buf); +int is_a_number (const char *num); /* lex.c */ -LEX * lex_close_file (LEX *lf); -LEX * lex_open_file (LEX *lf, char *fname, LEX_ERROR_HANDLER *scan_error); -int lex_get_char (LEX *lf); -void lex_unget_char (LEX *lf); -char * lex_tok_to_str (int token); -int lex_get_token (LEX *lf, int expect); +LEX * lex_close_file (LEX *lf); +LEX * lex_open_file (LEX *lf, char *fname, LEX_ERROR_HANDLER *scan_error); +int lex_get_char (LEX *lf); +void lex_unget_char (LEX *lf); +char * lex_tok_to_str (int token); +int lex_get_token (LEX *lf, int expect); /* message.c */ -void my_name_is (int argc, char *argv[], char *name); -void init_msg (void *jcr, MSGS *msg); -void term_msg (void); -void close_msg (void *jcr); -void add_msg_dest (MSGS *msg, int dest, int type, char *where, char *dest_code); -void rem_msg_dest (MSGS *msg, int dest, int type, char *where); -void Jmsg (void *jcr, int type, int level, char *fmt, ...); -void dispatch_message (void *jcr, int type, int level, char *buf); -void init_console_msg (char *wd); -void free_msgs_res (MSGS *msgs); -int open_spool_file (void *jcr, BSOCK *bs); -int close_spool_file (void *vjcr, BSOCK *bs); +void my_name_is (int argc, char *argv[], char *name); +void init_msg (void *jcr, MSGS *msg); +void term_msg (void); +void close_msg (void *jcr); +void add_msg_dest (MSGS *msg, int dest, int type, char *where, char *dest_code); +void rem_msg_dest (MSGS *msg, int dest, int type, char *where); +void Jmsg (void *jcr, int type, int level, char *fmt, ...); +void dispatch_message (void *jcr, int type, int level, char *buf); +void init_console_msg (char *wd); +void free_msgs_res (MSGS *msgs); +int open_spool_file (void *jcr, BSOCK *bs); +int close_spool_file (void *vjcr, BSOCK *bs); /* bnet_server.c */ -void bnet_thread_server(char *bind_addr, int port, int max_clients, workq_t *client_wq, - void handle_client_request(void *bsock)); -void bnet_server (int port, void handle_client_request(BSOCK *bsock)); -int net_connect (int port); -BSOCK * bnet_bind (int port); -BSOCK * bnet_accept (BSOCK *bsock, char *who); +void bnet_thread_server(char *bind_addr, int port, int max_clients, workq_t *client_wq, + void handle_client_request(void *bsock)); +void bnet_server (int port, void handle_client_request(BSOCK *bsock)); +int net_connect (int port); +BSOCK * bnet_bind (int port); +BSOCK * bnet_accept (BSOCK *bsock, char *who); /* signal.c */ -void init_signals (void terminate(int sig)); -void init_stack_dump (void); +void init_signals (void terminate(int sig)); +void init_stack_dump (void); /* util.c */ -void lcase (char *str); -void bash_spaces (char *str); -void unbash_spaces (char *str); -void strip_trailing_junk (char *str); -void strip_trailing_slashes (char *dir); -int skip_spaces (char **msg); -int skip_nonspaces (char **msg); -int fstrsch (char *a, char *b); -char * encode_time (time_t time, char *buf); -char * encode_mode (mode_t mode, char *buf); -char * edit_uint64_with_commas (uint64_t val, char *buf); -char * add_commas (char *val, char *buf); -char * edit_uint64 (uint64_t val, char *buf); -int do_shell_expansion (char *name); -int is_a_number (const char *num); -int is_buf_zero (char *buf, int len); -int duration_to_utime (char *str, utime_t *value); -int size_to_uint64(char *str, int str_len, uint64_t *rtn_value); -char *edit_utime (utime_t val, char *buf); -void jobstatus_to_ascii (int JobStatus, char *msg, int maxlen); -void pm_strcat (POOLMEM **pm, char *str); -void pm_strcpy (POOLMEM **pm, char *str); -int run_program (char *prog, int wait, POOLMEM *results); -char * job_type_to_str (int type); -char * job_status_to_str (int stat); -char * job_level_to_str (int level); -void makeSessionKey (char *key, char *seed, int mode); -BPIPE * open_bpipe(char *prog, int wait, char *mode); -int close_wpipe(BPIPE *bpipe); -int close_bpipe(BPIPE *bpipe); +void lcase (char *str); +void bash_spaces (char *str); +void unbash_spaces (char *str); +void strip_trailing_junk (char *str); +void strip_trailing_slashes (char *dir); +int skip_spaces (char **msg); +int skip_nonspaces (char **msg); +int fstrsch (char *a, char *b); +char * encode_time (time_t time, char *buf); +char * encode_mode (mode_t mode, char *buf); +int do_shell_expansion (char *name); +int is_buf_zero (char *buf, int len); +void jobstatus_to_ascii (int JobStatus, char *msg, int maxlen); +void pm_strcat (POOLMEM **pm, char *str); +void pm_strcpy (POOLMEM **pm, char *str); +int run_program (char *prog, int wait, POOLMEM *results); +char * job_type_to_str (int type); +char * job_status_to_str (int stat); +char * job_level_to_str (int level); +void makeSessionKey (char *key, char *seed, int mode); +BPIPE * open_bpipe(char *prog, int wait, char *mode); +int close_wpipe(BPIPE *bpipe); +int close_bpipe(BPIPE *bpipe); /* watchdog.c */ diff --git a/bacula/src/lib/util.c b/bacula/src/lib/util.c index cc0da0539c..2c6940aa91 100644 --- a/bacula/src/lib/util.c +++ b/bacula/src/lib/util.c @@ -60,214 +60,6 @@ int is_buf_zero(char *buf, int len) return 1; } -/* - * Convert a string duration to utime_t (64 bit seconds) - * Returns 0: if error - 1: if OK, and value stored in value - */ -int duration_to_utime(char *str, utime_t *value) -{ - int i, ch, len; - double val; - static int mod[] = {'*', 's', 'n', 'h', 'd', 'w', 'm', 'q', 'y', 0}; - static int mult[] = {1, 1, 60, 60*60, 60*60*24, 60*60*24*7, 60*60*24*30, - 60*60*24*91, 60*60*24*365}; - - /* Look for modifier */ - len = strlen(str); - ch = str[len - 1]; - i = 0; - if (B_ISALPHA(ch)) { - if (B_ISUPPER(ch)) { - ch = tolower(ch); - } - while (mod[++i] != 0) { - if (ch == mod[i]) { - len--; - str[len] = 0; /* strip modifier */ - break; - } - } - } - if (mod[i] == 0 || !is_a_number(str)) { - return 0; - } - val = strtod(str, NULL); - if (errno != 0 || val < 0) { - return 0; - } - *value = (utime_t)(val * mult[i]); - return 1; - -} - -/* - * Edit a utime "duration" into ASCII - */ -char *edit_utime(utime_t val, char *buf) -{ - char mybuf[30]; - static int mult[] = {60*60*24*365, 60*60*24*30, 60*60*24, 60*60, 60}; - static char *mod[] = {"year", "month", "day", "hour", "min"}; - int i; - uint32_t times; - - *buf = 0; - for (i=0; i<5; i++) { - times = val / mult[i]; - if (times > 0) { - val = val - (utime_t)times * mult[i]; - sprintf(mybuf, "%d %s%s ", times, mod[i], times>1?"s":""); - strcat(buf, mybuf); - } - } - if (val == 0 && strlen(buf) == 0) { - strcat(buf, "0 secs"); - } else if (val != 0) { - sprintf(mybuf, "%d sec%s", (uint32_t)val, val>1?"s":""); - strcat(buf, mybuf); - } - return buf; -} - -/* - * Convert a size size in bytes to uint64_t - * Returns 0: if error - 1: if OK, and value stored in value - */ -int size_to_uint64(char *str, int str_len, uint64_t *rtn_value) -{ - int i, ch; - double value; - int mod[] = {'*', 'k', 'm', 'g', 0}; /* first item * not used */ - uint64_t mult[] = {1, /* byte */ - 1024, /* kilobyte */ - 1048576, /* megabyte */ - 1073741824}; /* gigabyte */ - -#ifdef we_have_a_compiler_that_works - int mod[] = {'*', 'k', 'm', 'g', 't', 0}; - uint64_t mult[] = {1, /* byte */ - 1024, /* kilobyte */ - 1048576, /* megabyte */ - 1073741824, /* gigabyte */ - 1099511627776};/* terabyte */ -#endif - - Dmsg0(400, "Enter sized to uint64\n"); - - /* Look for modifier */ - ch = str[str_len - 1]; - i = 0; - if (B_ISALPHA(ch)) { - if (B_ISUPPER(ch)) { - ch = tolower(ch); - } - while (mod[++i] != 0) { - if (ch == mod[i]) { - str_len--; - str[str_len] = 0; /* strip modifier */ - break; - } - } - } - if (mod[i] == 0 || !is_a_number(str)) { - return 0; - } - Dmsg3(400, "size str=:%s: %f i=%d\n", str, strtod(str, NULL), i); - - value = (uint64_t)strtod(str, NULL); - Dmsg1(400, "Int value = %d\n", (int)value); - if (errno != 0 || value < 0) { - return 0; - } - *rtn_value = (uint64_t)(value * mult[i]); - Dmsg2(400, "Full value = %f %" lld "\n", strtod(str, NULL) * mult[i], - value *mult[i]); - return 1; -} - -/* - * Check if specified string is a number or not. - * Taken from SQLite, cool, thanks. - */ -int is_a_number(const char *n) -{ - int digit_seen = 0; - - if( *n == '-' || *n == '+' ) { - n++; - } - while (B_ISDIGIT(*n)) { - digit_seen = 1; - n++; - } - if (digit_seen && *n == '.') { - n++; - while (B_ISDIGIT(*n)) { n++; } - } - if (digit_seen && (*n == 'e' || *n == 'E') - && (B_ISDIGIT(n[1]) || ((n[1]=='-' || n[1] == '+') && B_ISDIGIT(n[2])))) { - n += 2; /* skip e- or e+ or e digit */ - while (B_ISDIGIT(*n)) { n++; } - } - return digit_seen && *n==0; -} - - -/* - * Edit an integer number with commas, the supplied buffer - * must be at least 27 bytes long. The incoming number - * is always widened to 64 bits. - */ -char *edit_uint64_with_commas(uint64_t val, char *buf) -{ - sprintf(buf, "%" lld, val); - return add_commas(buf, buf); -} - -/* - * Edit an integer number, the supplied buffer - * must be at least 27 bytes long. The incoming number - * is always widened to 64 bits. - */ -char *edit_uint64(uint64_t val, char *buf) -{ - sprintf(buf, "%" lld, val); - return buf; -} - - -/* - * Add commas to a string, which is presumably - * a number. - */ -char *add_commas(char *val, char *buf) -{ - int len, nc; - char *p, *q; - int i; - - if (val != buf) { - strcpy(buf, val); - } - len = strlen(buf); - if (len < 1) { - len = 1; - } - nc = (len - 1) / 3; - p = buf+len; - q = p + nc; - *q-- = *p--; - for ( ; nc; nc--) { - for (i=0; i < 3; i++) { - *q-- = *p--; - } - *q-- = ','; - } - return buf; -} - /* Convert a string in place to lower case */ void lcase(char *str) diff --git a/bacula/src/stored/acquire.c b/bacula/src/stored/acquire.c index a96519ad22..59418bc86a 100644 --- a/bacula/src/stored/acquire.c +++ b/bacula/src/stored/acquire.c @@ -127,7 +127,7 @@ default_path: attach_jcr_to_device(dev, jcr); /* attach jcr to device */ stat = 1; /* good return */ if ((dev->state & ST_TAPE) && vol->start_file > 0) { - Dmsg1(100, "====== Got start_file = %d\n", vol->start_file); + Dmsg1(200, "====== Got start_file = %d\n", vol->start_file); fsf_dev(dev, vol->start_file); } diff --git a/bacula/src/stored/block.c b/bacula/src/stored/block.c index fdbc19097a..c28a7b944d 100644 --- a/bacula/src/stored/block.c +++ b/bacula/src/stored/block.c @@ -113,6 +113,7 @@ DEV_BLOCK *new_block(DEVICE *dev) } else { block->buf_len = dev->max_block_size; } + block->dev = dev; block->block_len = block->buf_len; /* default block size */ block->buf = get_memory(block->buf_len); if (block->buf == NULL) { diff --git a/bacula/src/stored/block.h b/bacula/src/stored/block.h index 90f10a06dd..bb9e72a9d9 100644 --- a/bacula/src/stored/block.h +++ b/bacula/src/stored/block.h @@ -84,6 +84,7 @@ */ typedef struct s_dev_block { struct s_dev_block *next; /* pointer to next one */ + void *dev; /* pointer to device (DEVICE not defined yet) */ /* binbuf is the number of bytes remaining * in the buffer. For writes, it is bytes not yet written. * For reads, it is remaining bytes not yet read. diff --git a/bacula/src/stored/bsr.h b/bacula/src/stored/bsr.h index 7a86787b89..39acdd5624 100644 --- a/bacula/src/stored/bsr.h +++ b/bacula/src/stored/bsr.h @@ -47,10 +47,10 @@ typedef struct s_vol_list VOL_LIST; /* * !!!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!! - * !!! !!! - * !!! All records must have a pointer to !!! - * !!! the next item as the first item defined. !!! - * !!! !!! + * !!! !!! + * !!! All records must have a pointer to !!! + * !!! the next item as the first item defined. !!! + * !!! !!! * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ @@ -68,27 +68,35 @@ typedef struct s_bsr_sessid { struct s_bsr_sessid *next; uint32_t sessid; uint32_t sessid2; - int done; /* local done */ + int done; /* local done */ } BSR_SESSID; typedef struct s_bsr_sesstime { struct s_bsr_sesstime *next; uint32_t sesstime; - int done; /* local done */ + int done; /* local done */ } BSR_SESSTIME; typedef struct s_bsr_volfile { struct s_bsr_volfile *next; - uint32_t sfile; /* start file */ - uint32_t efile; /* end file */ - int done; /* local done */ + uint32_t sfile; /* start file */ + uint32_t efile; /* end file */ + int done; /* local done */ } BSR_VOLFILE; +typedef struct s_bsr_volblock { + struct s_bsr_volblock *next; + uint32_t sblock; /* start block */ + uint32_t eblock; /* end block */ + int done; /* local done */ +} BSR_VOLBLOCK; + + typedef struct s_bsr_findex { struct s_bsr_findex *next; - int32_t findex; /* start file index */ - int32_t findex2; /* end file index */ - int done; /* local done */ + int32_t findex; /* start file index */ + int32_t findex2; /* end file index */ + int done; /* local done */ } BSR_FINDEX; typedef struct s_bsr_jobid { @@ -115,27 +123,28 @@ typedef struct s_bsr_job { typedef struct s_bsr_stream { struct s_bsr_stream *next; - int32_t stream; /* stream desired */ + int32_t stream; /* stream desired */ } BSR_STREAM; typedef struct s_bsr { - struct s_bsr *next; /* pointer to next one */ - int done; /* set when everything found */ - BSR_VOLUME *volume; - int32_t Slot; /* Slot */ - uint32_t count; /* count of files to restore this bsr */ - uint32_t found; /* count of restored files this bsr */ - BSR_VOLFILE *volfile; + struct s_bsr *next; /* pointer to next one */ + int done; /* set when everything found */ + BSR_VOLUME *volume; + int32_t Slot; /* Slot */ + uint32_t count; /* count of files to restore this bsr */ + uint32_t found; /* count of restored files this bsr */ + BSR_VOLFILE *volfile; + BSR_VOLBLOCK *volblock; BSR_SESSTIME *sesstime; - BSR_SESSID *sessid; - BSR_JOBID *JobId; - BSR_JOB *job; - BSR_CLIENT *client; - BSR_FINDEX *FileIndex; - BSR_JOBTYPE *JobType; + BSR_SESSID *sessid; + BSR_JOBID *JobId; + BSR_JOB *job; + BSR_CLIENT *client; + BSR_FINDEX *FileIndex; + BSR_JOBTYPE *JobType; BSR_JOBLEVEL *JobLevel; - BSR_STREAM *stream; -// FF_PKT *ff; /* include/exclude */ + BSR_STREAM *stream; +// FF_PKT *ff; /* include/exclude */ } BSR; diff --git a/bacula/src/stored/match_bsr.c b/bacula/src/stored/match_bsr.c index aa564d0c34..da72874d59 100755 --- a/bacula/src/stored/match_bsr.c +++ b/bacula/src/stored/match_bsr.c @@ -85,10 +85,9 @@ static int match_all(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec, if (!match_volume(bsr, bsr->volume, volrec, 1)) { goto no_match; } - /* Not yet working */ -// if (!match_volfile(bsr, bsr->volfile, rec, 1)) { -// goto no_match; -// } + if (!match_volfile(bsr, bsr->volfile, rec, 1)) { + goto no_match; + } if (!match_sesstime(bsr, bsr->sesstime, rec, 1)) { goto no_match; } @@ -222,6 +221,12 @@ static int match_volfile(BSR *bsr, BSR_VOLFILE *volfile, DEV_RECORD *rec, int do if (!volfile) { return 1; /* no specification matches all */ } + /* For the moment, these tests work only with tapes. */ + if (!(rec->state & REC_ISTAPE)) { + return 1; /* All File records OK for this match */ + } +// Dmsg3(000, "match_volfile: sfile=%d efile=%d recfile=%d\n", +// volfile->sfile, volfile->efile, rec->File); if (volfile->sfile <= rec->File && volfile->efile >= rec->File) { return 1; } diff --git a/bacula/src/stored/parse_bsr.c b/bacula/src/stored/parse_bsr.c index 3cc924e8c0..2707477600 100755 --- a/bacula/src/stored/parse_bsr.c +++ b/bacula/src/stored/parse_bsr.c @@ -41,6 +41,7 @@ static BSR *store_joblevel(LEX *lc, BSR *bsr); static BSR *store_findex(LEX *lc, BSR *bsr); static BSR *store_sessid(LEX *lc, BSR *bsr); static BSR *store_volfile(LEX *lc, BSR *bsr); +static BSR *store_volblock(LEX *lc, BSR *bsr); static BSR *store_sesstime(LEX *lc, BSR *bsr); static BSR *store_include(LEX *lc, BSR *bsr); static BSR *store_exclude(LEX *lc, BSR *bsr); @@ -69,6 +70,7 @@ struct kw_items items[] = { {"include", store_include}, {"exclude", store_exclude}, {"volfile", store_volfile}, + {"volblock", store_volblock}, {"stream", store_stream}, {"slot", store_slot}, {NULL, NULL} @@ -399,6 +401,41 @@ static BSR *store_volfile(LEX *lc, BSR *bsr) } +/* + * Routine to handle Volume start/end Block + */ +static BSR *store_volblock(LEX *lc, BSR *bsr) +{ + int token; + BSR_VOLBLOCK *volblock; + + for (;;) { + token = lex_get_token(lc, T_PINT32_RANGE); + if (token == T_ERROR) { + return NULL; + } + volblock = (BSR_VOLBLOCK *)malloc(sizeof(BSR_VOLBLOCK)); + memset(volblock, 0, sizeof(BSR_VOLBLOCK)); + volblock->sblock = lc->pint32_val; + volblock->eblock = lc->pint32_val2; + /* Add it to the end of the chain */ + if (!bsr->volblock) { + bsr->volblock = volblock; + } else { + /* Add to end of chain */ + BSR_VOLBLOCK *bs = bsr->volblock; + for ( ;bs->next; bs=bs->next) + { } + bs->next = volblock; + } + token = lex_get_token(lc, T_ALL); + if (token != T_COMMA) { + break; + } + } + return bsr; +} + static BSR *store_sessid(LEX *lc, BSR *bsr) { @@ -528,6 +565,15 @@ void dump_volfile(BSR_VOLFILE *volfile) } } +void dump_volblock(BSR_VOLBLOCK *volblock) +{ + if (volblock) { + Dmsg2(-1, "VolBlock : %u-%u\n", volblock->sblock, volblock->eblock); + dump_volblock(volblock->next); + } +} + + void dump_findex(BSR_FINDEX *FileIndex) { if (FileIndex) { @@ -613,6 +659,7 @@ void dump_bsr(BSR *bsr) dump_sessid(bsr->sessid); dump_sesstime(bsr->sesstime); dump_volfile(bsr->volfile); + dump_volblock(bsr->volblock); dump_client(bsr->client); dump_jobid(bsr->JobId); dump_job(bsr->job); @@ -654,6 +701,7 @@ void free_bsr(BSR *bsr) free_bsr_item((BSR *)bsr->sessid); free_bsr_item((BSR *)bsr->sesstime); free_bsr_item((BSR *)bsr->volfile); + free_bsr_item((BSR *)bsr->volblock); free_bsr_item((BSR *)bsr->JobId); free_bsr_item((BSR *)bsr->job); free_bsr_item((BSR *)bsr->FileIndex); diff --git a/bacula/src/stored/read_record.c b/bacula/src/stored/read_record.c index de5d6050b3..85b9b44add 100644 --- a/bacula/src/stored/read_record.c +++ b/bacula/src/stored/read_record.c @@ -87,7 +87,6 @@ int read_records(JCR *jcr, DEVICE *dev, read_block_from_device(dev, block); read_record_from_block(block, trec); get_session_record(dev, trec, &sessrec); - trec->File = dev->file; record_cb(jcr, dev, block, trec); free_record(trec); goto next_record; @@ -118,7 +117,6 @@ next_record: block->BlockNumber, rec->remainder); break; } - rec->File = dev->file; Dmsg3(10, "read-OK. stat=%s blk=%d rem=%d\n", rec_state_to_str(rec), block->BlockNumber, rec->remainder); /* diff --git a/bacula/src/stored/record.c b/bacula/src/stored/record.c index 410daa54f5..e55a514997 100644 --- a/bacula/src/stored/record.c +++ b/bacula/src/stored/record.c @@ -359,9 +359,14 @@ int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec) remlen = block->binbuf; rec->Block = block->BlockNumber; + rec->File = ((DEVICE *)block->dev)->file; - /* Clear state flags */ + /* Clear state flags */ rec->state = 0; + if (((DEVICE *)block->dev)->state & ST_TAPE) { + rec->state |= REC_ISTAPE; + } + /* * Get the header. There is always a full header, diff --git a/bacula/src/stored/record.h b/bacula/src/stored/record.h index 3000a037ea..4824ecc34f 100644 --- a/bacula/src/stored/record.h +++ b/bacula/src/stored/record.h @@ -65,6 +65,7 @@ #define REC_BLOCK_EMPTY 0x04 /* not enough data in block */ #define REC_NO_MATCH 0x08 /* No match on continuation data */ #define REC_CONTINUATION 0x10 /* Continuation record found */ +#define REC_ISTAPE 0x20 /* Set if device is tape */ #define is_partial_record(r) ((r)->state & REC_PARTIAL_RECORD) #define is_block_empty(r) ((r)->state & REC_BLOCK_EMPTY) diff --git a/bacula/src/tools/Makefile.in b/bacula/src/tools/Makefile.in index 260003d734..0edf9b9ce0 100644 --- a/bacula/src/tools/Makefile.in +++ b/bacula/src/tools/Makefile.in @@ -44,7 +44,7 @@ smtp: smtp.o ../lib/libbac.a $(CXX) $(LDFLAGS) -L../lib -o $@ smtp.o -lbac -lm $(LIBS) $(DLIB) dbcheck: dbcheck.o ../lib/libbac.a ../cats/libsql.a - $(CXX) $(LDFLAGS) -L../lib -L../cats -o $@ dbcheck.o -lbac -lsql -lm $(LIBS) $(DB_LIBS) + $(CXX) $(LDFLAGS) -L../lib -L../cats -o $@ dbcheck.o -lsql -lbac -lm $(LIBS) $(DB_LIBS) testfind: ../findlib/libfind.a ../lib/libbac.a $(FINDOBJS) $(CXX) -g $(LDFLAGS) -L. -L../lib -L../findlib -o $@ $(FINDOBJS) \ diff --git a/bacula/src/version.h b/bacula/src/version.h index 031ebb90cd..3846672ee1 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -1,8 +1,8 @@ /* */ #define VERSION "1.28" #define VSTRING "1" -#define DATE "2 December 2002" -#define LSMDATE "02Dec02" +#define DATE "4 December 2002" +#define LSMDATE "04Dec02" /* Debug flags */ #define DEBUG 1 -- 2.39.5