From: Kern Sibbald Date: Sun, 2 Dec 2007 14:19:28 +0000 (+0000) Subject: This patch prevents the 'status dir' command from trying to use a scratch X-Git-Tag: Release-7.0.0~5337 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=285ab2baf7a9351bd32feb23043e89d979bf0d53;p=bacula%2Fbacula This patch prevents the 'status dir' command from trying to use a scratch volume and possibly moving it from one pool to another. This patch fixes bug #1019. + move old patches into subdirectory git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@6010 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/patches/2.2.4-ansi-label.patch b/bacula/patches/2.2.4-ansi-label.patch deleted file mode 100644 index d68e618aca..0000000000 --- a/bacula/patches/2.2.4-ansi-label.patch +++ /dev/null @@ -1,77 +0,0 @@ - - This patch fixes bug #954. - WEOF on non-appendable error when trying to label a tape with ANSI labels turned on. - - Apply it to version 2.2.4 (possibly earlier versions with): - - cd - patch -p0 <2.2.4-verify.patch - ./configure (your options) - make - ... - make install - -Index: block.c -=================================================================== ---- src/stored/block.c (revision 5615) -+++ src/stored/block.c (revision 5615) -@@ -273,6 +273,7 @@ - dev->dev_errno = EIO; - Mmsg4(dev->errmsg, _("Volume data error at %u:%u! Wanted ID: \"%s\", got \"%s\". Buffer discarded.\n"), - dev->file, dev->block_num, BLKHDR2_ID, Id); -+ Dmsg1(50, "%s", dev->errmsg); - if (block->read_errors == 0 || verbose >= 2) { - Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); - } -@@ -1008,8 +1009,19 @@ - dev->set_ateof(); - return false; /* return eof */ - } -+ - /* Continue here for successful read */ -+ - block->read_len = stat; /* save length read */ -+ if (dev->at_eof() && block->read_len == 80 && -+ (dcr->VolCatInfo.LabelType != B_BACULA_LABEL || -+ dcr->device->label_type != B_BACULA_LABEL)) { -+ /* ***FIXME*** should check label */ -+ Dmsg2(100, "Ignore 80 byte ANSI label at %u:%u\n", dev->file, dev->block_num); -+ dev->clear_eof(); -+ goto reread; /* skip ANSI/IBM label */ -+ } -+ - if (block->read_len < BLKHDR2_LENGTH) { - dev->dev_errno = EIO; - Mmsg4(dev->errmsg, _("Volume data error at %u:%u! Very short block of %d bytes on device %s discarded.\n"), - -Index: label.c -=================================================================== ---- src/stored/label.c (revision 5602) -+++ src/stored/label.c (working copy) -@@ -119,7 +119,6 @@ - bstrncpy(dev->VolHdr.Id, "**error**", sizeof(dev->VolHdr.Id)); - - /* Read ANSI/IBM label if so requested */ -- - want_ansi_label = dcr->VolCatInfo.LabelType != B_BACULA_LABEL || - dcr->device->label_type != B_BACULA_LABEL; - if (want_ansi_label || dev->has_cap(CAP_CHECKLABELS)) { -@@ -344,6 +343,9 @@ - } - } - -+ /* Temporarily mark in append state to enable writing */ -+ dev->set_append(); -+ - /* Create PRE_LABEL or VOL_LABEL if DVD */ - create_volume_label(dev, VolName, PoolName, dvdnow); - -@@ -364,8 +366,6 @@ - create_volume_label_record(dcr, dcr->rec); - dcr->rec->Stream = 0; - -- /* Temporarily mark in append state to enable writing */ -- dev->set_append(); - if (!write_record_to_block(dcr->block, dcr->rec)) { - Dmsg2(130, "Bad Label write on %s: ERR=%s\n", dev->print_name(), dev->print_errmsg()); - goto bail_out; diff --git a/bacula/patches/2.2.4-lost-block.patch b/bacula/patches/2.2.4-lost-block.patch deleted file mode 100644 index fbf7122a31..0000000000 --- a/bacula/patches/2.2.4-lost-block.patch +++ /dev/null @@ -1,30 +0,0 @@ - - This patch fixes a race condition where a Job is terminating at the same - time that another job reaches the end of Volume. In that case, sometimes - the last block or two are not written to the Volume. This seems to be - relatively rare, but does result in data loss. This fixes bug #964. - - Apply the patch to Bacula version 2.2.4 (or possibly any previous 2.2.x - version) with: - - cd - patch -p0 <2.2.4-lost-block.patch - ./configure (your options) - make - ... - make install - - -Index: src/stored/append.c -=================================================================== ---- src/stored/append.c (revision 5602) -+++ src/stored/append.c (working copy) -@@ -287,7 +287,7 @@ - * 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 (dev->can_write()) { -+ if (ok || 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()); diff --git a/bacula/patches/2.2.4-parse-command.patch b/bacula/patches/2.2.4-parse-command.patch deleted file mode 100644 index 312dd29efe..0000000000 --- a/bacula/patches/2.2.4-parse-command.patch +++ /dev/null @@ -1,28 +0,0 @@ - - This patch resolves a command parser issue - causing a director segfault when using something - like "run job 1 2" - - Apply to version 2.2.4 (and perhaps older 2.2.x versions) with - - cd - patch -p0 <2.2.4-parse-command.patch - ./configure (your options) - make - ... - make install - - -Index: src/dird/ua_run.c -=================================================================== ---- src/dird/ua_run.c (révision 5616) -+++ src/dird/ua_run.c (copie de travail) -@@ -933,7 +933,7 @@ - /* Note, yes and run have no value, so do not fail */ - if (!ua->argv[i] && j != YES_POS /*yes*/) { - ua->send_msg(_("Value missing for keyword %s\n"), ua->argk[i]); -- return true; -+ return false; - } - Dmsg1(800, "Got keyword=%s\n", NPRT(kw[j])); - switch (j) { diff --git a/bacula/patches/2.2.4-poll-mount.patch b/bacula/patches/2.2.4-poll-mount.patch deleted file mode 100644 index a4676e942f..0000000000 --- a/bacula/patches/2.2.4-poll-mount.patch +++ /dev/null @@ -1,27 +0,0 @@ - - This patch resolves bug #908 where a tape is not properly mounted - (recognized) during a poll. - - Apply to version 2.2.4 (and perhaps older 2.2.x versions) with - - cd - patch -p0 <2.2.4-poll-mount.patch - ./configure (your options) - make - ... - make install - -Index: src/stored/dev.c -=================================================================== ---- src/stored/dev.c (revision 5553) -+++ src/stored/dev.c (working copy) -@@ -1844,7 +1844,8 @@ - - /* Clean up device packet so it can be reused */ - clear_opened(); -- state &= ~(ST_LABEL|ST_READ|ST_APPEND|ST_EOT|ST_WEOT|ST_EOF); -+ state &= ~(ST_LABEL|ST_READ|ST_APPEND|ST_EOT|ST_WEOT|ST_EOF| -+ ST_MOUNTED|ST_MEDIA|ST_SHORT|ST_FREESPACE_OK|ST_PART_SPOOLED); - label_type = B_BACULA_LABEL; - file = block_num = 0; - file_size = 0; diff --git a/bacula/patches/2.2.4-replace.patch b/bacula/patches/2.2.4-replace.patch deleted file mode 100644 index 58e4e5109f..0000000000 --- a/bacula/patches/2.2.4-replace.patch +++ /dev/null @@ -1,24 +0,0 @@ - - This patch resolves bug #969 where the user can't change the - replace option in the restore menu - - Apply to version 2.2.4 (and perhaps older 2.2.x versions) with - - cd - patch -p0 <2.2.4-replace.patch - ./configure (your options) - make - ... - make install - ---- src/dird/ua_run.c (révision 5721) -+++ src/dird/ua_run.c (copie de travail) -@@ -424,6 +424,7 @@ - } - opt = do_prompt(ua, "", _("Select replace option"), NULL, 0); - if (opt >= 0) { -+ rc.replace = ReplaceOptions[opt].name; - jcr->replace = ReplaceOptions[opt].token; - } - goto try_again; - diff --git a/bacula/patches/2.2.4-restore.patch b/bacula/patches/2.2.4-restore.patch deleted file mode 100644 index 3ef991e3b7..0000000000 --- a/bacula/patches/2.2.4-restore.patch +++ /dev/null @@ -1,49 +0,0 @@ - - This patch resolves bug #955 where the director segfault when - where= option isn't specified anywhere. - - Apply to version 2.2.4 (and perhaps older 2.2.x versions) with - - cd - patch -p0 <2.2.4-restore.patch - ./configure (your options) - make - ... - make install - - -Index: src/dird/restore.c -=================================================================== ---- src/dird/restore.c (revision 5601) -+++ src/dird/restore.c (working copy) -@@ -173,7 +173,7 @@ - } - - /* Send restore command */ -- char replace, *where, *cmd=NULL; -+ char replace, *where, *cmd; - char empty = '\0'; - - if (jcr->replace != 0) { -@@ -183,8 +183,6 @@ - } else { - replace = REPLACE_ALWAYS; /* always replace */ - } -- -- where = ∅ /* default */ - - if (jcr->RegexWhere) { - where = jcr->RegexWhere; /* override */ -@@ -199,7 +197,11 @@ - } else if (jcr->job->RestoreWhere) { - where = jcr->job->RestoreWhere; /* no override take from job */ - cmd = restorecmd; -- } -+ -+ } else { /* nothing was specified */ -+ where = ∅ /* use default */ -+ cmd = restorecmd; -+ } - - jcr->prefix_links = jcr->job->PrefixLinks; - diff --git a/bacula/patches/2.2.4-sd-auth-fail.patch b/bacula/patches/2.2.4-sd-auth-fail.patch deleted file mode 100644 index 2e506e7884..0000000000 --- a/bacula/patches/2.2.4-sd-auth-fail.patch +++ /dev/null @@ -1,159 +0,0 @@ - - This patch applies to Bacula version 2.2.4 (possibly earlier 2.2.x versions) - and fixes a Storage daemon authentication problem with the FD. This fixes - bug #953. The patch also adds a bit of additional debug code and significantly - strengthens the SD session key. - - Apply it to 2.2.4 with: - - cd - patch -p0 <2.2.4-sd-auth-fail.patch - make - ... - make install - - -Index: src/stored/job.c -=================================================================== ---- src/stored/job.c (revision 5602) -+++ src/stored/job.c (working copy) -@@ -73,6 +73,7 @@ - { - int JobId; - char auth_key[100]; -+ char seed[100]; - BSOCK *dir = jcr->dir_bsock; - POOL_MEM job_name, client_name, job, fileset_name, fileset_md5; - int JobType, level, spool_attributes, no_attributes, spool_data; -@@ -91,7 +92,7 @@ - &write_part_after_job, &PreferMountedVols); - if (stat != 13) { - pm_strcpy(jcr->errmsg, dir->msg); -- bnet_fsend(dir, BAD_job, stat, jcr->errmsg); -+ dir->fsend(BAD_job, stat, jcr->errmsg); - Dmsg1(100, ">dird: %s", dir->msg); - set_jcr_job_status(jcr, JS_ErrorTerminated); - return false; -@@ -134,9 +135,10 @@ - /* - * Pass back an authorization key for the File daemon - */ -- make_session_key(auth_key, NULL, 1); -- bnet_fsend(dir, OKjob, jcr->VolSessionId, jcr->VolSessionTime, auth_key); -- Dmsg1(100, ">dird: %s", dir->msg); -+ bsnprintf(seed, sizeof(seed), "%p%d", jcr, JobId); -+ make_session_key(auth_key, seed, 1); -+ dir->fsend(OKjob, jcr->VolSessionId, jcr->VolSessionTime, auth_key); -+ Dmsg2(100, ">dird jid=%u: %s", (uint32_t)jcr->JobId, dir->msg); - jcr->sd_auth_key = bstrdup(auth_key); - memset(auth_key, 0, sizeof(auth_key)); - generate_daemon_event(jcr, "JobStart"); -@@ -169,17 +171,18 @@ - timeout.tv_nsec = tv.tv_usec * 1000; - timeout.tv_sec = tv.tv_sec + me->client_wait; - -- Dmsg2(100, "%s waiting %d sec for FD to contact SD\n", -- jcr->Job, (int)me->client_wait); -+ Dmsg3(050, "%s waiting %d sec for FD to contact SD key=%s\n", -+ jcr->Job, (int)me->client_wait, jcr->sd_auth_key); -+ - /* - * Wait for the File daemon to contact us to start the Job, - * when he does, we will be released, unless the 30 minutes - * expires. - */ - P(mutex); -- for ( ; !job_canceled(jcr); ) { -+ while ( !jcr->authenticated && !job_canceled(jcr) ) { - errstat = pthread_cond_timedwait(&jcr->job_start_wait, &mutex, &timeout); -- if (errstat == 0 || errstat == ETIMEDOUT) { -+ if (errstat == ETIMEDOUT || errstat == EINVAL || errstat == EPERM) { - break; - } - } -@@ -195,7 +198,7 @@ - } - - /* -- * After receiving a connection (in job.c) if it is -+ * After receiving a connection (in dircmd.c) if it is - * from the File daemon, this routine is called. - */ - void handle_filed_connection(BSOCK *fd, char *job_name) -@@ -204,8 +207,8 @@ - - bmicrosleep(0, 50000); /* wait 50 millisecs */ - if (!(jcr=get_jcr_by_full_name(job_name))) { -- Jmsg1(NULL, M_FATAL, 0, _("Job name not found: %s\n"), job_name); -- Dmsg1(100, "Job name not found: %s\n", job_name); -+ Jmsg1(NULL, M_FATAL, 0, _("FD connect failed: Job name not found: %s\n"), job_name); -+ Dmsg1(3, "**** Job \"%s\" not found", job_name); - return; - } - -@@ -216,7 +219,7 @@ - - if (jcr->authenticated) { - Jmsg2(jcr, M_FATAL, 0, _("Hey!!!! JobId %u Job %s already authenticated.\n"), -- jcr->JobId, jcr->Job); -+ (uint32_t)jcr->JobId, jcr->Job); - free_jcr(jcr); - return; - } -@@ -229,7 +232,7 @@ - Jmsg(jcr, M_FATAL, 0, _("Unable to authenticate File daemon\n")); - } else { - jcr->authenticated = true; -- Dmsg1(110, "OK Authentication Job %s\n", jcr->Job); -+ Dmsg2(110, "OK Authentication jid=%u Job %s\n", (uint32_t)jcr->JobId, jcr->Job); - } - - if (!jcr->authenticated) { -@@ -274,9 +277,9 @@ - } - ok = dir_update_device(jcr, device->dev); - if (ok) { -- ok = bnet_fsend(dir, OK_query); -+ ok = dir->fsend(OK_query); - } else { -- bnet_fsend(dir, NO_query); -+ dir->fsend(NO_query); - } - return ok; - } -@@ -289,9 +292,9 @@ - } - ok = dir_update_changer(jcr, changer); - if (ok) { -- ok = bnet_fsend(dir, OK_query); -+ ok = dir->fsend(OK_query); - } else { -- bnet_fsend(dir, NO_query); -+ dir->fsend(NO_query); - } - return ok; - } -@@ -299,12 +302,12 @@ - /* If we get here, the device/autochanger was not found */ - unbash_spaces(dir->msg); - pm_strcpy(jcr->errmsg, dir->msg); -- bnet_fsend(dir, NO_device, dev_name.c_str()); -+ dir->fsend(NO_device, dev_name.c_str()); - Dmsg1(100, ">dird: %s\n", dir->msg); - } else { - unbash_spaces(dir->msg); - pm_strcpy(jcr->errmsg, dir->msg); -- bnet_fsend(dir, BAD_query, jcr->errmsg); -+ dir->fsend(BAD_query, jcr->errmsg); - Dmsg1(100, ">dird: %s\n", dir->msg); - } - -@@ -322,7 +325,7 @@ - { - Dmsg1(900, "stored_free_jcr JobId=%u\n", jcr->JobId); - if (jcr->file_bsock) { -- bnet_close(jcr->file_bsock); -+ jcr->file_bsock->close(); - jcr->file_bsock = NULL; - } - if (jcr->job_name) { diff --git a/bacula/patches/2.2.4-sql.patch b/bacula/patches/2.2.4-sql.patch deleted file mode 100644 index 24de09994c..0000000000 --- a/bacula/patches/2.2.4-sql.patch +++ /dev/null @@ -1,476 +0,0 @@ - - This patch fixes several problems: it fixes incorrect or incomplete error - messages; it fixes a problem opening the SQLite3 database when multiple - simultaneous jobs were running; it fixes a bug with certain versions of - MySQL where batch inserts failed because of table name character case - (upper/lower) differences. - - It can be applied to version 2.2.4 (and possibly earlier 2.2.x versions) - with: - - cd - patch -p0 <2.2.4-sql.patch - ./configure (your options) - make - ... - make install - - - -Index: src/cats/sql.c -=================================================================== ---- src/cats/sql.c (revision 5687) -+++ src/cats/sql.c (working copy) -@@ -115,7 +115,6 @@ - - bacula_db_version = 0; - if (!db_sql_query(mdb, query, int_handler, (void *)&bacula_db_version)) { -- Mmsg(mdb->errmsg, "Database not created or server not running.\n"); - Jmsg(jcr, M_FATAL, 0, "%s", mdb->errmsg); - return false; - } -Index: src/cats/sqlite.c -=================================================================== ---- src/cats/sqlite.c (revision 5687) -+++ src/cats/sqlite.c (working copy) -@@ -148,6 +148,7 @@ - int len; - struct stat statbuf; - int errstat; -+ int retry = 0; - - P(mutex); - if (mdb->connected) { -@@ -157,8 +158,9 @@ - mdb->connected = FALSE; - - if ((errstat=rwl_init(&mdb->lock)) != 0) { -+ berrno be; - Mmsg1(&mdb->errmsg, _("Unable to initialize DB lock. ERR=%s\n"), -- strerror(errstat)); -+ be.bstrerror(errstat)); - V(mutex); - return 0; - } -@@ -178,28 +180,28 @@ - return 0; - } - -+ for (mdb->db=NULL; !mdb->db && retry++ < 10; ) { - #ifdef HAVE_SQLITE3 -- int stat = sqlite3_open(db_name, &mdb->db); -- if (stat != SQLITE_OK) { -- mdb->sqlite_errmsg = (char *)sqlite3_errmsg(mdb->db); -- sqlite3_close(mdb->db); -- mdb->db = NULL; -- } else { -- mdb->sqlite_errmsg = NULL; -- } --#ifdef SQLITE3_INIT_QUERY -- db_sql_query(mdb, SQLITE3_INIT_QUERY, NULL, NULL); --#endif -- -+ int stat = sqlite3_open(db_name, &mdb->db); -+ if (stat != SQLITE_OK) { -+ mdb->sqlite_errmsg = (char *)sqlite3_errmsg(mdb->db); -+ sqlite3_close(mdb->db); -+ mdb->db = NULL; -+ } else { -+ mdb->sqlite_errmsg = NULL; -+ } - #else -- mdb->db = sqlite_open( -- db_name, /* database name */ -- 644, /* mode */ -- &mdb->sqlite_errmsg); /* error message */ -+ mdb->db = sqlite_open( -+ db_name, /* database name */ -+ 644, /* mode */ -+ &mdb->sqlite_errmsg); /* error message */ - #endif - -- Dmsg0(300, "sqlite_open\n"); -- -+ Dmsg0(300, "sqlite_open\n"); -+ if (!mdb->db) { -+ bmicrosleep(1, 0); -+ } -+ } - if (mdb->db == NULL) { - Mmsg2(&mdb->errmsg, _("Unable to open Database=%s. ERR=%s\n"), - db_name, mdb->sqlite_errmsg ? mdb->sqlite_errmsg : _("unknown")); -@@ -209,10 +211,6 @@ - } - mdb->connected = true; - free(db_name); -- if (!check_tables_version(jcr, mdb)) { -- V(mutex); -- return 0; -- } - - /* set busy handler to wait when we use mult_db_connections = 1 */ - #ifdef HAVE_SQLITE3 -@@ -221,6 +219,16 @@ - sqlite_busy_handler(mdb->db, my_busy_handler, NULL); - #endif - -+#if defined(HAVE_SQLITE3) && defined(SQLITE3_INIT_QUERY) -+ db_sql_query(mdb, SQLITE3_INIT_QUERY, NULL, NULL); -+#endif -+ -+ if (!check_tables_version(jcr, mdb)) { -+ V(mutex); -+ return 0; -+ } -+ -+ - V(mutex); - return 1; - } -@@ -448,16 +456,20 @@ - return mdb->fields[mdb->field++]; - } - --char *my_sqlite_batch_lock_query = "BEGIN"; --char *my_sqlite_batch_unlock_query = "COMMIT"; --char *my_sqlite_batch_fill_path_query = "INSERT INTO Path (Path) " -- " SELECT DISTINCT Path FROM batch " -- " EXCEPT SELECT Path FROM Path "; -+#ifdef HAVE_BATCH_FILE_INSERT -+const char *my_sqlite_batch_lock_query = "BEGIN"; -+const char *my_sqlite_batch_unlock_query = "COMMIT"; - --char *my_sqlite_batch_fill_filename_query = "INSERT INTO Filename (Name) " -- " SELECT DISTINCT Name FROM batch " -- " EXCEPT SELECT Name FROM Filename "; -+const char *my_sqlite_batch_fill_path_query = -+ "INSERT INTO Path (Path)" -+ " SELECT DISTINCT Path FROM batch" -+ " EXCEPT SELECT Path FROM Path"; - -+const char *my_sqlite_batch_fill_filename_query = -+ "INSERT INTO Filename (Name)" -+ " SELECT DISTINCT Name FROM batch " -+ " EXCEPT SELECT Name FROM Filename"; -+#endif /* HAVE_BATCH_FILE_INSERT */ - - - #endif /* HAVE_SQLITE */ -Index: src/cats/cats.h -=================================================================== ---- src/cats/cats.h (revision 5687) -+++ src/cats/cats.h (working copy) -@@ -187,10 +187,10 @@ - int my_sqlite_query(B_DB *mdb, const char *cmd); - void my_sqlite_field_seek(B_DB *mdb, int field); - SQL_FIELD *my_sqlite_fetch_field(B_DB *mdb); --extern char* my_sqlite_batch_lock_query; --extern char* my_sqlite_batch_unlock_query; --extern char* my_sqlite_batch_fill_filename_query; --extern char* my_sqlite_batch_fill_path_query; -+extern const char* my_sqlite_batch_lock_query; -+extern const char* my_sqlite_batch_unlock_query; -+extern const char* my_sqlite_batch_fill_filename_query; -+extern const char* my_sqlite_batch_fill_path_query; - - - #else -@@ -317,10 +317,10 @@ - int my_sqlite_query(B_DB *mdb, const char *cmd); - void my_sqlite_field_seek(B_DB *mdb, int field); - SQL_FIELD *my_sqlite_fetch_field(B_DB *mdb); --extern char* my_sqlite_batch_lock_query; --extern char* my_sqlite_batch_unlock_query; --extern char* my_sqlite_batch_fill_filename_query; --extern char* my_sqlite_batch_fill_path_query; -+extern const char* my_sqlite_batch_lock_query; -+extern const char* my_sqlite_batch_unlock_query; -+extern const char* my_sqlite_batch_fill_filename_query; -+extern const char* my_sqlite_batch_fill_path_query; - - - #else -@@ -398,11 +398,11 @@ - #define sql_batch_fill_path_query my_mysql_batch_fill_path_query - - --extern char* my_mysql_batch_lock_path_query; --extern char* my_mysql_batch_lock_filename_query; --extern char* my_mysql_batch_unlock_tables_query; --extern char* my_mysql_batch_fill_filename_query; --extern char* my_mysql_batch_fill_path_query; -+extern const char* my_mysql_batch_lock_path_query; -+extern const char* my_mysql_batch_lock_filename_query; -+extern const char* my_mysql_batch_unlock_tables_query; -+extern const char* my_mysql_batch_fill_filename_query; -+extern const char* my_mysql_batch_fill_path_query; - extern void my_mysql_free_result(B_DB *mdb); - - #else -@@ -486,11 +486,11 @@ - int my_postgresql_batch_insert(JCR *jcr, B_DB *mdb, ATTR_DBR *ar); - char *my_postgresql_copy_escape(char *dest, char *src, size_t len); - --extern char* my_pg_batch_lock_path_query; --extern char* my_pg_batch_lock_filename_query; --extern char* my_pg_batch_unlock_tables_query; --extern char* my_pg_batch_fill_filename_query; --extern char* my_pg_batch_fill_path_query; -+extern const char* my_pg_batch_lock_path_query; -+extern const char* my_pg_batch_lock_filename_query; -+extern const char* my_pg_batch_unlock_tables_query; -+extern const char* my_pg_batch_fill_filename_query; -+extern const char* my_pg_batch_fill_path_query; - - /* "Generic" names for easier conversion */ - #define sql_store_result(x) ((x)->result) -Index: src/cats/mysql.c -=================================================================== ---- src/cats/mysql.c (revision 5687) -+++ src/cats/mysql.c (working copy) -@@ -149,8 +149,9 @@ - } - - if ((errstat=rwl_init(&mdb->lock)) != 0) { -+ berrno be; - Mmsg1(&mdb->errmsg, _("Unable to initialize DB lock. ERR=%s\n"), -- strerror(errstat)); -+ be.bstrerror(errstat)); - V(mutex); - return 0; - } -@@ -403,33 +404,27 @@ - db_unlock(mdb); - } - --char *my_mysql_batch_lock_path_query = "LOCK TABLES Path write, " -- " batch write, " -- " Path as p write "; -+#ifdef HAVE_BATCH_FILE_INSERT -+const char *my_mysql_batch_lock_path_query = -+ "LOCK TABLES Path write, batch write, Path as p write"; - - --char *my_mysql_batch_lock_filename_query = "LOCK TABLES Filename write, " -- " batch write, " -- " Filename as f write "; -+const char *my_mysql_batch_lock_filename_query = -+ "LOCK TABLES Filename write, batch write, Filename as f write"; - --char *my_mysql_batch_unlock_tables_query = "UNLOCK TABLES"; -+const char *my_mysql_batch_unlock_tables_query = "UNLOCK TABLES"; - --char *my_mysql_batch_fill_path_query = "INSERT INTO Path (Path) " -- " SELECT a.Path FROM " -- " (SELECT DISTINCT Path " -- " FROM batch) AS a " -- " WHERE NOT EXISTS " -- " (SELECT Path " -- " FROM Path AS p " -- " WHERE p.Path = a.Path) "; -+const char *my_mysql_batch_fill_path_query = -+ "INSERT INTO Path (Path) " -+ "SELECT a.Path FROM " -+ "(SELECT DISTINCT Path FROM batch) AS a WHERE NOT EXISTS " -+ "(SELECT Path FROM Path AS p WHERE p.Path = a.Path)"; - --char *my_mysql_batch_fill_filename_query = "INSERT INTO Filename (Name) " -- " SELECT a.Name FROM " -- " (SELECT DISTINCT Name " -- " FROM batch) AS a " -- " WHERE NOT EXISTS " -- " (SELECT Name " -- " FROM Filename AS f " -- " WHERE f.Name = a.Name) "; -+const char *my_mysql_batch_fill_filename_query = -+ "INSERT INTO Filename (Name) " -+ "SELECT a.Name FROM " -+ "(SELECT DISTINCT Name FROM batch) AS a WHERE NOT EXISTS " -+ "(SELECT Name FROM Filename AS f WHERE f.Name = a.Name)"; -+#endif /* HAVE_BATCH_FILE_INSERT */ - - #endif /* HAVE_MYSQL */ -Index: src/cats/sql_create.c -=================================================================== ---- src/cats/sql_create.c (revision 5687) -+++ src/cats/sql_create.c (working copy) -@@ -668,6 +668,8 @@ - * }; - */ - -+#ifdef HAVE_BATCH_FILE_INSERT -+ - /* All sql_batch_* functions are used to do bulk batch insert in File/Filename/Path - * tables. This code can be activated by adding "#define HAVE_BATCH_FILE_INSERT 1" - * in baconfig.h -@@ -690,13 +692,13 @@ - - db_lock(mdb); - ok = db_sql_query(mdb, -- " CREATE TEMPORARY TABLE batch " -- " (fileindex integer, " -- " jobid integer, " -- " path blob, " -- " name blob, " -- " lstat tinyblob, " -- " md5 tinyblob) ",NULL, NULL); -+ "CREATE TEMPORARY TABLE batch (" -+ "FileIndex integer," -+ "JobId integer," -+ "Path blob," -+ "Name blob," -+ "LStat tinyblob," -+ "MD5 tinyblob)",NULL, NULL); - db_unlock(mdb); - return ok; - } -@@ -746,7 +748,6 @@ - return true; - } - --#ifdef HAVE_BATCH_FILE_INSERT - /* - * Returns 1 if OK - * 0 if failed -@@ -794,7 +795,7 @@ - - if (!db_sql_query(jcr->db_batch,sql_batch_fill_filename_query, NULL,NULL)) { - Jmsg(jcr,M_FATAL,0,"Can't fill Filename table %s\n",jcr->db_batch->errmsg); -- QUERY_DB(jcr, jcr->db_batch, sql_batch_unlock_tables_query); -+ db_sql_query(jcr->db_batch, sql_batch_unlock_tables_query, NULL, NULL); - return false; - } - -@@ -804,12 +805,12 @@ - } - - if (!db_sql_query(jcr->db_batch, -- " INSERT INTO File (FileIndex, JobId, PathId, FilenameId, LStat, MD5)" -- " SELECT batch.FileIndex, batch.JobId, Path.PathId, " -- " Filename.FilenameId,batch.LStat, batch.MD5 " -- " FROM batch " -- " JOIN Path ON (batch.Path = Path.Path) " -- " JOIN Filename ON (batch.Name = Filename.Name) ", -+ "INSERT INTO File (FileIndex, JobId, PathId, FilenameId, LStat, MD5)" -+ "SELECT batch.FileIndex, batch.JobId, Path.PathId, " -+ "Filename.FilenameId,batch.LStat, batch.MD5 " -+ "FROM batch " -+ "JOIN Path ON (batch.Path = Path.Path) " -+ "JOIN Filename ON (batch.Name = Filename.Name)", - NULL,NULL)) - { - Jmsg(jcr, M_FATAL, 0, "Can't fill File table %s\n", jcr->db_batch->errmsg); -@@ -845,19 +846,24 @@ - mdb->db_port, - mdb->db_socket, - 1 /* multi_db = true */); -+ if (!jcr->db_batch) { -+ Mmsg1(&mdb->errmsg, _("Could not init batch database: \"%s\".\n"), -+ jcr->db->db_name); -+ Jmsg1(jcr, M_FATAL, 0, "%s", mdb->errmsg); -+ return false; -+ } - -- if (!jcr->db_batch || !db_open_database(jcr, jcr->db_batch)) { -- Jmsg(jcr, M_FATAL, 0, _("Could not open database \"%s\".\n"), -- jcr->db->db_name); -- if (jcr->db_batch) { -- Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db_batch)); -- } -+ if (!db_open_database(jcr, jcr->db_batch)) { -+ Mmsg2(&mdb->errmsg, _("Could not open database \"%s\": ERR=%s\n"), -+ jcr->db->db_name, db_strerror(jcr->db_batch)); -+ Jmsg1(jcr, M_FATAL, 0, "%s", mdb->errmsg); - return false; - } - - if (!sql_batch_start(jcr, jcr->db_batch)) { -- Jmsg(jcr, M_FATAL, 0, -- "Can't start batch mode %s", db_strerror(jcr->db_batch)); -+ Mmsg1(&mdb->errmsg, -+ "Can't start batch mode: ERR=%s", db_strerror(jcr->db_batch)); -+ Jmsg1(jcr, M_FATAL, 0, "%s", mdb->errmsg); - return false; - } - Dmsg3(100, "initdb ref=%d connected=%d db=%p\n", jcr->db_batch->ref_count, -@@ -870,10 +876,10 @@ - */ - if (!(ar->Stream == STREAM_UNIX_ATTRIBUTES || - ar->Stream == STREAM_UNIX_ATTRIBUTES_EX)) { -- Mmsg1(&bdb->errmsg, _("Attempt to put non-attributes into catalog. Stream=%d\n"), -+ Mmsg1(&mdb->errmsg, _("Attempt to put non-attributes into catalog. Stream=%d\n"), - ar->Stream); -- Jmsg(jcr, M_ERROR, 0, "%s", bdb->errmsg); -- return 0; -+ Jmsg(jcr, M_FATAL, 0, "%s", mdb->errmsg); -+ return false; - } - - split_path_and_file(jcr, bdb, ar->fname); -Index: src/cats/postgresql.c -=================================================================== ---- src/cats/postgresql.c (revision 5687) -+++ src/cats/postgresql.c (working copy) -@@ -605,13 +605,13 @@ - Dmsg0(500, "my_postgresql_batch_start started\n"); - - if (my_postgresql_query(mdb, -- " CREATE TEMPORARY TABLE batch " -- " (fileindex int, " -- " jobid int, " -- " path varchar, " -- " name varchar, " -- " lstat varchar, " -- " md5 varchar)") == 1) -+ "CREATE TEMPORARY TABLE batch (" -+ "fileindex int," -+ "jobid int," -+ "path varchar," -+ "name varchar," -+ "lstat varchar," -+ "md5 varchar)") == 1) - { - Dmsg0(500, "my_postgresql_batch_start failed\n"); - return 1; -@@ -785,22 +785,29 @@ - return dest; - } - --char *my_pg_batch_lock_path_query = "BEGIN; LOCK TABLE Path IN SHARE ROW EXCLUSIVE MODE"; -+#ifdef HAVE_BATCH_FILE_INSERT -+const char *my_pg_batch_lock_path_query = -+ "BEGIN; LOCK TABLE Path IN SHARE ROW EXCLUSIVE MODE"; - - --char *my_pg_batch_lock_filename_query = "BEGIN; LOCK TABLE Filename IN SHARE ROW EXCLUSIVE MODE"; -+const char *my_pg_batch_lock_filename_query = -+ "BEGIN; LOCK TABLE Filename IN SHARE ROW EXCLUSIVE MODE"; - --char *my_pg_batch_unlock_tables_query = "COMMIT"; -+const char *my_pg_batch_unlock_tables_query = "COMMIT"; - --char *my_pg_batch_fill_path_query = "INSERT INTO Path (Path) " -- " SELECT a.Path FROM " -- " (SELECT DISTINCT Path FROM batch) AS a " -- " WHERE NOT EXISTS (SELECT Path FROM Path WHERE Path = a.Path) "; -+const char *my_pg_batch_fill_path_query = -+ "INSERT INTO Path (Path) " -+ "SELECT a.Path FROM " -+ "(SELECT DISTINCT Path FROM batch) AS a " -+ "WHERE NOT EXISTS (SELECT Path FROM Path WHERE Path = a.Path) "; - - --char *my_pg_batch_fill_filename_query = "INSERT INTO Filename (Name) " -- " SELECT a.Name FROM " -- " (SELECT DISTINCT Name FROM batch) as a " -- " WHERE NOT EXISTS " -- " (SELECT Name FROM Filename WHERE Name = a.Name)"; -+const char *my_pg_batch_fill_filename_query = -+ "INSERT INTO Filename (Name) " -+ "SELECT a.Name FROM " -+ "(SELECT DISTINCT Name FROM batch) as a " -+ "WHERE NOT EXISTS " -+ "(SELECT Name FROM Filename WHERE Name = a.Name)"; -+#endif /* HAVE_BATCH_FILE_INSERT */ -+ - #endif /* HAVE_POSTGRESQL */ diff --git a/bacula/patches/2.2.4-verify.patch b/bacula/patches/2.2.4-verify.patch deleted file mode 100644 index 21e9af3442..0000000000 --- a/bacula/patches/2.2.4-verify.patch +++ /dev/null @@ -1,75 +0,0 @@ - This patch fixes bug #958 A Verify catalog Job that has differences reports Verify OK. - - Apply it to version 2.2.4 (possibly earlier versions with): - - cd - patch -p0 <2.2.4-verify.patch - ./configure (your options) - make - ... - make install - -Index: src/dird/verify.c -=================================================================== ---- src/dird/verify.c (revision 5553) -+++ src/dird/verify.c (working copy) -@@ -332,13 +332,10 @@ - } - - stat = wait_for_job_termination(jcr); -- if (stat == JS_Terminated) { -- verify_cleanup(jcr, stat); -- return true; -- } -+ verify_cleanup(jcr, stat); -+ return true; - - bail_out: -- verify_cleanup(jcr, JS_ErrorTerminated); - return false; - } - -@@ -421,7 +418,7 @@ - jobstatus_to_ascii(jcr->FDJobStatus, fd_term_msg, sizeof(fd_term_msg)); - if (jcr->JobLevel == L_VERIFY_VOLUME_TO_CATALOG) { - jobstatus_to_ascii(jcr->SDJobStatus, sd_term_msg, sizeof(sd_term_msg)); -- Jmsg(jcr, msg_type, 0, _("Bacula %s %s (%s): %s\n" -+ Jmsg(jcr, msg_type, 0, _("Bacula %s %s (%s): %s\n" - " Build OS: %s %s %s\n" - " JobId: %d\n" - " Job: %s\n" -@@ -456,7 +453,7 @@ - sd_term_msg, - term_msg); - } else { -- Jmsg(jcr, msg_type, 0, _("Bacula %s %s (%s): %s\n" -+ Jmsg(jcr, msg_type, 0, _("Bacula %s %s (%s): %s\n" - " Build: %s %s %s\n" - " JobId: %d\n" - " Job: %s\n" -@@ -750,7 +747,9 @@ - stat = JS_Differences; - } - free_pool_memory(fname); -- set_jcr_job_status(jcr, stat); -+ if (!job_canceled(jcr)) { -+ jcr->JobStatus = stat; -+ } - return stat == JS_Terminated; - } - -Index: src/lib/jcr.c -=================================================================== ---- src/lib/jcr.c (revision 5553) -+++ src/lib/jcr.c (working copy) -@@ -614,9 +614,8 @@ - /* Override more minor status */ - jcr->JobStatus = JobStatus; - break; -- default: -- break; - } -+ break; - default: - jcr->JobStatus = JobStatus; - } diff --git a/bacula/patches/2.2.5-deamon.patch b/bacula/patches/2.2.5-deamon.patch deleted file mode 100644 index 6e82f1ea87..0000000000 --- a/bacula/patches/2.2.5-deamon.patch +++ /dev/null @@ -1,40 +0,0 @@ - - This patch fixes the default behavior of a non-DEVELOPER version of Bacula - to close STDIN, STDOUT, and STDERR so that an ssh that starts bacula - will not hang. It also fixes a crash in bat when bat is executed and - cannot connect to the Director (e.g. it is not running). - This patch fixes bugs #991 and #993. - - Apply this fix to Bacula version 2.2.5 with: - - cd - patch -p0 <2.2.5-daemon.patch - ./configure (your options) - make - ... - make install - - -Index: src/lib/message.c -=================================================================== ---- src/lib/message.c (revision 5744) -+++ src/lib/message.c (working copy) -@@ -52,7 +52,8 @@ - */ - const char *working_directory = NULL; /* working directory path stored here */ - int verbose = 0; /* increase User messages */ --int debug_level = 1; /* debug level */ -+/* Keep debug level set to zero by default */ -+int debug_level = 0; /* debug level */ - time_t daemon_start_time = 0; /* Daemon start time */ - const char *version = VERSION " (" BDATE ")"; - char my_name[30]; /* daemon name is stored here */ -@@ -1338,7 +1339,7 @@ - jcr = get_jcr_from_tsd(); - } - /* If no jcr or dequeuing send to daemon to avoid recursion */ -- if (!jcr || jcr->dequeuing) { -+ if ((jcr && !jcr->msg_queue) || !jcr || jcr->dequeuing) { - /* jcr==NULL => daemon message, safe to send now */ - Jmsg(jcr, item->type, item->mtime, "%s", item->msg); - free(item); diff --git a/bacula/patches/2.2.5-hb.patch b/bacula/patches/2.2.5-hb.patch deleted file mode 100644 index b8d81c879d..0000000000 --- a/bacula/patches/2.2.5-hb.patch +++ /dev/null @@ -1,186 +0,0 @@ - - This patch fixes bug #947 where a large number of emails were generated - because the heartbeat interval was small and the tape in the drive did - not correspond to the one wanted by Bacula. - - Apply the patch to version 2.2.5 (and probably any 2.2.x version) with: - - cd - ./configure - patch -p0 <2.2.5-hb.patch - make - ... - make install - - -Index: src/stored/wait.c -=================================================================== ---- src/stored/wait.c (revision 5814) -+++ src/stored/wait.c (working copy) -@@ -40,9 +40,8 @@ - #include "bacula.h" /* pull in global headers */ - #include "stored.h" /* pull in Storage Deamon headers */ - --//static bool double_jcr_wait_time(JCR *jcr); -+const int dbglvl = 400; - -- - /* - * Wait for SysOp to mount a tape on a specific device - * -@@ -62,7 +61,7 @@ - JCR *jcr = dcr->jcr; - - dev->dlock(); -- Dmsg1(100, "Enter blocked=%s\n", dev->print_blocked()); -+ Dmsg1(dbglvl, "Enter blocked=%s\n", dev->print_blocked()); - unmounted = is_device_unmounted(dev); - - dev->poll = false; -@@ -84,27 +83,28 @@ - } - - if (!unmounted) { -- Dmsg1(400, "blocked=%s\n", dev->print_blocked()); -+ Dmsg1(dbglvl, "blocked=%s\n", dev->print_blocked()); - dev->dev_prev_blocked = dev->blocked(); - dev->set_blocked(BST_WAITING_FOR_SYSOP); /* indicate waiting for mount */ - } - - for ( ; !job_canceled(jcr); ) { -- time_t now, start; -+ time_t now, start, total_waited; - - gettimeofday(&tv, &tz); - timeout.tv_nsec = tv.tv_usec * 1000; - timeout.tv_sec = tv.tv_sec + add_wait; - -- Dmsg4(400, "I'm going to sleep on device %s. HB=%d wait=%d add_wait=%d\n", -- dev->print_name(), (int)me->heartbeat_interval, dev->wait_sec, add_wait); -+ Dmsg4(dbglvl, "I'm going to sleep on device %s. HB=%d rem_wait=%d add_wait=%d\n", -+ dev->print_name(), (int)me->heartbeat_interval, dev->rem_wait_sec, add_wait); - start = time(NULL); - /* Wait required time */ - stat = pthread_cond_timedwait(&dev->wait_next_vol, &dev->m_mutex, &timeout); -- Dmsg2(400, "Wokeup from sleep on device stat=%d blocked=%s\n", stat, -+ Dmsg2(dbglvl, "Wokeup from sleep on device stat=%d blocked=%s\n", stat, - dev->print_blocked()); - - now = time(NULL); -+ total_waited = now - first_start; - dev->rem_wait_sec -= (now - start); - - /* Note, this always triggers the first time. We want that. */ -@@ -113,7 +113,7 @@ - /* send heartbeats */ - if (jcr->file_bsock) { - jcr->file_bsock->signal(BNET_HEARTBEAT); -- Dmsg0(400, "Send heartbeat to FD.\n"); -+ Dmsg0(dbglvl, "Send heartbeat to FD.\n"); - } - if (jcr->dir_bsock) { - jcr->dir_bsock->signal(BNET_HEARTBEAT); -@@ -131,7 +131,7 @@ - - - if (dev->rem_wait_sec <= 0) { /* on exceeding wait time return */ -- Dmsg0(400, "Exceed wait time.\n"); -+ Dmsg0(dbglvl, "Exceed wait time.\n"); - stat = W_TIMEOUT; - break; - } -@@ -142,8 +142,8 @@ - unmounted = is_device_unmounted(dev); - - if (!unmounted && dev->vol_poll_interval && -- (now - first_start >= dev->vol_poll_interval)) { -- Dmsg1(400, "In wait blocked=%s\n", dev->print_blocked()); -+ (total_waited >= dev->vol_poll_interval)) { -+ Dmsg1(dbglvl, "poll return in wait blocked=%s\n", dev->print_blocked()); - dev->poll = true; /* returning a poll event */ - stat = W_POLL; - break; -@@ -152,6 +152,7 @@ - * Check if user mounted the device while we were waiting - */ - if (dev->blocked() == BST_MOUNT) { /* mount request ? */ -+ Dmsg0(dbglvl, "Mounted return.\n"); - stat = W_MOUNT; - break; - } -@@ -160,30 +161,39 @@ - * If we did not timeout, then some event happened, so - * return to check if state changed. - */ -- if (stat != 0) { -+ if (stat != ETIMEDOUT) { -+ berrno be; -+ Dmsg2(dbglvl, "Wake return. stat=%d. ERR=%s\n", stat, be.bstrerror(stat)); - stat = W_WAKE; /* someone woke us */ - break; - } - - /* - * At this point, we know we woke up because of a timeout, -- * that was due to a heartbeat, so we just update -- * the wait counters and continue. -+ * that was due to a heartbeat, because any other reason would -+ * have caused us to return, so update the wait counters and continue. - */ -- add_wait = dev->wait_sec - (now - start); -+ add_wait = dev->rem_wait_sec; -+ if (me->heartbeat_interval && add_wait > me->heartbeat_interval) { -+ add_wait = me->heartbeat_interval; -+ } -+ /* If the user did not unmount the tape and we are polling, ensure -+ * that we poll at the correct interval. -+ */ -+ if (!unmounted && dev->vol_poll_interval && -+ add_wait > dev->vol_poll_interval - total_waited) { -+ add_wait = dev->vol_poll_interval - total_waited; -+ } - if (add_wait < 0) { - add_wait = 0; - } -- if (me->heartbeat_interval && add_wait > me->heartbeat_interval) { -- add_wait = me->heartbeat_interval; -- } - } - - if (!unmounted) { - dev->set_blocked(dev->dev_prev_blocked); /* restore entry state */ -- Dmsg1(400, "set %s\n", dev->print_blocked()); -+ Dmsg1(dbglvl, "set %s\n", dev->print_blocked()); - } -- Dmsg1(400, "Exit blocked=%s\n", dev->print_blocked()); -+ Dmsg1(dbglvl, "Exit blocked=%s\n", dev->print_blocked()); - dev->dunlock(); - return stat; - } -@@ -209,7 +219,7 @@ - const int max_wait_time = 1 * 60; /* wait 1 minute */ - char ed1[50]; - -- Dmsg0(100, "Enter wait_for_device\n"); -+ Dmsg0(dbglvl, "Enter wait_for_device\n"); - P(device_release_mutex); - - if (++retries % 5 == 0) { -@@ -222,14 +232,14 @@ - timeout.tv_nsec = tv.tv_usec * 1000; - timeout.tv_sec = tv.tv_sec + max_wait_time; - -- Dmsg1(100, "JobId=%u going to wait for a device.\n", (uint32_t)jcr->JobId); -+ Dmsg0(dbglvl, "Going to wait for a device.\n"); - - /* Wait required time */ - stat = pthread_cond_timedwait(&wait_device_release, &device_release_mutex, &timeout); -- Dmsg2(100, "JobId=%u wokeup from sleep on device stat=%d\n", (uint32_t)jcr->JobId, stat); -+ Dmsg1(dbglvl, "Wokeup from sleep on device stat=%d\n", stat); - - V(device_release_mutex); -- Dmsg2(100, "JobId=%u return from wait_device ok=%d\n", (uint32_t)jcr->JobId, ok); -+ Dmsg1(dbglvl, "Return from wait_device ok=%d\n", ok); - return ok; - } - diff --git a/bacula/patches/2.2.5-lastwritten.patch b/bacula/patches/2.2.5-lastwritten.patch deleted file mode 100644 index c5373bcfec..0000000000 --- a/bacula/patches/2.2.5-lastwritten.patch +++ /dev/null @@ -1,41 +0,0 @@ - - This bug fixes the LastWritten field which was updated during - a restore (or a reading migration) - This fixes bug #982 - - This patch applies to Bacula version 2.2.5 (and previous versions), - and can be applied with the following: - - cd - patch -p0 <2.2.5-lastwritten.patch - ./configure (your options) - make - ... - make install - - - -Index: src/dird/catreq.c -=================================================================== ---- src/dird/catreq.c (révision 5789) -+++ src/dird/catreq.c (copie de travail) -@@ -266,6 +266,11 @@ - } - } - Dmsg2(400, "Update media: BefVolJobs=%u After=%u\n", mr.VolJobs, sdmr.VolJobs); -+ /* Check if the volume has been written by the job, -+ * and update the LastWritten field if needed */ -+ if (mr.VolBlocks != sdmr.VolBlocks) { -+ mr.LastWritten = sdmr.LastWritten; -+ } - /* Copy updated values to original media record */ - mr.VolJobs = sdmr.VolJobs; - mr.VolFiles = sdmr.VolFiles; -@@ -274,7 +279,6 @@ - mr.VolMounts = sdmr.VolMounts; - mr.VolErrors = sdmr.VolErrors; - mr.VolWrites = sdmr.VolWrites; -- mr.LastWritten = sdmr.LastWritten; - mr.Slot = sdmr.Slot; - mr.InChanger = sdmr.InChanger; - mr.VolReadTime = sdmr.VolReadTime; diff --git a/bacula/patches/2.2.5-nextvol.patch b/bacula/patches/2.2.5-nextvol.patch deleted file mode 100644 index 27bf0d5641..0000000000 --- a/bacula/patches/2.2.5-nextvol.patch +++ /dev/null @@ -1,29 +0,0 @@ - - This bug fixes the warning message that prints each time an automatic - Volume name is created. This fixes bug #979 - - This patch applies to Bacula version 2.2.5 (not to previous versions), - and can be applied with the following: - - cd - patch -p0 <2.2.5-newvol.patch - ./configure (your options) - make - ... - make install - - - -Index: src/dird/newvol.c -=================================================================== ---- src/dird/newvol.c (revision 5717) -+++ src/dird/newvol.c (working copy) -@@ -124,7 +124,7 @@ - mr->VolumeName[0] = 0; - bstrncpy(name, pr->LabelFormat, sizeof(name)); - ctx.value = 0; -- Mmsg(query, "SELECT MAX(MediaId) FROM Media,POOL WHERE Pool.PoolId=%s", -+ Mmsg(query, "SELECT MAX(MediaId) FROM Media,Pool WHERE Pool.PoolId=%s", - edit_int64(pr->PoolId, ed1)); - if (!db_sql_query(jcr->db, query.c_str(), db_int64_handler, (void *)&ctx)) { - Jmsg(jcr, M_WARNING, 0, _("SQL failed, but ignored. ERR=%s\n"), db_strerror(jcr->db)); diff --git a/bacula/patches/2.2.5-postgresql-errors.patch b/bacula/patches/2.2.5-postgresql-errors.patch deleted file mode 100644 index fb52b80dd2..0000000000 --- a/bacula/patches/2.2.5-postgresql-errors.patch +++ /dev/null @@ -1,28 +0,0 @@ - After a sql error, the error message that is printed - is incorrect and does not include the postgresql error message. - It fixes #989 - - This patch applies to Bacula version 2.2.5 (and previous versions), - and can be applied with the following: - - cd - patch -p0 <2.2.5-postgresql-errors.patch - ./configure (your options) - make - ... - make install - - -Index: src/cats/cats.h -=================================================================== ---- src/cats/cats.h (révision 5763) -+++ src/cats/cats.h (copie de travail) -@@ -498,7 +498,7 @@ - #define sql_fetch_row(x) my_postgresql_fetch_row(x) - #define sql_query(x, y) my_postgresql_query((x), (y)) - #define sql_close(x) PQfinish((x)->db) --#define sql_strerror(x) PQresultErrorMessage((x)->result) -+#define sql_strerror(x) PQerrorMessage((x)->db) - #define sql_num_rows(x) ((unsigned) PQntuples((x)->result)) - #define sql_data_seek(x, i) my_postgresql_data_seek((x), (i)) - #define sql_affected_rows(x) ((unsigned) atoi(PQcmdTuples((x)->result))) diff --git a/bacula/patches/2.2.5-tray-monitor.patch b/bacula/patches/2.2.5-tray-monitor.patch deleted file mode 100644 index 542aea74d0..0000000000 --- a/bacula/patches/2.2.5-tray-monitor.patch +++ /dev/null @@ -1,25 +0,0 @@ - - This patch activates the Close button in the tray monitor window. - It fixes bug #986. - - Apply it to Bacula version 2.2.5 with: - - cd - patch -p0 <2.2.5-tray-monitor.patch - make - ... - make install - -Index: src/tray-monitor/tray-monitor.c -=================================================================== ---- src/tray-monitor/tray-monitor.c (revision 5717) -+++ src/tray-monitor/tray-monitor.c (working copy) -@@ -478,7 +478,7 @@ - gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, FALSE, 0); - - button = new_image_button("gtk-close", _("Close")); --// g_signal_connect_swapped(G_OBJECT(button), "clicked", G_CALLBACK(gtk_widget_hide), G_OBJECT(window)); -+ g_signal_connect_swapped(G_OBJECT(button), "clicked", G_CALLBACK(gtk_widget_hide), G_OBJECT(window)); - gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, FALSE, 0); - - gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); diff --git a/bacula/patches/2.2.5-verify-loop.patch b/bacula/patches/2.2.5-verify-loop.patch deleted file mode 100644 index 9016cfe297..0000000000 --- a/bacula/patches/2.2.5-verify-loop.patch +++ /dev/null @@ -1,33 +0,0 @@ - - This patch fixes bug #1003 where putting the message output from - a Verify job into the catalog results in a recursive loop. The problem - seems to show up only with postgresql (to be verified). - - Apply it to version 2.2.5 (or probably any previous 2.2.x version) with - - cd - ./configure not necessary if already configured - patch -p0 <2.2.5-verify-loop.patch - make - ... - make install - - -Index: src/dird/verify.c -=================================================================== ---- src/dird/verify.c (revision 5814) -+++ src/dird/verify.c (working copy) -@@ -767,11 +767,11 @@ - return 1; - } - if (!jcr->fn_printed) { -- Jmsg(jcr, M_INFO, 0, _("\nThe following files are in the Catalog but not on %s:\n"), -+ Qmsg(jcr, M_INFO, 0, _("\nThe following files are in the Catalog but not on %s:\n"), - jcr->JobLevel == L_VERIFY_VOLUME_TO_CATALOG ? "the Volume(s)" : "disk"); - jcr->fn_printed = true; - } -- Jmsg(jcr, M_INFO, 0, " %s%s\n", row[0]?row[0]:"", row[1]?row[1]:""); -+ Qmsg(jcr, M_INFO, 0, " %s%s\n", row[0]?row[0]:"", row[1]?row[1]:""); - return 0; - } - diff --git a/bacula/patches/2.2.6-scratch.patch b/bacula/patches/2.2.6-scratch.patch new file mode 100644 index 0000000000..d6da1cd01e --- /dev/null +++ b/bacula/patches/2.2.6-scratch.patch @@ -0,0 +1,29 @@ + + This patch prevents the "status dir" command from trying to use a scratch + volume and possibly moving it from one pool to another. This patch fixes + bug #1019. + + Apply the patch to 2.2.6 (and possibly any 2.2.x version with): + + cd + patch -p0 <2.2.6-scratch.patch + ./configure + make + ... + make install + + + +Index: src/dird/next_vol.c +=================================================================== +--- src/dird/next_vol.c (revision 5999) ++++ src/dird/next_vol.c (working copy) +@@ -97,7 +97,7 @@ + prune_volumes(jcr, InChanger, mr); + } + ok = recycle_oldest_purged_volume(jcr, InChanger, mr); +- if (!ok) { ++ if (!ok && create) { + Dmsg4(050, "after prune volumes_vol ok=%d index=%d InChanger=%d Vstat=%s\n", + ok, index, InChanger, mr->VolStatus); + /* diff --git a/bacula/patches/2.2.x/2.2.4-ansi-label.patch b/bacula/patches/2.2.x/2.2.4-ansi-label.patch new file mode 100644 index 0000000000..d68e618aca --- /dev/null +++ b/bacula/patches/2.2.x/2.2.4-ansi-label.patch @@ -0,0 +1,77 @@ + + This patch fixes bug #954. + WEOF on non-appendable error when trying to label a tape with ANSI labels turned on. + + Apply it to version 2.2.4 (possibly earlier versions with): + + cd + patch -p0 <2.2.4-verify.patch + ./configure (your options) + make + ... + make install + +Index: block.c +=================================================================== +--- src/stored/block.c (revision 5615) ++++ src/stored/block.c (revision 5615) +@@ -273,6 +273,7 @@ + dev->dev_errno = EIO; + Mmsg4(dev->errmsg, _("Volume data error at %u:%u! Wanted ID: \"%s\", got \"%s\". Buffer discarded.\n"), + dev->file, dev->block_num, BLKHDR2_ID, Id); ++ Dmsg1(50, "%s", dev->errmsg); + if (block->read_errors == 0 || verbose >= 2) { + Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); + } +@@ -1008,8 +1009,19 @@ + dev->set_ateof(); + return false; /* return eof */ + } ++ + /* Continue here for successful read */ ++ + block->read_len = stat; /* save length read */ ++ if (dev->at_eof() && block->read_len == 80 && ++ (dcr->VolCatInfo.LabelType != B_BACULA_LABEL || ++ dcr->device->label_type != B_BACULA_LABEL)) { ++ /* ***FIXME*** should check label */ ++ Dmsg2(100, "Ignore 80 byte ANSI label at %u:%u\n", dev->file, dev->block_num); ++ dev->clear_eof(); ++ goto reread; /* skip ANSI/IBM label */ ++ } ++ + if (block->read_len < BLKHDR2_LENGTH) { + dev->dev_errno = EIO; + Mmsg4(dev->errmsg, _("Volume data error at %u:%u! Very short block of %d bytes on device %s discarded.\n"), + +Index: label.c +=================================================================== +--- src/stored/label.c (revision 5602) ++++ src/stored/label.c (working copy) +@@ -119,7 +119,6 @@ + bstrncpy(dev->VolHdr.Id, "**error**", sizeof(dev->VolHdr.Id)); + + /* Read ANSI/IBM label if so requested */ +- + want_ansi_label = dcr->VolCatInfo.LabelType != B_BACULA_LABEL || + dcr->device->label_type != B_BACULA_LABEL; + if (want_ansi_label || dev->has_cap(CAP_CHECKLABELS)) { +@@ -344,6 +343,9 @@ + } + } + ++ /* Temporarily mark in append state to enable writing */ ++ dev->set_append(); ++ + /* Create PRE_LABEL or VOL_LABEL if DVD */ + create_volume_label(dev, VolName, PoolName, dvdnow); + +@@ -364,8 +366,6 @@ + create_volume_label_record(dcr, dcr->rec); + dcr->rec->Stream = 0; + +- /* Temporarily mark in append state to enable writing */ +- dev->set_append(); + if (!write_record_to_block(dcr->block, dcr->rec)) { + Dmsg2(130, "Bad Label write on %s: ERR=%s\n", dev->print_name(), dev->print_errmsg()); + goto bail_out; diff --git a/bacula/patches/2.2.x/2.2.4-lost-block.patch b/bacula/patches/2.2.x/2.2.4-lost-block.patch new file mode 100644 index 0000000000..fbf7122a31 --- /dev/null +++ b/bacula/patches/2.2.x/2.2.4-lost-block.patch @@ -0,0 +1,30 @@ + + This patch fixes a race condition where a Job is terminating at the same + time that another job reaches the end of Volume. In that case, sometimes + the last block or two are not written to the Volume. This seems to be + relatively rare, but does result in data loss. This fixes bug #964. + + Apply the patch to Bacula version 2.2.4 (or possibly any previous 2.2.x + version) with: + + cd + patch -p0 <2.2.4-lost-block.patch + ./configure (your options) + make + ... + make install + + +Index: src/stored/append.c +=================================================================== +--- src/stored/append.c (revision 5602) ++++ src/stored/append.c (working copy) +@@ -287,7 +287,7 @@ + * 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 (dev->can_write()) { ++ if (ok || 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()); diff --git a/bacula/patches/2.2.x/2.2.4-parse-command.patch b/bacula/patches/2.2.x/2.2.4-parse-command.patch new file mode 100644 index 0000000000..312dd29efe --- /dev/null +++ b/bacula/patches/2.2.x/2.2.4-parse-command.patch @@ -0,0 +1,28 @@ + + This patch resolves a command parser issue + causing a director segfault when using something + like "run job 1 2" + + Apply to version 2.2.4 (and perhaps older 2.2.x versions) with + + cd + patch -p0 <2.2.4-parse-command.patch + ./configure (your options) + make + ... + make install + + +Index: src/dird/ua_run.c +=================================================================== +--- src/dird/ua_run.c (révision 5616) ++++ src/dird/ua_run.c (copie de travail) +@@ -933,7 +933,7 @@ + /* Note, yes and run have no value, so do not fail */ + if (!ua->argv[i] && j != YES_POS /*yes*/) { + ua->send_msg(_("Value missing for keyword %s\n"), ua->argk[i]); +- return true; ++ return false; + } + Dmsg1(800, "Got keyword=%s\n", NPRT(kw[j])); + switch (j) { diff --git a/bacula/patches/2.2.x/2.2.4-poll-mount.patch b/bacula/patches/2.2.x/2.2.4-poll-mount.patch new file mode 100644 index 0000000000..a4676e942f --- /dev/null +++ b/bacula/patches/2.2.x/2.2.4-poll-mount.patch @@ -0,0 +1,27 @@ + + This patch resolves bug #908 where a tape is not properly mounted + (recognized) during a poll. + + Apply to version 2.2.4 (and perhaps older 2.2.x versions) with + + cd + patch -p0 <2.2.4-poll-mount.patch + ./configure (your options) + make + ... + make install + +Index: src/stored/dev.c +=================================================================== +--- src/stored/dev.c (revision 5553) ++++ src/stored/dev.c (working copy) +@@ -1844,7 +1844,8 @@ + + /* Clean up device packet so it can be reused */ + clear_opened(); +- state &= ~(ST_LABEL|ST_READ|ST_APPEND|ST_EOT|ST_WEOT|ST_EOF); ++ state &= ~(ST_LABEL|ST_READ|ST_APPEND|ST_EOT|ST_WEOT|ST_EOF| ++ ST_MOUNTED|ST_MEDIA|ST_SHORT|ST_FREESPACE_OK|ST_PART_SPOOLED); + label_type = B_BACULA_LABEL; + file = block_num = 0; + file_size = 0; diff --git a/bacula/patches/2.2.x/2.2.4-replace.patch b/bacula/patches/2.2.x/2.2.4-replace.patch new file mode 100644 index 0000000000..58e4e5109f --- /dev/null +++ b/bacula/patches/2.2.x/2.2.4-replace.patch @@ -0,0 +1,24 @@ + + This patch resolves bug #969 where the user can't change the + replace option in the restore menu + + Apply to version 2.2.4 (and perhaps older 2.2.x versions) with + + cd + patch -p0 <2.2.4-replace.patch + ./configure (your options) + make + ... + make install + +--- src/dird/ua_run.c (révision 5721) ++++ src/dird/ua_run.c (copie de travail) +@@ -424,6 +424,7 @@ + } + opt = do_prompt(ua, "", _("Select replace option"), NULL, 0); + if (opt >= 0) { ++ rc.replace = ReplaceOptions[opt].name; + jcr->replace = ReplaceOptions[opt].token; + } + goto try_again; + diff --git a/bacula/patches/2.2.x/2.2.4-restore.patch b/bacula/patches/2.2.x/2.2.4-restore.patch new file mode 100644 index 0000000000..3ef991e3b7 --- /dev/null +++ b/bacula/patches/2.2.x/2.2.4-restore.patch @@ -0,0 +1,49 @@ + + This patch resolves bug #955 where the director segfault when + where= option isn't specified anywhere. + + Apply to version 2.2.4 (and perhaps older 2.2.x versions) with + + cd + patch -p0 <2.2.4-restore.patch + ./configure (your options) + make + ... + make install + + +Index: src/dird/restore.c +=================================================================== +--- src/dird/restore.c (revision 5601) ++++ src/dird/restore.c (working copy) +@@ -173,7 +173,7 @@ + } + + /* Send restore command */ +- char replace, *where, *cmd=NULL; ++ char replace, *where, *cmd; + char empty = '\0'; + + if (jcr->replace != 0) { +@@ -183,8 +183,6 @@ + } else { + replace = REPLACE_ALWAYS; /* always replace */ + } +- +- where = ∅ /* default */ + + if (jcr->RegexWhere) { + where = jcr->RegexWhere; /* override */ +@@ -199,7 +197,11 @@ + } else if (jcr->job->RestoreWhere) { + where = jcr->job->RestoreWhere; /* no override take from job */ + cmd = restorecmd; +- } ++ ++ } else { /* nothing was specified */ ++ where = ∅ /* use default */ ++ cmd = restorecmd; ++ } + + jcr->prefix_links = jcr->job->PrefixLinks; + diff --git a/bacula/patches/2.2.x/2.2.4-sd-auth-fail.patch b/bacula/patches/2.2.x/2.2.4-sd-auth-fail.patch new file mode 100644 index 0000000000..2e506e7884 --- /dev/null +++ b/bacula/patches/2.2.x/2.2.4-sd-auth-fail.patch @@ -0,0 +1,159 @@ + + This patch applies to Bacula version 2.2.4 (possibly earlier 2.2.x versions) + and fixes a Storage daemon authentication problem with the FD. This fixes + bug #953. The patch also adds a bit of additional debug code and significantly + strengthens the SD session key. + + Apply it to 2.2.4 with: + + cd + patch -p0 <2.2.4-sd-auth-fail.patch + make + ... + make install + + +Index: src/stored/job.c +=================================================================== +--- src/stored/job.c (revision 5602) ++++ src/stored/job.c (working copy) +@@ -73,6 +73,7 @@ + { + int JobId; + char auth_key[100]; ++ char seed[100]; + BSOCK *dir = jcr->dir_bsock; + POOL_MEM job_name, client_name, job, fileset_name, fileset_md5; + int JobType, level, spool_attributes, no_attributes, spool_data; +@@ -91,7 +92,7 @@ + &write_part_after_job, &PreferMountedVols); + if (stat != 13) { + pm_strcpy(jcr->errmsg, dir->msg); +- bnet_fsend(dir, BAD_job, stat, jcr->errmsg); ++ dir->fsend(BAD_job, stat, jcr->errmsg); + Dmsg1(100, ">dird: %s", dir->msg); + set_jcr_job_status(jcr, JS_ErrorTerminated); + return false; +@@ -134,9 +135,10 @@ + /* + * Pass back an authorization key for the File daemon + */ +- make_session_key(auth_key, NULL, 1); +- bnet_fsend(dir, OKjob, jcr->VolSessionId, jcr->VolSessionTime, auth_key); +- Dmsg1(100, ">dird: %s", dir->msg); ++ bsnprintf(seed, sizeof(seed), "%p%d", jcr, JobId); ++ make_session_key(auth_key, seed, 1); ++ dir->fsend(OKjob, jcr->VolSessionId, jcr->VolSessionTime, auth_key); ++ Dmsg2(100, ">dird jid=%u: %s", (uint32_t)jcr->JobId, dir->msg); + jcr->sd_auth_key = bstrdup(auth_key); + memset(auth_key, 0, sizeof(auth_key)); + generate_daemon_event(jcr, "JobStart"); +@@ -169,17 +171,18 @@ + timeout.tv_nsec = tv.tv_usec * 1000; + timeout.tv_sec = tv.tv_sec + me->client_wait; + +- Dmsg2(100, "%s waiting %d sec for FD to contact SD\n", +- jcr->Job, (int)me->client_wait); ++ Dmsg3(050, "%s waiting %d sec for FD to contact SD key=%s\n", ++ jcr->Job, (int)me->client_wait, jcr->sd_auth_key); ++ + /* + * Wait for the File daemon to contact us to start the Job, + * when he does, we will be released, unless the 30 minutes + * expires. + */ + P(mutex); +- for ( ; !job_canceled(jcr); ) { ++ while ( !jcr->authenticated && !job_canceled(jcr) ) { + errstat = pthread_cond_timedwait(&jcr->job_start_wait, &mutex, &timeout); +- if (errstat == 0 || errstat == ETIMEDOUT) { ++ if (errstat == ETIMEDOUT || errstat == EINVAL || errstat == EPERM) { + break; + } + } +@@ -195,7 +198,7 @@ + } + + /* +- * After receiving a connection (in job.c) if it is ++ * After receiving a connection (in dircmd.c) if it is + * from the File daemon, this routine is called. + */ + void handle_filed_connection(BSOCK *fd, char *job_name) +@@ -204,8 +207,8 @@ + + bmicrosleep(0, 50000); /* wait 50 millisecs */ + if (!(jcr=get_jcr_by_full_name(job_name))) { +- Jmsg1(NULL, M_FATAL, 0, _("Job name not found: %s\n"), job_name); +- Dmsg1(100, "Job name not found: %s\n", job_name); ++ Jmsg1(NULL, M_FATAL, 0, _("FD connect failed: Job name not found: %s\n"), job_name); ++ Dmsg1(3, "**** Job \"%s\" not found", job_name); + return; + } + +@@ -216,7 +219,7 @@ + + if (jcr->authenticated) { + Jmsg2(jcr, M_FATAL, 0, _("Hey!!!! JobId %u Job %s already authenticated.\n"), +- jcr->JobId, jcr->Job); ++ (uint32_t)jcr->JobId, jcr->Job); + free_jcr(jcr); + return; + } +@@ -229,7 +232,7 @@ + Jmsg(jcr, M_FATAL, 0, _("Unable to authenticate File daemon\n")); + } else { + jcr->authenticated = true; +- Dmsg1(110, "OK Authentication Job %s\n", jcr->Job); ++ Dmsg2(110, "OK Authentication jid=%u Job %s\n", (uint32_t)jcr->JobId, jcr->Job); + } + + if (!jcr->authenticated) { +@@ -274,9 +277,9 @@ + } + ok = dir_update_device(jcr, device->dev); + if (ok) { +- ok = bnet_fsend(dir, OK_query); ++ ok = dir->fsend(OK_query); + } else { +- bnet_fsend(dir, NO_query); ++ dir->fsend(NO_query); + } + return ok; + } +@@ -289,9 +292,9 @@ + } + ok = dir_update_changer(jcr, changer); + if (ok) { +- ok = bnet_fsend(dir, OK_query); ++ ok = dir->fsend(OK_query); + } else { +- bnet_fsend(dir, NO_query); ++ dir->fsend(NO_query); + } + return ok; + } +@@ -299,12 +302,12 @@ + /* If we get here, the device/autochanger was not found */ + unbash_spaces(dir->msg); + pm_strcpy(jcr->errmsg, dir->msg); +- bnet_fsend(dir, NO_device, dev_name.c_str()); ++ dir->fsend(NO_device, dev_name.c_str()); + Dmsg1(100, ">dird: %s\n", dir->msg); + } else { + unbash_spaces(dir->msg); + pm_strcpy(jcr->errmsg, dir->msg); +- bnet_fsend(dir, BAD_query, jcr->errmsg); ++ dir->fsend(BAD_query, jcr->errmsg); + Dmsg1(100, ">dird: %s\n", dir->msg); + } + +@@ -322,7 +325,7 @@ + { + Dmsg1(900, "stored_free_jcr JobId=%u\n", jcr->JobId); + if (jcr->file_bsock) { +- bnet_close(jcr->file_bsock); ++ jcr->file_bsock->close(); + jcr->file_bsock = NULL; + } + if (jcr->job_name) { diff --git a/bacula/patches/2.2.x/2.2.4-sql.patch b/bacula/patches/2.2.x/2.2.4-sql.patch new file mode 100644 index 0000000000..24de09994c --- /dev/null +++ b/bacula/patches/2.2.x/2.2.4-sql.patch @@ -0,0 +1,476 @@ + + This patch fixes several problems: it fixes incorrect or incomplete error + messages; it fixes a problem opening the SQLite3 database when multiple + simultaneous jobs were running; it fixes a bug with certain versions of + MySQL where batch inserts failed because of table name character case + (upper/lower) differences. + + It can be applied to version 2.2.4 (and possibly earlier 2.2.x versions) + with: + + cd + patch -p0 <2.2.4-sql.patch + ./configure (your options) + make + ... + make install + + + +Index: src/cats/sql.c +=================================================================== +--- src/cats/sql.c (revision 5687) ++++ src/cats/sql.c (working copy) +@@ -115,7 +115,6 @@ + + bacula_db_version = 0; + if (!db_sql_query(mdb, query, int_handler, (void *)&bacula_db_version)) { +- Mmsg(mdb->errmsg, "Database not created or server not running.\n"); + Jmsg(jcr, M_FATAL, 0, "%s", mdb->errmsg); + return false; + } +Index: src/cats/sqlite.c +=================================================================== +--- src/cats/sqlite.c (revision 5687) ++++ src/cats/sqlite.c (working copy) +@@ -148,6 +148,7 @@ + int len; + struct stat statbuf; + int errstat; ++ int retry = 0; + + P(mutex); + if (mdb->connected) { +@@ -157,8 +158,9 @@ + mdb->connected = FALSE; + + if ((errstat=rwl_init(&mdb->lock)) != 0) { ++ berrno be; + Mmsg1(&mdb->errmsg, _("Unable to initialize DB lock. ERR=%s\n"), +- strerror(errstat)); ++ be.bstrerror(errstat)); + V(mutex); + return 0; + } +@@ -178,28 +180,28 @@ + return 0; + } + ++ for (mdb->db=NULL; !mdb->db && retry++ < 10; ) { + #ifdef HAVE_SQLITE3 +- int stat = sqlite3_open(db_name, &mdb->db); +- if (stat != SQLITE_OK) { +- mdb->sqlite_errmsg = (char *)sqlite3_errmsg(mdb->db); +- sqlite3_close(mdb->db); +- mdb->db = NULL; +- } else { +- mdb->sqlite_errmsg = NULL; +- } +-#ifdef SQLITE3_INIT_QUERY +- db_sql_query(mdb, SQLITE3_INIT_QUERY, NULL, NULL); +-#endif +- ++ int stat = sqlite3_open(db_name, &mdb->db); ++ if (stat != SQLITE_OK) { ++ mdb->sqlite_errmsg = (char *)sqlite3_errmsg(mdb->db); ++ sqlite3_close(mdb->db); ++ mdb->db = NULL; ++ } else { ++ mdb->sqlite_errmsg = NULL; ++ } + #else +- mdb->db = sqlite_open( +- db_name, /* database name */ +- 644, /* mode */ +- &mdb->sqlite_errmsg); /* error message */ ++ mdb->db = sqlite_open( ++ db_name, /* database name */ ++ 644, /* mode */ ++ &mdb->sqlite_errmsg); /* error message */ + #endif + +- Dmsg0(300, "sqlite_open\n"); +- ++ Dmsg0(300, "sqlite_open\n"); ++ if (!mdb->db) { ++ bmicrosleep(1, 0); ++ } ++ } + if (mdb->db == NULL) { + Mmsg2(&mdb->errmsg, _("Unable to open Database=%s. ERR=%s\n"), + db_name, mdb->sqlite_errmsg ? mdb->sqlite_errmsg : _("unknown")); +@@ -209,10 +211,6 @@ + } + mdb->connected = true; + free(db_name); +- if (!check_tables_version(jcr, mdb)) { +- V(mutex); +- return 0; +- } + + /* set busy handler to wait when we use mult_db_connections = 1 */ + #ifdef HAVE_SQLITE3 +@@ -221,6 +219,16 @@ + sqlite_busy_handler(mdb->db, my_busy_handler, NULL); + #endif + ++#if defined(HAVE_SQLITE3) && defined(SQLITE3_INIT_QUERY) ++ db_sql_query(mdb, SQLITE3_INIT_QUERY, NULL, NULL); ++#endif ++ ++ if (!check_tables_version(jcr, mdb)) { ++ V(mutex); ++ return 0; ++ } ++ ++ + V(mutex); + return 1; + } +@@ -448,16 +456,20 @@ + return mdb->fields[mdb->field++]; + } + +-char *my_sqlite_batch_lock_query = "BEGIN"; +-char *my_sqlite_batch_unlock_query = "COMMIT"; +-char *my_sqlite_batch_fill_path_query = "INSERT INTO Path (Path) " +- " SELECT DISTINCT Path FROM batch " +- " EXCEPT SELECT Path FROM Path "; ++#ifdef HAVE_BATCH_FILE_INSERT ++const char *my_sqlite_batch_lock_query = "BEGIN"; ++const char *my_sqlite_batch_unlock_query = "COMMIT"; + +-char *my_sqlite_batch_fill_filename_query = "INSERT INTO Filename (Name) " +- " SELECT DISTINCT Name FROM batch " +- " EXCEPT SELECT Name FROM Filename "; ++const char *my_sqlite_batch_fill_path_query = ++ "INSERT INTO Path (Path)" ++ " SELECT DISTINCT Path FROM batch" ++ " EXCEPT SELECT Path FROM Path"; + ++const char *my_sqlite_batch_fill_filename_query = ++ "INSERT INTO Filename (Name)" ++ " SELECT DISTINCT Name FROM batch " ++ " EXCEPT SELECT Name FROM Filename"; ++#endif /* HAVE_BATCH_FILE_INSERT */ + + + #endif /* HAVE_SQLITE */ +Index: src/cats/cats.h +=================================================================== +--- src/cats/cats.h (revision 5687) ++++ src/cats/cats.h (working copy) +@@ -187,10 +187,10 @@ + int my_sqlite_query(B_DB *mdb, const char *cmd); + void my_sqlite_field_seek(B_DB *mdb, int field); + SQL_FIELD *my_sqlite_fetch_field(B_DB *mdb); +-extern char* my_sqlite_batch_lock_query; +-extern char* my_sqlite_batch_unlock_query; +-extern char* my_sqlite_batch_fill_filename_query; +-extern char* my_sqlite_batch_fill_path_query; ++extern const char* my_sqlite_batch_lock_query; ++extern const char* my_sqlite_batch_unlock_query; ++extern const char* my_sqlite_batch_fill_filename_query; ++extern const char* my_sqlite_batch_fill_path_query; + + + #else +@@ -317,10 +317,10 @@ + int my_sqlite_query(B_DB *mdb, const char *cmd); + void my_sqlite_field_seek(B_DB *mdb, int field); + SQL_FIELD *my_sqlite_fetch_field(B_DB *mdb); +-extern char* my_sqlite_batch_lock_query; +-extern char* my_sqlite_batch_unlock_query; +-extern char* my_sqlite_batch_fill_filename_query; +-extern char* my_sqlite_batch_fill_path_query; ++extern const char* my_sqlite_batch_lock_query; ++extern const char* my_sqlite_batch_unlock_query; ++extern const char* my_sqlite_batch_fill_filename_query; ++extern const char* my_sqlite_batch_fill_path_query; + + + #else +@@ -398,11 +398,11 @@ + #define sql_batch_fill_path_query my_mysql_batch_fill_path_query + + +-extern char* my_mysql_batch_lock_path_query; +-extern char* my_mysql_batch_lock_filename_query; +-extern char* my_mysql_batch_unlock_tables_query; +-extern char* my_mysql_batch_fill_filename_query; +-extern char* my_mysql_batch_fill_path_query; ++extern const char* my_mysql_batch_lock_path_query; ++extern const char* my_mysql_batch_lock_filename_query; ++extern const char* my_mysql_batch_unlock_tables_query; ++extern const char* my_mysql_batch_fill_filename_query; ++extern const char* my_mysql_batch_fill_path_query; + extern void my_mysql_free_result(B_DB *mdb); + + #else +@@ -486,11 +486,11 @@ + int my_postgresql_batch_insert(JCR *jcr, B_DB *mdb, ATTR_DBR *ar); + char *my_postgresql_copy_escape(char *dest, char *src, size_t len); + +-extern char* my_pg_batch_lock_path_query; +-extern char* my_pg_batch_lock_filename_query; +-extern char* my_pg_batch_unlock_tables_query; +-extern char* my_pg_batch_fill_filename_query; +-extern char* my_pg_batch_fill_path_query; ++extern const char* my_pg_batch_lock_path_query; ++extern const char* my_pg_batch_lock_filename_query; ++extern const char* my_pg_batch_unlock_tables_query; ++extern const char* my_pg_batch_fill_filename_query; ++extern const char* my_pg_batch_fill_path_query; + + /* "Generic" names for easier conversion */ + #define sql_store_result(x) ((x)->result) +Index: src/cats/mysql.c +=================================================================== +--- src/cats/mysql.c (revision 5687) ++++ src/cats/mysql.c (working copy) +@@ -149,8 +149,9 @@ + } + + if ((errstat=rwl_init(&mdb->lock)) != 0) { ++ berrno be; + Mmsg1(&mdb->errmsg, _("Unable to initialize DB lock. ERR=%s\n"), +- strerror(errstat)); ++ be.bstrerror(errstat)); + V(mutex); + return 0; + } +@@ -403,33 +404,27 @@ + db_unlock(mdb); + } + +-char *my_mysql_batch_lock_path_query = "LOCK TABLES Path write, " +- " batch write, " +- " Path as p write "; ++#ifdef HAVE_BATCH_FILE_INSERT ++const char *my_mysql_batch_lock_path_query = ++ "LOCK TABLES Path write, batch write, Path as p write"; + + +-char *my_mysql_batch_lock_filename_query = "LOCK TABLES Filename write, " +- " batch write, " +- " Filename as f write "; ++const char *my_mysql_batch_lock_filename_query = ++ "LOCK TABLES Filename write, batch write, Filename as f write"; + +-char *my_mysql_batch_unlock_tables_query = "UNLOCK TABLES"; ++const char *my_mysql_batch_unlock_tables_query = "UNLOCK TABLES"; + +-char *my_mysql_batch_fill_path_query = "INSERT INTO Path (Path) " +- " SELECT a.Path FROM " +- " (SELECT DISTINCT Path " +- " FROM batch) AS a " +- " WHERE NOT EXISTS " +- " (SELECT Path " +- " FROM Path AS p " +- " WHERE p.Path = a.Path) "; ++const char *my_mysql_batch_fill_path_query = ++ "INSERT INTO Path (Path) " ++ "SELECT a.Path FROM " ++ "(SELECT DISTINCT Path FROM batch) AS a WHERE NOT EXISTS " ++ "(SELECT Path FROM Path AS p WHERE p.Path = a.Path)"; + +-char *my_mysql_batch_fill_filename_query = "INSERT INTO Filename (Name) " +- " SELECT a.Name FROM " +- " (SELECT DISTINCT Name " +- " FROM batch) AS a " +- " WHERE NOT EXISTS " +- " (SELECT Name " +- " FROM Filename AS f " +- " WHERE f.Name = a.Name) "; ++const char *my_mysql_batch_fill_filename_query = ++ "INSERT INTO Filename (Name) " ++ "SELECT a.Name FROM " ++ "(SELECT DISTINCT Name FROM batch) AS a WHERE NOT EXISTS " ++ "(SELECT Name FROM Filename AS f WHERE f.Name = a.Name)"; ++#endif /* HAVE_BATCH_FILE_INSERT */ + + #endif /* HAVE_MYSQL */ +Index: src/cats/sql_create.c +=================================================================== +--- src/cats/sql_create.c (revision 5687) ++++ src/cats/sql_create.c (working copy) +@@ -668,6 +668,8 @@ + * }; + */ + ++#ifdef HAVE_BATCH_FILE_INSERT ++ + /* All sql_batch_* functions are used to do bulk batch insert in File/Filename/Path + * tables. This code can be activated by adding "#define HAVE_BATCH_FILE_INSERT 1" + * in baconfig.h +@@ -690,13 +692,13 @@ + + db_lock(mdb); + ok = db_sql_query(mdb, +- " CREATE TEMPORARY TABLE batch " +- " (fileindex integer, " +- " jobid integer, " +- " path blob, " +- " name blob, " +- " lstat tinyblob, " +- " md5 tinyblob) ",NULL, NULL); ++ "CREATE TEMPORARY TABLE batch (" ++ "FileIndex integer," ++ "JobId integer," ++ "Path blob," ++ "Name blob," ++ "LStat tinyblob," ++ "MD5 tinyblob)",NULL, NULL); + db_unlock(mdb); + return ok; + } +@@ -746,7 +748,6 @@ + return true; + } + +-#ifdef HAVE_BATCH_FILE_INSERT + /* + * Returns 1 if OK + * 0 if failed +@@ -794,7 +795,7 @@ + + if (!db_sql_query(jcr->db_batch,sql_batch_fill_filename_query, NULL,NULL)) { + Jmsg(jcr,M_FATAL,0,"Can't fill Filename table %s\n",jcr->db_batch->errmsg); +- QUERY_DB(jcr, jcr->db_batch, sql_batch_unlock_tables_query); ++ db_sql_query(jcr->db_batch, sql_batch_unlock_tables_query, NULL, NULL); + return false; + } + +@@ -804,12 +805,12 @@ + } + + if (!db_sql_query(jcr->db_batch, +- " INSERT INTO File (FileIndex, JobId, PathId, FilenameId, LStat, MD5)" +- " SELECT batch.FileIndex, batch.JobId, Path.PathId, " +- " Filename.FilenameId,batch.LStat, batch.MD5 " +- " FROM batch " +- " JOIN Path ON (batch.Path = Path.Path) " +- " JOIN Filename ON (batch.Name = Filename.Name) ", ++ "INSERT INTO File (FileIndex, JobId, PathId, FilenameId, LStat, MD5)" ++ "SELECT batch.FileIndex, batch.JobId, Path.PathId, " ++ "Filename.FilenameId,batch.LStat, batch.MD5 " ++ "FROM batch " ++ "JOIN Path ON (batch.Path = Path.Path) " ++ "JOIN Filename ON (batch.Name = Filename.Name)", + NULL,NULL)) + { + Jmsg(jcr, M_FATAL, 0, "Can't fill File table %s\n", jcr->db_batch->errmsg); +@@ -845,19 +846,24 @@ + mdb->db_port, + mdb->db_socket, + 1 /* multi_db = true */); ++ if (!jcr->db_batch) { ++ Mmsg1(&mdb->errmsg, _("Could not init batch database: \"%s\".\n"), ++ jcr->db->db_name); ++ Jmsg1(jcr, M_FATAL, 0, "%s", mdb->errmsg); ++ return false; ++ } + +- if (!jcr->db_batch || !db_open_database(jcr, jcr->db_batch)) { +- Jmsg(jcr, M_FATAL, 0, _("Could not open database \"%s\".\n"), +- jcr->db->db_name); +- if (jcr->db_batch) { +- Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db_batch)); +- } ++ if (!db_open_database(jcr, jcr->db_batch)) { ++ Mmsg2(&mdb->errmsg, _("Could not open database \"%s\": ERR=%s\n"), ++ jcr->db->db_name, db_strerror(jcr->db_batch)); ++ Jmsg1(jcr, M_FATAL, 0, "%s", mdb->errmsg); + return false; + } + + if (!sql_batch_start(jcr, jcr->db_batch)) { +- Jmsg(jcr, M_FATAL, 0, +- "Can't start batch mode %s", db_strerror(jcr->db_batch)); ++ Mmsg1(&mdb->errmsg, ++ "Can't start batch mode: ERR=%s", db_strerror(jcr->db_batch)); ++ Jmsg1(jcr, M_FATAL, 0, "%s", mdb->errmsg); + return false; + } + Dmsg3(100, "initdb ref=%d connected=%d db=%p\n", jcr->db_batch->ref_count, +@@ -870,10 +876,10 @@ + */ + if (!(ar->Stream == STREAM_UNIX_ATTRIBUTES || + ar->Stream == STREAM_UNIX_ATTRIBUTES_EX)) { +- Mmsg1(&bdb->errmsg, _("Attempt to put non-attributes into catalog. Stream=%d\n"), ++ Mmsg1(&mdb->errmsg, _("Attempt to put non-attributes into catalog. Stream=%d\n"), + ar->Stream); +- Jmsg(jcr, M_ERROR, 0, "%s", bdb->errmsg); +- return 0; ++ Jmsg(jcr, M_FATAL, 0, "%s", mdb->errmsg); ++ return false; + } + + split_path_and_file(jcr, bdb, ar->fname); +Index: src/cats/postgresql.c +=================================================================== +--- src/cats/postgresql.c (revision 5687) ++++ src/cats/postgresql.c (working copy) +@@ -605,13 +605,13 @@ + Dmsg0(500, "my_postgresql_batch_start started\n"); + + if (my_postgresql_query(mdb, +- " CREATE TEMPORARY TABLE batch " +- " (fileindex int, " +- " jobid int, " +- " path varchar, " +- " name varchar, " +- " lstat varchar, " +- " md5 varchar)") == 1) ++ "CREATE TEMPORARY TABLE batch (" ++ "fileindex int," ++ "jobid int," ++ "path varchar," ++ "name varchar," ++ "lstat varchar," ++ "md5 varchar)") == 1) + { + Dmsg0(500, "my_postgresql_batch_start failed\n"); + return 1; +@@ -785,22 +785,29 @@ + return dest; + } + +-char *my_pg_batch_lock_path_query = "BEGIN; LOCK TABLE Path IN SHARE ROW EXCLUSIVE MODE"; ++#ifdef HAVE_BATCH_FILE_INSERT ++const char *my_pg_batch_lock_path_query = ++ "BEGIN; LOCK TABLE Path IN SHARE ROW EXCLUSIVE MODE"; + + +-char *my_pg_batch_lock_filename_query = "BEGIN; LOCK TABLE Filename IN SHARE ROW EXCLUSIVE MODE"; ++const char *my_pg_batch_lock_filename_query = ++ "BEGIN; LOCK TABLE Filename IN SHARE ROW EXCLUSIVE MODE"; + +-char *my_pg_batch_unlock_tables_query = "COMMIT"; ++const char *my_pg_batch_unlock_tables_query = "COMMIT"; + +-char *my_pg_batch_fill_path_query = "INSERT INTO Path (Path) " +- " SELECT a.Path FROM " +- " (SELECT DISTINCT Path FROM batch) AS a " +- " WHERE NOT EXISTS (SELECT Path FROM Path WHERE Path = a.Path) "; ++const char *my_pg_batch_fill_path_query = ++ "INSERT INTO Path (Path) " ++ "SELECT a.Path FROM " ++ "(SELECT DISTINCT Path FROM batch) AS a " ++ "WHERE NOT EXISTS (SELECT Path FROM Path WHERE Path = a.Path) "; + + +-char *my_pg_batch_fill_filename_query = "INSERT INTO Filename (Name) " +- " SELECT a.Name FROM " +- " (SELECT DISTINCT Name FROM batch) as a " +- " WHERE NOT EXISTS " +- " (SELECT Name FROM Filename WHERE Name = a.Name)"; ++const char *my_pg_batch_fill_filename_query = ++ "INSERT INTO Filename (Name) " ++ "SELECT a.Name FROM " ++ "(SELECT DISTINCT Name FROM batch) as a " ++ "WHERE NOT EXISTS " ++ "(SELECT Name FROM Filename WHERE Name = a.Name)"; ++#endif /* HAVE_BATCH_FILE_INSERT */ ++ + #endif /* HAVE_POSTGRESQL */ diff --git a/bacula/patches/2.2.x/2.2.4-verify.patch b/bacula/patches/2.2.x/2.2.4-verify.patch new file mode 100644 index 0000000000..21e9af3442 --- /dev/null +++ b/bacula/patches/2.2.x/2.2.4-verify.patch @@ -0,0 +1,75 @@ + This patch fixes bug #958 A Verify catalog Job that has differences reports Verify OK. + + Apply it to version 2.2.4 (possibly earlier versions with): + + cd + patch -p0 <2.2.4-verify.patch + ./configure (your options) + make + ... + make install + +Index: src/dird/verify.c +=================================================================== +--- src/dird/verify.c (revision 5553) ++++ src/dird/verify.c (working copy) +@@ -332,13 +332,10 @@ + } + + stat = wait_for_job_termination(jcr); +- if (stat == JS_Terminated) { +- verify_cleanup(jcr, stat); +- return true; +- } ++ verify_cleanup(jcr, stat); ++ return true; + + bail_out: +- verify_cleanup(jcr, JS_ErrorTerminated); + return false; + } + +@@ -421,7 +418,7 @@ + jobstatus_to_ascii(jcr->FDJobStatus, fd_term_msg, sizeof(fd_term_msg)); + if (jcr->JobLevel == L_VERIFY_VOLUME_TO_CATALOG) { + jobstatus_to_ascii(jcr->SDJobStatus, sd_term_msg, sizeof(sd_term_msg)); +- Jmsg(jcr, msg_type, 0, _("Bacula %s %s (%s): %s\n" ++ Jmsg(jcr, msg_type, 0, _("Bacula %s %s (%s): %s\n" + " Build OS: %s %s %s\n" + " JobId: %d\n" + " Job: %s\n" +@@ -456,7 +453,7 @@ + sd_term_msg, + term_msg); + } else { +- Jmsg(jcr, msg_type, 0, _("Bacula %s %s (%s): %s\n" ++ Jmsg(jcr, msg_type, 0, _("Bacula %s %s (%s): %s\n" + " Build: %s %s %s\n" + " JobId: %d\n" + " Job: %s\n" +@@ -750,7 +747,9 @@ + stat = JS_Differences; + } + free_pool_memory(fname); +- set_jcr_job_status(jcr, stat); ++ if (!job_canceled(jcr)) { ++ jcr->JobStatus = stat; ++ } + return stat == JS_Terminated; + } + +Index: src/lib/jcr.c +=================================================================== +--- src/lib/jcr.c (revision 5553) ++++ src/lib/jcr.c (working copy) +@@ -614,9 +614,8 @@ + /* Override more minor status */ + jcr->JobStatus = JobStatus; + break; +- default: +- break; + } ++ break; + default: + jcr->JobStatus = JobStatus; + } diff --git a/bacula/patches/2.2.x/2.2.5-deamon.patch b/bacula/patches/2.2.x/2.2.5-deamon.patch new file mode 100644 index 0000000000..6e82f1ea87 --- /dev/null +++ b/bacula/patches/2.2.x/2.2.5-deamon.patch @@ -0,0 +1,40 @@ + + This patch fixes the default behavior of a non-DEVELOPER version of Bacula + to close STDIN, STDOUT, and STDERR so that an ssh that starts bacula + will not hang. It also fixes a crash in bat when bat is executed and + cannot connect to the Director (e.g. it is not running). + This patch fixes bugs #991 and #993. + + Apply this fix to Bacula version 2.2.5 with: + + cd + patch -p0 <2.2.5-daemon.patch + ./configure (your options) + make + ... + make install + + +Index: src/lib/message.c +=================================================================== +--- src/lib/message.c (revision 5744) ++++ src/lib/message.c (working copy) +@@ -52,7 +52,8 @@ + */ + const char *working_directory = NULL; /* working directory path stored here */ + int verbose = 0; /* increase User messages */ +-int debug_level = 1; /* debug level */ ++/* Keep debug level set to zero by default */ ++int debug_level = 0; /* debug level */ + time_t daemon_start_time = 0; /* Daemon start time */ + const char *version = VERSION " (" BDATE ")"; + char my_name[30]; /* daemon name is stored here */ +@@ -1338,7 +1339,7 @@ + jcr = get_jcr_from_tsd(); + } + /* If no jcr or dequeuing send to daemon to avoid recursion */ +- if (!jcr || jcr->dequeuing) { ++ if ((jcr && !jcr->msg_queue) || !jcr || jcr->dequeuing) { + /* jcr==NULL => daemon message, safe to send now */ + Jmsg(jcr, item->type, item->mtime, "%s", item->msg); + free(item); diff --git a/bacula/patches/2.2.x/2.2.5-hb.patch b/bacula/patches/2.2.x/2.2.5-hb.patch new file mode 100644 index 0000000000..b8d81c879d --- /dev/null +++ b/bacula/patches/2.2.x/2.2.5-hb.patch @@ -0,0 +1,186 @@ + + This patch fixes bug #947 where a large number of emails were generated + because the heartbeat interval was small and the tape in the drive did + not correspond to the one wanted by Bacula. + + Apply the patch to version 2.2.5 (and probably any 2.2.x version) with: + + cd + ./configure + patch -p0 <2.2.5-hb.patch + make + ... + make install + + +Index: src/stored/wait.c +=================================================================== +--- src/stored/wait.c (revision 5814) ++++ src/stored/wait.c (working copy) +@@ -40,9 +40,8 @@ + #include "bacula.h" /* pull in global headers */ + #include "stored.h" /* pull in Storage Deamon headers */ + +-//static bool double_jcr_wait_time(JCR *jcr); ++const int dbglvl = 400; + +- + /* + * Wait for SysOp to mount a tape on a specific device + * +@@ -62,7 +61,7 @@ + JCR *jcr = dcr->jcr; + + dev->dlock(); +- Dmsg1(100, "Enter blocked=%s\n", dev->print_blocked()); ++ Dmsg1(dbglvl, "Enter blocked=%s\n", dev->print_blocked()); + unmounted = is_device_unmounted(dev); + + dev->poll = false; +@@ -84,27 +83,28 @@ + } + + if (!unmounted) { +- Dmsg1(400, "blocked=%s\n", dev->print_blocked()); ++ Dmsg1(dbglvl, "blocked=%s\n", dev->print_blocked()); + dev->dev_prev_blocked = dev->blocked(); + dev->set_blocked(BST_WAITING_FOR_SYSOP); /* indicate waiting for mount */ + } + + for ( ; !job_canceled(jcr); ) { +- time_t now, start; ++ time_t now, start, total_waited; + + gettimeofday(&tv, &tz); + timeout.tv_nsec = tv.tv_usec * 1000; + timeout.tv_sec = tv.tv_sec + add_wait; + +- Dmsg4(400, "I'm going to sleep on device %s. HB=%d wait=%d add_wait=%d\n", +- dev->print_name(), (int)me->heartbeat_interval, dev->wait_sec, add_wait); ++ Dmsg4(dbglvl, "I'm going to sleep on device %s. HB=%d rem_wait=%d add_wait=%d\n", ++ dev->print_name(), (int)me->heartbeat_interval, dev->rem_wait_sec, add_wait); + start = time(NULL); + /* Wait required time */ + stat = pthread_cond_timedwait(&dev->wait_next_vol, &dev->m_mutex, &timeout); +- Dmsg2(400, "Wokeup from sleep on device stat=%d blocked=%s\n", stat, ++ Dmsg2(dbglvl, "Wokeup from sleep on device stat=%d blocked=%s\n", stat, + dev->print_blocked()); + + now = time(NULL); ++ total_waited = now - first_start; + dev->rem_wait_sec -= (now - start); + + /* Note, this always triggers the first time. We want that. */ +@@ -113,7 +113,7 @@ + /* send heartbeats */ + if (jcr->file_bsock) { + jcr->file_bsock->signal(BNET_HEARTBEAT); +- Dmsg0(400, "Send heartbeat to FD.\n"); ++ Dmsg0(dbglvl, "Send heartbeat to FD.\n"); + } + if (jcr->dir_bsock) { + jcr->dir_bsock->signal(BNET_HEARTBEAT); +@@ -131,7 +131,7 @@ + + + if (dev->rem_wait_sec <= 0) { /* on exceeding wait time return */ +- Dmsg0(400, "Exceed wait time.\n"); ++ Dmsg0(dbglvl, "Exceed wait time.\n"); + stat = W_TIMEOUT; + break; + } +@@ -142,8 +142,8 @@ + unmounted = is_device_unmounted(dev); + + if (!unmounted && dev->vol_poll_interval && +- (now - first_start >= dev->vol_poll_interval)) { +- Dmsg1(400, "In wait blocked=%s\n", dev->print_blocked()); ++ (total_waited >= dev->vol_poll_interval)) { ++ Dmsg1(dbglvl, "poll return in wait blocked=%s\n", dev->print_blocked()); + dev->poll = true; /* returning a poll event */ + stat = W_POLL; + break; +@@ -152,6 +152,7 @@ + * Check if user mounted the device while we were waiting + */ + if (dev->blocked() == BST_MOUNT) { /* mount request ? */ ++ Dmsg0(dbglvl, "Mounted return.\n"); + stat = W_MOUNT; + break; + } +@@ -160,30 +161,39 @@ + * If we did not timeout, then some event happened, so + * return to check if state changed. + */ +- if (stat != 0) { ++ if (stat != ETIMEDOUT) { ++ berrno be; ++ Dmsg2(dbglvl, "Wake return. stat=%d. ERR=%s\n", stat, be.bstrerror(stat)); + stat = W_WAKE; /* someone woke us */ + break; + } + + /* + * At this point, we know we woke up because of a timeout, +- * that was due to a heartbeat, so we just update +- * the wait counters and continue. ++ * that was due to a heartbeat, because any other reason would ++ * have caused us to return, so update the wait counters and continue. + */ +- add_wait = dev->wait_sec - (now - start); ++ add_wait = dev->rem_wait_sec; ++ if (me->heartbeat_interval && add_wait > me->heartbeat_interval) { ++ add_wait = me->heartbeat_interval; ++ } ++ /* If the user did not unmount the tape and we are polling, ensure ++ * that we poll at the correct interval. ++ */ ++ if (!unmounted && dev->vol_poll_interval && ++ add_wait > dev->vol_poll_interval - total_waited) { ++ add_wait = dev->vol_poll_interval - total_waited; ++ } + if (add_wait < 0) { + add_wait = 0; + } +- if (me->heartbeat_interval && add_wait > me->heartbeat_interval) { +- add_wait = me->heartbeat_interval; +- } + } + + if (!unmounted) { + dev->set_blocked(dev->dev_prev_blocked); /* restore entry state */ +- Dmsg1(400, "set %s\n", dev->print_blocked()); ++ Dmsg1(dbglvl, "set %s\n", dev->print_blocked()); + } +- Dmsg1(400, "Exit blocked=%s\n", dev->print_blocked()); ++ Dmsg1(dbglvl, "Exit blocked=%s\n", dev->print_blocked()); + dev->dunlock(); + return stat; + } +@@ -209,7 +219,7 @@ + const int max_wait_time = 1 * 60; /* wait 1 minute */ + char ed1[50]; + +- Dmsg0(100, "Enter wait_for_device\n"); ++ Dmsg0(dbglvl, "Enter wait_for_device\n"); + P(device_release_mutex); + + if (++retries % 5 == 0) { +@@ -222,14 +232,14 @@ + timeout.tv_nsec = tv.tv_usec * 1000; + timeout.tv_sec = tv.tv_sec + max_wait_time; + +- Dmsg1(100, "JobId=%u going to wait for a device.\n", (uint32_t)jcr->JobId); ++ Dmsg0(dbglvl, "Going to wait for a device.\n"); + + /* Wait required time */ + stat = pthread_cond_timedwait(&wait_device_release, &device_release_mutex, &timeout); +- Dmsg2(100, "JobId=%u wokeup from sleep on device stat=%d\n", (uint32_t)jcr->JobId, stat); ++ Dmsg1(dbglvl, "Wokeup from sleep on device stat=%d\n", stat); + + V(device_release_mutex); +- Dmsg2(100, "JobId=%u return from wait_device ok=%d\n", (uint32_t)jcr->JobId, ok); ++ Dmsg1(dbglvl, "Return from wait_device ok=%d\n", ok); + return ok; + } + diff --git a/bacula/patches/2.2.x/2.2.5-lastwritten.patch b/bacula/patches/2.2.x/2.2.5-lastwritten.patch new file mode 100644 index 0000000000..c5373bcfec --- /dev/null +++ b/bacula/patches/2.2.x/2.2.5-lastwritten.patch @@ -0,0 +1,41 @@ + + This bug fixes the LastWritten field which was updated during + a restore (or a reading migration) + This fixes bug #982 + + This patch applies to Bacula version 2.2.5 (and previous versions), + and can be applied with the following: + + cd + patch -p0 <2.2.5-lastwritten.patch + ./configure (your options) + make + ... + make install + + + +Index: src/dird/catreq.c +=================================================================== +--- src/dird/catreq.c (révision 5789) ++++ src/dird/catreq.c (copie de travail) +@@ -266,6 +266,11 @@ + } + } + Dmsg2(400, "Update media: BefVolJobs=%u After=%u\n", mr.VolJobs, sdmr.VolJobs); ++ /* Check if the volume has been written by the job, ++ * and update the LastWritten field if needed */ ++ if (mr.VolBlocks != sdmr.VolBlocks) { ++ mr.LastWritten = sdmr.LastWritten; ++ } + /* Copy updated values to original media record */ + mr.VolJobs = sdmr.VolJobs; + mr.VolFiles = sdmr.VolFiles; +@@ -274,7 +279,6 @@ + mr.VolMounts = sdmr.VolMounts; + mr.VolErrors = sdmr.VolErrors; + mr.VolWrites = sdmr.VolWrites; +- mr.LastWritten = sdmr.LastWritten; + mr.Slot = sdmr.Slot; + mr.InChanger = sdmr.InChanger; + mr.VolReadTime = sdmr.VolReadTime; diff --git a/bacula/patches/2.2.x/2.2.5-nextvol.patch b/bacula/patches/2.2.x/2.2.5-nextvol.patch new file mode 100644 index 0000000000..27bf0d5641 --- /dev/null +++ b/bacula/patches/2.2.x/2.2.5-nextvol.patch @@ -0,0 +1,29 @@ + + This bug fixes the warning message that prints each time an automatic + Volume name is created. This fixes bug #979 + + This patch applies to Bacula version 2.2.5 (not to previous versions), + and can be applied with the following: + + cd + patch -p0 <2.2.5-newvol.patch + ./configure (your options) + make + ... + make install + + + +Index: src/dird/newvol.c +=================================================================== +--- src/dird/newvol.c (revision 5717) ++++ src/dird/newvol.c (working copy) +@@ -124,7 +124,7 @@ + mr->VolumeName[0] = 0; + bstrncpy(name, pr->LabelFormat, sizeof(name)); + ctx.value = 0; +- Mmsg(query, "SELECT MAX(MediaId) FROM Media,POOL WHERE Pool.PoolId=%s", ++ Mmsg(query, "SELECT MAX(MediaId) FROM Media,Pool WHERE Pool.PoolId=%s", + edit_int64(pr->PoolId, ed1)); + if (!db_sql_query(jcr->db, query.c_str(), db_int64_handler, (void *)&ctx)) { + Jmsg(jcr, M_WARNING, 0, _("SQL failed, but ignored. ERR=%s\n"), db_strerror(jcr->db)); diff --git a/bacula/patches/2.2.x/2.2.5-postgresql-errors.patch b/bacula/patches/2.2.x/2.2.5-postgresql-errors.patch new file mode 100644 index 0000000000..fb52b80dd2 --- /dev/null +++ b/bacula/patches/2.2.x/2.2.5-postgresql-errors.patch @@ -0,0 +1,28 @@ + After a sql error, the error message that is printed + is incorrect and does not include the postgresql error message. + It fixes #989 + + This patch applies to Bacula version 2.2.5 (and previous versions), + and can be applied with the following: + + cd + patch -p0 <2.2.5-postgresql-errors.patch + ./configure (your options) + make + ... + make install + + +Index: src/cats/cats.h +=================================================================== +--- src/cats/cats.h (révision 5763) ++++ src/cats/cats.h (copie de travail) +@@ -498,7 +498,7 @@ + #define sql_fetch_row(x) my_postgresql_fetch_row(x) + #define sql_query(x, y) my_postgresql_query((x), (y)) + #define sql_close(x) PQfinish((x)->db) +-#define sql_strerror(x) PQresultErrorMessage((x)->result) ++#define sql_strerror(x) PQerrorMessage((x)->db) + #define sql_num_rows(x) ((unsigned) PQntuples((x)->result)) + #define sql_data_seek(x, i) my_postgresql_data_seek((x), (i)) + #define sql_affected_rows(x) ((unsigned) atoi(PQcmdTuples((x)->result))) diff --git a/bacula/patches/2.2.x/2.2.5-tray-monitor.patch b/bacula/patches/2.2.x/2.2.5-tray-monitor.patch new file mode 100644 index 0000000000..542aea74d0 --- /dev/null +++ b/bacula/patches/2.2.x/2.2.5-tray-monitor.patch @@ -0,0 +1,25 @@ + + This patch activates the Close button in the tray monitor window. + It fixes bug #986. + + Apply it to Bacula version 2.2.5 with: + + cd + patch -p0 <2.2.5-tray-monitor.patch + make + ... + make install + +Index: src/tray-monitor/tray-monitor.c +=================================================================== +--- src/tray-monitor/tray-monitor.c (revision 5717) ++++ src/tray-monitor/tray-monitor.c (working copy) +@@ -478,7 +478,7 @@ + gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, FALSE, 0); + + button = new_image_button("gtk-close", _("Close")); +-// g_signal_connect_swapped(G_OBJECT(button), "clicked", G_CALLBACK(gtk_widget_hide), G_OBJECT(window)); ++ g_signal_connect_swapped(G_OBJECT(button), "clicked", G_CALLBACK(gtk_widget_hide), G_OBJECT(window)); + gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, FALSE, 0); + + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); diff --git a/bacula/patches/2.2.x/2.2.5-verify-loop.patch b/bacula/patches/2.2.x/2.2.5-verify-loop.patch new file mode 100644 index 0000000000..9016cfe297 --- /dev/null +++ b/bacula/patches/2.2.x/2.2.5-verify-loop.patch @@ -0,0 +1,33 @@ + + This patch fixes bug #1003 where putting the message output from + a Verify job into the catalog results in a recursive loop. The problem + seems to show up only with postgresql (to be verified). + + Apply it to version 2.2.5 (or probably any previous 2.2.x version) with + + cd + ./configure not necessary if already configured + patch -p0 <2.2.5-verify-loop.patch + make + ... + make install + + +Index: src/dird/verify.c +=================================================================== +--- src/dird/verify.c (revision 5814) ++++ src/dird/verify.c (working copy) +@@ -767,11 +767,11 @@ + return 1; + } + if (!jcr->fn_printed) { +- Jmsg(jcr, M_INFO, 0, _("\nThe following files are in the Catalog but not on %s:\n"), ++ Qmsg(jcr, M_INFO, 0, _("\nThe following files are in the Catalog but not on %s:\n"), + jcr->JobLevel == L_VERIFY_VOLUME_TO_CATALOG ? "the Volume(s)" : "disk"); + jcr->fn_printed = true; + } +- Jmsg(jcr, M_INFO, 0, " %s%s\n", row[0]?row[0]:"", row[1]?row[1]:""); ++ Qmsg(jcr, M_INFO, 0, " %s%s\n", row[0]?row[0]:"", row[1]?row[1]:""); + return 0; + } + diff --git a/bacula/src/dird/next_vol.c b/bacula/src/dird/next_vol.c index 6aecf5331d..29a92541b6 100644 --- a/bacula/src/dird/next_vol.c +++ b/bacula/src/dird/next_vol.c @@ -97,7 +97,7 @@ int find_next_volume_for_append(JCR *jcr, MEDIA_DBR *mr, int index, prune_volumes(jcr, InChanger, mr); } ok = recycle_oldest_purged_volume(jcr, InChanger, mr); - if (!ok) { + if (!ok && create) { Dmsg4(050, "after prune volumes_vol ok=%d index=%d InChanger=%d Vstat=%s\n", ok, index, InChanger, mr->VolStatus); /* diff --git a/bacula/technotes-2.3 b/bacula/technotes-2.3 index 5ffc7b6eab..7bae8283cc 100644 --- a/bacula/technotes-2.3 +++ b/bacula/technotes-2.3 @@ -1,6 +1,10 @@ Technical notes on version 2.3 General: +02Dec07 +kes This patch prevents the 'status dir' command from trying to use a scratch + volume and possibly moving it from one pool to another. This patch fixes + bug #1019. 01Dec07 kes Add new include to cats/postgresql.c suggested by Marc Cousins so that it compiles correctly with pgre version 8.3.