]> git.sur5r.net Git - bacula/bacula/commitdiff
- Continue implementing migration.
authorKern Sibbald <kern@sibbald.com>
Mon, 30 Jan 2006 14:24:17 +0000 (14:24 +0000)
committerKern Sibbald <kern@sibbald.com>
Mon, 30 Jan 2006 14:24:17 +0000 (14:24 +0000)
- Implement support for removable filesystems in SD.
- Ensure that btraceback scripts can be read by anyone.
- Replace dvd-freespace and dvd-writepart by dvd-handler.
- Correct bug where canceling restore before the FD contacts
  the SD causes the drive to be left in read mode.
- Move ofline_or_rewind into DEVICE::close().
- Eliminate close_device.
- Convert several dev subroutines to methods (e.g. bsf,
  eod, ...)
- Eliminate force_close_device().
- Implement Device Type directive in Device resource that
  can have values File, Tape, Fifo, DVD, or Prog.
- Add has_cap() method to Device.

git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@2775 91ce42f0-d328-0410-95d8-f526ca767f89

42 files changed:
bacula/Makefile.in
bacula/kes-1.39
bacula/scripts/Makefile.in
bacula/src/cats/protos.h
bacula/src/cats/sql_find.c
bacula/src/dird/backup.c
bacula/src/dird/fd_cmds.c
bacula/src/dird/getmsg.c
bacula/src/dird/job.c
bacula/src/dird/mac.c
bacula/src/dird/msgchan.c
bacula/src/dird/protos.h
bacula/src/dird/restore.c
bacula/src/dird/ua_label.c
bacula/src/dird/ua_run.c
bacula/src/dird/ua_update.c
bacula/src/dird/verify.c
bacula/src/gnome2-console/test-gnome-console.conf
bacula/src/jcr.h
bacula/src/lib/parse_conf.c
bacula/src/stored/Makefile.in
bacula/src/stored/acquire.c
bacula/src/stored/append.c
bacula/src/stored/askdir.c
bacula/src/stored/autochanger.c
bacula/src/stored/block.c
bacula/src/stored/bscan.c
bacula/src/stored/btape.c
bacula/src/stored/dev.c
bacula/src/stored/dev.h
bacula/src/stored/device.c
bacula/src/stored/dircmd.c
bacula/src/stored/dvd.c
bacula/src/stored/fd_cmds.c
bacula/src/stored/job.c
bacula/src/stored/label.c
bacula/src/stored/mount.c
bacula/src/stored/protos.h
bacula/src/stored/read.c
bacula/src/stored/stored_conf.c
bacula/src/stored/stored_conf.h
bacula/src/version.h

index 71d0b70c992291d235e2d8de2a3cb6100338c810..64042e8390ab841cdf3f66e9c1500883d7627919 100755 (executable)
@@ -168,7 +168,7 @@ Makefiles:
        (cd scripts; \
        chmod 755 startmysql stopmysql bacula startit stopit btraceback; \
        chmod 755 mtx-changer bconsole gconsole devel_bacula; \
-       chmod 755 dvd-freespace dvd-writepart)
+       chmod 755 dvd-handler)
 
        (cd src/cats; \
        chmod 755 create_bacula_database      update_bacula_tables     make_bacula_tables; \
index b3ae87b2bbe9292bc67666c2b03c6fce9ec5cb81..18fa97fcbfea764cccb01ade3e12a102bd3ccc96 100644 (file)
@@ -3,6 +3,22 @@
 
 General:
 
+Changes to 1.39.5
+30Jan06
+- Continue implementing migration.
+- Implement support for removable filesystems in SD.
+- Ensure that btraceback scripts can be read by anyone.
+- Replace dvd-freespace and dvd-writepart by dvd-handler.
+- Correct bug where canceling restore before the FD contacts
+  the SD causes the drive to be left in read mode.
+- Move ofline_or_rewind into DEVICE::close().
+- Eliminate close_device.
+- Convert several dev subroutines to methods (e.g. bsf,
+  eod, ...)
+- Eliminate force_close_device().
+- Implement Device Type directive in Device resource that
+  can have values File, Tape, Fifo, DVD, or Prog.
+- Add has_cap() method to Device.
 Changes to 1.39.4
 17Jan06
 - Add patch from bug #527 to allow RedHat user to specify
index 03027516c2da97d5e0c4116dec9d32c22fa645ac..d440b3c48ae65e5c56aa8dd4c43f780f2c683276 100755 (executable)
@@ -50,6 +50,8 @@ install: installdirs
        $(INSTALL_SCRIPT) dvd-handler $(DESTDIR)$(scriptdir)/dvd-handler
        $(INSTALL_DATA)   btraceback.gdb $(DESTDIR)$(scriptdir)/btraceback.gdb
        $(INSTALL_DATA)   btraceback.dbx $(DESTDIR)$(scriptdir)/btraceback.dbx
+       chmod 0644 $(DESTDIR)$(scriptdir)/btraceback.gdb \
+                  $(DESTDIR)$(scriptdir)/btraceback.dbx
        $(INSTALL_SCRIPT) btraceback $(DESTDIR)$(sbindir)/btraceback
        gzip <bacula.man >bacula.8.gz
        $(INSTALL_DATA)   bacula.8.gz $(DESTDIR)$(mandir)/bacula.8.gz
index 580d3c387b7fc3719bfa997b2747209ab7eb04ed..6841dffdcf44786060d3d28828ae4c9a9a3758da 100644 (file)
@@ -6,22 +6,17 @@
  *    Version $Id$
  */
 /*
-   Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+   Copyright (C) 2000-2006 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of
-   the License, or (at your option) any later version.
+   modify it under the terms of the GNU General Public License
+   version 2 as amended with additional clauses defined in the
+   file LICENSE in the main source directory.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public
-   License along with this program; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
-   MA 02111-1307, USA.
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
+   the file LICENSE for additional details.
 
  */
 
@@ -65,7 +60,7 @@ int db_delete_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr);
 
 /* find.c */
 bool db_find_job_start_time(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM **stime);
-int db_find_last_jobid(JCR *jcr, B_DB *mdb, const char *Name, JOB_DBR *jr);
+bool db_find_last_jobid(JCR *jcr, B_DB *mdb, const char *Name, JOB_DBR *jr);
 int db_find_next_volume(JCR *jcr, B_DB *mdb, int index, bool InChanger, MEDIA_DBR *mr);
 bool db_find_failed_job_since(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM *stime, int &JobLevel);
 
