]> git.sur5r.net Git - bacula/bacula/commitdiff
Server address binding + bscan updates -- see kes25Sep02
authorKern Sibbald <kern@sibbald.com>
Wed, 25 Sep 2002 21:12:36 +0000 (21:12 +0000)
committerKern Sibbald <kern@sibbald.com>
Wed, 25 Sep 2002 21:12:36 +0000 (21:12 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@163 91ce42f0-d328-0410-95d8-f526ca767f89

26 files changed:
bacula/ChangeLog
bacula/src/cats/Makefile.in
bacula/src/dird/dird.c
bacula/src/dird/dird_conf.c
bacula/src/dird/dird_conf.h
bacula/src/dird/job.c
bacula/src/dird/ua_input.c
bacula/src/dird/ua_server.c
bacula/src/filed/filed.c
bacula/src/filed/filed_conf.c
bacula/src/filed/filed_conf.h
bacula/src/findlib/Makefile.in
bacula/src/jcr.h
bacula/src/lib/Makefile.in
bacula/src/lib/bnet_server.c
bacula/src/lib/jcr.c
bacula/src/lib/protos.h
bacula/src/lib/util.c
bacula/src/stored/bacula-sd.conf.in
bacula/src/stored/bscan.c
bacula/src/stored/butil.c
bacula/src/stored/read_record.c
bacula/src/stored/stored.c
bacula/src/stored/stored_conf.c
bacula/src/stored/stored_conf.h
bacula/src/version.h

index dc2b70f75e05b7325685f6b0b6f612ab4c97d309..9dafa5c9e60635eccdbdb3f5011094e544b71c55 100644 (file)
@@ -1,6 +1,27 @@
 
 2002-xx-xx Version 1.26 (xxOct02)
-General:
+General: From kes25Sep02
+- Added means to bind servers to specific address.
+- Documentation
+
+Changes submitted this submission:
+- Added DirAddress, FDAddress, and SDAddress records to the corresponding
+  resources that allow the server to bind to a specific address 
+  rather than any address.  This security improvement was suggested by
+  a user -- thank you.
+- Eliminated deprecated "Address" record from all sample Storage resources.
+- Made quite a lot of improvements to the bscan program. Much more
+  to do. Aside from details, it is able to recreate a database
+  from which you can do a restore.
+- The s option is not accepted on all versions of ar, so replaced it
+  by an explicit ranlib call.
+- Fixed a bug that caused the Director to crash if you rudely bring
+  down the console program in the middle of an SQL command.
+- Fixed a bug (missing break) that caused scheduled Admin jobs to
+  be listed as "Unknown type".
+- Removed old code from Storage daemon that used a separate FD port.
+
+General:  From kes14Sep02
 - Better key generation on non OpenSSL systems.
 - 64 bit file address support if available.
 - Implement autochanger for reading
index 9dcfd645f45aca4c72dab1749aeda847e3772c2b..fbdf8801c58c1f9936e689bef60c6f0ca005396d 100644 (file)
@@ -44,7 +44,8 @@ all: Makefile libsql.a
        @echo " "
 
 libsql.a: $(LIBOBJS)
-       $(AR) rcs $@ $(LIBOBJS)
+       $(AR) rc  $@ $(LIBOBJS)
+       $(RANLIB) $@
 
 cats: $(SVROBJS) ../findlib/libfind.a
        $(CC) $(LDFLAGS) -L../findlib -L../lib -o $@ $(SVROBJS) $(LIBS) $(DB_LIBS) -lfind -lbac
index 26eed34c9707d2ba2a7cc2c5ce68ff0bde11db56..7401a340c6ea00e772372d2d2d49923074438c1b 100644 (file)
@@ -43,7 +43,7 @@ extern void term_scheduler();
 extern void term_ua_server();
 extern int do_backup(JCR *jcr);
 extern void backup_cleanup(void);
-extern void start_UA_server(int port);
+extern void start_UA_server(char *addr, int port);
 extern void run_job(JCR *jcr);
 extern void init_job_server(int max_workers);
 
@@ -194,7 +194,7 @@ int main (int argc, char *argv[])
       4 /* UA */ + 4 /* sched+watchdog+jobsvr+misc */);
 
    Dmsg0(200, "Start UA server\n");
-   start_UA_server(director->DIRport);
+   start_UA_server(director->DIRaddr, director->DIRport);
 
    start_watchdog();                 /* start network watchdog thread */
 
