Technical notes on version 2.2.x
General:
+Release Version 2.2.5
+03Oct07
+kes Backport almost 4000 lines of 2.3 code that fixes a number of bugs.
+ The details are included in the notes in this file.
+28Sep07
+kes Backport 2.3 code that fixes: 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.
+kes Fix race condition that drops final block written to volume.
+ This happens in rare cases with multiple simultaneous jobs
+ when the Volume fills. This fixes bug #964. May be related
+ to bug #935 and possibly #903.
+27Sep07
+kes Fix FD->SD authorization failure, which was due to spurious
+ wakeups from a pthread_cond_timedwait(). Simply check the
+ predicate before continuing. This fixes bug #953
+dvl Add new configuration item --archivedir
+dvl Adjust regression tests to use tmp not /tmp. This will allow
+ multiple concurrent runs of the regression tests.
+28Sep07
+kes Fix race condition that drops final block written to volume.
+ This happens in rare cases with multiple simultaneous jobs
+ when the Volume fills. This fixes bug #964. May be related
+ to bug #935 and possibly #903.
+kes Eliminate more strerror() and replace with bstrerror().
+kes Remove BSD getopt and replace with unrestricted IBM version.
+kes Fix Win32 build for changed calling sequences.
+27Sep07
+kes Fix FD->SD authorization failure, which was due to spurious
+ wakeups from a pthread_cond_timedwait(). Simply check the
+ predicate before continuing. This fixes bug #953.
+kes Add const char where needed (more to do).
+26Sep07
+kes Setup SQLite busy handler before doing queries. Fixes bug #967.
+kes Don't overwrite error message in check_tables_version.
+ Fixes bug #966.
+kes Unlock batch insert tables with same calls used elsewhere.
+kes Allow starting 59 jobs a second.
+kes Make SD session key more random.
+kes Add retry for SQLite opening db if it fails. Probably helps
+ for bug #967.
+kes Suppress extra error messages during batch insert failure.
+ Fixes bug #966.
+kes Put some FD auth code on dbglvl rather than fixed.
+kes Return insert attributes error message in db msg buffer to avoid
+ false error messages. Helps fix bug #966.
+kes Separate batch init error messages. Probably helps fix bug #966.
+kes If Dir gets an error during inserting attributes, cancel SD.
+ This reduces unnecessary error messages.
+24Sep07
+ebl Cleanup batch insert code. Probably fixes bug #965.
+23Sep07
+kes Turn off some code when batch insert not enabled.
+kes Edit FD name in connect error messages.
+22Sep07
+kes Add code to handle tray monitor separated from Win32 FD.
+kes Fix display of Win32 tray monitor after reboot. Fixes bug #952.
+20Sep07
+kes Fix ANSI tape labeling. This fixes bug #954.
+kes Increase the max block size to 4MB fixes bug #957.
+kes Apply 2.2.4-poll-mount fix, that resolves bug #908 where a tape
+ is not properly mounted (recognized) during a poll.
+kes Apply 2.2.4-verify patch that resolves bug #958. A Verify catalog
+ Job that has differences reports Verify OK.
+
Release Version 2.2.4
14Sep07
kes Increase size of name string when FD making connection to SD.
#
# Define the main nightly save backup job
-# By default, this job will back up to disk in /tmp
+# By default, this job will back up to disk in @archivedir@
Job {
Name = "Client1"
JobDefs = "DefaultJob"
Storage = File
Pool = Default
Messages = Standard
- Where = /tmp/bacula-restores
+ Where = @archivedir@/bacula-restores
}
STORE *store = jcr->wstore;
bstrncpy(mr->MediaType, store->media_type, sizeof(mr->MediaType));
- Dmsg2(150, "find_next_vol_for_append: PoolId=%d, MediaType=%s\n", (int)mr->PoolId, mr->MediaType);
+ Dmsg3(100, "find_next_vol_for_append: JobId=%u PoolId=%d, MediaType=%s\n",
+ (uint32_t)jcr->JobId, (int)mr->PoolId, mr->MediaType);
/*
* If we are using an Autochanger, restrict Volume
* search to the Autochanger on the first pass
} else if (mr->MaxVolJobs > 0 && mr->MaxVolJobs <= mr->VolJobs) {
Jmsg(jcr, M_INFO, 0, _("Max Volume jobs exceeded. "
"Marking Volume \"%s\" as Used.\n"), mr->VolumeName);
+ Dmsg3(100, "MaxVolJobs=%d JobId=%d Vol=%s\n", mr->MaxVolJobs,
+ (uint32_t)jcr->JobId, mr->VolumeName);
bstrncpy(mr->VolStatus, "Used", sizeof(mr->VolStatus));
expired = true;
/* ua_acl.c */
-bool acl_access_ok(UAContext *ua, int acl, char *item);
-bool acl_access_ok(UAContext *ua, int acl, char *item, int len);
+bool acl_access_ok(UAContext *ua, int acl, const char *item);
+bool acl_access_ok(UAContext *ua, int acl, const char *item, int len);
/* ua_cmds.c */
int do_a_command(UAContext *ua, const char *cmd);
FILESET *select_fileset_resource(UAContext *ua);
int select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr);
int select_media_dbr(UAContext *ua, MEDIA_DBR *mr);
-bool select_pool_dbr(UAContext *ua, POOL_DBR *pr, char *argk="pool");
+bool select_pool_dbr(UAContext *ua, POOL_DBR *pr, const char *argk="pool");
bool select_client_dbr(UAContext *ua, CLIENT_DBR *cr);
void start_prompt(UAContext *ua, const char *msg);
int get_storage_drive(UAContext *ua, STORE *store);
int get_storage_slot(UAContext *ua, STORE *store);
int get_media_type(UAContext *ua, char *MediaType, int max_media);
-bool get_pool_dbr(UAContext *ua, POOL_DBR *pr, char *argk="pool");
+bool get_pool_dbr(UAContext *ua, POOL_DBR *pr, const char *argk="pool");
bool get_client_dbr(UAContext *ua, CLIENT_DBR *cr);
POOL *get_pool_resource(UAContext *ua);
POOL *select_pool_resource(UAContext *ua);
-/*
- *
- * Bacula Director -- User Agent Access Control List (ACL) handling
- *
- * Kern Sibbald, January MMIV
- *
- * Version $Id$
- */
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2004-2006 Free Software Foundation Europe e.V.
+ Copyright (C) 2004-2007 Free Software Foundation Europe e.V.
The main author of Bacula is Kern Sibbald, with contributions from
many others, a complete list can be found in the file AUTHORS.
(FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
Switzerland, email:ftf@fsfeurope.org.
*/
+/*
+ *
+ * Bacula Director -- User Agent Access Control List (ACL) handling
+ *
+ * Kern Sibbald, January MMIV
+ *
+ * Version $Id$
+ */
#include "bacula.h"
#include "dird.h"
/*
* Check if access is permitted to item in acl
*/
-bool acl_access_ok(UAContext *ua, int acl, char *item)
+bool acl_access_ok(UAContext *ua, int acl, const char *item)
{
return acl_access_ok(ua, acl, item, strlen(item));
}
/* This version expects the length of the item which we must check. */
-bool acl_access_ok(UAContext *ua, int acl, char *item, int len)
+bool acl_access_ok(UAContext *ua, int acl, const char *item, int len)
{
/* If no console resource => default console and all is permitted */
* returns: false on error
* true on success and fills in POOL_DBR
*/
-bool get_pool_dbr(UAContext *ua, POOL_DBR *pr, char *argk)
+bool get_pool_dbr(UAContext *ua, POOL_DBR *pr, const char *argk)
{
if (pr->Name[0]) { /* If name already supplied */
if (db_get_pool_record(ua->jcr, ua->db, pr) &&
* Select a Pool record from catalog
* argk can be pool, recyclepool, scratchpool etc..
*/
-bool select_pool_dbr(UAContext *ua, POOL_DBR *pr, char *argk)
+bool select_pool_dbr(UAContext *ua, POOL_DBR *pr, const char *argk)
{
POOL_DBR opr;
char name[MAX_NAME_LENGTH];
#include "bacula.h"
#include "find.h"
+static uid_t my_uid = 1;
+static gid_t my_gid = 1;
+static bool uid_set = false;
+
+
#if defined(HAVE_WIN32)
/* Forward referenced subroutines */
static bool set_win32_attributes(JCR *jcr, ATTR *attr, BFILE *ofd);
bool ok = true;
boffset_t fsize;
+ if (uid_set) {
+ my_uid = getuid();
+ my_gid = getgid();
+ uid_set = true;
+ }
+
#if defined(HAVE_WIN32)
if (attr->stream == STREAM_UNIX_ATTRIBUTES_EX &&
set_win32_attributes(jcr, attr, ofd)) {
*/
if (attr->type == FT_LNK) {
/* Change owner of link, not of real file */
- if (lchown(attr->ofname, attr->statp.st_uid, attr->statp.st_gid) < 0) {
+ if (lchown(attr->ofname, attr->statp.st_uid, attr->statp.st_gid) < 0 && my_uid == 0) {
berrno be;
Jmsg2(jcr, M_ERROR, 0, _("Unable to set file owner %s: ERR=%s\n"),
attr->ofname, be.bstrerror());
ok = false;
}
} else {
- if (chown(attr->ofname, attr->statp.st_uid, attr->statp.st_gid) < 0) {
+ if (chown(attr->ofname, attr->statp.st_uid, attr->statp.st_gid) < 0 && my_uid == 0) {
berrno be;
Jmsg2(jcr, M_ERROR, 0, _("Unable to set file owner %s: ERR=%s\n"),
attr->ofname, be.bstrerror());
ok = false;
}
- if (chmod(attr->ofname, attr->statp.st_mode) < 0) {
+ if (chmod(attr->ofname, attr->statp.st_mode) < 0 && my_uid == 0) {
berrno be;
Jmsg2(jcr, M_ERROR, 0, _("Unable to set file modes %s: ERR=%s\n"),
attr->ofname, be.bstrerror());
/*
* Reset file times.
*/
- if (utime(attr->ofname, &ut) < 0) {
+ if (utime(attr->ofname, &ut) < 0 && my_uid == 0) {
berrno be;
Jmsg2(jcr, M_ERROR, 0, _("Unable to set file times %s: ERR=%s\n"),
attr->ofname, be.bstrerror());
* but if the immutable bit is set, it will make the utimes()
* fail.
*/
- if (chflags(attr->ofname, attr->statp.st_flags) < 0) {
+ if (chflags(attr->ofname, attr->statp.st_flags) < 0 && my_uid == 0) {
berrno be;
Jmsg2(jcr, M_ERROR, 0, _("Unable to set file flags %s: ERR=%s\n"),
attr->ofname, be.bstrerror());
+++ /dev/null
-/* idcache.c -- map user and group IDs, cached for speed
- Copyright (C) 1985, 1988, 1989, 1990 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#include "bacula.h"
-
-struct userid {
- union {
- uid_t u;
- gid_t g;
- } id;
- char *name;
- struct userid *next;
-};
-
-static struct userid *user_alist = NULL;
-/* Use the same struct as for userids. */
-static struct userid *group_alist = NULL;
-
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-
-/* Translate UID to a login name or a stringified number,
- with cache. */
-
-char *getuser(uid_t uid, char *name, int len)
-{
- register struct userid *tail;
- char usernum_string[20];
-
- P(mutex);
- for (tail = user_alist; tail; tail = tail->next) {
- if (tail->id.u == uid) {
- goto uid_done;
- }
- }
-
- tail = (struct userid *)malloc(sizeof (struct userid));
- tail->id.u = uid;
- tail->name = NULL;
-
-#if !defined(HAVE_WIN32)
- {
- struct passwd *pwent = getpwuid(uid);
-
- if (pwent != NULL && strcmp(pwent->pw_name, "????????") != 0) {
- tail->name = bstrdup(pwent->pw_name);
- }
- }
-#endif
-
- if (tail->name == NULL) {
- sprintf(usernum_string, "%u", (uint32_t)uid);
- tail->name = bstrdup(usernum_string);
- }
-
- /* Add to the head of the list, so most recently used is first. */
- tail->next = user_alist;
- user_alist = tail;
-
-uid_done:
- bstrncpy(name, tail->name, len);
- V(mutex);
- return name;
-}
-
-void free_getuser_cache()
-{
- register struct userid *tail;
-
- P(mutex);
- for (tail = user_alist; tail; ) {
- struct userid *otail = tail;
- free(tail->name);
- tail = tail->next;
- free(otail);
- }
- user_alist = NULL;
- V(mutex);
-}
-
-
-
-/* Translate GID to a group name or a stringified number,
- with cache. */
-char *getgroup(gid_t gid, char *name, int len)
-{
- register struct userid *tail;
- char groupnum_string[20];
-
- P(mutex);
- for (tail = group_alist; tail; tail = tail->next) {
- if (tail->id.g == gid) {
- goto gid_done;
- }
- }
-
- tail = (struct userid *)malloc(sizeof (struct userid));
- tail->id.g = gid;
- tail->name = NULL;
-
-#if !defined(HAVE_WIN32)
- {
- struct group *grent = getgrgid(gid);
-
- if (grent != NULL && strcmp(grent->gr_name, "????????") != 0) {
- tail->name = bstrdup(grent->gr_name);
- }
- }
-#endif
-
- if (tail->name == NULL) {
- sprintf (groupnum_string, "%u", (uint32_t)gid);
- tail->name = bstrdup(groupnum_string);
- }
-
- /* Add to the head of the list, so most recently used is first. */
- tail->next = group_alist;
- group_alist = tail;
-
-gid_done:
- bstrncpy(name, tail->name, len);
- V(mutex);
- return name;
-}
-
-void free_getgroup_cache()
-{
- register struct userid *tail;
-
- P(mutex);
- for (tail = group_alist; tail; ) {
- struct userid *otail = tail;
- free(tail->name);
- tail = tail->next;
- free(otail);
- }
- group_alist = NULL;
- V(mutex);
-}
+++ /dev/null
-/*
- Bacula® - The Network Backup Solution
-
- Copyright (C) 2007 Kern Sibbald
-
- The main author of Bacula is Kern Sibbald, with contributions from
- many others, a complete list can be found in the file AUTHORS.
- This program is Free Software; you can redistribute it and/or
- modify it under the terms of version two of the GNU General Public
- License as published by the Free Software Foundation, which is
- listed in the file LICENSE.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
- Bacula® is a registered trademark of John Walker.
- The licensor of Bacula is the Free Software Foundation Europe
- (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
- Switzerland, email:ftf@fsfeurope.org.
-*/
-/*
- * Written by Kern Sibbald, July 2005 to replace idcache.c
- *
- * Program to convert uid and gid into names, and cache the results
- * for preformance reasons.
- */
-
-#include "bacula.h"
-
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-
-struct guitem {
- dlink link;
- char *name;
- union {
- uid_t uid;
- gid_t gid;
- };
-};
-
-class guid_list {
-public:
- dlist *uid_list;
- dlist *gid_list;
-
- char *uid_to_name(uid_t uid, char *name, int maxlen);
- char *gid_to_name(gid_t gid, char *name, int maxlen);
-};
-
-guid_list *new_guid_list()
-{
- guid_list *list;
- guitem *item = NULL;
- list = (guid_list *)malloc(sizeof(guid_list));
- list->uid_list = New(dlist(item, &item->link));
- list->gid_list = New(dlist(item, &item->link));
- return list;
-}
-
-void free_guid_list(guid_list *list)
-{
- guitem *item;
- foreach_dlist(item, list->uid_list) {
- free(item->name);
- }
- foreach_dlist(item, list->gid_list) {
- free(item->name);
- }
- delete list->uid_list;
- delete list->gid_list;
- free(list);
-}
-
-static int uid_compare(void *item1, void *item2)
-{
- guitem *i1 = (guitem *)item1;
- guitem *i2 = (guitem *)item2;
- if (i1->uid < i2->uid) {
- return -1;
- } else if (i1->uid > i2->uid) {
- return 1;
- } else {
- return 0;
- }
-}
-
-static int gid_compare(void *item1, void *item2)
-{
- guitem *i1 = (guitem *)item1;
- guitem *i2 = (guitem *)item2;
- if (i1->gid < i2->gid) {
- return -1;
- } else if (i1->gid > i2->gid) {
- return 1;
- } else {
- return 0;
- }
-}
-
-
-static void get_uidname(uid_t uid, guitem *item)
-{
-#ifndef HAVE_WIN32
- struct passwd *pwbuf;
- P(mutex);
- pwbuf = getpwuid(uid);
- if (pwbuf != NULL && strcmp(pwbuf->pw_name, "????????") != 0) {
- item->name = bstrdup(pwbuf->pw_name);
- }
- V(mutex);
-#endif
-}
-
-static void get_gidname(gid_t gid, guitem *item)
-{
-#ifndef HAVE_WIN32
- struct group *grbuf;
- P(mutex);
- grbuf = getgrgid(gid);
- if (grbuf != NULL && strcmp(grbuf->gr_name, "????????") != 0) {
- item->name = bstrdup(grbuf->gr_name);
- }
- V(mutex);
-#endif
-}
-
-
-char *guid_list::uid_to_name(uid_t uid, char *name, int maxlen)
-{
- guitem sitem, *item, *fitem;
- sitem.uid = uid;
- char buf[50];
-
- item = (guitem *)uid_list->binary_search(&sitem, uid_compare);
- Dmsg2(900, "uid=%d item=%p\n", uid, item);
- if (!item) {
- item = (guitem *)malloc(sizeof(guitem));
- item->uid = uid;
- item->name = NULL;
- get_uidname(uid, item);
- if (!item->name) {
- item->name = bstrdup(edit_int64(uid, buf));
- Dmsg2(900, "set uid=%d name=%s\n", uid, item->name);
- }
- fitem = (guitem *)uid_list->binary_insert(item, uid_compare);
- if (fitem != item) { /* item already there this shouldn't happen */
- free(item);
- item = fitem;
- }
- }
- bstrncpy(name, item->name, maxlen);
- return name;
-}
-
-char *guid_list::gid_to_name(gid_t gid, char *name, int maxlen)
-{
- guitem sitem, *item, *fitem;
- sitem.gid = gid;
- char buf[50];
-
- item = (guitem *)uid_list->binary_search(&sitem, gid_compare);
- if (!item) {
- item = (guitem *)malloc(sizeof(guitem));
- item->gid = gid;
- item->name = NULL;
- get_gidname(gid, item);
- if (!item->name) {
- item->name = bstrdup(edit_int64(gid, buf));
- }
- fitem = (guitem *)gid_list->binary_insert(item, gid_compare);
- if (fitem != item) { /* item already there this shouldn't happen */
- free(item);
- item = fitem;
- }
- }
-
- bstrncpy(name, item->name, maxlen);
- return name;
-}
-
-#ifdef TEST_PROGRAM
-
-int main()
-{
- int i;
- guid_list *list;
- char ed1[50], ed2[50];
- list = new_guid_list();
- for (i=0; i<1001; i++) {
- printf("uid=%d name=%s gid=%d name=%s\n", i, list->uid_to_name(i, ed1, sizeof(ed1)),
- i, list->gid_to_name(i, ed2, sizeof(ed2)));
- printf("uid=%d name=%s gid=%d name=%s\n", i, list->uid_to_name(i, ed1, sizeof(ed1)),
- i, list->gid_to_name(i, ed2, sizeof(ed2)));
- }
-
- free_guid_list(list);
- sm_dump(false);
-
- return 0;
-}
-
-#endif
#undef VERSION
#define VERSION "2.2.5"
-#define BDATE "28 September 2007"
-#define LSMDATE "28Sep07"
+#define BDATE "03 October 2007"
+#define LSMDATE "03Oct07"
#define PROG_COPYRIGHT "Copyright (C) %d-2007 Free Software Foundation Europe e.V.\n"
#define BYEAR "2007" /* year for copyright messages in progs */
$(OBJDIR)/edit.o \
$(OBJDIR)/enh_fnmatch.o \
$(OBJDIR)/fnmatch.o \
+ $(OBJDIR)/guid_to_name.o \
$(OBJDIR)/hmac.o \
$(OBJDIR)/htable.o \
- $(OBJDIR)/idcache.o \
$(OBJDIR)/jcr.o \
$(OBJDIR)/lex.o \
$(OBJDIR)/md5.o \