index 33ae9b0ac30aa7629cf7721723479c246afe5177..cac8a58cc3d4ea969d84f7534e9707dfc3407e91 100644 (file)
@@ -188,10 +188,10 @@ db_find_failed_job_since(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM *stime, int &
  *   VERIFY_CATALOG we want the JobId of the last INIT.
  *   For VERIFY_VOLUME_TO_CATALOG, we want the JobId of the last Job.
  *
- * Returns: 1 on success
- *          0 on failure
+ * Returns: true  on success
+ *          false on failure
  */
-int
+bool
 db_find_last_jobid(JCR *jcr, B_DB *mdb, const char *Name, JOB_DBR *jr)
 {
    SQL_ROW row;
@@ -207,7 +207,8 @@ db_find_last_jobid(JCR *jcr, B_DB *mdb, const char *Name, JOB_DBR *jr)
            L_VERIFY_INIT, jr->Name, 
            edit_int64(jr->ClientId, ed1));
    } else if (jr->JobLevel == L_VERIFY_VOLUME_TO_CATALOG ||
-              jr->JobLevel == L_VERIFY_DISK_TO_CATALOG) {
+              jr->JobLevel == L_VERIFY_DISK_TO_CATALOG ||
+              jr->JobType == JT_MIGRATE) {
       if (Name) {
          Mmsg(mdb->cmd,
 "SELECT JobId FROM Job WHERE Type='B' AND JobStatus='T' AND "
@@ -221,18 +222,18 @@ db_find_last_jobid(JCR *jcr, B_DB *mdb, const char *Name, JOB_DBR *jr)
    } else {
       Mmsg1(&mdb->errmsg, _("Unknown Job level=%c\n"), jr->JobLevel);
       db_unlock(mdb);
-      return 0;
+      return false;
    }
    Dmsg1(100, "Query: %s\n", mdb->cmd);
    if (!QUERY_DB(jcr, mdb, mdb->cmd)) {
       db_unlock(mdb);
-      return 0;
+      return false;
    }
    if ((row = sql_fetch_row(mdb)) == NULL) {
       Mmsg1(&mdb->errmsg, _("No Job found for: %s.\n"), mdb->cmd);
       sql_free_result(mdb);
       db_unlock(mdb);
-      return 0;
+      return false;
    }
 
    jr->JobId = str_to_int64(row[0]);
@@ -242,11 +243,11 @@ db_find_last_jobid(JCR *jcr, B_DB *mdb, const char *Name, JOB_DBR *jr)
    if (jr->JobId <= 0) {
       Mmsg1(&mdb->errmsg, _("No Job found for: %s\n"), mdb->cmd);
       db_unlock(mdb);
-      return 0;
+      return false;
    }
 
    db_unlock(mdb);
-   return 1;
+   return true;
 }
 
 /*
index cbc95c61e78e9f8463fe342f2d99dd0597600caa..225ffe5fccf9cd691d1be09ad4d3851dc9398721 100644 (file)
@@ -186,6 +186,10 @@ bool do_backup(JCR *jcr)
    }
    Dmsg0(150, "Storage daemon connection OK\n");
 
+   if (!bnet_fsend(jcr->store_bsock, "run")) {
+      return false;
+   }
+
    set_jcr_job_status(jcr, JS_WaitFD);
    if (!connect_to_file_daemon(jcr, 10, FDConnectTimeout, 1)) {
       return false;
@@ -223,8 +227,7 @@ bool do_backup(JCR *jcr)
       }
    }
 
-   bnet_fsend(fd, storaddr, store->address, store->SDDport,
-              tls_need);
+   bnet_fsend(fd, storaddr, store->address, store->SDDport, tls_need);
    if (!response(jcr, fd, OKstore, "Storage", DISPLAY_ERROR)) {
       return false;
    }
index 5855adf4e327d3cdc0ad650d52c2c37e240fec9c..dfc4cc11dbf8b39a4f865e508b7188429375a2f7 100644 (file)
@@ -13,7 +13,7 @@
  *   Version $Id$
  */
 /*
-   Copyright (C) 2000-2005 Kern Sibbald
+   Copyright (C) 2000-2006 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -43,7 +43,6 @@ static char runafter[]    = "RunAfterJob %s\n";
 /* Responses received from File daemon */
 static char OKinc[]       = "2000 OK include\n";
 static char OKjob[]       = "2000 OK Job";
-static char OKbootstrap[] = "2000 OK bootstrap\n";
 static char OKlevel[]     = "2000 OK level\n";
 static char OKRunBefore[] = "2000 OK RunBefore\n";
 static char OKRunAfter[]  = "2000 OK RunAfter\n";
@@ -422,19 +421,19 @@ bool send_exclude_list(JCR *jcr)
 
 
 /*
- * Send bootstrap file if any to the File daemon.
- *  This is used for restore and verify VolumeToCatalog
+ * Send bootstrap file if any to the socket given (FD or SD).
+ *  This is used for restore, verify VolumeToCatalog, and
+ *  for migration.
  */
-bool send_bootstrap_file(JCR *jcr)
+bool send_bootstrap_file(JCR *jcr, BSOCK *sock)
 {
    FILE *bs;
    char buf[1000];
-   BSOCK *fd = jcr->file_bsock;
    const char *bootstrap = "bootstrap\n";
 
    Dmsg1(400, "send_bootstrap_file: %s\n", jcr->RestoreBootstrap);
    if (!jcr->RestoreBootstrap) {
-      return 1;
+      return true;
    }
    bs = fopen(jcr->RestoreBootstrap, "r");
    if (!bs) {
@@ -442,23 +441,19 @@ bool send_bootstrap_file(JCR *jcr)
       Jmsg(jcr, M_FATAL, 0, _("Could not open bootstrap file %s: ERR=%s\n"),
          jcr->RestoreBootstrap, be.strerror());
       set_jcr_job_status(jcr, JS_ErrorTerminated);
-      return 0;
+      return false;
    }
-   bnet_fsend(fd, bootstrap);
+   bnet_fsend(sock, bootstrap);
    while (fgets(buf, sizeof(buf), bs)) {
-      bnet_fsend(fd, "%s", buf);
+      bnet_fsend(sock, "%s", buf);
    }
-   bnet_sig(fd, BNET_EOD);
+   bnet_sig(sock, BNET_EOD);
    fclose(bs);
    if (jcr->unlink_bsr) {
       unlink(jcr->RestoreBootstrap);
       jcr->unlink_bsr = false;
    }                         
-   if (!response(jcr, fd, OKbootstrap, "Bootstrap", DISPLAY_ERROR)) {
-      set_jcr_job_status(jcr, JS_ErrorTerminated);
-      return 0;
-   }
-   return 1;
+   return true;
 }
 
 /*
index 8150cb89727998543fce92491b2d8526fbbdaa4a..bd5dea6157d35ab0fe3597d0c1c26c8a56d4a2d5 100644 (file)
@@ -21,7 +21,7 @@
  *   Version $Id$
  */
 /*
-   Copyright (C) 2000-2005 Kern Sibbald
+   Copyright (C) 2000-2006 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -304,11 +304,9 @@ bool response(JCR *jcr, BSOCK *bs, char *resp, const char *cmd, e_prtmsg prtmsg)
       return false;
    }
    if ((n = bget_dirmsg(bs)) >= 0) {
-      Dmsg0(900, bs->msg);
       if (strcmp(bs->msg, resp) == 0) {
          return true;
       }
-      Dmsg1(900, "Bad response: ERR=%s", bs->msg);
       if (prtmsg == DISPLAY_ERROR) {
          Jmsg(jcr, M_FATAL, 0, _("Bad response to %s command: wanted %s, got %s\n"),
             cmd, resp, bs->msg);
index 6c12e089ce8474104b64138c061bcbb65fc450a1..dfd3b1e1f3632ddc73145eecdff05da14675d1f3 100644 (file)
@@ -7,7 +7,7 @@
  *    Version $Id$
  */
 /*
-   Copyright (C) 2000-2005 Kern Sibbald
+   Copyright (C) 2000-2006 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -379,7 +379,6 @@ bool cancel_job(UAContext *ua, JCR *jcr)
       return true;
 
    default:
-
       /* Cancel File daemon */
       if (jcr->file_bsock) {
          ua->jcr->client = jcr->client;
index ecbe8aa013c00f37e899f336a24bab5fd97b7bb9..eb1d7835e18a4afc6014368fc32addd387dce63f 100644 (file)
@@ -8,14 +8,14 @@
  *  Basic tasks done here:
  *     Open DB and create records for this job.
  *     Open Message Channel with Storage daemon to tell him a job will be starting.
- *     Open connection with File daemon and pass him commands
+ *     Open connection with Storage daemon and pass him commands
  *       to do the backup.
- *     When the File daemon finishes the job, update the DB.
+ *     When the Storage daemon finishes the job, update the DB.
  *
  *   Version $Id$
  */
 /*
-   Copyright (C) 2004-2005 Kern Sibbald
+   Copyright (C) 2004-2006 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -33,6 +33,8 @@
 #include "dird.h"
 #include "ua.h"
 
+static char OKbootstrap[] = "3000 OK bootstrap\n";
+
 /* 
  * Called here before the job is run to do the job
  *   specific setup.
@@ -98,7 +100,7 @@ bool do_mac_init(JCR *jcr)
    /*
     * Get the Pool record -- first apply any level defined pools
     */
-   switch (jcr->JobLevel) {
+   switch (jcr->target_jr.JobLevel) {
    case L_FULL:
       if (jcr->full_pool) {
          jcr->pool = jcr->full_pool;
@@ -171,6 +173,7 @@ bool do_mac(JCR *jcr)
    int stat;
    const char *Type;
    char ed1[100];
+   BSOCK *sd;
 
    switch(jcr->JobType) {
    case JT_MIGRATE:
@@ -213,19 +216,31 @@ bool do_mac(JCR *jcr)
    if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) {
       return false;
    }
+   sd = jcr->store_bsock;
    /*
     * Now start a job with the Storage daemon
     */
-   if (!start_storage_daemon_job(jcr, jcr->storage, jcr->storage)) {
+   if (!start_storage_daemon_job(jcr, jcr->storage, NULL)) {
+      return false;
+   }
+   Dmsg0(150, "Storage daemon connection OK\n");
+
+   if (!send_bootstrap_file(jcr, sd) ||
+       !response(jcr, sd, OKbootstrap, "Bootstrap", DISPLAY_ERROR)) {
       return false;
    }
+
+
    /*
     * Now start a Storage daemon message thread
     */
    if (!start_storage_daemon_message_thread(jcr)) {
       return false;
    }
-   Dmsg0(150, "Storage daemon connection OK\n");
+
+   if (!bnet_fsend(sd, "run")) {
+      return false;
+   }
 
    /* Pickup Job termination data */
    set_jcr_job_status(jcr, JS_Running);
@@ -252,8 +267,8 @@ bool do_mac(JCR *jcr)
 void mac_cleanup(JCR *jcr, int TermCode)
 {
    char sdt[50], edt[50];
-   char ec1[30], ec2[30], ec3[30], ec4[30], ec5[30], compress[50];
-   char term_code[100], fd_term_msg[100], sd_term_msg[100];
+   char ec3[30], ec4[30], ec5[30], compress[50];
+   char term_code[100], sd_term_msg[100];
    const char *term_msg;
    int msg_type;
    MEDIA_DBR mr;
@@ -359,14 +374,14 @@ void mac_cleanup(JCR *jcr, int TermCode)
    switch (jcr->JobStatus) {
       case JS_Terminated:
          if (jcr->Errors || jcr->SDErrors) {
-            term_msg = _("Backup OK -- with warnings");
+            term_msg = _("%s OK -- with warnings");
          } else {
-            term_msg = _("Backup OK");
+            term_msg = _("%s OK");
          }
          break;
       case JS_FatalError:
       case JS_ErrorTerminated:
-         term_msg = _("*** Backup Error ***");
+         term_msg = _("*** %s Error ***");
          msg_type = M_ERROR;          /* Generate error message */
          if (jcr->store_bsock) {
             bnet_sig(jcr->store_bsock, BNET_TERMINATE);
@@ -376,7 +391,7 @@ void mac_cleanup(JCR *jcr, int TermCode)
          }
          break;
       case JS_Canceled:
-         term_msg = _("Backup Canceled");
+         term_msg = _("%s Canceled");
          if (jcr->store_bsock) {
             bnet_sig(jcr->store_bsock, BNET_TERMINATE);
             if (jcr->SD_msg_chan) {
@@ -385,10 +400,10 @@ void mac_cleanup(JCR *jcr, int TermCode)
          }
          break;
       default:
-         term_msg = term_code;
-         sprintf(term_code, _("Inappropriate term code: %c\n"), jcr->JobStatus);
+         term_msg = _("Inappropriate %s term code");
          break;
    }
+   bsnprintf(term_code, sizeof(term_code), term_msg, Type);
    bstrftimes(sdt, sizeof(sdt), jcr->jr.StartTime);
    bstrftimes(edt, sizeof(edt), jcr->jr.EndTime);
    RunTime = jcr->jr.EndTime - jcr->jr.StartTime;
@@ -420,7 +435,6 @@ void mac_cleanup(JCR *jcr, int TermCode)
          bsnprintf(compress, sizeof(compress), "%.1f %%", (float)compression);
       }
    }
-   jobstatus_to_ascii(jcr->FDJobStatus, fd_term_msg, sizeof(fd_term_msg));
    jobstatus_to_ascii(jcr->SDJobStatus, sd_term_msg, sizeof(sd_term_msg));
 
 // bmicrosleep(15, 0);                /* for debugging SIGHUP */
@@ -434,9 +448,7 @@ void mac_cleanup(JCR *jcr, int TermCode)
 "  Pool:                   \"%s\"\n"
 "  Start time:             %s\n"
 "  End time:               %s\n"
-"  FD Files Written:       %s\n"
 "  SD Files Written:       %s\n"
-"  FD Bytes Written:       %s\n"
 "  SD Bytes Written:       %s\n"
 "  Rate:                   %.1f KB/s\n"
 "  Software Compression:   %s\n"
@@ -444,9 +456,7 @@ void mac_cleanup(JCR *jcr, int TermCode)
 "  Volume Session Id:      %d\n"
 "  Volume Session Time:    %d\n"
 "  Last Volume Bytes:      %s\n"
-"  Non-fatal FD errors:    %d\n"
 "  SD Errors:              %d\n"
-"  FD termination status:  %s\n"
 "  SD termination status:  %s\n"
 "  Termination:            %s\n\n"),
    VERSION,
@@ -460,9 +470,7 @@ void mac_cleanup(JCR *jcr, int TermCode)
         jcr->pool->hdr.name,
         sdt,
         edt,
-        edit_uint64_with_commas(jcr->jr.JobFiles, ec1),
         edit_uint64_with_commas(jcr->SDJobFiles, ec4),
-        edit_uint64_with_commas(jcr->jr.JobBytes, ec2),
         edit_uint64_with_commas(jcr->SDJobBytes, ec5),
         (float)kbps,
         compress,
@@ -470,11 +478,9 @@ void mac_cleanup(JCR *jcr, int TermCode)
         jcr->VolSessionId,
         jcr->VolSessionTime,
         edit_uint64_with_commas(mr.VolBytes, ec3),
-        jcr->Errors,
         jcr->SDErrors,
-        fd_term_msg,
         sd_term_msg,
-        term_msg);
+        term_code);
 
    Dmsg0(100, "Leave mac_cleanup()\n");
 }
index a0b2e0a1bf1f769a0757bcbdf02c8bfc6e884851..04ac72bfeecb5ddf9b4526f6fc676421327619c4 100644 (file)
@@ -16,7 +16,7 @@
  *   Version $Id$
  */
 /*
-   Copyright (C) 2000-2005 Kern Sibbald
+   Copyright (C) 2000-2006 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -250,10 +250,6 @@ bool start_storage_daemon_job(JCR *jcr, alist *rstore, alist *wstore)
          break;
       }
    }
-   if (ok) {
-      ok = bnet_fsend(sd, "run");
-      Dmsg1(100, ">stored: %s\n", sd->msg);
-   }
    return ok;
 }
 
index 4417a800a78d1bbfca61889b8505c8bb99f79f88..d65fa46a00bd22a5a07607987935c159233dc0ba 100644 (file)
@@ -71,7 +71,7 @@ extern int connect_to_file_daemon(JCR *jcr, int retry_interval,
                                   int max_retry_time, int verbose);
 extern bool send_include_list(JCR *jcr);
 extern bool send_exclude_list(JCR *jcr);
-extern bool send_bootstrap_file(JCR *jcr);
+extern bool send_bootstrap_file(JCR *jcr, BSOCK *sock);
 extern bool send_level_command(JCR *jcr);
 extern int get_attributes_and_put_in_catalog(JCR *jcr);
 extern int get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId);
index 3e5cc366fa198f9bae9c852aa63cbc46d2a6a5c1..ff7b18c99cdaa3d57da9538ccf448b4ec61af0f3 100644 (file)
@@ -18,7 +18,7 @@
  *   Version $Id$
  */
 /*
-   Copyright (C) 2000-2005 Kern Sibbald
+   Copyright (C) 2000-2006 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -43,6 +43,7 @@ static char storaddr[]     = "storage address=%s port=%d ssl=0\n";
 /* Responses received from File daemon */
 static char OKrestore[]   = "2000 OK restore\n";
 static char OKstore[]     = "2000 OK storage\n";
+static char OKbootstrap[] = "2000 OK bootstrap\n";
 
 /*
  * Do a restore of the specified files
@@ -107,6 +108,10 @@ bool do_restore(JCR *jcr)
    }
    Dmsg0(50, "Storage daemon connection OK\n");
 
+   if (!bnet_fsend(jcr->store_bsock, "run")) {
+      return false;
+   }
+
    /*
     * Start conversation with File daemon
     */
@@ -137,7 +142,8 @@ bool do_restore(JCR *jcr)
    /*
     * Send the bootstrap file -- what Volumes/files to restore
     */
-   if (!send_bootstrap_file(jcr)) {
+   if (!send_bootstrap_file(jcr, fd) ||
+       !response(jcr, fd, OKbootstrap, "Bootstrap", DISPLAY_ERROR)) {
       restore_cleanup(jcr, JS_ErrorTerminated);
       return false;
    }
index 7b9778ef8d9e96236fa2d0e0840a9f9b4526a135..dce647bbb81c4fd85807fa540c21b31b1ee97dd9 100644 (file)
@@ -147,7 +147,7 @@ bail_out:
 /*
  * Update Slots corresponding to Volumes in autochanger
  */
-int update_slots(UAContext *ua)
+void update_slots(UAContext *ua)
 {
    STORE *store;
    vol_list_t *vl, *vol_list = NULL;
@@ -159,11 +159,11 @@ int update_slots(UAContext *ua)
 
 
    if (!open_db(ua)) {
-      return 1;
+      return;
    }
    store = get_storage_resource(ua, true/*arg is storage*/);
    if (!store) {
-      return 1;
+      return;
    }
    set_storage(ua->jcr, store);
    drive = get_storage_drive(ua, store);
@@ -174,12 +174,12 @@ int update_slots(UAContext *ua)
    Dmsg1(100, "max_slots=%d\n", max_slots);
    if (max_slots <= 0) {
       bsendmsg(ua, _("No slots in changer to scan.\n"));
-      return 1;
+      return;
    }
    slot_list = (char *)malloc(max_slots+1);
    if (!get_user_slot_list(ua, slot_list, max_slots)) {
       free(slot_list);
-      return 1;
+      return;
    }
 
    vol_list = get_vol_list_from_SD(ua, scan);
@@ -273,7 +273,7 @@ bail_out:
    free(slot_list);
    close_sd_bsock(ua);
 
-   return 1;
+   return;
 }
 
 
index e544817cf032c7d7112bea36bfed361648ee9c38..470cd5bd9630b9871833967a01c00a63e6f4b05a 100644 (file)
@@ -34,7 +34,7 @@ extern struct s_kw ReplaceOptions[];
  *     run [job=]<job-name> level=<level-name>
  *
  * For Restore Jobs
- *     run <job-name> jobid=nn
+ *     run <job-name> 
  *
  *  Returns: 0 on error
  *           JobId if OK
@@ -47,6 +47,7 @@ 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 *migration_job_name;
    char *since = NULL;
    char *verify_list;
    bool cloned = false;
@@ -55,6 +56,7 @@ int run_cmd(UAContext *ua, const char *cmd)
    bool kw_ok;
    JOB *job = NULL;
    JOB *verify_job = NULL;
+   JOB *migration_job = NULL;
    STORE *store = NULL;
    CLIENT *client = NULL;
    FILESET *fileset = NULL;
@@ -81,6 +83,7 @@ int run_cmd(UAContext *ua, const char *cmd)
       "since",                        /* 18 since */
       "cloned",                       /* 19 cloned */
       "verifylist",                   /* 20 verify output list */
+      "migrationjob",                 /* 21 migration job name */
       NULL};
 
 #define YES_POS 14
@@ -101,6 +104,7 @@ int run_cmd(UAContext *ua, const char *cmd)
    bootstrap = NULL;
    replace = NULL;
    verify_job_name = NULL;
+   migration_job_name = NULL;
    catalog_name = NULL;
    verify_list = NULL;
 
@@ -254,6 +258,15 @@ int run_cmd(UAContext *ua, const char *cmd)
                verify_list = ua->argv[i];
                kw_ok = true;
                break;
+            case 21: /* Migration Job */
+               if (migration_job_name) {
+                  bsendmsg(ua, _("Migration Job specified twice.\n"));
+                  return 0;
+               }
+               migration_job_name = ua->argv[i];
+               kw_ok = true;
+               break;
+
 
             default:
                break;
@@ -401,6 +414,17 @@ int run_cmd(UAContext *ua, const char *cmd)
       verify_job = job->verify_job;
    }
 
+   if (migration_job_name) {
+      migration_job = (JOB *)GetResWithName(R_JOB, migration_job_name);
+      if (!migration_job) {
+         bsendmsg(ua, _("Migration Job \"%s\" not found.\n"), migration_job_name);
+         migration_job = select_job_resource(ua);
+      }
+   } else {
+      migration_job = job->verify_job;
+   }
+
+
    /*
     * Create JCR to run job.  NOTE!!! after this point, free_jcr()
     *  before returning.
@@ -409,6 +433,7 @@ int run_cmd(UAContext *ua, const char *cmd)
    set_jcr_defaults(jcr, job);
 
    jcr->verify_job = verify_job;
+   jcr->migration_job = migration_job;
    set_storage(jcr, store);
    jcr->client = client;
    jcr->fileset = fileset;
@@ -638,6 +663,32 @@ try_again:
               jcr->JobPriority);
       }
       break;
+   case JT_MIGRATE:
+      jcr->JobLevel = L_FULL;      /* default level */
+      bsendmsg(ua, _("Run Restore job\n"
+                     "JobName:       %s\n"
+                     "Bootstrap:     %s\n"
+                     "Where:         %s\n"
+                     "Replace:       %s\n"
+                     "FileSet:       %s\n"
+                     "Client:        %s\n"
+                     "Storage:       %s\n"
+                     "Migration Job: %s\n"
+                     "When:          %s\n"
+                     "Catalog:       %s\n"
+                     "Priority:      %d\n"),
+           job->hdr.name,
+           NPRT(jcr->RestoreBootstrap),
+           jcr->where?jcr->where:NPRT(job->RestoreWhere),
+           replace,
+           jcr->fileset->hdr.name,
+           jcr->client->hdr.name,
+           jcr->store->hdr.name,
+           jcr->migration_job->hdr.name,
+           bstrutime(dt, sizeof(dt), jcr->sched_time),
+           jcr->catalog->hdr.name,
+           jcr->JobPriority);
+      break;
    default:
       bsendmsg(ua, _("Unknown Job Type=%d\n"), jcr->JobType);
       goto bail_out;
index a95057209a8ecb23aec804ea3e9b2b8157108ea8..22e3e3a09864f6a71e01398275958e141c3633b2 100644 (file)
@@ -30,7 +30,8 @@ extern char *list_pool;               /* in sql_cmds.c */
 
 /* Imported functions */
 void set_pooldbr_from_poolres(POOL_DBR *pr, POOL *pool, e_pool_op op);
-int update_slots(UAContext *ua);
+void update_slots(UAContext *ua);
+
 
 
 /* Forward referenced functions */
@@ -340,6 +341,7 @@ static int update_volume(UAContext *ua)
    POOLMEM *query;
    char ed1[130];
    bool done = false;
+   int i;
    const char *kw[] = {
       _("VolStatus"),                /* 0 */
       _("VolRetention"),             /* 1 */
@@ -353,7 +355,7 @@ static int update_volume(UAContext *ua)
       _("AllFromPool"),              /* 9 */
       NULL };
 
-   for (int i=0; kw[i]; i++) {
+   for (i=0; kw[i]; i++) {
       int j;
       POOL_DBR pr;
       if ((j=find_arg_with_value(ua, kw[i])) > 0) {
@@ -403,9 +405,6 @@ static int update_volume(UAContext *ua)
    }
 
    for ( ; !done; ) {
-      if (!select_media_dbr(ua, &mr)) {
-         return 0;
-      }
       bsendmsg(ua, _("Updating Volume \"%s\"\n"), mr.VolumeName);
       start_prompt(ua, _("Parameters to modify:\n"));
       add_prompt(ua, _("Volume Status"));
@@ -422,7 +421,14 @@ static int update_volume(UAContext *ua)
       add_prompt(ua, _("Volume from Pool"));
       add_prompt(ua, _("All Volumes from Pool"));
       add_prompt(ua, _("Done"));
-      switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
+      i = do_prompt(ua, "", _("Select parameter to modify"), NULL, 0);  
+      /* For All Volumes from Pool we don't need a Volume record */
+      if (i != 12) {
+         if (!select_media_dbr(ua, &mr)) {  /* Get Volume record */
+            return 0;
+         }
+      }
+      switch (i) {
       case 0:                         /* Volume Status */
          /* Modify Volume Status */
          bsendmsg(ua, _("Current Volume status is: %s\n"), mr.VolStatus);
index 8081532727a3222543a380cc8d94a9616087183c..97be8d80953e7cd28471a2510396d6bffd184d3f 100644 (file)
@@ -14,7 +14,7 @@
  *   Version $Id$
  */
 /*
-   Copyright (C) 2000-2005 Kern Sibbald
+   Copyright (C) 2000-2006 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -43,6 +43,7 @@ static char storaddr[]     = "storage address=%s port=%d ssl=0\n";
 /* Responses received from File daemon */
 static char OKverify[]    = "2000 OK verify\n";
 static char OKstore[]     = "2000 OK storage\n";
+static char OKbootstrap[] = "2000 OK bootstrap\n";
 
 /* Forward referenced functions */
 static void prt_fname(JCR *jcr);
@@ -208,6 +209,10 @@ bool do_verify(JCR *jcr)
          return false;
       }
       Dmsg0(50, "Storage daemon connection OK\n");
+
+      if (!bnet_fsend(jcr->store_bsock, "run")) {
+         return false;
+      }
    }
    /*
     * OK, now connect to the File daemon
@@ -258,7 +263,8 @@ bool do_verify(JCR *jcr)
       /*
        * Send the bootstrap file -- what Volumes/files to restore
        */
-      if (!send_bootstrap_file(jcr)) {
+      if (!send_bootstrap_file(jcr, fd) ||
+          !response(jcr, fd, OKbootstrap, "Bootstrap", DISPLAY_ERROR)) {
          return false;
       }
 
index b2725a1f9f6e727978cddccb2aa54f1f76c0d9aa..fa5f9bcd4e4d6e1ad02dee60391cf08d0feb94c9 100644 (file)
@@ -5,6 +5,6 @@
 Director {
   Name = rufus-dir
   DIRport = 8101
-  address = rufus
+  address = localhost
   Password = UA_password
 }
index 869bde86a7ba988c59f0fcf173ec9529c4ba6236..bc6700de2c3a447e01fa26870557304e9af89fcf 100644 (file)
@@ -165,6 +165,7 @@ public:
    BSOCK *ua;                         /* User agent */
    JOB *job;                          /* Job resource */
    JOB *verify_job;                   /* Job resource of verify target job */
+   JOB *migration_job;                /* Job resource of migration target job */
    alist *storage;                    /* Storage possibilities */
    STORE *store;                      /* Storage daemon selected */
    CLIENT *client;                    /* Client resource */
index 41307bd07b5d9ecca4cea74468e612154dfb09ca..aaa75baf1f429899ae6fa26b2fff8e6877c27ed3 100755 (executable)
@@ -33,7 +33,7 @@
  *   Version $Id$
  */
 /*
-   Copyright (C) 2000-2005 Kern Sibbald
+   Copyright (C) 2000-2006 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -136,7 +136,7 @@ struct s_kw {
  *
  *   tape label      label code = token
  */
-struct s_kw tapelabels[] = {
+static s_kw tapelabels[] = {
    {"bacula",        B_BACULA_LABEL},
    {"ansi",          B_ANSI_LABEL},
    {"ibm",           B_IBM_LABEL},
index 3851a1681d2cdbb44edc73d6aa331e00f07cda70..e09428754571e96678d67591a4ecae815df05cc3 100644 (file)
@@ -28,18 +28,18 @@ SVRSRCS = stored.c ansi_label.c \
          askdir.c authenticate.c \
          block.c butil.c dev.c \
          device.c dircmd.c dvd.c ebcdic.c fd_cmds.c job.c \
-         label.c match_bsr.c mount.c parse_bsr.c \
+         label.c mac.c match_bsr.c mount.c parse_bsr.c \
          pythonsd.c read.c read_record.c record.c \
-         reserve.c \
+         reserve.c scan.c \
          spool.c status.c stored_conf.c wait.c
 SVROBJS = stored.o ansi_label.o \
          autochanger.o acquire.o append.o \
          askdir.o authenticate.o \
          block.o butil.o dev.o \
          device.o dircmd.o dvd.o ebcdic.c fd_cmds.o job.o \
-         label.o match_bsr.o mount.o parse_bsr.o \
+         label.o mac.o match_bsr.o mount.o parse_bsr.o \
          pythonsd.o read.o read_record.o record.o \
-         reserve.o \
+         reserve.o scan.o \
          spool.o status.o stored_conf.o wait.o
 
 # btape
@@ -50,32 +50,32 @@ TAPESRCS = btape.c block.c butil.c dev.c device.c label.c \
 TAPEOBJS = btape.o block.o butil.o dev.o device.o label.o \
           ansi_label.o dvd.o ebcdic.o \
           autochanger.o acquire.o mount.o record.o read_record.o \
-          stored_conf.o match_bsr.o parse_bsr.o spool.o wait.o
+          stored_conf.o match_bsr.o parse_bsr.o scan.o spool.o wait.o
 
 # bls
 BLSOBJS = bls.o block.o butil.o device.o dev.o label.o match_bsr.o \
          ansi_label.o dvd.o ebcdic.o \
          autochanger.o acquire.o mount.o parse_bsr.o record.o  \
-         read_record.o stored_conf.o spool.o wait.o
+         read_record.o scan.o stored_conf.o spool.o wait.o
 
 # bextract
 BEXTOBJS = bextract.o block.o device.o dev.o label.o record.o \
           ansi_label.o dvd.o ebcdic.o \
           autochanger.o acquire.o mount.o match_bsr.o parse_bsr.o butil.o \
           pythonsd.o \
-          read_record.o stored_conf.o spool.o wait.o
+          read_record.o scan.o stored_conf.o spool.o wait.o
 
 # bscan
 SCNOBJS = bscan.o block.o device.o dev.o label.o \
          ansi_label.o dvd.o ebcdic.o \
          autochanger.o acquire.o mount.o record.o match_bsr.o parse_bsr.o \
-         butil.o read_record.o stored_conf.o spool.o wait.o
+         butil.o read_record.o scan.o stored_conf.o spool.o wait.o
 
 # bcopy
 COPYOBJS = bcopy.o block.o device.o dev.o label.o \
           ansi_label.o dvd.o ebcdic.o \
           autochanger.o acquire.o mount.o record.o match_bsr.o parse_bsr.o \
-          butil.o read_record.o stored_conf.o spool.o wait.o
+          butil.o read_record.o scan.o stored_conf.o spool.o wait.o
 
 
 
index 44002603b19bb015dc99a04b39e168368d10c87b..fa69e3b4fa63e4500df23df2eb42493a2585165a 100644 (file)
@@ -6,7 +6,7 @@
  *   Version $Id$
  */
 /*
-   Copyright (C) 2002-2005 Kern Sibbald
+   Copyright (C) 2002-2006 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -86,6 +86,10 @@ void free_dcr(DCR *dcr)
    if (dcr->reserved_device) {
       lock_device(dev);
       dev->reserved_device--;
+      /* If we set read mode in reserving, remove it */
+      if (dev->can_read()) {
+         dev->clear_read();
+      }
       Dmsg1(100, "Dec reserve=%d\n", dev->reserved_device);
       dcr->reserved_device = false;
       if (dev->num_writers < 0) {
@@ -227,10 +231,11 @@ DCR *acquire_device_for_read(DCR *dcr)
 default_path:
          tape_previously_mounted = true;
          
-         /* If the device requires mount, close it, so the device can be ejected.
-          * FIXME: This should perhaps be done for all devices. */
+         /*
+          * If the device requires mount, close it, so the device can be ejected.
+          */
          if (dev->requires_mount()) {
-            force_close_device(dev);
+            dev->close();
          }
          
          /* Call autochanger only once unless ask_sysop called */
@@ -481,8 +486,7 @@ bool release_device(DCR *dcr)
 
    /* If no writers, close if file or !CAP_ALWAYS_OPEN */
    if (dev->num_writers == 0 && (!dev->is_tape() || !dev_cap(dev, CAP_ALWAYSOPEN))) {
-      offline_or_rewind_dev(dev);
-      close_device(dev);
+      dev->close();
    }
 
    /* Fire off Alert command and include any output */
index 1e5153e01923f62382b3733d666de22e6e1e24b7..cfa936df02824c175a23758ea1fecc4f17e07414 100644 (file)
@@ -251,10 +251,7 @@ bool do_append_data(JCR *jcr)
    /* Create Job status for end of session label */
    set_jcr_job_status(jcr, ok?JS_Terminated:JS_ErrorTerminated);
 
-   Dmsg1(200, "Write session label JobStatus=%d\n", jcr->JobStatus);
-   if ((!ok || job_canceled(jcr)) && dev->VolCatInfo.VolCatName[0] == 0) {
-      Pmsg0(000, _("NULL Volume name. This shouldn't happen!!!\n"));
-   }
+   Dmsg1(200, "Write EOS label JobStatus=%c\n", jcr->JobStatus);
 
    /*
     * If !OK, check if we can still write. This may not be the case
index b5b4c106b3caed6da2dcbf791c4a33136941e483..93984bcc9880566b805b136b89eb47931d014970 100644 (file)
@@ -7,7 +7,7 @@
  *   Version $Id$
  */
 /*
-   Copyright (C) 2000-2005 Kern Sibbald
+   Copyright (C) 2000-2006 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -510,7 +510,7 @@ bool dir_ask_sysop_to_mount_volume(DCR *dcr)
       }
 
       if (dev->is_dvd()) {   
-         unmount_dev(dev, 0);
+         unmount_dvd(dev, 0);
       }
       
       /*
index bd08996814a624e2a4fadb8fd4cf783696ed20f4..821c856c2c2e06a79e8033c89bdfc3ec7fdd9bf2 100644 (file)
@@ -104,6 +104,9 @@ int autoload_device(DCR *dcr, int writing, BSOCK *dir)
    int rtn_stat = -1;                 /* error status */
    POOLMEM *changer;
 
+   if (!dev->is_autochanger()) {
+      return 0;
+   }
    slot = dcr->VolCatInfo.InChanger ? dcr->VolCatInfo.Slot : 0;
    /*
     * Handle autoloaders here.  If we cannot autoload it, we
@@ -151,8 +154,7 @@ int autoload_device(DCR *dcr, int writing, BSOCK *dir)
          dcr->VolCatInfo.Slot = slot;    /* slot to be loaded */
          changer = edit_device_codes(dcr, changer, 
                       dcr->device->changer_command, "load");
-         offline_or_rewind_dev(dev);
-         force_close_device(dev);
+         dev->close();
          status = run_program(changer, timeout, NULL);
          if (status == 0) {
             Jmsg(jcr, M_INFO, 0, _("3305 Autochanger \"load slot %d, drive %d\", status is OK.\n"),
@@ -297,8 +299,7 @@ bool unload_autochanger(DCR *dcr, int loaded)
       dcr->VolCatInfo.Slot = loaded;
       changer = edit_device_codes(dcr, changer, 
                    dcr->device->changer_command, "unload");
-      offline_or_rewind_dev(dev);
-      force_close_device(dev);
+      dev->close();
       int stat = run_program(changer, timeout, NULL);
       dcr->VolCatInfo.Slot = slot;
       if (stat != 0) {
@@ -373,8 +374,7 @@ static bool unload_other_drive(DCR *dcr, int slot)
    changer_cmd = edit_device_codes(dcr, changer_cmd, 
                 dcr->device->changer_command, "unload");
    Dmsg1(200, "Run program=%s\n", changer_cmd);
-   offline_or_rewind_dev(dev);
-   force_close_device(dev);
+   dev->close();
    int stat = run_program(changer_cmd, timeout, NULL);
    dcr->VolCatInfo.Slot = save_slot;
    dcr->dev = save_dev;
index 5f3f2feb0442342f7ef6136d956b013efe2bd4bd..a7e7fe1cf443db4d3f4527a8e09136c5452e11d0 100644 (file)
@@ -9,7 +9,7 @@
  *
  */
 /*
-   Copyright (C) 2001-2005 Kern Sibbald
+   Copyright (C) 2001-2006 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -613,13 +613,13 @@ static void reread_last_block(DCR *dcr)
     */
    if (dev->is_tape() && dev_cap(dev, CAP_BSR)) {
       /* Now back up over what we wrote and read the last block */
-      if (!bsf_dev(dev, 1)) {
+      if (!dev->bsf(1)) {
          berrno be;
          ok = false;
          Jmsg(jcr, M_ERROR, 0, _("Backspace file at EOT failed. ERR=%s\n"), 
               be.strerror(dev->dev_errno));
       }
-      if (ok && dev_cap(dev, CAP_TWOEOF) && !bsf_dev(dev, 1)) {
+      if (ok && dev->has_cap(CAP_TWOEOF) && !dev->bsf(1)) {
          berrno be;
          ok = false;
          Jmsg(jcr, M_ERROR, 0, _("Backspace file at EOT failed. ERR=%s\n"), 
index 099736b338a712c594e0f2038eb33a771008c91e..a74f27554d75386e82d298f0a855eab96213d760 100644 (file)
@@ -1255,10 +1255,7 @@ bool dir_ask_sysop_to_mount_volume(DCR *dcr)
    DEVICE *dev = dcr->dev;
    Dmsg0(20, "Enter dir_ask_sysop_to_mount_volume\n");
    /* Close device so user can use autochanger if desired */
-   if (dev_cap(dev, CAP_OFFLINEUNMOUNT)) {
-      offline_dev(dev);
-   }
-   force_close_device(dev);
+   dev->close();
    fprintf(stderr, _("Mount Volume \"%s\" on device %s and press return when ready: "),
          dcr->VolumeName, dev->print_name());
    getchar();
index e6ef6ec9145afe7051a0f90dc9fdcc7b17cb36ce..aca4acc047fd7579ddf994d5ac47f3052401231d 100644 (file)
@@ -14,7 +14,7 @@
  *
  */
 /*
-   Copyright (C) 2000-2005 Kern Sibbald
+   Copyright (C) 2000-2006 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -483,7 +483,7 @@ static void weofcmd()
  */
 static void eomcmd()
 {
-   if (!eod_dev(dev)) {
+   if (!dev->eod()) {
       Pmsg1(0, "%s", strerror_dev(dev));
       return;
    } else {
@@ -513,7 +513,7 @@ static void bsfcmd()
       num = 1;
    }
 
-   if (!bsf_dev(dev, num)) {
+   if (!dev->bsf(num)) {
       Pmsg1(0, _("Bad status from bsf. ERR=%s\n"), strerror_dev(dev));
    } else {
       Pmsg2(0, _("Backspaced %d file%s.\n"), num, num==1?"":"s");
@@ -699,12 +699,12 @@ static int re_read_block_test()
    if (dev_cap(dev, CAP_TWOEOF)) {
       weofcmd();
    }
-   if (!bsf_dev(dev, 1)) {
+   if (!dev->bsf(1)) {
       Pmsg1(0, _("Backspace file failed! ERR=%s\n"), strerror_dev(dev));
       goto bail_out;
    }
    if (dev_cap(dev, CAP_TWOEOF)) {
-      if (!bsf_dev(dev, 1)) {
+      if (!dev->bsf(1)) {
          Pmsg1(0, _("Backspace file failed! ERR=%s\n"), strerror_dev(dev));
          goto bail_out;
       }
@@ -1053,7 +1053,7 @@ static int append_test()
    if (dev_cap(dev, CAP_TWOEOF)) {
       weofcmd();
    }
-   force_close_device(dev);              /* release device */
+   dev->close();              /* release device */
    if (!open_the_device()) {
       return -1;
    }
@@ -1147,9 +1147,8 @@ try_again:
    Dmsg1(100, "Results from loaded query=%s\n", results);
    if (loaded) {
       dcr->VolCatInfo.Slot = loaded;
-      offline_or_rewind_dev(dev);
       /* We are going to load a new tape, so close the device */
-      force_close_device(dev);
+      dev->close();
       Pmsg2(-1, _("3302 Issuing autochanger \"unload %d %d\" command.\n"),
          loaded, dev->drive_index);
       changer = edit_device_codes(dcr, changer, 
@@ -1174,7 +1173,7 @@ try_again:
    changer = edit_device_codes(dcr, changer, 
                 dcr->device->changer_command, "load");
    Dmsg1(100, "Changer=%s\n", changer);
-   force_close_device(dev);
+   dev->close();
    status = run_program(changer, timeout, results);
    if (status == 0) {
       Pmsg2(-1,  _("3303 Autochanger \"load %d %d\" status is OK.\n"),
@@ -2103,11 +2102,11 @@ static void do_unfill()
       /* Multiple Volume tape */
       /* Close device so user can use autochanger if desired */
       if (dev_cap(dev, CAP_OFFLINEUNMOUNT)) {
-         offline_dev(dev);
+         dev->offline();
       }
       autochanger = autoload_device(dcr, 1, NULL);
       if (!autochanger) {
-         force_close_device(dev);
+         dev->close();
          get_cmd(_("Mount first tape. Press enter when ready: "));
       }
       free_restore_volume_list(jcr);
@@ -2115,8 +2114,7 @@ static void do_unfill()
       set_volume_name("TestVolume1", 1);
       jcr->bsr = NULL;
       create_restore_volume_list(jcr);
-      close_device(dev);
-      dev->state &= ~(ST_READ|ST_APPEND);
+      dev->close();
       dev->num_writers = 0;
       if (!acquire_device_for_read(dcr)) {
          Pmsg1(-1, "%s", dev->errmsg);
@@ -2167,7 +2165,7 @@ static void do_unfill()
    /* Multiple Volume tape */
    /* Close device so user can use autochanger if desired */
    if (dev_cap(dev, CAP_OFFLINEUNMOUNT)) {
-      offline_dev(dev);
+      dev->offline();
    }
 
    free_restore_volume_list(jcr);
@@ -2176,7 +2174,7 @@ static void do_unfill()
    create_restore_volume_list(jcr);
    autochanger = autoload_device(dcr, 1, NULL);
    if (!autochanger) {
-      force_close_device(dev);
+      dev->close();
       get_cmd(_("Mount second tape. Press enter when ready: "));
    }
 
@@ -2677,11 +2675,7 @@ bool dir_ask_sysop_to_mount_volume(DCR *dcr)
    if (dcr->VolumeName[0] == 0) {
       return dir_ask_sysop_to_create_appendable_volume(dcr);
    }
-   /* Close device so user can use autochanger if desired */
-   if (dev_cap(dev, CAP_OFFLINEUNMOUNT)) {
-      offline_dev(dev);
-   }
-   force_close_device(dev);
+   dev->close();
    Pmsg1(-1, "%s", dev->errmsg);           /* print reason */
    if (dcr->VolumeName[0] == 0 || strcmp(dcr->VolumeName, "TestVolume2") == 0) {
       fprintf(stderr, _("Mount second Volume on device %s and press return when ready: "),
@@ -2706,11 +2700,11 @@ bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr)
    }
    /* Close device so user can use autochanger if desired */
    if (dev_cap(dev, CAP_OFFLINEUNMOUNT)) {
-      offline_dev(dev);
+      dev->offline();
    }
    autochanger = autoload_device(dcr, 1, NULL);
    if (!autochanger) {
-      force_close_device(dev);
+      dev->close();
       fprintf(stderr, _("Mount blank Volume on device %s and press return when ready: "),
          dev->print_name());
       getchar();
@@ -2753,8 +2747,7 @@ static bool my_mount_next_read_volume(DCR *dcr)
    set_volume_name("TestVolume2", 2);
    jcr->bsr = NULL;
    create_restore_volume_list(jcr);
-   close_device(dev);
-   dev->clear_read();
+   dev->close();
    if (!acquire_device_for_read(dcr)) {
       Pmsg2(0, _("Cannot open Dev=%s, Vol=%s\n"), dev->print_name(), dcr->VolumeName);
       return false;
index acb79b1d2b8959ab39327bf1fdb46d8c53a2c2db..8e1e224f1e5316e747f9141cba3a2b35a6c277b4 100644 (file)
@@ -29,7 +29,7 @@
  *   Version $Id$
  */
 /*
-   Copyright (C) 2000-2005 Kern Sibbald
+   Copyright (C) 2000-2006 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -99,36 +99,37 @@ DEVICE *
 init_dev(JCR *jcr, DEVRES *device)
 {
    struct stat statp;
-   bool tape, fifo;
    int errstat;
    DCR *dcr = NULL;
    DEVICE *dev;
 
-   /* Check that device is available */
-   if (stat(device->device_name, &statp) < 0) {
-      berrno be;
-      Jmsg2(jcr, M_ERROR, 0, _("Unable to stat device %s: ERR=%s\n"), 
-         device->device_name, be.strerror());
-      return NULL;
-   }
    
-   
-   tape = false;
-   fifo = false;
-   if (S_ISDIR(statp.st_mode)) {
-      tape = false;
-   } else if (S_ISCHR(statp.st_mode)) {
-      tape = true;
-   } else if (S_ISFIFO(statp.st_mode)) {
-      fifo = true;
-   } else if (!(device->cap_bits & CAP_REQMOUNT)) {
-      Jmsg2(jcr, M_ERROR, 0, _("%s is an unknown device type. Must be tape or directory\n"
-            " or have RequiresMount=yes for DVD. st_mode=%x\n"),
-         device->device_name, statp.st_mode);
-      return NULL;
-   }
-
-   dev = (DEVICE *)get_memory(sizeof(DEVICE));
+   /* If no device type specified, try to guess */
+   if (!device->dev_type) {
+      /* Check that device is available */
+      if (stat(device->device_name, &statp) < 0) {
+         berrno be;
+         Jmsg2(jcr, M_ERROR, 0, _("Unable to stat device %s: ERR=%s\n"), 
+            device->device_name, be.strerror());
+         return NULL;
+      }
+      if (S_ISDIR(statp.st_mode)) {
+         device->dev_type = B_FILE_DEV;
+      } else if (S_ISCHR(statp.st_mode)) {
+         device->dev_type = B_TAPE_DEV;
+      } else if (S_ISFIFO(statp.st_mode)) {
+         device->dev_type = B_FILE_DEV;
+      } else if (!(device->cap_bits & CAP_REQMOUNT)) {
+         Jmsg2(jcr, M_ERROR, 0, _("%s is an unknown device type. Must be tape or directory\n"
+               " or have RequiresMount=yes for DVD. st_mode=%x\n"),
+            device->device_name, statp.st_mode);
+         return NULL;
+      } else {
+         device->dev_type = B_DVD_DEV;
+      }
+   }
+
+   dev = (DEVICE *)malloc(sizeof(DEVICE));
    memset(dev, 0, sizeof(DEVICE));
    dev->state = ST_MALLOC;
 
@@ -151,10 +152,10 @@ init_dev(JCR *jcr, DEVRES *device)
    dev->max_spool_size = device->max_spool_size;
    dev->drive_index = device->drive_index;
    dev->autoselect = device->autoselect;
-   if (tape) { /* No parts on tapes */
+   dev->dev_type = device->dev_type;
+   if (dev->is_tape()) { /* No parts on tapes */
       dev->max_part_size = 0;
-   }
-   else {
+   } else {
       dev->max_part_size = device->max_part_size;
    }
    /* Sanity check */
@@ -163,34 +164,30 @@ init_dev(JCR *jcr, DEVRES *device)
    }
    dev->device = device;
 
-   if (tape) {
-      dev->state |= ST_TAPE;
-   } else if (fifo) {
-      dev->state |= ST_FIFO;
+   if (dev->is_fifo()) {
       dev->capabilities |= CAP_STREAM; /* set stream device */
-   } else {
-      dev->state |= ST_FILE;
    }
 
    /* If the device requires mount :
     * - Check that the mount point is available 
     * - Check that (un)mount commands are defined
     */
-   if (dev->is_file() && dev->requires_mount()) {
-      if (stat(device->mount_point, &statp) < 0) {
+   if ((dev->is_file() || dev->is_dvd()) && dev->requires_mount()) {
+      if (!device->mount_point || stat(device->mount_point, &statp) < 0) {
          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;
       }
+   }
+   if (dev->is_dvd()) {
       if (!device->mount_command || !device->unmount_command) {
          Jmsg0(jcr, M_ERROR_TERM, 0, _("Mount and unmount commands must defined for a device which requires mount.\n"));
       }
       if (!device->write_part_command) {
          Jmsg0(jcr, M_ERROR_TERM, 0, _("Write part command must be defined for a device which requires mount.\n"));
       }
-      dev->state |= ST_DVD;
    }
 
    if (dev->max_block_size > 1000000) {
@@ -260,6 +257,7 @@ init_dev(JCR *jcr, DEVRES *device)
 int
 DEVICE::open(DCR *dcr, int omode)
 {
+   int preserve = 0;
    if (is_open()) {
       if (openmode == omode) {
          return fd;
@@ -267,13 +265,14 @@ DEVICE::open(DCR *dcr, int omode)
         ::close(fd); /* use system close so correct mode will be used on open */
         clear_opened();
         Dmsg0(100, "Close fd for mode change.\n");
+        preserve = state & (ST_LABEL|ST_APPEND|ST_READ);
       }
    }
    if (dcr) {
       bstrncpy(VolCatInfo.VolCatName, dcr->VolumeName, sizeof(VolCatInfo.VolCatName));
    }
 
-   Dmsg4(29, "open dev: tape=%d dev_name=%s vol=%s mode=%s\n", is_tape(),
+   Dmsg4(29, "open dev: type=%d dev_name=%s vol=%s mode=%s\n", dev_type,
          print_name(), VolCatInfo.VolCatName, mode_to_str(omode));
    state &= ~(ST_LABEL|ST_APPEND|ST_READ|ST_EOT|ST_WEOT|ST_EOF);
    label_type = B_BACULA_LABEL;
@@ -284,7 +283,11 @@ DEVICE::open(DCR *dcr, int omode)
       open_dvd_device(dcr, omode);
    } else {
       Dmsg1(100, "call open_file_device mode=%s\n", mode_to_str(omode));
-      open_file_device(omode);
+      open_file_device(dcr, omode);
+   }
+   state |= preserve;                 /* reset any important state info */
+   if (preserve) {
+      Dmsg1(000, "preserve=0x%x\n", preserve);
    }
    return fd;
 }
@@ -296,11 +299,7 @@ void DEVICE::set_mode(int new_mode)
       mode = O_CREAT | O_RDWR | O_BINARY;
       break;
    case OPEN_READ_WRITE:
-      if (is_dvd() || is_file()) {
-         mode = O_CREAT | O_RDWR | O_BINARY;
-      } else {
-         mode = O_RDWR | O_BINARY;
-      }
+      mode = O_RDWR | O_BINARY;
       break;
    case OPEN_READ_ONLY:
       mode = O_RDONLY | O_BINARY;
@@ -404,15 +403,13 @@ void DEVICE::set_blocking()
 /*
  * Open a file device
  */
-void DEVICE::open_file_device(int omode) 
+void DEVICE::open_file_device(DCR *dcr, int omode) 
 {
    POOL_MEM archive_name(PM_FNAME);
 
    /*
     * Handle opening of File Archive (not a tape)
     */     
-   Dmsg3(29, "Enter: open_file_dev: %s dev=%s mode=%s\n", is_dvd()?"DVD":"disk",
-         archive_name.c_str(), mode_to_str(omode));
 
    if (VolCatInfo.VolCatName[0] == 0) {
       Mmsg(errmsg, _("Could not open file device %s. No Volume name given.\n"),
@@ -426,15 +423,13 @@ void DEVICE::open_file_device(int omode)
       pm_strcat(archive_name, "/");
    }
    pm_strcat(archive_name, VolCatInfo.VolCatName);
+
+   mount(1);                          /* do mount if required */
          
-   Dmsg3(29, "open dev: %s dev=%s mode=%s\n", is_dvd()?"DVD":"disk",
-         archive_name.c_str(), mode_to_str(omode));
    openmode = omode;
-   Dmsg2(100, "openmode=%d %s\n", openmode, mode_to_str(openmode));
-   
    set_mode(omode);
    /* If creating file, give 0640 permissions */
-   Dmsg3(29, "mode=%s open(%s, 0x%x, 0640)\n", mode_to_str(omode), 
+   Dmsg3(29, "open disk: mode=%s open(%s, 0x%x, 0640)\n", mode_to_str(omode), 
          archive_name.c_str(), mode);
    /* Use system open() */
    if ((fd = ::open(archive_name.c_str(), mode, 0640)) < 0) {
@@ -448,13 +443,13 @@ void DEVICE::open_file_device(int omode)
       dev_errno = 0;
       update_pos_dev(this);                /* update position */
    }
-   Dmsg5(29, "open dev: %s fd=%d opened, part=%d/%d, part_size=%u\n", 
-      is_dvd()?"DVD":"disk", fd, part, num_parts, 
-      part_size);
+   Dmsg4(29, "open dev: disk fd=%d opened, part=%d/%d, part_size=%u\n", 
+      fd, part, num_parts, part_size);
 }
 
 /*
- * Open a DVD device. N.B. at this point, dcr->VolCatInfo.VolCatName (NB:??? I think it's VolCatInfo.VolCatName that is right)
+ * Open a DVD device. N.B. at this point, dcr->VolCatInfo.VolCatName 
+ *  (NB:??? I think it's VolCatInfo.VolCatName that is right)
  *  has the desired Volume name, but there is NO assurance that
  *  any other field of VolCatInfo is correct.
  */
@@ -491,21 +486,20 @@ void DEVICE::open_dvd_device(DCR *dcr, int omode)
       dcr->dev->num_parts = dcr->VolCatInfo.VolCatParts;
    }
 
-   if (mount_dev(this, 1)) {
+   if (mount_dvd(this, 1)) {
       if ((num_parts == 0) && (!truncating)) {
          /* If we can mount the device, and we are not truncating the DVD, we usually want to abort. */
          /* There is one exception, if there is only one 0-sized file on the DVD, with the right volume name,
-          * we continue (it's the method used by truncate_dvd_dev to truncate a volume). */
+          * we continue (it's the method used by truncate_dvd to truncate a volume). */
          if (!check_can_write_on_non_blank_dvd(dcr)) {
             Mmsg(errmsg, _("The media in the device %s is not empty, please blank it before writing anything to it.\n"), print_name());
             Emsg0(M_FATAL, 0, errmsg);
-            unmount_dev(this, 1); /* Unmount the device, so the operator can change it. */
+            unmount_dvd(this, 1); /* Unmount the device, so the operator can change it. */
             clear_opened();
             return;
          }
       }
-   }
-   else {
+   } else {
       /* We cannot mount the device */
       if (num_parts == 0) {
          /* Run free space, check there is a media. */
@@ -753,56 +747,54 @@ void DEVICE::set_ateot()
  *  Returns: true  on succes
  *           false on error
  */
-bool
-eod_dev(DEVICE *dev)
+bool DEVICE::eod()
 {
    struct mtop mt_com;
    struct mtget mt_stat;
    bool ok = true;
    off_t pos;
 
-   if (dev->fd < 0) {
-      dev->dev_errno = EBADF;
-      Mmsg1(dev->errmsg, _("Bad call to eod_dev. Device %s not open\n"),
-            dev->print_name());
+   if (fd < 0) {
+      dev_errno = EBADF;
+      Mmsg1(errmsg, _("Bad call to eod_dev. Device %s not open\n"), print_name());
       return false;
    }
 
 #if defined (__digital__) && defined (__unix__)
-   return dev->fsf(dev->VolCatInfo.VolCatFiles);
+   return fsf(VolCatInfo.VolCatFiles);
 #endif
 
    Dmsg0(29, "eod_dev\n");
-   if (dev->at_eot()) {
+   if (at_eot()) {
       return true;
    }
-   dev->state &= ~(ST_EOF);  /* remove EOF flags */
-   dev->block_num = dev->file = 0;
-   dev->file_size = 0;
-   dev->file_addr = 0;
-   if (dev->state & (ST_FIFO | ST_PROG)) {
+   state &= ~(ST_EOF);  /* remove EOF flags */
+   block_num = file = 0;
+   file_size = 0;
+   file_addr = 0;
+   if (is_fifo() || is_prog()) {
       return true;
    }
-   if (!dev->is_tape()) {
-      pos = lseek_dev(dev, (off_t)0, SEEK_END);
+   if (!is_tape()) {
+      pos = lseek_dev(this, (off_t)0, SEEK_END);
 //    Dmsg1(100, "====== Seek to %lld\n", pos);
       if (pos >= 0) {
-         update_pos_dev(dev);
-         dev->state |= ST_EOT;
+         update_pos_dev(this);
+         state |= ST_EOT;
          return true;
       }
-      dev->dev_errno = errno;
+      dev_errno = errno;
       berrno be;
-      Mmsg2(dev->errmsg, _("lseek_dev error on %s. ERR=%s.\n"),
-             dev->print_name(), be.strerror());
+      Mmsg2(errmsg, _("lseek_dev error on %s. ERR=%s.\n"),
+             print_name(), be.strerror());
       return false;
    }
 #ifdef MTEOM
-   if (dev_cap(dev, CAP_FASTFSF) && !dev_cap(dev, CAP_EOM)) {
+   if (has_cap(CAP_FASTFSF) && !has_cap(CAP_EOM)) {
       Dmsg0(100,"Using FAST FSF for EOM\n");
       /* If unknown position, rewind */
-      if (!dev_get_os_pos(dev, &mt_stat)) {
-        if (!dev->rewind(NULL)) {
+      if (!dev_get_os_pos(this, &mt_stat)) {
+        if (!rewind(NULL)) {
           return false;
         }
       }
@@ -817,33 +809,33 @@ eod_dev(DEVICE *dev)
       }
    }
 
-   if (dev_cap(dev, CAP_MTIOCGET) && (dev_cap(dev, CAP_FASTFSF) || dev_cap(dev, CAP_EOM))) {
-      if (dev_cap(dev, CAP_EOM)) {
+   if (has_cap(CAP_MTIOCGET) && (has_cap(CAP_FASTFSF) || has_cap(CAP_EOM))) {
+      if (has_cap(CAP_EOM)) {
          Dmsg0(100,"Using EOM for EOM\n");
          mt_com.mt_op = MTEOM;
          mt_com.mt_count = 1;
       }
 
-      if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) {
+      if (ioctl(fd, MTIOCTOP, (char *)&mt_com) < 0) {
          berrno be;
-         clrerror_dev(dev, mt_com.mt_op);
+         clrerror_dev(this, mt_com.mt_op);
          Dmsg1(50, "ioctl error: %s\n", be.strerror());
-         update_pos_dev(dev);
-         Mmsg2(dev->errmsg, _("ioctl MTEOM error on %s. ERR=%s.\n"),
-            dev->print_name(), be.strerror());
+         update_pos_dev(this);
+         Mmsg2(errmsg, _("ioctl MTEOM error on %s. ERR=%s.\n"),
+            print_name(), be.strerror());
          return false;
       }
 
-      if (!dev_get_os_pos(dev, &mt_stat)) {
+      if (!dev_get_os_pos(this, &mt_stat)) {
          berrno be;
-         clrerror_dev(dev, -1);
-         Mmsg2(dev->errmsg, _("ioctl MTIOCGET error on %s. ERR=%s.\n"),
-            dev->print_name(), be.strerror());
+         clrerror_dev(this, -1);
+         Mmsg2(errmsg, _("ioctl MTIOCGET error on %s. ERR=%s.\n"),
+            print_name(), be.strerror());
          return false;
       }
       Dmsg2(100, "EOD file=%d block=%d\n", mt_stat.mt_fileno, mt_stat.mt_blkno);
-      dev->set_ateof();
-      dev->file = mt_stat.mt_fileno;
+      set_ateof();
+      file = mt_stat.mt_fileno;
    } else {
 #else
    {
@@ -851,29 +843,29 @@ eod_dev(DEVICE *dev)
       /*
        * Rewind then use FSF until EOT reached
        */
-      if (!dev->rewind(NULL)) {
+      if (!rewind(NULL)) {
          return false;
       }
       /*
        * Move file by file to the end of the tape
        */
       int file_num;
-      for (file_num=dev->file; !dev->at_eot(); file_num++) {
+      for (file_num=file; !at_eot(); file_num++) {
          Dmsg0(200, "eod_dev: doing fsf 1\n");
-         if (!dev->fsf(1)) {
+         if (!fsf(1)) {
             Dmsg0(200, "fsf error.\n");
             return false;
          }
          /*
           * Avoid infinite loop by ensuring we advance.
           */
-         if (file_num == (int)dev->file) {
+         if (file_num == (int)file) {
             struct mtget mt_stat;
             Dmsg1(100, "fsf did not advance from file %d\n", file_num);
-            dev->set_ateof();
-            if (dev_get_os_pos(dev, &mt_stat)) {
-               Dmsg2(100, "Adjust file from %d to %d\n", dev->file , mt_stat.mt_fileno);
-               dev->file = mt_stat.mt_fileno;
+            set_ateof();
+            if (dev_get_os_pos(this, &mt_stat)) {
+               Dmsg2(100, "Adjust file from %d to %d\n", file , mt_stat.mt_fileno);
+               file = mt_stat.mt_fileno;
             }       
             break;
          }
@@ -884,21 +876,21 @@ eod_dev(DEVICE *dev)
     * MTEOM, so we must backup so that appending overwrites
     * the second EOF.
     */
-   if (dev_cap(dev, CAP_BSFATEOM)) {
+   if (has_cap(CAP_BSFATEOM)) {
       struct mtget mt_stat;
       /* Backup over EOF */
-      ok = bsf_dev(dev, 1);
+      ok = bsf(1);
       /* 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;
+      if (dev_get_os_pos(this, &mt_stat)) {
+         Dmsg2(100, "BSFATEOF adjust file from %d to %d\n", file , mt_stat.mt_fileno);
+         file = mt_stat.mt_fileno;
       } else {
-         dev->file++;                 /* wing it -- not correct on all OSes */
+         file++;                 /* wing it -- not correct on all OSes */
       }
    } else {
-      update_pos_dev(dev);                   /* update position */
+      update_pos_dev(this);                   /* update position */
    }
-   Dmsg1(200, "EOD dev->file=%d\n", dev->file);
+   Dmsg1(200, "EOD dev->file=%d\n", file);
    return ok;
 }
 
@@ -1013,7 +1005,7 @@ uint32_t status_dev(DEVICE *dev)
          Pmsg0(-20, " IM_REP_EN");
       }
 #endif /* !SunOS && !OSF */
-      if (dev_cap(dev, CAP_MTIOCGET)) {
+      if (dev->has_cap(CAP_MTIOCGET)) {
          Pmsg2(-20, _(" file=%d block=%d\n"), mt_stat.mt_fileno, mt_stat.mt_blkno);
       } else {
          Pmsg2(-20, _(" file=%d block=%d\n"), -1, -1);
@@ -1075,44 +1067,44 @@ bool load_dev(DEVICE *dev)
  *  Returns: true  on success
  *           false on failure
  */
-bool offline_dev(DEVICE *dev)
+bool DEVICE::offline()
 {
    struct mtop mt_com;
 
-   if (!dev || dev->fd < 0 || !dev->is_tape()) {
+   if (!is_tape()) {
       return true;                    /* device not open */
    }
 
-   dev->state &= ~(ST_APPEND|ST_READ|ST_EOT|ST_EOF|ST_WEOT);  /* remove EOF/EOT flags */
-   dev->block_num = dev->file = 0;
-   dev->file_size = 0;
-   dev->file_addr = 0;
-   dev->part = 0;
+   state &= ~(ST_APPEND|ST_READ|ST_EOT|ST_EOF|ST_WEOT);  /* remove EOF/EOT flags */
+   block_num = file = 0;
+   file_size = 0;
+   file_addr = 0;
+   part = 0;
 #ifdef MTUNLOCK
    mt_com.mt_op = MTUNLOCK;
    mt_com.mt_count = 1;
-   ioctl(dev->fd, MTIOCTOP, (char *)&mt_com);
+   ioctl(fd, MTIOCTOP, (char *)&mt_com);
 #endif
    mt_com.mt_op = MTOFFL;
    mt_com.mt_count = 1;
-   if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) {
+   if (ioctl(fd, MTIOCTOP, (char *)&mt_com) < 0) {
       berrno be;
-      dev->dev_errno = errno;
-      Mmsg2(dev->errmsg, _("ioctl MTOFFL error on %s. ERR=%s.\n"),
-         dev->print_name(), be.strerror());
+      dev_errno = errno;
+      Mmsg2(errmsg, _("ioctl MTOFFL error on %s. ERR=%s.\n"),
+         print_name(), be.strerror());
       return false;
    }
-   Dmsg1(100, "Offlined device %s\n", dev->print_name());
+   Dmsg1(100, "Offlined device %s\n", print_name());
    return true;
 }
 
-bool offline_or_rewind_dev(DEVICE *dev)
+bool DEVICE::offline_or_rewind()
 {
-   if (dev->fd < 0) {
+   if (fd < 0) {
       return false;
    }
-   if (dev_cap(dev, CAP_OFFLINEUNMOUNT)) {
-      return offline_dev(dev);
+   if (has_cap(CAP_OFFLINEUNMOUNT)) {
+      return offline();
    } else {
    /*
     * Note, this rewind probably should not be here (it wasn't
@@ -1121,8 +1113,8 @@ bool offline_or_rewind_dev(DEVICE *dev)
     *  such as backspacing after writing and EOF. If it is not
     *  done, all future references to the drive get and I/O error.
     */
-      clrerror_dev(dev, MTREW);
-      return dev->rewind(NULL);
+      clrerror_dev(this, MTREW);
+      return rewind(NULL);
    }
 }
 
@@ -1165,7 +1157,7 @@ bool DEVICE::fsf(int num)
     *  the SCSI driver will ensure that we do not
     *  forward space past the end of the medium.
     */
-   if (dev_cap(this, CAP_FSF) && dev_cap(this, CAP_MTIOCGET) && dev_cap(this, CAP_FASTFSF)) {
+   if (has_cap(CAP_FSF) && has_cap(CAP_MTIOCGET) && has_cap(CAP_FASTFSF)) {
       mt_com.mt_op = MTFSF;
       mt_com.mt_count = num;
       stat = ioctl(fd, MTIOCTOP, (char *)&mt_com);
@@ -1191,7 +1183,7 @@ bool DEVICE::fsf(int num)
     *  is the only way we can be sure that we don't read
     *  two consecutive EOF marks, which means End of Data.
     */
-   } else if (dev_cap(this, CAP_FSF)) {
+   } else if (has_cap(CAP_FSF)) {
       POOLMEM *rbuf;
       int rbuf_len;
       Dmsg0(200, "FSF has cap_fsf\n");
@@ -1291,39 +1283,38 @@ bool DEVICE::fsf(int num)
  *  Returns: false on failure
  *           true  on success
  */
-bool
-bsf_dev(DEVICE *dev, int num)
+bool DEVICE::bsf(int num)
 {
    struct mtop mt_com;
    int stat;
 
-   if (dev->fd < 0) {
-      dev->dev_errno = EBADF;
-      Mmsg0(dev->errmsg, _("Bad call to bsf_dev. Device not open\n"));
-      Emsg0(M_FATAL, 0, dev->errmsg);
+   if (fd < 0) {
+      dev_errno = EBADF;
+      Mmsg0(errmsg, _("Bad call to bsf. Device not open\n"));
+      Emsg0(M_FATAL, 0, errmsg);
       return false;
    }
 
-   if (!dev->is_tape()) {
-      Mmsg1(dev->errmsg, _("Device %s cannot BSF because it is not a tape.\n"),
-         dev->print_name());
+   if (!is_tape()) {
+      Mmsg1(errmsg, _("Device %s cannot BSF because it is not a tape.\n"),
+         print_name());
       return false;
    }
-   Dmsg0(29, "bsf_dev\n");
-   dev->state &= ~(ST_EOT|ST_EOF);
-   dev->file -= num;
-   dev->file_addr = 0;
-   dev->file_size = 0;
+   Dmsg0(29, "bsf\n");
+   state &= ~(ST_EOT|ST_EOF);
+   file -= num;
+   file_addr = 0;
+   file_size = 0;
    mt_com.mt_op = MTBSF;
    mt_com.mt_count = num;
-   stat = ioctl(dev->fd, MTIOCTOP, (char *)&mt_com);
+   stat = ioctl(fd, MTIOCTOP, (char *)&mt_com);
    if (stat < 0) {
       berrno be;
-      clrerror_dev(dev, MTBSF);
-      Mmsg2(dev->errmsg, _("ioctl MTBSF error on %s. ERR=%s.\n"),
-         dev->print_name(), be.strerror());
+      clrerror_dev(this, MTBSF);
+      Mmsg2(errmsg, _("ioctl MTBSF error on %s. ERR=%s.\n"),
+         print_name(), be.strerror());
    }
-   update_pos_dev(dev);
+   update_pos_dev(this);
    return stat == 0;
 }
 
@@ -1348,7 +1339,7 @@ bool DEVICE::fsr(int num)
    if (!is_tape()) {
       return false;
    }
-   if (!dev_cap(this, CAP_FSR)) {
+   if (!has_cap(CAP_FSR)) {
       Mmsg1(errmsg, _("ioctl MTFSR not permitted on %s.\n"), print_name());
       return false;
    }
@@ -1406,7 +1397,7 @@ bsr_dev(DEVICE *dev, int num)
       return false;
    }
 
-   if (!dev_cap(dev, CAP_BSR)) {
+   if (!dev->has_cap(CAP_BSR)) {
       Mmsg1(dev->errmsg, _("ioctl MTBSR not permitted on %s.\n"), dev->print_name());
       return false;
    }
@@ -1475,13 +1466,13 @@ reposition_dev(DEVICE *dev, uint32_t file, uint32_t block)
    }
    if (block < dev->block_num) {
       Dmsg2(100, "wanted_blk=%d at_blk=%d\n", block, dev->block_num);
-      Dmsg0(100, "bsf_dev 1\n");
-      bsf_dev(dev, 1);
+      Dmsg0(100, "bsf 1\n");
+      dev->bsf(1);
       Dmsg0(100, "fsf_dev 1\n");
       dev->fsf(1);
       Dmsg2(100, "wanted_blk=%d at_blk=%d\n", block, dev->block_num);
    }
-   if (dev_cap(dev, CAP_POSITIONBLOCKS) && block > dev->block_num) {
+   if (dev->has_cap(CAP_POSITIONBLOCKS) && block > dev->block_num) {
       /* Ignore errors as Bacula can read to the correct block */
       Dmsg1(100, "fsr %d\n", block-dev->block_num);
       return dev->fsr(block-dev->block_num);
@@ -1679,25 +1670,32 @@ int flush_dev(DEVICE *dev)
    return 1;
 }
 
-static void do_close(DEVICE *dev)
+/*
+ * Close the device
+ */
+void DEVICE::close()
 {
-
-   Dmsg1(100, "really close_dev %s\n", dev->print_name());
-   if (dev->fd >= 0) {
-      ::close(dev->fd);
+   Dmsg1(100, "close_dev %s\n", print_name());
+   if (has_cap(CAP_OFFLINEUNMOUNT)) {
+      offline();
+   }
+   if (fd >= 0) {
+      ::close(fd);
+   } else {
+      return;                         /* already closed */
    }
 
-   if (!unmount_dev(dev, 1)) {
-      Dmsg1(0, "Cannot unmount device %s.\n", dev->print_name());
+   if (is_dvd() && !unmount_dvd(this, 1)) {
+      Dmsg1(0, "Cannot unmount device %s.\n", print_name());
    }
    
    /* Remove the last part file if it is empty */
-   if (dev->num_parts > 0) {
+   if (num_parts > 0) {
       struct stat statp;
       POOL_MEM archive_name(PM_FNAME);
-      dev->part = dev->num_parts;
-      Dmsg1(100, "Call make_dvd_filename. Vol=%s\n", dev->VolCatInfo.VolCatName);
-      make_spooled_dvd_filename(dev, archive_name);
+      part = num_parts;
+      Dmsg1(100, "Call make_dvd_filename. Vol=%s\n", VolCatInfo.VolCatName);
+      make_spooled_dvd_filename(this, archive_name);
       /* Check that the part file is empty */
       if ((stat(archive_name.c_str(), &statp) == 0) && (statp.st_size == 0)) {
          Dmsg1(100, "unlink(%s)\n", archive_name.c_str());
@@ -1706,59 +1704,263 @@ static void do_close(DEVICE *dev)
    }
    
    /* Clean up device packet so it can be reused */
-   dev->clear_opened();
-   dev->state &= ~(ST_LABEL|ST_READ|ST_APPEND|ST_EOT|ST_WEOT|ST_EOF);
-   dev->label_type = B_BACULA_LABEL;
-   dev->file = dev->block_num = 0;
-   dev->file_size = 0;
-   dev->file_addr = 0;
-   dev->part = 0;
-   dev->num_parts = 0;
-   dev->part_size = 0;
-   dev->part_start = 0;
-   dev->EndFile = dev->EndBlock = 0;
-   memset(&dev->VolCatInfo, 0, sizeof(dev->VolCatInfo));
-   free_volume(dev);
-   memset(&dev->VolHdr, 0, sizeof(dev->VolHdr));
-   if (dev->tid) {
-      stop_thread_timer(dev->tid);
-      dev->tid = 0;
-   }
-   dev->openmode = 0;
+   clear_opened();
+   state &= ~(ST_LABEL|ST_READ|ST_APPEND|ST_EOT|ST_WEOT|ST_EOF);
+   label_type = B_BACULA_LABEL;
+   file = block_num = 0;
+   file_size = 0;
+   file_addr = 0;
+   part = 0;
+   num_parts = 0;
+   part_size = 0;
+   part_start = 0;
+   EndFile = EndBlock = 0;
+   memset(&VolCatInfo, 0, sizeof(VolCatInfo));
+   free_volume(this);
+   memset(&VolHdr, 0, sizeof(VolHdr));
+   if (tid) {
+      stop_thread_timer(tid);
+      tid = 0;
+   }
+   openmode = 0;
 }
 
-/*
- * Close the device
- */
-void DEVICE::close()
-{
-   do_close(this);
-}
 
 
-bool truncate_dev(DCR *dcr) /* We need the DCR for DVD-writing */
+bool DEVICE::truncate(DCR *dcr) /* We need the DCR for DVD-writing */
 {
-   DEVICE *dev = dcr->dev;
-
-   Dmsg1(100, "truncate_dev %s\n", dev->print_name());
-   if (dev->is_tape()) {
+   Dmsg1(100, "truncate_dev %s\n", print_name());
+   if (is_tape()) {
       return true;                    /* we don't really truncate tapes */
       /* maybe we should rewind and write and eof ???? */
    }
    
-   if (dev->is_dvd()) {
-      return truncate_dvd_dev(dcr);
+   if (is_dvd()) {
+      return truncate_dvd(dcr);
    }
    
-   if (ftruncate(dev->fd, 0) != 0) {
+   if (ftruncate(fd, 0) != 0) {
       berrno be;
-      Mmsg2(dev->errmsg, _("Unable to truncate device %s. ERR=%s\n"), 
-            dev->print_name(), be.strerror());
+      Mmsg2(errmsg, _("Unable to truncate device %s. ERR=%s\n"), 
+            print_name(), be.strerror());
+      return false;
+   }
+   return true;
+}
+
+/* Mount the device.
+ * If timeout, wait until the mount command returns 0.
+ * If !timeout, try to mount the device only once.
+ */
+bool DEVICE::mount(int timeout) 
+{
+   Dmsg0(90, "Enter mount\n");
+   if (is_mounted()) {
+      return true;
+   } else if (requires_mount()) {
+      return do_mount(1, timeout);
+   }       
+   return true;
+}
+
+/* Unmount the device
+ * If timeout, wait until the unmount command returns 0.
+ * If !timeout, try to unmount the device only once.
+ */
+bool DEVICE::unmount(int timeout) 
+{
+   Dmsg0(90, "Enter unmount_dvd\n");
+   if (is_mounted()) {
+      return do_mount(0, timeout);
+   }
+   return true;
+}
+
+/* (Un)mount the device */
+bool DEVICE::do_mount(int mount, int dotimeout) 
+{
+   POOL_MEM ocmd(PM_FNAME);
+   POOLMEM *results;
+   char *icmd;
+   int status, timeout;
+   
+   sm_check(__FILE__, __LINE__, false);
+   if (mount) {
+      if (is_mounted()) {
+         Dmsg0(200, "======= mount=1\n");
+         return true;
+      }
+      icmd = device->mount_command;
+   } else {
+      if (!is_mounted()) {
+         Dmsg0(200, "======= mount=0\n");
+         return true;
+      }
+      icmd = device->unmount_command;
+   }
+   
+   edit_mount_codes(ocmd, icmd);
+   
+   Dmsg2(200, "do_mount_dvd: cmd=%s mounted=%d\n", ocmd.c_str(), !!is_mounted());
+
+   if (dotimeout) {
+      /* Try at most 1 time to (un)mount the device. This should perhaps be configurable. */
+      timeout = 1;
+   } else {
+      timeout = 0;
+   }
+   results = get_memory(2000);
+   results[0] = 0;
+   /* If busy retry each second */
+   while ((status = run_program_full_output(ocmd.c_str(), 
+                       max_open_wait/2, results)) != 0) {
+      /* Doesn't work with internationalisation (This is not a problem) */
+      if (fnmatch("*is already mounted on", results, 0) == 0) {
+         break;
+      }
+      if (timeout-- > 0) {
+         /* Sometimes the device cannot be mounted because it is already mounted.
+          * Try to unmount it, then remount it */
+         if (mount) {
+            Dmsg1(400, "Trying to unmount the device %s...\n", print_name());
+            do_mount(0, 0);
+         }
+         bmicrosleep(1, 0);
+         continue;
+      }
+      Dmsg2(40, "Device %s cannot be mounted. ERR=%s\n", print_name(), results);
+      Mmsg(errmsg, _("Device %s cannot be mounted. ERR=%s\n"), 
+           print_name(), results);
+      /*
+       * Now, just to be sure it is not mounted, try to read the
+       *  filesystem.
+       */
+      DIR* dp;
+      struct dirent *entry, *result;
+      int name_max;
+      int count;
+      
+      name_max = pathconf(".", _PC_NAME_MAX);
+      if (name_max < 1024) {
+         name_max = 1024;
+      }
+         
+      if (!(dp = opendir(device->mount_point))) {
+         berrno be;
+         dev_errno = errno;
+         Dmsg3(29, "do_mount: failed to open dir %s (dev=%s), ERR=%s\n", 
+               device->mount_point, print_name(), be.strerror());
+         goto get_out;
+      }
+      
+      entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 1000);
+      count = 0;
+      while (1) {
+         if ((readdir_r(dp, entry, &result) != 0) || (result == NULL)) {
+            dev_errno = EIO;
+            Dmsg2(129, "do_mount: failed to find suitable file in dir %s (dev=%s)\n", 
+                  device->mount_point, print_name());
+            break;
+         }
+         if ((strcmp(result->d_name, ".")) && (strcmp(result->d_name, "..")) && (strcmp(result->d_name, ".keep"))) {
+            count++; /* result->d_name != ., .. or .keep (Gentoo-specific) */
+            break;
+         } else {
+            Dmsg2(129, "do_mount: ignoring %s in %s\n", result->d_name, device->mount_point);
+         }
+      }
+      free(entry);
+      closedir(dp);
+      
+      Dmsg1(29, "do_mount: got %d files in the mount point (not counting ., .. and .keep)\n", count);
+      
+      if (count > 0) {
+         mount = 1;                      /* If we got more than ., .. and .keep */
+         break;                          /*   there must be something mounted */
+      }
+get_out:
+      set_mounted(false);
+      sm_check(__FILE__, __LINE__, false);
+      free_pool_memory(results);
+      Dmsg0(200, "============ mount=0\n");
       return false;
    }
+   
+   set_mounted(mount);              /* set/clear mounted flag */
+   free_pool_memory(results);
+   Dmsg1(200, "============ mount=%d\n", mount);
    return true;
 }
 
+/*
+ * Edit codes into (Un)MountCommand, Write(First)PartCommand
+ *  %% = %
+ *  %a = archive device name
+ *  %e = erase (set if cannot mount and first part)
+ *  %n = part number
+ *  %m = mount point
+ *  %v = last part name
+ *
+ *  omsg = edited output message
+ *  imsg = input string containing edit codes (%x)
+ *
+ */
+void DEVICE::edit_mount_codes(POOL_MEM &omsg, const char *imsg)
+{
+   const char *p;
+   const char *str;
+   char add[20];
+   
+   POOL_MEM archive_name(PM_FNAME);
+
+   omsg.c_str()[0] = 0;
+   Dmsg1(800, "edit_mount_codes: %s\n", imsg);
+   for (p=imsg; *p; p++) {
+      if (*p == '%') {
+         switch (*++p) {
+         case '%':
+            str = "%";
+            break;
+         case 'a':
+            str = dev_name;
+            break;
+         case 'e':
+            if (num_parts == 0) {
+               str = "1";
+            } else {
+               str = "0";
+            }
+            break;
+         case 'n':
+            bsnprintf(add, sizeof(add), "%d", part);
+            str = add;
+            break;
+         case 'm':
+            str = device->mount_point;
+            break;
+         case 'v':
+            make_spooled_dvd_filename(this, archive_name);
+            str = archive_name.c_str();
+            break;
+         default:
+            add[0] = '%';
+            add[1] = *p;
+            add[2] = 0;
+            str = add;
+            break;
+         }
+      } else {
+         add[0] = *p;
+         add[1] = 0;
+         str = add;
+      }
+      Dmsg1(1900, "add_str %s\n", str);
+      pm_strcat(omsg, (char *)str);
+      Dmsg1(1800, "omsg=%s\n", omsg.c_str());
+   }
+}
+
+
 /* Return the resource name for the device */
 const char *DEVICE::name() const
 {
@@ -1796,7 +1998,7 @@ term_dev(DEVICE *dev)
       return;
    }
    Dmsg1(29, "term_dev: %s\n", dev->print_name());
-   do_close(dev);
+   dev->close();
    if (dev->dev_name) {
       free_memory(dev->dev_name);
       dev->dev_name = NULL;
@@ -1819,7 +2021,7 @@ term_dev(DEVICE *dev)
       dev->attached_dcrs = NULL;
    }
    if (dev->state & ST_MALLOC) {
-      free_pool_memory((POOLMEM *)dev);
+      free((char *)dev);
    }
 }
 
@@ -1896,10 +2098,10 @@ void set_os_device_parameters(DEVICE *dev)
       }
       mt_com.mt_op = MTSETDRVBUFFER;
       mt_com.mt_count = MT_ST_CLEARBOOLEANS;
-      if (!dev_cap(dev, CAP_TWOEOF)) {
+      if (!dev->has_cap(CAP_TWOEOF)) {
          mt_com.mt_count |= MT_ST_TWO_FM;
       }
-      if (dev_cap(dev, CAP_EOM)) {
+      if (dev->has_cap(CAP_EOM)) {
          mt_com.mt_count |= MT_ST_FAST_MTEOM;
       }
       if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) {
@@ -1957,7 +2159,7 @@ 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) && 
+   return dev->has_cap(CAP_MTIOCGET) && 
           ioctl(dev->fd, MTIOCGET, (char *)mt_stat) == 0 &&
           mt_stat->mt_fileno >= 0;
 }
index 5d953e60458dad58d1519518dfcb935b6bdc65d8..76e8cdfb48c6620d762e0a5b4f7ec8d00a7407d5 100644 (file)
@@ -58,6 +58,15 @@ enum {
    OPEN_WRITE_ONLY
 };
 
+/* Device types */
+enum {
+   B_FILE_DEV = 1,
+   B_TAPE_DEV,
+   B_DVD_DEV,
+   B_FIFO_DEV,
+   B_PROG_DEV
+};
+
 /* Generic status bits returned from status_dev() */
 #define BMT_TAPE           (1<<0)     /* is tape device */
 #define BMT_EOF            (1<<1)     /* just read EOF */
@@ -104,11 +113,12 @@ enum {
 
 /* Device state bits */
 #define ST_XXXXXX          (1<<0)     /* was ST_OPENED */
-#define ST_TAPE            (1<<1)     /* is a tape device */
-#define ST_FILE            (1<<2)     /* is a file device */
-#define ST_FIFO            (1<<3)     /* is a fifo device */
-#define ST_DVD             (1<<4)     /* is a DVD device */  
-#define ST_PROG            (1<<5)     /* is a program device */
+#define ST_XXXXX           (1<<1)     /* was ST_TAPE */
+#define ST_XXXX            (1<<2)     /* was ST_FILE */
+#define ST_XXX             (1<<3)     /* was ST_FIFO */
+#define ST_XX              (1<<4)     /* was ST_DVD */
+#define ST_X               (1<<5)     /* was ST_PROG */
+
 #define ST_LABEL           (1<<6)     /* label found */
 #define ST_MALLOC          (1<<7)     /* dev packet malloc'ed in init_dev() */
 #define ST_APPEND          (1<<8)     /* ready for Bacula append */
@@ -204,6 +214,7 @@ public:
    int dev_errno;                     /* Our own errno */
    int mode;                          /* read/write modes */
    int openmode;                      /* parameter passed to open_dev (useful to reopen the device) */
+   int dev_type;                      /* device type */
    bool autoselect;                   /* Autoselect in autochanger */
    int label_type;                    /* Bacula/ANSI/IBM label types */
    uint32_t drive_index;              /* Autochanger drive index (base 0) */
@@ -259,12 +270,15 @@ public:
    int num_wait;
 
    /* Methods */
+   int has_cap(int cap) const { return capabilities & cap; }
    int is_autochanger() const { return capabilities & CAP_AUTOCHANGER; }
    int requires_mount() const { return capabilities & CAP_REQMOUNT; }
-   int is_tape() const { return state & ST_TAPE; }
-   int is_file() const { return state & ST_FILE; }
-   int is_fifo() const { return state & ST_FIFO; }
-   int is_dvd() const  { return state & ST_DVD; }
+   int is_removable() const { return capabilities & CAP_REM; }
+   int is_tape() const { return dev_type == B_TAPE_DEV; }
+   int is_file() const { return dev_type == B_FILE_DEV; }
+   int is_fifo() const { return dev_type == B_FIFO_DEV; }
+   int is_dvd() const  { return dev_type == B_DVD_DEV; }
+   int is_prog() const  { return dev_type == B_PROG_DEV; }
    int is_open() const { return fd >= 0; }
    int is_offline() const { return state & ST_OFFLINE; }
    int is_labeled() const { return state & ST_LABEL; }
@@ -295,8 +309,6 @@ public:
                      dev_blocked == BST_WAITING_FOR_SYSOP ||
                      dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP); };
    bool weof() { return !weof_dev(this, 1); };
-   bool fsr(int num);   /* in dev.c */
-   bool fsf(int num);   /* in dev.c */
    const char *strerror() const;
    const char *archive_name() const;
    const char *name() const;
@@ -307,7 +319,7 @@ public:
    void set_eof() { state |= ST_EOF; };
    void set_append() { state |= ST_APPEND; };
    void set_labeled() { state |= ST_LABEL; };
-   void set_read() { state |= ST_READ; };
+   inline void set_read() { state |= ST_READ; };
    void set_offline() { state |= ST_OFFLINE; };
    void set_mounted() { state |= ST_MOUNTED; };
    void set_media() { state |= ST_MEDIA; };
@@ -329,12 +341,22 @@ public:
    void clear_short_block() { state &= ~ST_SHORT; };
    void clear_freespace_ok() { state &= ~ST_FREESPACE_OK; }
 
-   void block(int why); /* in dev.c */
-   void unblock();      /* in dev.c */
-   void close();        /* in dev.c */
+   void block(int why);          /* in dev.c */
+   void unblock();               /* in dev.c */
+   void close();                 /* in dev.c */
+   bool truncate(DCR *dcr);      /* in dev.c */
    int open(DCR *dcr, int mode); /* in dev.c */
-   bool rewind(DCR *dcr);         /* in dev.c */
-
+   bool rewind(DCR *dcr);        /* in dev.c */
+   bool mount(int timeout);      /* in dev.c */
+   bool unmount(int timeout);    /* in dev.c */
+   void edit_mount_codes(POOL_MEM &omsg, const char *imsg); /* in dev.c */
+   bool offline_or_rewind();     /* in dev.c */
+   bool offline();               /* in dev.c */
+   bool bsf(int count);          /* in dev.c */
+   bool eod();                   /* in dev.c */
+   bool fsr(int num);            /* in dev.c */
+   bool fsf(int num);            /* in dev.c */
+   bool scan_dir_for_volume(DCR *dcr); /* in scan.c */
 
    void set_blocked(int block) { dev_blocked = block; };
    int  get_blocked() const { return dev_blocked; };
@@ -342,11 +364,12 @@ public:
    bool is_blocked() const { return dev_blocked != BST_NOT_BLOCKED; };
 
 private:
-   void set_mode(int omode); /* in dev.c */
+   bool do_mount(int mount, int timeout);      /* in dev.c */
+   void set_mode(int omode);                   /* in dev.c */
    void open_tape_device(DCR *dcr, int omode); /* in dev.c */
-   void open_file_device(int omode); /* in dev.c */
-   void open_dvd_device(DCR *dcr, int omode); /* in dev.c */
-   void set_blocking(); /* in dev.c */
+   void open_file_device(DCR *dcr, int omode); /* in dev.c */
+   void open_dvd_device(DCR *dcr, int omode);  /* in dev.c */
+   void set_blocking();                        /* in dev.c */
 
 };
 
index c7407d5d2411f51102022158da453041b51a5cbe..a5b3dae44ead5c317fe06d149de8246d8c311652 100644 (file)
@@ -291,7 +291,7 @@ bool open_device(DCR *dcr)
       /* If polling, ignore the error */
       /* If DVD, also ignore the error, very often you cannot open the device
        * (when there is no DVD, or when the one inserted is a wrong one) */
-      if ((!dev->poll) && (!dev->is_dvd())) {
+      if (!dev->poll && !dev->is_dvd() && !dev->is_removable()) {
          Jmsg2(dcr->jcr, M_FATAL, 0, _("Unable to open device %s: ERR=%s\n"),
             dev->print_name(), strerror_dev(dev));
          Pmsg2(000, _("Unable to open archive %s: ERR=%s\n"), 
@@ -302,27 +302,6 @@ bool open_device(DCR *dcr)
    return true;
 }
 
-/*
- * Release any Volume attached to this device 
- *  then close the device.
- */
-void close_device(DEVICE *dev)
-{
-   free_volume(dev);
-   dev->close();
-}
-
-/*
- */
-void force_close_device(DEVICE *dev)
-{
-   if (!dev || dev->fd < 0) {
-      return;
-   }
-   Dmsg1(29, "Force close_dev %s\n", dev->print_name());
-   free_volume(dev);
-   dev->close();
-}
 
 
 void dev_lock(DEVICE *dev)
index 2481b21b99ff3754818b64874779426cc5e0454b..e6d4b289ed3e766bce1bd380f8bd800ab451a12f 100644 (file)
@@ -20,7 +20,7 @@
  *
  */
 /*
-   Copyright (C) 2001-2005 Kern Sibbald
+   Copyright (C) 2001-2006 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -71,6 +71,7 @@ static bool setdebug_cmd(JCR *jcr);
 static bool cancel_cmd(JCR *cjcr);
 static bool mount_cmd(JCR *jcr);
 static bool unmount_cmd(JCR *jcr);
+static bool bootstrap_cmd(JCR *jcr);
 static bool changer_cmd(JCR *sjcr);
 static bool do_label(JCR *jcr, int relabel);
 static DCR *find_device(JCR *jcr, POOL_MEM &dev_name, int drive);
@@ -344,9 +345,9 @@ static bool do_label(JCR *jcr, int relabel)
          dev = dcr->dev;
          P(dev->mutex);               /* Use P to avoid indefinite block */
          if (!dev->is_open()) {
-            Dmsg0(400, "Can relabel. Device is not open\n");
+            Dmsg1(400, "Can %slabel. Device is not open\n", relabel?"re":"");
             label_volume_if_ok(dcr, oldname, newname, poolname, slot, relabel);
-            force_close_device(dev);
+            dev->close();
          /* Under certain "safe" conditions, we can steal the lock */
          } else if (dev->can_steal_lock()) {
             Dmsg0(400, "Can relabel. can_steal_lock\n");
@@ -390,15 +391,27 @@ static void label_volume_if_ok(DCR *dcr, char *oldname,
    bsteal_lock_t hold;
    DEVICE *dev = dcr->dev;
    int label_status;
+   int mode;
 
    steal_device_lock(dev, &hold, BST_WRITING_LABEL);
    Dmsg1(100, "Stole device %s lock, writing label.\n", dev->print_name());
 
-   /* Note, try_autoload_device() opens the device */
    if (!try_autoload_device(dcr->jcr, slot, newname)) {
       goto bail_out;                  /* error */
    }
 
+   /* Ensure that the device is open -- autoload_device() closes it */
+   if (dev->is_tape()) {
+      mode = OPEN_READ_WRITE;
+   } else {
+      mode = CREATE_READ_WRITE;
+   }
+   if (dev->open(dcr, mode) < 0) {
+      bnet_fsend(dir, _("3910 Unable to open device %s: ERR=%s\n"),
+         dev->print_name(), dev->strerror());
+      return;      
+   }
+
    /* See what we have for a Volume */
    label_status = read_dev_volume_label(dcr);
    
@@ -515,40 +528,42 @@ static DCR *find_device(JCR *jcr, POOL_MEM &devname, int drive)
          break;
       }
    }
-   foreach_res(changer, R_AUTOCHANGER) {
-      /* Find resource, and make sure we were able to open it */
-      if (fnmatch(devname.c_str(), changer->hdr.name, 0) == 0) {
-         /* Try each device in this AutoChanger */
-         foreach_alist(device, changer->device) {
-            Dmsg1(100, "Try changer device %s\n", device->hdr.name);
-            if (!device->dev) {
-               device->dev = init_dev(jcr, device);
-            }
-            if (!device->dev) {
-               Dmsg1(100, "Device %s could not be opened. Skipped\n", devname.c_str());
-               Jmsg(jcr, M_WARNING, 0, _("\n"
-                  "     Device \"%s\" in changer \"%s\" requested by DIR could not be opened or does not exist.\n"),
-                    device->hdr.name, devname.c_str());
-               continue;
-            }
-            if (!device->dev->autoselect) {
-               Dmsg1(100, "Device %s not autoselect skipped.\n", devname.c_str());
-               continue;              /* device is not available */
-            }
-            if (drive < 0 || drive == (int)device->dev->drive_index) {
-               Dmsg1(20, "Found changer device %s\n", device->hdr.name);
-               found = true;
-               break;
+   if (!found) {
+      foreach_res(changer, R_AUTOCHANGER) {
+         /* Find resource, and make sure we were able to open it */
+         if (fnmatch(devname.c_str(), changer->hdr.name, 0) == 0) {
+            /* Try each device in this AutoChanger */
+            foreach_alist(device, changer->device) {
+               Dmsg1(100, "Try changer device %s\n", device->hdr.name);
+               if (!device->dev) {
+                  device->dev = init_dev(jcr, device);
+               }
+               if (!device->dev) {
+                  Dmsg1(100, "Device %s could not be opened. Skipped\n", devname.c_str());
+                  Jmsg(jcr, M_WARNING, 0, _("\n"
+                     "     Device \"%s\" in changer \"%s\" requested by DIR could not be opened or does not exist.\n"),
+                       device->hdr.name, devname.c_str());
+                  continue;
+               }
+               if (!device->dev->autoselect) {
+                  Dmsg1(100, "Device %s not autoselect skipped.\n", devname.c_str());
+                  continue;              /* device is not available */
+               }
+               if (drive < 0 || drive == (int)device->dev->drive_index) {
+                  Dmsg1(20, "Found changer device %s\n", device->hdr.name);
+                  found = true;
+                  break;
+               }
+               Dmsg3(100, "Device %s drive wrong: want=%d got=%d skipping\n",
+                  devname.c_str(), drive, (int)device->dev->drive_index);
             }
-            Dmsg3(100, "Device %s drive wrong: want=%d got=%d skipping\n",
-               devname.c_str(), drive, (int)device->dev->drive_index);
+            break;                    /* we found it but could not open a device */
          }
-         break;                    /* we found it but could not open a device */
       }
    }
 
    if (found) {
-      Dmsg1(100, "Found changer device %s\n", device->hdr.name);
+      Dmsg1(100, "Found device %s\n", device->hdr.name);
       dcr = new_dcr(jcr, device->dev);
       dcr->device = device;
       jcr->dcr = dcr;
@@ -657,7 +672,7 @@ static bool mount_cmd(JCR *jcr)
                              dev->print_name());
                }
             } else if (dev->is_dvd()) {
-               if (mount_dev(dev, 1)) {
+               if (mount_dvd(dev, 1)) {
                   bnet_fsend(dir, _("3002 Device %s is mounted.\n"), 
                      dev->print_name());
                } else {
@@ -715,8 +730,7 @@ static bool unmount_cmd(JCR *jcr)
             Dmsg2(90, "%d waiter dev_block=%d. doing unmount\n", dev->num_waiting,
                dev->dev_blocked);
             if (!unload_autochanger(jcr->dcr, -1)) {
-               offline_or_rewind_dev(dev);
-               force_close_device(dev);
+               dev->close();
             }
             dev->dev_blocked = BST_UNMOUNTED_WAITING_FOR_SYSOP;
             bnet_fsend(dir, _("3001 Device %s unmounted.\n"), 
@@ -743,8 +757,7 @@ static bool unmount_cmd(JCR *jcr)
             dev->dev_blocked = BST_UNMOUNTED;
             dev->no_wait_id = 0;
             if (!unload_autochanger(jcr->dcr, -1)) {
-               offline_or_rewind_dev(dev);
-               force_close_device(dev);
+               dev->close();
             }
             bnet_fsend(dir, _("3002 Device %s unmounted.\n"), 
                dev->print_name());
@@ -828,6 +841,10 @@ static bool release_cmd(JCR *jcr)
 }
 
 
+static bool bootstrap_cmd(JCR *jcr)
+{
+   return get_bootstrap_file(jcr, jcr->dir_bsock);
+}
 
 /*
  * Autochanger command from Director
@@ -902,7 +919,7 @@ static bool readlabel_cmd(JCR *jcr)
          P(dev->mutex);               /* Use P to avoid indefinite block */
          if (!dev->is_open()) {
             read_volume_label(jcr, dev, Slot);
-            force_close_device(dev);
+            dev->close();
          /* Under certain "safe" conditions, we can steal the lock */
          } else if (dev->can_steal_lock()) {
             read_volume_label(jcr, dev, Slot);
@@ -925,6 +942,7 @@ static bool readlabel_cmd(JCR *jcr)
    return true;
 }
 
+
 /*
  * Read the tape label
  *
@@ -965,7 +983,6 @@ static bool try_autoload_device(JCR *jcr, int slot, const char *VolName)
 {
    DCR *dcr = jcr->dcr;
    BSOCK *dir = jcr->dir_bsock;
-   DEVICE *dev = dcr->dev;
 
    bstrncpy(dcr->VolumeName, VolName, sizeof(dcr->VolumeName));
    dcr->VolCatInfo.Slot = slot;
@@ -973,13 +990,6 @@ static bool try_autoload_device(JCR *jcr, int slot, const char *VolName)
    if (autoload_device(dcr, 0, dir) < 0) {    /* autoload if possible */
       return false;
    }
-
-   /* Ensure that the device is open -- autoload_device() closes it */
-   if (dev->open(dcr, OPEN_READ_WRITE) < 0) {
-      bnet_fsend(dir, _("3910 Unable to open device %s: ERR=%s\n"),
-         dev->print_name(), dev->strerror());
-      return false;
-   }
    return true;
 }
 
index 417cf5fcec0fad34143699161341700c004b17d1..f68ac089d0e3b66bdf46f4a0c154367297d3d604 100644 (file)
@@ -8,7 +8,7 @@
  *   Version $Id$
  */
 /*
-   Copyright (C) 2005 Kern Sibbald
+   Copyright (C) 2005-2006 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -26,8 +26,7 @@
 #include "stored.h"
 
 /* Forward referenced functions */
-static void edit_device_codes_dev(DEVICE *dev, POOL_MEM &omsg, const char *imsg);
-static bool do_mount_dev(DEVICE* dev, int mount, int dotimeout);
+static bool do_mount_dvd(DEVICE* dev, int mount, int dotimeout);
 static void add_file_and_part_name(DEVICE *dev, POOL_MEM &archive_name);
 
 /* 
@@ -73,13 +72,13 @@ static void add_file_and_part_name(DEVICE *dev, POOL_MEM &archive_name)
  * If timeout, wait until the mount command returns 0.
  * If !timeout, try to mount the device only once.
  */
-bool mount_dev(DEVICE* dev, int timeout) 
+bool mount_dvd(DEVICE* dev, int timeout) 
 {
-   Dmsg0(90, "Enter mount_dev\n");
+   Dmsg0(90, "Enter mount_dvd\n");
    if (dev->is_mounted()) {
       return true;
    } else if (dev->requires_mount()) {
-      return do_mount_dev(dev, 1, timeout);
+      return do_mount_dvd(dev, 1, timeout);
    }       
    return true;
 }
@@ -88,17 +87,20 @@ bool mount_dev(DEVICE* dev, int timeout)
  * If timeout, wait until the unmount command returns 0.
  * If !timeout, try to unmount the device only once.
  */
-bool unmount_dev(DEVICE *dev, int timeout) 
+bool unmount_dvd(DEVICE *dev, int timeout) 
 {
-   Dmsg0(90, "Enter unmount_dev\n");
+   if (!dev->is_dvd()) {
+      return true;
+   }
+   Dmsg0(90, "Enter unmount_dvd\n");
    if (dev->is_mounted()) {
-      return do_mount_dev(dev, 0, timeout);
+      return do_mount_dvd(dev, 0, timeout);
    }
    return true;
 }
 
 /* (Un)mount the device */
-static bool do_mount_dev(DEVICE* dev, int mount, int dotimeout) 
+static bool do_mount_dvd(DEVICE* dev, int mount, int dotimeout) 
 {
    POOL_MEM ocmd(PM_FNAME);
    POOLMEM *results;
@@ -120,9 +122,9 @@ static bool do_mount_dev(DEVICE* dev, int mount, int dotimeout)
       icmd = dev->device->unmount_command;
    }
    
-   edit_device_codes_dev(dev, ocmd, icmd);
+   dev->edit_mount_codes(ocmd, icmd);
    
-   Dmsg2(200, "do_mount_dev: cmd=%s mounted=%d\n", ocmd.c_str(), !!dev->is_mounted());
+   Dmsg2(200, "do_mount_dvd: cmd=%s mounted=%d\n", ocmd.c_str(), !!dev->is_mounted());
 
    if (dotimeout) {
       /* Try at most 1 time to (un)mount the device. This should perhaps be configurable. */
@@ -144,7 +146,7 @@ static bool do_mount_dev(DEVICE* dev, int mount, int dotimeout)
           * Try to unmount it, then remount it */
          if (mount) {
             Dmsg1(400, "Trying to unmount the device %s...\n", dev->print_name());
-            do_mount_dev(dev, 0, 0);
+            do_mount_dvd(dev, 0, 0);
          }
          bmicrosleep(1, 0);
          continue;
@@ -159,7 +161,7 @@ static bool do_mount_dev(DEVICE* dev, int mount, int dotimeout)
       DIR* dp;
       struct dirent *entry, *result;
       int name_max;
-      int count = 0;
+      int count;
       
       name_max = pathconf(".", _PC_NAME_MAX);
       if (name_max < 1024) {
@@ -169,31 +171,34 @@ static bool do_mount_dev(DEVICE* dev, int mount, int dotimeout)
       if (!(dp = opendir(dev->device->mount_point))) {
          berrno be;
          dev->dev_errno = errno;
-         Dmsg3(29, "open_mounted_dev: failed to open dir %s (dev=%s), ERR=%s\n", 
+         Dmsg3(29, "do_mount_dvd: failed to open dir %s (dev=%s), ERR=%s\n", 
                dev->device->mount_point, dev->print_name(), be.strerror());
          goto get_out;
       }
       
       entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 1000);
+      count = 0;
       while (1) {
          if ((readdir_r(dp, entry, &result) != 0) || (result == NULL)) {
             dev->dev_errno = EIO;
-            Dmsg2(129, "open_mounted_dev: failed to find suitable file in dir %s (dev=%s)\n", 
+            Dmsg2(129, "do_mount_dvd: failed to find suitable file in dir %s (dev=%s)\n", 
                   dev->device->mount_point, dev->print_name());
             break;
          }
-         if ((strcmp(result->d_name, ".")) && (strcmp(result->d_name, "..")) && (strcmp(result->d_name, ".keep"))) {
+         if (strcmp(result->d_name, ".") && strcmp(result->d_name, "..") && 
+             strcmp(result->d_name, ".keep")) {
             count++; /* result->d_name != ., .. or .keep (Gentoo-specific) */
+            break;
          }
          else {
-            Dmsg2(129, "open_mounted_dev: ignoring %s in %s\n", 
+            Dmsg2(129, "do_mount_dvd: ignoring %s in %s\n", 
                   result->d_name, dev->device->mount_point);
          }
       }
       free(entry);
       closedir(dp);
       
-      Dmsg1(29, "open_mounted_dev: got %d files in the mount point (not counting ., .. and .keep)\n", count);
+      Dmsg1(29, "do_mount_dvd: got %d files in the mount point (not counting ., .. and .keep)\n", count);
       
       if (count > 0) {
          mount = 1;                      /* If we got more than ., .. and .keep */
@@ -228,7 +233,7 @@ void update_free_space_dev(DEVICE* dev)
    char ed1[50];
    
    /* The device must be mounted in order to dvd-freespace to work */
-   mount_dev(dev, 1);
+   mount_dvd(dev, 1);
    
    sm_check(__FILE__, __LINE__, false);
    icmd = dev->device->free_space_command;
@@ -243,7 +248,7 @@ void update_free_space_dev(DEVICE* dev)
       return;
    }
    
-   edit_device_codes_dev(dev, ocmd, icmd);
+   dev->edit_mount_codes(ocmd, icmd);
    
    Dmsg1(29, "update_free_space_dev: cmd=%s\n", ocmd.c_str());
 
@@ -298,7 +303,7 @@ void update_free_space_dev(DEVICE* dev)
  * Write a part (Vol, Vol.1, ...) from the spool to the DVD   
  * This routine does not update the part number, so normally, you
  *  should call open_next_part()
- * It is also called from truncate_dvd_dev to "blank" the medium, as
+ * It is also called from truncate_dvd to "blank" the medium, as
  *  well as from block.c when the DVD is full to write the last part.
  */
 bool dvd_write_part(DCR *dcr) 
@@ -342,7 +347,7 @@ bool dvd_write_part(DCR *dcr)
    Dmsg3(29, "dvd_write_part: device is %s, part is %d, is_mounted=%d\n", dev->print_name(), dev->part, dev->is_mounted());
    icmd = dev->device->write_part_command;
    
-   edit_device_codes_dev(dev, ocmd, icmd);
+   dev->edit_mount_codes(ocmd, icmd);
       
    /*
     * original line follows
@@ -390,7 +395,7 @@ bool dvd_write_part(DCR *dcr)
    
    /* growisofs umounted the device, so remount it (it will update the free space) */
    dev->clear_mounted();
-   mount_dev(dev, 1);
+   mount_dvd(dev, 1);
    Jmsg(dcr->jcr, M_INFO, 0, _("Remaining free space %s on %s\n"), 
       edit_uint64_with_commas(dev->free_space, ed1), dev->print_name());
    sm_check(__FILE__, __LINE__, false);
@@ -708,7 +713,7 @@ bool dvd_close_job(DCR *dcr)
    return ok;
 }
 
-bool truncate_dvd_dev(DCR *dcr) {
+bool truncate_dvd(DCR *dcr) {
    DEVICE* dev = dcr->dev;
 
    /* Set num_parts to zero (on disk) */
@@ -716,17 +721,17 @@ bool truncate_dvd_dev(DCR *dcr) {
    dcr->VolCatInfo.VolCatParts = 0;
    dev->VolCatInfo.VolCatParts = 0;
    
-   Dmsg0(100, "truncate_dvd_dev: Opening first part (1)...\n");
+   Dmsg0(100, "truncate_dvd: Opening first part (1)...\n");
    
    dev->truncating = true;
    if (dvd_open_first_part(dcr, OPEN_READ_WRITE) < 0) {
-      Dmsg0(100, "truncate_dvd_dev: Error while opening first part (1).\n");
+      Dmsg0(100, "truncate_dvd: Error while opening first part (1).\n");
       dev->truncating = false;
       return false;
    }
    dev->truncating = false;
 
-   Dmsg0(100, "truncate_dvd_dev: Truncating...\n");
+   Dmsg0(100, "truncate_dvd: Truncating...\n");
 
    /* If necessary, truncate it. */
    if (ftruncate(dev->fd, 0) != 0) {
@@ -740,10 +745,10 @@ bool truncate_dvd_dev(DCR *dcr) {
    dev->fd = -1;
    dev->clear_opened();
    
-   Dmsg0(100, "truncate_dvd_dev: Opening first part (2)...\n");
+   Dmsg0(100, "truncate_dvd: Opening first part (2)...\n");
    
    if (!dvd_write_part(dcr)) {
-      Dmsg0(100, "truncate_dvd_dev: Error while writing to DVD.\n");
+      Dmsg0(100, "truncate_dvd: Error while writing to DVD.\n");
       return false;
    }
    
@@ -753,7 +758,7 @@ bool truncate_dvd_dev(DCR *dcr) {
    dev->VolCatInfo.VolCatParts = 0;
    
    if (dvd_open_first_part(dcr, OPEN_READ_WRITE) < 0) {
-      Dmsg0(100, "truncate_dvd_dev: Error while opening first part (2).\n");
+      Dmsg0(100, "truncate_dvd: Error while opening first part (2).\n");
       return false;
    }
 
@@ -792,8 +797,7 @@ bool check_can_write_on_non_blank_dvd(DCR *dcr) {
          Dmsg2(129, "check_can_write_on_non_blank_dvd: failed to find suitable file in dir %s (dev=%s)\n", 
                dev->device->mount_point, dev->print_name());
          break;
-      }
-      else {
+      } else {
          Dmsg2(99, "check_can_write_on_non_blank_dvd: found %s (versus %s)\n", 
                result->d_name, dev->VolCatInfo.VolCatName);
          if (strcmp(result->d_name, dev->VolCatInfo.VolCatName) == 0) {
@@ -813,7 +817,7 @@ bool check_can_write_on_non_blank_dvd(DCR *dcr) {
             }
             Dmsg2(99, "check_can_write_on_non_blank_dvd: size of %s is %d\n", 
                filename.c_str(), filestat.st_size);
-            matched = (filestat.st_size == 0);
+            matched = filestat.st_size == 0;
          }
       }
       count++;
@@ -824,77 +828,9 @@ bool check_can_write_on_non_blank_dvd(DCR *dcr) {
    Dmsg2(29, "check_can_write_on_non_blank_dvd: got %d files in the mount point (matched=%d)\n", count, matched);
    
    if (count != 3) {
-      /* There is more than 3 files (., .., and the volume file) */
+      /* There are more than 3 files (., .., and the volume file) */
       return false;
    }
    
    return matched;
 }
-
-/*
- * Edit codes into (Un)MountCommand, Write(First)PartCommand
- *  %% = %
- *  %a = archive device name
- *  %e = erase (set if cannot mount and first part)
- *  %n = part number
- *  %m = mount point
- *  %v = last part name
- *
- *  omsg = edited output message
- *  imsg = input string containing edit codes (%x)
- *
- */
-static void edit_device_codes_dev(DEVICE* dev, POOL_MEM &omsg, const char *imsg)
-{
-   const char *p;
-   const char *str;
-   char add[20];
-   
-   POOL_MEM archive_name(PM_FNAME);
-
-   omsg.c_str()[0] = 0;
-   Dmsg1(800, "edit_device_codes: %s\n", imsg);
-   for (p=imsg; *p; p++) {
-      if (*p == '%') {
-         switch (*++p) {
-         case '%':
-            str = "%";
-            break;
-         case 'a':
-            str = dev->dev_name;
-            break;
-         case 'e':
-            if (dev->num_parts == 0) {
-               str = "1";
-            } else {
-               str = "0";
-            }
-            break;
-         case 'n':
-            bsnprintf(add, sizeof(add), "%d", dev->part);
-            str = add;
-            break;
-         case 'm':
-            str = dev->device->mount_point;
-            break;
-         case 'v':
-            make_spooled_dvd_filename(dev, archive_name);
-            str = archive_name.c_str();
-            break;
-         default:
-            add[0] = '%';
-            add[1] = *p;
-            add[2] = 0;
-            str = add;
-            break;
-         }
-      } else {
-         add[0] = *p;
-         add[1] = 0;
-         str = add;
-      }
-      Dmsg1(1900, "add_str %s\n", str);
-      pm_strcat(omsg, (char *)str);
-      Dmsg1(1800, "omsg=%s\n", omsg.c_str());
-   }
-}
index 8c798a436de9bc1e442ac8e29c117c86b3877267..aca7e3c0d497570f14686de35083f9ff6e3ec50f 100644 (file)
@@ -13,7 +13,7 @@
  *
  */
 /*
-   Copyright (C) 2000-2005 Kern Sibbald
+   Copyright (C) 2000-2006 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
@@ -53,9 +53,10 @@ static bool append_end_session(JCR *jcr);
 static bool read_open_session(JCR *jcr);
 static bool read_data_cmd(JCR *jcr);
 static bool read_close_session(JCR *jcr);
+static bool bootstrap_cmd(JCR *jcr);
 
 /* Exported function */
-bool bootstrap_cmd(JCR *jcr);
+bool get_bootstrap_file(JCR *jcr, BSOCK *bs);
 
 struct s_cmds {
    const char *cmd;
@@ -93,7 +94,7 @@ static char ERROR_bootstrap[] = "3904 Error bootstrap\n";
 
 /* Information sent to the Director */
 static char Job_start[] = "3010 Job %s start\n";
-static char Job_end[]   =
+char Job_end[]   =
    "3099 Job %s end JobStatus=%d JobFiles=%d JobBytes=%s\n";
 
 /*
@@ -309,9 +310,13 @@ static bool read_open_session(JCR *jcr)
    return true;
 }
 
-bool bootstrap_cmd(JCR *jcr)
+static bool bootstrap_cmd(JCR *jcr)
+{
+   return get_bootstrap_file(jcr, jcr->file_bsock);
+}
+
+bool get_bootstrap_file(JCR *jcr, BSOCK *sock)
 {
-   BSOCK *fd = jcr->file_bsock;
    POOLMEM *fname = get_pool_memory(PM_FNAME);
    FILE *bs;
    bool ok = false;
@@ -330,9 +335,9 @@ bool bootstrap_cmd(JCR *jcr)
          jcr->RestoreBootstrap, strerror(errno));
       goto bail_out;
    }
-   while (bnet_recv(fd) >= 0) {
-       Dmsg1(400, "stored<filed: bootstrap file %s", fd->msg);
-       fputs(fd->msg, bs);
+   while (bnet_recv(sock) >= 0) {
+       Dmsg1(400, "stored<filed: bootstrap file %s", sock->msg);
+       fputs(sock->msg, bs);
    }
    fclose(bs);
    jcr->bsr = parse_bsr(jcr, jcr->RestoreBootstrap);
@@ -350,10 +355,10 @@ bail_out:
    free_pool_memory(jcr->RestoreBootstrap);
    jcr->RestoreBootstrap = NULL;
    if (!ok) {
-      bnet_fsend(fd, ERROR_bootstrap);
+      bnet_fsend(sock, ERROR_bootstrap);
       return false;
    }
-   return bnet_fsend(fd, OK_bootstrap);
+   return bnet_fsend(sock, OK_bootstrap);
 }
 
 
index 1176ef45f8e64de2fddbb2b7493a94b215f46e0c..c00c7d37ea01e28e05bd891261bd9f5cd8094c5c 100644 (file)
@@ -7,7 +7,7 @@
  *
  */
 /*
-   Copyright (C) 2000-2005 Kern Sibbald
+   Copyright (C) 2000-2006 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -29,6 +29,7 @@ extern uint32_t VolSessionTime;
 
 /* Imported functions */
 extern uint32_t newVolSessionId();
+extern bool do_mac(JCR *jcr);
 
 /* Requests from the Director daemon */
 static char jobcmd[] = "JobId=%d job=%127s job_name=%127s client_name=%127s "
@@ -141,7 +142,7 @@ bool run_cmd(JCR *jcr)
    case JT_COPY:
    case JT_ARCHIVE:
       jcr->authenticated = true;
-      run_job(jcr);
+      do_mac(jcr);
       return false;
    }
 
@@ -247,7 +248,6 @@ bool query_cmd(JCR *jcr)
    Dmsg1(100, "<dird: %s\n", dir->msg);
    if (ok) {
       unbash_spaces(dev_name);
-//    LockRes();
       foreach_res(device, R_DEVICE) {
          /* Find resource, and make sure we were able to open it */
          if (fnmatch(dev_name.c_str(), device->hdr.name, 0) == 0) {
@@ -257,7 +257,6 @@ bool query_cmd(JCR *jcr)
             if (!device->dev) {
                break;
             }  
-//          UnlockRes();
             ok = dir_update_device(jcr, device->dev);
             if (ok) {
                ok = bnet_fsend(dir, OK_query);
@@ -270,7 +269,6 @@ bool query_cmd(JCR *jcr)
       foreach_res(changer, R_AUTOCHANGER) {
          /* Find resource, and make sure we were able to open it */
          if (fnmatch(dev_name.c_str(), changer->hdr.name, 0) == 0) {
-//          UnlockRes();
             if (!changer->device || changer->device->size() == 0) {
                continue;              /* no devices */
             }
@@ -284,7 +282,6 @@ bool query_cmd(JCR *jcr)
          }
       }
       /* If we get here, the device/autochanger was not found */
-//    UnlockRes();
       unbash_spaces(dir->msg);
       pm_strcpy(jcr->errmsg, dir->msg);
       bnet_fsend(dir, NO_device, dev_name.c_str());
index ee0d4fbd74392773cd0db984bf0d88b5e96d3a7b..72340278f83c366c8795e1ff6293fa2cd6538036 100644 (file)
@@ -8,7 +8,7 @@
  *   Version $Id$
  */
 /*
-   Copyright (C) 2000-2005 Kern Sibbald
+   Copyright (C) 2000-2006 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -71,7 +71,9 @@ int read_dev_volume_label(DCR *dcr)
       dev->VolHdr.VolumeName[0]?dev->VolHdr.VolumeName:"*NULL*");
 
    if (!dev->is_open()) {
-      Emsg0(M_ABORT, 0, _("BAD call to read_dev_volume_label\n"));
+      if (dev->open(dcr, OPEN_READ_ONLY) < 0) {
+         return VOL_IO_ERROR;
+      }
    }
    if (dev->is_labeled()) {              /* did we already read label? */
       /* Compare Volume Names allow special wild card */
@@ -287,8 +289,6 @@ bool write_volume_label_to_block(DCR *dcr)
  *            after the label will be destroyed,
  *            in fact, we write the label 5 times !!!!
  *
- *  This routine expects that open_device() was previously called.
- *
  *  This routine should be used only when labeling a blank tape.
  */
 bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, const char *PoolName)
@@ -300,7 +300,10 @@ bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, const char *Po
    empty_block(dcr->block);
 
    if (dev->open(dcr, OPEN_READ_WRITE) < 0) {
-      goto bail_out;
+      /* If device is not tape, attempt to create it */
+      if (dev->is_tape() || dev->open(dcr, CREATE_READ_WRITE) < 0) {
+         goto bail_out;
+      }
    }
    Dmsg1(150, "Label type=%d\n", dev->label_type);
    if (!dev->rewind(dcr)) {
@@ -401,7 +404,7 @@ bool rewrite_volume_label(DCR *dcr, bool recycle)
                dev->print_name(), strerror_dev(dev));
       }
       if (recycle) {
-         if (!truncate_dev(dcr)) {
+         if (!dev->truncate(dcr)) {
             Jmsg2(jcr, M_WARNING, 0, _("Truncate error on device %s: ERR=%s\n"),
                   dev->print_name(), strerror_dev(dev));
          }
index 28ce910ab86672abb5053f9681ab9dc3bd4b1ba1..d88181a9c2b48c090e7a56ed62362dcfd2d61cc3 100644 (file)
@@ -8,7 +8,7 @@
  *   Version $Id$
  */
 /*
-   Copyright (C) 2002-2005 Kern Sibbald
+   Copyright (C) 2002-2006 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
 #include "stored.h"                   /* pull in Storage Deamon headers */
 
 static void mark_volume_not_inchanger(DCR *dcr);
+static int try_autolabel(DCR *dcr);
+
+enum {
+   try_next_vol = 1,
+   try_read_vol,
+   try_error,
+   try_default
+};
 
 /*
  * If release is set, we rewind the current volume,
@@ -47,6 +55,7 @@ bool mount_next_write_volume(DCR *dcr, bool release)
    DEVICE *dev = dcr->dev;
    JCR *jcr = dcr->jcr;
    DEV_BLOCK *block = dcr->block;
+   int mode;
 
    Dmsg1(150, "Enter mount_next_volume(release=%d)\n", release);
 
@@ -123,12 +132,12 @@ mount_next_vol:
     *   and read the label. If there is no tape in the drive,
     *   we will err, recurse and ask the operator the next time.
     */
-   if (!release && dev->is_tape() && dev_cap(dev, CAP_AUTOMOUNT)) {
+   if (!release && dev->is_tape() && dev->has_cap(CAP_AUTOMOUNT)) {
       Dmsg0(150, "(1)Ask=0\n");
       ask = false;                 /* don't ask SYSOP this time */
    }
    /* Don't ask if not removable */
-   if (!dev_cap(dev, CAP_REM)) {
+   if (!dev->is_removable()) {
       Dmsg0(150, "(2)Ask=0\n");
       ask = false;
    }
@@ -144,15 +153,30 @@ mount_next_vol:
    }
    Dmsg1(150, "want vol=%s\n", dcr->VolumeName);
 
-   if (dev->poll && dev_cap(dev, CAP_CLOSEONPOLL)) {
-      force_close_device(dev);
+   if (dev->poll && dev->has_cap(CAP_CLOSEONPOLL)) {
+      dev->close();
    }
 
    /* Ensure the device is open */
-   if (!open_device(dcr)) {
+   if (dev_cap(dev, CAP_STREAM)) {
+      mode = OPEN_WRITE_ONLY;
+   } else {
+      mode = OPEN_READ_WRITE;
+   }
+   while (dev->open(dcr, mode) < 0) {
+      Dmsg0(000, "open_device failed\n");
+      if (dev->is_file() && dev->is_removable()) {
+         Dmsg0(000, "call scan_dir_for_vol\n");
+         if (dev->scan_dir_for_volume(dcr)) {
+            break;                    /* got a valid volume */
+         }
+      }
+      if (try_autolabel(dcr) == try_read_vol) {
+         break;                       /* created a new volume label */
+      }
       /* If DVD, ignore the error, very often you cannot open the device
        * (when there is no DVD, or when the one inserted is a wrong one) */
-      if ((dev->poll) || (dev->is_dvd())) {
+      if (dev->poll || dev->is_dvd() || dev->is_removable()) {
          goto mount_next_vol;
       } else {
          return false;
@@ -167,7 +191,7 @@ read_volume:
     * If we are writing to a stream device, ASSUME the volume label
     *  is correct.
     */
-   if (dev_cap(dev, CAP_STREAM)) {
+   if (dev->has_cap(CAP_STREAM)) {
       vol_label_status = VOL_OK;
       create_volume_label(dev, dcr->VolumeName, "Default");
       dev->VolHdr.LabelType = PRE_LABEL;
@@ -194,7 +218,7 @@ read_volume:
       VOLUME_CAT_INFO VolCatInfo, devVolCatInfo;
 
       /* If not removable, Volume is broken */
-      if (!dev_cap(dev, CAP_REM)) {
+      if (!dev->is_removable()) {
          Jmsg(jcr, M_WARNING, 0, _("Volume \"%s\" not on device %s.\n"),
             dcr->VolumeName, dev->print_name());
          mark_volume_in_error(dcr);
@@ -205,8 +229,7 @@ read_volume:
       /* If polling and got a previous bad name, ignore it */
       if (dev->poll && strcmp(dev->BadVolName, dev->VolHdr.VolumeName) == 0) {
          ask = true;
-         Dmsg1(200, "Vol Name error supress due to poll. Name=%s\n",
-            dcr->VolumeName);
+         Dmsg1(200, "Vol Name error supress due to poll. Name=%s\n", dcr->VolumeName);
          goto mount_next_vol;
       }
       /*
@@ -254,49 +277,17 @@ read_volume:
       }
       /* Fall through wanted */
    case VOL_NO_LABEL:
-      /*
-       * If permitted, we label the device, make sure we can do
-       *   it by checking that the VolCatBytes is zero => not labeled,
-       *   once the Volume is labeled we don't want to label another
-       *   blank tape with the same name.  For disk, we go ahead and
-       *   label it anyway, because the OS insures that there is only
-       *   one Volume with that name.
-       * As noted above, at this point dcr->VolCatInfo has what
-       *   the Director wants and dev->VolCatInfo has info on the
-       *   previous tape (or nothing).
-       */
-      if (dev_cap(dev, CAP_LABEL) && (dcr->VolCatInfo.VolCatBytes == 0 ||
-            (!dev->is_tape() && strcmp(dcr->VolCatInfo.VolCatStatus,
-                                   "Recycle") == 0))) {
-         Dmsg0(150, "Create volume label\n");
-         /* Create a new Volume label and write it to the device */
-         if (!write_new_volume_label_to_dev(dcr, dcr->VolumeName,
-                dcr->pool_name)) {
-            Dmsg0(150, "!write_vol_label\n");
-            mark_volume_in_error(dcr);
-            goto mount_next_vol;
-         }
-         Dmsg0(150, "dir_update_vol_info. Set Append\n");
-         /* Copy Director's info into the device info */
-         memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
-         if (!dir_update_volume_info(dcr, true)) {  /* indicate tape labeled */
-            return false;
-         }
-         Jmsg(jcr, M_INFO, 0, _("Labeled new Volume \"%s\" on device %s.\n"),
-            dcr->VolumeName, dev->print_name());
-         goto read_volume;      /* read label we just wrote */
-      }
-      if (!dev_cap(dev, CAP_LABEL) && dcr->VolCatInfo.VolCatBytes == 0) {
-         Jmsg(jcr, M_INFO, 0, _("Warning device %s not configured to autolabel Volumes.\n"), 
-            dev->print_name());
-      }
-      /* If not removable, Volume is broken */
-      if (!dev_cap(dev, CAP_REM)) {
-         Jmsg(jcr, M_WARNING, 0, _("Volume \"%s\" not on device %s.\n"),
-            dcr->VolumeName, dev->print_name());
-         mark_volume_in_error(dcr);
+      switch (try_autolabel(dcr)) {
+      case try_next_vol:
          goto mount_next_vol;
+      case try_read_vol:
+         goto read_volume;
+      case try_error:
+         return false;
+      case try_default:
+         break;
       }
+
       /* NOTE! Fall-through wanted. */
    case VOL_NO_MEDIA:
    default:
@@ -309,7 +300,7 @@ read_volume:
       ask = true;
       /* Needed, so the medium can be changed */
       if (dev->requires_mount()) {
-         close_device(dev);  
+         dev->close();
       }
       goto mount_next_vol;
    }
@@ -341,7 +332,7 @@ read_volume:
       Dmsg0(200, "Device previously written, moving to end of data\n");
       Jmsg(jcr, M_INFO, 0, _("Volume \"%s\" previously written, moving to end of data.\n"),
          dcr->VolumeName);
-      if (!eod_dev(dev)) {
+      if (!dev->eod()) {
          Jmsg(jcr, M_ERROR, 0, _("Unable to position to end of data on device %s: ERR=%s\n"),
             dev->print_name(), strerror_dev(dev));
          mark_volume_in_error(dcr);
@@ -407,6 +398,54 @@ read_volume:
    return true;
 }
 
+/*
+ * If permitted, we label the device, make sure we can do
+ *   it by checking that the VolCatBytes is zero => not labeled,
+ *   once the Volume is labeled we don't want to label another
+ *   blank tape with the same name.  For disk, we go ahead and
+ *   label it anyway, because the OS insures that there is only
+ *   one Volume with that name.
+ * As noted above, at this point dcr->VolCatInfo has what
+ *   the Director wants and dev->VolCatInfo has info on the
+ *   previous tape (or nothing).
+ */
+static int try_autolabel(DCR *dcr)
+{
+   DEVICE *dev = dcr->dev;
+   if (dev->has_cap(CAP_LABEL) && (dcr->VolCatInfo.VolCatBytes == 0 ||
+         (!dev->is_tape() && strcmp(dcr->VolCatInfo.VolCatStatus,
+                                "Recycle") == 0))) {
+      Dmsg0(150, "Create volume label\n");
+      /* Create a new Volume label and write it to the device */
+      if (!write_new_volume_label_to_dev(dcr, dcr->VolumeName,
+             dcr->pool_name)) {
+         Dmsg0(150, "!write_vol_label\n");
+         mark_volume_in_error(dcr);
+         return try_next_vol;
+      }
+      Dmsg0(150, "dir_update_vol_info. Set Append\n");
+      /* Copy Director's info into the device info */
+      memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
+      if (!dir_update_volume_info(dcr, true)) {  /* indicate tape labeled */
+         return try_error;
+      }
+      Jmsg(dcr->jcr, M_INFO, 0, _("Labeled new Volume \"%s\" on device %s.\n"),
+         dcr->VolumeName, dev->print_name());
+      return try_read_vol;   /* read label we just wrote */
+   }
+   if (!dev->has_cap(CAP_LABEL) && dcr->VolCatInfo.VolCatBytes == 0) {
+      Jmsg(dcr->jcr, M_INFO, 0, _("Warning device %s not configured to autolabel Volumes.\n"), 
+         dev->print_name());
+   }
+   /* If not removable, Volume is broken */
+   if (!dev->is_removable()) {
+      Jmsg(dcr->jcr, M_WARNING, 0, _("Volume \"%s\" not on device %s.\n"),
+         dcr->VolumeName, dev->print_name());
+      mark_volume_in_error(dcr);
+      return try_next_vol;
+   }
+   return try_default;
+}
 
 
 /*
@@ -470,13 +509,12 @@ void release_volume(DCR *dcr)
    dcr->VolumeName[0] = 0;
 
    if (dev->is_open() && (!dev->is_tape() || !dev_cap(dev, CAP_ALWAYSOPEN))) {
-      offline_or_rewind_dev(dev);
-      close_device(dev);
+      dev->close();
    }
 
    /* If we have not closed the device, then at least rewind the tape */
    if (dev->is_open()) {
-      offline_or_rewind_dev(dev);
+      dev->offline_or_rewind();
    }
    Dmsg0(190, "release_volume\n");
 }
@@ -494,8 +532,7 @@ bool mount_next_read_volume(DCR *dcr)
     * End Of Tape -- mount next Volume (if another specified)
     */
    if (jcr->NumVolumes > 1 && jcr->CurVolume < jcr->NumVolumes) {
-      close_device(dev);
-      dev->clear_read();
+      dev->close();
       if (!acquire_device_for_read(dcr)) {
          Jmsg2(jcr, M_FATAL, 0, _("Cannot open Dev=%s, Vol=%s\n"), dev->print_name(),
                dcr->VolumeName);
index c5b458fd2aa7c50c8d614fe8d8d0490edd7dfa83..384cfb7ef739c846fcde9fbfbf9f54c851132841 100644 (file)
@@ -91,7 +91,6 @@ void     clrerror_dev(DEVICE *dev, int func);
 bool     update_pos_dev(DEVICE *dev);
 bool     rewind_dev(DEVICE *dev);
 bool     load_dev(DEVICE *dev);
-bool     offline_dev(DEVICE *dev);
 int      flush_dev(DEVICE *dev);
 int      weof_dev(DEVICE *dev, int num);
 int      write_block(DEVICE *dev);
@@ -103,7 +102,6 @@ bool     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);
-bool     offline_or_rewind_dev(DEVICE *dev);
 bool     reposition_dev(DEVICE *dev, uint32_t file, uint32_t block);
 void     init_device_wait_timers(DCR *dcr);
 void     init_jcr_device_wait_timers(JCR *jcr);
@@ -118,18 +116,16 @@ uint32_t dev_file(DEVICE *dev);
 int  dvd_open_next_part(DCR *dcr);
 bool dvd_write_part(DCR *dcr); 
 bool dvd_close_job(DCR *dcr);
-bool mount_dev(DEVICE* dev, int timeout);
-bool unmount_dev(DEVICE* dev, int timeout);
+bool mount_dvd(DEVICE* dev, int timeout);
+bool unmount_dvd(DEVICE* dev, int timeout);
 void update_free_space_dev(DEVICE *dev);
 void make_mounted_dvd_filename(DEVICE *dev, POOL_MEM &archive_name);
 void make_spooled_dvd_filename(DEVICE *dev, POOL_MEM &archive_name);
-bool truncate_dvd_dev(DCR *dcr);
+bool truncate_dvd(DCR *dcr);
 bool check_can_write_on_non_blank_dvd(DCR *dcr);
 
 /* From device.c */
 bool     open_device(DCR *dcr);
-void     close_device(DEVICE *dev);
-void     force_close_device(DEVICE *dev);
 bool     first_open_device(DCR *dcr);
 bool     fixup_device_block_write_error(DCR *dcr);
 void     _lock_device(const char *file, int line, DEVICE *dev);
@@ -150,7 +146,7 @@ void     *handle_connection_request(void *arg);
 
 /* From fd_cmds.c */
 void     run_job(JCR *jcr);
-bool     bootstrap_cmd(JCR *jcr);
+bool get_bootstrap_file(JCR *jcr, BSOCK *bsock);
 
 /* From job.c */
 void     stored_free_jcr(JCR *jcr);
index 2eb35186655f1390907607a4d528f77e33c180ff..633cea29fab810a996d16c2aedf65dcaafc8cd44 100644 (file)
@@ -6,7 +6,7 @@
  *   Version $Id$
  */
 /*
-   Copyright (C) 2000-2005 Kern Sibbald
+   Copyright (C) 2000-2006 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
index 2f00de4b58abb062e57084692f38b2da2241caad..f6f2e8ed3d5430965c702dda4f457489fe5a900a 100644 (file)
@@ -6,7 +6,7 @@
  *   Version $Id$
  */
 /*
-   Copyright (C) 2000-2005 Kern Sibbald
+   Copyright (C) 2000-2006 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -34,6 +34,8 @@ RES **res_head = sres_head;
 
 
 /* Forward referenced subroutines */
+static void store_devtype(LEX *lc, RES_ITEM *item, int index, int pass);
+
 
 /* We build the current resource here statically,
  * then move it to dynamic memory */
@@ -95,6 +97,7 @@ static RES_ITEM dev_items[] = {
    {"name",                  store_name,   ITEM(res_dev.hdr.name),        0, ITEM_REQUIRED, 0},
    {"description",           store_str,    ITEM(res_dir.hdr.desc),        0, 0, 0},
    {"mediatype",             store_strname,ITEM(res_dev.media_type),      0, ITEM_REQUIRED, 0},
+   {"devicetype",            store_devtype,ITEM(res_dev.dev_type), 0, 0, 0},
    {"archivedevice",         store_strname,ITEM(res_dev.device_name),     0, ITEM_REQUIRED, 0},
    {"hardwareendoffile",     store_yesno,  ITEM(res_dev.cap_bits), CAP_EOF,  ITEM_DEFAULT, 1},
    {"hardwareendofmedium",   store_yesno,  ITEM(res_dev.cap_bits), CAP_EOM,  ITEM_DEFAULT, 1},
@@ -174,7 +177,48 @@ RES_TABLE resources[] = {
    {NULL,            NULL,          0}
 };
 
+/*
+ * Device types
+ *
+ *   device type     device code = token
+ */
+struct s_kw {
+   const char *name;
+   int token;
+};
 
+static s_kw dev_types[] = {
+   {"file",          B_FILE_DEV},
+   {"tape",          B_TAPE_DEV},
+   {"dvd",           B_DVD_DEV},
+   {"fifo",          B_FIFO_DEV},
+   {NULL,            0}
+};
+
+
+/*
+ * Store Device Type (File, FIFO, Tape, DVD)
+ *
+ */
+static void store_devtype(LEX *lc, RES_ITEM *item, int index, int pass)
+{
+   int token, i;
+
+   token = lex_get_token(lc, T_NAME);
+   /* Store the label pass 2 so that type is defined */
+   for (i=0; dev_types[i].name; i++) {
+      if (strcasecmp(lc->str, dev_types[i].name) == 0) {
+         *(int *)(item->value) = dev_types[i].token;
+         i = 0;
+         break;
+      }
+   }
+   if (i != 0) {
+      scan_err1(lc, _("Expected a Device Type keyword, got: %s"), lc->str);
+   }
+   scan_to_eol(lc);
+   set_bit(index, res_all.hdr.item_present);
+}
 
 
 /* Dump contents of resource */
index c025dbbff17acf0e89ac0dac8e88acb0a929633b..6cc91f3eea6c86d2b036a7db985b58f87acd62a1 100644 (file)
@@ -4,7 +4,7 @@
  *   Version $Id$
  */
 /*
-   Copyright (C) 2000-2005 Kern Sibbald
+   Copyright (C) 2000-2006 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
@@ -75,7 +75,7 @@ public:
    utime_t heartbeat_interval;        /* Interval to send hb to FD */
    int tls_enable;                    /* Enable TLS */
    int tls_require;                   /* Require TLS */
-   int tls_verify_peer;              /* TLS Verify Client Certificate */
+   int tls_verify_peer;               /* TLS Verify Client Certificate */
    char *tls_ca_certfile;             /* TLS CA Certificate File */
    char *tls_ca_certdir;              /* TLS CA Certificate Directory */
    char *tls_certfile;                /* TLS Server Certificate File */
@@ -107,6 +107,7 @@ public:
    char *changer_command;             /* Changer command  -- external program */
    char *alert_command;               /* Alert command -- external program */
    char *spool_directory;             /* Spool file directory */
+   int   dev_type;                    /* device type */
    int   label_type;                  /* label type */
    int   autoselect;                  /* Automatically select from AutoChanger */
    uint32_t drive_index;              /* Autochanger drive index */
index c21e46b520ecef2a10c6d5524fabd54db341e142..03ae06a43f08a1ab2b7a359db8e4c4ed68c05f31 100644 (file)
@@ -3,9 +3,9 @@
  */
 
 #undef  VERSION
-#define VERSION "1.39.4"
-#define BDATE   "14 January 2006"
-#define LSMDATE "14Jan06"
+#define VERSION "1.39.5"
+#define BDATE   "30 January 2006"
+#define LSMDATE "30Jan06"
 
 /* Debug flags */
 #undef  DEBUG