-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
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.
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 <bacula-src>/src/cats/alter_mysql_tables (or alter_sqlite_tables)
+ to upgrade an existing database.
Minor Changes this Release:
- A number of small bug fixes.
- 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.
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;
#ifdef HAVE_SQLITE
-#define BDB_VERSION 3
+#define BDB_VERSION 4
#include <sqlite.h>
#ifdef HAVE_MYSQL
-#define BDB_VERSION 3
+#define BDB_VERSION 4
#include <mysql.h>
/* 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 */
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 */
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 */
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 */
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,
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)
);
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,
);
-- Initialize Version
-INSERT INTO Version (VersionId) VALUES (3);
+INSERT INTO Version (VersionId) VALUES (4);
CREATE TABLE Counters (
Counter TINYBLOB NOT NULL,
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)
);
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,
);
-- Initialize Version
-INSERT INTO Version (VersionId) VALUES (3);
+INSERT INTO Version (VersionId) VALUES (4);
CREATE TABLE Counters (
Counter TEXT NOT NULL,
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,
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)) {
/* 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),
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);
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);
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);
}
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;
}
}
}
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);
}
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));
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 {
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);
}
}
- 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\
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";
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));
/*
}
}
/* 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. "
* 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");
}
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 {
}
}
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 {
* 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");
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");
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");
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);
{"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},
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 */
}
}
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 */
};
/* 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);
/* 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);
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\
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);
/* 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) {
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++;
}
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) {
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);
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;
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);
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);
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"));
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: "))) {
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 {
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;
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);
#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
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);
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;
-}
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
}
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;
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;
}
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 */
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;
}
}
}
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"
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) {
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;
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;
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;
}
/* 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
*/
for (i=0; list[i]; i++) {
add_prompt(ua, list[i]);
}
- return do_prompt(ua, msg, NULL);
+ return do_prompt(ua, msg, NULL, 0);
}
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;
}
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;
}
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;
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;
}
}
}
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;
}
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;
}
}
for (i=1; i<ua->argc; 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));
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));
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);
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));
}
}
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;
}
for (i=1; i<ua->argc; 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 {
* 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];
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 {
continue;
}
if (prompt) {
- strcpy(prompt, ua->prompt[item]);
+ bstrncpy(prompt, ua->prompt[item], max_prompt);
}
break;
}
* 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;
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;
}
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;
}
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);
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\
* 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;
}
#include "bacula.h"
+/* Authorize other end */
int cram_md5_auth(BSOCK *bs, char *password)
{
struct timeval t1;
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;
}
return ok;
}
+/* Get authorization from other end */
int cram_md5_get_auth(BSOCK *bs, char *password)
{
char chal[MAXSTRING];
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;
}
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));
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)) {
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 ";
/* 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";
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);
{
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"));
}
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");
{
size_t stat = 0;
uint32_t wlen; /* length to write */
+ int hit_max1, hit_max2;
#ifdef NO_TAPE_WRITE_TEST
empty_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 */
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 */
/* */
#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