========================================================
1.35 Items to do for release:
-- Knoppix CDROM
+- Bacula rescue CDROM
+- Fix error handling in spooling both data and attribute.
- Perhaps add read/write programs and/or plugins to FileSets.
- Add new DCR calling sequences everywhere in SD. This will permit
simultaneous use of multiple devices by a single job.
-- Fix restore ++++ that get intermingled with "Building directory tree"
-
+- Look at Chris' patch for bscan bug.
-- Test Win32 errno handling.
- Add bscan to four-concurrent-jobs regression.
- Doc new IPv6 syntax
- Add IPv6 to regression
- Doc update AllFromVol
- Doc dbcheck eliminate orphaned clients.
- Doc new duration time input editing.
+- Doc -p option in stored
Documentation to do: (any release a little bit at a time)
non-existent directories will not be restored properly.
Wish list:
+- see lzma401.zip in others directory for new compression
+ algorithm/library.
+- Minimal autochanger handling in Bacula and in btape.
+- Look into how tar does not save sockets and the possiblity of
+ not saving them in Bacula (Martin Simmons reported this).
+ The next two lines will show them.
+ localmounts=`awk '/ext/ { print $2 }' /proc/mounts` # or whatever
+ find $localmounts -xdev -type s -ls
- Fix restore jobs so that multiple jobs can run if they
are not using the same tape(s).
- Allow the user to select JobType for manual pruning/purging.
- Solve the termcap.h problem on Solaris configure.
- Make Verify jobs require exclusive use of Volume as Restore
jobs do.
+- Fix restore ++++ that get intermingled with "Building directory tree"
+- Fix doc in dirdconf.html for @, where the file must
+ have not a list of files, but
+ file = xxx
+ file = yyy
+- Test Win32 errno handling.
+- port 1.34.6-block.patch to 1.35
Name = @hostname@-mon
Password = "@mon_dir_password@"
CommandACL = status, .status
- ClientACL = ""
- StorageACL = ""
-}
\ No newline at end of file
+}
int qstatus_cmd(JCR *jcr)
{
BSOCK *dir = jcr->dir_bsock;
- char time[dir->msglen+1];
+ char *time;
JCR *njcr;
s_last_job* job;
-
+
+ time = (char *) alloca(dir->msglen+1);
+
if (sscanf(dir->msg, qstatus, time) != 1) {
pm_strcpy(&jcr->errmsg, dir->msg);
Jmsg1(jcr, M_FATAL, 0, _("Bad .status command: %s\n"), jcr->errmsg);
/* Do casting according to unknown type to keep compiler happy */
+#if !HAVE_GCC & HAVE_SUN_OS
+#define plug(st, val) st = val /* brain damaged compiler */
+#else
template <class T> void plug(T &st, uint64_t val)
{ st = static_cast<T>(val); }
+#endif
/* Decode a stat packet from base64 characters */
if (bfd->prog) {
POOLMEM *ecmd = get_pool_memory(PM_FNAME);
ecmd = edit_job_codes(bfd->jcr, ecmd, bfd->prog, fname);
- char *pmode;
+ const char *pmode;
if (flags & O_RDONLY) {
pmode = "r";
} else {
*/
static const char *gethost_strerror()
{
+ const char *msg;
switch (h_errno) {
case NETDB_INTERNAL:
- return strerror(errno);
+ msg = strerror(errno);
+ break;
case NETDB_SUCCESS:
- return "No problem.";
+ msg = "No problem.";
+ break;
case HOST_NOT_FOUND:
- return "Authoritative answer Host not found.";
+ msg = "Authoritative answer for host not found.";
+ break;
case TRY_AGAIN:
- return "Non-authoritative Host not found, or ServerFail.";
+ msg = "Non-authoritative for host not found, or ServerFail.";
+ break;
case NO_RECOVERY:
- return "Non-recoverable errors, FORMERR, REFUSED, or NOTIMP.";
+ msg = "Non-recoverable errors, FORMERR, REFUSED, or NOTIMP.";
+ break;
case NO_DATA:
- return "Valid name, no data record of resquested type.";
+ msg = "Valid name, no data record of resquested type.";
+ break;
default:
- return "Unknown error.";
+ msg = "Unknown error.";
}
+ return msg;
}
return addr;
}
-static int resolv_host(int family, const char *host, dlist * addr_list,
- const char **errstr)
+static const char *resolv_host(int family, const char *host, dlist * addr_list)
{
struct hostent *hp;
+ const char *errmsg;
P(ip_mutex);
#ifdef HAVE_GETHOSTBYNAME2
if ((hp = gethostbyname(host)) == NULL) {
#endif
/* may be the strerror give not the right result -:( */
- *errstr = gethost_strerror();
+ errmsg = gethost_strerror();
V(ip_mutex);
- return 0;
+ return errmsg;
} else {
char **p;
for (p = hp->h_addr_list; *p != 0; p++) {
}
V(ip_mutex);
}
- return 1;
+ return NULL;
}
/*
{
struct in_addr inaddr;
IPADDR *addr = 0;
+ const char *errmsg;
#ifdef HAVE_IPV6
struct in6_addr inaddr6;
#endif
#endif
{
if (family != 0) {
- if (!resolv_host(family, host, addr_list, errstr)) {
+ errmsg = resolv_host(family, host, addr_list);
+ if (errmsg) {
+ *errstr = errmsg;
free_addresses(addr_list);
return 0;
}
} else {
int done = 0;
- done |= resolv_host(AF_INET, host, addr_list, errstr);
+ errmsg = resolv_host(AF_INET, host, addr_list);
#ifdef HAVE_IPV6
- done |= resolv_host(AF_INET6, host, addr_list, errstr);
+ if (errmsg) {
+ errmsg = resolv_host(AF_INET6, host, addr_list);
+ if (!errmsg) {
+ done = 1;
+ }
+ } else {
+ done = 1;
+ }
#endif
if (!done) {
+ *errstr = errmsg;
free_addresses(addr_list);
return 0;
}
* the server that we want to connect with.
*/
if ((addr_list = bnet_host2ipaddrs(host, 0, &errstr)) == NULL) {
+ /* Note errstr is not malloc'ed */
Qmsg2(jcr, M_ERROR, 0, "gethostbyname() for host \"%s\" failed: ERR=%s\n",
host, errstr);
- free((void *)errstr);
*fatal = 1;
return NULL;
}
}
if (!connected) {
- free_addresses(addr_list);
+ free_addresses(addr_list);
errno = save_errno;
return NULL;
}
static pthread_mutex_t mutex;
static int first = 1;
int stat = 0;
- char *msg;
+ const char *msg;
if (first) {
pthread_mutex_init(&mutex, NULL);
* do initialization of child */
dlink sibling;
dlist child;
- char *fname; /* file name */
+ const char *fname; /* file name */
int32_t FileIndex; /* file index */
uint32_t JobId; /* JobId */
uint16_t fname_len; /* filename length */
/* Create a jobmedia record for this job */
if (!dir_create_jobmedia_record(dcr)) {
dev->dev_errno = EIO;
- Jmsg(jcr, M_ERROR, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
+ Jmsg(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
jcr->VolCatInfo.VolCatName, jcr->Job);
set_new_volume_parameters(dcr);
stat = false;
}
if (!write_block_to_dev(dcr, block)) {
- stat = fixup_device_block_write_error(dcr, block);
+ if (job_canceled(jcr)) {
+ stat = 0;
+ } else {
+ stat = fixup_device_block_write_error(dcr, block);
+ }
}
bail_out:
ssize_t stat = 0;
uint32_t wlen; /* length to write */
int hit_max1, hit_max2;
- bool ok;
+ bool ok = true;
DEVICE *dev = dcr->dev;
JCR *jcr = dcr->jcr;
edit_uint64_with_commas(max_cap, ed1), dev->dev_name);
block->write_failed = true;
if (weof_dev(dev, 1) != 0) { /* end tape */
- Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
+ Jmsg(jcr, M_FATAL, 0, "%s", dev->errmsg);
dev->VolCatInfo.VolCatErrors++;
}
/* Don't do update after second EOF or file count will be wrong */
dev->VolCatInfo.VolCatFiles = dev->file;
dir_update_volume_info(dcr, false);
if (dev_cap(dev, CAP_TWOEOF) && weof_dev(dev, 1) != 0) { /* write eof */
+ /* This may not be fatal since we already wrote an EOF */
Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
dev->VolCatInfo.VolCatErrors++;
}
if (dev_state(dev, ST_TAPE) && weof_dev(dev, 1) != 0) { /* write eof */
/* Write EOF */
- Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
+ Jmsg(jcr, M_FATAL, 0, "%s", dev->errmsg);
block->write_failed = true;
dev->VolCatInfo.VolCatErrors++;
dev->state |= (ST_EOF | ST_EOT | ST_WEOT);
#endif
if (stat != (ssize_t)wlen) {
- /* We should check for errno == ENOSPC, BUT many
- * devices simply report EIO when the volume is full.
+ /* Some devices simply report EIO when the volume is full.
* With a little more thought we may be able to check
* capacity and distinguish real errors and EOT
* conditions. In any case, we probably want to
* simulate an End of Medium.
*/
if (stat == -1) {
+ berrno be;
/* I have added the ifdefing here because it appears on
* FreeBSD where MTIOCERRSTAT is defined, this not only
* clears the error but clears the residual unwritten
if (dev->dev_errno == 0) {
dev->dev_errno = ENOSPC; /* out of space */
}
- Jmsg4(jcr, M_ERROR, 0, _("Write error at %u:%u on device %s. ERR=%s.\n"),
- dev->file, dev->block_num, dev->dev_name, strerror(dev->dev_errno));
+ if (dev->dev_errno != ENOSPC) {
+ Jmsg4(jcr, M_ERROR, 0, _("Write error at %u:%u on device %s. ERR=%s.\n"),
+ dev->file, dev->block_num, dev->dev_name, be.strerror());
+ }
} else {
dev->dev_errno = ENOSPC; /* out of space */
+ }
+ if (dev->dev_errno == ENOSPC) {
Jmsg(jcr, M_INFO, 0, _("End of Volume \"%s\" at %u:%u on device %s. Write of %u bytes got %d.\n"),
dev->VolCatInfo.VolCatName,
dev->file, dev->block_num, dev->dev_name, wlen, stat);
- }
-
+ }
Dmsg6(100, "=== Write error. size=%u rtn=%d dev_blk=%d blk_blk=%d errno=%d: ERR=%s\n",
wlen, stat, dev->block_num, block->BlockNumber, dev->dev_errno, strerror(dev->dev_errno));
block->write_failed = true;
if (weof_dev(dev, 1) != 0) { /* end the tape */
dev->VolCatInfo.VolCatErrors++;
- Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
+ Jmsg(jcr, M_FATAL, 0, "%s", dev->errmsg);
+ ok = false;
}
Dmsg0(100, "dir_update_volume_info\n");
dev->VolCatInfo.VolCatFiles = dev->file;
dir_update_volume_info(dcr, false);
- if (dev_cap(dev, CAP_TWOEOF) && weof_dev(dev, 1) != 0) { /* end the tape */
+ if (ok && dev_cap(dev, CAP_TWOEOF) && weof_dev(dev, 1) != 0) { /* end the tape */
dev->VolCatInfo.VolCatErrors++;
+ /* This may not be fatal since we already wrote an EOF */
Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
}
dev->state |= (ST_EOF | ST_EOT | ST_WEOT);
- ok = true;
#define CHECK_LAST_BLOCK
#ifdef CHECK_LAST_BLOCK
/*
* then re-read it and verify that the block number is
* correct.
*/
- if ((dev->state & ST_TAPE) && dev_cap(dev, CAP_BSR)) {
-
+ if (ok && (dev->state & ST_TAPE) && dev_cap(dev, CAP_BSR)) {
/* Now back up over what we wrote and read the last block */
if (!bsf_dev(dev, 1)) {
ok = false;
Dmsg1(100, "fsf_dev did not advance from file %d\n", file_num);
if (ioctl(dev->fd, MTIOCGET, (char *)&mt_stat) == 0 &&
mt_stat.mt_fileno >= 0) {
- Dmsg2(000, "Adjust file from %d to %d\n", dev->file , mt_stat.mt_fileno);
+ Dmsg2(100, "Adjust file from %d to %d\n", dev->file , mt_stat.mt_fileno);
dev->file = mt_stat.mt_fileno;
}
stat = 0;
int qstatus_cmd(JCR *jcr)
{
BSOCK *dir = jcr->dir_bsock;
- char time[dir->msglen+1];
+ char *time;
JCR *njcr;
s_last_job* job;
-
+
+ time = (char *) alloca(dir->msglen+1);
+
if (sscanf(dir->msg, qstatus, time) != 1) {
pm_strcpy(&jcr->errmsg, dir->msg);
Jmsg1(jcr, M_FATAL, 0, _("Bad .status command: %s\n"), jcr->errmsg);
/* */
#undef VERSION
#define VERSION "1.35.2"
-#define BDATE "16 August 2004"
-#define LSMDATE "16Aug04"
+#define BDATE "24 August 2004"
+#define LSMDATE "24Aug04"
/* Debug flags */
#undef DEBUG