]> git.sur5r.net Git - bacula/bacula/commitdiff
Fix watchdog deadlog + restore soft link bug
authorKern Sibbald <kern@sibbald.com>
Sat, 7 Feb 2004 17:25:23 +0000 (17:25 +0000)
committerKern Sibbald <kern@sibbald.com>
Sat, 7 Feb 2004 17:25:23 +0000 (17:25 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@1030 91ce42f0-d328-0410-95d8-f526ca767f89

26 files changed:
bacula/ChangeLog
bacula/examples/backup-every-other-week.txt
bacula/examples/backup-to-cdwriter.txt
bacula/examples/upgrade-win32-client.txt [new file with mode: 0644]
bacula/kernstodo
bacula/src/dird/job.c
bacula/src/dird/ua_cmds.c
bacula/src/dird/ua_run.c
bacula/src/dird/ua_status.c
bacula/src/dird/ua_tree.c
bacula/src/findlib/attribs.c
bacula/src/findlib/protos.h
bacula/src/jcr.h
bacula/src/lib/jcr.c
bacula/src/lib/mem_pool.c
bacula/src/lib/tree.c
bacula/src/lib/tree.h
bacula/src/lib/watchdog.c
bacula/src/stored/block.c
bacula/src/stored/btape.c
bacula/src/stored/butil.c
bacula/src/stored/dev.c
bacula/src/stored/device.c
bacula/src/stored/dircmd.c
bacula/src/stored/protos.h
bacula/src/version.h

index 42f8e45ae19fafd41fee7e907d3e528d9f35aa83..4e1851b4aa496b06f83a8f2d8639b3fe4978bf2e 100644 (file)
@@ -1,5 +1,24 @@
 
 
+07Feb04
+- Added backup to cdwriter script to examples provided by Johan Decock.
+- Fixed a bug where ls really did lsmark (just invert command table
+  entries).
+- Fix bug where a soft linked file and a directory had the same name
+  by treating the soft link as a directory and putting the entries under
+  it. This fixes the bug reported by Alexander Mueller.
+- Fix a deadlock situation in the new watchdog code where the 
+  watchdog locks its semaphore, and attempts to lock the jcr_chain,
+  but another thread has locked the jcr_chain and wants to free a
+  watchdog, which tries to lock the watchdog semaphore -- deadlock!
+  Used read/write locks to solve the problem. 
+- Improved the error messages when I/O errors or buffer id errors
+  are detected, and prevent non-sense errors from being printed.
+- Fix some incorrect messages in restore if no name is supplied
+  on the command line (e.g. pool= ).
+- Add the third digit to the release version number.
+04Feb04
+- Add -l option to bls that causes it to ignore tape label errors.
 03Feb04
 - Correct problems with jobs scheduled at a later time by hand.
   Missing unlock(), backward test on pthread_create status.
index f2f91730ba7a8815a1cf9cb26a28bea1ab926f1d..b26a456abc5f4a5cc0030b4586fac85859f23b4c 100644 (file)
@@ -1,11 +1,7 @@
 
-From bacula-users-admin@lists.sourceforge.net Wed Aug 13 19:22:21 2003
 From: Robert L Mathews <lists@tigertech.com>
 To: <bacula-users@lists.sourceforge.net>
-Content-Type: text/plain; charset="US-ASCII"
-Message-Id: <20030813170422.E48403FC65F@fry.tigertech.net>
 Subject: [Bacula-users] Making Backups Run Every Other Week
-Sender: bacula-users-admin@lists.sourceforge.net
 Date: Wed, 13 Aug 2003 10:04:23 -0700
 
 In case anyone is interested, here's a tip I came up with.
@@ -78,15 +74,3 @@ while before coming up with this.
 
 -- 
 Robert L Mathews, Tiger Technologies
-
-
-
--------------------------------------------------------
-This SF.Net email sponsored by: Free pre-built ASP.NET sites including
-Data Reports, E-commerce, Portals, and Forums are available now.
-Download today and enter to win an XBOX or Visual Studio .NET.
-http://aspnet.click-url.com/go/psa00100003ave/direct;at.aspnet_072303_01/01
-_______________________________________________
-Bacula-users mailing list
-Bacula-users@lists.sourceforge.net
-https://lists.sourceforge.net/lists/listinfo/bacula-users
index 5d49b1bd0d4029eb3e31ed04412fa65e25b704bf..c0f85112d0af78452af0c7c985c793a6a397956c 100644 (file)
@@ -1,68 +1,15 @@
-From bacula-users-admin@lists.sourceforge.net Sat Jan 31 05:42:42 2004
-Return-Path: <bacula-users-admin@lists.sourceforge.net>
-Received: from sc8-sf-list2.sourceforge.net (lists.sourceforge.net
-       [66.35.250.206]) by matou.sibbald.com (8.12.10/8.12.10) with ESMTP id
-       i0V4ggtH005859 for <kern@sibbald.com>; Sat, 31 Jan 2004 05:42:42 +0100
-Received: from localhost ([127.0.0.1] helo=projects.sourceforge.net) by
-       sc8-sf-list2.sourceforge.net with esmtp (Exim 4.30) id 1Amms2-0004RT-4e;
-       Fri, 30 Jan 2004 20:36:38 -0800
-Received: from sc8-sf-mx1-b.sourceforge.net ([10.3.1.11]
-       helo=sc8-sf-mx1.sourceforge.net) by sc8-sf-list2.sourceforge.net with esmtp
-       (Exim 4.30) id 1Ammo5-0002Tt-2F for bacula-users@lists.sourceforge.net;
-       Fri, 30 Jan 2004 20:32:33 -0800
-Received: from www.abis.be ([195.0.32.120] helo=xenophon.abis.be) by
-       sc8-sf-mx1.sourceforge.net with esmtp (Exim 4.30) id 1AmbFN-0008Hu-99 for
-       bacula-users@lists.sourceforge.net; Fri, 30 Jan 2004 08:11:57 -0800
-Received: from tosfeb32.abis.be ([194.78.5.1]) by xenophon.abis.be
-       (8.11.6/8.11.6) with SMTP id i0UGBI715849 for
-       <bacula-users@lists.sourceforge.net>; Fri, 30 Jan 2004 17:11:18 +0100
-Received: by tosfeb32.abis.be(Lotus SMTP MTA v4.6.5  (863.2 5-20-1999))  id
-       C1256E2B.0058F4EE ; Fri, 30 Jan 2004 17:11:38 +0100
-X-Lotus-FromDomain: ABIS
 From: "Johan Decock" <jdecock@abis.be>
 To: bacula-users@lists.sourceforge.net
-Message-ID: <C1256E2B.0058F381.00@tosfeb32.abis.be>
 Subject: Re: [Bacula-users] cdwriter
-Mime-Version: 1.0
-Content-type: multipart/mixed;  Boundary="0__=dQlRuu8umGKzn67woQcbAbtp1kVJLJuYIqUZPSjcX1GgjEHuWdvHDqOX"
-Content-Disposition: inline
-X-Spam-Score: 1.1 (+)
-X-Spam-Report: Spam Filtering performed by sourceforge.net. See
-       http://spamassassin.org/tag/ for more details. Report problems to
-       http://sf.net/tracker/?func=add&group_id=1&atid=200001 1.1
-       MIME_BASE64_LATIN      RAW: Latin alphabet text using base64 encoding
-Sender: bacula-users-admin@lists.sourceforge.net
-Errors-To: bacula-users-admin@lists.sourceforge.net
-X-BeenThere: bacula-users@lists.sourceforge.net
-X-Mailman-Version: 2.0.9-sf.net
-Precedence: bulk
-List-Unsubscribe:
-       <https://lists.sourceforge.net/lists/listinfo/bacula-users>,
-       <mailto:bacula-users-request@lists.sourceforge.net?subject=unsubscribe>
-List-Id: Bacula user's email list for support and discussions
-       <bacula-users.lists.sourceforge.net>
-List-Post: <mailto:bacula-users@lists.sourceforge.net>
-List-Help: <mailto:bacula-users-request@lists.sourceforge.net?subject=help>
-List-Subscribe:
-       <https://lists.sourceforge.net/lists/listinfo/bacula-users>,
-       <mailto:bacula-users-request@lists.sourceforge.net?subject=subscribe>
-List-Archive:
-       <http://sourceforge.net/mailarchive/forum.php?forum=bacula-users>
 Date: Fri, 30 Jan 2004 17:11:34 +0100
 
+I thought it would be easy to find them in the archives.  I'll post them
+again.  I changed some things in them anyway in the mean time.  I also
+include the Director config.  Then you see how they are to be used in
+Runbefore- and RunafterJobs
 
---0__=dQlRuu8umGKzn67woQcbAbtp1kVJLJuYIqUZPSjcX1GgjEHuWdvHDqOX
-Content-type: text/plain; charset=us-ascii
-Content-Disposition: inline
-Content-Transfer-Encoding: 8bit
-
-
-
-Hi Alex,
-
-I thought it would be easy to find them in the archives. I'll post them again. I changed some things in them anyway in the mean time. I also include the Director config. Then you see how they are to be used in Runbefore- and RunafterJobs
-
-I'm interested in any remarks or improvements you might have. (I'm still getting started in shell scripting)
+I'm interested in any remarks or improvements you might have.  (I'm
+still getting started in shell scripting)
 
 
 #
