- Release Notes for Bacula 1.37.3
+ Release Notes for Bacula 1.37.6
- Bacula code: Total files = 411 Total lines = 122,189 (*.h *.c *.in)
+ Bacula code: Total files = 414 Total lines = 123,723 (*.h *.c *.in)
Major Changes:
and regexfile. See below for details.
New Directives:
+- New Run directive in Job resource of DIR. It permits
+ cloning of jobs. To clone a copy of the current job, use
+ Run = "job-name level=%l since=\"%s\""
+ Note, job-name is normally the same name as the job that
+ is running but there is no restriction on what you put. If you
+ want to start the job by hand and use job overrides such as
+ storage=xxx, realize that the job will be started with the
+ default storage values not the overrides. The level=%l guarantees
+ that the chosen level of the job is the same, and the since=...
+ ensures that the job uses *exactly* the same time/date for incremental
+ and differential jobs. The since=... is ignored when level=Full.
+ A cloned job will not start additional clones, so it is not possible
+ to recurse.
- New Options keywords in a FileSet directive:
- WildDir xxx
Will do a wild card match against directories (files will not
return 1
====
-
/* Defined if Gtk+-2.4 or greater is present */
#undef HAVE_GTK_2_4
+
+/* Needed on HP-UX/g++ systems to support long long ints (int64) */
+#undef _INCLUDE_LONGLONG
+
/* Defined if Gtk+-2.4 or greater is present */
#undef HAVE_GTK_2_4
+/* Needed on HP-UX/g++ systems to support long long ints (int64) */
+#undef _INCLUDE_LONGLONG
+
+
/* Define to 1 if the `closedir' function returns void instead of `int'. */
#undef CLOSEDIR_VOID
AC_CHECK_FUNCS(chflags)
-AC_CHECK_FUNCS(snprintf vsnprintf gethostid getdomainname)
+AC_CHECK_FUNCS(snprintf vsnprintf gethostid)
+if test "$DISTNAME" = "hpux" ; then
+ echo "*** getdomainname check is disabled for hpux"
+else
+ AC_CHECK_FUNCS(getdomainname)
+fi
dnl# --------------------------------------------------------------------------
dnl# CHECKING FOR THREAD SAFE FUNCTIONS
DISTVER=`uname -r`
TAPEDRIVE="/dev/rmt/0hnb"
PTHREAD_LIB="-lpthread"
+ AC_DEFINE([_INCLUDE_LONGLONG])
;;
irix)
DISTVER=`uname -r`
+for ac_func in snprintf vsnprintf gethostid
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
-for ac_func in snprintf vsnprintf gethostid getdomainname
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+if test "$DISTNAME" = "hpux" ; then
+ echo "*** getdomainname check is disabled for hpux"
+else
+
+for ac_func in getdomainname
do
as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
echo "$as_me:$LINENO: checking for $ac_func" >&5
fi
done
+fi
DISTVER=`uname -r`
TAPEDRIVE="/dev/rmt/0hnb"
PTHREAD_LIB="-lpthread"
+ cat >>confdefs.h <<\_ACEOF
+#define _INCLUDE_LONGLONG 1
+_ACEOF
+
;;
irix)
DISTVER=`uname -r`
The defined Storage resources are:
- Copy Changer Device and Changer Command from Autochanger
to Device resource in SD if none given in Device resource.
-- Doc the following
- to activate, check or disable the hardware compression feature on my
- exb-8900 i use the exabyte "MammothTool" you can get it here:
- http://www.exabyte.com/support/online/downloads/index.cfm
- There is a solaris version of this tool. With option -C 0 or 1 you can
- disable or activate compression. Start this tool without any options for
- a small reference.
- 3.Prevent two drives requesting the same Volume in any given
autochanger.
- 4. Use Changer Device and Changer Command specified in the
For 1.37:
+- By the way: on page http://www.bacula.org/?page=tapedrives , at the
+ bottom, the link to "Tape Testing Chapter" is broken. It goes to
+ /html-manual/... while the others point to /rel-manual/...
+- OS linux 2.4
+ 1) ADIC, DLT, FastStor 4000, 7*20GB
+ 2) Sun, DDS, (Suns name unknown - Archive Python DDS drive), 1.2GB
+ 3) Wangtek, QIC, 6525ES, 525MB (fixed block size 1k, block size etc.
+ driver dependent - aic7xxx works, ncr53c8xx with problems)
+ 4) HP, DDS-2, C1553A, 6*4GB
+- Doc the following
+ to activate, check or disable the hardware compression feature on my
+ exb-8900 i use the exabyte "MammothTool" you can get it here:
+ http://www.exabyte.com/support/online/downloads/index.cfm
+ There is a solaris version of this tool. With option -C 0 or 1 you can
+ disable or activate compression. Start this tool without any options for
+ a small reference.
- Linux Sony LIB-D81, AIT-3 library works.
- Device resource needs the "name" of the SD.
- Add and option to see if the file size changed
#ifdef HAVE_AIX_OS
#endif
+/* HP-UX 11 specific workarounds */
+
+#ifdef HAVE_HPUX_OS
+# undef h_errno
+extern int h_errno;
+/* the {get,set}domainname() functions exist in HPUX's libc.
+ * the configure script detects that correctly.
+ * the problem is no system headers declares the prototypes for these functions
+ * this is done below
+ */
+extern "C" int getdomainname(char *name, int namelen);
+extern "C" int setdomainname(char *name, int namelen);
+#define uLong unsigned long
+#endif /* HAVE_HPUX_OS */
+
+
#ifdef HAVE_OSF1_OS
#undef HAVE_CHFLAGS /* chflags is incorrectly detected */
extern "C" int fchdir(int filedes);
#include <stdlib.h>
#endif
#if HAVE_UNISTD_H
+# ifdef HAVE_HPUX_OS
+# undef _INCLUDE_POSIX1C_SOURCE
+# endif
#include <unistd.h>
#endif
#if HAVE_ALLOCA_H
jcr->PoolId = pr.PoolId; /****FIXME**** this can go away */
jcr->jr.PoolId = pr.PoolId;
- jcr->since[0] = 0;
-
if (!get_or_create_fileset_record(jcr, &fsr)) {
return false;
}
get_level_since_time(jcr, jcr->since, sizeof(jcr->since));
+ Dmsg2(900, "cloned=%d run_cmds=%p\n", jcr->cloned, jcr->job->run_cmds);
+ if (!jcr->cloned && jcr->job->run_cmds) {
+ char *runcmd;
+ JOB *job = jcr->job;
+ POOLMEM *cmd = get_pool_memory(PM_FNAME);
+ UAContext *ua = new_ua_context(jcr);
+ ua->batch = true;
+ foreach_alist(runcmd, job->run_cmds) {
+ cmd = edit_job_codes(jcr, cmd, runcmd, "");
+ Mmsg(ua->cmd, "run %s cloned=yes", cmd);
+ Dmsg1(900, "=============== Clone cmd=%s\n", ua->cmd);
+ parse_ua_args(ua); /* parse command */
+ int stat = run_cmd(ua, ua->cmd);
+ if (stat == 0) {
+ Jmsg(jcr, M_ERROR, 0, _("Could not start clone job.\n"));
+ } else {
+ Jmsg(jcr, M_INFO, 0, _("Clone JobId %d started.\n"), stat);
+ }
+ }
+ free_ua_context(ua);
+ free_pool_memory(cmd);
+ }
+
return true;
}
*/
/* Requests from the Storage daemon */
-static char Find_media[] = "CatReq Job=%127s FindMedia=%d\n";
+static char Find_media[] = "CatReq Job=%127s FindMedia=%d PoolId=%lld\n";
static char Get_Vol_Info[] = "CatReq Job=%127s GetVolInfo VolName=%127s write=%d\n";
static char Update_media[] = "CatReq Job=%127s UpdateMedia VolName=%s"
free_memory(omsg);
return;
}
- if (sscanf(bs->msg, Find_media, &Job, &index) == 2) {
+ /*
+ * Find next appendable medium for SD
+ */
+ if (sscanf(bs->msg, Find_media, &Job, &index, &mr.PoolId) == 3) {
ok = find_next_volume_for_append(jcr, &mr, true /*permit create new vol*/);
/*
* Send Find Media response to Storage daemon
{"fileset", store_res, ITEM(res_job.fileset), R_FILESET, ITEM_REQUIRED, 0},
{"schedule", store_res, ITEM(res_job.schedule), R_SCHEDULE, 0, 0},
{"verifyjob", store_res, ITEM(res_job.verify_job), R_JOB, 0, 0},
- {"jobdefs", store_res, ITEM(res_job.jobdefs), R_JOBDEFS, 0, 0},
+ {"jobdefs", store_res, ITEM(res_job.jobdefs), R_JOBDEFS, 0, 0},
+ {"run", store_alist_str, ITEM(res_job.run_cmds), 0, 0, 0},
{"where", store_dir, ITEM(res_job.RestoreWhere), 0, 0, 0},
{"bootstrap",store_dir, ITEM(res_job.RestoreBootstrap), 0, 0, 0},
{"writebootstrap",store_dir, ITEM(res_job.WriteBootstrap), 0, 0, 0},
static char level_no[30];
const char *str = level_no;
- bsnprintf(level_no, sizeof(level_no), "%d", level); /* default if not found */
+ bsnprintf(level_no, sizeof(level_no), "%c (%d)", level, level); /* default if not found */
for (i=0; joblevels[i].level_name; i++) {
if (level == joblevels[i].level) {
str = joblevels[i].level_name;
break;
case R_DEVICE:
dev = &res->res_dev;
- sendit(sock, "Device: name=%s ok=%d num_writers=%d num_waiting=%d\n"
-" use_cnt=%d open=%d append=%d read=%d labeled=%d offline=%d autochgr=%d\n"
-" volname=%s MediaType=%s\n",
- dev->hdr.name, dev->found, dev->num_writers, dev->num_waiting,
- dev->use_count, dev->open, dev->append, dev->read, dev->labeled,
+ char ed1[50];
+ sendit(sock, "Device: name=%s ok=%d num_writers=%d max_writers=%d\n"
+" reserved=%d open=%d append=%d read=%d labeled=%d offline=%d autochgr=%d\n"
+" poolid=%s volname=%s MediaType=%s\n",
+ dev->hdr.name, dev->found, dev->num_writers, dev->max_writers,
+ dev->reserved, dev->open, dev->append, dev->read, dev->labeled,
dev->offline, dev->autochanger,
+ edit_uint64(dev->PoolId, ed1),
dev->VolumeName, dev->MediaType);
break;
case R_STORAGE:
sendit(sock, " --> ");
dump_resource(-type, (RES *)res->res_job.verify_job, sendit, sock);
}
- break;
+ if (res->res_job.run_cmds) {
+ char *runcmd;
+ foreach_alist(runcmd, res->res_job.run_cmds) {
+ sendit(sock, " --> Run=%s\n", runcmd);
+ }
+ }
if (res->res_job.messages) {
sendit(sock, " --> ");
dump_resource(-R_MSGS, (RES *)res->res_job.messages, sendit, sock);
if (res->res_job.ClientRunAfterJob) {
free(res->res_job.ClientRunAfterJob);
}
+ if (res->res_job.run_cmds) {
+ delete res->res_job.run_cmds;
+ }
if (res->res_job.storage) {
delete res->res_job.storage;
}
res->res_job.dif_pool = res_all.res_job.dif_pool;
res->res_job.verify_job = res_all.res_job.verify_job;
res->res_job.jobdefs = res_all.res_job.jobdefs;
+ res->res_job.run_cmds = res_all.res_job.run_cmds;
break;
case R_COUNTER:
if ((res = (URES *)GetResWithName(R_COUNTER, res_all.res_counter.hdr.name)) == NULL) {
bool found; /* found with SD */
int num_writers;
- int num_waiting;
- int use_count;
+ int max_writers; /* = 1 for files */
+ int reserved; /* number of reserves */
bool open;
bool append; /* in append mode */
bool read;
bool autochanger;
bool offline;
bool autoselect;
+ uint32_t PoolId;
char ChangerName[MAX_NAME_LENGTH];
char VolumeName[MAX_NAME_LENGTH];
char MediaType[MAX_NAME_LENGTH];
POOL *dif_pool; /* Pool for Differental backups */
JOB *verify_job; /* Job name to verify */
JOB *jobdefs; /* Job defaults */
+ alist *run_cmds; /* Run commands */
uint32_t NumConcurrentJobs; /* number of concurrent jobs running */
};
void get_level_since_time(JCR *jcr, char *since, int since_len)
{
int JobLevel;
- /* Lookup the last FULL backup job to get the time/date for a
- * differential or incremental save.
- */
+
+ since[0] = 0;
+ if (jcr->cloned) {
+ if ( jcr->stime && jcr->stime[0]) {
+ bstrncpy(since, ", since=", since_len);
+ bstrncat(since, jcr->stime, since_len);
+ }
+ return;
+ }
if (!jcr->stime) {
jcr->stime = get_pool_memory(PM_MESSAGE);
- }
+ }
jcr->stime[0] = 0;
- since[0] = 0;
+ /* Lookup the last FULL backup job to get the time/date for a
+ * differential or incremental save.
+ */
switch (jcr->JobLevel) {
case L_DIFFERENTIAL:
case L_INCREMENTAL:
"type=%d level=%d FileSet=%s NoAttr=%d SpoolAttr=%d FileSetMD5=%s "
"SpoolData=%d WritePartAfterJob=%d";
static char use_device[] = "use device=%s media_type=%s pool_name=%s "
- "pool_type=%s append=%d\n";
+ "pool_type=%s PoolId=%s append=%d\n";
static char query_device[] = "query device=%s";
/* Response from Storage daemon */
static char OKjob[] = "3000 OK Job SDid=%d SDtime=%d Authorization=%100s\n";
static char OK_device[] = "3000 OK use device device=%s\n";
-static char OK_query[] = "3001 OK query append=%d read=%d num_writers=%d "
- "num_waiting=%d open=%d use_count=%d labeled=%d offline=%d "
+static char OK_query[] = "3001 OK query "
+ "append=%d read=%d num_writers=%d "
+ "open=%d labeled=%d offline=%d "
+ "reserved=%d max_writers=%d "
"autoselect=%d autochanger=%d "
+ "poolid=%lld "
"changer_name=%127s media_type=%127s volume_name=%127s";
/* Storage Daemon requests */
/*
* Open message channel with the Storage daemon
*/
- Dmsg2(200, "bnet_connect to Storage daemon %s:%d\n", store->address,
+ Dmsg2(100, "bnet_connect to Storage daemon %s:%d\n", store->address,
store->SDport);
sd = bnet_connect(jcr, retry_interval, max_retry_time,
_("Storage daemon"), store->address,
pm_strcpy(device_name, dev->hdr.name);
bash_spaces(device_name);
bnet_fsend(sd, query_device, device_name.c_str());
+ Dmsg1(100, ">stored: %s\n", sd->msg);
if (bget_dirmsg(sd) > 0) {
- Dmsg1(400, "<stored: %s", sd->msg);
- if (sscanf(sd->msg, OK_query, &dev_append, &dev_read,
- &dev->num_writers, &dev->num_waiting, &dev_open,
- &dev->use_count, &dev_labeled, &dev_offline, &dev_autoselect,
- &dev_autochanger, changer_name.c_str(), media_type.c_str(),
- volume_name.c_str()) != 13) {
+ Dmsg1(100, "<stored: %s", sd->msg);
+ if (sscanf(sd->msg, OK_query,
+ &dev_append, &dev_read,
+ &dev->num_writers, &dev_open,
+ &dev_labeled, &dev_offline, &dev->reserved,
+ &dev->max_writers, &dev_autoselect,
+ &dev_autochanger, &dev->PoolId,
+ changer_name.c_str(), media_type.c_str(),
+ volume_name.c_str()) != 14) {
return false;
}
unbash_spaces(changer_name);
bstrncpy(dev->ChangerName, changer_name.c_str(), sizeof(dev->ChangerName));
bstrncpy(dev->MediaType, media_type.c_str(), sizeof(dev->MediaType));
bstrncpy(dev->VolumeName, volume_name.c_str(), sizeof(dev->VolumeName));
+ /* Note, these are copied because they are boolean rather than
+ * integer.
+ */
dev->open = dev_open;
dev->append = dev_append;
dev->read = dev_read;
BSOCK *sd;
char auth_key[100];
POOL_MEM device_name, pool_name, pool_type, media_type;
+ char PoolId[50];
sd = jcr->store_bsock;
/*
jcr->client->hdr.name, jcr->JobType, jcr->JobLevel,
jcr->fileset->hdr.name, !jcr->pool->catalog_files,
jcr->job->SpoolAttributes, jcr->fileset->MD5, jcr->spool_data, jcr->write_part_after_job);
- Dmsg1(200, "Jobcmd=%s\n", sd->msg);
+ Dmsg1(100, ">stored: %s\n", sd->msg);
unbash_spaces(jcr->job->hdr.name);
unbash_spaces(jcr->client->hdr.name);
unbash_spaces(jcr->fileset->hdr.name);
if (bget_dirmsg(sd) > 0) {
- Dmsg1(110, "<stored: %s", sd->msg);
+ Dmsg1(100, "<stored: %s", sd->msg);
if (sscanf(sd->msg, OKjob, &jcr->VolSessionId,
&jcr->VolSessionTime, &auth_key) != 3) {
Dmsg1(100, "BadJob=%s\n", sd->msg);
pm_strcpy(pool_name, jcr->pool->hdr.name);
bash_spaces(pool_type);
bash_spaces(pool_name);
+ edit_int64(jcr->PoolId, PoolId);
/*
* We have two loops here. The first comes from the
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);
+ PoolId, append);
+ Dmsg1(100, ">stored: %s", sd->msg);
if (bget_dirmsg(sd) > 0) {
- Dmsg1(400, "<stored: %s", sd->msg);
+ Dmsg1(100, "<stored: %s", sd->msg);
/* ****FIXME**** save actual device name */
ok = sscanf(sd->msg, OK_device, device_name.c_str()) == 1;
if (ok) {
// }
if (ok) {
ok = bnet_fsend(sd, "run");
+ Dmsg1(100, ">stored: %s\n", sd->msg);
}
return ok;
}
/*
* Items needed:
- * jcr->PoolId
+ * mr.PoolId must be set
* jcr->store
* jcr->db
* jcr->pool
bool InChanger;
STORE *store = jcr->store;
- mr->PoolId = jcr->PoolId;
bstrncpy(mr->MediaType, store->media_type, sizeof(mr->MediaType));
- Dmsg2(120, "CatReq FindMedia: Id=%d, MediaType=%s\n", mr->PoolId, mr->MediaType);
+ Dmsg2(100, "CatReq FindMedia: Id=%d, MediaType=%s\n", (int)mr->PoolId, mr->MediaType);
/*
* If we are using an Autochanger, restrict Volume
* search to the Autochanger on the first pass
MEDIA_DBR mr;
memset(&mr, 0, sizeof(mr));
+ mr.PoolId = jcr->PoolId;
int i = find_arg_with_value(ua, "job");
if (i <= 0) {
if ((job = select_job_resource(ua)) == NULL) {
char *where, *fileset_name, *client_name, *bootstrap;
const char *replace;
char *when, *verify_job_name, *catalog_name;
+ char *since = NULL;
+ bool cloned = false;
int Priority = 0;
int i, j, opt, files = 0;
bool kw_ok;
FILESET *fileset = NULL;
POOL *pool = NULL;
static const char *kw[] = { /* command line arguments */
- N_("job"), /* Used in a switch() */
- N_("jobid"), /* 1 */
- N_("client"), /* 2 */
- N_("fd"),
- N_("fileset"), /* 4 */
- N_("level"), /* 5 */
- N_("storage"), /* 6 */
- N_("sd"), /* 7 */
- N_("pool"), /* 8 */
- N_("where"), /* 9 */
- N_("bootstrap"), /* 10 */
- N_("replace"), /* 11 */
- N_("when"), /* 12 */
- N_("priority"), /* 13 */
- N_("yes"), /* 14 -- if you change this change YES_POS too */
- N_("verifyjob"), /* 15 */
- N_("files"), /* 16 number of files to restore */
- N_("catalog"), /* 17 override catalog */
+ "job", /* Used in a switch() */
+ "jobid", /* 1 */
+ "client", /* 2 */
+ "fd",
+ "fileset", /* 4 */
+ "level", /* 5 */
+ "storage", /* 6 */
+ "sd", /* 7 */
+ "pool", /* 8 */
+ "where", /* 9 */
+ "bootstrap", /* 10 */
+ "replace", /* 11 */
+ "when", /* 12 */
+ "priority", /* 13 */
+ "yes", /* 14 -- if you change this change YES_POS too */
+ "verifyjob", /* 15 */
+ "files", /* 16 number of files to restore */
+ "catalog", /* 17 override catalog */
+ "since", /* 18 since */
+ "cloned", /* 19 cloned */
NULL};
#define YES_POS 14
kw_ok = true;
break;
+ case 18: /* since */
+ since = ua->argv[i];
+ kw_ok = true;
+ break;
+
+ case 19: /* cloned */
+ cloned = true;
+ kw_ok = true;
+ break;
+
default:
break;
}
jcr->JobPriority = Priority;
}
+ if (since) {
+ if (!jcr->stime) {
+ jcr->stime = get_pool_memory(PM_MESSAGE);
+ }
+ pm_strcpy(jcr->stime, since);
+ }
+
+ jcr->cloned = cloned;
+
if (find_arg(ua, _("fdcalled")) > 0) {
jcr->file_bsock = dup_bsock(ua->UA_sock);
ua->quit = true;
*/
/*
- 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
do_all_status(ua);
return 1;
} else if (strcasecmp(ua->argk[i], _("dir")) == 0 ||
- strcasecmp(ua->argk[i], _("director")) == 0) {
+ strcasecmp(ua->argk[i], _("director")) == 0) {
do_director_status(ua);
return 1;
} else if (strcasecmp(ua->argk[i], _("client")) == 0) {
}
if (!found) {
unique_store[i++] = store;
- Dmsg2(40, "Stuffing: %s:%d\n", store->address, store->SDport);
+ Dmsg2(40, "Stuffing: %s:%d\n", store->address, store->SDport);
}
}
UnlockRes();
}
if (!found) {
unique_client[i++] = client;
- Dmsg2(40, "Stuffing: %s:%d\n", client->address, client->FDport);
+ Dmsg2(40, "Stuffing: %s:%d\n", client->address, client->FDport);
}
}
UnlockRes();
HOST_OS, DISTNAME, DISTVER);
bstrftime_nc(dt, sizeof(dt), daemon_start_time);
bsendmsg(ua, _("Daemon started %s, %d Job%s run since started.\n"),
- dt, num_jobs_run, num_jobs_run == 1 ? "" : "s");
+ dt, num_jobs_run, num_jobs_run == 1 ? "" : "s");
if (debug_level > 0) {
char b1[35], b2[35], b3[35], b4[35];
bsendmsg(ua, _(" Heap: bytes=%s max_bytes=%s bufs=%s max_bufs=%s\n"),
JCR *jcr = ua->jcr;
MEDIA_DBR mr;
memset(&mr, 0, sizeof(mr));
+ mr.PoolId = jcr->PoolId;
if (sp->job->JobType == JT_BACKUP) {
jcr->db = NULL;
ok = complete_jcr_for_job(jcr, sp->job, sp->pool);
ok = find_next_volume_for_append(jcr, &mr, 0);
}
if (!ok) {
- bstrncpy(mr.VolumeName, "*unknown*", sizeof(mr.VolumeName));
+ bstrncpy(mr.VolumeName, "*unknown*", sizeof(mr.VolumeName));
}
}
bstrftime_nc(dt, sizeof(dt), sp->runtime);
*/
if (jcr->JobType == JT_CONSOLE) {
bstrftime_nc(dt, sizeof(dt), jcr->start_time);
- bsendmsg(ua, _("Console connected at %s\n"), dt);
+ bsendmsg(ua, _("Console connected at %s\n"), dt);
}
njobs--;
}
njobs++;
switch (jcr->JobStatus) {
case JS_Created:
- msg = _("is waiting execution");
+ msg = _("is waiting execution");
break;
case JS_Running:
- msg = _("is running");
+ msg = _("is running");
break;
case JS_Blocked:
- msg = _("is blocked");
+ msg = _("is blocked");
break;
case JS_Terminated:
- msg = _("has terminated");
+ msg = _("has terminated");
break;
case JS_ErrorTerminated:
- msg = _("has erred");
+ msg = _("has erred");
break;
case JS_Error:
- msg = _("has errors");
+ msg = _("has errors");
break;
case JS_FatalError:
- msg = _("has a fatal error");
+ msg = _("has a fatal error");
break;
case JS_Differences:
- msg = _("has verify differences");
+ msg = _("has verify differences");
break;
case JS_Canceled:
- msg = _("has been canceled");
+ msg = _("has been canceled");
break;
case JS_WaitFD:
emsg = (char *) get_pool_memory(PM_FNAME);
- Mmsg(emsg, _("is waiting on Client %s"), jcr->client->hdr.name);
+ Mmsg(emsg, _("is waiting on Client %s"), jcr->client->hdr.name);
pool_mem = true;
msg = emsg;
break;
case JS_WaitSD:
emsg = (char *) get_pool_memory(PM_FNAME);
- Mmsg(emsg, _("is waiting on Storage %s"), jcr->store->hdr.name);
+ Mmsg(emsg, _("is waiting on Storage %s"), jcr->store->hdr.name);
pool_mem = true;
msg = emsg;
break;
case JS_WaitStoreRes:
- msg = _("is waiting on max Storage jobs");
+ msg = _("is waiting on max Storage jobs");
break;
case JS_WaitClientRes:
- msg = _("is waiting on max Client jobs");
+ msg = _("is waiting on max Client jobs");
break;
case JS_WaitJobRes:
- msg = _("is waiting on max Job jobs");
+ msg = _("is waiting on max Job jobs");
break;
case JS_WaitMaxJobs:
- msg = _("is waiting on max total jobs");
+ msg = _("is waiting on max total jobs");
break;
case JS_WaitStartTime:
- msg = _("is waiting for its start time");
+ msg = _("is waiting for its start time");
break;
case JS_WaitPriority:
- msg = _("is waiting for higher priority jobs to finish");
+ msg = _("is waiting for higher priority jobs to finish");
break;
default:
emsg = (char *) get_pool_memory(PM_FNAME);
- Mmsg(emsg, _("is in unknown state %c"), jcr->JobStatus);
+ Mmsg(emsg, _("is in unknown state %c"), jcr->JobStatus);
pool_mem = true;
msg = emsg;
break;
free_pool_memory(emsg);
pool_mem = false;
}
- msg = _("is waiting for a mount request");
+ msg = _("is waiting for a mount request");
break;
case JS_WaitMedia:
if (pool_mem) {
free_pool_memory(emsg);
pool_mem = false;
}
- msg = _("is waiting for an appendable Volume");
+ msg = _("is waiting for an appendable Volume");
break;
case JS_WaitFD:
if (!pool_mem) {
emsg = (char *) get_pool_memory(PM_FNAME);
pool_mem = true;
}
- Mmsg(emsg, _("is waiting for Client %s to connect to Storage %s"),
+ Mmsg(emsg, _("is waiting for Client %s to connect to Storage %s"),
jcr->client->hdr.name, jcr->store->hdr.name);
msg = emsg;
break;
switch (jcr->JobType) {
case JT_ADMIN:
case JT_RESTORE:
- bstrncpy(level, " ", sizeof(level));
+ bstrncpy(level, " ", sizeof(level));
break;
default:
bstrncpy(level, level_to_str(jcr->JobLevel), sizeof(level));
/* There are three periods after the Job name */
char *p;
for (int i=0; i<3; i++) {
- if ((p=strrchr(JobName, '.')) != NULL) {
+ if ((p=strrchr(JobName, '.')) != NULL) {
*p = 0;
}
}
switch (je->JobType) {
case JT_ADMIN:
case JT_RESTORE:
- bstrncpy(level, " ", sizeof(level));
+ bstrncpy(level, " ", sizeof(level));
break;
default:
bstrncpy(level, level_to_str(je->JobLevel), sizeof(level));
}
switch (je->JobStatus) {
case JS_Created:
- termstat = "Created";
+ termstat = "Created";
break;
case JS_FatalError:
case JS_ErrorTerminated:
- termstat = "Error";
+ termstat = "Error";
break;
case JS_Differences:
- termstat = "Diffs";
+ termstat = "Diffs";
break;
case JS_Canceled:
- termstat = "Cancel";
+ termstat = "Cancel";
break;
case JS_Terminated:
- termstat = "OK";
+ termstat = "OK";
break;
default:
- termstat = "Other";
+ termstat = "Other";
break;
}
bsendmsg(ua, _("%6d %-6s %8s %14s %-7s %-8s %s\n"),
time_t end_time; /* job end time */
POOLMEM *client_name; /* client name */
POOLMEM *RestoreBootstrap; /* Bootstrap file to restore */
+ POOLMEM *stime; /* start time for incremental/differential */
char *sd_auth_key; /* SD auth key */
MSGS *jcr_msgs; /* Copy of message resource -- actually used */
uint32_t ClientId; /* Client associated with Job */
FileId_t FileId; /* Last file id inserted */
uint32_t FileIndex; /* Last FileIndex processed */
POOLMEM *fname; /* name to put into catalog */
- POOLMEM *stime; /* start time for incremental/differential */
JOB_DBR jr; /* Job DB record for current job */
JOB_DBR target_jr; /* target job */
char FSCreateTime[MAX_TIME_LENGTH]; /* FileSet CreateTime as returned from DB */
bool fn_printed; /* printed filename */
bool write_part_after_job; /* Write part after job in SD */
bool needs_sd; /* set if SD needed by Job */
+ bool cloned; /* set if cloned */
#endif /* DIRECTOR_DAEMON */
}
+/*
+ * Store a string in an alist.
+ */
+void store_alist_str(LEX *lc, RES_ITEM *item, int index, int pass)
+{
+ alist *list;
+
+ if (pass == 2) {
+ if (*(item->value) == NULL) {
+ list = New(alist(10, owned_by_alist));
+ } else {
+ list = (alist *)(*(item->value));
+ }
+
+ lex_get_token(lc, T_STRING); /* scan next item */
+ Dmsg4(900, "Append %s to alist %p size=%d %s\n",
+ lc->str, list, list->size(), item->name);
+ list->append(bstrdup(lc->str));
+ *(item->value) = (char *)list;
+ }
+ scan_to_eol(lc);
+ set_bit(index, res_all.hdr.item_present);
+}
+
+
+
/*
* Store default values for Resource from xxxDefs
* If we are in pass 2, do a lookup of the
* Version $Id$
*/
/*
- Copyright (C) 2000, 2001, 2002 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
void store_strname(LEX *lc, RES_ITEM *item, int index, int pass);
void store_res(LEX *lc, RES_ITEM *item, int index, int pass);
void store_alist_res(LEX *lc, RES_ITEM *item, int index, int pass);
+void store_alist_str(LEX *lc, RES_ITEM *item, int index, int pass);
void store_int(LEX *lc, RES_ITEM *item, int index, int pass);
void store_pint(LEX *lc, RES_ITEM *item, int index, int pass);
void store_msgs(LEX *lc, RES_ITEM *item, int index, int pass);
{
while (*str) {
if (*str == 0x1)
- *str = ' ';
+ *str = ' ';
str++;
}
}
char *str = pm.c_str();
while (*str) {
if (*str == 0x1)
- *str = ' ';
+ *str = ' ';
str++;
}
}
if (JobStatus == 0) {
buf[0] = 0;
} else {
- bsnprintf(buf, sizeof(buf), _("Unknown Job termination status=%d"), JobStatus);
+ bsnprintf(buf, sizeof(buf), _("Unknown Job termination status=%d"), JobStatus);
}
jobstat = buf;
break;
char *cp = buf;
*cp++ = S_ISDIR(mode) ? 'd' : S_ISBLK(mode) ? 'b' : S_ISCHR(mode) ? 'c' :
- S_ISLNK(mode) ? 'l' : S_ISFIFO(mode) ? 'f' : S_ISSOCK(mode) ? 's' : '-';
+ S_ISLNK(mode) ? 'l' : S_ISFIFO(mode) ? 'f' : S_ISSOCK(mode) ? 's' : '-';
*cp++ = mode & S_IRUSR ? 'r' : '-';
*cp++ = mode & S_IWUSR ? 'w' : '-';
*cp++ = (mode & S_ISUID
- ? (mode & S_IXUSR ? 's' : 'S')
- : (mode & S_IXUSR ? 'x' : '-'));
+ ? (mode & S_IXUSR ? 's' : 'S')
+ : (mode & S_IXUSR ? 'x' : '-'));
*cp++ = mode & S_IRGRP ? 'r' : '-';
*cp++ = mode & S_IWGRP ? 'w' : '-';
*cp++ = (mode & S_ISGID
- ? (mode & S_IXGRP ? 's' : 'S')
- : (mode & S_IXGRP ? 'x' : '-'));
+ ? (mode & S_IXGRP ? 's' : 'S')
+ : (mode & S_IXGRP ? 'x' : '-'));
*cp++ = mode & S_IROTH ? 'r' : '-';
*cp++ = mode & S_IWOTH ? 'w' : '-';
*cp++ = (mode & S_ISVTX
- ? (mode & S_IXOTH ? 't' : 'T')
- : (mode & S_IXOTH ? 'x' : '-'));
+ ? (mode & S_IXOTH ? 't' : 'T')
+ : (mode & S_IXOTH ? 'x' : '-'));
*cp = '\0';
return cp;
}
cmd = get_pool_memory(PM_FNAME);
/* look for shell */
if ((shellcmd = getenv("SHELL")) == NULL) {
- shellcmd = "/bin/sh";
+ shellcmd = "/bin/sh";
}
pm_strcpy(&cmd, shellcmd);
pm_strcat(&cmd, " -c \"echo ");
fgets(line, sizeof(line), bpipe->rfd);
strip_trailing_junk(line);
stat = close_bpipe(bpipe);
- Dmsg2(400, "stat=%d got: %s\n", stat, line);
+ Dmsg2(400, "stat=%d got: %s\n", stat, line);
} else {
stat = 1; /* error */
}
/* The following creates a seed for the session key generator
based on a collection of volatile and environment-specific
information unlikely to be vulnerable (as a whole) to an
- exhaustive search attack. If one of these items isn't
+ exhaustive search attack. If one of these items isn't
available on your machine, replace it with something
equivalent or, if you like, just delete it. */
key[k++] = Rad16(rb & 0xF);
#undef Rad16
if (j & 1) {
- key[k++] = '-';
+ key[k++] = '-';
}
}
key[--k] = 0;
* %j = Unique Job name
* %l = job level
* %n = Unadorned Job name
+ * %s = Since time
* %t = Job type (Backup, ...)
* %r = Recipients
* %v = Volume name
for (p=imsg; *p; p++) {
if (*p == '%') {
switch (*++p) {
- case '%':
- str = "%";
+ case '%':
+ str = "%";
break;
- case 'c':
+ case 'c':
if (jcr) {
str = jcr->client_name;
} else {
- str = "*none*";
+ str = "*none*";
}
break;
- case 'd':
- str = my_name; /* Director's name */
+ case 'd':
+ str = my_name; /* Director's name */
break;
- case 'e':
+ case 'e':
if (jcr) {
str = job_status_to_str(jcr->JobStatus);
} else {
- str = "*none*";
+ str = "*none*";
}
break;
- case 'i':
+ case 'i':
if (jcr) {
- bsnprintf(add, sizeof(add), "%d", jcr->JobId);
+ bsnprintf(add, sizeof(add), "%d", jcr->JobId);
str = add;
} else {
- str = "*none*";
+ str = "*none*";
}
break;
- case 'j': /* Job name */
+ case 'j': /* Job name */
if (jcr) {
str = jcr->Job;
} else {
- str = "*none*";
+ str = "*none*";
}
break;
- case 'l':
+ case 'l':
if (jcr) {
str = job_level_to_str(jcr->JobLevel);
} else {
- str = "*none*";
+ str = "*none*";
}
break;
- case 'n':
+ case 'n':
if (jcr) {
bstrncpy(name, jcr->Job, sizeof(name));
/* There are three periods after the Job name */
for (i=0; i<3; i++) {
- if ((q=strrchr(name, '.')) != NULL) {
+ if ((q=strrchr(name, '.')) != NULL) {
*q = 0;
}
}
str = name;
} else {
- str = "*none*";
+ str = "*none*";
}
break;
- case 'r':
+ case 'r':
str = to;
break;
- case 't':
+ case 's': /* since time */
+ if (jcr && jcr->stime) {
+ str = jcr->stime;
+ } else {
+ str = "*none*";
+ }
+ break;
+ case 't':
if (jcr) {
str = job_type_to_str(jcr->JobType);
} else {
- str = "*none*";
+ str = "*none*";
}
break;
- case 'v':
+ case 'v':
if (jcr) {
if (jcr->VolumeName && jcr->VolumeName[0]) {
str = jcr->VolumeName;
} else {
- str = "";
+ str = "";
}
} else {
- str = "*none*";
+ str = "*none*";
}
break;
default:
- add[0] = '%';
+ add[0] = '%';
add[1] = *p;
add[2] = 0;
str = add;
* as it should be, then remove it. Also zap the jcr pointer
* to the dcr if it is the same one.
*/
+#ifdef needed
static void remove_dcr_from_dcrs(DCR *dcr)
{
JCR *jcr = dcr->jcr;
}
}
}
+#endif
/*
* Free up all aspects of the given dcr -- i.e. dechain it,
if (dev->is_busy()) {
Jmsg2(jcr, M_FATAL, 0, _("Device %s is busy. Job %d canceled.\n"),
- dev_name(dev), jcr->JobId);
+ dev->name(), jcr->JobId);
goto get_out;
}
if (!dcr) {
* the DIR to reserve multiple devices before *really*
* starting the job. It also permits the SD to refuse
* certain devices (not up, ...).
+ *
+ * Note, in reserving a device, if the device is for the
+ * same pool and the same pool type, then it is acceptable.
+ * The Media Type has already been checked. If we are
+ * the first tor reserve the device, we put the pool
+ * name and pool type in the device record.
*/
bool reserve_device_for_append(JCR *jcr, DEVICE *dev)
{
DCR *dcr = jcr->dcr;
- bool recycle;
bool ok = false;
ASSERT(dcr);
lock_device(dev);
block_device(dev, BST_DOING_ACQUIRE);
unlock_device(dev);
+ if (dev->can_read()) {
+ Jmsg(jcr, M_WARNING, 0, _("Device %s is busy reading.\n"), dev->name());
+ goto bail_out;
+ }
if (device_is_unmounted(dev)) {
Jmsg(jcr, M_WARNING, 0, _("device %s is BLOCKED due to user unmount.\n"),
dev_name(dev));
- goto get_out;
+ goto bail_out;
}
Dmsg1(190, "reserve_append device is %s\n", dev_is_tape(dev)?"tape":"disk");
- if (dev->can_append() || dev->num_writers > 0 || dev->reserved_device) {
- Dmsg0(190, "device already in append.\n");
- /*
- * Device already in append mode or reserved for write
- *
- * Check if we have the right Volume mounted
- * OK if current volume info OK
- * OK if next volume matches current volume
- */
- bstrncpy(dcr->VolumeName, dev->VolHdr.VolName, sizeof(dcr->VolumeName));
- if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE) &&
- !(dir_find_next_appendable_volume(dcr) &&
- strcmp(dev->VolHdr.VolName, dcr->VolumeName) == 0)) { /* wrong tape mounted */
- Dmsg0(190, "Wrong tape mounted.\n");
- if (dev->num_writers != 0 || dev->reserved_device) {
- Jmsg(jcr, M_FATAL, 0, _("Device %s is busy writing on another Volume.\n"), dev_name(dev));
- goto get_out;
+ /*
+ * First handle the case that the drive is not yet in append mode
+ */
+ if (!dev->can_append() && dev->num_writers == 0) {
+ /* Now check if there are any reservations on the drive */
+ if (dev->reserved_device) {
+ /* Yes, now check if we want the same Pool and pool type */
+ if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
+ strcmp(dev->pool_type, dcr->pool_type) == 0) {
+ /* OK, compatible device */
+ } else {
+ /* Drive not suitable for us */
+ Jmsg(jcr, M_WARNING, 0, _("Device %s is busy writing on another Volume.\n"), dev->name());
+ goto bail_out;
}
} else {
- /*
- * At this point, the correct tape is already mounted, so
- * we do not need to do mount_next_write_volume(), unless
- * we need to recycle the tape.
- */
- recycle = strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") == 0;
- Dmsg1(190, "Correct tape mounted. recycle=%d\n", recycle);
- if (recycle && dev->num_writers != 0) {
- Jmsg(jcr, M_FATAL, 0, _("Cannot recycle volume \"%s\""
- " because it is in use by another job.\n"));
- goto get_out;
- }
- if (dev->num_writers == 0) {
- memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
- }
- }
- } else {
- if (dev->can_read()) {
- Jmsg(jcr, M_FATAL, 0, _("Device %s is busy reading.\n"), dev_name(dev));
- goto get_out;
+ /* Device is available but not yet reserved, reserve it for us */
+ bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
+ bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
+ dev->PoolId = dcr->PoolId;
}
- ASSERT(dev->num_writers == 0);
+ goto do_reserve;
}
+ /*
+ * Now check if the device is in append mode
+ */
+ if (dev->can_append() || dev->num_writers > 0) {
+ Dmsg0(190, "device already in append.\n");
+ /* Yes, now check if we want the same Pool and pool type */
+ if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
+ strcmp(dev->pool_type, dcr->pool_type) == 0) {
+ /* OK, compatible device */
+ } else {
+ /* Drive not suitable for us */
+ Jmsg(jcr, M_WARNING, 0, _("Device %s is busy writing on another Volume.\n"), dev->name());
+ goto bail_out;
+ }
+ } else {
+ Pmsg0(000, "Logic error!!!! Should not get here.\n");
+ goto bail_out; /* should not get here */
+ }
+
+do_reserve:
dev->reserved_device++;
dcr->reserved_device = true;
ok = true;
-get_out:
+bail_out:
P(dev->mutex);
unblock_device(dev);
V(dev->mutex);
dev->reserved_device--;
dcr->reserved_device = false;
}
+
+ /*
+ * With the reservation system, this should not happen
+ */
+ if (dev->can_read()) {
+ Jmsg(jcr, M_FATAL, 0, _("Device %s is busy reading.\n"), dev_name(dev));
+ goto get_out;
+ }
+
if (dev->can_append()) {
Dmsg0(190, "device already in append.\n");
/*
} else {
/* Not already in append mode, so mount the device */
Dmsg0(190, "Not in append mode, try mount.\n");
- if (dev->can_read()) {
- Jmsg(jcr, M_FATAL, 0, _("Device %s is busy reading.\n"), dev_name(dev));
- goto get_out;
- }
ASSERT(dev->num_writers == 0);
do_mount = true;
}
#include "stored.h" /* pull in Storage Deamon headers */
/* Requests sent to the Director */
-static char Find_media[] = "CatReq Job=%s FindMedia=%d\n";
+static char Find_media[] = "CatReq Job=%s FindMedia=%d PoolId=%s\n";
static char Get_Vol_Info[] = "CatReq Job=%s GetVolInfo VolName=%s write=%d\n";
static char Update_media[] = "CatReq Job=%s UpdateMedia VolName=%s"
" VolJobs=%u VolFiles=%u VolBlocks=%u VolBytes=%s VolMounts=%u"
return false;
}
memset(&vol, 0, sizeof(vol));
- Dmsg1(300, "Get vol info=%s", dir->msg);
+ Dmsg1(100, "<dird %s", dir->msg);
n = sscanf(dir->msg, OK_media, vol.VolCatName,
&vol.VolCatJobs, &vol.VolCatFiles,
&vol.VolCatBlocks, &vol.VolCatBytes,
BSOCK *dir = jcr->dir_bsock;
bstrncpy(dcr->VolCatInfo.VolCatName, dcr->VolumeName, sizeof(dcr->VolCatInfo.VolCatName));
- Dmsg1(300, "dir_get_volume_info=%s\n", dcr->VolCatInfo.VolCatName);
bash_spaces(dcr->VolCatInfo.VolCatName);
bnet_fsend(dir, Get_Vol_Info, jcr->Job, dcr->VolCatInfo.VolCatName,
writing==GET_VOL_INFO_FOR_WRITE?1:0);
+ Dmsg1(100, ">dird: %s", dir->msg);
return do_get_volume_info(dcr);
}
{
JCR *jcr = dcr->jcr;
BSOCK *dir = jcr->dir_bsock;
+ char ed1[50];
JCR *njcr;
Dmsg0(200, "dir_find_next_appendable_volume\n");
* drive, so we continue looking for a not in use Volume.
*/
for (int vol_index=1; vol_index < 3; vol_index++) {
- bnet_fsend(dir, Find_media, jcr->Job, vol_index);
+ bnet_fsend(dir, Find_media, jcr->Job, vol_index, edit_int64(dcr->PoolId, ed1));
+ Dmsg1(100, ">dird: %s", dir->msg);
if (do_get_volume_info(dcr)) {
Dmsg2(300, "JobId=%d got possible Vol=%s\n", jcr->JobId, dcr->VolumeName);
bool found = false;
edit_uint64(vol->VolReadTime, ed3),
edit_uint64(vol->VolWriteTime, ed4),
vol->VolCatParts);
-
- Dmsg1(300, "update_volume_info(): %s", dir->msg);
+ Dmsg1(100, ">dird: %s", dir->msg);
if (!do_get_volume_info(dcr)) {
Jmsg(jcr, M_FATAL, 0, "%s", jcr->errmsg);
dcr->VolFirstIndex, dcr->VolLastIndex,
dcr->StartFile, dcr->EndFile,
dcr->StartBlock, dcr->EndBlock);
- Dmsg1(400, "create_jobmedia(): %s", dir->msg);
+ Dmsg1(100, ">dird: %s", dir->msg);
if (bnet_recv(dir) <= 0) {
Dmsg0(190, "create_jobmedia error bnet_recv\n");
Jmsg(jcr, M_FATAL, 0, _("Error creating JobMedia record: ERR=%s\n"),
bnet_strerror(dir));
return false;
}
- Dmsg1(400, "Create_jobmedia: %s", dir->msg);
+ Dmsg1(100, "<dir: %s", dir->msg);
if (strcmp(dir->msg, OK_create) != 0) {
Dmsg1(130, "Bad response from Dir: %s\n", dir->msg);
Jmsg(jcr, M_FATAL, 0, _("Error creating JobMedia record: %s\n"), dir->msg);
ser_uint32(rec->data_len);
ser_bytes(rec->data, rec->data_len);
dir->msglen = ser_length(dir->msg);
+ Dmsg1(100, ">dird: %s", dir->msg);
return bnet_send(dir);
}
*
* 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
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;
}
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) {
*/
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"));
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);
* 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
* 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;
}
}
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()) {
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 {
* 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;
* 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;
/*
* Rewind the device.
* Returns: true on success
- * false on failure
+ * false on failure
*/
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;
}
* 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;
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)
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
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;
/*
*/
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();
* 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
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 */
+ }
}
}
/*
/* 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);
* 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)
{
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;
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 */
/*
* Load medium in device
* Returns: true on success
- * false on failure
+ * false on failure
*/
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
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;
/*
* Rewind device and put it offline
* Returns: true on success
- * false on failure
+ * false on failure
*/
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);
/*
* Foward space a file
* Returns: true on success
- * false on failure
+ * false on failure
*/
bool
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();
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);
} 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);
/*
* Backward space a file
* Returns: false on failure
- * true on success
+ * true on success
*/
bool
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");
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;
/*
* Foward space a record
* Returns: false on failure
- * true on success
+ * true on success
*/
bool
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;
/*
* Backward space a record
* Returns: false on failure
- * true on success
+ * true on success
*/
bool
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;
/*
* 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)
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;
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);
}
/*
* 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)
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;
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++;
}
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 */
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());
}
}
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());
}
}
}
}
+/* This returns the physical device name */
char *
dev_name(DEVICE *dev)
{
return dev->dev_name;
}
+/* Return the resource name for the device */
+const char *DEVICE::name() const
+{
+ return device->hdr.name;
+}
+
char *
dev_vol_name(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;
/*
* 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;
}
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;
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;
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;
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;
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;
}
VOLUME_CAT_INFO VolCatInfo; /* Volume Catalog Information */
VOLUME_LABEL VolHdr; /* Actual volume label */
+ uint64_t PoolId; /* DB PoolId */
+ char pool_name[MAX_NAME_LENGTH]; /* pool name */
+ char pool_type[MAX_NAME_LENGTH]; /* pool type */
/* Device wait times ***FIXME*** look at durations */
char BadVolName[MAX_NAME_LENGTH]; /* Last wrong Volume mounted */
int can_read() const;
const char *strerror() const;
const char *archive_name() const;
+ const char *name() const;
void set_eof();
void set_eot();
void set_append();
inline int DEVICE::is_open() const { return state & ST_OPENED; }
inline int DEVICE::is_offline() const { return state & ST_OFFLINE; }
inline int DEVICE::is_labeled() const { return state & ST_LABEL; }
-inline int DEVICE::is_busy() const { return state & ST_READ || num_writers; }
+inline int DEVICE::is_busy() const { return state & ST_READ || num_writers || reserved_device; }
inline int DEVICE::at_eof() const { return state & ST_EOF; }
inline int DEVICE::at_eot() const { return state & ST_EOT; }
inline int DEVICE::can_append() const { return state & ST_APPEND; }
uint32_t EndBlock; /* Ending block written */
int64_t spool_size; /* Current spool size */
int64_t max_spool_size; /* Max job spool size */
+ uint64_t PoolId; /* PoolId from DB */
char VolumeName[MAX_NAME_LENGTH]; /* Volume name */
char pool_name[MAX_NAME_LENGTH]; /* pool name */
char pool_type[MAX_NAME_LENGTH]; /* pool type */
"type=%d level=%d FileSet=%127s NoAttr=%d SpoolAttr=%d FileSetMD5=%127s "
"SpoolData=%d WritePartAfterJob=%d";
static char use_device[] = "use device=%127s media_type=%127s "
- "pool_name=%127s pool_type=%127s append=%d";
+ "pool_name=%127s pool_type=%127s PoolId=%lld append=%d";
static char query_device[] = "query device=%127s";
static char NOT_open[] = "3925 Device \"%s\" could not be opened or does not exist.\n";
static char BAD_use[] = "3913 Bad use command: %s\n";
static char BAD_job[] = "3915 Bad Job command: %s\n";
-static char OK_query[] = "3001 OK query append=%d read=%d num_writers=%d "
- "num_waiting=%d open=%d use_count=%d labeled=%d offline=%d "
+static char OK_query[] = "3001 OK query "
+ "append=%d read=%d num_writers=%d "
+ "open=%d labeled=%d offline=%d "
+ "reserved=%d max_writers=%d "
"autoselect=%d autochanger=%d "
+ "poolid=%s "
"changer_name=%s media_type=%s volume_name=%s";
static char BAD_query[] = "3917 Bad query command: %s\n";
/*
* Get JobId and permissions from Director
*/
- Dmsg1(100, "Job_cmd: %s\n", dir->msg);
+ Dmsg1(100, "<dird: %s\n", dir->msg);
if (sscanf(dir->msg, jobcmd, &JobId, job.c_str(), job_name.c_str(),
client_name.c_str(),
&JobType, &level, fileset_name.c_str(), &no_attributes,
&spool_attributes, fileset_md5.c_str(), &spool_data, &write_part_after_job) != 12) {
pm_strcpy(jcr->errmsg, dir->msg);
bnet_fsend(dir, BAD_job, jcr->errmsg);
+ Dmsg1(100, ">dird: %s\n", dir->msg);
Emsg1(M_FATAL, 0, _("Bad Job Command from Director: %s\n"), jcr->errmsg);
set_jcr_job_status(jcr, JS_ErrorTerminated);
return false;
*/
make_session_key(auth_key, NULL, 1);
bnet_fsend(dir, OKjob, jcr->VolSessionId, jcr->VolSessionTime, auth_key);
- Dmsg1(110, ">dird: %s", dir->msg);
+ Dmsg1(100, ">dird: %s", dir->msg);
jcr->sd_auth_key = bstrdup(auth_key);
memset(auth_key, 0, sizeof(auth_key));
return true;
/*
* Wait for the device, media, and pool information
*/
- Dmsg1(100, "Use_cmd: %s\n", jcr->dir_bsock->msg);
if (!use_device_cmd(jcr)) {
set_jcr_job_status(jcr, JS_ErrorTerminated);
memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
POOL_MEM dev_name, media_type, pool_name, pool_type;
BSOCK *dir = jcr->dir_bsock;
DEVRES *device;
+ uint64_t PoolId;
AUTOCHANGER *changer;
int append;
bool ok;
- Dmsg1(100, "Use_device_cmd: %s", jcr->dir_bsock->msg);
/*
* If there are multiple devices, the director sends us
* use_device for each device that it wants to use.
*/
+ Dmsg1(100, "<dird: %s", dir->msg);
ok = sscanf(dir->msg, use_device, dev_name.c_str(), media_type.c_str(),
- pool_name.c_str(), pool_type.c_str(), &append) == 5;
+ pool_name.c_str(), pool_type.c_str(), &PoolId, &append) == 6;
if (ok) {
unbash_spaces(dev_name);
unbash_spaces(media_type);
" 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());
+ Dmsg1(100, ">dird: %s\n", dir->msg);
return false;
}
dcr = new_dcr(jcr, device->dev);
if (!dcr) {
bnet_fsend(dir, _("3926 Could not get dcr for device: %s\n"), dev_name.c_str());
+ Dmsg1(100, ">dird: %s\n", dir->msg);
return false;
}
Dmsg1(100, "Found device %s\n", device->hdr.name);
bstrncpy(dcr->pool_type, pool_type, name_len);
bstrncpy(dcr->media_type, media_type, name_len);
bstrncpy(dcr->dev_name, dev_name, name_len);
+ dcr->PoolId = PoolId;
jcr->dcr = dcr;
if (append == SD_APPEND) {
ok = reserve_device_for_append(jcr, device->dev);
}
if (!ok) {
bnet_fsend(dir, _("3927 Could not reserve device: %s\n"), dev_name.c_str());
+ Dmsg1(100, ">dird: %s\n", dir->msg);
free_dcr(jcr->dcr);
return false;
}
Dmsg1(220, "Got: %s", dir->msg);
bash_spaces(dev_name);
- return bnet_fsend(dir, OK_device, dev_name.c_str());
+ ok = bnet_fsend(dir, OK_device, dev_name.c_str());
+ Dmsg1(100, ">dird: %s\n", dir->msg);
+ return ok;
}
}
dcr = new_dcr(jcr, device->dev);
if (!dcr) {
bnet_fsend(dir, _("3926 Could not get dcr for device: %s\n"), dev_name.c_str());
+ Dmsg1(100, ">dird: %s\n", dir->msg);
UnlockRes();
return false;
}
UnlockRes();
pm_strcpy(dev_name, device->hdr.name);
bash_spaces(dev_name);
- return bnet_fsend(dir, OK_device, dev_name.c_str());
+ ok = bnet_fsend(dir, OK_device, dev_name.c_str());
+ Dmsg1(100, ">dird: %s\n", dir->msg);
+ return ok;
}
break; /* we found it but could not open a device */
}
" Device \"%s\" with MediaType \"%s\" requested by DIR not found in SD Device resources.\n"),
dev_name.c_str(), media_type.c_str());
bnet_fsend(dir, NO_device, dev_name.c_str());
+ Dmsg1(100, ">dird: %s\n", dir->msg);
} else {
unbash_spaces(dir->msg);
pm_strcpy(jcr->errmsg, dir->msg);
}
Jmsg(jcr, M_FATAL, 0, _("Bad Use Device command: %s\n"), jcr->errmsg);
bnet_fsend(dir, BAD_use, jcr->errmsg);
+ Dmsg1(100, ">dird: %s\n", dir->msg);
}
return false; /* ERROR return */
DEVRES *device;
AUTOCHANGER *changer;
bool ok;
+ char ed1[50];
Dmsg1(100, "Query_cmd: %s", dir->msg);
-
ok = sscanf(dir->msg, query_device, dev_name.c_str()) == 1;
+ Dmsg1(100, "<dird: %s\n", dir->msg);
if (ok) {
unbash_spaces(dev_name);
LockRes();
if (dev->is_labeled()) {
pm_strcpy(VolumeName, dev->VolHdr.VolName);
} else {
- pm_strcpy(VolumeName, "");
+ pm_strcpy(VolumeName, "*");
}
bash_spaces(VolumeName);
pm_strcpy(MediaType, device->media_type);
pm_strcpy(ChangerName, device->changer_res->hdr.name);
bash_spaces(ChangerName);
} else {
- pm_strcpy(ChangerName, "");
+ pm_strcpy(ChangerName, "*");
}
- return bnet_fsend(dir, OK_query, dev->can_append()!=0,
- dev->can_read()!=0, dev->num_writers, dev->num_waiting,
- dev->is_open()!=0, dev->use_count, dev->is_labeled()!=0,
- dev->is_offline()!=0, 0, dev->autoselect,
+ ok =bnet_fsend(dir, OK_query,
+ dev->can_append()!=0,
+ dev->can_read()!=0, dev->num_writers,
+ dev->is_open()!=0, dev->is_labeled()!=0,
+ dev->is_offline()!=0, dev->reserved_device,
+ dev->is_tape()?100000:1,
+ dev->autoselect, 0,
+ edit_uint64(dev->PoolId, ed1),
ChangerName.c_str(), MediaType.c_str(), VolumeName.c_str());
+ Dmsg1(100, ">dird: %s\n", dir->msg);
+ return ok;
}
}
foreach_res(changer, R_AUTOCHANGER) {
if (fnmatch(dev_name.c_str(), changer->hdr.name, 0) == 0) {
UnlockRes();
/* This is mostly to indicate that we are here */
- return bnet_fsend(dir, OK_query, 0,
- 0, 0, 0,
- 0, 0, 0,
- 0, 1, "*", /* Set AutoChanger = 1 */
- "*", "*");
+ ok = bnet_fsend(dir, OK_query,
+ 0, 0, 0, /* append, read, num_writers */
+ 0, 0, 0, /* is_open, is_labeled, offline */
+ 0, 0, /* reserved, max_writers */
+ 0, 1, /* autoselect, AutoChanger = 1 */
+ "0", /* PoolId */
+ "*", "*", "*"); /* ChangerName, MediaType, VolName */
+ Dmsg1(100, ">dird: %s\n", dir->msg);
+ return ok;
}
}
/* If we get here, the device/autochanger was not found */
unbash_spaces(dir->msg);
pm_strcpy(jcr->errmsg, dir->msg);
bnet_fsend(dir, NO_device, dev_name.c_str());
+ Dmsg1(100, ">dird: %s\n", dir->msg);
} else {
unbash_spaces(dir->msg);
pm_strcpy(jcr->errmsg, dir->msg);
bnet_fsend(dir, BAD_query, jcr->errmsg);
+ Dmsg1(100, ">dird: %s\n", dir->msg);
}
return true;
/* */
#undef VERSION
-#define VERSION "1.37.5"
-#define BDATE "04 March 2005"
-#define LSMDATE "04Mar05"
+#define VERSION "1.37.6"
+#define BDATE "06 March 2005"
+#define LSMDATE "06Mar05"
/* Debug flags */
#undef DEBUG