General:
Changes to 1.38.1:
+12Oct05
+- Implement "autochanger drives" protocol so that Dir knows
+ how many drives an autochanger has.
+- Do not request drive number in label, ... if only one drive.
+- Turn off debug code.
+- Fix update slots to clear slot number of every slot before
+ setting it. This fixes (I believe) bug #471
+- Make unmount unload the autochanger slot.
+- Modify open() on mount to be read-only and non-blocking,
+ otherwise the mount can block for a long time.
+- Make a few error message numbers unique.
+- Make a few error messages more correct.
+- Apply patch from Thorsten to fix Win98 stat() command.
+10Oct05
- Remove delete of CVS from all makefiles.
- Fix seg fault when clicking on Add button in wx-console
restore panel. Bug #470.
char *media_type;
alist *device; /* Alternate devices for this Storage */
int autochanger; /* set if autochanger */
+ int drives; /* number of drives in autochanger */
uint32_t MaxConcurrentJobs; /* Maximume concurrent jobs */
uint32_t NumConcurrentJobs; /* number of concurrent jobs running */
int tls_enable; /* Enable TLS */
/* ua_label.c */
bool is_volume_name_legal(UAContext *ua, const char *name);
+int get_num_drives_from_SD(UAContext *ua);
/* ua_output.c */
void prtit(void *ctx, const char *msg);
if (!store) {
return;
}
+ set_storage(jcr, store);
+
drive = get_storage_drive(ua, store);
Dmsg3(120, "Found storage, MediaType=%s DevName=%s drive=%d\n",
store->media_type, store->dev_name(), drive);
- set_storage(jcr, store);
if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) {
bsendmsg(ua, _("Failed to connect to Storage daemon.\n"));
return;
Dmsg0(100, "Slots turned on:\n");
for (i=1; i <= num_slots; i++) {
if (slot_list[i]) {
- Dmsg1(000, "%d\n", i);
+ Dmsg1(100, "%d\n", i);
}
}
return true;
/* Walk through the list updating the media records */
for (vl=vol_list; vl; vl=vl->next) {
if (vl->Slot > max_slots) {
- bsendmsg(ua, _("Slot %d larger than max %d ignored.\n"),
+ bsendmsg(ua, _("Slot %d greater than max %d ignored.\n"),
vl->Slot, max_slots);
continue;
}
Dmsg2(100, "Got Vol=%s from SD for Slot=%d\n", vl->VolName, vl->Slot);
}
slot_list[vl->Slot] = 0; /* clear Slot */
+ memset(&mr, 0, sizeof(mr));
+ mr.Slot = vl->Slot;
+ mr.InChanger = 1;
+ mr.StorageId = store->StorageId;
+ /* Set InChanger to zero for this Slot */
+ db_lock(ua->db);
+ db_make_inchanger_unique(ua->jcr, ua->db, &mr);
+ db_unlock(ua->db);
if (!vl->VolName) {
- Dmsg1(100, "No VolName for Slot=%d setting InChanger to zero.\n", vl->Slot);
- memset(&mr, 0, sizeof(mr));
- mr.Slot = vl->Slot;
- mr.InChanger = 1;
- mr.StorageId = store->StorageId;
- /* Set InChanger to zero for this Slot */
- db_lock(ua->db);
- db_make_inchanger_unique(ua->jcr, ua->db, &mr);
- db_unlock(ua->db);
+ Dmsg1(000, "No VolName for Slot=%d setting InChanger to zero.\n", vl->Slot);
bsendmsg(ua, _("No VolName for Slot=%d set InChanger to zero.\n"), vl->Slot);
continue;
}
db_unlock(ua->db);
continue;
} else {
- bsendmsg(ua, _("Record for Volume \"%s\" not found in catalog.\n"),
- mr.VolumeName);
+ bsendmsg(ua, _("Volume \"%s\" not found in catalog. Slot=%d set InChanger to zero.\n"),
+ mr.VolumeName, vl->Slot);
}
db_unlock(ua->db);
}
bstrncpy(dev_name, store->dev_name(), sizeof(dev_name));
bash_spaces(dev_name);
- /* Ask for autochanger list of volumes */
- bnet_fsend(sd, _("autochanger slots %s \n"), dev_name);
+ /* Ask for autochanger number of slots */
+ bnet_fsend(sd, _("autochanger slots %s\n"), dev_name);
while (bnet_recv(sd) >= 0) {
if (sscanf(sd->msg, "slots=%d\n", &slots) == 1) {
return slots;
}
+/*
+ * We get the number of drives in the changer from the SD
+ */
+int get_num_drives_from_SD(UAContext *ua)
+{
+ STORE *store = ua->jcr->store;
+ char dev_name[MAX_NAME_LENGTH];
+ BSOCK *sd;
+ int drives = 0;
+
+
+ if (!(sd=open_sd_bsock(ua))) {
+ return 0;
+ }
+
+ bstrncpy(dev_name, store->dev_name(), sizeof(dev_name));
+ bash_spaces(dev_name);
+ /* Ask for autochanger number of slots */
+ bnet_fsend(sd, _("autochanger drives %s\n"), dev_name);
+
+ while (bnet_recv(sd) >= 0) {
+ if (sscanf(sd->msg, "drives=%d\n", &drives) == 1) {
+ break;
+ } else {
+ bsendmsg(ua, "%s", sd->msg);
+ }
+ }
+ close_sd_bsock(ua);
+// bsendmsg(ua, _("Device \"%s\" has %d drives.\n"), store->dev_name(), drives);
+ return drives;
+}
+
+
/*
return store;
}
+/* Get drive that we are working with for this storage */
int get_storage_drive(UAContext *ua, STORE *store)
{
int i, drive = -1;
if (i >=0) {
drive = atoi(ua->argv[i]);
} else if (store && store->autochanger) {
- ua->cmd[0] = 0;
- if (!get_cmd(ua, _("Enter autochanger drive[0]: "))) {
- drive = -1; /* None */
- } else {
- drive = atoi(ua->cmd);
+ /* If our structure is not set ask SD for # drives */
+ if (store->drives == 0) {
+ store->drives = get_num_drives_from_SD(ua);
}
+ /* If only one drive, default = 0 */
+ if (store->drives == 1) {
+ drive = 0;
+ } else {
+ /* Ask user to enter drive number */
+ ua->cmd[0] = 0;
+ if (!get_cmd(ua, _("Enter autochanger drive[0]: "))) {
+ drive = -1; /* None */
+ } else {
+ drive = atoi(ua->cmd);
+ }
+ }
}
return drive;
}
free_pool_memory(jcr->acl_text);
- bnet_sig(sd, BNET_EOD); /* end of sending data */
-
stop_heartbeat_monitor(jcr);
+ bnet_sig(sd, BNET_EOD); /* end of sending data */
+
if (jcr->big_buf) {
free(jcr->big_buf);
jcr->big_buf = NULL;
/*
- S M A R T A L L O C
- Smart Memory Allocator
+ S M A R T A L L O C
+ Smart Memory Allocator
- Evolved over several years, starting with the initial
- SMARTALLOC code for AutoSketch in 1986, guided by the Blind
- Watchbreaker, John Walker. Isolated in this general-purpose
- form in September of 1989. Updated with be more POSIX
- compliant and to include Web-friendly HTML documentation in
- October of 1998 by the same culprit. For additional
- information and the current version visit the Web page:
+ Evolved over several years, starting with the initial
+ SMARTALLOC code for AutoSketch in 1986, guided by the Blind
+ Watchbreaker, John Walker. Isolated in this general-purpose
+ form in September of 1989. Updated with be more POSIX
+ compliant and to include Web-friendly HTML documentation in
+ October of 1998 by the same culprit. For additional
+ information and the current version visit the Web page:
- http://www.fourmilab.ch/smartall/
+ http://www.fourmilab.ch/smartall/
- Version $Id$
+ Version $Id$
*/
/*
- Copyright (C) 2000-2004 Kern Sibbald and John Walker
+ Copyright (C) 2000-2005 Kern Sibbald
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 of
- the License, or (at your option) any later version.
+ modify it under the terms of the GNU General Public License
+ version 2 as amended with additional clauses defined in the
+ file LICENSE in the main source directory.
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., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA.
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ the file LICENSE for additional details.
*/
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-extern char my_name[]; /* daemon name */
+extern char my_name[]; /* daemon name */
typedef unsigned short sm_ushort;
/* Memory allocation control structures and storage. */
struct abufhead {
- struct b_queue abq; /* Links on allocated queue */
- unsigned ablen; /* Buffer length in bytes */
+ struct b_queue abq; /* Links on allocated queue */
+ unsigned ablen; /* Buffer length in bytes */
const char *abfname; /* File name pointer */
- sm_ushort ablineno; /* Line number of allocation */
+ sm_ushort ablineno; /* Line number of allocation */
};
static struct b_queue abqueue = { /* Allocated buffer queue */
};
-static bool bufimode = false; /* Buffers not tracked when True */
+static bool bufimode = false; /* Buffers not tracked when True */
#define HEAD_SIZE BALIGN(sizeof(struct abufhead))
/* SMALLOC -- Allocate buffer, enqueing on the orphaned buffer
- tracking list. */
+ tracking list. */
static void *smalloc(const char *fname, int lineno, unsigned int nbytes)
{
buf[nbytes - 1] = (((long) buf) & 0xFF) ^ 0xC5;
buf += HEAD_SIZE; /* Increment to user data start */
if (++sm_buffers > sm_max_buffers) {
- sm_max_buffers = sm_buffers;
+ sm_max_buffers = sm_buffers;
}
sm_bytes += nbytes;
if (sm_bytes > sm_max_bytes) {
- sm_max_bytes = sm_bytes;
+ sm_max_bytes = sm_bytes;
}
V(mutex);
} else {
}
/* SM_NEW_OWNER -- Update the File and line number for a buffer
- This is to accomodate mem_pool. */
+ This is to accomodate mem_pool. */
void sm_new_owner(const char *fname, int lineno, char *buf)
{
}
/* SM_FREE -- Update free pool availability. FREE is never called
- except through this interface or by actuallyfree().
- free(x) is defined to generate a call to this
- routine. */
+ except through this interface or by actuallyfree().
+ free(x) is defined to generate a call to this
+ routine. */
void sm_free(const char *file, int line, void *fp)
{
P(mutex);
Dmsg4(1150, "sm_free %d at %x from %s:%d\n",
- head->ablen, fp,
- head->abfname, head->ablineno);
+ head->ablen, fp,
+ head->abfname, head->ablineno);
/* The following assertions will catch virtually every release
of an address which isn't an allocated buffer. */
Emsg2(M_ABORT, 0, _("qp->qprev->qnext != qp called from %s:%d\n"), file, line);
}
- /* The following assertion detects storing off the end of the
+ /* The following assertion detects storing off the end of the
allocated space in the buffer by comparing the end of buffer
- checksum with the address of the buffer. */
+ checksum with the address of the buffer. */
if (((unsigned char *)cp)[head->ablen - 1] != ((((long) cp) & 0xFF) ^ 0xC5)) {
V(mutex);
qdchain(qp);
V(mutex);
- /* Now we wipe the contents of the just-released buffer with
+ /* Now we wipe the contents of the just-released buffer with
"designer garbage" (Duff Kurland's phrase) of alternating
bits. This is intended to ruin the day for any miscreant who
attempts to access data through a pointer into storage that's
}
/* SM_MALLOC -- Allocate buffer. NULL is returned if no memory
- was available. */
+ was available. */
void *sm_malloc(const char *fname, int lineno, unsigned int nbytes)
{
if ((buf = smalloc(fname, lineno, nbytes)) != NULL) {
/* To catch sloppy code that assumes buffers obtained from
- malloc() are zeroed, we preset the buffer contents to
- "designer garbage" consisting of alternating bits. */
+ malloc() are zeroed, we preset the buffer contents to
+ "designer garbage" consisting of alternating bits. */
memset(buf, 0x55, (int) nbytes);
} else {
/* SM_CALLOC -- Allocate an array and clear it to zero. */
void *sm_calloc(const char *fname, int lineno,
- unsigned int nelem, unsigned int elsize)
+ unsigned int nelem, unsigned int elsize)
{
void *buf;
return buf;
}
-/* SM_REALLOC -- Adjust the size of a previously allocated buffer.
- Note that the trick of "resurrecting" a previously
- freed buffer with realloc() is NOT supported by this
- function. Further, because of the need to maintain
- our control storage, SM_REALLOC must always allocate
- a new block and copy the data in the old block.
- This may result in programs which make heavy use of
- realloc() running much slower than normally. */
+/* SM_REALLOC -- Adjust the size of a previously allocated buffer.
+ Note that the trick of "resurrecting" a previously
+ freed buffer with realloc() is NOT supported by this
+ function. Further, because of the need to maintain
+ our control storage, SM_REALLOC must always allocate
+ a new block and copy the data in the old block.
+ This may result in programs which make heavy use of
+ realloc() running much slower than normally. */
void *sm_realloc(const char *fname, int lineno, void *ptr, unsigned int size)
{
e_msg(fname, lineno, M_ABORT, 0, _("sm_realloc size: %d\n"), size);
}
- /* If the old block pointer is NULL, treat realloc() as a
+ /* If the old block pointer is NULL, treat realloc() as a
malloc(). SVID is silent on this, but many C libraries
permit this. */
/* Sizes differ. Allocate a new buffer of the requested size.
If we can't obtain such a buffer, act as defined in SVID:
- return NULL from realloc() and leave the buffer in PTR
+ return NULL from realloc() and leave the buffer in PTR
intact. */
sm_buffers--;
if ((buf = smalloc(fname, lineno, size)) != NULL) {
memcpy(buf, ptr, (int) sm_min(size, osize));
/* If the new buffer is larger than the old, fill the balance
- of it with "designer garbage". */
+ of it with "designer garbage". */
if (size > osize) {
- memset(((char *) buf) + osize, 0x55, (int) (size - osize));
+ memset(((char *) buf) + osize, 0x55, (int) (size - osize));
}
/* All done. Free and dechain the original buffer. */
return buf;
}
-/* ACTUALLYMALLOC -- Call the system malloc() function to obtain
- storage which will eventually be released
- by system or library routines not compiled
- using SMARTALLOC. */
+/* ACTUALLYMALLOC -- Call the system malloc() function to obtain
+ storage which will eventually be released
+ by system or library routines not compiled
+ using SMARTALLOC. */
void *actuallymalloc(unsigned int size)
{
return malloc(size);
}
-/* ACTUALLYCALLOC -- Call the system calloc() function to obtain
- storage which will eventually be released
- by system or library routines not compiled
- using SMARTALLOC. */
+/* ACTUALLYCALLOC -- Call the system calloc() function to obtain
+ storage which will eventually be released
+ by system or library routines not compiled
+ using SMARTALLOC. */
void *actuallycalloc(unsigned int nelem, unsigned int elsize)
{
}
/* ACTUALLYREALLOC -- Call the system realloc() function to obtain
- storage which will eventually be released
- by system or library routines not compiled
- using SMARTALLOC. */
+ storage which will eventually be released
+ by system or library routines not compiled
+ using SMARTALLOC. */
void *actuallyrealloc(void *ptr, unsigned int size)
{
}
/* ACTUALLYFREE -- Interface to system free() function to release
- buffers allocated by low-level routines. */
+ buffers allocated by low-level routines. */
void actuallyfree(void *cp)
{
}
/* SM_DUMP -- Print orphaned buffers (and dump them if BUFDUMP is
- * True).
+ * True).
* N.B. DO NOT USE any Bacula print routines (Dmsg, Jmsg, Emsg, ...)
* as they have all been shut down at this point.
*/
while (ap != (struct abufhead *) &abqueue) {
if ((ap == NULL) ||
- (ap->abq.qnext->qprev != (struct b_queue *) ap) ||
- (ap->abq.qprev->qnext != (struct b_queue *) ap)) {
- fprintf(stderr, _(
- "\nOrphaned buffers exist. Dump terminated following\n"
- " discovery of bad links in chain of orphaned buffers.\n"
- " Buffer address with bad links: %lx\n"), (long) ap);
- break;
+ (ap->abq.qnext->qprev != (struct b_queue *) ap) ||
+ (ap->abq.qprev->qnext != (struct b_queue *) ap)) {
+ fprintf(stderr, _(
+ "\nOrphaned buffers exist. Dump terminated following\n"
+ " discovery of bad links in chain of orphaned buffers.\n"
+ " Buffer address with bad links: %lx\n"), (long) ap);
+ break;
}
if (ap->abfname != NULL) {
- unsigned memsize = ap->ablen - (HEAD_SIZE + 1);
- char errmsg[500];
-
- bsnprintf(errmsg, sizeof(errmsg),
- _("Orphaned buffer: %6u bytes allocated at line %d of %s %s\n"),
- memsize, ap->ablineno, my_name, ap->abfname
- );
- fprintf(stderr, "%s", errmsg);
- if (bufdump) {
- char buf[20];
- unsigned llen = 0;
- char *cp = ((char *) ap) + HEAD_SIZE;
-
- errmsg[0] = EOS;
- while (memsize) {
- if (llen >= 16) {
- bstrncat(errmsg, "\n", sizeof(errmsg));
- llen = 0;
- fprintf(stderr, "%s", errmsg);
- errmsg[0] = EOS;
- }
- bsnprintf(buf, sizeof(buf), " %02X",
- (*cp++) & 0xFF);
- bstrncat(errmsg, buf, sizeof(errmsg));
- llen++;
- memsize--;
- }
- fprintf(stderr, "%s\n", errmsg);
- }
+ unsigned memsize = ap->ablen - (HEAD_SIZE + 1);
+ char errmsg[500];
+
+ bsnprintf(errmsg, sizeof(errmsg),
+ _("Orphaned buffer: %6u bytes allocated at line %d of %s %s\n"),
+ memsize, ap->ablineno, my_name, ap->abfname
+ );
+ fprintf(stderr, "%s", errmsg);
+ if (bufdump) {
+ char buf[20];
+ unsigned llen = 0;
+ char *cp = ((char *) ap) + HEAD_SIZE;
+
+ errmsg[0] = EOS;
+ while (memsize) {
+ if (llen >= 16) {
+ bstrncat(errmsg, "\n", sizeof(errmsg));
+ llen = 0;
+ fprintf(stderr, "%s", errmsg);
+ errmsg[0] = EOS;
+ }
+ bsnprintf(buf, sizeof(buf), " %02X",
+ (*cp++) & 0xFF);
+ bstrncat(errmsg, buf, sizeof(errmsg));
+ llen++;
+ memsize--;
+ }
+ fprintf(stderr, "%s\n", errmsg);
+ }
}
ap = (struct abufhead *) ap->abq.qnext;
}
/* SM_CHECK -- Check the buffers and dump if any damage exists. */
void sm_check(const char *fname, int lineno, bool bufdump)
{
- if (!sm_check_rtn(fname, lineno, bufdump)) {
- Emsg2(M_ABORT, 0, _("Damaged buffer found. Called from %s:%d\n"),
- fname, lineno);
- }
+ if (!sm_check_rtn(fname, lineno, bufdump)) {
+ Emsg2(M_ABORT, 0, _("Damaged buffer found. Called from %s:%d\n"),
+ fname, lineno);
+ }
}
#undef sm_check_rtn
while (ap != (struct abufhead *) &abqueue) {
bad = 0;
if ((ap == NULL) ||
- (ap->abq.qnext->qprev != (struct b_queue *) ap)) {
- bad = 0x1;
+ (ap->abq.qnext->qprev != (struct b_queue *) ap)) {
+ bad = 0x1;
}
if (ap->abq.qprev->qnext != (struct b_queue *) ap) {
- bad |= 0x2;
+ bad |= 0x2;
}
if (((unsigned char *) ap)[((struct abufhead *) ap)->ablen - 1] !=
- ((((long) ap) & 0xFF) ^ 0xC5)) {
- bad |= 0x4;
+ ((((long) ap) & 0xFF) ^ 0xC5)) {
+ bad |= 0x4;
}
badbuf |= bad;
if (bad) {
- fprintf(stderr,
- _("\nDamaged buffers found at %s:%d\n"), fname, lineno);
-
- if (bad & 0x1) {
- fprintf(stderr, _(" discovery of bad prev link.\n"));
- }
- if (bad & 0x2) {
- fprintf(stderr, _(" discovery of bad next link.\n"));
- }
- if (bad & 0x4) {
- fprintf(stderr, _(" discovery of data overrun.\n"));
- }
-
- fprintf(stderr, _(" Buffer address: %lx\n"), (long) ap);
-
- if (ap->abfname != NULL) {
- unsigned memsize = ap->ablen - (HEAD_SIZE + 1);
- char errmsg[80];
-
- fprintf(stderr,
- _("Damaged buffer: %6u bytes allocated at line %d of %s %s\n"),
- memsize, ap->ablineno, my_name, ap->abfname
- );
- if (bufdump) {
- unsigned llen = 0;
- char *cp = ((char *) ap) + HEAD_SIZE;
-
- errmsg[0] = EOS;
- while (memsize) {
- if (llen >= 16) {
- strcat(errmsg, "\n");
- llen = 0;
- fprintf(stderr, "%s", errmsg);
- errmsg[0] = EOS;
- }
- if (*cp < 0x20) {
- sprintf(errmsg + strlen(errmsg), " %02X",
- (*cp++) & 0xFF);
- } else {
- sprintf(errmsg + strlen(errmsg), " %c ",
- (*cp++) & 0xFF);
- }
- llen++;
- memsize--;
- }
- fprintf(stderr, "%s\n", errmsg);
- }
- }
+ fprintf(stderr,
+ _("\nDamaged buffers found at %s:%d\n"), fname, lineno);
+
+ if (bad & 0x1) {
+ fprintf(stderr, _(" discovery of bad prev link.\n"));
+ }
+ if (bad & 0x2) {
+ fprintf(stderr, _(" discovery of bad next link.\n"));
+ }
+ if (bad & 0x4) {
+ fprintf(stderr, _(" discovery of data overrun.\n"));
+ }
+
+ fprintf(stderr, _(" Buffer address: %lx\n"), (long) ap);
+
+ if (ap->abfname != NULL) {
+ unsigned memsize = ap->ablen - (HEAD_SIZE + 1);
+ char errmsg[80];
+
+ fprintf(stderr,
+ _("Damaged buffer: %6u bytes allocated at line %d of %s %s\n"),
+ memsize, ap->ablineno, my_name, ap->abfname
+ );
+ if (bufdump) {
+ unsigned llen = 0;
+ char *cp = ((char *) ap) + HEAD_SIZE;
+
+ errmsg[0] = EOS;
+ while (memsize) {
+ if (llen >= 16) {
+ strcat(errmsg, "\n");
+ llen = 0;
+ fprintf(stderr, "%s", errmsg);
+ errmsg[0] = EOS;
+ }
+ if (*cp < 0x20) {
+ sprintf(errmsg + strlen(errmsg), " %02X",
+ (*cp++) & 0xFF);
+ } else {
+ sprintf(errmsg + strlen(errmsg), " %c ",
+ (*cp++) & 0xFF);
+ }
+ llen++;
+ memsize--;
+ }
+ fprintf(stderr, "%s\n", errmsg);
+ }
+ }
}
ap = (struct abufhead *) ap->abq.qnext;
}
/* SM_STATIC -- Orphaned buffer detection can be disabled (for such
- items as buffers allocated during initialisation) by
- calling sm_static(1). Normal orphaned buffer
- detection can be re-enabled with sm_static(0). Note
- that all the other safeguards still apply to buffers
- allocated when sm_static(1) mode is in effect. */
+ items as buffers allocated during initialisation) by
+ calling sm_static(1). Normal orphaned buffer
+ detection can be re-enabled with sm_static(0). Note
+ that all the other safeguards still apply to buffers
+ allocated when sm_static(1) mode is in effect. */
void sm_static(int mode)
{
/*
- Definitions for the smart memory allocator
+ Definitions for the smart memory allocator
Version $Id$
*/
/*
- Copyright (C) 2000-2004 Kern Sibbald and John Walker
+ Copyright (C) 2000-2005 Kern Sibbald
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 of
- the License, or (at your option) any later version.
+ modify it under the terms of the GNU General Public License
+ version 2 as amended with additional clauses defined in the
+ file LICENSE in the main source directory.
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., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA.
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ the file LICENSE for additional details.
*/
extern void *sm_malloc(const char *fname, int lineno, unsigned int nbytes),
- *sm_calloc(const char *fname, int lineno,
- unsigned int nelem, unsigned int elsize),
- *sm_realloc(const char *fname, int lineno, void *ptr, unsigned int size),
- *actuallymalloc(unsigned int size),
- *actuallycalloc(unsigned int nelem, unsigned int elsize),
- *actuallyrealloc(void *ptr, unsigned int size);
+ *sm_calloc(const char *fname, int lineno,
+ unsigned int nelem, unsigned int elsize),
+ *sm_realloc(const char *fname, int lineno, void *ptr, unsigned int size),
+ *actuallymalloc(unsigned int size),
+ *actuallycalloc(unsigned int nelem, unsigned int elsize),
+ *actuallyrealloc(void *ptr, unsigned int size);
extern void sm_free(const char *fname, int lineno, void *fp);
extern void actuallyfree(void *cp),
- sm_dump(bool bufdump), sm_static(int mode);
+ sm_dump(bool bufdump), sm_static(int mode);
extern void sm_new_owner(const char *fname, int lineno, char *buf);
#ifdef SMCHECK
public:
void *operator new(size_t s)
{
- return malloc(s);
+ return malloc(s);
}
void *operator new[](size_t s)
{
- return malloc(s);
+ return malloc(s);
}
void operator delete(void *ptr)
{
- free(ptr);
+ free(ptr);
}
void operator delete[](void *ptr, size_t i)
{
- free(ptr);
+ free(ptr);
}
};
#endif
return false;
}
- changer = get_pool_memory(PM_FNAME);
/* List command? */
if (strcmp(cmd, "list") == 0) {
unload_autochanger(dcr, -1);
}
+ if (strcmp(cmd, "drives") == 0) {
+ AUTOCHANGER *changer_res = dcr->device->changer_res;
+ bnet_fsend(dir, "drives=%d\n", changer_res->device->size());
+ Dmsg1(100, "drives=%d\n", changer_res->device->size());
+ return true;
+ }
+ changer = get_pool_memory(PM_FNAME);
lock_changer(dcr);
/* Now issue the command */
changer = edit_device_codes(dcr, changer,
Dmsg1(100, "<stored: %s\n", dir->msg);
bnet_send(dir);
}
- } else {
+ } else if (strcmp(cmd, "slots") == 0 ) {
/* For slots command, read a single line */
bstrncpy(dir->msg, "slots=", len);
fgets(dir->msg+6, len-6, bpipe->rfd);
dir->msglen = strlen(dir->msg);
Dmsg1(100, "<stored: %s", dir->msg);
bnet_send(dir);
- }
+ }
stat = close_bpipe(bpipe);
if (stat != 0) {
static bool cancel_cmd(JCR *cjcr);
static bool mount_cmd(JCR *jcr);
static bool unmount_cmd(JCR *jcr);
-static bool autochanger_cmd(JCR *sjcr);
+static bool changer_cmd(JCR *sjcr);
static bool do_label(JCR *jcr, int relabel);
static DEVICE *find_device(JCR *jcr, POOL_MEM &dev_name, int drive);
static void read_volume_label(JCR *jcr, DEVICE *dev, int Slot);
*/
static struct s_cmds cmds[] = {
{"JobId=", job_cmd, 0}, /* start Job */
- {"autochanger", autochanger_cmd, 0},
+ {"autochanger", changer_cmd, 0},
{"bootstrap", bootstrap_cmd, 0},
{"cancel", cancel_cmd, 0},
{"label", label_cmd, 0}, /* label a tape */
}
V(dev->mutex);
} else {
- bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), dev_name.c_str());
+ bnet_fsend(dir, _("3999 Device \"%s\" not found or could not be opened.\n"), dev_name.c_str());
}
} else {
/* NB dir->msg gets clobbered in bnet_fsend, so save command */
continue;
}
if (!device->dev->autoselect) {
+ Dmsg1(100, "Device %s not autoselect skipped.\n", devname.c_str());
continue; /* device is not available */
}
if (drive < 0 || drive == (int)device->dev->drive_index) {
found = true;
break;
}
+ Dmsg3(100, "Device %s drive wrong: want=%d got=%d skipping\n",
+ devname.c_str(), drive, (int)device->dev->drive_index);
}
break; /* we found it but could not open a device */
}
}
if (found) {
+ Dmsg1(100, "Found changer device %s\n", device->hdr.name);
jcr->dcr = new_dcr(jcr, device->dev);
jcr->dcr->device = device;
return jcr->dcr->dev;
if (sscanf(dir->msg, "mount %127s drive=%d", devname.c_str(), &drive) == 2) {
dev = find_device(jcr, devname, drive);
dcr = jcr->dcr;
- if (dev) {
+ if (dev) {
P(dev->mutex); /* Use P to avoid indefinite block */
switch (dev->dev_blocked) { /* device blocked? */
case BST_WAITING_FOR_SYSOP:
case BST_UNMOUNTED_WAITING_FOR_SYSOP:
case BST_UNMOUNTED:
/* We freed the device, so reopen it and wake any waiting threads */
- if (dev->open(dcr, OPEN_READ_WRITE) < 0) {
+ dev->open_nowait = true;
+ if (dev->open(dcr, OPEN_READ_ONLY) < 0) {
bnet_fsend(dir, _("3901 open device failed: ERR=%s\n"),
strerror_dev(dev));
+ dev->open_nowait = false;
break;
}
+ dev->open_nowait = false;
read_dev_volume_label(dcr);
if (dev->dev_blocked == BST_UNMOUNTED) {
/* We blocked the device, so unblock it */
dev->print_name());
}
} else if (dev->is_tape()) {
- if (dev->open(dcr, OPEN_READ_WRITE) < 0) {
+ dev->open_nowait = true;
+ if (dev->open(dcr, OPEN_READ_ONLY) < 0) {
bnet_fsend(dir, _("3901 open device failed: ERR=%s\n"),
strerror_dev(dev));
+ dev->open_nowait = false;
break;
}
+ dev->open_nowait = false;
read_label(dcr);
if (dev->is_labeled()) {
bnet_fsend(dir, _("3001 Device %s is already mounted with Volume \"%s\"\n"),
}
V(dev->mutex);
} else {
- bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), devname.c_str());
+ bnet_fsend(dir, _("3999 Device \"%s\" not found or could not be opened.\n"), devname.c_str());
}
} else {
pm_strcpy(jcr->errmsg, dir->msg);
if (dev) {
P(dev->mutex); /* Use P to avoid indefinite block */
if (!dev->is_open()) {
+ if (!dev->is_busy()) {
+ unload_autochanger(jcr->dcr, -1);
+ }
Dmsg0(90, "Device already unmounted\n");
bnet_fsend(dir, _("3901 Device %s is already unmounted.\n"),
dev->print_name());
} else if (dev->dev_blocked == BST_WAITING_FOR_SYSOP) {
Dmsg2(90, "%d waiter dev_block=%d. doing unmount\n", dev->num_waiting,
dev->dev_blocked);
- offline_or_rewind_dev(dev);
- force_close_device(dev);
+ if (!unload_autochanger(jcr->dcr, -1)) {
+ offline_or_rewind_dev(dev);
+ force_close_device(dev);
+ }
dev->dev_blocked = BST_UNMOUNTED_WAITING_FOR_SYSOP;
bnet_fsend(dir, _("3001 Device %s unmounted.\n"),
dev->print_name());
/* block_device(dev, BST_UNMOUNTED); replace with 2 lines below */
dev->dev_blocked = BST_UNMOUNTED;
dev->no_wait_id = 0;
- offline_or_rewind_dev(dev);
- force_close_device(dev);
+ if (!unload_autochanger(jcr->dcr, -1)) {
+ offline_or_rewind_dev(dev);
+ force_close_device(dev);
+ }
bnet_fsend(dir, _("3002 Device %s unmounted.\n"),
dev->print_name());
}
V(dev->mutex);
} else {
- bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), devname.c_str());
+ bnet_fsend(dir, _("3999 Device \"%s\" not found or could not be opened.\n"), devname.c_str());
}
} else {
/* NB dir->msg gets clobbered in bnet_fsend, so save command */
P(dev->mutex); /* Use P to avoid indefinite block */
if (!dev->is_open()) {
Dmsg0(90, "Device already released\n");
- bnet_fsend(dir, _("3911 Device %s already released.\n"),
+ bnet_fsend(dir, _("3921 Device %s already released.\n"),
dev->print_name());
} else if (dev->dev_blocked == BST_WAITING_FOR_SYSOP ||
dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP) {
Dmsg2(90, "%d waiter dev_block=%d. doing unmount\n", dev->num_waiting,
dev->dev_blocked);
- bnet_fsend(dir, _("3912 Device %s waiting for mount.\n"),
+ bnet_fsend(dir, _("3922 Device %s waiting for mount.\n"),
dev->print_name());
} else if (dev->dev_blocked == BST_DOING_ACQUIRE) {
- bnet_fsend(dir, _("3913 Device %s is busy in acquire.\n"),
+ bnet_fsend(dir, _("3923 Device %s is busy in acquire.\n"),
dev->print_name());
} else if (dev->dev_blocked == BST_WRITING_LABEL) {
} else { /* device not being used */
Dmsg0(90, "Device not in use, unmounting\n");
release_volume(jcr->dcr);
- bnet_fsend(dir, _("3012 Device %s released.\n"),
+ bnet_fsend(dir, _("3022 Device %s released.\n"),
dev->print_name());
}
V(dev->mutex);
} else {
- bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), devname.c_str());
+ bnet_fsend(dir, _("3999 Device \"%s\" not found or could not be opened.\n"), devname.c_str());
}
} else {
/* NB dir->msg gets clobbered in bnet_fsend, so save command */
pm_strcpy(jcr->errmsg, dir->msg);
- bnet_fsend(dir, _("3917 Error scanning release command: %s\n"), jcr->errmsg);
+ bnet_fsend(dir, _("3927 Error scanning release command: %s\n"), jcr->errmsg);
}
bnet_sig(dir, BNET_EOD);
return true;
/*
* Autochanger command from Director
*/
-static bool autochanger_cmd(JCR *jcr)
+static bool changer_cmd(JCR *jcr)
{
POOL_MEM devname;
BSOCK *dir = jcr->dir_bsock;
const char *cmd = NULL;
bool ok = false;
- if (sscanf(dir->msg, "autochanger list %127s ", devname.c_str()) == 1) {
+ if (sscanf(dir->msg, "autochanger list %127s", devname.c_str()) == 1) {
cmd = "list";
ok = true;
- } else if (sscanf(dir->msg, "autochanger slots %127s ", devname.c_str()) == 1) {
+ } else if (sscanf(dir->msg, "autochanger slots %127s", devname.c_str()) == 1) {
cmd = "slots";
ok = true;
+ } else if (sscanf(dir->msg, "autochanger drives %127s", devname.c_str()) == 1) {
+ cmd = "drives";
+ ok = true;
}
if (ok) {
dev = find_device(jcr, devname, -1);
}
V(dev->mutex);
} else {
- bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), devname.c_str());
+ bnet_fsend(dir, _("3999 Device \"%s\" not found or could not be opened.\n"), devname.c_str());
}
} else { /* error on scanf */
pm_strcpy(jcr->errmsg, dir->msg);
- bnet_fsend(dir, _("3908 Error scanning autocharger list/slots command: %s\n"),
+ bnet_fsend(dir, _("3908 Error scanning autocharger drives/list/slots command: %s\n"),
jcr->errmsg);
}
bnet_sig(dir, BNET_EOD);
}
V(dev->mutex);
} else {
- bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), devname.c_str());
+ bnet_fsend(dir, _("3999 Device \"%s\" not found or could not be opened.\n"), devname.c_str());
}
} else {
pm_strcpy(jcr->errmsg, dir->msg);
static void send_dir_busy_message(BSOCK *dir, DEVICE *dev)
{
- if (dev->can_read()) {
- bnet_fsend(dir, _("3911 Device %s is busy reading.\n"),
+ if (dev->is_blocked()) {
+ switch (dev->dev_blocked) {
+ case BST_UNMOUNTED:
+ bnet_fsend(dir, _("3931 Device %s is BLOCKED. user unmounted.\n"),
+ dev->print_name());
+ break;
+ case BST_UNMOUNTED_WAITING_FOR_SYSOP:
+ bnet_fsend(dir, _("3932 Device %s is BLOCKED. user unmounted during wait for media/mount.\n"),
+ dev->print_name());
+ break;
+ case BST_WAITING_FOR_SYSOP:
+ bnet_fsend(dir, _("3933 Device %s is BLOCKED waiting for media.\n"),
+ dev->print_name());
+ break;
+ case BST_DOING_ACQUIRE:
+ bnet_fsend(dir, _("3934 Device %s is being initialized.\n"),
+ dev->print_name());
+ break;
+ case BST_WRITING_LABEL:
+ bnet_fsend(dir, _("3935 Device %s is blocked labeling a Volume.\n"),
+ dev->print_name());
+ break;
+ default:
+ bnet_fsend(dir, _("3935 Device %s is blocked for unknown reason.\n"),
+ dev->print_name());
+ break;
+ }
+ } else if (dev->can_read()) {
+ bnet_fsend(dir, _("3936 Device %s is busy reading.\n"),
dev->print_name());;
} else {
- bnet_fsend(dir, _("3912 Device %s is busy with %d writer(s).\n"),
+ bnet_fsend(dir, _("3937 Device %s is busy with %d writer(s).\n"),
dev->print_name(), dev->num_writers);
}
}
return 1;
} else {
/* Changing pool, unload old tape if any in drive */
- Dmsg0(200, "got dev: num_writers=0, reserved, pool change\n");
+ Dmsg0(200, "got dev: num_writers=0, not reserved, pool change, unload changer\n");
unload_autochanger(dcr, 0);
}
}
memset(sb, 0, sizeof(*sb));
- if (g_platform_id == VER_PLATFORM_WIN32_WINDOWS) {
- return stat2(file, sb);
- }
-
- // otherwise we're on NT
-#if 0
- WCHAR buf[32767];
- buf[0] = '\\';
- buf[1] = '\\';
- buf[2] = '?';
- buf[3] = '\\';
-
- wchar_win32_path(file, buf+4);
-
- if (!GetFileAttributesExW((WCHAR *)buf, GetFileExInfoStandard, &data)) {
- return stat2(file, sb);
- }
-#else
+ /* why not allow win 95 to use p_GetFileAttributesExA ?
+ * this function allows _some_ open files to be stat'ed
+ * if (g_platform_id == VER_PLATFORM_WIN32_WINDOWS) {
+ * return stat2(file, sb);
+ * }
+ */
if (p_GetFileAttributesExW) {
/* dynamically allocate enough space for UCS2 filename */
return stat2(file, sb);
}
-#endif
-
sb->st_mode = 0777; /* start with everything */
if (data.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
sb->st_mode &= ~(S_IRUSR|S_IRGRP|S_IROTH);