- Optimized bootstrap.
For 1.37:
+- Windows restore:
+ data-fd: RestoreFiles.2004-12-07_15.56.42 Error:
+ > ..\findlib\../../findlib/create_file.c:275 Could not open e:/: ERR=Der
+ > Prozess kann nicht auf die Datei zugreifen, da sie von einem anderen
+ > Prozess verwendet wird.
+ Restore restores all files, but then fails at the end.
+- Add better documentation on how restores can be done
+ from failed jobs.
+- Resolve the problem between Device name and Archive name,
+ and fix SD messages.
- Make sure SD deletes spool files on error exit.
- Delete old spool files when SD starts.
- When Python creates a new label, the tape is immediately
--- /dev/null
+
+ This patch fixes a bug where a tape gets "truncated" after
+ doing a restore. The number of files in the catalog do not
+ agree with what Bacula thinks is on tape, then the tape is
+ marked in error.
+ Apply this patch to version 1.36.1 with:
+
+ cd <bacula>
+ patch -p0 <1.36.1-truncate.patch
+ make
+ ...
+
+
+--- src/stored/read_record.c.orig 2004-09-29 21:11:17.000000000 +0200
++++ src/stored/read_record.c 2005-02-15 13:22:12.723140229 +0100
+@@ -266,7 +266,7 @@
+ Dmsg2(300, "Current postion (file:block) %d:%d\n",
+ dev->file, dev->block_num);
+ jcr->bsr->mount_next_volume = false;
+- dev->state |= ST_EOT;
++// dev->state |= ST_EOT;
+ rec->Block = 0;
+ return 1;
+ }
in the incorrect name being used for the check.
This could lead to security problems with unwanted
access by restricted consoles.
+
+15Feb05 1.36.1-truncate.patch
+ This patch fixes a bug where a tape gets "truncated" after
+ doing a restore. The number of files in the catalog do not
+ agree with what Bacula thinks is on tape, then the tape is
+ marked in error.
*/
char cFirstWritten[MAX_TIME_LENGTH]; /* FirstWritten returned from DB */
char cLastWritten[MAX_TIME_LENGTH]; /* LastWritten returned from DB */
- char cLabelData[MAX_TIME_LENGTH]; /* LabelData returned from DB */
+ char cLabelDate[MAX_TIME_LENGTH]; /* LabelData returned from DB */
+ bool set_first_written;
+ bool set_label_date;
};
/* Client record -- same as the database */
# INDEX (FilenameId),
# INDEX (JobId, PathId, FilenameId)
#
+# Adding an index on JobId can speed up pruning
+#
CREATE TABLE Job (
JobId INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
} else {
mr->MediaId = sql_insert_id(mdb, _("Media"));
stat = 1;
- if (mr->LabelDate) {
+ if (mr->set_label_date) {
char dt[MAX_TIME_LENGTH];
+ if (mr->LabelDate == 0) {
+ mr->LabelDate = time(NULL);
+ }
localtime_r(&mr->LabelDate, &tm);
strftime(dt, sizeof(dt), "%Y-%m-%d %T", &tm);
Mmsg(mdb->cmd, "UPDATE Media SET LabelDate='%s' "
"VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,"
"MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,"
"MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger,"
- "EndFile,EndBlock,VolParts,LabelType "
+ "EndFile,EndBlock,VolParts,LabelType,LabelDate "
"FROM Media WHERE MediaId=%s",
edit_int64(mr->MediaId, ed1));
} else { /* find by name */
"VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,"
"MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,"
"MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger,"
- "EndFile,EndBlock,VolParts,LabelType "
+ "EndFile,EndBlock,VolParts,LabelType,LabelDate "
"FROM Media WHERE VolumeName='%s'", mr->VolumeName);
}
mr->EndBlock = str_to_uint64(row[24]);
mr->VolParts = str_to_int64(row[25]);
mr->LabelType = str_to_int64(row[26]);
+ bstrncpy(mr->cLabelDate, row[27]!=NULL?row[27]:"", sizeof(mr->cLabelDate));
+ mr->LabelDate = (time_t)str_to_utime(mr->cLabelDate);
stat = mr->MediaId;
}
} else {
Dmsg1(100, "update_media: FirstWritten=%d\n", mr->FirstWritten);
db_lock(mdb);
- if (mr->VolJobs == 1) {
+ if (mr->set_first_written) {
Dmsg1(400, "Set FirstWritten Vol=%s\n", mr->VolumeName);
ttime = mr->FirstWritten;
localtime_r(&ttime, &tm);
Mmsg(mdb->cmd, "UPDATE Media SET FirstWritten='%s'"
" WHERE VolumeName='%s'", dt, mr->VolumeName);
stat = UPDATE_DB(jcr, mdb, mdb->cmd);
- Dmsg1(400, "Firstwritten stat=%d\n", stat);
+ Dmsg1(400, "Firstwritten=%d\n", mr->FirstWritten);
}
/* Label just done? */
- if (mr->VolBytes == 1) {
+ if (mr->set_label_date) {
ttime = mr->LabelDate;
if (ttime == 0) {
ttime = time(NULL);
ALTER TABLE Media ADD COLUMN VolParts INTEGER UNSIGNED NOT NULL DEFAULT 0;
CREATE TABLE MediaType (
- MediaTypeId INTERGER UNSIGNED NOT NULL AUTO_INCREMENT,
+ MediaTypeId INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
MediaType VARCHAR(128) NOT NULL,
ReadOnly TINYINT DEFAULT 0,
PRIMARY KEY(MediaTypeId)
CREATE TABLE Device (
DeviceId INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
Name VARCHAR(128) NOT NULL,
- MediaTypeId INTEGER UNSIGNED REFERENCES MediaType NOT NULL,
+ MediaTypeId INTEGER UNSIGNED NOT NULL REFERENCES MediaType,
StorageId INTEGER UNSIGNED REFERENCES Storage,
DevMounts INTEGER UNSIGNED DEFAULT 0,
DevReadBytes BIGINT UNSIGNED DEFAULT 0,
* Request to find next appendable Volume for this Job
*/
Dmsg1(400, "catreq %s", bs->msg);
+ if (!jcr->db) {
+ omsg = get_memory(bs->msglen+1);
+ pm_strcpy(omsg, bs->msg);
+ bnet_fsend(bs, "1990 Invalid Catalog Request: %s", omsg);
+ Jmsg1(jcr, M_FATAL, 0, _("Invalid Catalog request; DB not open: %s"), omsg);
+ free_memory(omsg);
+ return;
+ }
if (sscanf(bs->msg, Find_media, &Job, &index) == 2) {
ok = find_next_volume_for_append(jcr, &mr, true /*permit create new vol*/);
/*
bnet_fsend(bs, "1997 Volume \"%s\" not in catalog.\n", mr.VolumeName);
}
-
/*
* Request to update Media record. Comes typically at the end
* of a Storage daemon Job Session, when labeling/relabeling a
return;
}
/* Set first written time if this is first job */
- if (mr.VolJobs == 0 || sdmr.VolJobs == 1) {
+ if (mr.FirstWritten == 0) {
mr.FirstWritten = jcr->start_time; /* use Job start time as first write */
+ mr.set_first_written = true;
}
/* If we just labeled the tape set time */
- Dmsg2(400, "label=%d labeldate=%d\n", label, mr.LabelDate);
if (label || mr.LabelDate == 0) {
- mr.LabelDate = time(NULL);
+ mr.LabelDate = jcr->start_time;
+ mr.set_label_date = true;
+ Dmsg2(400, "label=%d labeldate=%d\n", label, mr.LabelDate);
} else {
/*
* Insanity check for VolFiles get set to a smaller value
} else if (db_update_media_record(jcr, jcr->db, &mr)) {
send_volume_info_to_storage_daemon(jcr, bs, &mr);
} else {
- Jmsg(jcr, M_ERROR, 0, _("Catalog error updating Media record. %s"),
+ Jmsg(jcr, M_FATAL, 0, _("Catalog error updating Media record. %s"),
db_strerror(jcr->db));
bnet_fsend(bs, "1992 Update Media error\n");
Dmsg0(400, "send error\n");
Dmsg6(400, "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, jcr->db, &jm)) {
- Jmsg(jcr, M_ERROR, 0, _("Catalog error creating JobMedia record. %s"),
+ Jmsg(jcr, M_FATAL, 0, _("Catalog error creating JobMedia record. %s"),
db_strerror(jcr->db));
bnet_fsend(bs, "1991 Update JobMedia error\n");
} else {
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);
+ Jmsg1(jcr, M_FATAL, 0, _("Invalid Catalog request: %s"), omsg);
free_memory(omsg);
}
Dmsg1(400, ">CatReq response: %s", bs->msg);
Dmsg1(2300, "Took jobid=%d from ready and appended to run\n", jcr->JobId);
/* Release job queue lock */
- if ((stat = pthread_mutex_unlock(&jq->mutex)) != 0) {
- berrno be;
- Jmsg1(NULL, M_ERROR, 0, "pthread_mutex_unlock: ERR=%s\n", be.strerror(stat));
- jq->num_workers--;
- return NULL;
- }
+ V(jq->mutex);
/* Call user's routine here */
Dmsg1(2300, "Calling user engine for jobid=%d\n", jcr->JobId);
Dmsg1(2300, "Back from user engine jobid=%d.\n", jcr->JobId);
/* Reacquire job queue lock */
- if ((stat = pthread_mutex_lock(&jq->mutex)) != 0) {
- berrno be;
- Jmsg1(NULL, M_ERROR, 0, "pthread_mutex_lock: ERR=%s\n", be.strerror(stat));
- jq->num_workers--;
- free(je); /* release job entry */
- return NULL;
- }
+ P(jq->mutex);
Dmsg0(200, "Done lock mutex after running job. Release locks.\n");
jq->running_jobs->remove(je);
/*
*/
if (jcr->acquired_resource_locks) {
jcr->store->NumConcurrentJobs--;
- if (jcr->JobType == JT_RESTORE || jcr->JobType == JT_VERIFY) {
- jcr->store->MaxConcurrentJobs = jcr->saveMaxConcurrentJobs;
- }
jcr->client->NumConcurrentJobs--;
jcr->job->NumConcurrentJobs--;
}
if (jcr->JobType == JT_RESTORE || jcr->JobType == JT_VERIFY) {
/* Let only one Restore/verify job run at a time regardless of MaxConcurrentJobs */
if (jcr->store->NumConcurrentJobs == 0) {
- jcr->store->NumConcurrentJobs++;
- jcr->saveMaxConcurrentJobs = jcr->store->MaxConcurrentJobs;
- jcr->store->MaxConcurrentJobs = 1;
+ jcr->store->NumConcurrentJobs = 1;
} else {
set_jcr_job_status(jcr, JS_WaitStoreRes);
je = jn; /* point to next waiting job */
if (!skip_this_jcr) {
jcr->store->NumConcurrentJobs++;
}
+ } else {
+ skip_this_jcr = true;
}
if (skip_this_jcr) {
set_jcr_job_status(jcr, JS_WaitStoreRes);
} else {
/* Back out previous locks */
jcr->store->NumConcurrentJobs--;
- if (jcr->JobType == JT_RESTORE || jcr->JobType == JT_VERIFY) {
- jcr->store->MaxConcurrentJobs = jcr->saveMaxConcurrentJobs;
- }
set_jcr_job_status(jcr, JS_WaitClientRes);
je = jn; /* point to next waiting job */
continue;
} else {
/* Back out previous locks */
jcr->store->NumConcurrentJobs--;
- if (jcr->JobType == JT_RESTORE || jcr->JobType == JT_VERIFY) {
- jcr->store->MaxConcurrentJobs = jcr->saveMaxConcurrentJobs;
- }
jcr->client->NumConcurrentJobs--;
set_jcr_job_status(jcr, JS_WaitJobRes);
je = jn; /* Point to next waiting job */
mr->VolJobs = mr->VolFiles = mr->VolBlocks = mr->VolErrors = 0;
mr->VolBytes = 1;
mr->FirstWritten = mr->LastWritten = 0;
+ mr->set_first_written = true;
return db_update_media_record(jcr, jcr->db, mr);
}
"ORDER BY Job.StartTime DESC LIMIT 1";
/* Query to get all files in a directory -- no recursing */
-// cleanup needed -- add client, ...
const char *uar_jobid_fileindex_from_dir =
"SELECT Job.JobId,File.FileIndex FROM Job,File,Path,Filename,Client "
"WHERE Job.JobId IN (%s) "
unbash_spaces(mr->MediaType);
unbash_spaces(pr->Name);
mr->LabelDate = time(NULL);
+ mr->set_label_date = true;
if (ok) {
if (media_record_exists) { /* we update it */
mr->VolBytes = 1;
extern int debug_level;
static bool terminate_writing_volume(DCR *dcr);
+static bool do_new_file_bookkeeping(DCR *dcr);
+static bool do_dvd_size_checks(DCR *dcr);
/*
* Dump the block header, then walk through
(dev->file_size+block->binbuf) >= dev->max_file_size) {
dev->file_size = 0; /* reset file size */
- if (dev->is_tape() && weof_dev(dev, 1) != 0) { /* write eof */
+ if (weof_dev(dev, 1) != 0) { /* write eof */
Dmsg0(190, "WEOF error in max file size.\n");
terminate_writing_volume(dcr);
dev->dev_errno = ENOSPC;
return false;
}
- /* Create a JobMedia record so restore can seek */
- if (!dir_create_jobmedia_record(dcr)) {
- Dmsg0(190, "Error from create_job_media.\n");
- dev->dev_errno = EIO;
- Jmsg(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
- dcr->VolCatInfo.VolCatName, jcr->Job);
- terminate_writing_volume(dcr);
- dev->dev_errno = EIO;
- return false;
- }
- dev->VolCatInfo.VolCatFiles = dev->file;
- if (!dir_update_volume_info(dcr, false)) {
- Dmsg0(190, "Error from update_vol_info.\n");
- terminate_writing_volume(dcr);
- dev->dev_errno = EIO;
- return false;
- }
- Dmsg0(100, "dir_update_volume_info max file size -- OK\n");
-
-
- /*
- * Walk through all attached dcrs setting flag to call
- * set_new_file_parameters() when that dcr is next used.
- */
- DCR *mdcr;
- foreach_dlist(mdcr, dev->attached_dcrs) {
- if (mdcr->jcr->JobId == 0) {
- continue;
- }
- mdcr->NewFile = true; /* set reminder to do set_new_file_params */
- }
- /* Set new file/block parameters for current dcr */
- set_new_file_parameters(dcr);
- }
-
- /* Limit maximum part size to value specified by user (not applicable to tapes/fifos) */
- if (!(dev->state & (ST_TAPE|ST_FIFO)) &&
- (dev->max_part_size > 0) &&
- ((dev->part_size + block->binbuf) >= dev->max_part_size)) {
- if (dev->part < dev->num_parts) {
- Jmsg3(dcr->jcr, M_FATAL, 0, _("Error while writing, current part number is less than the total number of parts (%d/%d, device=%s)\n"),
- dev->part, dev->num_parts, dev_name(dev));
- dev->dev_errno = EIO;
- return false;
- }
-
- if (open_next_part(dev) < 0) {
- Jmsg2(dcr->jcr, M_FATAL, 0, _("Unable to open device next part %s. ERR=%s\n"),
- dev_name(dev), strerror_dev(dev));
- dev->dev_errno = EIO;
- return false;
- }
-
- dev->VolCatInfo.VolCatParts = dev->num_parts;
-
- if (!dir_update_volume_info(dcr, false)) {
- Dmsg0(190, "Error from update_vol_info.\n");
- dev->dev_errno = EIO;
+ if (!do_new_file_bookkeeping(dcr)) {
return false;
}
}
- if (dev->free_space_errno < 0) { /* Error while getting free space */
- char ed1[50], ed2[50];
- Dmsg1(10, "Cannot get free space on the device ERR=%s.\n", dev->errmsg);
- Jmsg(jcr, M_FATAL, 0, _("End of Volume \"%s\" at %u:%u on device %s (part_size=%s, free_space=%s, free_space_errno=%d, errmsg=%s).\n"),
- dev->VolCatInfo.VolCatName,
- dev->file, dev->block_num, dev->dev_name,
- edit_uint64_with_commas(dev->part_size, ed1), edit_uint64_with_commas(dev->free_space, ed2),
- dev->free_space_errno, dev->errmsg);
- dev->dev_errno = -dev->free_space_errno;
+ if (!do_dvd_size_checks(dcr)) {
return false;
}
-
- if (((dev->free_space_errno > 0) && ((dev->part_size + block->binbuf) >= dev->free_space))) {
- char ed1[50], ed2[50];
- Dmsg0(10, "==== Just enough free space on the device to write the current part...\n");
- Jmsg(jcr, M_INFO, 0, _("End of Volume \"%s\" at %u:%u on device %s (part_size=%s, free_space=%s, free_space_errno=%d).\n"),
- dev->VolCatInfo.VolCatName,
- dev->file, dev->block_num, dev->dev_name,
- edit_uint64_with_commas(dev->part_size, ed1), edit_uint64_with_commas(dev->free_space, ed2),
- dev->free_space_errno);
- terminate_writing_volume(dcr);
- dev->dev_errno = ENOSPC;
- return false;
- }
dev->VolCatInfo.VolCatWrites++;
Dmsg1(300, "Write block of %u bytes\n", wlen);
Jmsg(dcr->jcr, M_ERROR, 0, "%s", dev->errmsg);
}
bail_out:
- dev->state |= (ST_EOF|ST_EOT|ST_WEOT);
- dev->state &= ~ST_APPEND; /* make tape read-only */
+ dev->set_eot();
Dmsg1(100, "Leave terminate_writing_volume -- %s\n", ok?"OK":"ERROR");
return ok;
}
+/*
+ * Do bookkeeping when a new file is created on a Volume. This is
+ * also done for disk files to generate the jobmedia records for
+ * quick seeking.
+ */
+static bool do_new_file_bookkeeping(DCR *dcr)
+{
+ DEVICE *dev = dcr->dev;
+ JCR *jcr = dcr->jcr;
+
+ /* Create a JobMedia record so restore can seek */
+ if (!dir_create_jobmedia_record(dcr)) {
+ Dmsg0(190, "Error from create_job_media.\n");
+ dev->dev_errno = EIO;
+ Jmsg(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
+ dcr->VolCatInfo.VolCatName, jcr->Job);
+ terminate_writing_volume(dcr);
+ dev->dev_errno = EIO;
+ return false;
+ }
+ dev->VolCatInfo.VolCatFiles = dev->file;
+ if (!dir_update_volume_info(dcr, false)) {
+ Dmsg0(190, "Error from update_vol_info.\n");
+ terminate_writing_volume(dcr);
+ dev->dev_errno = EIO;
+ return false;
+ }
+ Dmsg0(100, "dir_update_volume_info max file size -- OK\n");
+
+ /*
+ * Walk through all attached dcrs setting flag to call
+ * set_new_file_parameters() when that dcr is next used.
+ */
+ DCR *mdcr;
+ foreach_dlist(mdcr, dev->attached_dcrs) {
+ if (mdcr->jcr->JobId == 0) {
+ continue;
+ }
+ mdcr->NewFile = true; /* set reminder to do set_new_file_params */
+ }
+ /* Set new file/block parameters for current dcr */
+ set_new_file_parameters(dcr);
+ return true;
+}
+
+/*
+ * Do all checks for DVD sizes during writing.
+ */
+static bool do_dvd_size_checks(DCR *dcr)
+{
+ DEVICE *dev = dcr->dev;
+ JCR *jcr = dcr->jcr;
+ DEV_BLOCK *block = dcr->block;
+
+ /* Limit maximum part size to value specified by user (not applicable to tapes/fifos) */
+ if (!(dev->state & (ST_TAPE|ST_FIFO)) && dev->max_part_size > 0 &&
+ (dev->part_size + block->binbuf) >= dev->max_part_size) {
+ if (dev->part < dev->num_parts) {
+ Jmsg3(dcr->jcr, M_FATAL, 0, _("Error while writing, current part number is less than the total number of parts (%d/%d, device=%s)\n"),
+ dev->part, dev->num_parts, dev_name(dev));
+ dev->dev_errno = EIO;
+ return false;
+ }
+
+ if (open_next_part(dev) < 0) {
+ Jmsg2(dcr->jcr, M_FATAL, 0, _("Unable to open device next part %s. ERR=%s\n"),
+ dev_name(dev), strerror_dev(dev));
+ dev->dev_errno = EIO;
+ return false;
+ }
+
+ dev->VolCatInfo.VolCatParts = dev->num_parts;
+
+ if (!dir_update_volume_info(dcr, false)) {
+ Dmsg0(190, "Error from update_vol_info.\n");
+ dev->dev_errno = EIO;
+ return false;
+ }
+ }
+
+ if (dev->free_space_errno < 0) { /* Error while getting free space */
+ char ed1[50], ed2[50];
+ Dmsg1(10, "Cannot get free space on the device ERR=%s.\n", dev->errmsg);
+ Jmsg(jcr, M_FATAL, 0, _("End of Volume \"%s\" at %u:%u on device %s (part_size=%s, free_space=%s, free_space_errno=%d, errmsg=%s).\n"),
+ dev->VolCatInfo.VolCatName,
+ dev->file, dev->block_num, dev->dev_name,
+ edit_uint64_with_commas(dev->part_size, ed1), edit_uint64_with_commas(dev->free_space, ed2),
+ dev->free_space_errno, dev->errmsg);
+ dev->dev_errno = -dev->free_space_errno;
+ return false;
+ }
+
+ if ((dev->free_space_errno > 0 && (dev->part_size + block->binbuf) >= dev->free_space)) {
+ char ed1[50], ed2[50];
+ Dmsg0(10, "==== Just enough free space on the device to write the current part...\n");
+ Jmsg(jcr, M_INFO, 0, _("End of Volume \"%s\" at %u:%u on device %s (part_size=%s, free_space=%s, free_space_errno=%d).\n"),
+ dev->VolCatInfo.VolCatName,
+ dev->file, dev->block_num, dev->dev_name,
+ edit_uint64_with_commas(dev->part_size, ed1), edit_uint64_with_commas(dev->free_space, ed2),
+ dev->free_space_errno);
+ terminate_writing_volume(dcr);
+ dev->dev_errno = ENOSPC;
+ return false;
+ }
+ return true;
+}
+
/*
* Read block with locking
for ( ;; ) {
if (!read_block_from_device(dcr, NO_BLOCK_NUMBER_CHECK)) {
Dmsg1(100, "!read_block(): ERR=%s\n", dev->strerror());
- if (dev->at_eom()) {
+ if (dev->at_eot()) {
if (!mount_next_read_volume(dcr)) {
Jmsg(jcr, M_INFO, 0, _("Got EOM at file %u on device %s, Volume \"%s\"\n"),
dev->file, dev_name(dev), dcr->VolumeName);
printf("%sMALLOC ", dev->state & ST_MALLOC ? "" : "!");
printf("%sAPPEND ", dev->can_append() ? "" : "!");
printf("%sREAD ", dev->can_read() ? "" : "!");
- printf("%sEOT ", dev->at_eom() ? "" : "!");
+ printf("%sEOT ", dev->at_eot() ? "" : "!");
printf("%sWEOT ", dev->state & ST_WEOT ? "" : "!");
printf("%sEOF ", dev->at_eof() ? "" : "!");
printf("%sNEXTVOL ", dev->state & ST_NEXTVOL ? "" : "!");
}
Dmsg4(29, "open_dev: disk fd=%d opened, part=%d/%d, part_size=%u\n", dev->fd, dev->part, dev->num_parts, dev->part_size);
if (dev->is_dvd() && (dev->mode != OPEN_READ_ONLY) &&
- ((dev->free_space_errno == 0) || (dev->num_parts == dev->part))) {
+ (dev->free_space_errno == 0 || dev->num_parts == dev->part)) {
update_free_space_dev(dev);
}
}
block_num = 0;
}
+/*
+ * Called to indicate we are now at the end of the tape, and
+ * writing is not possible.
+ */
+void DEVICE::set_eot()
+{
+ state |= (ST_EOF|ST_EOT|ST_WEOT);
+ state &= ~ST_APPEND; /* make tape read-only */
+}
+
/*
* Position device to end of medium (end of data)
* Returns: 1 on succes
const char *strerror() const;
const char *archive_name() const;
void set_eof();
+ void set_eot();
};
/* Note, these return int not bool! */
inline int DEVICE::is_labeled() const { return state & ST_LABEL; }
inline int DEVICE::is_busy() const { return state & ST_READ || num_writers; }
inline int DEVICE::at_eof() const { return state & ST_EOF; }
-inline int DEVICE::at_eom() const { return state & ST_EOT; }
inline int DEVICE::at_eot() const { return state & ST_EOT; }
inline int DEVICE::can_append() const { return state & ST_APPEND; }
inline int DEVICE::can_read() const { return state & ST_READ; }
break;
}
if (!read_block_from_device(dcr, CHECK_BLOCK_NUMBERS)) {
- if (dev_state(dev, ST_EOT)) {
+ if (dev->at_eot()) {
DEV_RECORD *trec = new_record();
Jmsg(jcr, M_INFO, 0, "End of Volume at file %u on device %s, Volume \"%s\"\n",
/* After reading label, we must read first data block */
continue;
- } else if (dev_state(dev, ST_EOF)) {
+ } else if (dev->at_eof()) {
if (verbose) {
Jmsg(jcr, M_INFO, 0, "Got EOF at file %u on device %s, Volume \"%s\"\n",
dev->file, dev_name(dev), dcr->VolumeName);
Dmsg2(300, "Current postion (file:block) %d:%d\n",
dev->file, dev->block_num);
jcr->bsr->mount_next_volume = false;
- dev->state |= ST_EOT;
+// dev->state |= ST_EOT;
rec->Block = 0;
return 1;
}
bnet_fsend(user, "%sMALLOC ", dev->state & ST_MALLOC ? "" : "!");
bnet_fsend(user, "%sAPPEND ", dev->can_append() ? "" : "!");
bnet_fsend(user, "%sREAD ", dev->can_read() ? "" : "!");
- bnet_fsend(user, "%sEOT ", dev->at_eom() ? "" : "!");
+ bnet_fsend(user, "%sEOT ", dev->at_eot() ? "" : "!");
bnet_fsend(user, "%sWEOT ", dev->state & ST_WEOT ? "" : "!");
bnet_fsend(user, "%sEOF ", dev->at_eof() ? "" : "!");
bnet_fsend(user, "%sNEXTVOL ", dev->state & ST_NEXTVOL ? "" : "!");