spoolfile name doesn't include that information. The date/time
stamp is useful (and should be retained).
+============= New Freature Requests after vote of 26 Jan 2007 ========
+Item n: Enable to relocate files and directories when restoring
+ Date: 2007-03-01
+ Origin: Eric Bollengier <eric@eb.homelinux.org>
+ Status:
+
+ What: The where= option is not powerful enough. It will be
+ a great feature if bacula can restore a file in the
+ same directory, but with a different name, or in
+ an other directory without recreating the full path.
+
+ Why: When i want to restore a production environment to a
+ development environment, i just want change the first
+ directory. ie restore /prod/data/file.dat to /rect/data/file.dat.
+ At this time, i have to move by hand files. You must have a big
+ dump space to restore and move data after.
+
+ When i use Linux or SAN snapshot, i mount them to /mnt/snap_xxx
+ so, when a restore a file, i have to move by hand
+ from /mnt/snap_xxx/file to /xxx/file. I can't replace a file
+ easily.
+
+ When a user ask me to restore a file in its personal folder,
+ (without replace the existing one), i can't restore from
+ my_file.txt to my_file.txt.old witch is very practical.
+
+
+ Notes: I think we can enhance the where= option very easily by
+ allowing regexp expression. (by replacing bregex by libpcre
+ see http://en.wikipedia.org/wiki/PCRE and http://www.pcre.org/)
+
+ Since, many users think that regexp are not user friendly, i think
+ that bat, bconsole or brestore must provide a simple way to
+ configure where= option (i think to something like in
+ openoffice "search and replace").
+
+ Ie, if user uses where=/tmp/bacula-restore, we keep the old
+ fashion.
+
+ If user uses something like where=s!/prod!/test!, files will
+ be restored from /prod/xxx to /test/xxx.
+
+ If user uses something like where=s/$/.old/, files will
+ be restored from /prod/xxx.txt to /prod/xxx.txt.old.
+
+ If user uses something like where=s/txt$/old.txt/, files will
+ be restored from /prod/xxx.txt to /prod/xxx.old.txt
+
+ if user uses something like where=s/([a-z]+)$/old.$1/, files will
+ be restored from /prod/xxx.ext to /prod/xxx.old.ext
+
============= Empty Feature Request form ===========
Item n: One line summary ...
Date: Date submitted
-/*
- *
- * Bacula Director -- migrate.c -- responsible for doing
- * migration jobs.
- *
- * Kern Sibbald, September MMIV
- *
- * Basic tasks done here:
- * Open DB and create records for this job.
- * Open Message Channel with Storage daemon to tell him a job will be starting.
- * Open connection with Storage daemon and pass him commands
- * to do the backup.
- * When the Storage daemon finishes the job, update the DB.
- *
- * Version $Id$
- */
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2004-2006 Free Software Foundation Europe e.V.
+ Copyright (C) 2004-2007 Free Software Foundation Europe e.V.
The main author of Bacula is Kern Sibbald, with contributions from
many others, a complete list can be found in the file AUTHORS.
(FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
Switzerland, email:ftf@fsfeurope.org.
*/
+/*
+ *
+ * Bacula Director -- migrate.c -- responsible for doing
+ * migration jobs.
+ *
+ * Kern Sibbald, September MMIV
+ *
+ * Basic tasks done here:
+ * Open DB and create records for this job.
+ * Open Message Channel with Storage daemon to tell him a job will be starting.
+ * Open connection with Storage daemon and pass him commands
+ * to do the backup.
+ * When the Storage daemon finishes the job, update the DB.
+ *
+ * Version $Id$
+ */
#include "bacula.h"
#include "dird.h"
*/
static int get_job_to_migrate(JCR *jcr)
{
- char ed1[30];
+ char ed1[30], ed2[30];
POOL_MEM query(PM_MESSAGE);
JobId_t JobId;
DBId_t MediaId = 0;
ctx.count = 0;
/* Find count of bytes from Jobs */
Mmsg(query, sql_job_bytes, mid.list);
+ Dmsg1(dbglevel, "Jobbytes query: %s\n", query.c_str());
if (!db_sql_query(jcr->db, query.c_str(), db_int64_handler, (void *)&ctx)) {
Jmsg(jcr, M_FATAL, 0, _("SQL failed. ERR=%s\n"), db_strerror(jcr->db));
goto bail_out;
}
pool_bytes -= ctx.value;
- Dmsg1(dbglevel, "Job bytes=%d\n", (int)ctx.value);
- Dmsg2(dbglevel, "lowbytes=%d pool=%d\n", (int)jcr->rpool->MigrationLowBytes,
- (int)pool_bytes);
+ Dmsg1(dbglevel, "Total migrate Job bytes=%s\n", edit_int64(ctx.value, ed1));
+ Dmsg2(dbglevel, "lowbytes=%s poolafter=%s\n",
+ edit_int64(jcr->rpool->MigrationLowBytes, ed1),
+ edit_int64(pool_bytes, ed2));
if (pool_bytes <= (int64_t)jcr->rpool->MigrationLowBytes) {
Dmsg0(dbglevel, "We should be done.\n");
break;
}
}
- Dmsg2(dbglevel, "Pool Occupancy ids=%d JobIds=%s\n", jids.count, jids.list);
-
+ /* Transfer jids to ids, where the jobs list is expected */
+ ids.count = jids.count;
+ pm_strcpy(ids.list, jids.list);
+ Dmsg2(dbglevel, "Pool Occupancy ids=%d JobIds=%s\n", ids.count, ids.list);
break;
case MT_POOL_TIME:
if (strncasecmp(ua->argk[0], _(commands[i].key), len) == 0) {
bool gui = ua->gui;
ua->gui = true;
+ /* Check if command permitted, but "quit" is always OK */
+ if (strcmp(ua->argk[0], NT_(".quit")) != 0 &&
+ !acl_access_ok(ua, Command_ACL, ua->argk[0], len)) {
+ break;
+ }
stat = (*commands[i].func)(ua, cmd); /* go execute command */
ua->gui = gui;
found = true;
}
}
if (!found) {
- pm_strcat(ua->UA_sock->msg, _(": is an invalid command\n"));
+ pm_strcat(ua->UA_sock->msg, _(": is an invalid command.\n"));
ua->UA_sock->msglen = strlen(ua->UA_sock->msg);
bnet_send(ua->UA_sock);
}
*/
static int save_file(FF_PKT *ff_pkt, void *vjcr, bool top_level)
{
- int stat, data_stream;
+ int stat, data_stream;
+ int rtnstat = 0;
DIGEST *digest = NULL;
DIGEST *signing_digest = NULL;
int digest_stream = STREAM_NONE;
+ SIGNATURE *sig = NULL;
+ uint8_t *buf = NULL;
bool has_file_data = false;
// TODO landonf: Allow the user to specify the digest algorithm
#ifdef HAVE_SHA2
Jmsg(jcr, M_NOTSAVED, 0, _("%s signature digest initialization failed\n"),
stream_to_ascii(signing_algorithm));
jcr->Errors++;
- return 1;
+ goto good_rtn;
}
}
if (!set_prog(&ff_pkt->bfd, ff_pkt->reader, jcr)) {
Jmsg(jcr, M_FATAL, 0, _("Python reader program \"%s\" not found.\n"),
ff_pkt->reader);
- return 0;
+ goto bail_out;
}
}
/* Send attributes -- must be done after binit() */
if (!encode_and_send_attributes(jcr, ff_pkt, data_stream)) {
- return 0;
+ goto bail_out;
}
/*
stop_thread_timer(tid);
tid = NULL;
}
- return 1;
+ goto good_rtn;
}
if (tid) {
stop_thread_timer(tid);
stat = send_data(jcr, data_stream, ff_pkt, digest, signing_digest);
bclose(&ff_pkt->bfd);
if (!stat) {
- return 0;
+ goto bail_out;
}
}
if (is_bopen(&ff_pkt->bfd)) {
bclose(&ff_pkt->bfd);
}
- return 1;
+ goto good_rtn;
}
flags = ff_pkt->flags;
ff_pkt->flags &= ~(FO_GZIP|FO_SPARSE);
ff_pkt->flags = flags;
bclose(&ff_pkt->bfd);
if (!stat) {
- return 0;
+ goto bail_out;
}
}
if (ff_pkt->flags & FO_ACL) {
/* Read access ACLs for files, dirs and links */
if (!read_and_send_acl(jcr, BACL_TYPE_ACCESS, STREAM_UNIX_ATTRIBUTES_ACCESS_ACL)) {
- return 0;
+ goto bail_out;
}
/* Directories can have default ACLs too */
if (ff_pkt->type == FT_DIREND && (BACL_CAP & BACL_CAP_DEFAULTS_DIR)) {
if (!read_and_send_acl(jcr, BACL_TYPE_DEFAULT, STREAM_UNIX_ATTRIBUTES_DEFAULT_ACL)) {
- return 0;
+ goto bail_out;
}
}
}
/* Terminate the signing digest and send it to the Storage daemon */
if (signing_digest) {
- SIGNATURE *sig;
uint32_t size = 0;
- uint8_t *buf;
if ((sig = crypto_sign_new()) == NULL) {
Jmsg(jcr, M_FATAL, 0, _("Failed to allocate memory for stream signature.\n"));
- return 0;
+ goto bail_out;
}
if (crypto_sign_add_signer(sig, signing_digest, jcr->pki_keypair) == false) {
Jmsg(jcr, M_FATAL, 0, _("An error occurred while signing the stream.\n"));
- return 0;
+ goto bail_out;
}
/* Get signature size */
if (crypto_sign_encode(sig, NULL, &size) == false) {
Jmsg(jcr, M_FATAL, 0, _("An error occurred while signing the stream.\n"));
- return 0;
+ goto bail_out;
}
/* Allocate signature data buffer */
buf = (uint8_t *)malloc(size);
if (!buf) {
- crypto_sign_free(sig);
- return 0;
+ goto bail_out;
}
/* Encode signature data */
if (crypto_sign_encode(sig, buf, &size) == false) {
Jmsg(jcr, M_FATAL, 0, _("An error occurred while signing the stream.\n"));
- return 0;
+ goto bail_out;
}
/* Send our header */
sd->msglen = size;
bnet_send(sd);
bnet_sig(sd, BNET_EOD); /* end of checksum */
-
- crypto_digest_free(signing_digest);
- crypto_sign_free(sig);
- free(buf);
+ goto good_rtn;
}
/* Terminate any digest and send it to Storage daemon and the Director */
bnet_send(sd);
bnet_sig(sd, BNET_EOD); /* end of checksum */
}
+ }
+
+good_rtn:
+ rtnstat = 1; /* good return */
+bail_out:
+ if (digest) {
crypto_digest_free(digest);
}
-
- return 1;
+ if (signing_digest) {
+ crypto_digest_free(signing_digest);
+ }
+ if (sig) {
+ crypto_sign_free(sig);
+ }
+ if (buf) {
+ free(buf);
+ }
+ return rtnstat;
}
/*
if (digest_file(jcr, ff_pkt, digest) != 0) {
jcr->Errors++;
- return 1;
+ goto good_rtn;
}
if (crypto_digest_finalize(digest, (uint8_t *)md, &size)) {
free(digest_buf);
}
-
- crypto_digest_free(digest);
}
}
+good_rtn:
+ if (digest) {
+ crypto_digest_free(digest);
+ }
return 1;
}
# AutoChanger = yes
# # Enable the Alert command only if you have the mtx package loaded
# Alert Command = "sh -c 'tapeinfo -f %c |grep TapeAlert|cat'"
+# If you have smartctl, enable this, it has more info than tapeinfo
+# Alert Command = "sh -c 'smartctl -H -l error %c'"
#}
#Device {
# AutoChanger = yes
# # Enable the Alert command only if you have the mtx package loaded
# Alert Command = "sh -c 'tapeinfo -f %c |grep TapeAlert|cat'"
+# If you have smartctl, enable this, it has more info than tapeinfo
+# Alert Command = "sh -c 'smartctl -H -l error %c'"
#}
#
## AutoChanger = yes
# # Enable the Alert command only if you have the mtx package loaded
## Alert Command = "sh -c 'tapeinfo -f %c |grep TapeAlert|cat'"
+## If you have smartctl, enable this, it has more info than tapeinfo
+## Alert Command = "sh -c 'smartctl -H -l error %c'"
#}
#
# Backward Space Record = no
# Fast Forward Space File = no
# TWO EOF = yes
+# If you have smartctl, enable this, it has more info than tapeinfo
+# Alert Command = "sh -c 'smartctl -H -l error %c'"
#}
#
## The min/max blocksizes of 32768 are *required*
# Minimum Block Size = 32768
# Maximum Block Size = 32768
+# If you have smartctl, enable this, it has more info than tapeinfo
+# Alert Command = "sh -c 'smartctl -H -l error %c'"
#}
#
# AlwaysOpen = yes;
# RemovableMedia = yes;
# RandomAccess = no;
+# If you have smartctl, enable this, it has more info than tapeinfo
+# Alert Command = "sh -c 'smartctl -H -l error %c'"
#}
#
# AlwaysOpen = Yes;
# RemovableMedia = yes;
# RandomAccess = no;
+# If you have smartctl, enable this, it has more info than tapeinfo
+# Alert Command = "sh -c 'smartctl -H -l error %c'"
#}
#
#undef VERSION
#define VERSION "2.0.3"
-#define BDATE "02 March 2007"
-#define LSMDATE "02Mar07"
+#define BDATE "05 March 2007"
+#define LSMDATE "05Mar07"
#define PROG_COPYRIGHT "Copyright (C) %d-2007 Free Software Foundation Europe e.V.\n"
#define BYEAR "2007" /* year for copyright messages in progs */
Technical notes on version 2.0
General:
+5Mar07
+kes File migrate bug with Pool Occupancy using mediaid instead
+ of jobids. Fixes bug #795.
+kes Fix orphaned buffers in filed backup and verify due to
+ crypto buffers not freed during errors. Fixes bug #789.
+04Mar07
+kes Add smartctl call to bacula-sd.conf as an example of getting
+ tape alert info.
02Mar07
kes Add Client Connect Wait to Storage daemon to permit users to
modify the time the SD waits for a FD connection.