From 6ffa0d9da98111111f1723ab010f47b040ce4938 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Mon, 5 Mar 2007 12:33:59 +0000 Subject: [PATCH] 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. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/branches/Branch-2.0@4312 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/projects | 51 +++++++++++++++++++++++++ bacula/src/dird/migrate.c | 50 +++++++++++++----------- bacula/src/dird/ua_dotcmds.c | 7 +++- bacula/src/filed/backup.c | 59 +++++++++++++++++------------ bacula/src/filed/verify.c | 8 ++-- bacula/src/stored/bacula-sd.conf.in | 14 +++++++ bacula/src/version.h | 4 +- bacula/technotes-2.0 | 8 ++++ 8 files changed, 148 insertions(+), 53 deletions(-) diff --git a/bacula/projects b/bacula/projects index 24c6573c08..bae68a506b 100644 --- a/bacula/projects +++ b/bacula/projects @@ -1129,6 +1129,57 @@ Item 40: Include JobID in spool file name ****DONE**** 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 + 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 diff --git a/bacula/src/dird/migrate.c b/bacula/src/dird/migrate.c index 6d21bd8a4a..0165f7153d 100644 --- a/bacula/src/dird/migrate.c +++ b/bacula/src/dird/migrate.c @@ -1,23 +1,7 @@ -/* - * - * 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. @@ -41,6 +25,22 @@ (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" @@ -587,7 +587,7 @@ const char *sql_pool_time = */ 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; @@ -726,22 +726,26 @@ static int get_job_to_migrate(JCR *jcr) 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: diff --git a/bacula/src/dird/ua_dotcmds.c b/bacula/src/dird/ua_dotcmds.c index 04e87c0da9..8272b90599 100644 --- a/bacula/src/dird/ua_dotcmds.c +++ b/bacula/src/dird/ua_dotcmds.c @@ -111,6 +111,11 @@ int do_a_dot_command(UAContext *ua, const char *cmd) 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; @@ -118,7 +123,7 @@ int do_a_dot_command(UAContext *ua, const char *cmd) } } 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); } diff --git a/bacula/src/filed/backup.c b/bacula/src/filed/backup.c index 1f970301f9..4af0603576 100644 --- a/bacula/src/filed/backup.c +++ b/bacula/src/filed/backup.c @@ -211,10 +211,13 @@ bool blast_data_to_storage_daemon(JCR *jcr, char *addr) */ 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 @@ -369,7 +372,7 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr, bool top_level) Jmsg(jcr, M_NOTSAVED, 0, _("%s signature digest initialization failed\n"), stream_to_ascii(signing_algorithm)); jcr->Errors++; - return 1; + goto good_rtn; } } @@ -388,13 +391,13 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr, bool top_level) 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; } /* @@ -424,7 +427,7 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr, bool top_level) stop_thread_timer(tid); tid = NULL; } - return 1; + goto good_rtn; } if (tid) { stop_thread_timer(tid); @@ -455,7 +458,7 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr, bool top_level) stat = send_data(jcr, data_stream, ff_pkt, digest, signing_digest); bclose(&ff_pkt->bfd); if (!stat) { - return 0; + goto bail_out; } } @@ -475,7 +478,7 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr, bool top_level) 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); @@ -488,7 +491,7 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr, bool top_level) ff_pkt->flags = flags; bclose(&ff_pkt->bfd); if (!stat) { - return 0; + goto bail_out; } } @@ -511,49 +514,46 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr, bool top_level) 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 */ @@ -570,10 +570,7 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr, bool top_level) 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 */ @@ -591,11 +588,25 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr, bool top_level) 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; } /* diff --git a/bacula/src/filed/verify.c b/bacula/src/filed/verify.c index 86403d533f..5727706047 100644 --- a/bacula/src/filed/verify.c +++ b/bacula/src/filed/verify.c @@ -248,7 +248,7 @@ static int verify_file(FF_PKT *ff_pkt, void *pkt, bool top_level) if (digest_file(jcr, ff_pkt, digest) != 0) { jcr->Errors++; - return 1; + goto good_rtn; } if (crypto_digest_finalize(digest, (uint8_t *)md, &size)) { @@ -267,11 +267,13 @@ static int verify_file(FF_PKT *ff_pkt, void *pkt, bool top_level) free(digest_buf); } - - crypto_digest_free(digest); } } +good_rtn: + if (digest) { + crypto_digest_free(digest); + } return 1; } diff --git a/bacula/src/stored/bacula-sd.conf.in b/bacula/src/stored/bacula-sd.conf.in index 4d20586b3b..3840520914 100644 --- a/bacula/src/stored/bacula-sd.conf.in +++ b/bacula/src/stored/bacula-sd.conf.in @@ -76,6 +76,8 @@ 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'" #} #Device { @@ -90,6 +92,8 @@ 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'" #} # @@ -108,6 +112,8 @@ 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'" #} # @@ -126,6 +132,8 @@ Device { # 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'" #} # @@ -144,6 +152,8 @@ Device { ## 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'" #} # @@ -182,6 +192,8 @@ Device { # 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'" #} # @@ -196,6 +208,8 @@ Device { # 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'" #} # diff --git a/bacula/src/version.h b/bacula/src/version.h index 6b3669be46..eabe5ba9a1 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -4,8 +4,8 @@ #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 */ diff --git a/bacula/technotes-2.0 b/bacula/technotes-2.0 index 7bbba84906..4b6fe54b93 100644 --- a/bacula/technotes-2.0 +++ b/bacula/technotes-2.0 @@ -1,6 +1,14 @@ 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. -- 2.39.5