For 1.39:
+- Fix hardlinked immutable files when linking a second file, the
+ immutable flag must be removed prior to trying to link it.
- Implement Python event for backing up/restoring a file.
- Change dbcheck to tell users to use native tools for fixing
broken databases, and to ensure they have the proper indexes.
example conf files (especially in the manual).
- Fix prog copyright (SD) all other files.
- Document need for UTF-8 format
-
functionality is the ultimate goal.
Assistance with either code or testing would be fantastic.
+
+Item 1: On the bconsole "restore" command line, implement separate
+ option for specifying the host to restore from, and the
+ host to restore to.
+
+ Date: 11 December 2006
+
+ Origin: Discussion on Bacula-users entitled 'Scripted restores to
+ different clients', December 2006
+
+ Status: New feature request
+
+ What: While using bconsole interactively, you can specify the client
+ that a backup job is to be restored for, and then you can
+ specify later a different client to send the restored files
+ back to. However, using the 'restore' command with all options
+ on the command line, this cannot be done, due to the ambiguous
+ 'client' parameter. Additionally, this parameter means different
+ things depending on if it's specified on the command line or
+ afterwards, in the Modify Job screens.
+
+ Why: This feature would enable restore jobs to be more completely
+ automated, for example by a web or GUI front-end.
+
+ Notes: client can also be implied by specifying the jobid on the command
+ line
break;
}
} else {
+ if (jcr->previous_jr.JobId != 0) {
+ /* Mark previous job as migrated */
+ Mmsg(query, "UPDATE Job SET Type='%c' WHERE JobId=%s",
+ (char)JT_MIGRATED_JOB, edit_uint64(jcr->previous_jr.JobId, ec1));
+ db_sql_query(jcr->db, query.c_str(), NULL, NULL);
+ }
term_msg = _("%s -- no files to migrate");
}
jcr->compress_buf_size = compress_buf_size;
}
+ cipher_ctx.cipher = NULL;
+ alt_cipher_ctx.cipher = NULL;
if (have_crypto) {
- cipher_ctx.cipher = NULL;
cipher_ctx.buf = get_memory(CRYPTO_CIPHER_MAX_BLOCK_SIZE);
cipher_ctx.buf_len = 0;
cipher_ctx.packet_len = 0;
- cipher_ctx.cipher = NULL;
alt_cipher_ctx.buf = get_memory(CRYPTO_CIPHER_MAX_BLOCK_SIZE);
alt_cipher_ctx.buf_len = 0;
alt_cipher_ctx.packet_len = 0;
+ } else {
+ cipher_ctx.buf = NULL;
+ alt_cipher_ctx.buf = NULL;
}
/*
Dmsg1(200, "Write EOS label JobStatus=%c\n", jcr->JobStatus);
/*
- * If !OK, check if we can still write. This may not be the case
+ * Check if we can still write. This may not be the case
* if we are at the end of the tape or we got a fatal I/O error.
*/
- if (ok || dev->can_write()) {
+ if (dev->can_write()) {
if (!write_session_label(dcr, EOS_LABEL)) {
Jmsg1(jcr, M_FATAL, 0, _("Error writting end session label. ERR=%s\n"),
dev->bstrerror());
DEV_RECORD *record;
record = new_record();
read_block_from_device(dcr, NO_BLOCK_NUMBER_CHECK);
- read_record_from_block(block, record);
+ read_record_from_block(dcr, block, record);
get_session_record(dev, record, &sessrec);
free_record(record);
Jmsg(jcr, M_INFO, 0, _("Mounted Volume \"%s\".\n"), dcr->VolumeName);
block->BlockNumber, block->block_len, block->BlockVer,
block->VolSessionId, block->VolSessionTime);
if (verbose == 1) {
- read_record_from_block(block, rec);
+ read_record_from_block(dcr, block, rec);
Pmsg9(-1, _("File:blk=%u:%u blk_num=%u blen=%u First rec FI=%s SessId=%u SessTim=%u Strm=%s rlen=%d\n"),
dev->file, dev->block_num,
block->BlockNumber, block->block_len,
goto bail_out;
}
memset(rec->data, 0, rec->data_len);
- if (!read_record_from_block(block, rec)) {
+ if (!read_record_from_block(dcr, block, rec)) {
berrno be;
Pmsg1(0, _("Read block failed! ERR=%s\n"), be.strerror(dev->dev_errno));
goto bail_out;
goto bail_out;
}
memset(rec->data, 0, rec->data_len);
- if (!read_record_from_block(block, rec)) {
+ if (!read_record_from_block(dcr, block, rec)) {
berrno be;
Pmsg2(0, _("Read record failed. Block %d! ERR=%s\n"), i, be.strerror(dev->dev_errno));
goto bail_out;
goto bail_out;
}
memset(rec->data, 0, rec->data_len);
- if (!read_record_from_block(block, rec)) {
+ if (!read_record_from_block(dcr, block, rec)) {
berrno be;
Pmsg1(0, _("Read record failed! ERR=%s\n"), be.strerror(dev->dev_errno));
goto bail_out;
block->VolSessionId, block->VolSessionTime);
if (verbose == 1) {
DEV_RECORD *rec = new_record();
- read_record_from_block(block, rec);
+ read_record_from_block(dcr, block, rec);
Pmsg8(-1, _("Blk_block: %u dev_blk=%u blen=%u First rec FI=%s SessId=%u SessTim=%u Strm=%s rlen=%d\n"),
block->BlockNumber, dev->block_num, block->block_len,
FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId, rec->VolSessionTime,
"labeled Volume, because: ERR=%s"), NPRT(VolName),
dev->print_name(), dev->print_errmsg());
Dmsg1(30, "%s", jcr->errmsg);
- } else if (!read_record_from_block(block, record)) {
+ } else if (!read_record_from_block(dcr, block, record)) {
Mmsg(jcr->errmsg, _("Could not read Volume label from block.\n"));
Dmsg1(30, "%s", jcr->errmsg);
} else if (!unser_volume_label(dev, record)) {
const char *stream_to_ascii(char *buf, int stream, int fi);
bool write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
bool can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
-bool read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec);
+bool read_record_from_block(DCR *dcr, DEV_BLOCK *block, DEV_RECORD *rec);
DEV_RECORD *new_record();
void free_record(DEV_RECORD *rec);
void empty_record(DEV_RECORD *rec);
* most likely reading the previous record.
*/
read_block_from_device(dcr, NO_BLOCK_NUMBER_CHECK);
- read_record_from_block(block, trec);
+ read_record_from_block(dcr, block, trec);
handle_session_record(dev, trec, &sessrec);
ok = record_cb(dcr, trec);
free_record(trec);
rec->state = 0;
Dmsg1(dbglvl, "Block %s empty\n", is_block_empty(rec)?"is":"NOT");
for (rec->state=0; ok && !is_block_empty(rec); ) {
- if (!read_record_from_block(block, rec)) {
+ if (!read_record_from_block(dcr, block, rec)) {
Dmsg3(400, "!read-break. state=%s blk=%d rem=%d\n", rec_state_to_str(rec),
block->BlockNumber, rec->remainder);
break;
* routine may have to be called again with a new
* block if the entire record was not read.
*/
-bool read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec)
+bool read_record_from_block(DCR *dcr, DEV_BLOCK *block, DEV_RECORD *rec)
{
ser_declare;
uint32_t remlen;
return false;
}
- ASSERT(data_bytes < MAX_BLOCK_LENGTH); /* temp sanity check */
+ /* Sanity check */
+ if (data_bytes >= MAX_BLOCK_LENGTH) {
+ /*
+ * Something is wrong, force read of next block, abort
+ * continuing with this block.
+ */
+ rec->state |= (REC_NO_HEADER | REC_BLOCK_EMPTY);
+ empty_block(block);
+ Jmsg2(dcr->jcr, M_WARNING, 0, _("Sanity check failed. maxlen=%d datalen=%d. Block discarded.\n"),
+ MAX_BLOCK_LENGTH, data_bytes);
+ return false;
+ }
rec->data = check_pool_memory_size(rec->data, rec->data_len+data_bytes);
rec->remainder = 1; /* partial record transferred */
Dmsg1(450, "read_record_block: partial xfered=%d\n", rec->data_len);
rec->state |= (REC_PARTIAL_RECORD | REC_BLOCK_EMPTY);
- return 1;
+ return true;
}
rec->remainder = 0;
Dmsg4(450, "Rtn full rd_rec_blk FI=%s SessId=%d Strm=%s len=%d\n",
Technical notes on version 1.39
General:
+13Dec06
+kes Implement code that should properly set that a job was migrated,
+ if the migration was successful even if there were no file to
+ migrate.
+kes Apply Richard's patch to fix building or filed/restore.c without
+ OpenSSL support.
+kes Ensure that at least one block is written by the SD even if the
+ FD dies or fails -- should fix bug #728.
+kes Convert stored/record.c ASSERT into a soft fail if the length of
+ a record is too insanely long. This should fix bug #???
12Dec06
-
+kes Fix automatic labeling of File volumes, which was broken by new
+ removable device code.
10Dec06
kes Remove typedef uLong for HP in baconfig.h. It broke things.
lf Fix job byte reporting -- the digest code runs in verify.c and