index 2b9c2f781d17452c13cee1f45ca84b7c679ff760..1fd62959b6c6bd47ad6a9def041c6d86d91c3d9e 100644 (file)
@@ -88,6 +88,7 @@ static struct res_items dir_items[] = {
    {"description", store_str,      ITEM(res_dir.hdr.desc), 0, 0, 0},
    {"messages",    store_res,      ITEM(res_dir.messages), R_MSGS, 0, 0},
    {"dirport",     store_pint,     ITEM(res_dir.DIRport),  0, ITEM_DEFAULT, 9101},
+   {"diraddress",  store_str,      ITEM(res_dir.DIRaddr),  0, 0, 0},
    {"queryfile",   store_dir,      ITEM(res_dir.query_file), 0, ITEM_REQUIRED, 0},
    {"workingdirectory", store_dir, ITEM(res_dir.working_directory), 0, ITEM_REQUIRED, 0},
    {"piddirectory", store_dir,     ITEM(res_dir.pid_directory), 0, ITEM_REQUIRED, 0},
@@ -642,22 +643,32 @@ void free_resource(int type)
 
    switch (type) {
       case R_DIRECTOR:
-        if (res->res_dir.working_directory)
+        if (res->res_dir.working_directory) {
            free(res->res_dir.working_directory);
-        if (res->res_dir.pid_directory)
+        }
+        if (res->res_dir.pid_directory) {
            free(res->res_dir.pid_directory);
-        if (res->res_dir.subsys_directory)
+        }
+        if (res->res_dir.subsys_directory) {
            free(res->res_dir.subsys_directory);
-        if (res->res_dir.password)
+        }
+        if (res->res_dir.password) {
            free(res->res_dir.password);
-        if (res->res_dir.query_file)
+        }
+        if (res->res_dir.query_file) {
            free(res->res_dir.query_file);
+        }
+        if (res->res_dir.DIRaddr) {
+           free(res->res_dir.DIRaddr);
+        }
         break;
       case R_CLIENT:
-        if (res->res_client.address)
+        if (res->res_client.address) {
            free(res->res_client.address);
-        if (res->res_client.password)
+        }
+        if (res->res_client.password) {
            free(res->res_client.password);
+        }
         break;
       case R_STORAGE:
         if (res->res_store.address)
index 67a9fb8d15d9418224ddce018a121c36d6bfc860..11c47bdfc303ee79883130f400fc958f51875a03 100644 (file)
@@ -84,6 +84,7 @@ struct s_jt {
 struct s_res_dir {
    RES  hdr;
    int  DIRport;                     /* where we listen -- UA port server port */
+   char *DIRaddr;                    /* bind address */
    char *password;                   /* Password for UA access */
    char *query_file;                 /* SQL query file */
    char *working_directory;          /* WorkingDirectory */
index 1ed219546f48883fda36a939b8cf40c4b5368641..ebf9bac1b4b65c4f390d4c993e8d2170e26ac731 100644 (file)
@@ -45,7 +45,6 @@ extern int do_backup(JCR *jcr);
 extern int do_restore(JCR *jcr);
 extern int do_verify(JCR *jcr);
 extern void backup_cleanup(void);
-extern void start_UA_server(int port);
 
 /* Queue of jobs to be run */
 static workq_t job_wq;               /* our job work queue */
index 8cd28d37b397256bc804d4c72561a9cdd0bf5d89..5ad9ae53694069a6ec90a64e73aa32d43cadd7a1 100644 (file)
@@ -48,7 +48,7 @@ int get_cmd(UAContext *ua, char *prompt)
    bnet_fsend(sock, "%s", prompt);
    bnet_sig(sock, BNET_PROMPT);       /* request more input */
    for ( ;; ) {
-      if (bnet_recv(sock) < 0) {
+      if (bnet_recv(sock) <= 0) {
         return 0;
       }
       ua->cmd = check_pool_memory_size(ua->cmd, sock->msglen+1);
index a2af20fc7a2d46e4dcb11a50a12eab92b150edd6..4a1e9ff639eb03e709bfd0461b0228af94a24ac7 100644 (file)
@@ -58,16 +58,24 @@ static void handle_UA_client_request(void *arg);
 static int started = FALSE;
 static workq_t ua_workq;
 
+struct s_addr_port {
+   char *addr;
+   int port;
+};
+
 /* Called here by Director daemon to start UA (user agent)
  * command thread. This routine creates the thread and then
  * returns.
  */
-void start_UA_server(int UA_port)
+void start_UA_server(char *UA_addr, int UA_port)
 {
    pthread_t thid;
    int status;
+   static struct s_addr_port arg;
 
-   if ((status=pthread_create(&thid, NULL, connect_thread, (void *)UA_port)) != 0) {
+   arg.port = UA_port;
+   arg.addr = UA_addr;
+   if ((status=pthread_create(&thid, NULL, connect_thread, (void *)&arg)) != 0) {
       Emsg1(M_ABORT, 0, _("Cannot create UA thread: %s\n"), strerror(status));
    }
    started = TRUE;
@@ -76,12 +84,12 @@ void start_UA_server(int UA_port)
 
 static void *connect_thread(void *arg)
 {
-   int UA_port = (int)arg;
+   struct s_addr_port *UA = (struct s_addr_port *)arg;
 
    pthread_detach(pthread_self());
 
    /*  ****FIXME**** put # 5 on config parameter */
-   bnet_thread_server(UA_port, 5, &ua_workq, handle_UA_client_request);
+   bnet_thread_server(UA->addr, UA->port, 5, &ua_workq, handle_UA_client_request);
    return NULL;
 }
 
index 9496f002557988303e361b8e8dbbb4913f905229..851e3b2b191ed97cd7de2d4cd75cc9d3497ad23f 100644 (file)
@@ -199,7 +199,8 @@ Without that I don't know who I am :-(\n"), configfile);
 
    /* Become server, and handle requests */
    Dmsg1(10, "filed: listening on port %d\n", me->FDport);
-   bnet_thread_server(me->FDport, me->MaxConcurrentJobs, &dir_workq, handle_client_request);
+   bnet_thread_server(me->FDaddr, me->FDport, me->MaxConcurrentJobs, 
+                     &dir_workq, handle_client_request);
 
    exit(0);                          /* should never get here */
 }
index 3bb886ff950411ea913543ee0479d3446fb3b3f8..484116c1bfeb99344b06f61af9aa00a0a0db7f06 100644 (file)
@@ -74,6 +74,7 @@ static struct res_items cli_items[] = {
    {"name",     store_name,     ITEM(res_client.hdr.name), 0, ITEM_REQUIRED, 0},
    {"description", store_str,   ITEM(res_client.hdr.desc), 0, 0, 0},
    {"fdport",   store_pint,     ITEM(res_client.FDport),  0, ITEM_DEFAULT, 9102},
+   {"fdaddress",   store_str,   ITEM(res_client.FDaddr),  0, 0, 0},
    {"workingdirectory",  store_dir, ITEM(res_client.working_directory), 0, ITEM_REQUIRED, 0}, 
    {"piddirectory",  store_dir, ITEM(res_client.pid_directory), 0, ITEM_REQUIRED, 0}, 
    {"subsysdirectory",  store_dir,  ITEM(res_client.subsys_directory), 0, ITEM_REQUIRED, 0}, 
@@ -174,18 +175,26 @@ void free_resource(int type)
 
    switch (type) {
       case R_DIRECTOR:
-        if (res->res_dir.password)
+        if (res->res_dir.password) {
            free(res->res_dir.password);
-        if (res->res_dir.address)
+        }
+        if (res->res_dir.address) {
            free(res->res_dir.address);
+        }
         break;
       case R_CLIENT:
-        if (res->res_client.working_directory)
+        if (res->res_client.working_directory) {
            free(res->res_client.working_directory);
-        if (res->res_client.pid_directory)
+        }
+        if (res->res_client.pid_directory) {
            free(res->res_client.pid_directory);
-        if (res->res_client.subsys_directory)
+        }
+        if (res->res_client.subsys_directory) {
            free(res->res_client.subsys_directory);
+        }
+        if (res->res_client.FDaddr) {
+           free(res->res_client.FDaddr);
+        }
         break;
       case R_MSGS:
         if (res->res_msgs.mail_cmd)
index 40c28ba361a9c9eb2b1615c076f310bb07e69a08..956070999b2f7cdf734b3a453088c43dcef10ec0 100644 (file)
 /*
  * Resource codes -- they must be sequential for indexing   
  */
-#define R_FIRST                       1001
+#define R_FIRST                      1001
 
-#define R_DIRECTOR                    1001
-#define R_CLIENT                      1002
-#define R_MSGS                        1003
+#define R_DIRECTOR                   1001
+#define R_CLIENT                     1002
+#define R_MSGS                       1003
 
-#define R_LAST                        R_MSGS
+#define R_LAST                       R_MSGS
 
 /*
  * Some resource attributes
  */
-#define R_NAME                        1020
-#define R_ADDRESS                     1021
-#define R_PASSWORD                    1022
-#define R_TYPE                        1023
+#define R_NAME                       1020
+#define R_ADDRESS                    1021
+#define R_PASSWORD                   1022
+#define R_TYPE                       1023
 
 
 /* Definition of the contents of each Resource */
 struct s_res_dir {
-   RES   hdr;
-   char *password;                    /* Director password */
-   char *address;                     /* Director address or zero */
+   RES  hdr;
+   char *password;                   /* Director password */
+   char *address;                    /* Director address or zero */
 };
 typedef struct s_res_dir DIRRES;
 
 struct s_res_client {
-   RES   hdr;
-   int   FDport;                      /* where we listen for Directors */ 
+   RES  hdr;
+   int  FDport;                      /* where we listen for Directors */ 
+   char *FDaddr;                     /* bind address */
    char *working_directory;
    char *pid_directory;
    char *subsys_directory;
@@ -70,9 +71,9 @@ typedef struct s_res_client CLIENT;
  * resource structure definitions.
  */
 union u_res {
-   struct s_res_dir     res_dir;
-   struct s_res_client  res_client;
-   struct s_res_msgs    res_msgs;
+   struct s_res_dir    res_dir;
+   struct s_res_client res_client;
+   struct s_res_msgs   res_msgs;
    RES hdr;
 };
 
index 1a66eca54bcedf4d677ebea8a04115b6822f6686..6b84dac1a4a0c161091dba699a92a59f6e6044d9 100644 (file)
@@ -36,8 +36,9 @@ all: Makefile libfind.a ../lib/libbac.a
        @echo " "
 
 libfind.a: $(LIBOBJS) 
-       $(RMF) libfind.a
-       $(AR) crs $@ $(LIBOBJS)
+       $(RMF) $@
+       $(AR) cr $@ $(LIBOBJS)
+       $(RANLIB) $@
 
 Makefile: $(srcdir)/Makefile.in $(topdir)/config.status
        cd $(topdir) \
index 26e24a99d0e1408399a96c17ba3a3f142dd9c462..dc4d775ba1a5d9c685c381b98c359b1684f6808f 100644 (file)
@@ -108,6 +108,7 @@ struct s_jcr {
    char *RestoreBootstrap;            /* Bootstrap file to restore */
    char *sd_auth_key;                 /* SD auth key */
    MSGS *jcr_msgs;                    /* Copy of message resource -- actually used */
+   uint32_t ClientId;                 /* Client associated with Job */
 
    /* Daemon specific part of JCR */
    /* This should be empty in the library */
@@ -128,8 +129,7 @@ struct s_jcr {
    int SDJobStatus;                   /* Storage Job Status */
    int mode;                          /* manual/auto run */
    B_DB *db;                          /* database pointer */
-   int MediaId;                       /* DB record IDs associated with this job */
-   int ClientId;                      /* Client associated with file */
+   uint32_t MediaId;                  /* DB record IDs associated with this job */
    uint32_t PoolId;                   /* Pool record id */
    FileId_t FileId;                   /* Last file id inserted */
    uint32_t FileIndex;                /* Last FileIndex processed */
@@ -137,7 +137,7 @@ struct s_jcr {
    int fn_printed;                    /* printed filename */
    POOLMEM *stime;                    /* start time for incremental/differential */
    JOB_DBR jr;                        /* Job record in Database */
-   int RestoreJobId;                  /* Id specified by UA */
+   uint32_t RestoreJobId;             /* Id specified by UA */
    char *RestoreWhere;                /* Where to restore the files */
 #endif /* DIRECTOR_DAEMON */
 
@@ -191,6 +191,7 @@ struct s_jcr {
    DEV_RECORD rec;                    /* Read/Write record */
    long Ticket;                       /* ticket for this job */
    uint32_t VolFirstFile;             /* First file index this Volume */
+   uint32_t FileIndex;                /* Current File Index */
    uint32_t start_block;              /* Start write block */
    uint32_t start_file;               /* Start write file */
    uint32_t end_block;                /* Ending block written */
@@ -238,6 +239,7 @@ extern JCR *new_jcr(int size, JCR_free_HANDLER *daemon_free_jcr);
 extern void free_jcr(JCR *jcr);
 extern void free_locked_jcr(JCR *jcr);
 extern JCR *get_jcr_by_id(uint32_t JobId);
+extern JCR *get_jcr_by_session(uint32_t SessionId, uint32_t SessionTime);
 extern JCR *get_jcr_by_partial_name(char *Job);
 extern JCR *get_jcr_by_full_name(char *Job);
 extern JCR *get_next_jcr(JCR *jcr);
index df0ba1335b5d968bba78d4165db55637e70b5c18..7c288c4e9db7a7fe7af70ed62af853e5312e3669 100644 (file)
@@ -88,7 +88,8 @@ all: Makefile libbac.a
        @echo " "
 
 libbac.a: $(LIBOBJS)
-       $(AR) rcs $@ $(LIBOBJS)
+       $(AR) rc  $@ $(LIBOBJS)
+       $(RANLIB) $@
 
 
 Makefile: $(srcdir)/Makefile.in $(topdir)/config.status
index 0b9f6ebee29e8334edcf3551e89c22e9c6275e0e..1841e0f69d542574fa98e7c919f51cd4fd49355f 100644 (file)
@@ -39,13 +39,14 @@ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
 
 /* Become Threaded Network Server */
 void
-bnet_thread_server(int port, int max_clients, workq_t *client_wq, 
+bnet_thread_server(char *bind_addr, int port, int max_clients, workq_t *client_wq, 
                   void handle_client_request(void *bsock))
 {
    int newsockfd, sockfd, stat;
    socklen_t clilen;
    struct sockaddr_in cli_addr;       /* client's address */
    struct sockaddr_in serv_addr;      /* our address */
+   struct in_addr bind_ip;           /* address to bind to */
    int tlog;
    fd_set ready, sockset;
    int turnon = 1;
@@ -75,9 +76,17 @@ bnet_thread_server(int port, int max_clients, workq_t *client_wq,
    /* 
     * Bind our local address so that the client can send to us.
     */
-   bzero((char *) &serv_addr, sizeof(serv_addr));
+   bind_ip.s_addr = htonl(INADDR_ANY);
+   if (bind_addr && bind_addr[0]) {
+      if (inet_pton(AF_INET, bind_addr, &bind_ip) <= 0) {
+         Emsg1(M_WARNING, 0, _("Invalid bind address: %s, using INADDR_ANY\n"),
+           bind_addr);
+        bind_ip.s_addr = htonl(INADDR_ANY);
+      }
+   }
+   memset((char *) &serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
-   serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+   serv_addr.sin_addr.s_addr = bind_ip.s_addr;
    serv_addr.sin_port = htons(port);
 
    int tmax = 30 * (60 / 5);         /* wait 30 minutes max */
index 6657dffeda7b4a97be744d188c23d6fbe965c4af..92b529fbda259f223e01c5f817d2de7a6ef3662a 100755 (executable)
@@ -213,6 +213,27 @@ JCR *get_jcr_by_id(uint32_t JobId)
    return jcr; 
 }
 
+/*
+ * Given a SessionId and SessionTime, find the JCR     
+ *   Returns: jcr on success
+ *           NULL on failure
+ */
+JCR *get_jcr_by_session(uint32_t SessionId, uint32_t SessionTime)
+{
+   JCR *jcr;      
+
+   P(mutex);
+   for (jcr = jobs; jcr; jcr=jcr->next) {
+      if (jcr->VolSessionId == SessionId && 
+         jcr->VolSessionTime == SessionTime) {
+        jcr->use_count++;
+         Dmsg1(200, "Increment jcr use_count=%d\n", jcr->use_count);
+        break;
+      }
+   }
+   V(mutex);
+   return jcr; 
+}
 
 
 /*
index 5ee1231389eecf17b50d036dedc152f0e0ebfbd7..390b207829aeccb352db48ccf39f47128c5c37f7 100644 (file)
  */
 
 /* base64.c */
-void     base64_init            (void);
-int      to_base64              (intmax_t value, char *where);
-int      from_base64            (intmax_t *value, char *where);
-void     encode_stat            (char *buf, struct stat *statp);
-void     decode_stat            (char *buf, struct stat *statp);
-int      bin_to_base64          (char *buf, char *bin, int len);
+void      base64_init            (void);
+int       to_base64              (intmax_t value, char *where);
+int       from_base64            (intmax_t *value, char *where);
+void      encode_stat            (char *buf, struct stat *statp);
+void      decode_stat            (char *buf, struct stat *statp);
+int       bin_to_base64          (char *buf, char *bin, int len);
 
 /* bmisc.c */
-char    *bstrncpy               (char *dest, char *src, int maxlen);
-void    *b_malloc               (char *file, int line, size_t size);
+char     *bstrncpy               (char *dest, char *src, int maxlen);
+void     *b_malloc               (char *file, int line, size_t size);
 #ifndef DEBUG
-void    *bmalloc                (size_t size);
+void     *bmalloc                (size_t size);
 #endif
-void    *brealloc               (void *buf, size_t size);
-void    *bcalloc                (size_t size1, size_t size2);
-int      bsnprintf              (char *str, size_t size, const  char  *format, ...);
-int      bvsnprintf             (char *str, size_t size, const char  *format, va_list ap);
-int      pool_sprintf           (char *pool_buf, char *fmt, ...);
-void     create_pid_file        (char *dir, char *progname, int port);
-int      delete_pid_file        (char *dir, char *progname, int port);
+void     *brealloc               (void *buf, size_t size);
+void     *bcalloc                (size_t size1, size_t size2);
+int       bsnprintf              (char *str, size_t size, const  char  *format, ...);
+int       bvsnprintf             (char *str, size_t size, const char  *format, va_list ap);
+int       pool_sprintf           (char *pool_buf, char *fmt, ...);
+void      create_pid_file        (char *dir, char *progname, int port);
+int       delete_pid_file        (char *dir, char *progname, int port);
 #ifndef HAVE_STRERROR_R
-int      strerror_r             (int errnum, char *buf, size_t bufsiz);
+int       strerror_r             (int errnum, char *buf, size_t bufsiz);
 #endif
 
 
 /* bnet.c */
-int32_t    bnet_recv            (BSOCK *bsock);
-int       bnet_send             (BSOCK *bsock);
-int       bnet_fsend              (BSOCK *bs, char *fmt, ...);
-int       bnet_set_buffer_size    (BSOCK *bs, uint32_t size, int rw);
-int       bnet_sig                (BSOCK *bs, int sig);
-BSOCK *    bnet_connect           (void *jcr, int retry_interval,
-              int max_retry_time, char *name, char *host, char *service, 
-              int port, int verbose);
-int       bnet_wait_data         (BSOCK *bsock, int sec);
-void      bnet_close            (BSOCK *bsock);
-BSOCK *    init_bsock           (void *jcr, int sockfd, char *who, char *ip, int port);
-BSOCK *    dup_bsock            (BSOCK *bsock);
-void      term_bsock            (BSOCK *bsock);
-char *    bnet_strerror         (BSOCK *bsock);
-char *    bnet_sig_to_ascii     (BSOCK *bsock);
-int       bnet_wait_data        (BSOCK *bsock, int sec);
-int       bnet_despool          (BSOCK *bsock);
+int32_t    bnet_recv             (BSOCK *bsock);
+int        bnet_send             (BSOCK *bsock);
+int        bnet_fsend              (BSOCK *bs, char *fmt, ...);
+int        bnet_set_buffer_size    (BSOCK *bs, uint32_t size, int rw);
+int        bnet_sig                (BSOCK *bs, int sig);
+BSOCK *    bnet_connect            (void *jcr, int retry_interval,
+               int max_retry_time, char *name, char *host, char *service, 
+               int port, int verbose);
+int        bnet_wait_data         (BSOCK *bsock, int sec);
+void       bnet_close            (BSOCK *bsock);
+BSOCK *    init_bsock            (void *jcr, int sockfd, char *who, char *ip, int port);
+BSOCK *    dup_bsock             (BSOCK *bsock);
+void       term_bsock            (BSOCK *bsock);
+char *     bnet_strerror         (BSOCK *bsock);
+char *     bnet_sig_to_ascii     (BSOCK *bsock);
+int        bnet_wait_data        (BSOCK *bsock, int sec);
+int        bnet_despool          (BSOCK *bsock);
 
 
 /* cram-md5.c */
 int cram_md5_get_auth(BSOCK *bs, char *password);
 int cram_md5_auth(BSOCK *bs, char *password);
 void hmac_md5(uint8_t* text, int text_len, uint8_t*  key,
-             int key_len, uint8_t *hmac);
+              int key_len, uint8_t *hmac);
 
 /* create_file.c */
 int create_file(void *jcr, char *fname, char *ofile, char *lname,
-                      int type, struct stat *statp, int *ofd);
+                       int type, struct stat *statp, int *ofd);
 int set_statp(void *jcr, char *fname, char *ofile, char *lname, int type, 
-                      struct stat *statp);
+                       struct stat *statp);
 
 
 /* crc32.c */
 uint32_t bcrc32(uint8_t *buf, int len);
 
 /* daemon.c */
-void    daemon_start            ();
+void     daemon_start            ();
 
 /* lex.c */
-LEX *    lex_close_file         (LEX *lf);
-LEX *    lex_open_file          (LEX *lf, char *fname, LEX_ERROR_HANDLER *scan_error);
-int      lex_get_char           (LEX *lf);
-void     lex_unget_char         (LEX *lf);
-char *   lex_tok_to_str         (int token);
-int      lex_get_token          (LEX *lf, int expect);
+LEX *     lex_close_file         (LEX *lf);
+LEX *     lex_open_file          (LEX *lf, char *fname, LEX_ERROR_HANDLER *scan_error);
+int       lex_get_char           (LEX *lf);
+void      lex_unget_char         (LEX *lf);
+char *    lex_tok_to_str         (int token);
+int       lex_get_token          (LEX *lf, int expect);
 
 /* makepath.c */
 int make_path(
-          void *jcr,
-          const char *argpath,
-          int mode,
-          int parent_mode,
-          uid_t owner,
-          gid_t group,
-          int preserve_existing,
-          char *verbose_fmt_string);
+           void *jcr,
+           const char *argpath,
+           int mode,
+           int parent_mode,
+           uid_t owner,
+           gid_t group,
+           int preserve_existing,
+           char *verbose_fmt_string);
 
 
 /* message.c */
-void      my_name_is            (int argc, char *argv[], char *name);
-void      init_msg              (void *jcr, MSGS *msg);
-void      term_msg              (void);
-void      close_msg             (void *jcr);
-void      add_msg_dest          (MSGS *msg, int dest, int type, char *where, char *dest_code);
-void      rem_msg_dest          (MSGS *msg, int dest, int type, char *where);
-void      Jmsg                  (void *jcr, int type, int level, char *fmt, ...);
-void      dispatch_message      (void *jcr, int type, int level, char *buf);
-void      init_console_msg      (char *wd);
-void      free_msgs_res         (MSGS *msgs);
-int       open_spool_file       (void *jcr, BSOCK *bs);
-int       close_spool_file      (void *vjcr, BSOCK *bs);
+void       my_name_is            (int argc, char *argv[], char *name);
+void       init_msg              (void *jcr, MSGS *msg);
+void       term_msg              (void);
+void       close_msg             (void *jcr);
+void       add_msg_dest          (MSGS *msg, int dest, int type, char *where, char *dest_code);
+void       rem_msg_dest          (MSGS *msg, int dest, int type, char *where);
+void       Jmsg                  (void *jcr, int type, int level, char *fmt, ...);
+void       dispatch_message      (void *jcr, int type, int level, char *buf);
+void       init_console_msg      (char *wd);
+void       free_msgs_res         (MSGS *msgs);
+int        open_spool_file       (void *jcr, BSOCK *bs);
+int        close_spool_file      (void *vjcr, BSOCK *bs);
 
 
 /* bnet_server.c */
-void      bnet_thread_server(int port, int max_clients, workq_t *client_wq, 
-                  void handle_client_request(void *bsock));
-void            bnet_server             (int port, void handle_client_request(BSOCK *bsock));
-int             net_connect             (int port);
-BSOCK *         bnet_bind               (int port);
-BSOCK *         bnet_accept             (BSOCK *bsock, char *who);
+void       bnet_thread_server(char *bind_addr, int port, int max_clients, workq_t *client_wq, 
+                   void handle_client_request(void *bsock));
+void             bnet_server             (int port, void handle_client_request(BSOCK *bsock));
+int              net_connect             (int port);
+BSOCK *          bnet_bind               (int port);
+BSOCK *          bnet_accept             (BSOCK *bsock, char *who);
 
 /* signal.c */
-void            init_signals             (void terminate(int sig));
-void            init_stack_dump          (void);
+void             init_signals             (void terminate(int sig));
+void             init_stack_dump          (void);
 
 /* util.c */
-void            lcase                   (char *str);
-void            bash_spaces             (char *str);
-void            unbash_spaces           (char *str);
-void            strip_trailing_junk     (char *str);
-void            strip_trailing_slashes  (char *dir);
-int             skip_spaces             (char **msg);
-int             skip_nonspaces          (char **msg);
-int             fstrsch                 (char *a, char *b);
-char *          encode_time             (time_t time, char *buf);
-char *          encode_mode             (mode_t mode, char *buf);
-char *          edit_uint64_with_commas   (uint64_t val, char *buf);
-char *          add_commas              (char *val, char *buf);
-char *          edit_uint64             (uint64_t val, char *buf);
-int             do_shell_expansion      (char *name);
-int             is_a_number             (const char *num);
-int             string_to_btime         (char *str, btime_t *value);
-char            *edit_btime             (btime_t val, char *buf);
-void            jobstatus_to_ascii      (int JobStatus, char *msg, int maxlen);
-void            pm_strcat               (POOLMEM **pm, char *str);
-void            pm_strcpy               (POOLMEM **pm, char *str);
-int             run_program             (char *prog, int wait, POOLMEM *results);
-char *          job_type_to_str         (int type);
-char *          job_status_to_str       (int stat);
-char *          job_level_to_str        (int level);
-void            makeSessionKey          (char *key, char *seed, int mode);
+void             lcase                   (char *str);
+void             bash_spaces             (char *str);
+void             unbash_spaces           (char *str);
+void             strip_trailing_junk     (char *str);
+void             strip_trailing_slashes  (char *dir);
+int              skip_spaces             (char **msg);
+int              skip_nonspaces          (char **msg);
+int              fstrsch                 (char *a, char *b);
+char *           encode_time             (time_t time, char *buf);
+char *           encode_mode             (mode_t mode, char *buf);
+char *           edit_uint64_with_commas   (uint64_t val, char *buf);
+char *           add_commas              (char *val, char *buf);
+char *           edit_uint64             (uint64_t val, char *buf);
+int              do_shell_expansion      (char *name);
+int              is_a_number             (const char *num);
+int              string_to_btime         (char *str, btime_t *value);
+char             *edit_btime             (btime_t val, char *buf);
+void             jobstatus_to_ascii      (int JobStatus, char *msg, int maxlen);
+void             pm_strcat               (POOLMEM **pm, char *str);
+void             pm_strcpy               (POOLMEM **pm, char *str);
+int              run_program             (char *prog, int wait, POOLMEM *results);
+char *           job_type_to_str         (int type);
+char *           job_status_to_str       (int stat);
+char *           job_level_to_str        (int level);
+void             makeSessionKey          (char *key, char *seed, int mode);
 
 
 
index c8f65699abda086051e7255fa95f8f7323567ea6..92ba70d363936279b1ff8a4d171a6b7c7db43682 100644 (file)
@@ -432,6 +432,7 @@ char *job_type_to_str(int type)
       break;
    case JT_ADMIN:
       str = _("Admin");
+      break;
    default:
       str = _("Unknown Type");
       break;
index f3952d50d117838aeec450ecf58dd5fa15f3119b..0e936dd705fffbb5b22faa39ee707f1d461e255f 100644 (file)
@@ -12,7 +12,6 @@
 
 Storage {                             # definition of myself
   Name = @hostname@-sd
-  Address = @hostname@
   SDPort = @sd_port@                  # Director's port      
   WorkingDirectory = "@working_dir@"
   Pid Directory = "@piddir@"
index 2a7aaf381451b4fc2e85c7f5546ee2851a829ebb..de17a011c080e409ef94f4a058e1c863c3fba993 100644 (file)
 /* Forward referenced functions */
 static void do_scan(char *fname);
 static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec);
-static void create_file_attributes_record(B_DB *db, char *fname, char *lname, int type,
+static int  create_file_attributes_record(B_DB *db, char *fname, char *lname, int type,
                               char *ap, DEV_RECORD *rec);
-static void create_media_record(B_DB *db, MEDIA_DBR *mr, VOLUME_LABEL *vl);
-static void create_pool_record(B_DB *db, POOL_DBR *pr);
-static void create_job_record(B_DB *db, JOB_DBR *mr, SESSION_LABEL *label);
-static void update_job_record(B_DB *db, JOB_DBR *mr, SESSION_LABEL *elabel, 
+static int  create_media_record(B_DB *db, MEDIA_DBR *mr, VOLUME_LABEL *vl);
+static int  create_pool_record(B_DB *db, POOL_DBR *pr);
+static int  create_job_record(B_DB *db, JOB_DBR *mr, SESSION_LABEL *label, DEV_RECORD *rec);
+static int  update_job_record(B_DB *db, JOB_DBR *mr, SESSION_LABEL *elabel, 
                              DEV_RECORD *rec);
-static void create_client_record(B_DB *db, CLIENT_DBR *cr);
-static void create_fileset_record(B_DB *db, FILESET_DBR *fsr);
-static void create_jobmedia_record(B_DB *db, JOBMEDIA_DBR *jmr, SESSION_LABEL *elabel);
+static int  create_client_record(B_DB *db, CLIENT_DBR *cr);
+static int  create_fileset_record(B_DB *db, FILESET_DBR *fsr);
+static int  create_jobmedia_record(B_DB *db, JCR *jcr);
+static void create_jcr(JOB_DBR *jr, DEV_RECORD *rec, uint32_t JobId);
 
 
 /* Global variables */
 static DEVICE *dev = NULL;
 static B_DB *db;
-static JCR *jcr;
+static JCR *jcr;                     /* jcr for bscan */
+static JCR *jobjcr;                  /* jcr for simulating running job */
 static BSR *bsr;
 static struct stat statp;
 static int type;
@@ -64,13 +66,10 @@ static MEDIA_DBR mr;
 static POOL_DBR pr;
 static JOB_DBR jr;
 static CLIENT_DBR cr;
-static JOBMEDIA_DBR jmr;
 static FILESET_DBR fsr;
 static ATTR_DBR ar;
 static SESSION_LABEL label;
 static SESSION_LABEL elabel;
-static uint32_t FirstIndex = 0;
-static uint32_t LastIndex = 0;
 
 static char *db_name = "bacula";
 static char *db_user = "bacula";
@@ -81,7 +80,7 @@ static int update_db = 0;
 
 static void usage()
 {
-   fprintf(stderr,
+   fprintf(stderr, _(
 "\nVersion: " VERSION " (" DATE ")\n\n"
 "Usage: bscan [-d debug_level] <bacula-archive>\n"
 "       -b bootstrap      specify a bootstrap file\n"
@@ -92,7 +91,7 @@ static void usage()
 "       -s                synchronize or store in database\n"
 "       -v                verbose\n"
 "       -w dir            specify working directory (default /tmp)\n"
-"       -?                print this message\n\n");
+"       -?                print this message\n\n"));
    exit(1);
 }
 
@@ -104,7 +103,7 @@ int main (int argc, char *argv[])
    init_msg(NULL, NULL);
 
 
-   while ((ch = getopt(argc, argv, "b:d:n:p:u:vw:?")) != -1) {
+   while ((ch = getopt(argc, argv, "b:d:n:p:su:vw:?")) != -1) {
       switch (ch) {
          case 'b':
            bsr = parse_bsr(NULL, optarg);
@@ -149,7 +148,7 @@ int main (int argc, char *argv[])
    argv += optind;
 
    if (argc != 1) {
-      Pmsg0(0, "Wrong number of arguments: \n");
+      Pmsg0(0, _("Wrong number of arguments: \n"));
       usage();
    }
 
@@ -158,13 +157,15 @@ int main (int argc, char *argv[])
    jcr = setup_jcr("bscan", argv[0], bsr);
 
    if ((db=db_init_database(NULL, db_name, db_user, db_password)) == NULL) {
-      Emsg0(M_ABORT, 0, "Could not init Bacula database\n");
+      Emsg0(M_ERROR_TERM, 0, _("Could not init Bacula database\n"));
    }
    if (!db_open_database(db)) {
-      Emsg0(M_ABORT, 0, db_strerror(db));
+      Emsg0(M_ERROR_TERM, 0, db_strerror(db));
    }
    Dmsg0(200, "Database opened\n");
-
+   if (verbose) {
+      Pmsg2(000, _("Using Database: %s, User: %s\n"), db_name, db_user);
+   }
 
    do_scan(argv[0]);
 
@@ -186,13 +187,13 @@ static void do_scan(char *devname)
    lname = get_pool_memory(PM_FNAME);
 
    memset(&ar, 0, sizeof(ar));
-   memset(&mr, 0, sizeof(mr));
    memset(&pr, 0, sizeof(pr));
    memset(&jr, 0, sizeof(jr));
    memset(&cr, 0, sizeof(cr));
-   memset(&jmr, 0, sizeof(jmr));
    memset(&fsr, 0, sizeof(fsr));
 
+   detach_jcr_from_device(dev, jcr);
+
    read_records(jcr, dev, record_cb, mount_next_read_volume);
    release_device(jcr, dev);
 
@@ -223,13 +224,14 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
            /* Check Pool info */
            strcpy(pr.Name, dev->VolHdr.PoolName);
            strcpy(pr.PoolType, dev->VolHdr.PoolType);
-           if (!db_get_pool_record(db, &pr)) {
+           if (db_get_pool_record(db, &pr)) {
+              if (verbose) {
+                  Pmsg1(000, "Pool record for %s found in DB.\n", pr.Name);
+              }
+           } else {
                Pmsg1(000, "VOL_LABEL: Pool record not found for Pool: %s\n",
                  pr.Name);
               create_pool_record(db, &pr);
-              return;
-           } else if (verbose) {
-               Pmsg1(000, "Pool record for %s found in DB.\n", pr.Name);
            }
            if (strcmp(pr.PoolType, dev->VolHdr.PoolType) != 0) {
                Pmsg2(000, "VOL_LABEL: PoolType mismatch. DB=%s Vol=%s\n",
@@ -240,16 +242,18 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
            }
 
            /* Check Media Info */
+           memset(&mr, 0, sizeof(mr));
            strcpy(mr.VolumeName, dev->VolHdr.VolName);
            mr.PoolId = pr.PoolId;
-           if (!db_get_media_record(db, &mr)) {
+           if (db_get_media_record(db, &mr)) {
+              if (verbose) {
+                  Pmsg1(000, "Media record for %s found in DB.\n", mr.VolumeName);
+              }
+           } else {
                Pmsg1(000, "VOL_LABEL: Media record not found for Volume: %s\n",
                  mr.VolumeName);
               strcpy(mr.MediaType, dev->VolHdr.MediaType);
               create_media_record(db, &mr, &dev->VolHdr);
-              return;
-           } else if (verbose) {
-               Pmsg1(000, "Media record for %s found in DB.\n", mr.VolumeName);
            }
            if (strcmp(mr.MediaType, dev->VolHdr.MediaType) != 0) {
                Pmsg2(000, "VOL_LABEL: MediaType mismatch. DB=%s Vol=%s\n",
@@ -258,21 +262,42 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
            } else if (verbose) {
                Pmsg1(000, "Media type \"%s\" is OK.\n", mr.MediaType);
            }
+           /* Reset some JCR variables */
+           for (JCR *mjcr=NULL; (mjcr=next_attached_jcr(dev, mjcr)); ) {
+              mjcr->VolFirstFile = mjcr->FileIndex = 0;
+              mjcr->start_block = mjcr->end_block = 0;
+              mjcr->start_file = mjcr->end_file = 0;
+           }
+
             Pmsg1(000, "VOL_LABEL: OK for Volume: %s\n", mr.VolumeName);
            break;
         case SOS_LABEL:
            unser_session_label(&label, rec);
-           FirstIndex = LastIndex = 0;
            memset(&jr, 0, sizeof(jr));
            jr.JobId = label.JobId;
-           if (!db_get_job_record(db, &jr)) {
+           if (db_get_job_record(db, &jr)) {
+              /* Job record already exists in DB */
+              create_jcr(&jr, rec, jr.JobId);
+              attach_jcr_to_device(dev, jobjcr);
+              if (verbose) {
+                  Pmsg1(000, _("SOS_LABEL: Found Job record for JobId: %d\n"), jr.JobId);
+              }
+           } else {
+            
+              /* Must create a Job record in DB */
                Pmsg1(000, "SOS_LABEL: Job record not found for JobId: %d\n",
                  jr.JobId);
-              create_job_record(db, &jr, &label);
+
+              /* Create Client record */
+              strcpy(cr.Name, label.ClientName);
+              create_client_record(db, &cr);
+              jr.ClientId = cr.ClientId;
+
+              create_job_record(db, &jr, &label, rec);
               jr.PoolId = pr.PoolId;
-              jr.VolSessionId = rec->VolSessionId;
-              jr.VolSessionTime = rec->VolSessionTime;
-              return;
+              /* Set start positions into JCR */
+              jobjcr->start_block = dev->block_num;
+              jobjcr->start_file = dev->file;
            }
            if (rec->VolSessionId != jr.VolSessionId) {
                Pmsg3(000, "SOS_LABEL: VolSessId mismatch for JobId=%u. DB=%d Vol=%d\n",
@@ -296,40 +321,28 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
         case EOS_LABEL:
            unser_session_label(&elabel, rec);
 
-           /* Create Client record */
-           strcpy(cr.Name, label.ClientName);
-           create_client_record(db, &cr);
-           jr.ClientId = cr.ClientId;
-
            /* Create FileSet record */
            strcpy(fsr.FileSet, label.FileSetName);
            create_fileset_record(db, &fsr);
            jr.FileSetId = fsr.FileSetId;
 
-           /* Update Job record */
+           /* Do the final update to the Job record */
            update_job_record(db, &jr, &elabel, rec);
 
            /* Create JobMedia record */
-           jmr.JobId = jr.JobId;
-           jmr.MediaId = mr.MediaId;
-           create_jobmedia_record(db, &jmr, &elabel);
-           if (elabel.JobId != label.JobId) {
-               Pmsg2(000, "EOS_LABEL: Start/End JobId mismatch. Start=%d End=%d\n",
-                 label.JobId, elabel.JobId);
-              return;
+           jobjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
+           if (!jobjcr) {
+               Pmsg2(000, _("Could not find SessId=%d SessTime=%d for EOS record.\n"),
+                  rec->VolSessionId, rec->VolSessionTime);
+              break;
            }
-           if (elabel.JobFiles != jr.JobFiles) {
-               Pmsg3(000, "EOS_LABEL: JobFiles mismatch for JobId=%u. DB=%d EOS=%d\n",
-                 elabel.JobId,
-                 jr.JobFiles, elabel.JobFiles);
-              return;
-           }                                 
-           if (elabel.JobBytes != jr.JobBytes) {
-               Pmsg3(000, "EOS_LABEL: JobBytes mismatch for JobId=%u. DB=%d EOS=%d\n",
-                 elabel.JobId,
-                 jr.JobBytes, elabel.JobBytes);
-              return;
-           }                                 
+
+           jobjcr->end_block = dev->block_num;
+           jobjcr->end_file = dev->file;
+           create_jobmedia_record(db, jobjcr);
+           detach_jcr_from_device(dev, jobjcr);
+           free_jcr(jobjcr);
+
             Pmsg1(000, "EOS_LABEL: OK for JobId=%d\n", elabel.JobId);
            break;
         case EOM_LABEL:
@@ -392,46 +405,97 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
         print_ls_output(fname, lname, type, &statp);   
       }
       create_file_attributes_record(db, fname, lname, type, ap, rec);
-      if (FirstIndex == 0) {
-        FirstIndex = rec->FileIndex;
-      }
-      LastIndex = rec->FileIndex;
 
    /* Data stream and extracting */
    } else if (rec->Stream == STREAM_FILE_DATA) {
 
-   } else if (rec->Stream != STREAM_MD5_SIGNATURE) {
-      Pmsg2(0, "None of above!!! stream=%d data=%s\n", rec->Stream, rec->data);
+   } else if (rec->Stream == STREAM_GZIP_DATA) {
+
+   } else if (rec->Stream == STREAM_MD5_SIGNATURE) {
+      if (verbose > 1) {
+         Pmsg0(000, _("Got MD5 record.\n"));
+      }
+      /* ****FIXME**** implement db_update_md5_record */
+   } else {
+      Pmsg2(0, _("Unknown stream type!!! stream=%d data=%s\n"), rec->Stream, rec->data);
    }
-   
    return;
 }
 
-static void create_file_attributes_record(B_DB *db, char *fname, char *lname, int type,
+/*
+ * Free the Job Control Record if no one is still using it.
+ *  Called from main free_jcr() routine in src/lib/jcr.c so
+ *  that we can do our Director specific cleanup of the jcr.
+ */
+static void dird_free_jcr(JCR *jcr)
+{
+   Dmsg0(200, "Start dird free_jcr\n");
+
+   if (jcr->file_bsock) {
+      Dmsg0(200, "Close File bsock\n");
+      bnet_close(jcr->file_bsock);
+   }
+   if (jcr->store_bsock) {
+      Dmsg0(200, "Close Store bsock\n");
+      bnet_close(jcr->store_bsock);
+   }
+   if (jcr->RestoreBootstrap) {
+      free(jcr->RestoreBootstrap);
+   }
+   Dmsg0(200, "End dird free_jcr\n");
+}
+
+/*
+ * We got a File Attributes record on the tape.  Now, lookup the Job
+ *   record, and then create the attributes record.
+ */
+static int create_file_attributes_record(B_DB *db, char *fname, char *lname, int type,
                               char *ap, DEV_RECORD *rec)
 {
+   JCR *mjcr;
+
    if (!update_db) {
-      return;
+      return 1;
+   }
+
+   mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
+   if (!mjcr) {
+      Pmsg2(000, _("Could not find Job SessId=%d SessTime=%d for Attributes record.\n"),
+                  rec->VolSessionId, rec->VolSessionTime);
+      return 0;
    }
    ar.fname = fname;
    ar.link = lname;
-   ar.ClientId = cr.ClientId;
-   ar.JobId = jr.JobId;
+   ar.ClientId = mjcr->ClientId;
+   ar.JobId = mjcr->JobId;
    ar.Stream = rec->Stream;
    ar.FileIndex = rec->FileIndex;
    ar.attr = ap;
+   if (mjcr->VolFirstFile == 0) {
+      mjcr->VolFirstFile = rec->FileIndex;
+   }
+   mjcr->FileIndex = rec->FileIndex;
+   free_jcr(mjcr);                   /* done using JCR */
+
    if (!db_create_file_attributes_record(db, &ar)) {
       Pmsg1(0, _("Could not create File Attributes record. ERR=%s\n"), db_strerror(db));
+      return 0;
    }
-
+   if (verbose > 1) {
+      Pmsg1(000, _("Created File record: %s\n"), fname);   
+   }
+   return 1;
 }
 
-static void create_media_record(B_DB *db, MEDIA_DBR *mr, VOLUME_LABEL *vl)
+/*
+ * For each Volume we see, we create a Medium record
+ */
+static int create_media_record(B_DB *db, MEDIA_DBR *mr, VOLUME_LABEL *vl)
 {
    struct date_time dt;
    struct tm tm;
    if (!update_db) {
-      return;
+      return 1;
    }
    strcpy(mr->VolStatus, "Full");
    mr->VolRetention = 355 * 3600 * 24; /* 1 year */
@@ -445,59 +509,93 @@ static void create_media_record(B_DB *db, MEDIA_DBR *mr, VOLUME_LABEL *vl)
    mr->LabelDate = mktime(&tm);
    if (!db_create_media_record(db, mr)) {
       Pmsg1(0, _("Could not create media record. ERR=%s\n"), db_strerror(db));
+      return 0;
    }
    if (!db_update_media_record(db, mr)) {
       Pmsg1(0, _("Could not update media record. ERR=%s\n"), db_strerror(db));
+      return 0;
+   }
+   if (verbose) {
+      Pmsg2(000, _("Created Media record for Volume: %s, JobId: %d\n"), 
+                  mr->VolumeName, jr.JobId);
    }
+   return 1;
 
 }
 
-static void create_pool_record(B_DB *db, POOL_DBR *pr)
+static int create_pool_record(B_DB *db, POOL_DBR *pr)
 {
    if (!update_db) {
-      return;
+      return 1;
    }
    pr->NumVols++;
    pr->UseCatalog = 1;
    pr->VolRetention = 355 * 3600 * 24; /* 1 year */
    if (!db_create_pool_record(db, pr)) {
       Pmsg1(0, _("Could not create pool record. ERR=%s\n"), db_strerror(db));
+      return 0;
+   }
+   if (verbose) {
+      Pmsg1(000, _("Created Pool record for Pool: %s\n"), pr->Name);
    }
+   return 1;
 
 }
 
 
-static void create_client_record(B_DB *db, CLIENT_DBR *cr)
+/*
+ * Called from SOS to create a client for the current Job 
+ */
+static int create_client_record(B_DB *db, CLIENT_DBR *cr)
 {
    if (!update_db) {
-      return;
+      return 1;
    }
    if (!db_create_client_record(db, cr)) {
       Pmsg1(0, _("Could not create Client record. ERR=%s\n"), db_strerror(db));
+      return 0;
+   }
+   if (verbose) {
+      Pmsg1(000, _("Created Client record for Client: %s\n"), cr->Name);
    }
+   return 1;
 }
 
-static void create_fileset_record(B_DB *db, FILESET_DBR *fsr)
+static int create_fileset_record(B_DB *db, FILESET_DBR *fsr)
 {
    if (!update_db) {
-      return;
+      return 1;
    }
    if (!db_create_fileset_record(db, fsr)) {
       Pmsg1(0, _("Could not create FileSet record. ERR=%s\n"), db_strerror(db));
+      return 0;
+   }
+   if (verbose) {
+      Pmsg1(000, _("Created FileSet record %s\n"), fsr->FileSet);
    }
+   return 1;
 }
 
-static void create_job_record(B_DB *db, JOB_DBR *jr, SESSION_LABEL *label)
+/*
+ * Simulate the two calls on the database to create
+ *  the Job record and to update it when the Job actually
+ *  begins running.
+ */
+static int create_job_record(B_DB *db, JOB_DBR *jr, SESSION_LABEL *label, 
+                            DEV_RECORD *rec)
 {
    struct date_time dt;
    struct tm tm;
 
    if (!update_db) {
-      return;
+      return 1;
    }
+   Pmsg1(000, _("Creating Job record for JobId: %d\n"), jr->JobId);
+
    jr->JobId = label->JobId;
    jr->Type = label->JobType;
    jr->Level = label->JobLevel;
+   jr->JobStatus = JS_Created;
    strcpy(jr->Name, label->JobName);
    strcpy(jr->Job, label->Job);
    dt.julian_day_number = label->write_date;
@@ -506,54 +604,123 @@ static void create_job_record(B_DB *db, JOB_DBR *jr, SESSION_LABEL *label)
    jr->SchedTime = mktime(&tm);
    jr->StartTime = jr->SchedTime;
    jr->JobTDate = (btime_t)jr->SchedTime;
+   jr->VolSessionId = rec->VolSessionId;
+   jr->VolSessionTime = rec->VolSessionTime;
+
+   /* This creates the bare essentials */
    if (!db_create_job_record(db, jr)) {
       Pmsg1(0, _("Could not create job record. ERR=%s\n"), db_strerror(db));
+      return 0;
    }
 
+   /* Now create a JCR as if starting the Job */
+   create_jcr(jr, rec, label->JobId);
+
+   /* This adds the client, StartTime, JobTDate, ... */
+   if (!db_update_job_start_record(db, jr)) {
+      Pmsg1(0, _("Could not update job start record. ERR=%s\n"), db_strerror(db));
+      return 0;
+   }
+   if (verbose) {
+      Pmsg1(000, _("Created Job record for JobId: %d\n"), jr->JobId);
+   }
+   return 1;
 }
 
-static void update_job_record(B_DB *db, JOB_DBR *jr, SESSION_LABEL *elabel,
+/* 
+ * Simulate the database call that updates the Job 
+ *  at Job termination time.
+ */
+static int update_job_record(B_DB *db, JOB_DBR *jr, SESSION_LABEL *elabel,
                              DEV_RECORD *rec)
 {
    struct date_time dt;
    struct tm tm;
+   JCR *mjcr;
 
    if (!update_db) {
-      return;
+      return 1;
+   }
+   mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
+   if (!mjcr) {
+      Pmsg2(000, _("Could not find SessId=%d SessTime=%d for EOS record.\n"),
+                  rec->VolSessionId, rec->VolSessionTime);
+      return 0;
    }
    dt.julian_day_number = elabel->write_date;
    dt.julian_day_fraction = elabel->write_time;
    tm_decode(&dt, &tm);
-   jr->JobStatus = JS_Terminated;
+   jr->JobId = mjcr->JobId;
+   jr->JobStatus = JS_Terminated;     /* ***FIXME*** need to add to EOS label */
    jr->EndTime = mktime(&tm);
    jr->JobFiles = elabel->JobFiles;
    jr->JobBytes = elabel->JobBytes;
    jr->VolSessionId = rec->VolSessionId;
    jr->VolSessionTime = rec->VolSessionTime;
-   if (!db_create_job_record(db, jr)) {
-      Pmsg1(0, _("Could not create job record. ERR=%s\n"), db_strerror(db));
+   jr->JobTDate = (btime_t)mjcr->start_time;
+   jr->ClientId = mjcr->ClientId;
+   if (!db_update_job_end_record(db, jr)) {
+      Pmsg1(0, _("Could not update job record. ERR=%s\n"), db_strerror(db));
+      free_jcr(mjcr);
+      return 0;
    }
-
+   if (verbose) {
+      Pmsg1(000, _("Updated Job termination record for JobId: %d\n"), jr->JobId);
+   }
+   free_jcr(mjcr);
+   return 1;
 }
 
-static void create_jobmedia_record(B_DB *db, JOBMEDIA_DBR *jmr, SESSION_LABEL *elabel)
+static int create_jobmedia_record(B_DB *db, JCR *mjcr)
 {
+   JOBMEDIA_DBR jmr;
+
    if (!update_db) {
-      return;
+      return 1;
    }
-   jmr->FirstIndex = FirstIndex;
-   jmr->LastIndex = LastIndex;
-   jmr->StartFile = elabel->start_file;
-   jmr->EndFile = elabel->end_file;
-   jmr->StartBlock = elabel->start_block;
-   jmr->EndBlock = elabel->end_block;
-   if (!db_create_jobmedia_record(db, jmr)) {
+   memset(&jmr, 0, sizeof(jmr));
+   jmr.JobId = mjcr->JobId;
+   jmr.MediaId = mr.MediaId;
+   jmr.FirstIndex = mjcr->VolFirstFile;
+   jmr.LastIndex = mjcr->FileIndex;
+   jmr.StartFile = mjcr->start_file;
+   jmr.EndFile = mjcr->end_file;
+   jmr.StartBlock = mjcr->start_block;
+   jmr.EndBlock = mjcr->end_block;
+
+   if (!db_create_jobmedia_record(db, &jmr)) {
       Pmsg1(0, _("Could not create JobMedia record. ERR=%s\n"), db_strerror(db));
+      return 0;
    }
-
+   if (verbose) {
+      Pmsg2(000, _("Created JobMedia record JobId %d, MediaId %d\n"), 
+               jmr.JobId, jmr.MediaId);
+   }
+   return 1;
 }
 
+/* 
+ * Create a JCR as if we are really starting the job
+ */
+static void create_jcr(JOB_DBR *jr, DEV_RECORD *rec, uint32_t JobId)
+{
+   /*
+    * Transfer as much as possible to the Job JCR. Most important is
+    *  the JobId and the ClientId.
+    */
+   jobjcr = new_jcr(sizeof(JCR), dird_free_jcr);
+   jobjcr->JobType = jr->Type;
+   jobjcr->JobLevel = jr->Level;
+   jobjcr->JobStatus = jr->JobStatus;
+   strcpy(jobjcr->Job, jr->Job);
+   jobjcr->JobId = JobId;      /* this is JobId on tape */
+   jobjcr->sched_time = jr->SchedTime;
+   jobjcr->start_time = jr->StartTime;
+   jobjcr->VolSessionId = rec->VolSessionId;
+   jobjcr->VolSessionTime = rec->VolSessionTime;
+   jobjcr->ClientId = jr->ClientId;
+   attach_jcr_to_device(dev, jobjcr);
+}
 
 /* Dummies to replace askdir.c */
 int    dir_get_volume_info(JCR *jcr, int writing) { return 1;}
@@ -567,6 +734,24 @@ int        dir_send_job_status(JCR *jcr) {return 1;}
 
 int dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev)
 {
+   /*  
+    * We are at the end of reading a tape. Now, we simulate handling
+    *  the end of writing a tape by wiffling through the attached
+    *  jcrs creating jobmedia records.
+    */
+   Dmsg1(100, "Walk attached jcrs. Volume=%s\n", dev->VolCatInfo.VolCatName);
+   for (JCR *mjcr=NULL; (mjcr=next_attached_jcr(dev, mjcr)); ) {
+      if (verbose) {
+         Pmsg1(000, "create JobMedia for Job %s\n", mjcr->Job);
+      }
+      mjcr->end_block = dev->block_num;
+      mjcr->end_file = dev->file;
+      if (!create_jobmedia_record(db, mjcr)) {
+         Pmsg2(000, _("Could not create JobMedia record for Volume=%s Job=%s\n"),
+           dev->VolCatInfo.VolCatName, mjcr->Job);
+      }
+   }
+
    fprintf(stderr, "Mount Volume %s on device %s and press return when ready: ",
       jcr->VolumeName, dev_name(dev));
    getchar();  
index 668dbec46fdf286576396ce00f498a28981914c3..323e714ec86037460671703cef540d05ebbb2254 100644 (file)
@@ -113,6 +113,10 @@ static void my_free_jcr(JCR *jcr)
    return;
 }
 
+/*
+ * Setup a "daemon" JCR for the various standalone
+ *  tools (e.g. bls, bextract, bscan, ...)
+ */
 JCR *setup_jcr(char *name, char *device, BSR *bsr) 
 {
    JCR *jcr = new_jcr(sizeof(JCR), my_free_jcr);
index e78a2ee3c56b85f18b29d2f83d8a99720ffd9495..4720fce987206b1abad5d478a7bea1728ede3fa5 100644 (file)
@@ -67,6 +67,11 @@ int read_records(JCR *jcr,  DEVICE *dev,
            }
             Dmsg3(100, "After mount next vol. stat=%s blk=%d rem=%d\n", rec_state_to_str(rec), 
                  block->BlockNumber, rec->remainder);
+           /*
+            * We just have a new tape up, now read the label (first record)
+            *  and pass it off to the callback routine, then continue
+            *  most likely reading the previous record.
+            */
            record = new_record();
            read_block_from_device(dev, block);
            read_record_from_block(block, record);
@@ -218,4 +223,3 @@ static char *rec_state_to_str(DEV_RECORD *rec)
    }
    return buf;
 }
-
index 498968b4817e3a71e569a3cb749c6d567489e616..43d21450342e6d7fb363e8e2de2ec48c6b3926a5 100644 (file)
@@ -38,7 +38,6 @@
 /* Forward referenced functions */
 void terminate_stored(int sig);
 static void check_config();
-static void *director_thread(void *arg);
 
 #define CONFIG_FILE "bacula-sd.conf"  /* Default config file */
 
@@ -61,7 +60,6 @@ static char *configfile;
 static int foreground = 0;
 
 static workq_t dird_workq;           /* queue for processing connections */
-static workq_t filed_workq;          /* queue for processing connections */
 
 
 static void usage()
@@ -90,8 +88,6 @@ int main (int argc, char *argv[])
    int no_signals = FALSE;
    int test_config = FALSE;
    DEVRES *device;
-   pthread_t dirid;
-   int status;
 
    init_stack_dump();
    my_name_is(argc, argv, "stored");
@@ -255,35 +251,12 @@ int main (int argc, char *argv[])
 
    start_watchdog();                 /* start watchdog thread */
 
-   /*
-    * Here we support either listening on one port or on two ports
-    */
-   if (me->SDDport == 0 || me->SDDport == me->SDport) {
-      /* Single server used for Director and File daemon */
-      bnet_thread_server(me->SDport, me->max_concurrent_jobs * 2,
-        &dird_workq, connection_request);
-   } else {
-      /* Start the Director server */
-      if ((status=pthread_create(&dirid, NULL, director_thread,        
-          (void *)me->SDport)) != 0) {
-         Emsg1(M_ABORT, 0, _("Cannot create Director thread: %s\n"), strerror(status));
-      }
-      /* Start File daemon server */
-      bnet_thread_server(me->SDDport, 10, &filed_workq, connection_from_filed);
-      /* never returns */
-   }
-
+   /* Single server used for Director and File daemon */
+   bnet_thread_server(me->SDaddr, me->SDport, me->max_concurrent_jobs * 2 + 1,
+                     &dird_workq, connection_request);
    exit(1);                          /* to keep compiler quiet */
 }
 
-static void *director_thread(void *arg)
-{
-   int dir_port = (int)arg;
-   pthread_detach(pthread_self());
-   bnet_thread_server(dir_port, 10, &dird_workq, connection_request);
-   return NULL;
-}
-
 /* Return a new Session Id */
 uint32_t newVolSessionId()
 {
index 8eed0fa90709b023b99d87db6bbeb8bb316822e8..2ff9448bee02f42c0a1e4f6dfeb090206bb228cf 100644 (file)
@@ -54,10 +54,11 @@ int res_all_size = sizeof(res_all);
 static struct res_items store_items[] = {
    {"name",                  store_name, ITEM(res_store.hdr.name),   0, ITEM_REQUIRED, 0},
    {"description",           store_str,  ITEM(res_dir.hdr.desc),     0, 0, 0},
-   {"address",               store_str,  ITEM(res_store.address),    0, 0, 0},
+   {"address",               store_str,  ITEM(res_store.address),    0, 0, 0}, /* deprecated */
+   {"sdaddress",             store_str,  ITEM(res_store.SDaddr),     0, 0, 0},
    {"messages",              store_res,  ITEM(res_store.messages),   0, R_MSGS, 0},
    {"sdport",                store_int,  ITEM(res_store.SDport),     0, ITEM_DEFAULT, 9103},
-   {"sddport",               store_int,  ITEM(res_store.SDDport),    0, 0, 0}, /* depricated */
+   {"sddport",               store_int,  ITEM(res_store.SDDport),    0, 0, 0}, /* deprecated */
    {"workingdirectory",      store_dir,  ITEM(res_store.working_directory), 0, ITEM_REQUIRED, 0},
    {"piddirectory",          store_dir,  ITEM(res_store.pid_directory), 0, ITEM_REQUIRED, 0},
    {"subsysdirectory",       store_dir,  ITEM(res_store.subsys_directory), 0, ITEM_REQUIRED, 0},
@@ -145,8 +146,8 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, char *fmt, ...
          sendit(sock, "Director: name=%s\n", res->res_dir.hdr.name);
         break;
       case R_STORAGE:
-         sendit(sock, "Storage: name=%s address=%s SDport=%d SDDport=%d\n",
-           res->res_store.hdr.name, res->res_store.address
+         sendit(sock, "Storage: name=%s SDaddr=%s SDport=%d SDDport=%d\n",
+           res->res_store.hdr.name, res->res_store.SDaddr
            res->res_store.SDport, res->res_store.SDDport);
         break;
       case R_DEVICE:
@@ -245,36 +246,51 @@ void free_resource(int type)
 
    switch (type) {
       case R_DIRECTOR:
-        if (res->res_dir.password)
+        if (res->res_dir.password) {
            free(res->res_dir.password);
-        if (res->res_dir.address)
+        }
+        if (res->res_dir.address) {
            free(res->res_dir.address);
+        }
         break;
       case R_STORAGE:
-        if (res->res_store.address)
+        if (res->res_store.address) {  /* ***FIXME*** deprecated */
            free(res->res_store.address);
-        if (res->res_store.working_directory)
+        }
+        if (res->res_store.SDaddr) {
+           free(res->res_store.SDaddr);
+        }
+        if (res->res_store.working_directory) {
            free(res->res_store.working_directory);
-        if (res->res_store.pid_directory)
+        }
+        if (res->res_store.pid_directory) {
            free(res->res_store.pid_directory);
-        if (res->res_store.subsys_directory)
+        }
+        if (res->res_store.subsys_directory) {
            free(res->res_store.subsys_directory);
+        }
         break;
       case R_DEVICE:
-        if (res->res_dev.media_type)
+        if (res->res_dev.media_type) {
            free(res->res_dev.media_type);
-        if (res->res_dev.device_name)
+        }
+        if (res->res_dev.device_name) {
            free(res->res_dev.device_name);
-        if (res->res_dev.changer_name)
+        }
+        if (res->res_dev.changer_name) {
            free(res->res_dev.changer_name);
-        if (res->res_dev.changer_command)
+        }
+        if (res->res_dev.changer_command) {
            free(res->res_dev.changer_command);
+        }
         break;
       case R_MSGS:
-        if (res->res_msgs.mail_cmd)
+        if (res->res_msgs.mail_cmd) {
            free(res->res_msgs.mail_cmd);
-        if (res->res_msgs.operator_cmd)
+        }
+        if (res->res_msgs.operator_cmd) {
            free(res->res_msgs.operator_cmd);
+        }
         free_msgs_res((MSGS *)res);  /* free message resource */
         res = NULL;
         break;
index 585030e9da903f7f3d069d44edd040767640d5ea..2c333b7656790d08ba9fc9d0f2dbccece2056481 100644 (file)
 
  */
 
-#define R_FIRST                       3001
+#define R_FIRST                      3001
 
-#define R_DIRECTOR                    3001
-#define R_STORAGE                     3002
-#define R_DEVICE                      3003
-#define R_MSGS                        3004
+#define R_DIRECTOR                   3001
+#define R_STORAGE                    3002
+#define R_DEVICE                     3003
+#define R_MSGS                       3004
 
-#define R_LAST                        R_MSGS
+#define R_LAST                       R_MSGS
 
 
-#define R_NAME                        3020
-#define R_ADDRESS                     3021
-#define R_PASSWORD                    3022
-#define R_TYPE                        3023
-#define R_BACKUP                      3024
+#define R_NAME                       3020
+#define R_ADDRESS                    3021
+#define R_PASSWORD                   3022
+#define R_TYPE                       3023
+#define R_BACKUP                     3024
 
 #define STORAGE_DAEMON 1
 
 /* Definition of the contents of each Resource */
 struct s_res_dir {
-   RES   hdr;
+   RES  hdr;
 
-   char *password;                    /* Director password */
-   char *address;                     /* Director IP address or zero */
+   char *password;                   /* Director password */
+   char *address;                    /* Director IP address or zero */
 };
 typedef struct s_res_dir DIRRES;
 
 
 /* Storage daemon "global" definitions */
 struct s_res_store {
-   RES   hdr;
+   RES  hdr;
 
-   char *address;
-   int   SDport;                      /* Where we listen for Directors */
+   char *address;                    /* deprecated */
+   char *SDaddr;                     /* bind address */
+   int  SDport;                      /* Where we listen for Directors */
    int   SDDport;                     /* "Data" port where we listen for File daemons */
-   char *working_directory;           /* working directory for checkpoints */
+   char *working_directory;          /* working directory for checkpoints */
    char *pid_directory;
    char *subsys_directory;
    uint32_t max_concurrent_jobs;      /* maximum concurrent jobs to run */
@@ -68,32 +69,32 @@ typedef struct s_res_store STORES;
 
 /* Device specific definitions */
 struct s_res_dev {
-   RES   hdr;
-
-   char *media_type;                  /* User assigned media type */
-   char *device_name;                 /* Archive device name */
-   char *changer_name;                /* Changer device name */
-   char *changer_command;             /* Changer command  -- external program */
-   int  cap_bits;                     /* Capabilities of this device */
-   uint32_t max_changer_wait;         /* Changer timeout */
-   uint32_t max_rewind_wait;          /* maximum secs to wait for rewind */
-   uint32_t max_open_wait;            /* maximum secs to wait for open */
-   uint32_t min_block_size;           /* min block size */
-   uint32_t max_block_size;           /* max block size */
-   uint32_t max_volume_jobs;          /* max jobs to put on one volume */
-   int64_t max_volume_files;          /* max files to put on one volume */
-   int64_t max_volume_size;           /* max bytes to put on one volume */
-   int64_t max_file_size;             /* max file size in bytes */
-   int64_t volume_capacity;           /* advisory capacity */
-   DEVICE *dev;                       /* Pointer to phyical dev -- set at runtime */
+   RES  hdr;
+
+   char *media_type;                 /* User assigned media type */
+   char *device_name;                /* Archive device name */
+   char *changer_name;               /* Changer device name */
+   char *changer_command;            /* Changer command  -- external program */
+   int cap_bits;                     /* Capabilities of this device */
+   uint32_t max_changer_wait;        /* Changer timeout */
+   uint32_t max_rewind_wait;         /* maximum secs to wait for rewind */
+   uint32_t max_open_wait;           /* maximum secs to wait for open */
+   uint32_t min_block_size;          /* min block size */
+   uint32_t max_block_size;          /* max block size */
+   uint32_t max_volume_jobs;         /* max jobs to put on one volume */
+   int64_t max_volume_files;         /* max files to put on one volume */
+   int64_t max_volume_size;          /* max bytes to put on one volume */
+   int64_t max_file_size;            /* max file size in bytes */
+   int64_t volume_capacity;          /* advisory capacity */
+   DEVICE *dev;                      /* Pointer to phyical dev -- set at runtime */
 };
 typedef struct s_res_dev DEVRES;
 
 union u_res {
-   struct s_res_dir     res_dir;
-   struct s_res_store   res_store;
-   struct s_res_dev     res_dev;
-   struct s_res_msgs    res_msgs;
+   struct s_res_dir    res_dir;
+   struct s_res_store  res_store;
+   struct s_res_dev    res_dev;
+   struct s_res_msgs   res_msgs;
    RES hdr;
 };
 typedef union u_res URES;
index 6c7343678c915f6020c805f22b66dbb0967dee33..e566b7bb3c9205d6489fb03e9d15ed9449bb1133 100644 (file)
@@ -1,8 +1,8 @@
 /* */
 #define VERSION "1.26"
 #define VSTRING "1"
-#define DATE    "21 September 2002"
-#define LSMDATE "21Sep02"
+#define DATE    "25 September 2002"
+#define LSMDATE "25Sep02"
 
 /* Debug flags */
 #define DEBUG 1