From 0cceb525c499e462c2d061e84a8237dfe036977a Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Wed, 2 Mar 2005 11:38:09 +0000 Subject: [PATCH] - Make Director loop over alternative Devices specified in the Storage resource until one is reserved by SD. - Fix storing of StorageId in Media records. - Add AutoSelect = yes|no in bacula-sd.conf - Add Autochanger support to Label command. - Do not autoselect devices with autoselect set false git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@1856 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/src/dird/msgchan.c | 68 ++-- bacula/src/dird/ua_cmds.c | 1 + bacula/src/dird/ua_label.c | 3 +- bacula/src/stored/dev.c | 543 ++++++++++++++++---------------- bacula/src/stored/dircmd.c | 99 ++++-- bacula/src/stored/job.c | 5 +- bacula/src/stored/label.c | 2 +- bacula/src/stored/stored_conf.c | 205 ++++++------ bacula/src/stored/stored_conf.h | 1 + bacula/src/version.h | 6 +- 10 files changed, 498 insertions(+), 435 deletions(-) diff --git a/bacula/src/dird/msgchan.c b/bacula/src/dird/msgchan.c index 12233796ee..3e9199a1e4 100644 --- a/bacula/src/dird/msgchan.c +++ b/bacula/src/dird/msgchan.c @@ -191,34 +191,56 @@ int start_storage_daemon_job(JCR *jcr, alist *store, int append) return 0; } + pm_strcpy(pool_type, jcr->pool->pool_type); + pm_strcpy(pool_name, jcr->pool->hdr.name); + bash_spaces(pool_type); + bash_spaces(pool_name); + + /* + * We have two loops here. The first comes from the + * Storage = associated with the Job, and we need + * to attach to each one. + * The inner loop loops over all the alternative devices + * associated with each Storage. It selects the first + * available one. + * + * Note, the outer loop is not yet implemented. + */ // foreach_alist(storage, store) { storage = (STORE *)store->first(); - pm_strcpy(device_name, storage->dev_name()); - pm_strcpy(media_type, storage->media_type); - pm_strcpy(pool_type, jcr->pool->pool_type); - pm_strcpy(pool_name, jcr->pool->hdr.name); - bash_spaces(device_name); - bash_spaces(media_type); - bash_spaces(pool_type); - bash_spaces(pool_name); - bnet_fsend(sd, use_device, device_name.c_str(), - media_type.c_str(), pool_name.c_str(), pool_type.c_str(), - append); - Dmsg1(200, ">stored: %s", sd->msg); - if (bget_dirmsg(sd) > 0) { - Dmsg1(400, "msg); - ok = sscanf(sd->msg, OK_device, device_name.c_str()) == 1; - } else { - POOL_MEM err_msg; - ok = false; - pm_strcpy(err_msg, sd->msg); /* save message */ - Jmsg(jcr, M_FATAL, 0, _("\n" - " Storage daemon didn't accept Device \"%s\" because:\n %s"), - device_name.c_str(), err_msg.c_str()/* sd->msg */); + DEVICE *dev; + /* Loop over alternative storages until one is OK */ + foreach_alist(dev, storage->device) { + pm_strcpy(device_name, dev->hdr.name); + pm_strcpy(media_type, dev->MediaType); + bash_spaces(device_name); + bash_spaces(media_type); + bnet_fsend(sd, use_device, device_name.c_str(), + media_type.c_str(), pool_name.c_str(), pool_type.c_str(), + append); + Dmsg1(200, ">stored: %s", sd->msg); + if (bget_dirmsg(sd) > 0) { + Dmsg1(400, "msg); + /* ****FIXME**** save actual device name */ + ok = sscanf(sd->msg, OK_device, device_name.c_str()) == 1; + if (ok) { + break; + } + } else { + POOL_MEM err_msg; + ok = false; + pm_strcpy(err_msg, sd->msg); /* save message */ + Jmsg(jcr, M_WARNING, 0, _("\n" + " Storage daemon didn't accept Device \"%s\" because:\n %s"), + device_name.c_str(), err_msg.c_str()/* sd->msg */); + } } +// if (!ok) { +// break; +// } // } if (ok) { - bnet_fsend(sd, "run"); + ok = bnet_fsend(sd, "run"); } return ok; } diff --git a/bacula/src/dird/ua_cmds.c b/bacula/src/dird/ua_cmds.c index 8146d281d4..13e19c9478 100644 --- a/bacula/src/dird/ua_cmds.c +++ b/bacula/src/dird/ua_cmds.c @@ -316,6 +316,7 @@ getVolName: bsnprintf(mr.VolumeName, sizeof(mr.VolumeName), name, i); mr.Slot = Slot++; mr.InChanger = InChanger; + mr.StorageId = store->StorageId; Dmsg1(200, "Create Volume %s\n", mr.VolumeName); if (!db_create_media_record(ua->jcr, ua->db, &mr)) { bsendmsg(ua, "%s", db_strerror(ua->db)); diff --git a/bacula/src/dird/ua_label.c b/bacula/src/dird/ua_label.c index eecd1ee946..1fe5dc0647 100644 --- a/bacula/src/dird/ua_label.c +++ b/bacula/src/dird/ua_label.c @@ -376,6 +376,7 @@ checkName: } mr.InChanger = 1; /* assumed if we are labeling it */ } + mr.StorageId = store->StorageId; bstrncpy(mr.MediaType, store->media_type, sizeof(mr.MediaType)); @@ -387,7 +388,6 @@ checkName: } } - ok = send_label_request(ua, &mr, &omr, &pr, relabel, media_record_exists); if (ok) { @@ -505,6 +505,7 @@ static void label_from_barcodes(UAContext *ua) media_record_exists = true; } mr.InChanger = 1; + mr.StorageId = store->StorageId; /* * Deal with creating cleaning tape here. Normal tapes created in * send_label_request() below diff --git a/bacula/src/stored/dev.c b/bacula/src/stored/dev.c index cc3316fe78..e244dc621a 100644 --- a/bacula/src/stored/dev.c +++ b/bacula/src/stored/dev.c @@ -2,18 +2,18 @@ * * dev.c -- low level operations on device (storage device) * - * Kern Sibbald, MM + * Kern Sibbald, MM * * NOTE!!!! None of these routines are reentrant. You must - * use lock_device() and unlock_device() at a higher level, - * or use the xxx_device() equivalents. By moving the - * thread synchronization to a higher level, we permit + * use lock_device() and unlock_device() at a higher level, + * or use the xxx_device() equivalents. By moving the + * thread synchronization to a higher level, we permit * the higher level routines to "seize" the device and - * to carry out operations without worrying about who - * set what lock (i.e. race conditions). + * to carry out operations without worrying about who + * set what lock (i.e. race conditions). * * Note, this is the device dependent code, and my have - * to be modified for each system, but is meant to + * to be modified for each system, but is meant to * be as "generic" as possible. * * The purpose of this code is to develop a SIMPLE Storage @@ -114,10 +114,10 @@ init_dev(JCR *jcr, DEVICE *dev, DEVRES *device) if (stat(device->device_name, &statp) < 0) { berrno be; if (dev) { - dev->dev_errno = errno; + dev->dev_errno = errno; } Jmsg2(jcr, M_ERROR, 0, _("Unable to stat device %s: ERR=%s\n"), - device->device_name, be.strerror()); + device->device_name, be.strerror()); return NULL; } @@ -132,10 +132,10 @@ init_dev(JCR *jcr, DEVICE *dev, DEVRES *device) fifo = true; } else { if (dev) { - dev->dev_errno = ENODEV; + dev->dev_errno = ENODEV; } Jmsg2(jcr, M_ERROR, 0, _("%s is an unknown device type. Must be tape or directory. st_mode=%x\n"), - device->device_name, statp.st_mode); + device->device_name, statp.st_mode); return NULL; } if (!dev) { @@ -161,6 +161,7 @@ init_dev(JCR *jcr, DEVICE *dev, DEVRES *device) dev->vol_poll_interval = device->vol_poll_interval; dev->max_spool_size = device->max_spool_size; dev->drive_index = device->drive_index; + dev->autoselect = device->autoselect; if (tape) { /* No parts on tapes */ dev->max_part_size = 0; } @@ -188,11 +189,11 @@ init_dev(JCR *jcr, DEVICE *dev, DEVRES *device) */ if (dev->is_file() && device->cap_bits & CAP_REQMOUNT) { if (stat(device->mount_point, &statp) < 0) { - berrno be; - dev->dev_errno = errno; + berrno be; + dev->dev_errno = errno; Jmsg2(jcr, M_ERROR, 0, _("Unable to stat mount point %s: ERR=%s\n"), - device->mount_point, be.strerror()); - return NULL; + device->mount_point, be.strerror()); + return NULL; } if (!device->mount_command || !device->unmount_command) { Jmsg0(jcr, M_ERROR_TERM, 0, _("Mount and unmount commands must defined for a device which requires mount.\n")); @@ -205,12 +206,12 @@ init_dev(JCR *jcr, DEVICE *dev, DEVRES *device) if (dev->max_block_size > 1000000) { Jmsg3(jcr, M_ERROR, 0, _("Block size %u on device %s is too large, using default %u\n"), - dev->max_block_size, dev->dev_name, DEFAULT_BLOCK_SIZE); + dev->max_block_size, dev->dev_name, DEFAULT_BLOCK_SIZE); dev->max_block_size = 0; } if (dev->max_block_size % TAPE_BSIZE != 0) { Jmsg2(jcr, M_WARNING, 0, _("Max block size %u not multiple of device %s block size.\n"), - dev->max_block_size, dev->dev_name); + dev->max_block_size, dev->dev_name); } dev->errmsg = get_pool_memory(PM_EMSG); @@ -259,7 +260,7 @@ init_dev(JCR *jcr, DEVICE *dev, DEVRES *device) * initialize buffer pointers. * * Returns: -1 on error - * fd on success + * fd on success * * Note, for a tape, the VolName is the name we give to the * volume (not really used here), but for a file, the @@ -278,11 +279,11 @@ open_dev(DEVICE *dev, char *VolName, int mode) * starts and snatches up the device. */ if (VolName && strcmp(dev->VolCatInfo.VolCatName, VolName) != 0) { - return -1; + return -1; } dev->use_count++; Mmsg2(&dev->errmsg, _("WARNING!!!! device %s opened %d times!!!\n"), - dev->dev_name, dev->use_count); + dev->dev_name, dev->use_count); Emsg1(M_WARNING, 0, "%s", dev->errmsg); return dev->fd; } @@ -291,7 +292,7 @@ open_dev(DEVICE *dev, char *VolName, int mode) } Dmsg3(29, "open_dev: tape=%d dev_name=%s vol=%s\n", dev_is_tape(dev), - dev->dev_name, dev->VolCatInfo.VolCatName); + dev->dev_name, dev->VolCatInfo.VolCatName); dev->state &= ~(ST_LABEL|ST_APPEND|ST_READ|ST_EOT|ST_WEOT|ST_EOF); dev->label_type = B_BACULA_LABEL; if (dev->is_tape() || dev->is_fifo()) { @@ -299,53 +300,53 @@ open_dev(DEVICE *dev, char *VolName, int mode) int timeout; Dmsg0(29, "open_dev: device is tape\n"); if (mode == OPEN_READ_WRITE) { - dev->mode = O_RDWR | O_BINARY; + dev->mode = O_RDWR | O_BINARY; } else if (mode == OPEN_READ_ONLY) { - dev->mode = O_RDONLY | O_BINARY; + dev->mode = O_RDONLY | O_BINARY; } else if (mode == OPEN_WRITE_ONLY) { - dev->mode = O_WRONLY | O_BINARY; + dev->mode = O_WRONLY | O_BINARY; } else { Emsg0(M_ABORT, 0, _("Illegal mode given to open_dev.\n")); } timeout = dev->max_open_wait; errno = 0; if (dev->is_fifo() && timeout) { - /* Set open timer */ - dev->tid = start_thread_timer(pthread_self(), timeout); + /* Set open timer */ + dev->tid = start_thread_timer(pthread_self(), timeout); } /* If busy retry each second for max_open_wait seconds */ while ((dev->fd = open(dev->dev_name, dev->mode, MODE_RW)) < 0) { - berrno be; - if (errno == EINTR || errno == EAGAIN) { - continue; - } - if (errno == EBUSY && timeout-- > 0) { + berrno be; + if (errno == EINTR || errno == EAGAIN) { + continue; + } + if (errno == EBUSY && timeout-- > 0) { Dmsg2(100, "Device %s busy. ERR=%s\n", dev->dev_name, be.strerror()); - bmicrosleep(1, 0); - continue; - } - dev->dev_errno = errno; + bmicrosleep(1, 0); + continue; + } + dev->dev_errno = errno; Mmsg2(&dev->errmsg, _("stored: unable to open device %s: ERR=%s\n"), - dev->dev_name, be.strerror()); - /* Stop any open timer we set */ - if (dev->tid) { - stop_thread_timer(dev->tid); - dev->tid = 0; - } - Emsg0(M_FATAL, 0, dev->errmsg); - break; + dev->dev_name, be.strerror()); + /* Stop any open timer we set */ + if (dev->tid) { + stop_thread_timer(dev->tid); + dev->tid = 0; + } + Emsg0(M_FATAL, 0, dev->errmsg); + break; } if (dev->fd >= 0) { - dev->dev_errno = 0; - dev->state |= ST_OPENED; - dev->use_count = 1; - update_pos_dev(dev); /* update position */ - set_os_device_parameters(dev); /* do system dependent stuff */ + dev->dev_errno = 0; + dev->state |= ST_OPENED; + dev->use_count = 1; + update_pos_dev(dev); /* update position */ + set_os_device_parameters(dev); /* do system dependent stuff */ } /* Stop any open() timer we started */ if (dev->tid) { - stop_thread_timer(dev->tid); - dev->tid = 0; + stop_thread_timer(dev->tid); + dev->tid = 0; } Dmsg1(29, "open_dev: tape %d opened\n", dev->fd); } else { @@ -355,31 +356,31 @@ open_dev(DEVICE *dev, char *VolName, int mode) * Handle opening of File Archive (not a tape) */ if (dev->part == 0) { - dev->file_size = 0; + dev->file_size = 0; } dev->part_size = 0; /* if num_parts has not been set, but VolCatInfo is available, copy * it from the VolCatInfo.VolCatParts */ if (dev->num_parts < dev->VolCatInfo.VolCatParts) { - dev->num_parts = dev->VolCatInfo.VolCatParts; + dev->num_parts = dev->VolCatInfo.VolCatParts; } if (VolName == NULL || *VolName == 0) { Mmsg(dev->errmsg, _("Could not open file device %s. No Volume name given.\n"), - dev->dev_name); - return -1; + dev->dev_name); + return -1; } get_filename(dev, VolName, archive_name); if (mount_dev(dev, 1) < 0) { Mmsg(dev->errmsg, _("Could not mount archive device %s.\n"), - dev->dev_name); - Emsg0(M_FATAL, 0, dev->errmsg); - dev->fd = -1; - return dev->fd; + dev->dev_name); + Emsg0(M_FATAL, 0, dev->errmsg); + dev->fd = -1; + return dev->fd; } - + Dmsg2(29, "open_dev: device is disk %s (mode:%d)\n", archive_name.c_str(), mode); dev->openmode = mode; @@ -388,42 +389,42 @@ open_dev(DEVICE *dev, char *VolName, int mode) * OPEN_READ_ONLY as writing would be an error. */ if (dev->part < dev->num_parts) { - mode = OPEN_READ_ONLY; + mode = OPEN_READ_ONLY; } if (mode == OPEN_READ_WRITE) { - dev->mode = O_CREAT | O_RDWR | O_BINARY; + dev->mode = O_CREAT | O_RDWR | O_BINARY; } else if (mode == OPEN_READ_ONLY) { - dev->mode = O_RDONLY | O_BINARY; + dev->mode = O_RDONLY | O_BINARY; } else if (mode == OPEN_WRITE_ONLY) { - dev->mode = O_WRONLY | O_BINARY; + dev->mode = O_WRONLY | O_BINARY; } else { Emsg0(M_ABORT, 0, _("Illegal mode given to open_dev.\n")); } /* If creating file, give 0640 permissions */ if ((dev->fd = open(archive_name.c_str(), dev->mode, 0640)) < 0) { - berrno be; - dev->dev_errno = errno; + berrno be; + dev->dev_errno = errno; Mmsg2(&dev->errmsg, _("Could not open: %s, ERR=%s\n"), archive_name.c_str(), be.strerror()); - Emsg0(M_FATAL, 0, dev->errmsg); + Emsg0(M_FATAL, 0, dev->errmsg); } else { - dev->dev_errno = 0; - dev->state |= ST_OPENED; - dev->use_count = 1; - update_pos_dev(dev); /* update position */ - if (fstat(dev->fd, &filestat) < 0) { - berrno be; - dev->dev_errno = errno; + dev->dev_errno = 0; + dev->state |= ST_OPENED; + dev->use_count = 1; + update_pos_dev(dev); /* update position */ + if (fstat(dev->fd, &filestat) < 0) { + berrno be; + dev->dev_errno = errno; Mmsg2(&dev->errmsg, _("Could not fstat: %s, ERR=%s\n"), archive_name.c_str(), be.strerror()); - Emsg0(M_FATAL, 0, dev->errmsg); - } else { - dev->part_size = filestat.st_size; - } + Emsg0(M_FATAL, 0, dev->errmsg); + } else { + dev->part_size = filestat.st_size; + } } Dmsg4(29, "open_dev: disk fd=%d opened, part=%d/%d, part_size=%u\n", dev->fd, dev->part, dev->num_parts, dev->part_size); if (dev->is_dvd() && (dev->mode != OPEN_READ_ONLY) && - (dev->free_space_errno == 0 || dev->num_parts == dev->part)) { - update_free_space_dev(dev); + (dev->free_space_errno == 0 || dev->num_parts == dev->part)) { + update_free_space_dev(dev); } } return dev->fd; @@ -441,7 +442,7 @@ bool _rewind_dev(char *file, int line, DEVICE *dev) /* * Rewind the device. * Returns: true on success - * false on failure + * false on failure */ bool rewind_dev(DEVICE *dev) { @@ -452,7 +453,7 @@ bool rewind_dev(DEVICE *dev) if (dev->fd < 0) { dev->dev_errno = EBADF; Mmsg1(&dev->errmsg, _("Bad call to rewind_dev. Device %s not open\n"), - dev->dev_name); + dev->dev_name); Emsg0(M_ABORT, 0, dev->errmsg); return false; } @@ -468,30 +469,30 @@ bool rewind_dev(DEVICE *dev) * retrying every 5 seconds. */ for (i=dev->max_rewind_wait; ; i -= 5) { - if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) { - berrno be; - clrerror_dev(dev, MTREW); - if (i == dev->max_rewind_wait) { + if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) { + berrno be; + clrerror_dev(dev, MTREW); + if (i == dev->max_rewind_wait) { Dmsg1(200, "Rewind error, %s. retrying ...\n", be.strerror()); - } - if (dev->dev_errno == EIO && i > 0) { + } + if (dev->dev_errno == EIO && i > 0) { Dmsg0(200, "Sleeping 5 seconds.\n"); - bmicrosleep(5, 0); - continue; - } + bmicrosleep(5, 0); + continue; + } Mmsg2(&dev->errmsg, _("Rewind error on %s. ERR=%s.\n"), - dev->dev_name, be.strerror()); - return false; - } - break; + dev->dev_name, be.strerror()); + return false; + } + break; } } else if (dev->is_file()) { if (lseek_dev(dev, (off_t)0, SEEK_SET) < 0) { - berrno be; - dev->dev_errno = errno; + berrno be; + dev->dev_errno = errno; Mmsg2(&dev->errmsg, _("lseek_dev error on %s. ERR=%s.\n"), - dev->dev_name, be.strerror()); - return false; + dev->dev_name, be.strerror()); + return false; } } return true; @@ -517,13 +518,13 @@ void DEVICE::set_eof() void DEVICE::set_eot() { state |= (ST_EOF|ST_EOT|ST_WEOT); - state &= ~ST_APPEND; /* make tape read-only */ + state &= ~ST_APPEND; /* make tape read-only */ } /* * Position device to end of medium (end of data) * Returns: 1 on succes - * 0 on error + * 0 on error */ int eod_dev(DEVICE *dev) @@ -548,14 +549,14 @@ eod_dev(DEVICE *dev) pos = lseek_dev(dev, (off_t)0, SEEK_END); // Dmsg1(100, "====== Seek to %lld\n", pos); if (pos >= 0) { - update_pos_dev(dev); - dev->state |= ST_EOT; - return 1; + update_pos_dev(dev); + dev->state |= ST_EOT; + return 1; } dev->dev_errno = errno; berrno be; Mmsg2(&dev->errmsg, _("lseek_dev error on %s. ERR=%s.\n"), - dev->dev_name, be.strerror()); + dev->dev_name, be.strerror()); return 0; } #ifdef MTEOM @@ -563,9 +564,9 @@ eod_dev(DEVICE *dev) Dmsg0(100,"Using FAST FSF for EOM\n"); /* If unknown position, rewind */ if (!dev_get_os_pos(dev, &mt_stat)) { - if (!rewind_dev(dev)) { - return 0; - } + if (!rewind_dev(dev)) { + return 0; + } } mt_com.mt_op = MTFSF; /* @@ -574,33 +575,33 @@ eod_dev(DEVICE *dev) */ mt_com.mt_count = INT16_MAX; /* use big positive number */ if (mt_com.mt_count < 0) { - mt_com.mt_count = INT16_MAX; /* brain damaged system */ + mt_com.mt_count = INT16_MAX; /* brain damaged system */ } } if (dev_cap(dev, CAP_MTIOCGET) && (dev_cap(dev, CAP_FASTFSF) || dev_cap(dev, CAP_EOM))) { if (dev_cap(dev, CAP_EOM)) { Dmsg0(100,"Using EOM for EOM\n"); - mt_com.mt_op = MTEOM; - mt_com.mt_count = 1; + mt_com.mt_op = MTEOM; + mt_com.mt_count = 1; } if ((stat=ioctl(dev->fd, MTIOCTOP, (char *)&mt_com)) < 0) { - berrno be; - clrerror_dev(dev, mt_com.mt_op); + berrno be; + clrerror_dev(dev, mt_com.mt_op); Dmsg1(50, "ioctl error: %s\n", be.strerror()); - update_pos_dev(dev); + update_pos_dev(dev); Mmsg2(&dev->errmsg, _("ioctl MTEOM error on %s. ERR=%s.\n"), - dev->dev_name, be.strerror()); - return 0; + dev->dev_name, be.strerror()); + return 0; } if (!dev_get_os_pos(dev, &mt_stat)) { - berrno be; - clrerror_dev(dev, -1); + berrno be; + clrerror_dev(dev, -1); Mmsg2(&dev->errmsg, _("ioctl MTIOCGET error on %s. ERR=%s.\n"), - dev->dev_name, be.strerror()); - return 0; + dev->dev_name, be.strerror()); + return 0; } Dmsg2(100, "EOD file=%d block=%d\n", mt_stat.mt_fileno, mt_stat.mt_blkno); dev->set_eof(); @@ -614,7 +615,7 @@ eod_dev(DEVICE *dev) * Rewind then use FSF until EOT reached */ if (!rewind_dev(dev)) { - return 0; + return 0; } /* * Move file by file to the end of the tape @@ -622,25 +623,25 @@ eod_dev(DEVICE *dev) int file_num; for (file_num=dev->file; !dev->at_eot(); file_num++) { Dmsg0(200, "eod_dev: doing fsf 1\n"); - if (!fsf_dev(dev, 1)) { + if (!fsf_dev(dev, 1)) { Dmsg0(200, "fsf_dev error.\n"); - return 0; - } - /* - * Avoid infinite loop. ***FIXME*** possibly add code - * to set EOD or to turn off CAP_FASTFSF if on. - */ - if (file_num == (int)dev->file) { - struct mtget mt_stat; + return 0; + } + /* + * Avoid infinite loop. ***FIXME*** possibly add code + * to set EOD or to turn off CAP_FASTFSF if on. + */ + if (file_num == (int)dev->file) { + struct mtget mt_stat; Dmsg1(100, "fsf_dev did not advance from file %d\n", file_num); - if (dev_get_os_pos(dev, &mt_stat)) { + if (dev_get_os_pos(dev, &mt_stat)) { Dmsg2(100, "Adjust file from %d to %d\n", dev->file , mt_stat.mt_fileno); - dev->set_eof(); - dev->file = mt_stat.mt_fileno; - } - stat = 0; - break; /* we are not progressing, bail out */ - } + dev->set_eof(); + dev->file = mt_stat.mt_fileno; + } + stat = 0; + break; /* we are not progressing, bail out */ + } } } /* @@ -655,12 +656,12 @@ eod_dev(DEVICE *dev) /* If BSF worked and fileno is known (not -1), set file */ if (dev_get_os_pos(dev, &mt_stat)) { Dmsg2(100, "BSFATEOF adjust file from %d to %d\n", dev->file , mt_stat.mt_fileno); - dev->file = mt_stat.mt_fileno; + dev->file = mt_stat.mt_fileno; } else { - dev->file++; /* wing it -- not correct on all OSes */ + dev->file++; /* wing it -- not correct on all OSes */ } } else { - update_pos_dev(dev); /* update position */ + update_pos_dev(dev); /* update position */ stat = 1; } Dmsg1(200, "EOD dev->file=%d\n", dev->file); @@ -671,7 +672,7 @@ eod_dev(DEVICE *dev) * Set the position of the device -- only for files * For other devices, there is no generic way to do it. * Returns: true on succes - * false on error + * false on error */ bool update_pos_dev(DEVICE *dev) { @@ -691,14 +692,14 @@ bool update_pos_dev(DEVICE *dev) dev->file_addr = 0; pos = lseek_dev(dev, (off_t)0, SEEK_CUR); if (pos < 0) { - berrno be; - dev->dev_errno = errno; + berrno be; + dev->dev_errno = errno; Pmsg1(000, "Seek error: ERR=%s\n", be.strerror()); Mmsg2(&dev->errmsg, _("lseek_dev error on %s. ERR=%s.\n"), - dev->dev_name, be.strerror()); - ok = false; + dev->dev_name, be.strerror()); + ok = false; } else { - dev->file_addr = pos; + dev->file_addr = pos; } } return ok; @@ -732,49 +733,49 @@ uint32_t status_dev(DEVICE *dev) Dmsg0(-20," Bacula status:"); Dmsg2(-20," file=%d block=%d\n", dev->file, dev->block_num); if (ioctl(dev->fd, MTIOCGET, (char *)&mt_stat) < 0) { - berrno be; - dev->dev_errno = errno; + berrno be; + dev->dev_errno = errno; Mmsg2(&dev->errmsg, _("ioctl MTIOCGET error on %s. ERR=%s.\n"), - dev->dev_name, be.strerror()); - return 0; + dev->dev_name, be.strerror()); + return 0; } Dmsg0(-20, " Device status:"); #if defined(HAVE_LINUX_OS) if (GMT_EOF(mt_stat.mt_gstat)) { - stat |= BMT_EOF; + stat |= BMT_EOF; Dmsg0(-20, " EOF"); } if (GMT_BOT(mt_stat.mt_gstat)) { - stat |= BMT_BOT; + stat |= BMT_BOT; Dmsg0(-20, " BOT"); } if (GMT_EOT(mt_stat.mt_gstat)) { - stat |= BMT_EOT; + stat |= BMT_EOT; Dmsg0(-20, " EOT"); } if (GMT_SM(mt_stat.mt_gstat)) { - stat |= BMT_SM; + stat |= BMT_SM; Dmsg0(-20, " SM"); } if (GMT_EOD(mt_stat.mt_gstat)) { - stat |= BMT_EOD; + stat |= BMT_EOD; Dmsg0(-20, " EOD"); } if (GMT_WR_PROT(mt_stat.mt_gstat)) { - stat |= BMT_WR_PROT; + stat |= BMT_WR_PROT; Dmsg0(-20, " WR_PROT"); } if (GMT_ONLINE(mt_stat.mt_gstat)) { - stat |= BMT_ONLINE; + stat |= BMT_ONLINE; Dmsg0(-20, " ONLINE"); } if (GMT_DR_OPEN(mt_stat.mt_gstat)) { - stat |= BMT_DR_OPEN; + stat |= BMT_DR_OPEN; Dmsg0(-20, " DR_OPEN"); } if (GMT_IM_REP_EN(mt_stat.mt_gstat)) { - stat |= BMT_IM_REP_EN; + stat |= BMT_IM_REP_EN; Dmsg0(-20, " IM_REP_EN"); } #endif /* !SunOS && !OSF */ @@ -793,7 +794,7 @@ uint32_t status_dev(DEVICE *dev) /* * Load medium in device * Returns: true on success - * false on failure + * false on failure */ bool load_dev(DEVICE *dev) { @@ -813,9 +814,9 @@ bool load_dev(DEVICE *dev) #ifndef MTLOAD Dmsg0(200, "stored: MTLOAD command not available\n"); berrno be; - dev->dev_errno = ENOTTY; /* function not available */ + dev->dev_errno = ENOTTY; /* function not available */ Mmsg2(&dev->errmsg, _("ioctl MTLOAD error on %s. ERR=%s.\n"), - dev->dev_name, be.strerror()); + dev->dev_name, be.strerror()); return false; #else @@ -828,7 +829,7 @@ bool load_dev(DEVICE *dev) berrno be; dev->dev_errno = errno; Mmsg2(&dev->errmsg, _("ioctl MTLOAD error on %s. ERR=%s.\n"), - dev->dev_name, be.strerror()); + dev->dev_name, be.strerror()); return false; } return true; @@ -838,7 +839,7 @@ bool load_dev(DEVICE *dev) /* * Rewind device and put it offline * Returns: true on success - * false on failure + * false on failure */ bool offline_dev(DEVICE *dev) { @@ -870,7 +871,7 @@ bool offline_dev(DEVICE *dev) berrno be; dev->dev_errno = errno; Mmsg2(&dev->errmsg, _("ioctl MTOFFL error on %s. ERR=%s.\n"), - dev->dev_name, be.strerror()); + dev->dev_name, be.strerror()); return false; } Dmsg1(100, "Offlined device %s\n", dev->dev_name); @@ -900,7 +901,7 @@ bool offline_or_rewind_dev(DEVICE *dev) /* * Foward space a file * Returns: true on success - * false on failure + * false on failure */ bool fsf_dev(DEVICE *dev, int num) @@ -942,14 +943,14 @@ fsf_dev(DEVICE *dev, int num) mt_com.mt_count = num; stat = ioctl(dev->fd, MTIOCTOP, (char *)&mt_com); if (stat < 0 || !dev_get_os_pos(dev, &mt_stat)) { - berrno be; - dev->state |= ST_EOT; + berrno be; + dev->state |= ST_EOT; Dmsg0(200, "Set ST_EOT\n"); - clrerror_dev(dev, MTFSF); + clrerror_dev(dev, MTFSF); Mmsg2(dev->errmsg, _("ioctl MTFSF error on %s. ERR=%s.\n"), - dev->dev_name, be.strerror()); + dev->dev_name, be.strerror()); Dmsg1(200, "%s", dev->errmsg); - return false; + return false; } Dmsg2(200, "fsf file=%d block=%d\n", mt_stat.mt_fileno, mt_stat.mt_blkno); dev->set_eof(); @@ -968,60 +969,60 @@ fsf_dev(DEVICE *dev, int num) int rbuf_len; Dmsg0(200, "FSF has cap_fsf\n"); if (dev->max_block_size == 0) { - rbuf_len = DEFAULT_BLOCK_SIZE; + rbuf_len = DEFAULT_BLOCK_SIZE; } else { - rbuf_len = dev->max_block_size; + rbuf_len = dev->max_block_size; } rbuf = get_memory(rbuf_len); mt_com.mt_op = MTFSF; mt_com.mt_count = 1; while (num-- && !(dev->state & ST_EOT)) { Dmsg0(100, "Doing read before fsf\n"); - if ((stat = read(dev->fd, (char *)rbuf, rbuf_len)) < 0) { - if (errno == ENOMEM) { /* tape record exceeds buf len */ - stat = rbuf_len; /* This is OK */ - } else { - berrno be; - dev->state |= ST_EOT; - clrerror_dev(dev, -1); + if ((stat = read(dev->fd, (char *)rbuf, rbuf_len)) < 0) { + if (errno == ENOMEM) { /* tape record exceeds buf len */ + stat = rbuf_len; /* This is OK */ + } else { + berrno be; + dev->state |= ST_EOT; + clrerror_dev(dev, -1); Dmsg2(100, "Set ST_EOT read errno=%d. ERR=%s\n", dev->dev_errno, - be.strerror()); + be.strerror()); Mmsg2(dev->errmsg, _("read error on %s. ERR=%s.\n"), - dev->dev_name, be.strerror()); + dev->dev_name, be.strerror()); Dmsg1(100, "%s", dev->errmsg); - break; - } - } - if (stat == 0) { /* EOF */ - update_pos_dev(dev); + break; + } + } + if (stat == 0) { /* EOF */ + update_pos_dev(dev); Dmsg1(100, "End of File mark from read. File=%d\n", dev->file+1); - /* Two reads of zero means end of tape */ - if (dev->state & ST_EOF) { - dev->state |= ST_EOT; + /* Two reads of zero means end of tape */ + if (dev->state & ST_EOF) { + dev->state |= ST_EOT; Dmsg0(100, "Set ST_EOT\n"); - break; - } else { - dev->set_eof(); - continue; - } - } else { /* Got data */ - dev->state &= ~(ST_EOF|ST_EOT); - } + break; + } else { + dev->set_eof(); + continue; + } + } else { /* Got data */ + dev->state &= ~(ST_EOF|ST_EOT); + } Dmsg0(100, "Doing MTFSF\n"); - stat = ioctl(dev->fd, MTIOCTOP, (char *)&mt_com); - if (stat < 0) { /* error => EOT */ - berrno be; - dev->state |= ST_EOT; + stat = ioctl(dev->fd, MTIOCTOP, (char *)&mt_com); + if (stat < 0) { /* error => EOT */ + berrno be; + dev->state |= ST_EOT; Dmsg0(100, "Set ST_EOT\n"); - clrerror_dev(dev, MTFSF); + clrerror_dev(dev, MTFSF); Mmsg2(&dev->errmsg, _("ioctl MTFSF error on %s. ERR=%s.\n"), - dev->dev_name, be.strerror()); + dev->dev_name, be.strerror()); Dmsg0(100, "Got < 0 for MTFSF\n"); Dmsg1(100, "%s", dev->errmsg); - } else { - dev->set_eof(); - } + } else { + dev->set_eof(); + } } free_memory(rbuf); @@ -1031,14 +1032,14 @@ fsf_dev(DEVICE *dev, int num) } else { Dmsg0(200, "Doing FSR for FSF\n"); while (num-- && !(dev->state & ST_EOT)) { - fsr_dev(dev, INT32_MAX); /* returns -1 on EOF or EOT */ + fsr_dev(dev, INT32_MAX); /* returns -1 on EOF or EOT */ } if (dev->state & ST_EOT) { - dev->dev_errno = 0; + dev->dev_errno = 0; Mmsg1(dev->errmsg, _("Device %s at End of Tape.\n"), dev->dev_name); - stat = -1; + stat = -1; } else { - stat = 0; + stat = 0; } } update_pos_dev(dev); @@ -1054,7 +1055,7 @@ fsf_dev(DEVICE *dev, int num) /* * Backward space a file * Returns: false on failure - * true on success + * true on success */ bool bsf_dev(DEVICE *dev, int num) @@ -1071,7 +1072,7 @@ bsf_dev(DEVICE *dev, int num) if (!dev->is_tape()) { Mmsg1(dev->errmsg, _("Device %s cannot BSF because it is not a tape.\n"), - dev->dev_name); + dev->dev_name); return false; } Dmsg0(29, "bsf_dev\n"); @@ -1086,7 +1087,7 @@ bsf_dev(DEVICE *dev, int num) berrno be; clrerror_dev(dev, MTBSF); Mmsg2(dev->errmsg, _("ioctl MTBSF error on %s. ERR=%s.\n"), - dev->dev_name, be.strerror()); + dev->dev_name, be.strerror()); } update_pos_dev(dev); return stat == 0; @@ -1096,7 +1097,7 @@ bsf_dev(DEVICE *dev, int num) /* * Foward space a record * Returns: false on failure - * true on success + * true on success */ bool fsr_dev(DEVICE *dev, int num) @@ -1133,18 +1134,18 @@ fsr_dev(DEVICE *dev, int num) Dmsg1(100, "FSF fail: ERR=%s\n", be.strerror()); if (dev_get_os_pos(dev, &mt_stat)) { Dmsg4(100, "Adjust from %d:%d to %d:%d\n", dev->file, - dev->block_num, mt_stat.mt_fileno, mt_stat.mt_blkno); - dev->file = mt_stat.mt_fileno; - dev->block_num = mt_stat.mt_blkno; + dev->block_num, mt_stat.mt_fileno, mt_stat.mt_blkno); + dev->file = mt_stat.mt_fileno; + dev->block_num = mt_stat.mt_blkno; } else { - if (dev->state & ST_EOF) { - dev->state |= ST_EOT; - } else { - dev->set_eof(); - } + if (dev->state & ST_EOF) { + dev->state |= ST_EOT; + } else { + dev->set_eof(); + } } Mmsg2(dev->errmsg, _("ioctl MTFSR error on %s. ERR=%s.\n"), - dev->dev_name, be.strerror()); + dev->dev_name, be.strerror()); } update_pos_dev(dev); return stat == 0; @@ -1153,7 +1154,7 @@ fsr_dev(DEVICE *dev, int num) /* * Backward space a record * Returns: false on failure - * true on success + * true on success */ bool bsr_dev(DEVICE *dev, int num) @@ -1187,7 +1188,7 @@ bsr_dev(DEVICE *dev, int num) berrno be; clrerror_dev(dev, MTBSR); Mmsg2(dev->errmsg, _("ioctl MTBSR error on %s. ERR=%s.\n"), - dev->dev_name, be.strerror()); + dev->dev_name, be.strerror()); } update_pos_dev(dev); return stat == 0; @@ -1196,7 +1197,7 @@ bsr_dev(DEVICE *dev, int num) /* * Reposition the device to file, block * Returns: false on failure - * true on success + * true on success */ bool reposition_dev(DEVICE *dev, uint32_t file, uint32_t block) @@ -1212,11 +1213,11 @@ reposition_dev(DEVICE *dev, uint32_t file, uint32_t block) off_t pos = (((off_t)file)<<32) + block; Dmsg1(100, "===== lseek_dev to %d\n", (int)pos); if (lseek_dev(dev, pos, SEEK_SET) == (off_t)-1) { - berrno be; - dev->dev_errno = errno; + berrno be; + dev->dev_errno = errno; Mmsg2(dev->errmsg, _("lseek_dev error on %s. ERR=%s.\n"), - dev->dev_name, be.strerror()); - return false; + dev->dev_name, be.strerror()); + return false; } dev->file = file; dev->block_num = block; @@ -1228,14 +1229,14 @@ reposition_dev(DEVICE *dev, uint32_t file, uint32_t block) if (file < dev->file) { Dmsg0(100, "Rewind_dev\n"); if (!rewind_dev(dev)) { - return false; + return false; } } if (file > dev->file) { Dmsg1(100, "fsf %d\n", file-dev->file); if (!fsf_dev(dev, file-dev->file)) { Dmsg1(100, "fsf failed! ERR=%s\n", strerror_dev(dev)); - return false; + return false; } Dmsg2(100, "wanted_file=%d at_file=%d\n", file, dev->file); } @@ -1260,7 +1261,7 @@ reposition_dev(DEVICE *dev, uint32_t file, uint32_t block) /* * Write an end of file on the device * Returns: 0 on success - * non-zero on failure + * non-zero on failure */ int weof_dev(DEVICE *dev, int num) @@ -1299,7 +1300,7 @@ weof_dev(DEVICE *dev, int num) clrerror_dev(dev, MTWEOF); if (stat == -1) { Mmsg2(dev->errmsg, _("ioctl MTWEOF error on %s. ERR=%s.\n"), - dev->dev_name, be.strerror()); + dev->dev_name, be.strerror()); } } return stat; @@ -1329,7 +1330,7 @@ clrerror_dev(DEVICE *dev, int func) struct mtget mt_stat; char buf[100]; - dev->dev_errno = errno; /* save errno */ + dev->dev_errno = errno; /* save errno */ if (errno == EIO) { dev->VolCatInfo.VolCatErrors++; } @@ -1341,60 +1342,60 @@ clrerror_dev(DEVICE *dev, int func) switch (func) { case -1: Emsg0(M_ABORT, 0, "Got ENOTTY on read/write!\n"); - break; + break; case MTWEOF: msg = "WTWEOF"; - dev->capabilities &= ~CAP_EOF; /* turn off feature */ - break; + dev->capabilities &= ~CAP_EOF; /* turn off feature */ + break; #ifdef MTEOM case MTEOM: msg = "WTEOM"; - dev->capabilities &= ~CAP_EOM; /* turn off feature */ - break; + dev->capabilities &= ~CAP_EOM; /* turn off feature */ + break; #endif case MTFSF: msg = "MTFSF"; - dev->capabilities &= ~CAP_FSF; /* turn off feature */ - break; + dev->capabilities &= ~CAP_FSF; /* turn off feature */ + break; case MTBSF: msg = "MTBSF"; - dev->capabilities &= ~CAP_BSF; /* turn off feature */ - break; + dev->capabilities &= ~CAP_BSF; /* turn off feature */ + break; case MTFSR: msg = "MTFSR"; - dev->capabilities &= ~CAP_FSR; /* turn off feature */ - break; + dev->capabilities &= ~CAP_FSR; /* turn off feature */ + break; case MTBSR: msg = "MTBSR"; - dev->capabilities &= ~CAP_BSR; /* turn off feature */ - break; + dev->capabilities &= ~CAP_BSR; /* turn off feature */ + break; case MTREW: msg = "MTREW"; - break; + break; #ifdef MTSETBLK case MTSETBLK: msg = "MTSETBLK"; - break; + break; #endif #ifdef MTSETBSIZ case MTSETBSIZ: msg = "MTSETBSIZ"; - break; + break; #endif #ifdef MTSRSZ case MTSRSZ: msg = "MTSRSZ"; - break; + break; #endif default: bsnprintf(buf, sizeof(buf), "unknown func code %d", func); - msg = buf; - break; + msg = buf; + break; } if (msg != NULL) { - dev->dev_errno = ENOSYS; + dev->dev_errno = ENOSYS; Mmsg1(dev->errmsg, _("I/O function \"%s\" not supported on this device.\n"), msg); - Emsg0(M_ERROR, 0, dev->errmsg); + Emsg0(M_ERROR, 0, dev->errmsg); } } /* On some systems such as NetBSD, this clears all errors */ @@ -1465,7 +1466,7 @@ static void do_close(DEVICE *dev) get_filename(dev, dev->VolCatInfo.VolCatName, archive_name); /* Check that the part file is empty */ if ((stat(archive_name.c_str(), &statp) == 0) && (statp.st_size == 0)) { - unlink(archive_name.c_str()); + unlink(archive_name.c_str()); } } @@ -1546,7 +1547,7 @@ bool truncate_dev(DEVICE *dev) dev->num_parts = 0; dev->VolCatInfo.VolCatParts = 0; if (open_first_part(dev) < 0) { - berrno be; + berrno be; Mmsg1(&dev->errmsg, "Unable to truncate device, because I'm unable to open the first part. ERR=%s\n", be.strerror()); } } @@ -1651,7 +1652,7 @@ void init_dev_wait_timers(DEVICE *dev) /* ******FIXME******* put these on config variables */ dev->min_wait = 60 * 60; dev->max_wait = 24 * 60 * 60; - dev->max_num_wait = 9; /* 5 waits =~ 1 day, then 1 day at a time */ + dev->max_num_wait = 9; /* 5 waits =~ 1 day, then 1 day at a time */ dev->wait_sec = dev->min_wait; dev->rem_wait_sec = dev->wait_sec; dev->num_wait = 0; @@ -1661,11 +1662,11 @@ void init_dev_wait_timers(DEVICE *dev) /* * Returns: true if time doubled - * false if max time expired + * false if max time expired */ bool double_dev_wait_time(DEVICE *dev) { - dev->wait_sec *= 2; /* double wait time */ + dev->wait_sec *= 2; /* double wait time */ if (dev->wait_sec > dev->max_wait) { /* but not longer than maxtime */ dev->wait_sec = dev->max_wait; } @@ -1686,18 +1687,18 @@ void set_os_device_parameters(DEVICE *dev) mt_com.mt_op = MTSETBLK; mt_com.mt_count = 0; if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) { - clrerror_dev(dev, MTSETBLK); + clrerror_dev(dev, MTSETBLK); } mt_com.mt_op = MTSETDRVBUFFER; mt_com.mt_count = MT_ST_CLEARBOOLEANS; if (!dev_cap(dev, CAP_TWOEOF)) { - mt_com.mt_count |= MT_ST_TWO_FM; + mt_com.mt_count |= MT_ST_TWO_FM; } if (dev_cap(dev, CAP_EOM)) { - mt_com.mt_count |= MT_ST_FAST_MTEOM; + mt_com.mt_count |= MT_ST_FAST_MTEOM; } if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) { - clrerror_dev(dev, MTSETBLK); + clrerror_dev(dev, MTSETBLK); } } return; @@ -1710,13 +1711,13 @@ void set_os_device_parameters(DEVICE *dev) mt_com.mt_op = MTSETBSIZ; mt_com.mt_count = 0; if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) { - clrerror_dev(dev, MTSETBSIZ); + clrerror_dev(dev, MTSETBSIZ); } /* Get notified at logical end of tape */ mt_com.mt_op = MTEWARN; mt_com.mt_count = 1; if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) { - clrerror_dev(dev, MTEWARN); + clrerror_dev(dev, MTEWARN); } } return; @@ -1729,7 +1730,7 @@ void set_os_device_parameters(DEVICE *dev) mt_com.mt_op = MTSETBSIZ; mt_com.mt_count = 0; if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) { - clrerror_dev(dev, MTSETBSIZ); + clrerror_dev(dev, MTSETBSIZ); } } return; @@ -1742,7 +1743,7 @@ void set_os_device_parameters(DEVICE *dev) mt_com.mt_op = MTSRSZ; mt_com.mt_count = 0; if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) { - clrerror_dev(dev, MTSRSZ); + clrerror_dev(dev, MTSRSZ); } } return; @@ -1752,6 +1753,6 @@ void set_os_device_parameters(DEVICE *dev) static bool dev_get_os_pos(DEVICE *dev, struct mtget *mt_stat) { return dev_cap(dev, CAP_MTIOCGET) && - ioctl(dev->fd, MTIOCGET, (char *)mt_stat) == 0 && - mt_stat->mt_fileno >= 0; + ioctl(dev->fd, MTIOCGET, (char *)mt_stat) == 0 && + mt_stat->mt_fileno >= 0; } diff --git a/bacula/src/stored/dircmd.c b/bacula/src/stored/dircmd.c index 4026e1c737..35c1086871 100644 --- a/bacula/src/stored/dircmd.c +++ b/bacula/src/stored/dircmd.c @@ -76,7 +76,7 @@ static bool mount_cmd(JCR *jcr); static bool unmount_cmd(JCR *jcr); static bool autochanger_cmd(JCR *sjcr); static bool do_label(JCR *jcr, int relabel); -static DEVICE *find_device(JCR *jcr, POOL_MEM &dname); +static DEVICE *find_device(JCR *jcr, POOL_MEM &dev_name); static void read_volume_label(JCR *jcr, DEVICE *dev, int Slot); static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *oldname, char *newname, char *poolname, @@ -299,7 +299,7 @@ static bool relabel_cmd(JCR *jcr) static bool do_label(JCR *jcr, int relabel) { POOLMEM *newname, *oldname, *poolname, *mtype; - POOL_MEM dname; + POOL_MEM dev_name; BSOCK *dir = jcr->dir_bsock; DEVICE *dev; bool ok = false; @@ -311,13 +311,13 @@ static bool do_label(JCR *jcr, int relabel) mtype = get_memory(dir->msglen+1); if (relabel) { if (sscanf(dir->msg, "relabel %127s OldName=%127s NewName=%127s PoolName=%127s MediaType=%127s Slot=%d", - dname.c_str(), oldname, newname, poolname, mtype, &slot) == 6) { + dev_name.c_str(), oldname, newname, poolname, mtype, &slot) == 6) { ok = true; } } else { *oldname = 0; if (sscanf(dir->msg, "label %127s VolumeName=%127s PoolName=%127s MediaType=%127s Slot=%d", - dname.c_str(), newname, poolname, mtype, &slot) == 5) { + dev_name.c_str(), newname, poolname, mtype, &slot) == 5) { ok = true; } } @@ -326,7 +326,7 @@ static bool do_label(JCR *jcr, int relabel) unbash_spaces(oldname); unbash_spaces(poolname); unbash_spaces(mtype); - dev = find_device(jcr, dname); + dev = find_device(jcr, dev_name); if (dev) { /******FIXME**** compare MediaTypes */ P(dev->mutex); /* Use P to avoid indefinite block */ @@ -346,7 +346,7 @@ static bool do_label(JCR *jcr, int relabel) } V(dev->mutex); } else { - bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), dname.c_str()); + bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), dev_name.c_str()); } } else { /* NB dir->msg gets clobbered in bnet_fsend, so save command */ @@ -469,26 +469,59 @@ static bool read_label(DCR *dcr) return ok; } -static DEVICE *find_device(JCR *jcr, POOL_MEM &dname) +static DEVICE *find_device(JCR *jcr, POOL_MEM &devname) { DEVRES *device; + AUTOCHANGER *changer; bool found = false; - unbash_spaces(dname); + unbash_spaces(devname); LockRes(); foreach_res(device, R_DEVICE) { /* Find resource, and make sure we were able to open it */ - if (strcmp(device->hdr.name, dname.c_str()) == 0 && device->dev) { + if (fnmatch(device->hdr.name, devname.c_str(), 0) == 0) { + if (!device->dev) { + device->dev = init_dev(jcr, NULL, device); + } + if (!device->dev) { + Jmsg(jcr, M_WARNING, 0, _("\n" + " Device \"%s\" requested by DIR could not be opened or does not exist.\n"), + devname.c_str()); + continue; + } Dmsg1(20, "Found device %s\n", device->hdr.name); found = true; break; } } + foreach_res(changer, R_AUTOCHANGER) { + /* Find resource, and make sure we were able to open it */ + if (fnmatch(devname.c_str(), changer->hdr.name, 0) == 0) { + /* Try each device in this AutoChanger */ + foreach_alist(device, changer->device) { + Dmsg1(100, "Try changer device %s\n", device->hdr.name); + if (!device->dev) { + device->dev = init_dev(jcr, NULL, device); + } + if (!device->dev) { + Dmsg1(100, "Device %s could not be opened. Skipped\n", devname.c_str()); + Jmsg(jcr, M_WARNING, 0, _("\n" + " Device \"%s\" in changer \"%s\" requested by DIR could not be opened or does not exist.\n"), + device->hdr.name, devname.c_str()); + continue; + } + if (!device->dev->autoselect) { + continue; /* device is not available */ + } + Dmsg1(20, "Found changer device %s\n", device->hdr.name); + found = true; + break; + } + break; /* we found it but could not open a device */ + } + } + if (found) { - /* - * ****FIXME***** device->dev may not point to right device - * if there are multiple devices open - */ jcr->dcr = new_dcr(jcr, device->dev); UnlockRes(); jcr->dcr->device = device; @@ -504,13 +537,13 @@ static DEVICE *find_device(JCR *jcr, POOL_MEM &dname) */ static bool mount_cmd(JCR *jcr) { - POOL_MEM dname; + POOL_MEM devname; BSOCK *dir = jcr->dir_bsock; DEVICE *dev; DCR *dcr; - if (sscanf(dir->msg, "mount %127s", dname.c_str()) == 1) { - dev = find_device(jcr, dname); + if (sscanf(dir->msg, "mount %127s", devname.c_str()) == 1) { + dev = find_device(jcr, devname); dcr = jcr->dcr; if (dev) { P(dev->mutex); /* Use P to avoid indefinite block */ @@ -600,7 +633,7 @@ static bool mount_cmd(JCR *jcr) } V(dev->mutex); } else { - bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), dname.c_str()); + bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), devname.c_str()); } } else { pm_strcpy(jcr->errmsg, dir->msg); @@ -615,12 +648,12 @@ static bool mount_cmd(JCR *jcr) */ static bool unmount_cmd(JCR *jcr) { - POOL_MEM dname; + POOL_MEM devname; BSOCK *dir = jcr->dir_bsock; DEVICE *dev; - if (sscanf(dir->msg, "unmount %127s", dname.c_str()) == 1) { - dev = find_device(jcr, dname); + if (sscanf(dir->msg, "unmount %127s", devname.c_str()) == 1) { + dev = find_device(jcr, devname); if (dev) { P(dev->mutex); /* Use P to avoid indefinite block */ if (!dev->is_open()) { @@ -661,7 +694,7 @@ static bool unmount_cmd(JCR *jcr) } V(dev->mutex); } else { - bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), dname.c_str()); + bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), devname.c_str()); } } else { /* NB dir->msg gets clobbered in bnet_fsend, so save command */ @@ -681,12 +714,12 @@ static bool unmount_cmd(JCR *jcr) */ static bool release_cmd(JCR *jcr) { - POOL_MEM dname; + POOL_MEM devname; BSOCK *dir = jcr->dir_bsock; DEVICE *dev; - if (sscanf(dir->msg, "release %127s", dname.c_str()) == 1) { - dev = find_device(jcr, dname); + if (sscanf(dir->msg, "release %127s", devname.c_str()) == 1) { + dev = find_device(jcr, devname); if (dev) { P(dev->mutex); /* Use P to avoid indefinite block */ if (!dev->is_open()) { @@ -714,7 +747,7 @@ static bool release_cmd(JCR *jcr) } V(dev->mutex); } else { - bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), dname.c_str()); + bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), devname.c_str()); } } else { /* NB dir->msg gets clobbered in bnet_fsend, so save command */ @@ -732,13 +765,13 @@ static bool release_cmd(JCR *jcr) */ static bool autochanger_cmd(JCR *jcr) { - POOL_MEM dname; + POOL_MEM devname; BSOCK *dir = jcr->dir_bsock; DEVICE *dev; DCR *dcr; - if (sscanf(dir->msg, "autochanger list %127s ", dname.c_str()) == 1) { - dev = find_device(jcr, dname); + if (sscanf(dir->msg, "autochanger list %127s ", devname.c_str()) == 1) { + dev = find_device(jcr, devname); dcr = jcr->dcr; if (dev) { P(dev->mutex); /* Use P to avoid indefinite block */ @@ -759,7 +792,7 @@ static bool autochanger_cmd(JCR *jcr) } V(dev->mutex); } else { - bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), dname.c_str()); + bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), devname.c_str()); } } else { /* error on scanf */ pm_strcpy(jcr->errmsg, dir->msg); @@ -775,13 +808,13 @@ static bool autochanger_cmd(JCR *jcr) */ static bool readlabel_cmd(JCR *jcr) { - POOL_MEM dname; + POOL_MEM devname; BSOCK *dir = jcr->dir_bsock; DEVICE *dev; int Slot; - if (sscanf(dir->msg, "readlabel %127s Slot=%d", dname.c_str(), &Slot) == 2) { - dev = find_device(jcr, dname); + if (sscanf(dir->msg, "readlabel %127s Slot=%d", devname.c_str(), &Slot) == 2) { + dev = find_device(jcr, devname); if (dev) { P(dev->mutex); /* Use P to avoid indefinite block */ if (!dev->is_open()) { @@ -800,7 +833,7 @@ static bool readlabel_cmd(JCR *jcr) } V(dev->mutex); } else { - bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), dname.c_str()); + bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), devname.c_str()); } } else { pm_strcpy(jcr->errmsg, dir->msg); diff --git a/bacula/src/stored/job.c b/bacula/src/stored/job.c index e6b8c560d3..5bfe6f2b1a 100644 --- a/bacula/src/stored/job.c +++ b/bacula/src/stored/job.c @@ -291,7 +291,7 @@ static bool use_device_cmd(JCR *jcr) device->dev = init_dev(jcr, NULL, device); } if (!device->dev) { - Jmsg(jcr, M_FATAL, 0, _("\n" + Jmsg(jcr, M_WARNING, 0, _("\n" " Device \"%s\" requested by DIR could not be opened or does not exist.\n"), dev_name.c_str()); bnet_fsend(dir, NOT_open, dev_name.c_str()); @@ -342,6 +342,9 @@ static bool use_device_cmd(JCR *jcr) device->hdr.name, dev_name.c_str()); continue; } + if (!device->dev->autoselect) { + continue; /* device is not available */ + } dcr = new_dcr(jcr, device->dev); if (!dcr) { bnet_fsend(dir, _("3926 Could not get dcr for device: %s\n"), dev_name.c_str()); diff --git a/bacula/src/stored/label.c b/bacula/src/stored/label.c index 1ae87ff3aa..1d55f2cff0 100644 --- a/bacula/src/stored/label.c +++ b/bacula/src/stored/label.c @@ -370,7 +370,7 @@ bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, const char *Po Dmsg0(99, "write_volume_label()\n"); empty_block(dcr->block); - Dmsg1(000, "Label type=%d\n", dev->label_type); + Dmsg1(100, "Label type=%d\n", dev->label_type); if (!rewind_dev(dev)) { memset(&dev->VolHdr, 0, sizeof(dev->VolHdr)); Dmsg2(30, "Bad status on %s from rewind. ERR=%s\n", dev_name(dev), strerror_dev(dev)); diff --git a/bacula/src/stored/stored_conf.c b/bacula/src/stored/stored_conf.c index 3020768b14..a776b492c1 100644 --- a/bacula/src/stored/stored_conf.c +++ b/bacula/src/stored/stored_conf.c @@ -104,6 +104,7 @@ static RES_ITEM dev_items[] = { {"blockpositioning", store_yesno, ITEM(res_dev.cap_bits), CAP_POSITIONBLOCKS, ITEM_DEFAULT, 1}, {"usemtiocget", store_yesno, ITEM(res_dev.cap_bits), CAP_MTIOCGET, ITEM_DEFAULT, 1}, {"checklabels", store_yesno, ITEM(res_dev.cap_bits), CAP_CHECKLABELS, ITEM_DEFAULT, 0}, + {"autoselect", store_yesno, ITEM(res_dev.autoselect), 1, ITEM_DEFAULT, 1}, {"changerdevice", store_strname,ITEM(res_dev.changer_name), 0, 0, 0}, {"changercommand", store_strname,ITEM(res_dev.changer_command), 0, 0, 0}, {"alertcommand", store_strname,ITEM(res_dev.alert_command), 0, 0, 0}, @@ -159,7 +160,7 @@ RES_TABLE resources[] = { {"device", dev_items, R_DEVICE}, {"messages", msgs_items, R_MSGS}, {"autochanger", changer_items, R_AUTOCHANGER}, - {NULL, NULL, 0} + {NULL, NULL, 0} }; @@ -177,7 +178,7 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm return; } sendit(sock, "dump_resource type=%d\n", type); - if (type < 0) { /* no recursion */ + if (type < 0) { /* no recursion */ type = - type; recurse = 0; } @@ -187,40 +188,40 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm break; case R_STORAGE: sendit(sock, "Storage: name=%s SDaddr=%s SDport=%d SDDport=%d HB=%s\n", - res->res_store.hdr.name, - NPRT(get_first_address(res->res_store.sdaddrs, buf, sizeof(buf))), - get_first_port_host_order(res->res_store.sdaddrs), - get_first_port_host_order(res->res_store.sddaddrs), - edit_utime(res->res_store.heartbeat_interval, buf, sizeof(buf))); + res->res_store.hdr.name, + NPRT(get_first_address(res->res_store.sdaddrs, buf, sizeof(buf))), + get_first_port_host_order(res->res_store.sdaddrs), + get_first_port_host_order(res->res_store.sddaddrs), + edit_utime(res->res_store.heartbeat_interval, buf, sizeof(buf))); if (res->res_store.sdaddrs) { - foreach_dlist(p, res->res_store.sdaddrs) { + foreach_dlist(p, res->res_store.sdaddrs) { sendit(sock, " SDaddr=%s SDport=%d\n", - p->get_address(buf, sizeof(buf)), p->get_port_host_order()); - } + p->get_address(buf, sizeof(buf)), p->get_port_host_order()); + } } if (res->res_store.sddaddrs) { - foreach_dlist(p, res->res_store.sddaddrs) { + foreach_dlist(p, res->res_store.sddaddrs) { sendit(sock, " SDDaddr=%s SDDport=%d\n", - p->get_address(buf, sizeof(buf)), p->get_port_host_order()); - } + p->get_address(buf, sizeof(buf)), p->get_port_host_order()); + } } break; case R_DEVICE: sendit(sock, "Device: name=%s MediaType=%s Device=%s LabelType=%d\n", - res->res_dev.hdr.name, - res->res_dev.media_type, res->res_dev.device_name, - res->res_dev.label_type); + res->res_dev.hdr.name, + res->res_dev.media_type, res->res_dev.device_name, + res->res_dev.label_type); sendit(sock, " rew_wait=%d min_bs=%d max_bs=%d\n", - res->res_dev.max_rewind_wait, res->res_dev.min_block_size, - res->res_dev.max_block_size); + res->res_dev.max_rewind_wait, res->res_dev.min_block_size, + res->res_dev.max_block_size); sendit(sock, " max_jobs=%d max_files=%" lld " max_size=%" lld "\n", - res->res_dev.max_volume_jobs, res->res_dev.max_volume_files, - res->res_dev.max_volume_size); + res->res_dev.max_volume_jobs, res->res_dev.max_volume_files, + res->res_dev.max_volume_size); sendit(sock, " max_file_size=%" lld " capacity=%" lld "\n", - res->res_dev.max_file_size, res->res_dev.volume_capacity); + res->res_dev.max_file_size, res->res_dev.volume_capacity); sendit(sock, " spool_directory=%s\n", NPRT(res->res_dev.spool_directory)); sendit(sock, " max_spool_size=%" lld " max_job_spool_size=%" lld "\n", - res->res_dev.max_spool_size, res->res_dev.max_job_spool_size); + res->res_dev.max_spool_size, res->res_dev.max_job_spool_size); if (res->res_dev.changer_res) { sendit(sock, " changer=%p\n", res->res_dev.changer_res); } @@ -270,8 +271,8 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm case R_AUTOCHANGER: DEVRES *dev; sendit(sock, "Changer: name=%s Changer_devname=%s\n Changer_cmd=%s\n", - res->res_changer.hdr.name, - res->res_changer.changer_name, res->res_changer.changer_command); + res->res_changer.hdr.name, + res->res_changer.changer_name, res->res_changer.changer_command); foreach_alist(dev, res->res_changer.device) { sendit(sock, " --->Device: name=%s\n", dev->hdr.name); } @@ -321,81 +322,81 @@ void free_resource(RES *sres, int type) switch (type) { case R_DIRECTOR: if (res->res_dir.password) { - free(res->res_dir.password); + free(res->res_dir.password); } if (res->res_dir.address) { - free(res->res_dir.address); + free(res->res_dir.address); } break; case R_AUTOCHANGER: if (res->res_changer.changer_name) { - free(res->res_changer.changer_name); + free(res->res_changer.changer_name); } if (res->res_changer.changer_command) { - free(res->res_changer.changer_command); + free(res->res_changer.changer_command); } if (res->res_changer.device) { - delete res->res_changer.device; + delete res->res_changer.device; } break; case R_STORAGE: if (res->res_store.sdaddrs) { - free_addresses(res->res_store.sdaddrs); + free_addresses(res->res_store.sdaddrs); } if (res->res_store.sddaddrs) { - free_addresses(res->res_store.sddaddrs); + free_addresses(res->res_store.sddaddrs); } if (res->res_store.working_directory) { - free(res->res_store.working_directory); + free(res->res_store.working_directory); } if (res->res_store.pid_directory) { - free(res->res_store.pid_directory); + free(res->res_store.pid_directory); } if (res->res_store.subsys_directory) { - free(res->res_store.subsys_directory); + free(res->res_store.subsys_directory); } break; case R_DEVICE: if (res->res_dev.media_type) { - free(res->res_dev.media_type); + free(res->res_dev.media_type); } if (res->res_dev.device_name) { - free(res->res_dev.device_name); + free(res->res_dev.device_name); } if (res->res_dev.changer_name) { - free(res->res_dev.changer_name); + free(res->res_dev.changer_name); } if (res->res_dev.changer_command) { - free(res->res_dev.changer_command); + free(res->res_dev.changer_command); } if (res->res_dev.alert_command) { - free(res->res_dev.alert_command); + free(res->res_dev.alert_command); } if (res->res_dev.spool_directory) { - free(res->res_dev.spool_directory); + free(res->res_dev.spool_directory); } if (res->res_dev.mount_point) { - free(res->res_dev.mount_point); + free(res->res_dev.mount_point); } if (res->res_dev.mount_command) { - free(res->res_dev.mount_command); + free(res->res_dev.mount_command); } if (res->res_dev.unmount_command) { - free(res->res_dev.unmount_command); + free(res->res_dev.unmount_command); } if (res->res_dev.write_part_command) { - free(res->res_dev.write_part_command); + free(res->res_dev.write_part_command); } if (res->res_dev.free_space_command) { - free(res->res_dev.free_space_command); + free(res->res_dev.free_space_command); } break; case R_MSGS: if (res->res_msgs.mail_cmd) { - free(res->res_msgs.mail_cmd); + free(res->res_msgs.mail_cmd); } if (res->res_msgs.operator_cmd) { - free(res->res_msgs.operator_cmd); + free(res->res_msgs.operator_cmd); } free_msgs_res((MSGS *)res); /* free message resource */ res = NULL; @@ -429,10 +430,10 @@ void save_resource(int type, RES_ITEM *items, int pass) */ for (i=0; items[i].name; i++) { if (items[i].flags & ITEM_REQUIRED) { - if (!bit_is_set(i, res_all.res_dir.hdr.item_present)) { + if (!bit_is_set(i, res_all.res_dir.hdr.item_present)) { Emsg2(M_ERROR_TERM, 0, _("\"%s\" item is required in \"%s\" resource, but not found.\n"), - items[i].name, resources[rindex]); - } + items[i].name, resources[rindex]); + } } /* If this triggers, take a look at lib/parse_conf.h */ if (i >= MAX_RES_ITEMS) { @@ -453,49 +454,49 @@ void save_resource(int type, RES_ITEM *items, int pass) case R_DIRECTOR: case R_DEVICE: case R_MSGS: - break; + break; /* Resources containing a resource or an alist */ case R_STORAGE: - if ((res = (URES *)GetResWithName(R_STORAGE, res_all.res_dir.hdr.name)) == NULL) { + if ((res = (URES *)GetResWithName(R_STORAGE, res_all.res_dir.hdr.name)) == NULL) { Emsg1(M_ERROR_TERM, 0, "Cannot find Storage resource \"%s\"\n", res_all.res_dir.hdr.name); - } - res->res_store.messages = res_all.res_store.messages; - break; + } + res->res_store.messages = res_all.res_store.messages; + break; case R_AUTOCHANGER: - if ((res = (URES *)GetResWithName(type, res_all.res_changer.hdr.name)) == NULL) { + if ((res = (URES *)GetResWithName(type, res_all.res_changer.hdr.name)) == NULL) { Emsg1(M_ERROR_TERM, 0, "Cannot find AutoChanger resource %s\n", - res_all.res_changer.hdr.name); - } - /* we must explicitly copy the device alist pointer */ - res->res_changer.device = res_all.res_changer.device; - /* - * Now update each device in this resource to point back - * to the changer resource. - */ - foreach_alist(dev, res->res_changer.device) { - dev->changer_res = (AUTOCHANGER *)&res->res_changer; - } - if ((errstat = pthread_mutex_init(&res->res_changer.changer_mutex, NULL)) != 0) { - berrno be; + res_all.res_changer.hdr.name); + } + /* we must explicitly copy the device alist pointer */ + res->res_changer.device = res_all.res_changer.device; + /* + * Now update each device in this resource to point back + * to the changer resource. + */ + foreach_alist(dev, res->res_changer.device) { + dev->changer_res = (AUTOCHANGER *)&res->res_changer; + } + if ((errstat = pthread_mutex_init(&res->res_changer.changer_mutex, NULL)) != 0) { + berrno be; Jmsg1(NULL, M_ERROR_TERM, 0, _("Unable to init mutex: ERR=%s\n"), - be.strerror(errstat)); - } - break; + be.strerror(errstat)); + } + break; default: printf("Unknown resource type %d\n", type); - error = 1; - break; + error = 1; + break; } if (res_all.res_dir.hdr.name) { - free(res_all.res_dir.hdr.name); - res_all.res_dir.hdr.name = NULL; + free(res_all.res_dir.hdr.name); + res_all.res_dir.hdr.name = NULL; } if (res_all.res_dir.hdr.desc) { - free(res_all.res_dir.hdr.desc); - res_all.res_dir.hdr.desc = NULL; + free(res_all.res_dir.hdr.desc); + res_all.res_dir.hdr.desc = NULL; } return; } @@ -503,45 +504,45 @@ void save_resource(int type, RES_ITEM *items, int pass) /* The following code is only executed on pass 1 */ switch (type) { case R_DIRECTOR: - size = sizeof(DIRRES); - break; + size = sizeof(DIRRES); + break; case R_STORAGE: - size = sizeof(STORES); - break; + size = sizeof(STORES); + break; case R_DEVICE: - size = sizeof(DEVRES); - break; + size = sizeof(DEVRES); + break; case R_MSGS: - size = sizeof(MSGS); - break; + size = sizeof(MSGS); + break; case R_AUTOCHANGER: - size = sizeof(AUTOCHANGER); - break; + size = sizeof(AUTOCHANGER); + break; default: printf("Unknown resource type %d\n", type); - error = 1; - size = 1; - break; + error = 1; + size = 1; + break; } /* Common */ if (!error) { res = (URES *)malloc(size); memcpy(res, &res_all, size); if (!res_head[rindex]) { - res_head[rindex] = (RES *)res; /* store first entry */ + res_head[rindex] = (RES *)res; /* store first entry */ } else { - RES *next; - /* Add new res to end of chain */ - for (next=res_head[rindex]; next->next; next=next->next) { - if (strcmp(next->name, res->res_dir.hdr.name) == 0) { - Emsg2(M_ERROR_TERM, 0, + RES *next; + /* Add new res to end of chain */ + for (next=res_head[rindex]; next->next; next=next->next) { + if (strcmp(next->name, res->res_dir.hdr.name) == 0) { + Emsg2(M_ERROR_TERM, 0, _("Attempt to define second \"%s\" resource named \"%s\" is not permitted.\n"), - resources[rindex].name, res->res_dir.hdr.name); - } - } - next->next = (RES *)res; + resources[rindex].name, res->res_dir.hdr.name); + } + } + next->next = (RES *)res; Dmsg2(90, "Inserting %s res: %s\n", res_to_str(type), - res->res_dir.hdr.name); + res->res_dir.hdr.name); } } } diff --git a/bacula/src/stored/stored_conf.h b/bacula/src/stored/stored_conf.h index 44a9331a12..8ac96e14cd 100644 --- a/bacula/src/stored/stored_conf.h +++ b/bacula/src/stored/stored_conf.h @@ -92,6 +92,7 @@ public: char *alert_command; /* Alert command -- external program */ char *spool_directory; /* Spool file directory */ int label_type; /* label type */ + int autoselect; /* Automatically select from AutoChanger */ uint32_t drive_index; /* Autochanger drive index */ uint32_t cap_bits; /* Capabilities of this device */ uint32_t max_changer_wait; /* Changer timeout */ diff --git a/bacula/src/version.h b/bacula/src/version.h index a31b2f3939..a3ba960533 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -1,8 +1,8 @@ /* */ #undef VERSION -#define VERSION "1.37.4" -#define BDATE "01 March 2005" -#define LSMDATE "01Mar05" +#define VERSION "1.37.5" +#define BDATE "02 March 2005" +#define LSMDATE "02Mar05" /* Debug flags */ #undef DEBUG -- 2.39.5