@@ -859,93 +806,8 @@ else
   echo "hello"
 fi
 
-# This is run as a RunAfterJob of the catalog backup. It already had a RunAfterJob, so we execute that here
-/etc/bacula/delete_catalog_backup
-
-
-
-
-
-
-From: "Alex Federau" <alex.federau@gmx.ch> on 30/01/2004 15:57 GMT
-
-To:   Johan Decock/Abis@Abis
-cc:
-Subject:  Re: [Bacula-users] cdwriter
-
-
-
---0__=dQlRuu8umGKzn67woQcbAbtp1kVJLJuYIqUZPSjcX1GgjEHuWdvHDqOX
-Content-type: text/plain; charset=iso-8859-1
-Content-Disposition: inline
-Content-Transfer-Encoding: 8bit
-
-
-Hi Johan,
-Could you send me the scripts or tell me where they are located. I am
-browsing the mail archive,
-and while I can find several of your mails, I am unable to find your
-scripts. Probably they would be very useful for us.
-
-Cheers
-Alex
-
-
->
->
-> Hi Alex,
->
-> Bacula isn't able to write to CD-R or DVD+/-R directly. This isn't needed
-> though. If you look in the mailing list archive, you will find that I have
-> implemented a solution where the backup volume files are written to DVD+R
-> with some bash scripts. A caveat is that files on an ISO9660 can't be
-larger
-> than 2 GB (Not on Linux anyway). This has kept me busy for a while,
-> looking what was going on and why I wasn't able to read back my DVD's.
->
-> I hope my scripts are of help to you.
->
-> Johan
->
->
->
->
-> From: "Alex Federau" <alex.federau@gmx.ch> on 30/01/2004 14:29 GMT
->
-> To:   bacula-users@lists.sourceforge.net
-> cc:    (bcc: Johan Decock/Abis)
-> Subject:  [Bacula-users] cdwriter
->
->
->
-
---
-+++ Mailpower für Multimedia-Begeisterte: http://www.gmx.net/topmail +++
-250 MB Mailbox, 1 GB Online-Festplatte, 100 FreeSMS. Jetzt kostenlos testen!
-
-
-
-
-
-
-
-
---------------------------------------------------------------------------
-ABIS Training & Consulting
-website: http://www.abis.be   -   e-mail: training@abis.be
-tel: Belgium: (+32)-16-245610   -   The Netherlands: (+31)-348-435570
-fax: Belgium: (+32)-16-245691   -   The Netherlands: (+31)-348-432493
---------------------------------------------------------------------------
---0__=dQlRuu8umGKzn67woQcbAbtp1kVJLJuYIqUZPSjcX1GgjEHuWdvHDqOX--
-
+# This is run as a RunAfterJob of the catalog backup.  It already had a
+# RunAfterJob, so we execute that here 
 
+/etc/bacula/delete_catalog_backup
 
