From db408b1c519492b0bf19c56ebba5414858c3f5ea Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Thu, 21 Nov 2002 20:24:36 +0000 Subject: [PATCH] See kes21Nov02 git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@203 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/ChangeLog | 32 ++++++- bacula/ReleaseNotes | 7 +- bacula/src/cats/bdb_update.c | 2 +- bacula/src/cats/cats.h | 16 ++-- bacula/src/cats/make_mysql_tables.in | 6 +- bacula/src/cats/make_sqlite_tables.in | 6 +- bacula/src/cats/sql_create.c | 12 +-- bacula/src/cats/sql_find.c | 13 +-- bacula/src/cats/sql_get.c | 26 +++--- bacula/src/cats/sql_update.c | 4 +- bacula/src/dird/backup.c | 2 +- bacula/src/dird/catreq.c | 116 ++++++++++++++++---------- bacula/src/dird/dird_conf.c | 46 +++++----- bacula/src/dird/dird_conf.h | 1 + bacula/src/dird/protos.h | 6 +- bacula/src/dird/restore.c | 2 +- bacula/src/dird/ua.h | 4 +- bacula/src/dird/ua_cmds.c | 49 ++++++++--- bacula/src/dird/ua_prune.c | 22 +---- bacula/src/dird/ua_purge.c | 21 +++-- bacula/src/dird/ua_restore.c | 7 +- bacula/src/dird/ua_run.c | 8 +- bacula/src/dird/ua_select.c | 48 +++++------ bacula/src/dird/ua_status.c | 2 +- bacula/src/dird/verify.c | 2 +- bacula/src/lib/bnet_server.c | 2 +- bacula/src/lib/cram-md5.c | 16 ++-- bacula/src/lib/parse_conf.c | 3 +- bacula/src/stored/acquire.c | 4 +- bacula/src/stored/askdir.c | 34 ++++---- bacula/src/stored/block.c | 18 +++- bacula/src/stored/dev.h | 4 +- bacula/src/version.h | 4 +- 33 files changed, 322 insertions(+), 223 deletions(-) diff --git a/bacula/ChangeLog b/bacula/ChangeLog index a3463631c0..63f0f77100 100644 --- a/bacula/ChangeLog +++ b/bacula/ChangeLog @@ -1,5 +1,35 @@ -2002-mm-dd Version 1.27 (18Nov02) not yet released +2002-mm-dd Version 1.27 (20Nov02) not yet released +General: from kes21Nov02 +- Another change in the database. You MUST either re-initialize + your database or use the appropriate ./alter_xxx_tables in + the src/cats directory. + +Changes submitted this submission: +- Additional documentation. +- Added MaxVolFiles to the database (not yet implemented in code). +- Increased the database version from 3 to 4. +- Change VolMaxBytes to MaxVolBytes, which is much more descriptive. +- Compressed unnecessary spaces out of a lot of SQL statements. +- Changed many %d to %u where unsigned integers are used. +- Added the Bacula version and build date to each backup output. + This will help knowing what version of Bacula was used. +- Implemented VolUseDuration MaxVolBytes, MaxVolFiles, and MaxVolJobs + based on maximums set in the Volume (Media) record rather than in the + resource. This means the values can be individually set on a Volume basis. +- Allow commas separating Include options (this was a subtle bug). +- Added maximum string length argments to a number of subroutines to + prevent buffer overflows. Most notably was do_prompt(). +- Replaced MANY occurrences of strcpy() with bstrncpy(), which guarantees + both that the length is not exceeded and that the string is properly terminated. + This has a risk of a certain destabilization -- as does the changes to + the SQL noted above. +- In cram-md5 routine use my_name if gethostname() returns an error. +- Increase timeout from 2 minutes to 3 minutes in authorization code. +- Check the full string including \n in authorization. +- Throw away any response longer than MAXSTRING. +- Added a number of additional error checks on subroutine return statuses. +- Replaced as many lld's with edit_uint64 as I could find. General: from kes18Nov02 - Did a number of cleanups of string copying to limit the length diff --git a/bacula/ReleaseNotes b/bacula/ReleaseNotes index 472a2ee4a7..bc636c04f7 100644 --- a/bacula/ReleaseNotes +++ b/bacula/ReleaseNotes @@ -1,6 +1,6 @@ Release Notes for Bacula 1.27 - Bacula code: Total files = 222 Total lines = 60,233 (*.h *.c *.in) + Bacula code: Total files = 222 Total lines = 60,396 (*.h *.c *.in) Major Changes this Release: - Implemented support for Sparse files. @@ -25,6 +25,9 @@ Major Changes this Release: it would accept ONLY the next appendable volume. To get the old behavior add "Accept Any Volume = No" to the Storage resources of your Director's configuration file. +- New database format. You must either re-initialize your database or + use /src/cats/alter_mysql_tables (or alter_sqlite_tables) + to upgrade an existing database. Minor Changes this Release: - A number of small bug fixes. @@ -36,9 +39,11 @@ Minor Changes this Release: - Fixed mount loop when the autochanger slot is incorrect in the catalog. - Updated the bacula script to work on more systems. +- Fixed many places prone to buffer overflows. Items to note: - The Dir-SD protocol has changed since 1.26, so you must update the Director and Storage daemons. - The Dir-FD protocol has changed since 1.26 (and earlier versions of 1.27). +- You must re-initialize or alter your databases. diff --git a/bacula/src/cats/bdb_update.c b/bacula/src/cats/bdb_update.c index 50a3a50900..76abba20a7 100755 --- a/bacula/src/cats/bdb_update.c +++ b/bacula/src/cats/bdb_update.c @@ -140,7 +140,7 @@ int db_update_media_record(B_DB *mdb, MEDIA_DBR *mr) strcpy(mr->MediaType, omr.MediaType); mr->MediaId = omr.MediaId; mr->PoolId = omr.PoolId; - mr->VolMaxBytes = omr.VolMaxBytes; + mr->MaxVolBytes = omr.MaxVolBytes; mr->VolCapacityBytes = omr.VolCapacityBytes; mr->Recycle = omr.Recycle; diff --git a/bacula/src/cats/cats.h b/bacula/src/cats/cats.h index 6fd62190b5..cd19edecdc 100644 --- a/bacula/src/cats/cats.h +++ b/bacula/src/cats/cats.h @@ -48,7 +48,7 @@ typedef int (DB_RESULT_HANDLER)(void *, int, char **); #ifdef HAVE_SQLITE -#define BDB_VERSION 3 +#define BDB_VERSION 4 #include @@ -134,7 +134,7 @@ extern void my_sqlite_free_table(B_DB *mdb); #ifdef HAVE_MYSQL -#define BDB_VERSION 3 +#define BDB_VERSION 4 #include @@ -191,7 +191,7 @@ typedef struct s_db { /* Change this each time there is some incompatible * file format change!!!! */ -#define BDB_VERSION 10 /* file version number */ +#define BDB_VERSION 11 /* file version number */ struct s_control { int bdb_version; /* Version number */ @@ -360,7 +360,8 @@ typedef struct { int Recycle; /* default Vol recycle flag */ utime_t VolRetention; /* retention period in seconds */ utime_t VolUseDuration; /* time in secs volume can be used */ - uint32_t MaxVolJobs; /* Max jobs on volume */ + uint32_t MaxVolJobs; /* Max Jobs on Volume */ + uint32_t MaxVolFiles; /* Max files on Volume */ char PoolType[MAX_NAME_LENGTH]; char LabelFormat[MAX_NAME_LENGTH]; /* Extra stuff not in DB */ @@ -375,7 +376,7 @@ typedef struct { uint32_t PoolId; /* Pool id */ time_t FirstWritten; /* Time Volume first written */ time_t LastWritten; /* Time Volume last written */ - time_t LabelDate; /* Date/Time Volume labelled */ + time_t LabelDate; /* Date/Time Volume labeled */ uint32_t VolJobs; /* number of jobs on this medium */ uint32_t VolFiles; /* Number of files */ uint32_t VolBlocks; /* Number of blocks */ @@ -384,11 +385,12 @@ typedef struct { uint32_t VolWrites; /* Number of writes */ uint32_t VolReads; /* Number of reads */ uint64_t VolBytes; /* Number of bytes written */ - uint64_t VolMaxBytes; /* max bytes to write */ + uint64_t MaxVolBytes; /* Max bytes to write to Volume */ uint64_t VolCapacityBytes; /* capacity estimate */ utime_t VolRetention; /* Volume retention in seconds */ utime_t VolUseDuration; /* time in secs volume can be used */ - uint32_t MaxVolJobs; /* Max jobs on volume */ + uint32_t MaxVolJobs; /* Max Jobs on Volume */ + uint32_t MaxVolFiles; /* Max files on Volume */ int Recycle; /* recycle yes/no */ int32_t Slot; /* slot in changer */ char VolStatus[20]; /* Volume status */ diff --git a/bacula/src/cats/make_mysql_tables.in b/bacula/src/cats/make_mysql_tables.in index 97ee273a31..e3f4c03ff4 100644 --- a/bacula/src/cats/make_mysql_tables.in +++ b/bacula/src/cats/make_mysql_tables.in @@ -102,7 +102,7 @@ CREATE TABLE Media ( VolBytes BIGINT UNSIGNED NOT NULL, VolErrors INTEGER UNSIGNED NOT NULL, VolWrites INTEGER UNSIGNED NOT NULL, - VolMaxBytes BIGINT UNSIGNED NOT NULL, + MaxVolBytes BIGINT UNSIGNED NOT NULL, VolCapacityBytes BIGINT UNSIGNED NOT NULL, VolStatus ENUM('Full', 'Archive', 'Append', 'Recycle', 'Purged', 'Read-Only', 'Disabled', 'Error', 'Busy', 'Used') NOT NULL, @@ -110,6 +110,7 @@ CREATE TABLE Media ( VolRetention BIGINT UNSIGNED NOT NULL, VolUseDuration BIGINT UNSIGNED NOT NULL, MaxVolJobs INTEGER UNSIGNED NOT NULL, + MaxVolFiles INTEGER UNSIGNED NOT NULL, PRIMARY KEY(MediaId), INDEX (PoolId) ); @@ -125,6 +126,7 @@ CREATE TABLE Pool ( VolRetention BIGINT UNSIGNED NOT NULL, VolUseDuration BIGINT UNSIGNED NOT NULL, MaxVolJobs INTEGER UNSIGNED NOT NULL, + MaxVolFiles INTEGER UNSIGNED NOT NULL, AutoPrune TINYINT DEFAULT 0, Recycle TINYINT DEFAULT 0, PoolType ENUM('Backup', 'Copy', 'Cloned', 'Archive', 'Migration') NOT NULL, @@ -150,7 +152,7 @@ CREATE TABLE Version ( ); -- Initialize Version -INSERT INTO Version (VersionId) VALUES (3); +INSERT INTO Version (VersionId) VALUES (4); CREATE TABLE Counters ( Counter TINYBLOB NOT NULL, diff --git a/bacula/src/cats/make_sqlite_tables.in b/bacula/src/cats/make_sqlite_tables.in index e7bbee7004..8bac3c7a6a 100644 --- a/bacula/src/cats/make_sqlite_tables.in +++ b/bacula/src/cats/make_sqlite_tables.in @@ -104,13 +104,14 @@ CREATE TABLE Media ( VolBytes BIGINT UNSIGNED DEFAULT 0, VolErrors INTEGER UNSIGNED DEFAULT 0, VolWrites INTEGER UNSIGNED DEFAULT 0, - VolMaxBytes BIGINT UNSIGNED DEFAULT 0, + MaxVolBytes BIGINT UNSIGNED DEFAULT 0, VolCapacityBytes BIGINT UNSIGNED DEFAULT 0, VolStatus VARCHAR(20) NOT NULL, Recycle TINYINT DEFAULT 0, VolRetention BIGINT UNSIGNED DEFAULT 0, VolUseDuration BIGINT UNSIGNED DEFAULT 0, MaxVolJobs INTEGER UNSIGNED DEFAULT 0, + MaxVolFiles INTEGER UNSIGNED DEFAULT 0, PRIMARY KEY(MediaId) ); @@ -127,6 +128,7 @@ CREATE TABLE Pool ( VolRetention BIGINT UNSIGNED DEFAULT 0, VolUseDuration BIGINT UNSIGNED DEFAULT 0, MaxVolJobs INTEGER UNSIGNED DEFAULT 0, + MaxVolfiles INTEGER UNSIGNED DEFAULT 0, AutoPrune TINYINT DEFAULT 0, Recycle TINYINT DEFAULT 0, PoolType VARCHAR(20) NOT NULL, @@ -161,7 +163,7 @@ CREATE TABLE Version ( ); -- Initialize Version -INSERT INTO Version (VersionId) VALUES (3); +INSERT INTO Version (VersionId) VALUES (4); CREATE TABLE Counters ( Counter TEXT NOT NULL, diff --git a/bacula/src/cats/sql_create.c b/bacula/src/cats/sql_create.c index 82239182a4..251f80c017 100644 --- a/bacula/src/cats/sql_create.c +++ b/bacula/src/cats/sql_create.c @@ -186,8 +186,8 @@ db_create_pool_record(B_DB *mdb, POOL_DBR *pr) Mmsg(&mdb->cmd, "INSERT INTO Pool (Name,NumVols,MaxVols,UseOnce,UseCatalog,\ AcceptAnyVolume,AutoPrune,Recycle,VolRetention,VolUseDuration,\ -MaxVolJobs,PoolType,LabelFormat) \ -VALUES ('%s',%u,%u,%d,%d,%d,%d,%d,%s,%s,%u,'%s','%s')", +MaxVolJobs,MaxVolFiles,PoolType,LabelFormat) \ +VALUES ('%s',%u,%u,%d,%d,%d,%d,%d,%s,%s,%u,%u,'%s','%s')", pr->Name, pr->NumVols, pr->MaxVols, pr->UseOnce, pr->UseCatalog, @@ -195,7 +195,7 @@ VALUES ('%s',%u,%u,%d,%d,%d,%d,%d,%s,%s,%u,'%s','%s')", pr->AutoPrune, pr->Recycle, edit_uint64(pr->VolRetention, ed1), edit_uint64(pr->VolUseDuration, ed2), - pr->MaxVolJobs, + pr->MaxVolJobs, pr->MaxVolFiles, pr->PoolType, pr->LabelFormat); Dmsg1(200, "Create Pool: %s\n", mdb->cmd); if (!INSERT_DB(mdb, mdb->cmd)) { @@ -242,11 +242,11 @@ db_create_media_record(B_DB *mdb, MEDIA_DBR *mr) /* Must create it */ Mmsg(&mdb->cmd, -"INSERT INTO Media (VolumeName,MediaType,PoolId,VolMaxBytes,VolCapacityBytes, \ -Recycle,VolRetention,VolStatus,Slot) VALUES ('%s', '%s', %d, %s, %s, %d, %s, '%s', %d)", +"INSERT INTO Media (VolumeName,MediaType,PoolId,MaxVolBytes,VolCapacityBytes, \ +Recycle,VolRetention,VolStatus,Slot) VALUES ('%s','%s',%u,%s,%s,%d,%s,'%s',%d)", mr->VolumeName, mr->MediaType, mr->PoolId, - edit_uint64(mr->VolMaxBytes,ed1), + edit_uint64(mr->MaxVolBytes,ed1), edit_uint64(mr->VolCapacityBytes, ed2), mr->Recycle, edit_uint64(mr->VolRetention, ed3), diff --git a/bacula/src/cats/sql_find.c b/bacula/src/cats/sql_find.c index 0512f8d5c3..89901505e0 100644 --- a/bacula/src/cats/sql_find.c +++ b/bacula/src/cats/sql_find.c @@ -204,8 +204,8 @@ db_find_next_volume(B_DB *mdb, int item, MEDIA_DBR *mr) db_lock(mdb); Mmsg(&mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,\ -VolBytes,VolMounts,VolErrors,VolWrites,VolMaxBytes,VolCapacityBytes,\ -VolRetention,VolUseDuration,MaxVolJobs,Recycle,Slot,\ +VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,\ +VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,Recycle,Slot,\ FirstWritten FROM Media WHERE PoolId=%d AND MediaType='%s' AND VolStatus='%s' \ ORDER BY MediaId", mr->PoolId, mr->MediaType, mr->VolStatus); @@ -244,14 +244,15 @@ ORDER BY MediaId", mr->PoolId, mr->MediaType, mr->VolStatus); mr->VolMounts = atoi(row[6]); mr->VolErrors = atoi(row[7]); mr->VolWrites = atoi(row[8]); - mr->VolMaxBytes = (uint64_t)strtod(row[9], NULL); + 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->Recycle = atoi(row[14]); - mr->Slot = atoi(row[15]); - bstrncpy(mr->cFirstWritten, row[16]!=NULL?row[16]:"", sizeof(mr->cFirstWritten)); + mr->MaxVolFiles = atoi(row[14]); + mr->Recycle = atoi(row[15]); + mr->Slot = atoi(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 787c3503d5..40ff866f39 100644 --- a/bacula/src/cats/sql_get.c +++ b/bacula/src/cats/sql_get.c @@ -482,12 +482,12 @@ int db_get_pool_record(B_DB *mdb, POOL_DBR *pdbr) if (pdbr->PoolId != 0) { /* find by id */ Mmsg(&mdb->cmd, "SELECT PoolId,Name,NumVols,MaxVols,UseOnce,UseCatalog,AcceptAnyVolume,\ -AutoPrune,Recycle,VolRetention,VolUseDuration,MaxVolJobs,\ +AutoPrune,Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,\ PoolType,LabelFormat FROM Pool WHERE Pool.PoolId=%d", pdbr->PoolId); } else { /* find by name */ Mmsg(&mdb->cmd, "SELECT PoolId,Name,NumVols,MaxVols,UseOnce,UseCatalog,AcceptAnyVolume,\ -AutoPrune,Recycle,VolRetention,VolUseDuration,MaxVolJobs,\ +AutoPrune,Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,\ PoolType,LabelFormat FROM Pool WHERE Pool.Name='%s'", pdbr->Name); } @@ -515,8 +515,9 @@ PoolType,LabelFormat FROM Pool WHERE Pool.Name='%s'", pdbr->Name); pdbr->VolRetention = (utime_t)strtod(row[9], NULL); pdbr->VolUseDuration = (utime_t)strtod(row[10], NULL); pdbr->MaxVolJobs = atoi(row[11]); - bstrncpy(pdbr->PoolType, row[12]!=NULL?row[12]:"", sizeof(pdbr->PoolType)); - bstrncpy(pdbr->LabelFormat, row[13]!=NULL?row[13]:"", sizeof(pdbr->LabelFormat)); + pdbr->MaxVolFiles = atoi(row[12]); + bstrncpy(pdbr->PoolType, row[13]!=NULL?row[13]:"", sizeof(pdbr->PoolType)); + bstrncpy(pdbr->LabelFormat, row[14]!=NULL?row[14]:"", sizeof(pdbr->LabelFormat)); stat = pdbr->PoolId; } } @@ -647,14 +648,14 @@ int db_get_media_record(B_DB *mdb, MEDIA_DBR *mr) } if (mr->MediaId != 0) { /* find by id */ Mmsg(&mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,\ -VolBytes,VolMounts,VolErrors,VolWrites,VolMaxBytes,VolCapacityBytes,\ -MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,\ +VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,\ +MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,\ Recycle,Slot, FirstWritten \ FROM Media WHERE MediaId=%d", mr->MediaId); } else { /* find by name */ Mmsg(&mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,\ -VolBytes,VolMounts,VolErrors,VolWrites,VolMaxBytes,VolCapacityBytes,\ -MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,\ +VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,\ +MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,\ Recycle,Slot,FirstWritten \ FROM Media WHERE VolumeName='%s'", mr->VolumeName); } @@ -681,7 +682,7 @@ FROM Media WHERE VolumeName='%s'", mr->VolumeName); mr->VolMounts = atoi(row[6]); mr->VolErrors = atoi(row[7]); mr->VolWrites = atoi(row[8]); - mr->VolMaxBytes = (uint64_t)strtod(row[9], NULL); + mr->MaxVolBytes = (uint64_t)strtod(row[9], NULL); mr->VolCapacityBytes = (uint64_t)strtod(row[10], NULL); bstrncpy(mr->MediaType, row[11]!=NULL?row[11]:"", sizeof(mr->MediaType)); bstrncpy(mr->VolStatus, row[12]!=NULL?row[12]:"", sizeof(mr->VolStatus)); @@ -689,9 +690,10 @@ FROM Media WHERE VolumeName='%s'", mr->VolumeName); mr->VolRetention = (utime_t)strtod(row[14], NULL); mr->VolUseDuration = (utime_t)strtod(row[15], NULL); mr->MaxVolJobs = atoi(row[16]); - mr->Recycle = atoi(row[17]); - mr->Slot = atoi(row[18]); - bstrncpy(mr->cFirstWritten, row[19]!=NULL?row[19]:"", sizeof(mr->cFirstWritten)); + mr->MaxVolFiles = atoi(row[17]); + mr->Recycle = atoi(row[18]); + mr->Slot = atoi(row[19]); + bstrncpy(mr->cFirstWritten, row[20]!=NULL?row[20]:"", sizeof(mr->cFirstWritten)); stat = mr->MediaId; } } else { diff --git a/bacula/src/cats/sql_update.c b/bacula/src/cats/sql_update.c index 845cf6c383..db8960212b 100644 --- a/bacula/src/cats/sql_update.c +++ b/bacula/src/cats/sql_update.c @@ -199,11 +199,11 @@ db_update_media_record(B_DB *mdb, MEDIA_DBR *mr) Mmsg(&mdb->cmd, "UPDATE Media SET VolJobs=%u,\ VolFiles=%u, VolBlocks=%u, VolBytes=%s, VolMounts=%u, VolErrors=%u,\ - VolWrites=%u, VolMaxBytes=%s, LastWritten='%s', VolStatus='%s',\ + VolWrites=%u, MaxVolBytes=%s, LastWritten='%s', VolStatus='%s',\ Slot=%d WHERE VolumeName='%s'", mr->VolJobs, mr->VolFiles, mr->VolBlocks, edit_uint64(mr->VolBytes, ed1), mr->VolMounts, mr->VolErrors, mr->VolWrites, - edit_uint64(mr->VolMaxBytes, ed2), dt, + edit_uint64(mr->MaxVolBytes, ed2), dt, mr->VolStatus, mr->Slot, mr->VolumeName); Dmsg1(400, "%s\n", mdb->cmd); diff --git a/bacula/src/dird/backup.c b/bacula/src/dird/backup.c index 193cdbbfa5..8213c6b0d0 100644 --- a/bacula/src/dird/backup.c +++ b/bacula/src/dird/backup.c @@ -386,7 +386,7 @@ static void backup_cleanup(JCR *jcr, int TermCode, char *since) } } - Jmsg(jcr, msg_type, 0, _("%s\n\ + Jmsg(jcr, msg_type, 0, _("Bacula " VERSION " (" LSMDATE "): %s\n\ JobId: %d\n\ Job: %s\n\ FileSet: %s\n\ diff --git a/bacula/src/dird/catreq.c b/bacula/src/dird/catreq.c index 467eea555f..f8ef8ed748 100644 --- a/bacula/src/dird/catreq.c +++ b/bacula/src/dird/catreq.c @@ -45,19 +45,20 @@ static char Find_media[] = "CatReq Job=%127s FindMedia=%d\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\ - VolJobs=%d VolFiles=%d VolBlocks=%d VolBytes=%" lld " VolMounts=%d\ - VolErrors=%d VolWrites=%d VolMaxBytes=%" lld " EndTime=%d VolStatus=%10s\ + VolJobs=%u VolFiles=%u VolBlocks=%u VolBytes=%" lld " VolMounts=%u\ + VolErrors=%u VolWrites=%u MaxVolBytes=%" lld " EndTime=%d VolStatus=%10s\ Slot=%d relabel=%d\n"; static char Create_job_media[] = "CatReq Job=%127s CreateJobMedia \ - FirstIndex=%d LastIndex=%d StartFile=%d EndFile=%d \ - StartBlock=%d EndBlock=%d\n"; + FirstIndex=%u LastIndex=%u StartFile=%u EndFile=%u \ + StartBlock=%u EndBlock=%u\n"; /* Responses sent to Storage daemon */ -static char OK_media[] = "1000 OK VolName=%s VolJobs=%d VolFiles=%d\ - VolBlocks=%d VolBytes=%" lld " VolMounts=%d VolErrors=%d VolWrites=%d\ - VolMaxBytes=%" lld " VolCapacityBytes=%" lld " VolStatus=%s Slot=%d\n"; +static char OK_media[] = "1000 OK VolName=%s VolJobs=%u VolFiles=%u\ + VolBlocks=%u VolBytes=%s VolMounts=%u VolErrors=%u VolWrites=%u\ + MaxVolBytes=%s VolCapacityBytes=%s VolStatus=%s Slot=%d\ + MaxVolJobs=%u MaxVolFiles=%u\n"; static char OK_update[] = "1000 OK UpdateMedia\n"; @@ -66,13 +67,14 @@ static char OK_update[] = "1000 OK UpdateMedia\n"; void catalog_request(JCR *jcr, BSOCK *bs, char *msg) { - MEDIA_DBR mr; + MEDIA_DBR mr, sdmr; JOBMEDIA_DBR jm; char Job[MAX_NAME_LENGTH]; int index, ok, relabel, writing, retry = 0; POOLMEM *omsg; memset(&mr, 0, sizeof(mr)); + memset(&sdmr, 0, sizeof(sdmr)); memset(&jm, 0, sizeof(jm)); /* @@ -106,11 +108,11 @@ next_volume: } } /* Check if use duration has expired */ - if (ok && jcr->pool->VolUseDuration > 0 && + if (ok && mr.VolUseDuration > 0 && strcmp(mr.VolStatus, "Recycle") != 0) { utime_t now = time(NULL); utime_t start = str_to_utime(mr.cFirstWritten); - if (start > 0 && jcr->pool->VolUseDuration <= (now - start)) { + if (start > 0 && mr.VolUseDuration <= (now - start)) { Dmsg4(100, "Duration=%d now=%d start=%d now-start=%d\n", (int)jcr->pool->VolUseDuration, (int)now, (int)start, (int)(now-start)); Jmsg(jcr, M_INFO, 0, _("Max configured use duration exceeded. " @@ -133,13 +135,16 @@ next_volume: * Send Find Media response to Storage daemon */ if (ok) { + char ed1[50], ed2[50], ed3[50]; jcr->MediaId = mr.MediaId; pm_strcpy(&jcr->VolumeName, mr.VolumeName); bash_spaces(mr.VolumeName); bnet_fsend(bs, OK_media, mr.VolumeName, mr.VolJobs, - mr.VolFiles, mr.VolBlocks, mr.VolBytes, mr.VolMounts, mr.VolErrors, - mr.VolWrites, mr.VolMaxBytes, mr.VolCapacityBytes, - mr.VolStatus, mr.Slot); + mr.VolFiles, mr.VolBlocks, edit_uint64(mr.VolBytes, ed1), + mr.VolMounts, mr.VolErrors, mr.VolWrites, + edit_uint64(mr.MaxVolBytes, ed2), + edit_uint64(mr.VolCapacityBytes, ed3), + mr.VolStatus, mr.Slot, mr.MaxVolJobs, mr.MaxVolFiles); } else { bnet_fsend(bs, "1999 No Media\n"); } @@ -157,7 +162,7 @@ next_volume: int VolSuitable = 0; jcr->MediaId = mr.MediaId; Dmsg1(120, "VolumeInfo MediaId=%d\n", jcr->MediaId); - strcpy(jcr->VolumeName, mr.VolumeName); + pm_strcpy(&jcr->VolumeName, mr.VolumeName); if (!writing) { VolSuitable = 1; /* accept anything for read */ } else { @@ -175,14 +180,17 @@ next_volume: } } if (VolSuitable) { + char ed1[50], ed2[50], ed3[50]; /* * Send Find Media response to Storage daemon */ bash_spaces(mr.VolumeName); bnet_fsend(bs, OK_media, mr.VolumeName, mr.VolJobs, - mr.VolFiles, mr.VolBlocks, mr.VolBytes, mr.VolMounts, mr.VolErrors, - mr.VolWrites, mr.VolMaxBytes, mr.VolCapacityBytes, - mr.VolStatus, mr.Slot); + mr.VolFiles, mr.VolBlocks, edit_uint64(mr.VolBytes, ed1), + mr.VolMounts, mr.VolErrors, mr.VolWrites, + edit_uint64(mr.MaxVolBytes, ed2), + edit_uint64(mr.VolCapacityBytes, ed3), + mr.VolStatus, mr.Slot, mr.MaxVolJobs, mr.MaxVolFiles); Dmsg5(200, "get_media_record PoolId=%d wanted %d, Status=%s, Slot=%d \ MediaType=%s\n", mr.PoolId, jcr->PoolId, mr.VolStatus, mr.Slot, mr.MediaType); } else { @@ -199,18 +207,37 @@ MediaType=%s\n", mr.PoolId, jcr->PoolId, mr.VolStatus, mr.Slot, mr.MediaType); * Request to update Media record. Comes typically at the end * of a Storage daemon Job Session */ - } else if (sscanf(bs->msg, Update_media, &Job, &mr.VolumeName, &mr.VolJobs, - &mr.VolFiles, &mr.VolBlocks, &mr.VolBytes, &mr.VolMounts, &mr.VolErrors, - &mr.VolWrites, &mr.VolMaxBytes, &mr.LastWritten, &mr.VolStatus, - &mr.Slot, &relabel) == 14) { + } else if (sscanf(bs->msg, Update_media, &Job, &sdmr.VolumeName, &sdmr.VolJobs, + &sdmr.VolFiles, &sdmr.VolBlocks, &sdmr.VolBytes, &sdmr.VolMounts, &sdmr.VolErrors, + &sdmr.VolWrites, &sdmr.MaxVolBytes, &sdmr.LastWritten, &sdmr.VolStatus, + &sdmr.Slot, &relabel) == 14) { + + bstrncpy(mr.VolumeName, sdmr.VolumeName, sizeof(mr.VolumeName)); /* copy Volume name */ + if (!db_get_media_record(jcr->db, &mr)) { + Jmsg(jcr, M_ERROR, 0, _("Unable to get Media record for Volume %s: ERR=%s\n"), + mr.VolumeName, db_strerror(jcr->db)); + bnet_fsend(bs, "1991 Catalog Request failed: %s", db_strerror(jcr->db)); + return; + } + /* Copy updated values to original media record */ + mr.VolJobs = sdmr.VolJobs; + mr.VolFiles = sdmr.VolFiles; + mr.VolBlocks = sdmr.VolBlocks; + mr.VolBytes = sdmr.VolBytes; + mr.VolMounts = sdmr.VolMounts; + mr.VolErrors = sdmr.VolErrors; + mr.VolWrites = sdmr.VolWrites; + mr.LastWritten = sdmr.LastWritten; + bstrncpy(mr.VolStatus, sdmr.VolStatus, sizeof(mr.VolStatus)); + mr.Slot = sdmr.Slot; /* * Update Media Record */ /* First handle Max Volume Bytes */ - if ((mr.VolMaxBytes > 0 && mr.VolBytes >= mr.VolMaxBytes)) { - Jmsg(jcr, M_INFO, 0, _("Max configure Volume bytes exceeded. " + if ((mr.MaxVolBytes > 0 && mr.VolBytes >= mr.MaxVolBytes)) { + Jmsg(jcr, M_INFO, 0, _("Max Volume bytes exceeded. " "Marking Volume \"%s\" as Full.\n"), mr.VolumeName); strcpy(mr.VolStatus, "Full"); @@ -221,35 +248,31 @@ MediaType=%s\n", mr.PoolId, jcr->PoolId, mr.VolStatus, mr.Slot, mr.MediaType); strcpy(mr.VolStatus, "Used"); /* Now see if Max Jobs written to volume */ - } else if (jcr->pool->MaxVolJobs > 0 && - jcr->pool->MaxVolJobs <= mr.VolJobs) { - Jmsg(jcr, M_INFO, 0, _("Max configured Volume jobs exceeded. " + } else if (mr.MaxVolJobs > 0 && mr.MaxVolJobs <= mr.VolJobs) { + Jmsg(jcr, M_INFO, 0, _("Max Volume jobs exceeded. " + "Marking Volume \"%s\" as Used.\n"), mr.VolumeName); + strcpy(mr.VolStatus, "Used"); + + /* Now see if Max Files written to volume */ + } else if (mr.MaxVolFiles > 0 && mr.MaxVolFiles <= mr.VolFiles) { + Jmsg(jcr, M_INFO, 0, _("Max Volume files exceeded. " "Marking Volume \"%s\" as Used.\n"), mr.VolumeName); strcpy(mr.VolStatus, "Used"); /* Finally, check Use duration expiration */ - } else if (jcr->pool->VolUseDuration > 0) { - MEDIA_DBR omr; - memset(&omr, 0, sizeof(omr)); /* clear media record */ - strcpy(omr.VolumeName, mr.VolumeName); /* copy Volume name */ - if (db_get_media_record(jcr->db, &omr)) { - utime_t start; - utime_t now = time(NULL); - start = str_to_utime(omr.cFirstWritten); - /* See if Vol Use has expired */ - if (start > 0 && jcr->pool->VolUseDuration <= (now - start)) { - Jmsg(jcr, M_INFO, 0, _("Max configured use duration exceeded. " - "Marking Volume \"%s\"as Used.\n"), mr.VolumeName); - strcpy(mr.VolStatus, "Used"); /* yes, mark as used */ - } - } else { - Jmsg(jcr, M_ERROR, 0, _("Unable to get Media record for Volume %s: ERR=%s\n"), - mr.VolumeName, db_strerror(jcr->db)); + } else if (mr.VolUseDuration > 0) { + utime_t start; + utime_t now = time(NULL); + start = str_to_utime(mr.cFirstWritten); + /* See if Vol Use has expired */ + if (start > 0 && mr.VolUseDuration <= (now - start)) { + Jmsg(jcr, M_INFO, 0, _("Max configured use duration exceeded. " + "Marking Volume \"%s\"as Used.\n"), mr.VolumeName); + strcpy(mr.VolStatus, "Used"); /* yes, mark as used */ } } - Dmsg2(200, "db_update_media_record. Stat=%s Vol=%s\n", - mr.VolStatus, mr.VolumeName); + Dmsg2(200, "db_update_media_record. Stat=%s Vol=%s\n", mr.VolStatus, mr.VolumeName); if (db_update_media_record(jcr->db, &mr)) { bnet_fsend(bs, OK_update); Dmsg0(190, "send OK\n"); @@ -271,7 +294,7 @@ MediaType=%s\n", mr.PoolId, jcr->PoolId, mr.VolStatus, mr.Slot, mr.MediaType); jm.MediaId = jcr->MediaId; Dmsg6(100, "create_jobmedia JobId=%d MediaId=%d SF=%d EF=%d FI=%d LI=%d\n", jm.JobId, jm.MediaId, jm.StartFile, jm.EndFile, jm.FirstIndex, jm.LastIndex); - if(!db_create_jobmedia_record(jcr->db, &jm)) { + if (!db_create_jobmedia_record(jcr->db, &jm)) { Jmsg(jcr, M_ERROR, 0, _("Catalog error creating JobMedia record. %s"), db_strerror(jcr->db)); bnet_fsend(bs, "1991 Update JobMedia error\n"); @@ -284,6 +307,7 @@ MediaType=%s\n", mr.PoolId, jcr->PoolId, mr.VolStatus, mr.Slot, mr.MediaType); omsg = get_memory(bs->msglen+1); pm_strcpy(&omsg, bs->msg); bnet_fsend(bs, "1990 Invalid Catalog Request: %s", omsg); + Jmsg1(jcr, M_ERROR, 0, _("Invalid Catalog request: %s"), omsg); free_memory(omsg); } Dmsg1(120, ">CatReq response: %s", bs->msg); diff --git a/bacula/src/dird/dird_conf.c b/bacula/src/dird/dird_conf.c index 367a13d49d..f6dc17c82d 100644 --- a/bacula/src/dird/dird_conf.c +++ b/bacula/src/dird/dird_conf.c @@ -235,6 +235,7 @@ static struct res_items pool_items[] = { {"usevolumeonce", store_yesno, ITEM(res_pool.use_volume_once), 1, 0, 0}, {"maximumvolumes", store_pint, ITEM(res_pool.max_volumes), 0, 0, 0}, {"maximumvolumejobs", store_pint, ITEM(res_pool.MaxVolJobs), 0, 0, 0}, + {"maximumvolumefiles", store_pint, ITEM(res_pool.MaxVolFiles), 0, 0, 0}, {"acceptanyvolume", store_yesno, ITEM(res_pool.accept_any_volume), 1, ITEM_DEFAULT, 1}, {"catalogfiles", store_yesno, ITEM(res_pool.catalog_files), 1, ITEM_DEFAULT, 1}, {"volumeretention", store_time, ITEM(res_pool.VolRetention), 0, ITEM_DEFAULT, 60*60*24*365}, @@ -1226,33 +1227,30 @@ static void scan_include_options(LEX *lc, int keyword, char *opts, int optlen) option[0] = 0; /* default option = none */ opts[0] = option[2] = 0; /* terminate options */ - for (;;) { - token = lex_get_token(lc, T_NAME); /* expect at least one option */ - if (keyword == INC_KW_VERIFY) { /* special case */ - /* ***FIXME**** ensure these are in permitted set */ - bstrncat(opts, "V", optlen); /* indicate Verify */ - bstrncat(opts, lc->str, optlen); - bstrncat(opts, ":", optlen); /* terminate it */ - } else { - for (i=0; FS_options[i].name; i++) { - if (strcasecmp(lc->str, FS_options[i].name) == 0 && FS_options[i].keyword == keyword) { - /* NOTE! maximum 2 letters here or increase option[3] */ - option[0] = FS_options[i].option[0]; - option[1] = FS_options[i].option[1]; - i = 0; - break; - } - } - if (i != 0) { - scan_err1(lc, "Expected a FileSet option keyword, got: %s", lc->str); + token = lex_get_token(lc, T_NAME); /* expect at least one option */ + if (keyword == INC_KW_VERIFY) { /* special case */ + /* ***FIXME**** ensure these are in permitted set */ + bstrncat(opts, "V", optlen); /* indicate Verify */ + bstrncat(opts, lc->str, optlen); + bstrncat(opts, ":", optlen); /* terminate it */ + } else { + for (i=0; FS_options[i].name; i++) { + if (strcasecmp(lc->str, FS_options[i].name) == 0 && FS_options[i].keyword == keyword) { + /* NOTE! maximum 2 letters here or increase option[3] */ + option[0] = FS_options[i].option[0]; + option[1] = FS_options[i].option[1]; + i = 0; + break; } - bstrncat(opts, option, optlen); } - - /* check if more options are specified */ - if (lc->ch != ',') { - break; /* no, get out */ + if (i != 0) { + scan_err1(lc, "Expected a FileSet option keyword, got:%s:", lc->str); } + bstrncat(opts, option, optlen); + } + + /* If option terminated by comma, eat it */ + if (lc->ch == ',') { token = lex_get_token(lc, T_ALL); /* yes, eat comma */ } } diff --git a/bacula/src/dird/dird_conf.h b/bacula/src/dird/dird_conf.h index 7c588252a2..87ecba0c3c 100644 --- a/bacula/src/dird/dird_conf.h +++ b/bacula/src/dird/dird_conf.h @@ -249,6 +249,7 @@ struct s_res_pool { utime_t VolRetention; /* volume retention period in seconds */ utime_t VolUseDuration; /* duration volume can be used */ uint32_t MaxVolJobs; /* Maximum jobs on the volume */ + uint32_t MaxVolFiles; /* Maximum files on the volume */ int AutoPrune; /* default for pool auto prune */ int Recycle; /* default for media recycle yes/no */ }; diff --git a/bacula/src/dird/protos.h b/bacula/src/dird/protos.h index 3621473616..23fbbefe93 100644 --- a/bacula/src/dird/protos.h +++ b/bacula/src/dird/protos.h @@ -46,13 +46,13 @@ extern char *level_to_str(int level); /* fd_cmds.c */ extern int connect_to_file_daemon(JCR *jcr, int retry_interval, - int max_retry_time, int verbose); + int max_retry_time, int verbose); extern int send_include_list(JCR *jcr); extern int send_exclude_list(JCR *jcr); extern int get_attributes_and_put_in_catalog(JCR *jcr); extern int get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId); extern int put_file_into_catalog(JCR *jcr, long file_index, char *fname, - char *link, char *attr, int stream); + char *link, char *attr, int stream); /* job.c */ extern void set_jcr_defaults(JCR *jcr, JOB *job); @@ -65,7 +65,7 @@ extern void mount_request(JCR *jcr, BSOCK *bs, char *buf); /* msgchan.c */ extern int connect_to_storage_daemon(JCR *jcr, int retry_interval, - int max_retry_time, int verbose); + int max_retry_time, int verbose); extern int start_storage_daemon_job(JCR *jcr); extern int start_storage_daemon_message_thread(JCR *jcr); extern int32_t bget_msg(BSOCK *bs, int type); diff --git a/bacula/src/dird/restore.c b/bacula/src/dird/restore.c index f702c620a6..f1d132aedb 100644 --- a/bacula/src/dird/restore.c +++ b/bacula/src/dird/restore.c @@ -314,7 +314,7 @@ static void restore_cleanup(JCR *jcr, int TermCode) bstrftime(edt, sizeof(edt), jcr->jr.EndTime); kbps = (double)jcr->jr.JobBytes / (1000 * (jcr->jr.EndTime - jcr->jr.StartTime)); - Jmsg(jcr, msg_type, 0, _("%s\n\ + Jmsg(jcr, msg_type, 0, _("Bacula " VERSION " (" LSMDATE "): %s\n\ JobId: %d\n\ Job: %s\n\ Client: %s\n\ diff --git a/bacula/src/dird/ua.h b/bacula/src/dird/ua.h index 61a5bbd967..1d2b2938c3 100644 --- a/bacula/src/dird/ua.h +++ b/bacula/src/dird/ua.h @@ -77,10 +77,10 @@ int select_pool_dbr(UAContext *ua, POOL_DBR *pr); void start_prompt(UAContext *ua, char *msg); void add_prompt(UAContext *ua, char *prompt); -int do_prompt(UAContext *ua, char *msg, 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 get_media_type(UAContext *ua, char *MediaType, int max_media); int get_pool_dbr(UAContext *ua, POOL_DBR *pr); POOL *get_pool_resource(UAContext *ua); CLIENT *get_client_resource(UAContext *ua); diff --git a/bacula/src/dird/ua_cmds.c b/bacula/src/dird/ua_cmds.c index daf9720d32..999745f491 100644 --- a/bacula/src/dird/ua_cmds.c +++ b/bacula/src/dird/ua_cmds.c @@ -185,10 +185,8 @@ static int addcmd(UAContext *ua, char *cmd) /* Get media type */ if ((store = get_storage_resource(ua, cmd)) != NULL) { strcpy(mr.MediaType, store->media_type); - } else { - if (!get_media_type(ua, mr.MediaType)) { - return 1; - } + } else if (!get_media_type(ua, mr.MediaType, sizeof(mr.MediaType))) { + return 1; } if (pr.MaxVols == 0) { @@ -266,6 +264,7 @@ getVolName: mr.VolRetention = pr.VolRetention; mr.VolUseDuration = pr.VolUseDuration; mr.MaxVolJobs = pr.MaxVolJobs; + mr.MaxVolFiles = pr.MaxVolFiles; for (i=startnum; i < num+startnum; i++) { sprintf(mr.VolumeName, name, i); mr.Slot = slot++; @@ -381,7 +380,7 @@ static int cancelcmd(UAContext *ua, char *cmd) } unlock_jcr_chain(); - if (do_prompt(ua, _("Choose Job to cancel"), JobName) < 0) { + if (do_prompt(ua, _("Choose Job to cancel"), JobName, sizeof(JobName)) < 0) { return 1; } if (njobs == 1) { @@ -480,6 +479,7 @@ int create_pool(B_DB *db, POOL *pool) pr.VolRetention = pool->VolRetention; pr.VolUseDuration = pool->VolUseDuration; pr.MaxVolJobs = pool->MaxVolJobs; + pr.MaxVolFiles = pool->MaxVolFiles; pr.AutoPrune = pool->AutoPrune; if (pool->label_format) { strcpy(pr.LabelFormat, pool->label_format); @@ -568,7 +568,7 @@ static int updatecmd(UAContext *ua, char *cmd) start_prompt(ua, _("Update choice:\n")); add_prompt(ua, _("Volume parameters")); add_prompt(ua, _("Pool from resource")); - switch (do_prompt(ua, _("Choose catalog item to update"), NULL)) { + switch (do_prompt(ua, _("Choose catalog item to update"), NULL, 0)) { case 0: update_volume(ua); break; @@ -613,10 +613,11 @@ static int update_volume(UAContext *ua) add_prompt(ua, _("Volume Retention Period")); add_prompt(ua, _("Volume Use Duration")); add_prompt(ua, _("Maximum Volume Jobs")); + add_prompt(ua, _("Maximum Volume Files")); add_prompt(ua, _("Recycle Flag")); add_prompt(ua, _("Slot")); add_prompt(ua, _("Done")); - switch (do_prompt(ua, _("Select parameter to modify"), NULL)) { + switch (do_prompt(ua, _("Select parameter to modify"), NULL, 0)) { case 0: /* Volume Status */ /* Modify Volume Status */ bsendmsg(ua, _("Current value is: %s\n"), mr.VolStatus); @@ -630,10 +631,10 @@ static int update_volume(UAContext *ua) add_prompt(ua, "Recycle"); } add_prompt(ua, "Read-Only"); - if (do_prompt(ua, _("Choose new Volume Status"), ua->cmd) < 0) { + if (do_prompt(ua, _("Choose new Volume Status"), ua->cmd, sizeof(mr.VolStatus)) < 0) { return 1; } - strcpy(mr.VolStatus, ua->cmd); + bstrncpy(mr.VolStatus, ua->cmd, sizeof(mr.VolStatus)); query = get_pool_memory(PM_MESSAGE); Mmsg(&query, "UPDATE Media SET VolStatus='%s' WHERE MediaId=%u", mr.VolStatus, mr.MediaId); @@ -702,8 +703,30 @@ static int update_volume(UAContext *ua) free_pool_memory(query); break; + case 4: /* Max Files */ + int32_t maxfiles; + bsendmsg(ua, _("Current value is: %u\n"), mr.MaxVolFiles); + if (!get_cmd(ua, _("Enter new Maximum Files: "))) { + return 0; + } + maxfiles = atoi(ua->cmd); + if (maxfiles < 0) { + bsendmsg(ua, _("Invalid number, it must be 0 or greater\n")); + break; + } + query = get_pool_memory(PM_MESSAGE); + Mmsg(&query, "UPDATE Media SET MaxVolFiles=%u WHERE MediaId=%u", + maxfiles, mr.MediaId); + if (!db_sql_query(ua->db, query, NULL, NULL)) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + } else { + bsendmsg(ua, "New value is: %u\n", maxfiles); + } + free_pool_memory(query); + break; + - case 4: /* Recycle */ + case 5: /* Recycle */ int recycle; bsendmsg(ua, _("Current value is: %s\n"), mr.Recycle==1?_("yes"):_("no")); @@ -727,7 +750,7 @@ static int update_volume(UAContext *ua) free_pool_memory(query); break; - case 5: /* Slot */ + case 6: /* Slot */ int slot; bsendmsg(ua, _("Current value is: %d\n"), mr.Slot); if (!get_cmd(ua, _("Enter new Slot: "))) { @@ -794,6 +817,7 @@ static int update_pool(UAContext *ua) pr.VolRetention = pool->VolRetention; pr.VolUseDuration = pool->VolUseDuration; pr.MaxVolJobs = pool->MaxVolJobs; + pr.MaxVolFiles = pool->MaxVolFiles; if (pool->label_format) { strcpy(pr.LabelFormat, pool->label_format); } else { @@ -1010,7 +1034,7 @@ static int setdebugcmd(UAContext *ua, char *cmd) add_prompt(ua, _("Storage")); add_prompt(ua, _("Client")); add_prompt(ua, _("All")); - switch(do_prompt(ua, _("Select daemon type to set debug level"), NULL)) { + switch(do_prompt(ua, _("Select daemon type to set debug level"), NULL, 0)) { case 0: /* Director */ debug_level = level; break; @@ -1240,6 +1264,7 @@ gotVol: mr.VolRetention = pr.VolRetention; mr.VolUseDuration = pr.VolUseDuration; mr.MaxVolJobs = pr.MaxVolJobs; + mr.MaxVolFiles = pr.MaxVolFiles; if (db_create_media_record(ua->db, &mr)) { bsendmsg(ua, _("Media record for Volume=%s successfully created.\n"), mr.VolumeName); diff --git a/bacula/src/dird/ua_prune.c b/bacula/src/dird/ua_prune.c index 11f3e5748e..52a336fa86 100644 --- a/bacula/src/dird/ua_prune.c +++ b/bacula/src/dird/ua_prune.c @@ -32,11 +32,13 @@ #include "dird.h" #include "ua.h" +/* Imported functions */ +int mark_media_purged(UAContext *ua, MEDIA_DBR *mr); + /* Forward referenced functions */ int prune_files(UAContext *ua, CLIENT *client); int prune_jobs(UAContext *ua, CLIENT *client, int JobType); int prune_volume(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr); -static int mark_media_purged(UAContext *ua, MEDIA_DBR *mr); #define MAX_DEL_LIST_LEN 1000000 @@ -506,7 +508,7 @@ int prune_volume(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr) if (cnt.count == 0) { if (ua->verbose) { - bsendmsg(ua, "There are no Jobs associated with Volume %s. It is purged.\n", + bsendmsg(ua, "There are no Jobs associated with Volume %s. Marking it purged.\n", mr->VolumeName); } stat = mark_media_purged(ua, mr); @@ -575,19 +577,3 @@ bail_out: free_pool_memory(query); return stat; } - -static int mark_media_purged(UAContext *ua, MEDIA_DBR *mr) -{ - if (strcmp(mr->VolStatus, "Append") == 0 || - strcmp(mr->VolStatus, "Full") == 0) { - strcpy(mr->VolStatus, "Purged"); - if (!db_update_media_record(ua->db, mr)) { - if (ua->verbose) { - bsendmsg(ua, "%s", db_strerror(ua->db)); - } - return 0; - } - return 1; - } - return strcpy(mr->VolStatus, "Purged") == 0; -} diff --git a/bacula/src/dird/ua_purge.c b/bacula/src/dird/ua_purge.c index f544a79081..e45b89d334 100644 --- a/bacula/src/dird/ua_purge.c +++ b/bacula/src/dird/ua_purge.c @@ -41,8 +41,7 @@ int purge_jobs_from_client(UAContext *ua, CLIENT *client); void purge_files_from_volume(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr ); void purge_jobs_from_volume(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr); void purge_files_from_job(UAContext *ua, JOB_DBR *jr); -static int mark_media_purged(UAContext *ua, MEDIA_DBR *mr); - +int mark_media_purged(UAContext *ua, MEDIA_DBR *mr); #define MAX_DEL_LIST_LEN 1000000 @@ -448,7 +447,7 @@ void purge_jobs_from_volume(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr) } if (cnt.count == 0) { - bsendmsg(ua, "There are no Jobs associated with Volume %s. It is purged.\n", + bsendmsg(ua, "There are no Jobs associated with Volume %s. Marking it purged.\n", mr->VolumeName); if (!mark_media_purged(ua, mr)) { goto bail_out; @@ -497,15 +496,23 @@ bail_out: free_pool_memory(query); } -static int mark_media_purged(UAContext *ua, MEDIA_DBR *mr) +/* + * IF volume status is Append, Full, or Used, mark it Purged + * Purged volumes can then be recycled (if enabled). + */ +int mark_media_purged(UAContext *ua, MEDIA_DBR *mr) { if (strcmp(mr->VolStatus, "Append") == 0 || - strcmp(mr->VolStatus, "Full") == 0) { + strcmp(mr->VolStatus, "Full") == 0 || + strcmp(mr->VolStatus, "Used") == 0) { strcpy(mr->VolStatus, "Purged"); if (!db_update_media_record(ua->db, mr)) { - bsendmsg(ua, "%s", db_strerror(ua->db)); + if (ua->verbose) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + } return 0; } + return 1; } - return 1; + return strcpy(mr->VolStatus, "Purged") == 0; } diff --git a/bacula/src/dird/ua_restore.c b/bacula/src/dird/ua_restore.c index 68c050f05d..6266ab4ea0 100644 --- a/bacula/src/dird/ua_restore.c +++ b/bacula/src/dird/ua_restore.c @@ -306,7 +306,7 @@ static int user_select_jobids(UAContext *ua, JobIds *ji) add_prompt(ua, list[i]); } done = 1; - switch (do_prompt(ua, "Select item: ", NULL)) { + switch (do_prompt(ua, "Select item: ", NULL, 0)) { case -1: /* error */ return 0; case 0: /* list last 20 Jobs run */ @@ -361,7 +361,8 @@ static int user_select_jobids(UAContext *ua, JobIds *ji) if (!db_sql_query(ua->db, query, fileset_handler, (void *)ua)) { bsendmsg(ua, "%s\n", db_strerror(ua->db)); } - if (do_prompt(ua, _("Select FileSet resource"), fileset_name) < 0) { + if (do_prompt(ua, _("Select FileSet resource"), + fileset_name, sizeof(fileset_name)) < 0) { free_pool_memory(query); return 0; } @@ -1195,7 +1196,7 @@ static void get_storage_from_mediatype(UAContext *ua, NAME_LIST *name_list, JobI } } UnlockRes(); - do_prompt(ua, _("Select Storage resource"), name); + do_prompt(ua, _("Select Storage resource"), name, sizeof(name)); ji->store = (STORE *)GetResWithName(R_STORAGE, name); if (!ji->store) { bsendmsg(ua, _("\nWarning. Unable to find Storage resource for\n" diff --git a/bacula/src/dird/ua_run.c b/bacula/src/dird/ua_run.c index 84e5b8c283..76fad86336 100644 --- a/bacula/src/dird/ua_run.c +++ b/bacula/src/dird/ua_run.c @@ -403,7 +403,7 @@ JobId: %s\n"), add_prompt(ua, _("Replace")); /* 7 */ add_prompt(ua, _("JobId")); /* 8 */ } - switch (do_prompt(ua, _("Select parameter to modify"), NULL)) { + switch (do_prompt(ua, _("Select parameter to modify"), NULL, 0)) { case 0: /* Level */ if (jcr->JobType == JT_BACKUP) { @@ -413,7 +413,7 @@ JobId: %s\n"), add_prompt(ua, _("Differential")); add_prompt(ua, _("Level")); add_prompt(ua, _("Since")); - switch (do_prompt(ua, _("Select level"), NULL)) { + switch (do_prompt(ua, _("Select level"), NULL, 0)) { case 0: jcr->JobLevel = L_FULL; break; @@ -439,7 +439,7 @@ JobId: %s\n"), add_prompt(ua, _("Verify Catalog")); add_prompt(ua, _("Verify Volume")); add_prompt(ua, _("Verify Volume Data")); - switch (do_prompt(ua, _("Select level"), NULL)) { + switch (do_prompt(ua, _("Select level"), NULL, 0)) { case 0: jcr->JobLevel = L_VERIFY_INIT; break; @@ -533,7 +533,7 @@ JobId: %s\n"), for (i=0; ReplaceOptions[i].name; i++) { add_prompt(ua, ReplaceOptions[i].name); } - opt = do_prompt(ua, _("Select replace option"), NULL); + opt = do_prompt(ua, _("Select replace option"), NULL, 0); if (opt <= 0) { jcr->replace = ReplaceOptions[opt].token; } diff --git a/bacula/src/dird/ua_select.c b/bacula/src/dird/ua_select.c index d9ed6a3f13..0e982291e1 100644 --- a/bacula/src/dird/ua_select.c +++ b/bacula/src/dird/ua_select.c @@ -35,14 +35,6 @@ /* Imported variables */ -/* Exported functions */ - -int do_prompt(UAContext *ua, char *msg, char *prompt); -void add_prompt(UAContext *ua, char *prompt); -void start_prompt(UAContext *ua, char *msg); -STORE *select_storage_resource(UAContext *ua); -JOB *select_job_resource(UAContext *ua); - /* * Confirm a retention period */ @@ -106,7 +98,7 @@ int do_keyword_prompt(UAContext *ua, char *msg, char **list) for (i=0; list[i]; i++) { add_prompt(ua, list[i]); } - return do_prompt(ua, msg, NULL); + return do_prompt(ua, msg, NULL, 0); } @@ -124,7 +116,7 @@ STORE *select_storage_resource(UAContext *ua) add_prompt(ua, store->hdr.name); } UnlockRes(); - do_prompt(ua, _("Select Storage resource"), name); + do_prompt(ua, _("Select Storage resource"), name, sizeof(name)); store = (STORE *)GetResWithName(R_STORAGE, name); return store; } @@ -143,7 +135,7 @@ FILESET *select_fileset_resource(UAContext *ua) add_prompt(ua, fs->hdr.name); } UnlockRes(); - do_prompt(ua, _("Select FileSet resource"), name); + do_prompt(ua, _("Select FileSet resource"), name, sizeof(name)); fs = (FILESET *)GetResWithName(R_FILESET, name); return fs; } @@ -171,7 +163,7 @@ CAT *get_catalog_resource(UAContext *ua) add_prompt(ua, catalog->hdr.name); } UnlockRes(); - do_prompt(ua, _("Select Catalog resource"), name); + do_prompt(ua, _("Select Catalog resource"), name, sizeof(name)); catalog = (CAT *)GetResWithName(R_CATALOG, name); } return catalog; @@ -192,7 +184,7 @@ JOB *select_job_resource(UAContext *ua) add_prompt(ua, job->hdr.name); } UnlockRes(); - do_prompt(ua, _("Select Job resource"), name); + do_prompt(ua, _("Select Job resource"), name, sizeof(name)); job = (JOB *)GetResWithName(R_JOB, name); return job; } @@ -213,7 +205,7 @@ JOB *select_restore_job_resource(UAContext *ua) } } UnlockRes(); - do_prompt(ua, _("Select Restore Job"), name); + do_prompt(ua, _("Select Restore Job"), name, sizeof(name)); job = (JOB *)GetResWithName(R_JOB, name); return job; } @@ -234,7 +226,7 @@ CLIENT *select_client_resource(UAContext *ua) add_prompt(ua, client->hdr.name); } UnlockRes(); - do_prompt(ua, _("Select Client (File daemon) resource"), name); + do_prompt(ua, _("Select Client (File daemon) resource"), name, sizeof(name)); client = (CLIENT *)GetResWithName(R_CLIENT, name); return client; } @@ -284,7 +276,7 @@ int get_pool_dbr(UAContext *ua, POOL_DBR *pr) } for (i=1; iargc; i++) { if (strcasecmp(ua->argk[i], _("pool")) == 0 && ua->argv[i]) { - strcpy(pr->Name, ua->argv[i]); + bstrncpy(pr->Name, ua->argv[i], sizeof(pr->Name)); if (!db_get_pool_record(ua->db, pr)) { bsendmsg(ua, _("Could not find Pool %s: ERR=%s"), ua->argv[i], db_strerror(ua->db)); @@ -330,11 +322,11 @@ int select_pool_dbr(UAContext *ua, POOL_DBR *pr) add_prompt(ua, opr.Name); } free(ids); - if (do_prompt(ua, _("Select the Pool"), name) < 0) { + if (do_prompt(ua, _("Select the Pool"), name, sizeof(name)) < 0) { return 0; } memset(&opr, 0, sizeof(pr)); - strcpy(opr.Name, name); + bstrncpy(opr.Name, name, sizeof(opr.Name)); if (!db_get_pool_record(ua->db, &opr)) { bsendmsg(ua, _("Could not find Pool %s: ERR=%s"), name, db_strerror(ua->db)); @@ -365,7 +357,7 @@ int select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr) i = find_arg_keyword(ua, kw); if (i == 0 && ua->argv[i]) { - strcpy(mr->VolumeName, ua->argv[i]); + bstrncpy(mr->VolumeName, ua->argv[i], sizeof(mr->VolumeName)); } if (mr->VolumeName[0] == 0) { db_list_media_records(ua->db, mr, prtit, ua); @@ -375,7 +367,7 @@ int select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr) if (is_a_number(ua->cmd)) { mr->MediaId = atoi(ua->cmd); } else { - strcpy(mr->VolumeName, ua->cmd); + bstrncpy(mr->VolumeName, ua->cmd, sizeof(mr->VolumeName)); } } @@ -415,7 +407,7 @@ POOL *get_pool_resource(UAContext *ua) add_prompt(ua, pool->hdr.name); } UnlockRes(); - do_prompt(ua, _("Select Pool resource"), name); + do_prompt(ua, _("Select Pool resource"), name, sizeof(name)); pool = (POOL *)GetResWithName(R_POOL, name); return pool; } @@ -456,7 +448,7 @@ int get_job_dbr(UAContext *ua, JOB_DBR *jr) for (i=1; iargc; i++) { if (strcasecmp(ua->argk[i], _("job")) == 0 && ua->argv[i]) { jr->JobId = 0; - strcpy(jr->Job, ua->argv[i]); + bstrncpy(jr->Job, ua->argv[i], sizeof(jr->Job)); } else if (strcasecmp(ua->argk[i], _("jobid")) == 0 && ua->argv[i]) { jr->JobId = atoi(ua->argv[i]); } else { @@ -519,7 +511,7 @@ void add_prompt(UAContext *ua, char *prompt) * index base 0 on success, and choice * is copied to prompt if not NULL */ -int do_prompt(UAContext *ua, char *msg, char *prompt) +int do_prompt(UAContext *ua, char *msg, char *prompt, int max_prompt) { int i, item; char pmsg[MAXSTRING]; @@ -543,7 +535,7 @@ int do_prompt(UAContext *ua, char *msg, char *prompt) item = 1; bsendmsg(ua, _("Item 1 selected automatically.\n")); if (prompt) { - strcpy(prompt, ua->prompt[1]); + bstrncpy(prompt, ua->prompt[1], max_prompt); } break; } else { @@ -561,7 +553,7 @@ int do_prompt(UAContext *ua, char *msg, char *prompt) continue; } if (prompt) { - strcpy(prompt, ua->prompt[item]); + bstrncpy(prompt, ua->prompt[item], max_prompt); } break; } @@ -671,7 +663,7 @@ STORE *get_storage_resource(UAContext *ua, char *cmd) * Returns: 0 on error * 1 on success, MediaType is set */ -int get_media_type(UAContext *ua, char *MediaType) +int get_media_type(UAContext *ua, char *MediaType, int max_media) { STORE *store; int i; @@ -681,7 +673,7 @@ int get_media_type(UAContext *ua, char *MediaType) i = find_arg_keyword(ua, keyword); if (i >= 0 && ua->argv[i]) { - strcpy(MediaType, ua->argv[i]); + bstrncpy(MediaType, ua->argv[i], max_media); return 1; } @@ -691,5 +683,5 @@ int get_media_type(UAContext *ua, char *MediaType) add_prompt(ua, store->media_type); } UnlockRes(); - return (do_prompt(ua, _("Select the Media Type"), MediaType) < 0) ? 0 : 1; + return (do_prompt(ua, _("Select the Media Type"), MediaType, max_media) < 0) ? 0 : 1; } diff --git a/bacula/src/dird/ua_status.c b/bacula/src/dird/ua_status.c index 918302ad80..927e71b520 100644 --- a/bacula/src/dird/ua_status.c +++ b/bacula/src/dird/ua_status.c @@ -85,7 +85,7 @@ int statuscmd(UAContext *ua, char *cmd) add_prompt(ua, _("Client")); add_prompt(ua, _("All")); Dmsg0(20, "do_prompt: select daemon\n"); - if ((item=do_prompt(ua, _("Select daemon type for status"), cmd)) < 0) { + if ((item=do_prompt(ua, _("Select daemon type for status"), cmd, MAX_NAME_LENGTH)) < 0) { return 1; } Dmsg1(20, "item=%d\n", item); diff --git a/bacula/src/dird/verify.c b/bacula/src/dird/verify.c index ae0db6cb52..14c47c3c83 100644 --- a/bacula/src/dird/verify.c +++ b/bacula/src/dird/verify.c @@ -336,7 +336,7 @@ static void verify_cleanup(JCR *jcr, int TermCode) bstrftime(sdt, sizeof(sdt), jcr->jr.StartTime); bstrftime(edt, sizeof(edt), jcr->jr.EndTime); - Jmsg(jcr, msg_type, 0, _("%s\n\ + Jmsg(jcr, msg_type, 0, _("Bacula " VERSION " (" LSMDATE "): %s\n\ JobId: %d\n\ Job: %s\n\ FileSet: %s\n\ diff --git a/bacula/src/lib/bnet_server.c b/bacula/src/lib/bnet_server.c index d61521b162..040a773fb9 100644 --- a/bacula/src/lib/bnet_server.c +++ b/bacula/src/lib/bnet_server.c @@ -284,7 +284,7 @@ bnet_accept(BSOCK *bsock, char *who) * return it in the input message buffer. */ if ((caller = inet_ntoa(cli_addr.sin_addr)) != NULL) { - strcpy(bsock->msg, caller); + pm_strcpy(&bsock->msg, caller); } else { bsock->msg[0] = 0; } diff --git a/bacula/src/lib/cram-md5.c b/bacula/src/lib/cram-md5.c index 90310dbacd..ec9a05572e 100644 --- a/bacula/src/lib/cram-md5.c +++ b/bacula/src/lib/cram-md5.c @@ -29,6 +29,7 @@ #include "bacula.h" +/* Authorize other end */ int cram_md5_auth(BSOCK *bs, char *password) { struct timeval t1; @@ -43,13 +44,15 @@ int cram_md5_auth(BSOCK *bs, char *password) for (i=0; i<4; i++) gettimeofday(&t2, &tz); srandom((t1.tv_sec&0xffff) * (t2.tv_usec&0xff)); - gethostname(host, sizeof(host)); + if (!gethostname(host, sizeof(host))) { + bstrncpy(host, my_name, sizeof(host)); + } sprintf((char *)chal, "<%u.%u@%s>", (uint32_t)random(), (uint32_t)time(NULL), host); if (!bnet_fsend(bs, "auth cram-md5 %s\n", chal)) { return 0; } Dmsg1(99, "%s", bs->msg); - if (bnet_wait_data(bs, 120) <= 0 || bnet_recv(bs) <= 0) { + if (bnet_wait_data(bs, 180) <= 0 || bnet_recv(bs) <= 0) { sleep(5); return 0; } @@ -72,6 +75,7 @@ int cram_md5_auth(BSOCK *bs, char *password) return ok; } +/* Get authorization from other end */ int cram_md5_get_auth(BSOCK *bs, char *password) { char chal[MAXSTRING]; @@ -81,18 +85,18 @@ int cram_md5_get_auth(BSOCK *bs, char *password) sleep(5); return 0; } - if (sscanf(bs->msg, "auth cram-md5 %s", chal) != 1) { - Dmsg1(99, "Wanted auth cram... Got: %s\n", bs->msg); + if (bs->msglen >= MAXSTRING || sscanf(bs->msg, "auth cram-md5 %s\n", chal) != 1) { + Dmsg1(99, "Wanted auth cram... Got: %s", bs->msg); sleep(5); return 0; } hmac_md5((uint8_t *)chal, strlen(chal), (uint8_t *)password, strlen(password), hmac); - bs->msglen = bin_to_base64(bs->msg, (char *)hmac, 16); + bs->msglen = bin_to_base64(bs->msg, (char *)hmac, 16) + 1; if (!bnet_send(bs)) { return 0; } Dmsg1(99, "sending resp to challenge: %s\n", bs->msg); - if (bnet_wait_data(bs, 120) <= 0 || bnet_recv(bs) <= 0) { + if (bnet_wait_data(bs, 180) <= 0 || bnet_recv(bs) <= 0) { sleep(5); return 0; } diff --git a/bacula/src/lib/parse_conf.c b/bacula/src/lib/parse_conf.c index dff9cfa03b..d1bf98d8b5 100755 --- a/bacula/src/lib/parse_conf.c +++ b/bacula/src/lib/parse_conf.c @@ -237,8 +237,7 @@ void store_msgs(LEX *lc, struct res_items *item, int index, int pass) dest = get_pool_memory(PM_MESSAGE); /* Pick up a single destination */ token = lex_get_token(lc, T_NAME); /* scan destination */ - dest = check_pool_memory_size(dest, lc->str_len + 2); - strcpy(dest, lc->str); + pm_strcpy(&dest, lc->str); dest_len = lc->str_len; token = lex_get_token(lc, T_ALL); Dmsg1(200, "store_msgs dest=%s:\n", NPRT(dest)); diff --git a/bacula/src/stored/acquire.c b/bacula/src/stored/acquire.c index 2c799d64e8..48b6fb64c1 100644 --- a/bacula/src/stored/acquire.c +++ b/bacula/src/stored/acquire.c @@ -93,7 +93,9 @@ int acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) default_path: tape_previously_mounted = 0; Dmsg0(200, "dir_get_volume_info\n"); - dir_get_volume_info(jcr, 0); /* Get info for reading */ + if (!dir_get_volume_info(jcr, 0)) { + Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg); + } Dmsg2(200, "calling autoload Vol=%s Slot=%d\n", jcr->VolumeName, jcr->VolCatInfo.Slot); if (autoload_device(jcr, dev, 0, NULL)) { diff --git a/bacula/src/stored/askdir.c b/bacula/src/stored/askdir.c index 00e6612084..c8a9e511c0 100644 --- a/bacula/src/stored/askdir.c +++ b/bacula/src/stored/askdir.c @@ -34,13 +34,13 @@ static char Find_media[] = "CatReq Job=%s FindMedia=%d\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=%d VolFiles=%d VolBlocks=%d VolBytes=%" lld " VolMounts=%d\ - VolErrors=%d VolWrites=%d VolMaxBytes=%" lld " EndTime=%d VolStatus=%s\ + VolJobs=%u VolFiles=%u VolBlocks=%u VolBytes=%s VolMounts=%u\ + VolErrors=%u VolWrites=%u MaxVolBytes=%s EndTime=%d VolStatus=%s\ Slot=%d relabel=%d\n"; static char Create_job_media[] = "CatReq Job=%s CreateJobMedia \ - FirstIndex=%d LastIndex=%d StartFile=%d EndFile=%d \ - StartBlock=%d EndBlock=%d\n"; + FirstIndex=%u LastIndex=%u StartFile=%u EndFile=%u \ + StartBlock=%u EndBlock=%u\n"; static char FileAttributes[] = "UpdCat Job=%s FileAttributes "; @@ -49,10 +49,10 @@ static char Job_status[] = "3012 Job %s jobstatus %d\n"; /* Responses received from the Director */ -static char OK_media[] = "1000 OK VolName=%127s VolJobs=%d VolFiles=%d\ - VolBlocks=%d VolBytes=%" lld " VolMounts=%d VolErrors=%d VolWrites=%d\ - VolMaxBytes=%" lld " VolCapacityBytes=%" lld " VolStatus=%20s\ - Slot=%d\n"; +static char OK_media[] = "1000 OK VolName=%127s VolJobs=%u VolFiles=%u\ + VolBlocks=%u VolBytes=%" lld " VolMounts=%u VolErrors=%u VolWrites=%u\ + MaxVolBytes=%" lld " VolCapacityBytes=%" lld " VolStatus=%20s\ + Slot=%d MaxVolJobs=%u MaxVolFiles=%u\n"; static char OK_update[] = "1000 OK UpdateMedia\n"; @@ -79,16 +79,19 @@ static int do_request_volume_info(JCR *jcr) jcr->VolumeName[0] = 0; /* No volume */ if (bnet_recv(dir) <= 0) { Dmsg0(200, "getvolname error bnet_recv\n"); + Mmsg(&jcr->errmsg, _("Network error on bnet_recv in req_vol_info.\n")); return 0; } if (sscanf(dir->msg, OK_media, vol->VolCatName, &vol->VolCatJobs, &vol->VolCatFiles, - &vol->VolCatBlocks, &vol->VolCatBytes, + &vol->VolCatBlocks, &vol->VolCatBytes, &vol->VolCatMounts, &vol->VolCatErrors, - &vol->VolCatWrites, &vol->VolCatMaxBytes, + &vol->VolCatWrites, &vol->VolCatMaxBytes, &vol->VolCatCapacityBytes, vol->VolCatStatus, - &vol->Slot) != 12) { - Dmsg1(200, "Bad response from Dir: %s\n", dir->msg); + &vol->Slot, &vol->VolCatMaxJobs, &vol->VolCatMaxFiles) != 14) { + + Dmsg1(000, "Bad response from Dir: %s\n", dir->msg); + Mmsg(&jcr->errmsg, _("Error scanning Dir response: %s\n"), dir->msg); return 0; } unbash_spaces(vol->VolCatName); @@ -149,6 +152,7 @@ int dir_update_volume_info(JCR *jcr, VOLUME_CAT_INFO *vol, int relabel) { BSOCK *dir = jcr->dir_bsock; time_t EndTime = time(NULL); + char ed1[50], ed2[50]; if (vol->VolCatName[0] == 0) { Jmsg0(jcr, M_ERROR, 0, _("NULL Volume name. This shouldn't happen!!!\n")); @@ -156,10 +160,10 @@ int dir_update_volume_info(JCR *jcr, VOLUME_CAT_INFO *vol, int relabel) } bnet_fsend(dir, Update_media, jcr->Job, vol->VolCatName, vol->VolCatJobs, vol->VolCatFiles, - vol->VolCatBlocks, vol->VolCatBytes, + vol->VolCatBlocks, edit_uint64(vol->VolCatBytes, ed1), vol->VolCatMounts, vol->VolCatErrors, - vol->VolCatWrites, vol->VolCatMaxBytes, EndTime, - vol->VolCatStatus, vol->Slot, relabel); + vol->VolCatWrites, edit_uint64(vol->VolCatMaxBytes, ed2), + EndTime, vol->VolCatStatus, vol->Slot, relabel); Dmsg1(120, "update_volume_data(): %s", dir->msg); if (bnet_recv(dir) <= 0) { Dmsg0(190, "updateVolCatInfo error bnet_recv\n"); diff --git a/bacula/src/stored/block.c b/bacula/src/stored/block.c index 5e653f9f15..fdbc19097a 100644 --- a/bacula/src/stored/block.c +++ b/bacula/src/stored/block.c @@ -291,6 +291,7 @@ int write_block_to_dev(DEVICE *dev, DEV_BLOCK *block) { size_t stat = 0; uint32_t wlen; /* length to write */ + int hit_max1, hit_max2; #ifdef NO_TAPE_WRITE_TEST empty_block(block); @@ -336,12 +337,21 @@ int write_block_to_dev(DEVICE *dev, DEV_BLOCK *block) ser_block_header(block); /* Limit maximum Volume size to value specified by user */ - if ((dev->max_volume_size > 0) && - ((dev->VolCatInfo.VolCatBytes + block->binbuf)) >= dev->max_volume_size) { + hit_max1 = (dev->max_volume_size > 0) && + ((dev->VolCatInfo.VolCatBytes + block->binbuf)) >= dev->max_volume_size; + hit_max2 = (dev->VolCatInfo.VolCatMaxBytes > 0) && + ((dev->VolCatInfo.VolCatBytes + block->binbuf)) >= dev->VolCatInfo.VolCatMaxBytes; + if (hit_max1 || hit_max2) { + char ed1[50]; dev->state |= ST_WEOT; Dmsg0(10, "==== Output bytes Triggered medium max capacity.\n"); - Mmsg2(&dev->errmsg, _("Max. Volume capacity %" lld " exceeded on device %s.\n"), - dev->max_volume_size, dev->dev_name); + if (hit_max1) { + Mmsg2(&dev->errmsg, _("Max. Volume capacity %s exceeded on device %s.\n"), + edit_uint64(dev->max_volume_size, ed1), dev->dev_name); + } else { + Mmsg2(&dev->errmsg, _("Max. Volume capacity %s exceeded on device %s.\n"), + edit_uint64(dev->VolCatInfo.VolCatMaxBytes, ed1), dev->dev_name); + } block->failed_write = TRUE; /* ****FIXME**** write EOD record here */ weof_dev(dev, 1); /* end the tape */ diff --git a/bacula/src/stored/dev.h b/bacula/src/stored/dev.h index 252b932ca4..39eb20b997 100644 --- a/bacula/src/stored/dev.h +++ b/bacula/src/stored/dev.h @@ -110,7 +110,9 @@ typedef struct s_volume_catalog_info { uint32_t VolCatReads; /* Number of reads this volume */ uint32_t VolCatRecycles; /* Number of recycles this volume */ int32_t Slot; /* Slot in changer */ - uint64_t VolCatMaxBytes; /* max bytes to write */ + uint32_t VolCatMaxJobs; /* Maximum Jobs to write to volume */ + uint32_t VolCatMaxFiles; /* Maximum files to write to volume */ + uint64_t VolCatMaxBytes; /* Max bytes to write to volume */ uint64_t VolCatCapacityBytes; /* capacity estimate */ char VolCatStatus[20]; /* Volume status */ char VolCatName[MAX_NAME_LENGTH]; /* Desired volume to mount */ diff --git a/bacula/src/version.h b/bacula/src/version.h index db75bc6016..45ffa96f4a 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -1,8 +1,8 @@ /* */ #define VERSION "1.27" #define VSTRING "1" -#define DATE "18 November 2002" -#define LSMDATE "18Nov02" +#define DATE "20 November 2002" +#define LSMDATE "20Nov02" /* Debug flags */ #define DEBUG 1 -- 2.39.5