From ad7a16fbbb61842d3272431ccac46f128c3335c5 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Sun, 6 Mar 2005 14:56:05 +0000 Subject: [PATCH] 06Mar05 - Add new run command to Job resource in DIR. This permits cloning a job as many times as you want. - Pass PoolId to SD on Query request. It is now used in the Find_media catalog request. - Reworked the Device resource in the DIR. Eliminated num_waiting and use_count, but added max_writers, reserved, and PoolId. - This DIR is nolonger compatible with previous SDs. - Add since and cloned keywords to the Console run command to support cloning. - Implemented store_alist_str() to allow multiple string items to be specified in a .conf file. - Added %s (since time) to Job code editing. - Reworked reserving drives in the SD. It now does it much simpler and correctly. 05Mar05 - Integrate HP-UX patch from Olivier Mehani - Fix FD job.c to test correctly for no level. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@1867 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/ReleaseNotes | 18 +- bacula/autoconf/acconfig.h | 4 + bacula/autoconf/config.h.in | 4 + bacula/autoconf/configure.in | 8 +- bacula/configure | 111 ++++++- bacula/kernstodo | 23 +- bacula/src/baconfig.h | 16 + bacula/src/bacula.h | 3 + bacula/src/dird/backup.c | 25 +- bacula/src/dird/catreq.c | 7 +- bacula/src/dird/dird_conf.c | 28 +- bacula/src/dird/dird_conf.h | 6 +- bacula/src/dird/fd_cmds.c | 18 +- bacula/src/dird/msgchan.c | 43 ++- bacula/src/dird/next_vol.c | 5 +- bacula/src/dird/ua_output.c | 1 + bacula/src/dird/ua_run.c | 59 ++-- bacula/src/dird/ua_status.c | 75 ++--- bacula/src/jcr.h | 3 +- bacula/src/lib/parse_conf.c | 26 ++ bacula/src/lib/parse_conf.h | 3 +- bacula/src/lib/util.c | 86 +++--- bacula/src/stored/acquire.c | 109 ++++--- bacula/src/stored/askdir.c | 18 +- bacula/src/stored/dev.c | 549 ++++++++++++++++++----------------- bacula/src/stored/dev.h | 7 +- bacula/src/stored/job.c | 72 +++-- bacula/src/version.h | 6 +- 28 files changed, 837 insertions(+), 496 deletions(-) diff --git a/bacula/ReleaseNotes b/bacula/ReleaseNotes index 29c16fdff2..13e985bfe6 100644 --- a/bacula/ReleaseNotes +++ b/bacula/ReleaseNotes @@ -1,7 +1,7 @@ - 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: @@ -23,6 +23,19 @@ 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 @@ -202,4 +215,3 @@ def NewVolume(j): return 1 ==== - diff --git a/bacula/autoconf/acconfig.h b/bacula/autoconf/acconfig.h index e93344357f..2b74fa8e21 100644 --- a/bacula/autoconf/acconfig.h +++ b/bacula/autoconf/acconfig.h @@ -216,3 +216,7 @@ /* 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 + diff --git a/bacula/autoconf/config.h.in b/bacula/autoconf/config.h.in index 9470a3e23a..9629e4f89b 100644 --- a/bacula/autoconf/config.h.in +++ b/bacula/autoconf/config.h.in @@ -217,6 +217,10 @@ /* 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 diff --git a/bacula/autoconf/configure.in b/bacula/autoconf/configure.in index bfdbc7e035..c0ef4202f0 100644 --- a/bacula/autoconf/configure.in +++ b/bacula/autoconf/configure.in @@ -1572,7 +1572,12 @@ AC_CHECK_FUNCS(strtoll, [AC_DEFINE(HAVE_STRTOLL)]) 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 @@ -1780,6 +1785,7 @@ hpux) DISTVER=`uname -r` TAPEDRIVE="/dev/rmt/0hnb" PTHREAD_LIB="-lpthread" + AC_DEFINE([_INCLUDE_LONGLONG]) ;; irix) DISTVER=`uname -r` diff --git a/bacula/configure b/bacula/configure index 4aafe1dbb5..c4239612c2 100755 --- a/bacula/configure +++ b/bacula/configure @@ -18289,8 +18289,112 @@ done +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 declares $ac_func. + For example, HP-UX 11i 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 to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 @@ -18391,6 +18495,7 @@ _ACEOF fi done +fi @@ -21381,6 +21486,10 @@ hpux) DISTVER=`uname -r` TAPEDRIVE="/dev/rmt/0hnb" PTHREAD_LIB="-lpthread" + cat >>confdefs.h <<\_ACEOF +#define _INCLUDE_LONGLONG 1 +_ACEOF + ;; irix) DISTVER=`uname -r` diff --git a/bacula/kernstodo b/bacula/kernstodo index fa64ec71ad..34896383e5 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -36,13 +36,6 @@ Autochangers: 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 @@ -77,6 +70,22 @@ Autochangers Done: 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 diff --git a/bacula/src/baconfig.h b/bacula/src/baconfig.h index 9ce9c4a305..06baea30ff 100644 --- a/bacula/src/baconfig.h +++ b/bacula/src/baconfig.h @@ -511,6 +511,22 @@ extern "C" int getdomainname(char *name, int len); #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); diff --git a/bacula/src/bacula.h b/bacula/src/bacula.h index e662530756..57f59891fb 100644 --- a/bacula/src/bacula.h +++ b/bacula/src/bacula.h @@ -58,6 +58,9 @@ #include #endif #if HAVE_UNISTD_H +# ifdef HAVE_HPUX_OS +# undef _INCLUDE_POSIX1C_SOURCE +# endif #include #endif #if HAVE_ALLOCA_H diff --git a/bacula/src/dird/backup.c b/bacula/src/dird/backup.c index ecf379b1cd..d8dad976b6 100644 --- a/bacula/src/dird/backup.c +++ b/bacula/src/dird/backup.c @@ -97,8 +97,6 @@ bool do_backup_init(JCR *jcr) 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; } @@ -106,6 +104,29 @@ bool do_backup_init(JCR *jcr) 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; } diff --git a/bacula/src/dird/catreq.c b/bacula/src/dird/catreq.c index fd53c276c8..6df8db94fe 100644 --- a/bacula/src/dird/catreq.c +++ b/bacula/src/dird/catreq.c @@ -41,7 +41,7 @@ */ /* 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" @@ -114,7 +114,10 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg) 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 diff --git a/bacula/src/dird/dird_conf.c b/bacula/src/dird/dird_conf.c index 25c2ecac89..27175cda70 100644 --- a/bacula/src/dird/dird_conf.c +++ b/bacula/src/dird/dird_conf.c @@ -215,7 +215,8 @@ RES_ITEM job_items[] = { {"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}, @@ -395,7 +396,7 @@ const char *level_to_str(int level) 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; @@ -471,12 +472,14 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm 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: @@ -563,7 +566,12 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm 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); @@ -948,6 +956,9 @@ void free_resource(RES *sres, int type) 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; } @@ -1055,6 +1066,7 @@ void save_resource(int type, RES_ITEM *items, int pass) 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) { diff --git a/bacula/src/dird/dird_conf.h b/bacula/src/dird/dird_conf.h index 3bc8ec5a51..03b14f2d81 100644 --- a/bacula/src/dird/dird_conf.h +++ b/bacula/src/dird/dird_conf.h @@ -125,8 +125,8 @@ public: 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; @@ -134,6 +134,7 @@ public: bool autochanger; bool offline; bool autoselect; + uint32_t PoolId; char ChangerName[MAX_NAME_LENGTH]; char VolumeName[MAX_NAME_LENGTH]; char MediaType[MAX_NAME_LENGTH]; @@ -291,6 +292,7 @@ public: 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 */ }; diff --git a/bacula/src/dird/fd_cmds.c b/bacula/src/dird/fd_cmds.c index 24e13e6e2d..c4c9bba8b7 100644 --- a/bacula/src/dird/fd_cmds.c +++ b/bacula/src/dird/fd_cmds.c @@ -145,14 +145,22 @@ int connect_to_file_daemon(JCR *jcr, int retry_interval, int max_retry_time, 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: diff --git a/bacula/src/dird/msgchan.c b/bacula/src/dird/msgchan.c index 632b7783a5..1c49dfc122 100644 --- a/bacula/src/dird/msgchan.c +++ b/bacula/src/dird/msgchan.c @@ -43,15 +43,18 @@ static char jobcmd[] = "JobId=%d job=%s job_name=%s client_name=%s " "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 */ @@ -80,7 +83,7 @@ bool connect_to_storage_daemon(JCR *jcr, int retry_interval, /* * 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, @@ -116,13 +119,17 @@ bool update_device_res(JCR *jcr, DEVICE *dev) 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, "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, "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); @@ -131,6 +138,9 @@ bool update_device_res(JCR *jcr, DEVICE *dev) 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; @@ -155,6 +165,7 @@ int start_storage_daemon_job(JCR *jcr, alist *store, int append) BSOCK *sd; char auth_key[100]; POOL_MEM device_name, pool_name, pool_type, media_type; + char PoolId[50]; sd = jcr->store_bsock; /* @@ -170,12 +181,12 @@ int start_storage_daemon_job(JCR *jcr, alist *store, int append) 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, "msg); + Dmsg1(100, "msg); if (sscanf(sd->msg, OKjob, &jcr->VolSessionId, &jcr->VolSessionTime, &auth_key) != 3) { Dmsg1(100, "BadJob=%s\n", sd->msg); @@ -195,6 +206,7 @@ int start_storage_daemon_job(JCR *jcr, alist *store, int append) 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 @@ -217,10 +229,10 @@ int start_storage_daemon_job(JCR *jcr, alist *store, int append) 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, "msg); + Dmsg1(100, "msg); /* ****FIXME**** save actual device name */ ok = sscanf(sd->msg, OK_device, device_name.c_str()) == 1; if (ok) { @@ -240,6 +252,7 @@ int start_storage_daemon_job(JCR *jcr, alist *store, int append) // } if (ok) { ok = bnet_fsend(sd, "run"); + Dmsg1(100, ">stored: %s\n", sd->msg); } return ok; } diff --git a/bacula/src/dird/next_vol.c b/bacula/src/dird/next_vol.c index bf44fc8442..53e941eaba 100644 --- a/bacula/src/dird/next_vol.c +++ b/bacula/src/dird/next_vol.c @@ -33,7 +33,7 @@ /* * Items needed: - * jcr->PoolId + * mr.PoolId must be set * jcr->store * jcr->db * jcr->pool @@ -47,9 +47,8 @@ int find_next_volume_for_append(JCR *jcr, MEDIA_DBR *mr, bool create) 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 diff --git a/bacula/src/dird/ua_output.c b/bacula/src/dird/ua_output.c index 5542066280..af30220093 100644 --- a/bacula/src/dird/ua_output.c +++ b/bacula/src/dird/ua_output.c @@ -421,6 +421,7 @@ static bool list_nextvol(UAContext *ua) 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) { diff --git a/bacula/src/dird/ua_run.c b/bacula/src/dird/ua_run.c index 29fba3371d..5cd149e200 100644 --- a/bacula/src/dird/ua_run.c +++ b/bacula/src/dird/ua_run.c @@ -53,6 +53,8 @@ int run_cmd(UAContext *ua, const char *cmd) 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; @@ -63,24 +65,26 @@ int run_cmd(UAContext *ua, const char *cmd) 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 @@ -239,6 +243,16 @@ int run_cmd(UAContext *ua, const char *cmd) 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; } @@ -444,6 +458,15 @@ int run_cmd(UAContext *ua, const char *cmd) 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; diff --git a/bacula/src/dird/ua_status.c b/bacula/src/dird/ua_status.c index 0b204a064e..3c6c372ea5 100644 --- a/bacula/src/dird/ua_status.c +++ b/bacula/src/dird/ua_status.c @@ -8,7 +8,7 @@ */ /* - 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 @@ -108,7 +108,7 @@ int status_cmd(UAContext *ua, const char *cmd) 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) { @@ -197,7 +197,7 @@ static void do_all_status(UAContext *ua) } 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(); @@ -231,7 +231,7 @@ static void do_all_status(UAContext *ua) } 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(); @@ -252,7 +252,7 @@ static void do_director_status(UAContext *ua) 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"), @@ -372,6 +372,7 @@ static void prt_runtime(UAContext *ua, sched_pkt *sp) 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); @@ -382,7 +383,7 @@ static void prt_runtime(UAContext *ua, sched_pkt *sp) 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); @@ -503,7 +504,7 @@ static void list_running_jobs(UAContext *ua) */ 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--; } @@ -527,66 +528,66 @@ static void list_running_jobs(UAContext *ua) 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; @@ -600,21 +601,21 @@ static void list_running_jobs(UAContext *ua) 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; @@ -622,7 +623,7 @@ static void list_running_jobs(UAContext *ua) 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)); @@ -669,7 +670,7 @@ static void list_terminated_jobs(UAContext *ua) /* 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; } } @@ -682,7 +683,7 @@ static void list_terminated_jobs(UAContext *ua) 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)); @@ -691,23 +692,23 @@ static void list_terminated_jobs(UAContext *ua) } 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"), diff --git a/bacula/src/jcr.h b/bacula/src/jcr.h index 550be78ef8..85e8e98923 100644 --- a/bacula/src/jcr.h +++ b/bacula/src/jcr.h @@ -130,6 +130,7 @@ struct JCR { 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 */ @@ -174,7 +175,6 @@ struct JCR { 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 */ @@ -190,6 +190,7 @@ struct JCR { 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 */ diff --git a/bacula/src/lib/parse_conf.c b/bacula/src/lib/parse_conf.c index 031f939d35..d5dc130815 100755 --- a/bacula/src/lib/parse_conf.c +++ b/bacula/src/lib/parse_conf.c @@ -528,6 +528,32 @@ void store_alist_res(LEX *lc, RES_ITEM *item, int index, int pass) } +/* + * 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 diff --git a/bacula/src/lib/parse_conf.h b/bacula/src/lib/parse_conf.h index 18a22261da..46f08f2eec 100644 --- a/bacula/src/lib/parse_conf.h +++ b/bacula/src/lib/parse_conf.h @@ -2,7 +2,7 @@ * 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 @@ -130,6 +130,7 @@ void store_name(LEX *lc, RES_ITEM *item, int index, int pass); 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); diff --git a/bacula/src/lib/util.c b/bacula/src/lib/util.c index a7c634b55b..ed15119ab3 100644 --- a/bacula/src/lib/util.c +++ b/bacula/src/lib/util.c @@ -109,7 +109,7 @@ unbash_spaces(char *str) { while (*str) { if (*str == 0x1) - *str = ' '; + *str = ' '; str++; } } @@ -121,7 +121,7 @@ unbash_spaces(POOL_MEM &pm) char *str = pm.c_str(); while (*str) { if (*str == 0x1) - *str = ' '; + *str = ' '; str++; } } @@ -240,7 +240,7 @@ void jobstatus_to_ascii(int JobStatus, char *msg, int maxlen) 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; @@ -364,22 +364,22 @@ char *encode_mode(mode_t mode, char *buf) 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; } @@ -407,7 +407,7 @@ int do_shell_expansion(char *name, int name_len) 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 "); @@ -419,7 +419,7 @@ int do_shell_expansion(char *name, int name_len) 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 */ } @@ -454,7 +454,7 @@ void make_session_key(char *key, char *seed, int mode) /* 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. */ @@ -492,7 +492,7 @@ void make_session_key(char *key, char *seed, int mode) key[k++] = Rad16(rb & 0xF); #undef Rad16 if (j & 1) { - key[k++] = '-'; + key[k++] = '-'; } } key[--k] = 0; @@ -516,6 +516,7 @@ void make_session_key(char *key, char *seed, int mode) * %j = Unique Job name * %l = job level * %n = Unadorned Job name + * %s = Since time * %t = Job type (Backup, ...) * %r = Recipients * %v = Volume name @@ -538,85 +539,92 @@ POOLMEM *edit_job_codes(JCR *jcr, char *omsg, char *imsg, const char *to) 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; diff --git a/bacula/src/stored/acquire.c b/bacula/src/stored/acquire.c index e0543f3e91..0fc975be3a 100644 --- a/bacula/src/stored/acquire.c +++ b/bacula/src/stored/acquire.c @@ -64,6 +64,7 @@ DCR *new_dcr(JCR *jcr, DEVICE *dev) * 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; @@ -82,6 +83,7 @@ static void remove_dcr_from_dcrs(DCR *dcr) } } } +#endif /* * Free up all aspects of the given dcr -- i.e. dechain it, @@ -149,7 +151,7 @@ bool reserve_device_for_read(JCR *jcr, DEVICE *dev) 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) { @@ -353,11 +355,16 @@ get_out: * 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); @@ -365,60 +372,65 @@ bool reserve_device_for_append(JCR *jcr, DEVICE *dev) 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); @@ -453,6 +465,15 @@ DCR *acquire_device_for_append(JCR *jcr, DEVICE *dev) 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"); /* @@ -497,10 +518,6 @@ DCR *acquire_device_for_append(JCR *jcr, DEVICE *dev) } 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; } diff --git a/bacula/src/stored/askdir.c b/bacula/src/stored/askdir.c index 7671daa1a6..461b60b96a 100644 --- a/bacula/src/stored/askdir.c +++ b/bacula/src/stored/askdir.c @@ -30,7 +30,7 @@ #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" @@ -90,7 +90,7 @@ static bool do_get_volume_info(DCR *dcr) return false; } memset(&vol, 0, sizeof(vol)); - Dmsg1(300, "Get vol info=%s", dir->msg); + Dmsg1(100, "msg); n = sscanf(dir->msg, OK_media, vol.VolCatName, &vol.VolCatJobs, &vol.VolCatFiles, &vol.VolCatBlocks, &vol.VolCatBytes, @@ -133,10 +133,10 @@ bool dir_get_volume_info(DCR *dcr, enum get_vol_info_rw writing) 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); } @@ -154,6 +154,7 @@ bool dir_find_next_appendable_volume(DCR *dcr) { JCR *jcr = dcr->jcr; BSOCK *dir = jcr->dir_bsock; + char ed1[50]; JCR *njcr; Dmsg0(200, "dir_find_next_appendable_volume\n"); @@ -163,7 +164,8 @@ bool dir_find_next_appendable_volume(DCR *dcr) * 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; @@ -249,8 +251,7 @@ bool dir_update_volume_info(DCR *dcr, bool label) 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); @@ -281,14 +282,14 @@ bool dir_create_jobmedia_record(DCR *dcr) 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, "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); @@ -322,6 +323,7 @@ bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) 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); } diff --git a/bacula/src/stored/dev.c b/bacula/src/stored/dev.c index e244dc621a..e34856ec89 100644 --- a/bacula/src/stored/dev.c +++ b/bacula/src/stored/dev.c @@ -2,18 +2,18 @@ * * dev.c -- low level operations on device (storage device) * - * Kern Sibbald, MM + * Kern Sibbald, MM * * NOTE!!!! None of these routines are reentrant. You must - * use lock_device() and unlock_device() at a higher level, - * or use the xxx_device() equivalents. By moving the - * thread synchronization to a higher level, we permit + * use lock_device() and unlock_device() at a higher level, + * or use the xxx_device() equivalents. By moving the + * thread synchronization to a higher level, we permit * the higher level routines to "seize" the device and - * to carry out operations without worrying about who - * set what lock (i.e. race conditions). + * to carry out operations without worrying about who + * set what lock (i.e. race conditions). * * Note, this is the device dependent code, and my have - * to be modified for each system, but is meant to + * to be modified for each system, but is meant to * be as "generic" as possible. * * The purpose of this code is to develop a SIMPLE Storage @@ -114,10 +114,10 @@ init_dev(JCR *jcr, DEVICE *dev, DEVRES *device) if (stat(device->device_name, &statp) < 0) { berrno be; if (dev) { - dev->dev_errno = errno; + dev->dev_errno = errno; } Jmsg2(jcr, M_ERROR, 0, _("Unable to stat device %s: ERR=%s\n"), - device->device_name, be.strerror()); + device->device_name, be.strerror()); return NULL; } @@ -132,10 +132,10 @@ init_dev(JCR *jcr, DEVICE *dev, DEVRES *device) fifo = true; } else { if (dev) { - dev->dev_errno = ENODEV; + dev->dev_errno = ENODEV; } Jmsg2(jcr, M_ERROR, 0, _("%s is an unknown device type. Must be tape or directory. st_mode=%x\n"), - device->device_name, statp.st_mode); + device->device_name, statp.st_mode); return NULL; } if (!dev) { @@ -189,11 +189,11 @@ init_dev(JCR *jcr, DEVICE *dev, DEVRES *device) */ if (dev->is_file() && device->cap_bits & CAP_REQMOUNT) { if (stat(device->mount_point, &statp) < 0) { - berrno be; - dev->dev_errno = errno; + berrno be; + dev->dev_errno = errno; Jmsg2(jcr, M_ERROR, 0, _("Unable to stat mount point %s: ERR=%s\n"), - device->mount_point, be.strerror()); - return NULL; + device->mount_point, be.strerror()); + return NULL; } if (!device->mount_command || !device->unmount_command) { Jmsg0(jcr, M_ERROR_TERM, 0, _("Mount and unmount commands must defined for a device which requires mount.\n")); @@ -206,12 +206,12 @@ init_dev(JCR *jcr, DEVICE *dev, DEVRES *device) if (dev->max_block_size > 1000000) { Jmsg3(jcr, M_ERROR, 0, _("Block size %u on device %s is too large, using default %u\n"), - dev->max_block_size, dev->dev_name, DEFAULT_BLOCK_SIZE); + dev->max_block_size, dev->dev_name, DEFAULT_BLOCK_SIZE); dev->max_block_size = 0; } if (dev->max_block_size % TAPE_BSIZE != 0) { Jmsg2(jcr, M_WARNING, 0, _("Max block size %u not multiple of device %s block size.\n"), - dev->max_block_size, dev->dev_name); + dev->max_block_size, dev->dev_name); } dev->errmsg = get_pool_memory(PM_EMSG); @@ -260,7 +260,7 @@ init_dev(JCR *jcr, DEVICE *dev, DEVRES *device) * initialize buffer pointers. * * Returns: -1 on error - * fd on success + * fd on success * * Note, for a tape, the VolName is the name we give to the * volume (not really used here), but for a file, the @@ -279,11 +279,11 @@ open_dev(DEVICE *dev, char *VolName, int mode) * starts and snatches up the device. */ if (VolName && strcmp(dev->VolCatInfo.VolCatName, VolName) != 0) { - return -1; + return -1; } dev->use_count++; Mmsg2(&dev->errmsg, _("WARNING!!!! device %s opened %d times!!!\n"), - dev->dev_name, dev->use_count); + dev->dev_name, dev->use_count); Emsg1(M_WARNING, 0, "%s", dev->errmsg); return dev->fd; } @@ -292,7 +292,7 @@ open_dev(DEVICE *dev, char *VolName, int mode) } Dmsg3(29, "open_dev: tape=%d dev_name=%s vol=%s\n", dev_is_tape(dev), - dev->dev_name, dev->VolCatInfo.VolCatName); + dev->dev_name, dev->VolCatInfo.VolCatName); dev->state &= ~(ST_LABEL|ST_APPEND|ST_READ|ST_EOT|ST_WEOT|ST_EOF); dev->label_type = B_BACULA_LABEL; if (dev->is_tape() || dev->is_fifo()) { @@ -300,53 +300,53 @@ open_dev(DEVICE *dev, char *VolName, int mode) int timeout; Dmsg0(29, "open_dev: device is tape\n"); if (mode == OPEN_READ_WRITE) { - dev->mode = O_RDWR | O_BINARY; + dev->mode = O_RDWR | O_BINARY; } else if (mode == OPEN_READ_ONLY) { - dev->mode = O_RDONLY | O_BINARY; + dev->mode = O_RDONLY | O_BINARY; } else if (mode == OPEN_WRITE_ONLY) { - dev->mode = O_WRONLY | O_BINARY; + dev->mode = O_WRONLY | O_BINARY; } else { Emsg0(M_ABORT, 0, _("Illegal mode given to open_dev.\n")); } timeout = dev->max_open_wait; errno = 0; if (dev->is_fifo() && timeout) { - /* Set open timer */ - dev->tid = start_thread_timer(pthread_self(), timeout); + /* Set open timer */ + dev->tid = start_thread_timer(pthread_self(), timeout); } /* If busy retry each second for max_open_wait seconds */ while ((dev->fd = open(dev->dev_name, dev->mode, MODE_RW)) < 0) { - berrno be; - if (errno == EINTR || errno == EAGAIN) { - continue; - } - if (errno == EBUSY && timeout-- > 0) { + berrno be; + if (errno == EINTR || errno == EAGAIN) { + continue; + } + if (errno == EBUSY && timeout-- > 0) { Dmsg2(100, "Device %s busy. ERR=%s\n", dev->dev_name, be.strerror()); - bmicrosleep(1, 0); - continue; - } - dev->dev_errno = errno; + bmicrosleep(1, 0); + continue; + } + dev->dev_errno = errno; Mmsg2(&dev->errmsg, _("stored: unable to open device %s: ERR=%s\n"), - dev->dev_name, be.strerror()); - /* Stop any open timer we set */ - if (dev->tid) { - stop_thread_timer(dev->tid); - dev->tid = 0; - } - Emsg0(M_FATAL, 0, dev->errmsg); - break; + dev->dev_name, be.strerror()); + /* Stop any open timer we set */ + if (dev->tid) { + stop_thread_timer(dev->tid); + dev->tid = 0; + } + Emsg0(M_FATAL, 0, dev->errmsg); + break; } if (dev->fd >= 0) { - dev->dev_errno = 0; - dev->state |= ST_OPENED; - dev->use_count = 1; - update_pos_dev(dev); /* update position */ - set_os_device_parameters(dev); /* do system dependent stuff */ + dev->dev_errno = 0; + dev->state |= ST_OPENED; + dev->use_count = 1; + update_pos_dev(dev); /* update position */ + set_os_device_parameters(dev); /* do system dependent stuff */ } /* Stop any open() timer we started */ if (dev->tid) { - stop_thread_timer(dev->tid); - dev->tid = 0; + stop_thread_timer(dev->tid); + dev->tid = 0; } Dmsg1(29, "open_dev: tape %d opened\n", dev->fd); } else { @@ -356,31 +356,31 @@ open_dev(DEVICE *dev, char *VolName, int mode) * Handle opening of File Archive (not a tape) */ if (dev->part == 0) { - dev->file_size = 0; + dev->file_size = 0; } dev->part_size = 0; /* if num_parts has not been set, but VolCatInfo is available, copy * it from the VolCatInfo.VolCatParts */ if (dev->num_parts < dev->VolCatInfo.VolCatParts) { - dev->num_parts = dev->VolCatInfo.VolCatParts; + dev->num_parts = dev->VolCatInfo.VolCatParts; } if (VolName == NULL || *VolName == 0) { Mmsg(dev->errmsg, _("Could not open file device %s. No Volume name given.\n"), - dev->dev_name); - return -1; + dev->dev_name); + return -1; } get_filename(dev, VolName, archive_name); if (mount_dev(dev, 1) < 0) { Mmsg(dev->errmsg, _("Could not mount archive device %s.\n"), - dev->dev_name); - Emsg0(M_FATAL, 0, dev->errmsg); - dev->fd = -1; - return dev->fd; + dev->dev_name); + Emsg0(M_FATAL, 0, dev->errmsg); + dev->fd = -1; + return dev->fd; } - + Dmsg2(29, "open_dev: device is disk %s (mode:%d)\n", archive_name.c_str(), mode); dev->openmode = mode; @@ -389,42 +389,42 @@ open_dev(DEVICE *dev, char *VolName, int mode) * OPEN_READ_ONLY as writing would be an error. */ if (dev->part < dev->num_parts) { - mode = OPEN_READ_ONLY; + mode = OPEN_READ_ONLY; } if (mode == OPEN_READ_WRITE) { - dev->mode = O_CREAT | O_RDWR | O_BINARY; + dev->mode = O_CREAT | O_RDWR | O_BINARY; } else if (mode == OPEN_READ_ONLY) { - dev->mode = O_RDONLY | O_BINARY; + dev->mode = O_RDONLY | O_BINARY; } else if (mode == OPEN_WRITE_ONLY) { - dev->mode = O_WRONLY | O_BINARY; + dev->mode = O_WRONLY | O_BINARY; } else { Emsg0(M_ABORT, 0, _("Illegal mode given to open_dev.\n")); } /* If creating file, give 0640 permissions */ if ((dev->fd = open(archive_name.c_str(), dev->mode, 0640)) < 0) { - berrno be; - dev->dev_errno = errno; + berrno be; + dev->dev_errno = errno; Mmsg2(&dev->errmsg, _("Could not open: %s, ERR=%s\n"), archive_name.c_str(), be.strerror()); - Emsg0(M_FATAL, 0, dev->errmsg); + Emsg0(M_FATAL, 0, dev->errmsg); } else { - dev->dev_errno = 0; - dev->state |= ST_OPENED; - dev->use_count = 1; - update_pos_dev(dev); /* update position */ - if (fstat(dev->fd, &filestat) < 0) { - berrno be; - dev->dev_errno = errno; + dev->dev_errno = 0; + dev->state |= ST_OPENED; + dev->use_count = 1; + update_pos_dev(dev); /* update position */ + if (fstat(dev->fd, &filestat) < 0) { + berrno be; + dev->dev_errno = errno; Mmsg2(&dev->errmsg, _("Could not fstat: %s, ERR=%s\n"), archive_name.c_str(), be.strerror()); - Emsg0(M_FATAL, 0, dev->errmsg); - } else { - dev->part_size = filestat.st_size; - } + Emsg0(M_FATAL, 0, dev->errmsg); + } else { + dev->part_size = filestat.st_size; + } } Dmsg4(29, "open_dev: disk fd=%d opened, part=%d/%d, part_size=%u\n", dev->fd, dev->part, dev->num_parts, dev->part_size); if (dev->is_dvd() && (dev->mode != OPEN_READ_ONLY) && - (dev->free_space_errno == 0 || dev->num_parts == dev->part)) { - update_free_space_dev(dev); + (dev->free_space_errno == 0 || dev->num_parts == dev->part)) { + update_free_space_dev(dev); } } return dev->fd; @@ -442,7 +442,7 @@ bool _rewind_dev(char *file, int line, DEVICE *dev) /* * Rewind the device. * Returns: true on success - * false on failure + * false on failure */ bool rewind_dev(DEVICE *dev) { @@ -453,7 +453,7 @@ bool rewind_dev(DEVICE *dev) if (dev->fd < 0) { dev->dev_errno = EBADF; Mmsg1(&dev->errmsg, _("Bad call to rewind_dev. Device %s not open\n"), - dev->dev_name); + dev->dev_name); Emsg0(M_ABORT, 0, dev->errmsg); return false; } @@ -469,30 +469,30 @@ bool rewind_dev(DEVICE *dev) * retrying every 5 seconds. */ for (i=dev->max_rewind_wait; ; i -= 5) { - if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) { - berrno be; - clrerror_dev(dev, MTREW); - if (i == dev->max_rewind_wait) { + if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) { + berrno be; + clrerror_dev(dev, MTREW); + if (i == dev->max_rewind_wait) { Dmsg1(200, "Rewind error, %s. retrying ...\n", be.strerror()); - } - if (dev->dev_errno == EIO && i > 0) { + } + if (dev->dev_errno == EIO && i > 0) { Dmsg0(200, "Sleeping 5 seconds.\n"); - bmicrosleep(5, 0); - continue; - } + bmicrosleep(5, 0); + continue; + } Mmsg2(&dev->errmsg, _("Rewind error on %s. ERR=%s.\n"), - dev->dev_name, be.strerror()); - return false; - } - break; + dev->dev_name, be.strerror()); + return false; + } + break; } } else if (dev->is_file()) { if (lseek_dev(dev, (off_t)0, SEEK_SET) < 0) { - berrno be; - dev->dev_errno = errno; + berrno be; + dev->dev_errno = errno; Mmsg2(&dev->errmsg, _("lseek_dev error on %s. ERR=%s.\n"), - dev->dev_name, be.strerror()); - return false; + dev->dev_name, be.strerror()); + return false; } } return true; @@ -518,13 +518,13 @@ void DEVICE::set_eof() void DEVICE::set_eot() { state |= (ST_EOF|ST_EOT|ST_WEOT); - state &= ~ST_APPEND; /* make tape read-only */ + state &= ~ST_APPEND; /* make tape read-only */ } /* * Position device to end of medium (end of data) * Returns: 1 on succes - * 0 on error + * 0 on error */ int eod_dev(DEVICE *dev) @@ -549,14 +549,14 @@ eod_dev(DEVICE *dev) pos = lseek_dev(dev, (off_t)0, SEEK_END); // Dmsg1(100, "====== Seek to %lld\n", pos); if (pos >= 0) { - update_pos_dev(dev); - dev->state |= ST_EOT; - return 1; + update_pos_dev(dev); + dev->state |= ST_EOT; + return 1; } dev->dev_errno = errno; berrno be; Mmsg2(&dev->errmsg, _("lseek_dev error on %s. ERR=%s.\n"), - dev->dev_name, be.strerror()); + dev->dev_name, be.strerror()); return 0; } #ifdef MTEOM @@ -564,9 +564,9 @@ eod_dev(DEVICE *dev) Dmsg0(100,"Using FAST FSF for EOM\n"); /* If unknown position, rewind */ if (!dev_get_os_pos(dev, &mt_stat)) { - if (!rewind_dev(dev)) { - return 0; - } + if (!rewind_dev(dev)) { + return 0; + } } mt_com.mt_op = MTFSF; /* @@ -575,33 +575,33 @@ eod_dev(DEVICE *dev) */ mt_com.mt_count = INT16_MAX; /* use big positive number */ if (mt_com.mt_count < 0) { - mt_com.mt_count = INT16_MAX; /* brain damaged system */ + mt_com.mt_count = INT16_MAX; /* brain damaged system */ } } if (dev_cap(dev, CAP_MTIOCGET) && (dev_cap(dev, CAP_FASTFSF) || dev_cap(dev, CAP_EOM))) { if (dev_cap(dev, CAP_EOM)) { Dmsg0(100,"Using EOM for EOM\n"); - mt_com.mt_op = MTEOM; - mt_com.mt_count = 1; + mt_com.mt_op = MTEOM; + mt_com.mt_count = 1; } if ((stat=ioctl(dev->fd, MTIOCTOP, (char *)&mt_com)) < 0) { - berrno be; - clrerror_dev(dev, mt_com.mt_op); + berrno be; + clrerror_dev(dev, mt_com.mt_op); Dmsg1(50, "ioctl error: %s\n", be.strerror()); - update_pos_dev(dev); + update_pos_dev(dev); Mmsg2(&dev->errmsg, _("ioctl MTEOM error on %s. ERR=%s.\n"), - dev->dev_name, be.strerror()); - return 0; + dev->dev_name, be.strerror()); + return 0; } if (!dev_get_os_pos(dev, &mt_stat)) { - berrno be; - clrerror_dev(dev, -1); + berrno be; + clrerror_dev(dev, -1); Mmsg2(&dev->errmsg, _("ioctl MTIOCGET error on %s. ERR=%s.\n"), - dev->dev_name, be.strerror()); - return 0; + dev->dev_name, be.strerror()); + return 0; } Dmsg2(100, "EOD file=%d block=%d\n", mt_stat.mt_fileno, mt_stat.mt_blkno); dev->set_eof(); @@ -615,7 +615,7 @@ eod_dev(DEVICE *dev) * Rewind then use FSF until EOT reached */ if (!rewind_dev(dev)) { - return 0; + return 0; } /* * Move file by file to the end of the tape @@ -623,25 +623,25 @@ eod_dev(DEVICE *dev) int file_num; for (file_num=dev->file; !dev->at_eot(); file_num++) { Dmsg0(200, "eod_dev: doing fsf 1\n"); - if (!fsf_dev(dev, 1)) { + if (!fsf_dev(dev, 1)) { Dmsg0(200, "fsf_dev error.\n"); - return 0; - } - /* - * Avoid infinite loop. ***FIXME*** possibly add code - * to set EOD or to turn off CAP_FASTFSF if on. - */ - if (file_num == (int)dev->file) { - struct mtget mt_stat; + return 0; + } + /* + * Avoid infinite loop. ***FIXME*** possibly add code + * to set EOD or to turn off CAP_FASTFSF if on. + */ + if (file_num == (int)dev->file) { + struct mtget mt_stat; Dmsg1(100, "fsf_dev did not advance from file %d\n", file_num); - if (dev_get_os_pos(dev, &mt_stat)) { + if (dev_get_os_pos(dev, &mt_stat)) { Dmsg2(100, "Adjust file from %d to %d\n", dev->file , mt_stat.mt_fileno); - dev->set_eof(); - dev->file = mt_stat.mt_fileno; - } - stat = 0; - break; /* we are not progressing, bail out */ - } + dev->set_eof(); + dev->file = mt_stat.mt_fileno; + } + stat = 0; + break; /* we are not progressing, bail out */ + } } } /* @@ -656,12 +656,12 @@ eod_dev(DEVICE *dev) /* If BSF worked and fileno is known (not -1), set file */ if (dev_get_os_pos(dev, &mt_stat)) { Dmsg2(100, "BSFATEOF adjust file from %d to %d\n", dev->file , mt_stat.mt_fileno); - dev->file = mt_stat.mt_fileno; + dev->file = mt_stat.mt_fileno; } else { - dev->file++; /* wing it -- not correct on all OSes */ + dev->file++; /* wing it -- not correct on all OSes */ } } else { - update_pos_dev(dev); /* update position */ + update_pos_dev(dev); /* update position */ stat = 1; } Dmsg1(200, "EOD dev->file=%d\n", dev->file); @@ -672,7 +672,7 @@ eod_dev(DEVICE *dev) * Set the position of the device -- only for files * For other devices, there is no generic way to do it. * Returns: true on succes - * false on error + * false on error */ bool update_pos_dev(DEVICE *dev) { @@ -692,14 +692,14 @@ bool update_pos_dev(DEVICE *dev) dev->file_addr = 0; pos = lseek_dev(dev, (off_t)0, SEEK_CUR); if (pos < 0) { - berrno be; - dev->dev_errno = errno; + berrno be; + dev->dev_errno = errno; Pmsg1(000, "Seek error: ERR=%s\n", be.strerror()); Mmsg2(&dev->errmsg, _("lseek_dev error on %s. ERR=%s.\n"), - dev->dev_name, be.strerror()); - ok = false; + dev->dev_name, be.strerror()); + ok = false; } else { - dev->file_addr = pos; + dev->file_addr = pos; } } return ok; @@ -733,49 +733,49 @@ uint32_t status_dev(DEVICE *dev) Dmsg0(-20," Bacula status:"); Dmsg2(-20," file=%d block=%d\n", dev->file, dev->block_num); if (ioctl(dev->fd, MTIOCGET, (char *)&mt_stat) < 0) { - berrno be; - dev->dev_errno = errno; + berrno be; + dev->dev_errno = errno; Mmsg2(&dev->errmsg, _("ioctl MTIOCGET error on %s. ERR=%s.\n"), - dev->dev_name, be.strerror()); - return 0; + dev->dev_name, be.strerror()); + return 0; } Dmsg0(-20, " Device status:"); #if defined(HAVE_LINUX_OS) if (GMT_EOF(mt_stat.mt_gstat)) { - stat |= BMT_EOF; + stat |= BMT_EOF; Dmsg0(-20, " EOF"); } if (GMT_BOT(mt_stat.mt_gstat)) { - stat |= BMT_BOT; + stat |= BMT_BOT; Dmsg0(-20, " BOT"); } if (GMT_EOT(mt_stat.mt_gstat)) { - stat |= BMT_EOT; + stat |= BMT_EOT; Dmsg0(-20, " EOT"); } if (GMT_SM(mt_stat.mt_gstat)) { - stat |= BMT_SM; + stat |= BMT_SM; Dmsg0(-20, " SM"); } if (GMT_EOD(mt_stat.mt_gstat)) { - stat |= BMT_EOD; + stat |= BMT_EOD; Dmsg0(-20, " EOD"); } if (GMT_WR_PROT(mt_stat.mt_gstat)) { - stat |= BMT_WR_PROT; + stat |= BMT_WR_PROT; Dmsg0(-20, " WR_PROT"); } if (GMT_ONLINE(mt_stat.mt_gstat)) { - stat |= BMT_ONLINE; + stat |= BMT_ONLINE; Dmsg0(-20, " ONLINE"); } if (GMT_DR_OPEN(mt_stat.mt_gstat)) { - stat |= BMT_DR_OPEN; + stat |= BMT_DR_OPEN; Dmsg0(-20, " DR_OPEN"); } if (GMT_IM_REP_EN(mt_stat.mt_gstat)) { - stat |= BMT_IM_REP_EN; + stat |= BMT_IM_REP_EN; Dmsg0(-20, " IM_REP_EN"); } #endif /* !SunOS && !OSF */ @@ -794,7 +794,7 @@ uint32_t status_dev(DEVICE *dev) /* * Load medium in device * Returns: true on success - * false on failure + * false on failure */ bool load_dev(DEVICE *dev) { @@ -814,9 +814,9 @@ bool load_dev(DEVICE *dev) #ifndef MTLOAD Dmsg0(200, "stored: MTLOAD command not available\n"); berrno be; - dev->dev_errno = ENOTTY; /* function not available */ + dev->dev_errno = ENOTTY; /* function not available */ Mmsg2(&dev->errmsg, _("ioctl MTLOAD error on %s. ERR=%s.\n"), - dev->dev_name, be.strerror()); + dev->dev_name, be.strerror()); return false; #else @@ -829,7 +829,7 @@ bool load_dev(DEVICE *dev) berrno be; dev->dev_errno = errno; Mmsg2(&dev->errmsg, _("ioctl MTLOAD error on %s. ERR=%s.\n"), - dev->dev_name, be.strerror()); + dev->dev_name, be.strerror()); return false; } return true; @@ -839,7 +839,7 @@ bool load_dev(DEVICE *dev) /* * Rewind device and put it offline * Returns: true on success - * false on failure + * false on failure */ bool offline_dev(DEVICE *dev) { @@ -871,7 +871,7 @@ bool offline_dev(DEVICE *dev) berrno be; dev->dev_errno = errno; Mmsg2(&dev->errmsg, _("ioctl MTOFFL error on %s. ERR=%s.\n"), - dev->dev_name, be.strerror()); + dev->dev_name, be.strerror()); return false; } Dmsg1(100, "Offlined device %s\n", dev->dev_name); @@ -901,7 +901,7 @@ bool offline_or_rewind_dev(DEVICE *dev) /* * Foward space a file * Returns: true on success - * false on failure + * false on failure */ bool fsf_dev(DEVICE *dev, int num) @@ -943,14 +943,14 @@ fsf_dev(DEVICE *dev, int num) mt_com.mt_count = num; stat = ioctl(dev->fd, MTIOCTOP, (char *)&mt_com); if (stat < 0 || !dev_get_os_pos(dev, &mt_stat)) { - berrno be; - dev->state |= ST_EOT; + berrno be; + dev->state |= ST_EOT; Dmsg0(200, "Set ST_EOT\n"); - clrerror_dev(dev, MTFSF); + clrerror_dev(dev, MTFSF); Mmsg2(dev->errmsg, _("ioctl MTFSF error on %s. ERR=%s.\n"), - dev->dev_name, be.strerror()); + dev->dev_name, be.strerror()); Dmsg1(200, "%s", dev->errmsg); - return false; + return false; } Dmsg2(200, "fsf file=%d block=%d\n", mt_stat.mt_fileno, mt_stat.mt_blkno); dev->set_eof(); @@ -969,60 +969,60 @@ fsf_dev(DEVICE *dev, int num) int rbuf_len; Dmsg0(200, "FSF has cap_fsf\n"); if (dev->max_block_size == 0) { - rbuf_len = DEFAULT_BLOCK_SIZE; + rbuf_len = DEFAULT_BLOCK_SIZE; } else { - rbuf_len = dev->max_block_size; + rbuf_len = dev->max_block_size; } rbuf = get_memory(rbuf_len); mt_com.mt_op = MTFSF; mt_com.mt_count = 1; while (num-- && !(dev->state & ST_EOT)) { Dmsg0(100, "Doing read before fsf\n"); - if ((stat = read(dev->fd, (char *)rbuf, rbuf_len)) < 0) { - if (errno == ENOMEM) { /* tape record exceeds buf len */ - stat = rbuf_len; /* This is OK */ - } else { - berrno be; - dev->state |= ST_EOT; - clrerror_dev(dev, -1); + if ((stat = read(dev->fd, (char *)rbuf, rbuf_len)) < 0) { + if (errno == ENOMEM) { /* tape record exceeds buf len */ + stat = rbuf_len; /* This is OK */ + } else { + berrno be; + dev->state |= ST_EOT; + clrerror_dev(dev, -1); Dmsg2(100, "Set ST_EOT read errno=%d. ERR=%s\n", dev->dev_errno, - be.strerror()); + be.strerror()); Mmsg2(dev->errmsg, _("read error on %s. ERR=%s.\n"), - dev->dev_name, be.strerror()); + dev->dev_name, be.strerror()); Dmsg1(100, "%s", dev->errmsg); - break; - } - } - if (stat == 0) { /* EOF */ - update_pos_dev(dev); + break; + } + } + if (stat == 0) { /* EOF */ + update_pos_dev(dev); Dmsg1(100, "End of File mark from read. File=%d\n", dev->file+1); - /* Two reads of zero means end of tape */ - if (dev->state & ST_EOF) { - dev->state |= ST_EOT; + /* Two reads of zero means end of tape */ + if (dev->state & ST_EOF) { + dev->state |= ST_EOT; Dmsg0(100, "Set ST_EOT\n"); - break; - } else { - dev->set_eof(); - continue; - } - } else { /* Got data */ - dev->state &= ~(ST_EOF|ST_EOT); - } + break; + } else { + dev->set_eof(); + continue; + } + } else { /* Got data */ + dev->state &= ~(ST_EOF|ST_EOT); + } Dmsg0(100, "Doing MTFSF\n"); - stat = ioctl(dev->fd, MTIOCTOP, (char *)&mt_com); - if (stat < 0) { /* error => EOT */ - berrno be; - dev->state |= ST_EOT; + stat = ioctl(dev->fd, MTIOCTOP, (char *)&mt_com); + if (stat < 0) { /* error => EOT */ + berrno be; + dev->state |= ST_EOT; Dmsg0(100, "Set ST_EOT\n"); - clrerror_dev(dev, MTFSF); + clrerror_dev(dev, MTFSF); Mmsg2(&dev->errmsg, _("ioctl MTFSF error on %s. ERR=%s.\n"), - dev->dev_name, be.strerror()); + dev->dev_name, be.strerror()); Dmsg0(100, "Got < 0 for MTFSF\n"); Dmsg1(100, "%s", dev->errmsg); - } else { - dev->set_eof(); - } + } else { + dev->set_eof(); + } } free_memory(rbuf); @@ -1032,14 +1032,14 @@ fsf_dev(DEVICE *dev, int num) } else { Dmsg0(200, "Doing FSR for FSF\n"); while (num-- && !(dev->state & ST_EOT)) { - fsr_dev(dev, INT32_MAX); /* returns -1 on EOF or EOT */ + fsr_dev(dev, INT32_MAX); /* returns -1 on EOF or EOT */ } if (dev->state & ST_EOT) { - dev->dev_errno = 0; + dev->dev_errno = 0; Mmsg1(dev->errmsg, _("Device %s at End of Tape.\n"), dev->dev_name); - stat = -1; + stat = -1; } else { - stat = 0; + stat = 0; } } update_pos_dev(dev); @@ -1055,7 +1055,7 @@ fsf_dev(DEVICE *dev, int num) /* * Backward space a file * Returns: false on failure - * true on success + * true on success */ bool bsf_dev(DEVICE *dev, int num) @@ -1072,7 +1072,7 @@ bsf_dev(DEVICE *dev, int num) if (!dev->is_tape()) { Mmsg1(dev->errmsg, _("Device %s cannot BSF because it is not a tape.\n"), - dev->dev_name); + dev->dev_name); return false; } Dmsg0(29, "bsf_dev\n"); @@ -1087,7 +1087,7 @@ bsf_dev(DEVICE *dev, int num) berrno be; clrerror_dev(dev, MTBSF); Mmsg2(dev->errmsg, _("ioctl MTBSF error on %s. ERR=%s.\n"), - dev->dev_name, be.strerror()); + dev->dev_name, be.strerror()); } update_pos_dev(dev); return stat == 0; @@ -1097,7 +1097,7 @@ bsf_dev(DEVICE *dev, int num) /* * Foward space a record * Returns: false on failure - * true on success + * true on success */ bool fsr_dev(DEVICE *dev, int num) @@ -1134,18 +1134,18 @@ fsr_dev(DEVICE *dev, int num) Dmsg1(100, "FSF fail: ERR=%s\n", be.strerror()); if (dev_get_os_pos(dev, &mt_stat)) { Dmsg4(100, "Adjust from %d:%d to %d:%d\n", dev->file, - dev->block_num, mt_stat.mt_fileno, mt_stat.mt_blkno); - dev->file = mt_stat.mt_fileno; - dev->block_num = mt_stat.mt_blkno; + dev->block_num, mt_stat.mt_fileno, mt_stat.mt_blkno); + dev->file = mt_stat.mt_fileno; + dev->block_num = mt_stat.mt_blkno; } else { - if (dev->state & ST_EOF) { - dev->state |= ST_EOT; - } else { - dev->set_eof(); - } + if (dev->state & ST_EOF) { + dev->state |= ST_EOT; + } else { + dev->set_eof(); + } } Mmsg2(dev->errmsg, _("ioctl MTFSR error on %s. ERR=%s.\n"), - dev->dev_name, be.strerror()); + dev->dev_name, be.strerror()); } update_pos_dev(dev); return stat == 0; @@ -1154,7 +1154,7 @@ fsr_dev(DEVICE *dev, int num) /* * Backward space a record * Returns: false on failure - * true on success + * true on success */ bool bsr_dev(DEVICE *dev, int num) @@ -1188,7 +1188,7 @@ bsr_dev(DEVICE *dev, int num) berrno be; clrerror_dev(dev, MTBSR); Mmsg2(dev->errmsg, _("ioctl MTBSR error on %s. ERR=%s.\n"), - dev->dev_name, be.strerror()); + dev->dev_name, be.strerror()); } update_pos_dev(dev); return stat == 0; @@ -1197,7 +1197,7 @@ bsr_dev(DEVICE *dev, int num) /* * Reposition the device to file, block * Returns: false on failure - * true on success + * true on success */ bool reposition_dev(DEVICE *dev, uint32_t file, uint32_t block) @@ -1213,11 +1213,11 @@ reposition_dev(DEVICE *dev, uint32_t file, uint32_t block) off_t pos = (((off_t)file)<<32) + block; Dmsg1(100, "===== lseek_dev to %d\n", (int)pos); if (lseek_dev(dev, pos, SEEK_SET) == (off_t)-1) { - berrno be; - dev->dev_errno = errno; + berrno be; + dev->dev_errno = errno; Mmsg2(dev->errmsg, _("lseek_dev error on %s. ERR=%s.\n"), - dev->dev_name, be.strerror()); - return false; + dev->dev_name, be.strerror()); + return false; } dev->file = file; dev->block_num = block; @@ -1229,14 +1229,14 @@ reposition_dev(DEVICE *dev, uint32_t file, uint32_t block) if (file < dev->file) { Dmsg0(100, "Rewind_dev\n"); if (!rewind_dev(dev)) { - return false; + return false; } } if (file > dev->file) { Dmsg1(100, "fsf %d\n", file-dev->file); if (!fsf_dev(dev, file-dev->file)) { Dmsg1(100, "fsf failed! ERR=%s\n", strerror_dev(dev)); - return false; + return false; } Dmsg2(100, "wanted_file=%d at_file=%d\n", file, dev->file); } @@ -1261,7 +1261,7 @@ reposition_dev(DEVICE *dev, uint32_t file, uint32_t block) /* * Write an end of file on the device * Returns: 0 on success - * non-zero on failure + * non-zero on failure */ int weof_dev(DEVICE *dev, int num) @@ -1300,7 +1300,7 @@ weof_dev(DEVICE *dev, int num) clrerror_dev(dev, MTWEOF); if (stat == -1) { Mmsg2(dev->errmsg, _("ioctl MTWEOF error on %s. ERR=%s.\n"), - dev->dev_name, be.strerror()); + dev->dev_name, be.strerror()); } } return stat; @@ -1330,7 +1330,7 @@ clrerror_dev(DEVICE *dev, int func) struct mtget mt_stat; char buf[100]; - dev->dev_errno = errno; /* save errno */ + dev->dev_errno = errno; /* save errno */ if (errno == EIO) { dev->VolCatInfo.VolCatErrors++; } @@ -1342,60 +1342,60 @@ clrerror_dev(DEVICE *dev, int func) switch (func) { case -1: Emsg0(M_ABORT, 0, "Got ENOTTY on read/write!\n"); - break; + break; case MTWEOF: msg = "WTWEOF"; - dev->capabilities &= ~CAP_EOF; /* turn off feature */ - break; + dev->capabilities &= ~CAP_EOF; /* turn off feature */ + break; #ifdef MTEOM case MTEOM: msg = "WTEOM"; - dev->capabilities &= ~CAP_EOM; /* turn off feature */ - break; + dev->capabilities &= ~CAP_EOM; /* turn off feature */ + break; #endif case MTFSF: msg = "MTFSF"; - dev->capabilities &= ~CAP_FSF; /* turn off feature */ - break; + dev->capabilities &= ~CAP_FSF; /* turn off feature */ + break; case MTBSF: msg = "MTBSF"; - dev->capabilities &= ~CAP_BSF; /* turn off feature */ - break; + dev->capabilities &= ~CAP_BSF; /* turn off feature */ + break; case MTFSR: msg = "MTFSR"; - dev->capabilities &= ~CAP_FSR; /* turn off feature */ - break; + dev->capabilities &= ~CAP_FSR; /* turn off feature */ + break; case MTBSR: msg = "MTBSR"; - dev->capabilities &= ~CAP_BSR; /* turn off feature */ - break; + dev->capabilities &= ~CAP_BSR; /* turn off feature */ + break; case MTREW: msg = "MTREW"; - break; + break; #ifdef MTSETBLK case MTSETBLK: msg = "MTSETBLK"; - break; + break; #endif #ifdef MTSETBSIZ case MTSETBSIZ: msg = "MTSETBSIZ"; - break; + break; #endif #ifdef MTSRSZ case MTSRSZ: msg = "MTSRSZ"; - break; + break; #endif default: bsnprintf(buf, sizeof(buf), "unknown func code %d", func); - msg = buf; - break; + msg = buf; + break; } if (msg != NULL) { - dev->dev_errno = ENOSYS; + dev->dev_errno = ENOSYS; Mmsg1(dev->errmsg, _("I/O function \"%s\" not supported on this device.\n"), msg); - Emsg0(M_ERROR, 0, dev->errmsg); + Emsg0(M_ERROR, 0, dev->errmsg); } } /* On some systems such as NetBSD, this clears all errors */ @@ -1466,7 +1466,7 @@ static void do_close(DEVICE *dev) get_filename(dev, dev->VolCatInfo.VolCatName, archive_name); /* Check that the part file is empty */ if ((stat(archive_name.c_str(), &statp) == 0) && (statp.st_size == 0)) { - unlink(archive_name.c_str()); + unlink(archive_name.c_str()); } } @@ -1547,7 +1547,7 @@ bool truncate_dev(DEVICE *dev) dev->num_parts = 0; dev->VolCatInfo.VolCatParts = 0; if (open_first_part(dev) < 0) { - berrno be; + berrno be; Mmsg1(&dev->errmsg, "Unable to truncate device, because I'm unable to open the first part. ERR=%s\n", be.strerror()); } } @@ -1584,12 +1584,19 @@ dev_can_write(DEVICE *dev) } } +/* 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) { @@ -1652,7 +1659,7 @@ void init_dev_wait_timers(DEVICE *dev) /* ******FIXME******* put these on config variables */ dev->min_wait = 60 * 60; dev->max_wait = 24 * 60 * 60; - dev->max_num_wait = 9; /* 5 waits =~ 1 day, then 1 day at a time */ + dev->max_num_wait = 9; /* 5 waits =~ 1 day, then 1 day at a time */ dev->wait_sec = dev->min_wait; dev->rem_wait_sec = dev->wait_sec; dev->num_wait = 0; @@ -1662,11 +1669,11 @@ void init_dev_wait_timers(DEVICE *dev) /* * Returns: true if time doubled - * false if max time expired + * false if max time expired */ bool double_dev_wait_time(DEVICE *dev) { - dev->wait_sec *= 2; /* double wait time */ + dev->wait_sec *= 2; /* double wait time */ if (dev->wait_sec > dev->max_wait) { /* but not longer than maxtime */ dev->wait_sec = dev->max_wait; } @@ -1687,18 +1694,18 @@ void set_os_device_parameters(DEVICE *dev) mt_com.mt_op = MTSETBLK; mt_com.mt_count = 0; if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) { - clrerror_dev(dev, MTSETBLK); + clrerror_dev(dev, MTSETBLK); } mt_com.mt_op = MTSETDRVBUFFER; mt_com.mt_count = MT_ST_CLEARBOOLEANS; if (!dev_cap(dev, CAP_TWOEOF)) { - mt_com.mt_count |= MT_ST_TWO_FM; + mt_com.mt_count |= MT_ST_TWO_FM; } if (dev_cap(dev, CAP_EOM)) { - mt_com.mt_count |= MT_ST_FAST_MTEOM; + mt_com.mt_count |= MT_ST_FAST_MTEOM; } if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) { - clrerror_dev(dev, MTSETBLK); + clrerror_dev(dev, MTSETBLK); } } return; @@ -1711,13 +1718,13 @@ void set_os_device_parameters(DEVICE *dev) mt_com.mt_op = MTSETBSIZ; mt_com.mt_count = 0; if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) { - clrerror_dev(dev, MTSETBSIZ); + clrerror_dev(dev, MTSETBSIZ); } /* Get notified at logical end of tape */ mt_com.mt_op = MTEWARN; mt_com.mt_count = 1; if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) { - clrerror_dev(dev, MTEWARN); + clrerror_dev(dev, MTEWARN); } } return; @@ -1730,7 +1737,7 @@ void set_os_device_parameters(DEVICE *dev) mt_com.mt_op = MTSETBSIZ; mt_com.mt_count = 0; if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) { - clrerror_dev(dev, MTSETBSIZ); + clrerror_dev(dev, MTSETBSIZ); } } return; @@ -1743,7 +1750,7 @@ void set_os_device_parameters(DEVICE *dev) mt_com.mt_op = MTSRSZ; mt_com.mt_count = 0; if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) { - clrerror_dev(dev, MTSRSZ); + clrerror_dev(dev, MTSRSZ); } } return; @@ -1753,6 +1760,6 @@ void set_os_device_parameters(DEVICE *dev) static bool dev_get_os_pos(DEVICE *dev, struct mtget *mt_stat) { return dev_cap(dev, CAP_MTIOCGET) && - ioctl(dev->fd, MTIOCGET, (char *)mt_stat) == 0 && - mt_stat->mt_fileno >= 0; + ioctl(dev->fd, MTIOCGET, (char *)mt_stat) == 0 && + mt_stat->mt_fileno >= 0; } diff --git a/bacula/src/stored/dev.h b/bacula/src/stored/dev.h index a88f14291f..4f562e7539 100644 --- a/bacula/src/stored/dev.h +++ b/bacula/src/stored/dev.h @@ -233,6 +233,9 @@ public: 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 */ @@ -260,6 +263,7 @@ public: 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(); @@ -279,7 +283,7 @@ inline int DEVICE::is_dvd() const { return state & ST_DVD; } 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; } @@ -326,6 +330,7 @@ public: 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 */ diff --git a/bacula/src/stored/job.c b/bacula/src/stored/job.c index 560c98b2ed..a99dbb7b40 100644 --- a/bacula/src/stored/job.c +++ b/bacula/src/stored/job.c @@ -43,7 +43,7 @@ static char jobcmd[] = "JobId=%d job=%127s job_name=%127s client_name=%127s " "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"; @@ -54,9 +54,12 @@ static char NO_device[] = "3924 Device \"%s\" not in SD Device resources.\n"; 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"; @@ -82,13 +85,14 @@ bool job_cmd(JCR *jcr) /* * Get JobId and permissions from Director */ - Dmsg1(100, "Job_cmd: %s\n", dir->msg); + Dmsg1(100, "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; @@ -132,7 +136,7 @@ bool job_cmd(JCR *jcr) */ 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; @@ -143,7 +147,6 @@ bool use_cmd(JCR *jcr) /* * 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)); @@ -263,17 +266,18 @@ static bool use_device_cmd(JCR *jcr) 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, "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); @@ -295,11 +299,13 @@ static bool use_device_cmd(JCR *jcr) " 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); @@ -307,6 +313,7 @@ static bool use_device_cmd(JCR *jcr) 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); @@ -315,12 +322,15 @@ static bool use_device_cmd(JCR *jcr) } 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; } } @@ -348,6 +358,7 @@ static bool use_device_cmd(JCR *jcr) 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; } @@ -371,7 +382,9 @@ static bool use_device_cmd(JCR *jcr) 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 */ } @@ -387,6 +400,7 @@ static bool use_device_cmd(JCR *jcr) " 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); @@ -395,6 +409,7 @@ static bool use_device_cmd(JCR *jcr) } 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 */ @@ -415,10 +430,11 @@ bool query_cmd(JCR *jcr) 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, "msg); if (ok) { unbash_spaces(dev_name); LockRes(); @@ -437,7 +453,7 @@ bool query_cmd(JCR *jcr) 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); @@ -446,13 +462,19 @@ bool query_cmd(JCR *jcr) 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) { @@ -460,11 +482,15 @@ bool query_cmd(JCR *jcr) 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 */ @@ -472,10 +498,12 @@ bool query_cmd(JCR *jcr) 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; diff --git a/bacula/src/version.h b/bacula/src/version.h index eb3e1f6eda..c1c4f7f117 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -1,8 +1,8 @@ /* */ #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 -- 2.39.5