--------------------------------------------------------
-The SF.Net email is sponsored by EclipseCon 2004
-Premiere Conference on Open Tools Development and Integration
-See the breadth of Eclipse activity. February 3-5 in Anaheim, CA.
-http://www.eclipsecon.org/osdn
-_______________________________________________
-Bacula-users mailing list
-Bacula-users@lists.sourceforge.net
-https://lists.sourceforge.net/lists/listinfo/bacula-users
diff --git a/bacula/examples/upgrade-win32-client.txt b/bacula/examples/upgrade-win32-client.txt
new file mode 100644 (file)
index 0000000..3ffe0ef
--- /dev/null
@@ -0,0 +1,68 @@
+From: "Michel Meyers" <steltek@tcnnet.dyndns.org>
+To: "bacula-users" <bacula-users@lists.sourceforge.net>
+Subject: [Bacula-users] Script for pushing new clients to Windows boxes
+Date: Mon, 2 Feb 2004 16:10:48 +0100
+
+Hello,
+
+Some of you may remember my document on how to remotely push a Win32 bacula
+client onto a WinNT/2k/XP box. Well, I've written a script to do it for me
+and thought I'd share it with you:
+- ----------------------------------------------------------------
+#!/bin/bash
+#
+# Remote Win32 client upgrade script
+# written by Michel Meyers (last update 02/02/04 16:10)
+#
+# WARNING: Make sure that no bacula-fd.conf exists in the source directory!
+# You will destroy/overwrite all your client's configs if you don't
+# be careful with this.
+#
+# The upgrade function does the following:
+# - Shutdown Bacula service on remote machine
+# - Wait 30 seconds (to allow proper shutdown)
+# - Mount C: drive of remote box
+# - Copy new client to remote machine
+# - Unmount C;
+# - Startup the new Bacula service
+#
+# To upgrade a machine append the following at the bottom of this file:
+#
+# SERVERNAME=<hostname>
+# USERNAME=<username>
+# PASSWORD=<password, "" for blank>
+# upgrade
+
+upgrade() {
+rpcclient -S $SERVERNAME -U $USERNAME%"$PASSWORD" -c "service stop bacula"
+sleep 30
+smbmount //$SERVERNAME/c$ /mnt -o username=$USERNAME,password="$PASSWORD"
+cp /home/michel/winbacula/bin/* /mnt/bacula/bin
+umount /mnt
+rpcclient -S $SERVERNAME -U $USERNAME%"$PASSWORD" -c "service start bacula"
+}
+
+SERVERNAME=xerxes
+USERNAME=administrator
+PASSWORD=secret
+upgrade
+
+SERVERNAME=shodan
+USERNAME=teh_one
+PASSWORD=""
+upgrade
+- ----------------------------------------------------------------
+
+It should be pretty self-explanatory. I'm not good at shell programming and
+I don't know whether there's any notion of arrays or 'for' loops that could
+make it cleaner so I simply wrote a function which references some variables
+and then call that repeatedly (once per machine). You can of course change
+the values according to your system and liking (if 30 secs seem to much for
+you, just reduce the value after sleep, make sure to check on the paths and
+mountpoint /mnt may not be usable on your system, ...)
+
+Note: The requirements are the same as described in my other document
+(Samba-TNG clients among others, otherwise you'll be missing rpcclient).
+
+Enjoy!
+
index 063e0a9af149e4871569211e4c0fb3bfa9c1e6a3..d4c627a5ea07e49a65946201da3e65517643912b 100644 (file)
@@ -70,6 +70,10 @@ For 1.33 Testing/Documentation:
      http://howtos.linux.com/guides/nag2/x-087-2-nfs.mountd.shtml
 
 For 1.33
+- Have each daemon save the last_jobs structure when exiting and
+  read it back in when starting up.
+- "restore jobid=1 select" calls get_storage_xxx, which prints "JobId 1 is
+  not running."
 - Add FromClient and ToClient keywords on restore command (or
   BackupClient RestoreClient).
 - Automatic "update slots" on user configuration directive when a
index b0f5467f6ce2989186da2681699cb0b3cbb73eca..051a540447bf943fec92f2e7ff9c8c288b829763 100644 (file)
@@ -83,13 +83,13 @@ static void job_monitor_watchdog(watchdog_t *self)
 {
    JCR *control_jcr, *jcr;
 
-   control_jcr = (JCR *) self->data;
+   control_jcr = (JCR *)self->data;
 
    Dmsg1(400, "job_monitor_watchdog %p called\n", self);
 
    lock_jcr_chain();
 
-   for (jcr = NULL; (jcr = get_next_jcr(jcr)); /* nothing */) {
+   foreach_jcr(jcr) {
       bool cancel;
 
       if (jcr->JobId == 0) {
index 954ac237f614126fac884f2b998b5b22a65c448c..1d89432a78e992b9b22df3c5bb85328cc63e92d3 100644 (file)
@@ -388,13 +388,13 @@ static int cancel_cmd(UAContext *ua, char *cmd)
    if (!jcr) {
       /* Count Jobs running */
       lock_jcr_chain();
-      for (jcr=NULL; (jcr=get_next_jcr(jcr)); njobs++) {
+      foreach_jcr(jcr) {
         if (jcr->JobId == 0) {      /* this is us */
            free_locked_jcr(jcr);
-           njobs--;
            continue;
         }
         free_locked_jcr(jcr);
+        njobs++;
       }
       unlock_jcr_chain();
 
@@ -404,7 +404,7 @@ static int cancel_cmd(UAContext *ua, char *cmd)
       }
       start_prompt(ua, _("Select Job:\n"));
       lock_jcr_chain();
-      for (jcr=NULL; (jcr=get_next_jcr(jcr)); ) {
+      foreach_jcr(jcr) {
         if (jcr->JobId == 0) {      /* this is us */
            free_locked_jcr(jcr);
            continue;
@@ -1674,13 +1674,14 @@ int quit_cmd(UAContext *ua, char *cmd)
  */
 int wait_cmd(UAContext *ua, char *cmd) 
 {
+   JCR *jcr;
    bmicrosleep(0, 200000);           /* let job actually start */
-   for (int running=1; running; ) {
-      running = 0;
+   for (bool running=true; running; ) {
+      running = false;
       lock_jcr_chain();
-      for (JCR *jcr=NULL; (jcr=get_next_jcr(jcr)); ) {
+      foreach_jcr(jcr) {
         if (jcr->JobId != 0) {
-           running = 1;
+           running = true;
            free_locked_jcr(jcr);
            break;
         }
index 275340955668f3a4ce9ac1559b70ee3d27e96397..747b62d2761a30d5a1ae5947c1c4b7f96eaf8bf3 100644 (file)
@@ -258,7 +258,9 @@ int run_cmd(UAContext *ua, char *cmd)
       /* Find Job */
       job = (JOB *)GetResWithName(R_JOB, job_name);
       if (!job) {
-         bsendmsg(ua, _("Job \"%s\" not found\n"), job_name);
+        if (*job_name != 0) {
+            bsendmsg(ua, _("Job \"%s\" not found\n"), job_name);
+        }
         job = select_job_resource(ua);
       } else {
          Dmsg1(200, "Found job=%s\n", job_name);
@@ -274,7 +276,9 @@ int run_cmd(UAContext *ua, char *cmd)
    if (store_name) {
       store = (STORE *)GetResWithName(R_STORAGE, store_name);
       if (!store) {
-         bsendmsg(ua, _("Storage \"%s\" not found.\n"), store_name);
+        if (*store_name != 0) {
+            bsendmsg(ua, _("Storage \"%s\" not found.\n"), store_name);
+        }
         store = select_storage_resource(ua);
       }
    } else {
@@ -288,7 +292,9 @@ int run_cmd(UAContext *ua, char *cmd)
    if (pool_name) {
       pool = (POOL *)GetResWithName(R_POOL, pool_name);
       if (!pool) {
-         bsendmsg(ua, _("Pool \"%s\" not found.\n"), pool_name);
+        if (*pool_name != 0) {
+            bsendmsg(ua, _("Pool \"%s\" not found.\n"), pool_name);
+        }
         pool = select_pool_resource(ua);
       }
    } else {
@@ -301,7 +307,9 @@ int run_cmd(UAContext *ua, char *cmd)
    if (client_name) {
       client = (CLIENT *)GetResWithName(R_CLIENT, client_name);
       if (!client) {
-         bsendmsg(ua, _("Client \"%s\" not found.\n"), client_name);
+        if (*client_name != 0) {
+            bsendmsg(ua, _("Client \"%s\" not found.\n"), client_name);
+        }
         client = select_client_resource(ua);
       }
    } else {
index 754b0199f89bc932d990096be25433d81ff7a1b7..7a8a47d147cf5dec5e8937596fccab37f0b659ec 100644 (file)
@@ -391,7 +391,8 @@ static void list_running_jobs(UAContext *ua)
 
    Dmsg0(200, "enter list_run_jobs()\n");
    lock_jcr_chain();
-   for (jcr=NULL; (jcr=get_next_jcr(jcr)); njobs++) {
+   foreach_jcr(jcr) {
+      njobs++;
       if (jcr->JobId == 0) {     /* this is us */
         /* this is a console or other control job. We only show console
          * jobs in the status output.
@@ -414,12 +415,12 @@ static void list_running_jobs(UAContext *ua)
    bsendmsg(ua, _("\nRunning Jobs:\n"));
    bsendmsg(ua, _("Level JobId  Job                        Status\n"));
    bsendmsg(ua, _("====================================================================\n"));
-   for (jcr=NULL; (jcr=get_next_jcr(jcr)); njobs++) {
+   foreach_jcr(jcr) {
       if (jcr->JobId == 0 || !acl_access_ok(ua, Job_ACL, jcr->job->hdr.name)) {
-        njobs--;
         free_locked_jcr(jcr);
         continue;
       }
+      njobs++;
       switch (jcr->JobStatus) {
       case JS_Created:
          msg = _("is waiting execution");
index b7641f9b3cc1d932c7431970818df45b84963e5f..7bc68576cf807a66ce5694eec18fe7891c6d1515 100644 (file)
@@ -64,8 +64,8 @@ static struct cmdstruct commands[] = {
  { N_("exit"),       donecmd,      _("exit = done")},
  { N_("find"),       findcmd,      _("find files -- wildcards allowed")},
  { N_("help"),       helpcmd,      _("print help")},
- { N_("lsmark"),     lsmarkcmd,    _("list the marked files in and below the cd")},    
  { N_("ls"),         lscmd,        _("list current directory -- wildcards allowed")},    
+ { N_("lsmark"),     lsmarkcmd,    _("list the marked files in and below the cd")},    
  { N_("mark"),       markcmd,      _("mark file to be restored")},
  { N_("markdir"),    markdircmd,   _("mark directory entry to be restored -- nonrecursive")},
  { N_("pwd"),        pwdcmd,       _("print current working directory")},
@@ -149,10 +149,12 @@ bool user_select_files_from_tree(TREE_CTX *tree)
  */
 int insert_tree_handler(void *ctx, int num_fields, char **row)
 {
+   struct stat statp;
    TREE_CTX *tree = (TREE_CTX *)ctx;
    char fname[5000];
    TREE_NODE *node, *new_node;
    int type;
+   bool hard_link;
 
    strip_trailing_junk(row[1]);
    if (*row[1] == 0) {               /* no filename => directory */
@@ -164,29 +166,32 @@ int insert_tree_handler(void *ctx, int num_fields, char **row)
    } else {
       type = TN_FILE;
    }
-   bsnprintf(fname, sizeof(fname), "%s%s", row[0], row[1]);
    if (tree->avail_node) {
-      node = tree->avail_node;
+      node = tree->avail_node;       /* if prev node avail use it */
    } else {
-      node = new_tree_node(tree->root, type);
+      node = new_tree_node(tree->root, type);  /* get new node */
       tree->avail_node = node;
    }
+   hard_link = (decode_LinkFI(row[4], &statp) != 0);
+   bsnprintf(fname, sizeof(fname), "%s%s%s", row[0], row[1], "");
+//    S_ISLNK(statp.st_mode)?" ->":"");
    Dmsg3(200, "FI=%d type=%d fname=%s\n", node->FileIndex, type, fname);
    new_node = insert_tree_node(fname, node, tree->root, NULL);
    /* Note, if node already exists, save new one for next time */
    if (new_node != node) {
-      tree->avail_node = node;
+      tree->avail_node = node;       /* node already exists */
    } else {
-      tree->avail_node = NULL;
+      tree->avail_node = NULL;       /* added node to tree */
    }
    new_node->FileIndex = atoi(row[2]);
    new_node->JobId = (JobId_t)str_to_int64(row[3]);
    new_node->type = type;
    new_node->extract = true;         /* extract all by default */
+   new_node->hard_link = hard_link;
+   new_node->soft_link = S_ISLNK(statp.st_mode) != 0;
    if (type == TN_DIR || type == TN_DIR_NLS) {
       new_node->extract_dir = true;   /* if dir, extract it */
    }
-   new_node->have_link = (decode_LinkFI(row[4]) != 0);
    tree->cnt++;
    return 0;
 }
@@ -212,7 +217,7 @@ static int set_extract(UAContext *ua, TREE_NODE *node, TREE_CTX *tree, bool extr
       count++;
    }
    /* For a non-file (i.e. directory), we see all the children */
-   if (node->type != TN_FILE) {
+   if (node->type != TN_FILE || (node->soft_link && node->child)) {
       /* Recursive set children within directory */
       for (n=node->child; n; n=n->sibling) {
         count += set_extract(ua, n, tree, extract);
@@ -237,7 +242,7 @@ static int set_extract(UAContext *ua, TREE_NODE *node, TREE_CTX *tree, bool extr
       tree_getpath(node, cwd, sizeof(cwd));
       fdbr.FileId = 0;
       fdbr.JobId = node->JobId;
-      if (node->have_link && db_get_file_attributes_record(ua->jcr, ua->db, cwd, NULL, &fdbr)) {
+      if (node->hard_link && db_get_file_attributes_record(ua->jcr, ua->db, cwd, NULL, &fdbr)) {
         int32_t LinkFI;
         decode_stat(fdbr.LStat, &statp, &LinkFI); /* decode stat pkt */
         /*
@@ -379,10 +384,9 @@ static int lscmd(UAContext *ua, TREE_CTX *tree)
         } else if (node->extract_dir) {
             tag = "+";
         } else {
-               tag = "";
+            tag = "";
         }
-         bsendmsg(ua, "%s%s%s\n", tag, node->fname,
-            (node->type==TN_DIR||node->type==TN_NEWDIR)?"/":"");
+         bsendmsg(ua, "%s%s%s\n", tag, node->fname, node->child?"/":"");
       }
    }
    return 1;
@@ -409,8 +413,7 @@ static int lsmarkcmd(UAContext *ua, TREE_CTX *tree)
         } else {
             tag = "";
         }
-         bsendmsg(ua, "%s%s%s\n", tag, node->fname,
-            (node->type==TN_DIR||node->type==TN_NEWDIR)?"/":"");
+         bsendmsg(ua, "%s%s%s\n", tag, node->fname, node->child?"/":"");
       }
    }
    return 1;
@@ -454,8 +457,8 @@ static int dircmd(UAContext *ua, TREE_CTX *tree)
    TREE_NODE *node;
    FILE_DBR fdbr;
    struct stat statp;
-   char buf[1000];
-   char cwd[1100];
+   char buf[1100];
+   char cwd[1100], *pcwd;
 
    if (!tree->node->child) {    
       return 1;
@@ -473,19 +476,32 @@ static int dircmd(UAContext *ua, TREE_CTX *tree)
         tree_getpath(node, cwd, sizeof(cwd));
         fdbr.FileId = 0;
         fdbr.JobId = node->JobId;
-        if (db_get_file_attributes_record(ua->jcr, ua->db, cwd, NULL, &fdbr)) {
+        /*
+         * Strip / from soft links to directories.
+         *   This is because soft links to files have a trailing slash
+         *   when returned from tree_getpath, but db_get_file_attr...
+         *   treats soft links as files, so they do not have a trailing
+         *   slash like directory names.
+         */
+        if (node->type == TN_FILE && node->child) {
+           bstrncpy(buf, cwd, sizeof(buf));
+           pcwd = buf;
+           int len = strlen(buf);
+           if (len > 1) {
+              buf[len-1] = 0;        /* strip trailing / */
+           }
+        } else {
+           pcwd = cwd;
+        }
+        if (db_get_file_attributes_record(ua->jcr, ua->db, pcwd, NULL, &fdbr)) {
            int32_t LinkFI;
            decode_stat(fdbr.LStat, &statp, &LinkFI); /* decode stat pkt */
-           ls_output(buf, cwd, tag, &statp);
-            bsendmsg(ua, "%s\n", buf);
         } else {
            /* Something went wrong getting attributes -- print name */
-            if (*tag == ' ') {
-               tag = "";
-           }
-            bsendmsg(ua, "%s%s%s\n", tag, node->fname,
-               (node->type==TN_DIR||node->type==TN_NEWDIR)?"/":"");
+           memset(&statp, 0, sizeof(statp));
         }
+        ls_output(buf, cwd, tag, &statp);
+         bsendmsg(ua, "%s\n", buf);
       }
    }
    return 1;
index d16c3ec9644a6d6afdb2c0ba3ce7458ca8046cc6..87514c67c037c127fa997fc819ae1beae9f2630a 100755 (executable)
@@ -221,7 +221,7 @@ int decode_stat(char *buf, struct stat *statp, int32_t *LinkFI)
 }
 
 /* Decode a LinkFI field of encoded stat packet */
-int32_t decode_LinkFI(char *buf
+int32_t decode_LinkFI(char *buf, struct stat *statp)
 {
    char *p = buf;
    int64_t val;
@@ -230,7 +230,8 @@ int32_t decode_LinkFI(char *buf)
    p++;                              /* skip space */
    skip_nonspaces(&p);               /* st_ino */
    p++;
-   skip_nonspaces(&p);               /* st_mode */
+   p += from_base64(&val, p);
+   statp->st_mode = val;             /* st_mode */
    p++;
    skip_nonspaces(&p);               /* st_nlink */
    p++;
index 618b0f0d64c66a25b0f5049ff967b691d18222b9..4355b1260780702db664fd052a9e91aa24f6ad69 100644 (file)
@@ -26,7 +26,7 @@
 /* from attribs.c */
 void   encode_stat       (char *buf, FF_PKT *ff_pkt, int data_stream);
 int    decode_stat       (char *buf, struct stat *statp, int32_t *LinkFI);
-int32_t decode_LinkFI    (char *buf);
+int32_t decode_LinkFI    (char *buf, struct stat *statp);
 int    encode_attribsEx  (JCR *jcr, char *attribsEx, FF_PKT *ff_pkt);
 int    set_attributes    (JCR *jcr, ATTR *attr, BFILE *ofd);
 int    select_data_stream(FF_PKT *ff_pkt);
index 3dba8948d489b757c2fccb81e4f2829c00cd0822..2844d6da366e88b8dcd70b6994188a937c0a21f7 100644 (file)
    jcr->JobStatus == JS_ErrorTerminated || \
    jcr->JobStatus == JS_FatalError)
 
+#define foreach_jcr(jcr) \
+   for ((jcr)=NULL; ((jcr)=get_next_jcr(jcr)); ) 
+
+
 
 struct JCR;
 typedef void (JCR_free_HANDLER)(JCR *jcr);
index f3710da0032a03227402e048c2ccda63233cb0f2..aaff694372d03dbab9e5d3e466f2597e81d0eddf 100755 (executable)
@@ -44,16 +44,21 @@ dlist *last_jobs = NULL;
 
 static JCR *jobs = NULL;             /* pointer to JCR chain */
 
-/* Mutex for locking various jcr chains while updating */
-static pthread_mutex_t jcr_chain_mutex = PTHREAD_MUTEX_INITIALIZER;
+static brwlock_t lock;               /* lock for last jobs and JCR chain */
 
 void init_last_jobs_list()
 {
+   int errstat;
    struct s_last_job *job_entry;
    if (!last_jobs) {
       last_jobs = new dlist(job_entry, &job_entry->link);
       memset(&last_job, 0, sizeof(last_job));
    }
+   if ((errstat=rwl_init(&lock)) != 0) {
+      Emsg1(M_ABORT, 0, _("Unable to initialize jcr_chain lock. ERR=%s\n"), 
+           strerror(errstat));
+   }
+
 }
 
 void term_last_jobs_list()
@@ -66,18 +71,19 @@ void term_last_jobs_list()
       delete last_jobs;
       last_jobs = NULL;
    }
+   rwl_destroy(&lock);
 }
 
 void lock_last_jobs_list() 
 {
    /* Use jcr chain mutex */
-   P(jcr_chain_mutex);
+   lock_jcr_chain();
 }
 
 void unlock_last_jobs_list() 
 {
    /* Use jcr chain mutex */
-   V(jcr_chain_mutex);
+   unlock_jcr_chain();
 }
 
 /*
@@ -111,14 +117,14 @@ JCR *new_jcr(int size, JCR_free_HANDLER *daemon_free_jcr)
    sigfillset(&sigtimer.sa_mask);
    sigaction(TIMEOUT_SIGNAL, &sigtimer, NULL);
 
-   P(jcr_chain_mutex);
+   lock_jcr_chain();
    jcr->prev = NULL;
    jcr->next = jobs;
    if (jobs) {
       jobs->prev = jcr;
    }
    jobs = jcr;
-   V(jcr_chain_mutex);
+   unlock_jcr_chain();
    return jcr;
 }
 
@@ -232,11 +238,11 @@ void free_jcr(JCR *jcr)
 #endif
    struct s_last_job *je;
 
-   P(jcr_chain_mutex);
+   lock_jcr_chain();
    jcr->use_count--;                 /* decrement use count */
    Dmsg3(200, "Dec free_jcr 0x%x use_count=%d jobid=%d\n", jcr, jcr->use_count, jcr->JobId);
    if (jcr->use_count > 0) {         /* if in use */
-      V(jcr_chain_mutex);
+      unlock_jcr_chain();
       Dmsg2(200, "free_jcr 0x%x use_count=%d\n", jcr, jcr->use_count);
       return;
    }
@@ -263,7 +269,7 @@ void free_jcr(JCR *jcr)
       last_job.JobId = 0;            /* zap last job */
    }
    close_msg(NULL);                  /* flush any daemon messages */
-   V(jcr_chain_mutex);
+   unlock_jcr_chain();
    Dmsg0(200, "Exit free_jcr\n");
 }
 
@@ -296,7 +302,7 @@ JCR *get_jcr_by_id(uint32_t JobId)
 {
    JCR *jcr;      
 
-   P(jcr_chain_mutex);                 /* lock chain */
+   lock_jcr_chain();                   /* lock chain */
    for (jcr = jobs; jcr; jcr=jcr->next) {
       if (jcr->JobId == JobId) {
         P(jcr->mutex);
@@ -306,7 +312,7 @@ JCR *get_jcr_by_id(uint32_t JobId)
         break;
       }
    }
-   V(jcr_chain_mutex);
+   unlock_jcr_chain();
    return jcr; 
 }
 
@@ -319,7 +325,7 @@ JCR *get_jcr_by_session(uint32_t SessionId, uint32_t SessionTime)
 {
    JCR *jcr;      
 
-   P(jcr_chain_mutex);
+   lock_jcr_chain();
    for (jcr = jobs; jcr; jcr=jcr->next) {
       if (jcr->VolSessionId == SessionId && 
          jcr->VolSessionTime == SessionTime) {
@@ -330,7 +336,7 @@ JCR *get_jcr_by_session(uint32_t SessionId, uint32_t SessionTime)
         break;
       }
    }
-   V(jcr_chain_mutex);
+   unlock_jcr_chain();
    return jcr; 
 }
 
@@ -350,7 +356,7 @@ JCR *get_jcr_by_partial_name(char *Job)
    if (!Job) {
       return NULL;
    }
-   P(jcr_chain_mutex);
+   lock_jcr_chain();
    len = strlen(Job);
    for (jcr = jobs; jcr; jcr=jcr->next) {
       if (strncmp(Job, jcr->Job, len) == 0) {
@@ -361,7 +367,7 @@ JCR *get_jcr_by_partial_name(char *Job)
         break;
       }
    }
-   V(jcr_chain_mutex);
+   unlock_jcr_chain();
    return jcr; 
 }
 
@@ -379,7 +385,7 @@ JCR *get_jcr_by_full_name(char *Job)
    if (!Job) {
       return NULL;
    }
-   P(jcr_chain_mutex);
+   lock_jcr_chain();
    for (jcr = jobs; jcr; jcr=jcr->next) {
       if (strcmp(jcr->Job, Job) == 0) {
         P(jcr->mutex);
@@ -389,7 +395,7 @@ JCR *get_jcr_by_full_name(char *Job)
         break;
       }
    }
-   V(jcr_chain_mutex);
+   unlock_jcr_chain();
    return jcr; 
 }
 
@@ -416,7 +422,11 @@ void set_jcr_job_status(JCR *jcr, int JobStatus)
  */
 void lock_jcr_chain()
 {
-   P(jcr_chain_mutex);
+   int errstat;
+   if ((errstat=rwl_writelock(&lock)) != 0) {
+      Emsg1(M_ABORT, 0, "rwl_writelock failure. ERR=%s\n",
+          strerror(errstat));
+   }
 }
 
 /*
@@ -424,7 +434,11 @@ void lock_jcr_chain()
  */
 void unlock_jcr_chain()
 {
-   V(jcr_chain_mutex);
+   int errstat;
+   if ((errstat=rwl_writeunlock(&lock)) != 0) {
+      Emsg1(M_ABORT, 0, "rwl_writeunlock failure. ERR=%s\n",
+          strerror(errstat));
+   }
 }
 
 
@@ -472,7 +486,7 @@ static void jcr_timeout_check(watchdog_t *self)
     * blocked for more than specified max time.
     */
    lock_jcr_chain();
-   for (jcr=NULL; (jcr=get_next_jcr(jcr)); ) {
+   foreach_jcr(jcr) {
       free_locked_jcr(jcr);          /* OK to free now cuz chain is locked */
       if (jcr->JobId == 0) {
         continue;
index ff8b048092807b9225db5c547d969f47bbd5f5d8..74fb59bf738543c672324272c688644ef5f7623e 100644 (file)
@@ -134,7 +134,7 @@ POOLMEM *sm_get_memory(char *fname, int lineno, int32_t size)
    struct abufhead *buf;
    int pool = 0;
 
-   if ((buf = (struct abufhead *) sm_malloc(fname, lineno, size+HEAD_SIZE)) == NULL) {
+   if ((buf = (struct abufhead *)sm_malloc(fname, lineno, size+HEAD_SIZE)) == NULL) {
       Emsg1(M_ABORT, 0, "Out of memory requesting %d bytes\n", size);
    }
    buf->ablen = size;
index de1e7f25e91efc56112eec7c9ff76cbad5ae6647..e13ae8c33b1771b45d78e7e2f7eb4eb2f8d6f73d 100755 (executable)
@@ -32,6 +32,9 @@
 #define MAXPATHLEN 1000
 #endif
 
+/*
+ * NOTE !!!!! we turn off Debug messages for performance reasons.
+ */
 #undef Dmsg0
 #undef Dmsg1
 #undef Dmsg2
@@ -347,7 +350,6 @@ void print_tree(char *path, TREE_NODE *tree)
    Dmsg3(-1, "%s/%s%s\n", path, tree->fname, termchr);
    switch (tree->type) {
    case TN_FILE:
-      break;
    case TN_NEWDIR:
    case TN_DIR:
    case TN_DIR_NLS:
@@ -380,7 +382,12 @@ int tree_getpath(TREE_NODE *node, char *buf, int buf_size)
       buf[0] = 0;   
    }
    bstrncat(buf, node->fname, buf_size);
-   if (node->type != TN_FILE) {
+   /* Add a slash for all directories unless we are at the root,
+    *  also add a slash to a soft linked file if it has children
+    *  i.e. it is linked to a directory.
+    */
+   if ((node->type != TN_FILE && !(buf[0] == '/' && buf[1] == 0)) ||
+       (node->soft_link && node->child)) {
       bstrncat(buf, "/", buf_size);
    }
    return 1;
@@ -437,7 +444,7 @@ TREE_NODE *tree_relcwd(char *path, TREE_ROOT *root, TREE_NODE *node)
         break;
       }
    }
-   if (!cd || cd->type == TN_FILE) {
+   if (!cd || (cd->type == TN_FILE && !cd->child)) {
       return NULL;
    }
    if (!p) {
index 838f920966587f3eb3da49818c6583fd997e6a69..e398e546cd361a417bca94dca576430e69545380 100644 (file)
@@ -40,10 +40,11 @@ struct s_tree_node {
    int32_t FileIndex;                 /* file index */
    uint32_t JobId;                    /* JobId */
    uint16_t fname_len;                /* filename length */
-   unsigned int type: 8;              /* node type */
+   int type: 8;                       /* node type */
    unsigned int extract: 1;           /* extract item */
    unsigned int extract_dir: 1;       /* extract dir entry only */
-   unsigned int have_link: 1;         /* set if have hard link */
+   unsigned int hard_link: 1;         /* set if have hard link */
+   unsigned int soft_link: 1;         /* set if is soft link */  
    struct s_tree_node *parent;
    struct s_tree_node *sibling;
    struct s_tree_node *child;
index ff0c8658836ca0d021efe1186c62b845261934a5..708554a908c2c3e9aa4bada72204b7481234b96a 100755 (executable)
@@ -37,17 +37,15 @@ time_t watchdog_time = 0;         /* this has granularity of SLEEP_TIME */
 
 /* Forward referenced functions */
 static void *watchdog_thread(void *arg);
+static void wd_lock();
+static void wd_unlock();
 
 /* Static globals */
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_cond_t  timer = PTHREAD_COND_INITIALIZER;
-static bool quit;
+static bool quit = false;;
 static bool wd_is_init = false;
+static brwlock_t lock;               /* watchdog lock */
 
-/* Forward referenced callback functions */
 static pthread_t wd_tid;
-
-/* Static globals */
 static dlist *wd_queue;
 static dlist *wd_inactive;
 
@@ -61,14 +59,18 @@ int start_watchdog(void)
 {
    int stat;
    watchdog_t *dummy = NULL;
+   int errstat;
 
    if (wd_is_init) {
       return 0;
    }
    Dmsg0(200, "Initialising NicB-hacked watchdog thread\n");
    watchdog_time = time(NULL);
-   quit = false;
 
+   if ((errstat=rwl_init(&lock)) != 0) {
+      Emsg1(M_ABORT, 0, _("Unable to initialize watchdog lock. ERR=%s\n"), 
+           strerror(errstat));
+   }
    wd_queue = new dlist(wd_queue, &dummy->link);
    wd_inactive = new dlist(wd_inactive, &dummy->link);
 
@@ -94,12 +96,7 @@ int stop_watchdog(void)
       return 0;
    }
 
-   Dmsg0(200, "Sending stop signal to NicB-hacked watchdog thread\n");
-   P(mutex);
-   quit = true;
-   stat = pthread_cond_signal(&timer);
-   V(mutex);
-
+   quit = true;                      /* notify watchdog thread to stop */
    wd_is_init = false;
 
    stat = pthread_join(wd_tid, NULL);
@@ -119,8 +116,10 @@ int stop_watchdog(void)
       }
       free(p);
    }
+
    delete wd_inactive;
    wd_inactive = NULL;
+   rwl_destroy(&lock);
 
    return stat;
 }
@@ -131,9 +130,6 @@ watchdog_t *new_watchdog(void)
 
    if (!wd_is_init) {
       start_watchdog();
-      if (!wd_is_init) {
-         Emsg0(M_ABORT, 0, "BUG! new_watchdog called before start_watchdog\n");
-      }
    }
 
    if (wd == NULL) {
@@ -160,12 +156,12 @@ bool register_watchdog(watchdog_t *wd)
       Emsg1(M_ABORT, 0, "BUG! Watchdog %p has zero interval\n", wd);
    }
 
-   P(mutex);
+   wd_lock();
    wd->next_fire = watchdog_time + wd->interval;
    wd_queue->append(wd);
    Dmsg3(200, "Registered watchdog %p, interval %d%s\n",
          wd, wd->interval, wd->one_shot ? " one shot" : "");
-   V(mutex);
+   wd_unlock();
 
    return false;
 }
@@ -206,9 +202,9 @@ bool unregister_watchdog(watchdog_t *wd)
       Emsg0(M_ABORT, 0, "BUG! unregister_watchdog called before start_watchdog\n");
    }
 
-   P(mutex);
+   wd_lock();
    ret = unregister_watchdog_unlocked(wd);
-   V(mutex);
+   wd_unlock();
 
    return ret;
 }
@@ -217,15 +213,20 @@ static void *watchdog_thread(void *arg)
 {
    Dmsg0(200, "NicB-reworked watchdog thread entered\n");
 
-   while (true) {
+   while (!quit) {
       watchdog_t *p;
 
-      P(mutex);
-      if (quit) {
-        V(mutex);
-        break;
-      }
-
+      /* 
+       * We lock the jcr chain here because a good number of the
+       *   callback routines lock the jcr chain. We need to lock
+       *   it here *before* the watchdog lock because the SD message
+       *   thread first locks the jcr chain, then when closing the
+       *   job locks the watchdog chain. If the two thread do not
+       *   lock in the same order, we get a deadlock -- each holds
+       *   the other's needed lock.
+       */
+      lock_jcr_chain();
+      wd_lock();
       watchdog_time = time(NULL);
 
       foreach_dlist(p, wd_queue) {
@@ -242,10 +243,39 @@ static void *watchdog_thread(void *arg)
            }
         }
       }
-      V(mutex);
+      wd_unlock();
+      unlock_jcr_chain();
       bmicrosleep(SLEEP_TIME, 0);
    }
 
    Dmsg0(200, "NicB-reworked watchdog thread exited\n");
    return NULL;
 }
+
+/*
+ * Watchdog lock, this can be called multiple times by the same
+ *   thread without blocking, but must be unlocked the number of
+ *   times it was locked.
+ */
+static void wd_lock()
+{
+   int errstat;
+   if ((errstat=rwl_writelock(&lock)) != 0) {
+      Emsg1(M_ABORT, 0, "rwl_writelock failure. ERR=%s\n",
+          strerror(errstat));
+   }
+}    
+
+/*
+ * Unlock the watchdog. This can be called multiple times by the
+ *   same thread up to the number of times that thread called
+ *   wd_ lock()/
+ */
+static void wd_unlock()
+{
+   int errstat;
+   if ((errstat=rwl_writeunlock(&lock)) != 0) {
+      Emsg1(M_ABORT, 0, "rwl_writeunlock failure. ERR=%s\n",
+          strerror(errstat));
+   }
+}    
index 5a3028403e38d761e5ee2e8feb7d31f26784e93a..58fa67ef5e65ff0a052b1d2d5a47955dbd03fa97 100644 (file)
@@ -116,11 +116,6 @@ DEV_BLOCK *new_block(DEVICE *dev)
    block->dev = dev;
    block->block_len = block->buf_len;  /* default block size */
    block->buf = get_memory(block->buf_len); 
-   if (block->buf == NULL) {
-      Mmsg0(&dev->errmsg, _("Unable to malloc block buffer.\n"));
-      Emsg0(M_FATAL, 0, dev->errmsg);
-      return NULL;
-   }
    empty_block(block);
    block->BlockVer = BLOCK_VER;       /* default write version */
    Dmsg1(90, "Returning new block=%x\n", block);
@@ -134,7 +129,7 @@ DEV_BLOCK *new_block(DEVICE *dev)
 void print_block_read_errors(JCR *jcr, DEV_BLOCK *block)
 {
    if (block->read_errors > 1) {
-      Jmsg(jcr, M_ERROR, 0, _("%d block read errors ignored.\n"),
+      Jmsg(jcr, M_ERROR, 0, _("%d block read errors not printed.\n"),
         block->read_errors);
    }
 }
@@ -221,7 +216,7 @@ static int unser_block_header(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
       block->BlockVer = 1;
       block->bufp = block->buf + bhl;
       if (strncmp(Id, BLKHDR1_ID, BLKHDR_ID_LENGTH) != 0) {
-         Mmsg2(&dev->errmsg, _("Buffer ID error. Wanted: %s, got %s. Buffer discarded.\n"),
+         Mmsg2(&dev->errmsg, _("Volume data error! Wanted ID: %s, got %s. Buffer discarded.\n"),
            BLKHDR1_ID, Id);
         if (block->read_errors == 0 || verbose >= 2) {
             Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
@@ -236,7 +231,7 @@ static int unser_block_header(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
       block->BlockVer = 2;
       block->bufp = block->buf + bhl;
       if (strncmp(Id, BLKHDR2_ID, BLKHDR_ID_LENGTH) != 0) {
-         Mmsg2(&dev->errmsg, _("Buffer ID error. Wanted: %s, got %s. Buffer discarded.\n"),
+         Mmsg2(&dev->errmsg, _("Volume data error! Wanted ID: %s, got %s. Buffer discarded.\n"),
            BLKHDR2_ID, Id);
         if (block->read_errors == 0 || verbose >= 2) {
             Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
@@ -245,7 +240,7 @@ static int unser_block_header(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
         return 0;
       }
    } else {
-      Mmsg1(&dev->errmsg, _("Expected block-id BB01 or BB02, got %s. Buffer discarded.\n"), Id);
+      Mmsg1(&dev->errmsg, _("Volume data error! Wanted block-id BB02, got %s. Buffer discarded.\n"), Id);
       if (block->read_errors == 0 || verbose >= 2) {
          Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
       }
@@ -255,7 +250,7 @@ static int unser_block_header(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
 
    /* Sanity check */
    if (block_len > MAX_BLOCK_LENGTH) {
-      Mmsg1(&dev->errmsg,  _("Block length %u is insane (too large), probably due to a bad archive.\n"),
+      Mmsg1(&dev->errmsg,  _("Volume data error! Block length %u is insane (too large), probably due to a bad archive.\n"),
         block_len);
       if (block->read_errors == 0 || verbose >= 2) {
          Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
@@ -280,7 +275,7 @@ static int unser_block_header(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
       BlockCheckSum = bcrc32((uint8_t *)block->buf+BLKHDR_CS_LENGTH,
                         block_len-BLKHDR_CS_LENGTH);
       if (BlockCheckSum != CheckSum) {
-         Mmsg3(&dev->errmsg, _("Block checksum mismatch in block %u: calc=%x blk=%x\n"), 
+         Mmsg3(&dev->errmsg, _("Volume data error! Block checksum mismatch in block %u: calc=%x blk=%x\n"), 
            (unsigned)BlockNumber, BlockCheckSum, CheckSum);
         if (block->read_errors == 0 || verbose >= 2) {
             Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
@@ -308,7 +303,7 @@ int write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
     * If a new volume has been mounted since our last write
     *  Create a JobMedia record for the previous volume written,
     *  and set new parameters to write this volume   
-    * The saem applies for if we are in a new file.
+    * The same applies for if we are in a new file.
     */
    if (jcr->NewVol || jcr->NewFile) {
       /* Create a jobmedia record for this job */
@@ -680,7 +675,7 @@ reread:
    /* Continue here for successful read */
    block->read_len = stat;     /* save length read */
    if (block->read_len < BLKHDR2_LENGTH) {
-      Mmsg2(&dev->errmsg, _("Very short block of %d bytes on device %s discarded.\n"), 
+      Mmsg2(&dev->errmsg, _("Volume data error! Very short block of %d bytes on device %s discarded.\n"), 
         block->read_len, dev->dev_name);
       Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
       dev->state |= ST_SHORT;  /* set short block */
@@ -732,7 +727,7 @@ reread:
    }
 
    if (block->block_len > block->read_len) {
-      Mmsg3(&dev->errmsg, _("Short block at %u of %d bytes on device %s discarded.\n"), 
+      Mmsg3(&dev->errmsg, _("Volume data error! Short block at %u of %d bytes on device %s discarded.\n"), 
         dev->block_num, block->read_len, dev->dev_name);
       Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
       dev->state |= ST_SHORT;  /* set short block */
index 1a812d5efa7abda0a37b6b1079ecfc37fd0e7d4b..ca18e1d8026f75edfedefe07ba4e8a31196f70ca 100644 (file)
@@ -1352,15 +1352,9 @@ bail_out:
 
 static void statcmd()
 {
-   int stat = 0;
-   int debug;
-   uint32_t status;
-
-   debug = debug_level;
+   int debug = debug_level;
    debug_level = 30;
-   if (!status_dev(dev, &status)) {
-      Pmsg2(0, "Bad status from status %d. ERR=%s\n", stat, strerror_dev(dev));
-   }
+   Pmsg2(0, "Device status: %u. ERR=%s\n", status_dev(dev), strerror_dev(dev));
 #ifdef xxxx
    dump_volume_label(dev);
 #endif
index 249a503c5c5a82da9da8324c221222466aef1594..5586309d82afb60cbbf568d29e0e3edc22bdfb00 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *
  *  Utility routines for "tool" programs such as bscan, bls,
- *    bextract, ...  
+ *    bextract, ...  Some routines also used by Bacula.
  * 
  *  Normally nothing in this file is called by the Storage   
  *    daemon because we interact more directly with the user
@@ -240,12 +240,11 @@ void display_tape_error_status(JCR *jcr, DEVICE *dev)
 {
    uint32_t status;
 
-   Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
-   status_dev(dev, &status);
+   status = status_dev(dev);
    Dmsg1(20, "Device status: %x\n", status);
    if (status & BMT_EOD)
       Jmsg(jcr, M_ERROR, 0, _("Unexpected End of Data\n"));
-   else if (status & BMT_EOT)
+  else if (status & BMT_EOT)
       Jmsg(jcr, M_ERROR, 0, _("Unexpected End of Tape\n"));
    else if (status & BMT_EOF)
       Jmsg(jcr, M_ERROR, 0, _("Unexpected End of File\n"));
@@ -253,6 +252,4 @@ void display_tape_error_status(JCR *jcr, DEVICE *dev)
       Jmsg(jcr, M_ERROR, 0, _("Tape Door is Open\n"));
    else if (!(status & BMT_ONLINE))
       Jmsg(jcr, M_ERROR, 0, _("Unexpected Tape is Off-line\n"));
-   else
-      Jmsg(jcr, M_ERROR, 0, _("Read error on Record Header %s: %s\n"), dev_name(dev), strerror(errno));
 }
index 1664f9ca20bfa412be01d89ff57e76ab324574a1..146be7862441b6f1b5ef4389f31b23f83333e435 100644 (file)
@@ -555,11 +555,9 @@ int update_pos_dev(DEVICE *dev)
  * currently), which means that for the moment, this
  * routine has very little value.
  *
- *   Returns: 1 on success
- *           0 on error
+ *   Returns: status
  */
-int
-status_dev(DEVICE *dev, uint32_t *status)
+uint32_t status_dev(DEVICE *dev)
 {
    struct mtget mt_stat;
    uint32_t stat = 0;
@@ -626,8 +624,7 @@ status_dev(DEVICE *dev, uint32_t *status)
    } else {
       stat |= BMT_ONLINE | BMT_BOT;
    }
-   *status = stat; 
-   return 1;
+   return stat;
 }
 
 
index 115a9d5ae270d53e70341b31435b611677ed79d1..51f5d3a83151c7d5906644b726eb762bee302620 100644 (file)
@@ -78,7 +78,7 @@ extern int debug_level;
  */
 int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
 {
-   uint32_t stat = 0;                  
+   uint32_t stat;
    char PrevVolName[MAX_NAME_LENGTH];
    DEV_BLOCK *label_blk;
    char b1[30], b2[30];
@@ -86,7 +86,7 @@ int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
    char dt[MAX_TIME_LENGTH];
 
    wait_time = time(NULL);
-   status_dev(dev, &stat);
+   stat = status_dev(dev);
    if (!(stat & BMT_EOD)) {
       return 0;                       /* this really shouldn't happen */
    }
index 6cd627f03b594069d3aa886563347671265db61d..5cef5693e4fa099d344e175ee9169c9eb8ab22a3 100644 (file)
@@ -781,12 +781,8 @@ static int readlabel_cmd(JCR *jcr)
 
         P(dev->mutex);               /* Use P to avoid indefinite block */
         if (!dev_state(dev, ST_OPENED)) {
-           if (open_dev(dev, NULL, READ_WRITE) < 0) {
-               bnet_fsend(dir, _("3994 Connot open device: %s\n"), strerror_dev(dev));
-           } else {
-              read_volume_label(jcr, dev, Slot);
-              force_close_dev(dev);
-           }
+           read_volume_label(jcr, dev, Slot);
+           force_close_dev(dev);
          /* Under certain "safe" conditions, we can steal the lock */
         } else if (dev->dev_blocked && 
                    (dev->dev_blocked == BST_UNMOUNTED ||
index 10b4122db9d62abda71134ea33130c0b05f03303..c46d9ad22f1931211a7a988dfff5125d16e7be47 100644 (file)
 uint32_t new_VolSessionId();
 
 /* From acquire.c */
-DEVICE  *acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-int      acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-int      release_device(JCR *jcr, DEVICE *dev);
+DEVICE *acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+int     acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+int     release_device(JCR *jcr, DEVICE *dev);
 
 /* From askdir.c */
 enum get_vol_info_rw {
    GET_VOL_INFO_FOR_WRITE,
    GET_VOL_INFO_FOR_READ
 };
-int     dir_get_volume_info(JCR *jcr, enum get_vol_info_rw);
-int     dir_find_next_appendable_volume(JCR *jcr);
-int     dir_update_volume_info(JCR *jcr, DEVICE *dev, int label);
-int     dir_ask_sysop_to_create_appendable_volume(JCR *jcr, DEVICE *dev);
-int     dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev);
-int     dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec);
-int     dir_send_job_status(JCR *jcr);
-int     dir_create_jobmedia_record(JCR *jcr);
+int    dir_get_volume_info(JCR *jcr, enum get_vol_info_rw);
+int    dir_find_next_appendable_volume(JCR *jcr);
+int    dir_update_volume_info(JCR *jcr, DEVICE *dev, int label);
+int    dir_ask_sysop_to_create_appendable_volume(JCR *jcr, DEVICE *dev);
+int    dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev);
+int    dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec);
+int    dir_send_job_status(JCR *jcr);
+int    dir_create_jobmedia_record(JCR *jcr);
 
 /* authenticate.c */
-int     authenticate_director(JCR *jcr);
-int     authenticate_filed(JCR *jcr);
+int    authenticate_director(JCR *jcr);
+int    authenticate_filed(JCR *jcr);
 
 /* From block.c */
-void    dump_block(DEV_BLOCK *b, char *msg);
+void   dump_block(DEV_BLOCK *b, char *msg);
 DEV_BLOCK *new_block(DEVICE *dev);
-void    init_block_write(DEV_BLOCK *block);
-void    empty_block(DEV_BLOCK *block);
-void    free_block(DEV_BLOCK *block);
-int     write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-int     write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-void    print_block_read_errors(JCR *jcr, DEV_BLOCK *block);
+void   init_block_write(DEV_BLOCK *block);
+void   empty_block(DEV_BLOCK *block);
+void   free_block(DEV_BLOCK *block);
+int    write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+int    write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+void   print_block_read_errors(JCR *jcr, DEV_BLOCK *block);
 
 #define CHECK_BLOCK_NUMBERS    true
 #define NO_BLOCK_NUMBER_CHECK  false
-int     read_block_from_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, bool check_block_numbers);
-int     read_block_from_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, bool check_block_numbers);
+int    read_block_from_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, bool check_block_numbers);
+int    read_block_from_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, bool check_block_numbers);
 
 /* From butil.c -- utilities for SD tool programs */
-void    print_ls_output(char *fname, char *link, int type, struct stat *statp);
+void   print_ls_output(char *fname, char *link, int type, struct stat *statp);
 JCR    *setup_jcr(char *name, char *device, BSR *bsr, char *VolumeName);
 DEVICE *setup_to_access_device(JCR *jcr, int read_access);
-void    display_tape_error_status(JCR *jcr, DEVICE *dev);
+void   display_tape_error_status(JCR *jcr, DEVICE *dev);
 DEVRES *find_device_res(char *device_name, int read_access);
 
 
 /* From dev.c */
-DEVICE  *init_dev(DEVICE *dev, DEVRES *device);
-int      open_dev(DEVICE *dev, char *VolName, int mode);
-void     close_dev(DEVICE *dev);
-void     force_close_dev(DEVICE *dev);
-int      truncate_dev(DEVICE *dev);
-void     term_dev(DEVICE *dev);
-char *   strerror_dev(DEVICE *dev);
-void     clrerror_dev(DEVICE *dev, int func);
-int      update_pos_dev(DEVICE *dev);
-int      rewind_dev(DEVICE *dev);
-int      load_dev(DEVICE *dev);
-int      offline_dev(DEVICE *dev);
-int      flush_dev(DEVICE *dev);
-int      weof_dev(DEVICE *dev, int num);
-int      write_block(DEVICE *dev);
-int      write_dev(DEVICE *dev, char *buf, size_t len);
-int      read_dev(DEVICE *dev, char *buf, size_t len);
-int      status_dev(DEVICE *dev, uint32_t *status);
-int      eod_dev(DEVICE *dev);
-int      fsf_dev(DEVICE *dev, int num);
-int      fsr_dev(DEVICE *dev, int num);
-int      bsf_dev(DEVICE *dev, int num);
-int      bsr_dev(DEVICE *dev, int num);
-void     attach_jcr_to_device(DEVICE *dev, JCR *jcr);
-void     detach_jcr_from_device(DEVICE *dev, JCR *jcr);
-JCR     *next_attached_jcr(DEVICE *dev, JCR *jcr);
-int      dev_can_write(DEVICE *dev);
-int      offline_or_rewind_dev(DEVICE *dev);
-int      reposition_dev(DEVICE *dev, uint32_t file, uint32_t block);
-void     init_dev_wait_timers(DEVICE *dev);
-bool     double_dev_wait_time(DEVICE *dev);
+DEVICE *init_dev(DEVICE *dev, DEVRES *device);
+int     open_dev(DEVICE *dev, char *VolName, int mode);
+void    close_dev(DEVICE *dev);
+void    force_close_dev(DEVICE *dev);
+int     truncate_dev(DEVICE *dev);
+void    term_dev(DEVICE *dev);
+char *  strerror_dev(DEVICE *dev);
+void    clrerror_dev(DEVICE *dev, int func);
+int     update_pos_dev(DEVICE *dev);
+int     rewind_dev(DEVICE *dev);
+int     load_dev(DEVICE *dev);
+int     offline_dev(DEVICE *dev);
+int     flush_dev(DEVICE *dev);
+int     weof_dev(DEVICE *dev, int num);
+int     write_block(DEVICE *dev);
+int     write_dev(DEVICE *dev, char *buf, size_t len);
+int     read_dev(DEVICE *dev, char *buf, size_t len);
+uint32_t status_dev(DEVICE *dev);
+int     eod_dev(DEVICE *dev);
+int     fsf_dev(DEVICE *dev, int num);
+int     fsr_dev(DEVICE *dev, int num);
+int     bsf_dev(DEVICE *dev, int num);
+int     bsr_dev(DEVICE *dev, int num);
+void    attach_jcr_to_device(DEVICE *dev, JCR *jcr);
+void    detach_jcr_from_device(DEVICE *dev, JCR *jcr);
+JCR    *next_attached_jcr(DEVICE *dev, JCR *jcr);
+int     dev_can_write(DEVICE *dev);
+int     offline_or_rewind_dev(DEVICE *dev);
+int     reposition_dev(DEVICE *dev, uint32_t file, uint32_t block);
+void    init_dev_wait_timers(DEVICE *dev);
+bool    double_dev_wait_time(DEVICE *dev);
 
 
 /* Get info about device */
-char *   dev_name(DEVICE *dev);
-char *   dev_vol_name(DEVICE *dev);
+char *  dev_name(DEVICE *dev);
+char *  dev_vol_name(DEVICE *dev);
 uint32_t dev_block(DEVICE *dev);
 uint32_t dev_file(DEVICE *dev);
-int      dev_is_tape(DEVICE *dev);
+int     dev_is_tape(DEVICE *dev);
 
 /* From device.c */
-int      open_device(DEVICE *dev);
-int      fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-void     _lock_device(char *file, int line, DEVICE *dev);
-void     _unlock_device(char *file, int line, DEVICE *dev);
-void     _block_device(char *file, int line, DEVICE *dev, int state);
-void     _unblock_device(char *file, int line, DEVICE *dev);
-void     _steal_device_lock(char *file, int line, DEVICE *dev, bsteal_lock_t *hold, int state);
-void     _give_back_device_lock(char *file, int line, DEVICE *dev, bsteal_lock_t *hold);
-void     set_new_volume_parameters(JCR *jcr, DEVICE *dev);
-void     set_new_file_parameters(JCR *jcr, DEVICE *dev); 
-int      device_is_unmounted(DEVICE *dev);
+int     open_device(DEVICE *dev);
+int     fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+void    _lock_device(char *file, int line, DEVICE *dev);
+void    _unlock_device(char *file, int line, DEVICE *dev);
+void    _block_device(char *file, int line, DEVICE *dev, int state);
+void    _unblock_device(char *file, int line, DEVICE *dev);
+void    _steal_device_lock(char *file, int line, DEVICE *dev, bsteal_lock_t *hold, int state);
+void    _give_back_device_lock(char *file, int line, DEVICE *dev, bsteal_lock_t *hold);
+void    set_new_volume_parameters(JCR *jcr, DEVICE *dev);
+void    set_new_file_parameters(JCR *jcr, DEVICE *dev); 
+int     device_is_unmounted(DEVICE *dev);
 
 /* From dircmd.c */
-void     *connection_request(void *arg); 
+void    *connection_request(void *arg); 
 
 
 /* From fd_cmds.c */
-void     run_job(JCR *jcr);
+void    run_job(JCR *jcr);
 
 /* From job.c */
-void     stored_free_jcr(JCR *jcr);
-void     connection_from_filed(void *arg);     
-void     handle_filed_connection(BSOCK *fd, char *job_name);
+void    stored_free_jcr(JCR *jcr);
+void    connection_from_filed(void *arg);     
+void    handle_filed_connection(BSOCK *fd, char *job_name);
 
 /* From label.c */
-int      read_dev_volume_label(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-void     create_session_label(JCR *jcr, DEV_RECORD *rec, int label);
-void     create_volume_label(DEVICE *dev, char *VolName, char *PoolName);
-int      write_volume_label_to_dev(JCR *jcr, DEVRES *device, char *VolName, char *PoolName);
-int      write_session_label(JCR *jcr, DEV_BLOCK *block, int label);
-int      write_volume_label_to_block(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-void     dump_volume_label(DEVICE *dev);
-void     dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose);
-int      unser_volume_label(DEVICE *dev, DEV_RECORD *rec);
-int      unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec);
+int     read_dev_volume_label(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+void    create_session_label(JCR *jcr, DEV_RECORD *rec, int label);
+void    create_volume_label(DEVICE *dev, char *VolName, char *PoolName);
+int     write_volume_label_to_dev(JCR *jcr, DEVRES *device, char *VolName, char *PoolName);
+int     write_session_label(JCR *jcr, DEV_BLOCK *block, int label);
+int     write_volume_label_to_block(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+void    dump_volume_label(DEVICE *dev);
+void    dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose);
+int     unser_volume_label(DEVICE *dev, DEV_RECORD *rec);
+int     unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec);
 
 /* From match_bsr.c */
-int      match_bsr(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec, 
-              SESSION_LABEL *sesrec);
-int      match_bsr_block(BSR *bsr, DEV_BLOCK *block);
-void     position_bsr_block(BSR *bsr, DEV_BLOCK *block);
-BSR     *find_next_bsr(BSR *root_bsr, DEVICE *dev);
-bool     match_set_eof(BSR *bsr, DEV_RECORD *rec);
+int     match_bsr(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec, 
+             SESSION_LABEL *sesrec);
+int     match_bsr_block(BSR *bsr, DEV_BLOCK *block);
+void    position_bsr_block(BSR *bsr, DEV_BLOCK *block);
+BSR    *find_next_bsr(BSR *root_bsr, DEVICE *dev);
+bool    match_set_eof(BSR *bsr, DEV_RECORD *rec);
 
 /* From mount.c */
-int      mount_next_write_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, int release);
-int      mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-void     release_volume(JCR *jcr, DEVICE *dev);
-void     mark_volume_in_error(JCR *jcr, DEVICE *dev);
+int     mount_next_write_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, int release);
+int     mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+void    release_volume(JCR *jcr, DEVICE *dev);
+void    mark_volume_in_error(JCR *jcr, DEVICE *dev);
 
 /* From autochanger.c */
-int      autoload_device(JCR *jcr, DEVICE *dev, int writing, BSOCK *dir);
-int      autochanger_list(JCR *jcr, DEVICE *dev, BSOCK *dir);
-void     invalidate_slot_in_catalog(JCR *jcr, DEVICE *dev);
+int     autoload_device(JCR *jcr, DEVICE *dev, int writing, BSOCK *dir);
+int     autochanger_list(JCR *jcr, DEVICE *dev, BSOCK *dir);
+void    invalidate_slot_in_catalog(JCR *jcr, DEVICE *dev);
 
 
 /* From parse_bsr.c */
-BSR     *parse_bsr(JCR *jcr, char *lf);
-void     dump_bsr(BSR *bsr, bool recurse);
-void     free_bsr(BSR *bsr);
+BSR    *parse_bsr(JCR *jcr, char *lf);
+void    dump_bsr(BSR *bsr, bool recurse);
+void    free_bsr(BSR *bsr);
 VOL_LIST *new_vol();
-int      add_vol(JCR *jcr, VOL_LIST *vol);
-void     free_vol_list(JCR *jcr);
-void     create_vol_list(JCR *jcr);
+int     add_vol(JCR *jcr, VOL_LIST *vol);
+void    free_vol_list(JCR *jcr);
+void    create_vol_list(JCR *jcr);
 
 /* From record.c */
-char    *FI_to_ascii(int fi);
-char    *stream_to_ascii(int stream, int fi);
-int      write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
-int      can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
-int      read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec); 
+char   *FI_to_ascii(int fi);
+char   *stream_to_ascii(int stream, int fi);
+int     write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
+int     can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
+int     read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec); 
 DEV_RECORD *new_record();
-void     free_record(DEV_RECORD *rec);
+void    free_record(DEV_RECORD *rec);
 
 /* From read_record.c */
 int read_records(JCR *jcr,  DEVICE *dev, 
index 492893a380684dfc2b52b46061d39637f24d232b..2dde19f717bf1f00d3fd5f4ffdde7e47b319d56d 100644 (file)
@@ -1,9 +1,9 @@
 /* */
 #undef  VERSION
-#define VERSION "1.33"
+#define VERSION "1.33.3"
 #define VSTRING "1"
-#define BDATE   "04 Feb 2004"
-#define LSMDATE "04Feb04"
+#define BDATE   "07 Feb 2004"
+#define LSMDATE "07Feb04"
 
 /* Debug flags */
 #undef  DEBUG