]> git.sur5r.net Git - bacula/bacula/commitdiff
See kes-1.31 for details
authorKern Sibbald <kern@sibbald.com>
Fri, 30 May 2003 14:44:53 +0000 (14:44 +0000)
committerKern Sibbald <kern@sibbald.com>
Fri, 30 May 2003 14:44:53 +0000 (14:44 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@556 91ce42f0-d328-0410-95d8-f526ca767f89

65 files changed:
bacula/ReleaseNotes
bacula/kernstodo
bacula/src/cats/bdb.c
bacula/src/cats/bdb_list.c
bacula/src/cats/cats.h
bacula/src/cats/drop_mysql_tables.in
bacula/src/cats/make_mysql_tables.in
bacula/src/cats/make_sqlite_tables.in
bacula/src/cats/mysql.c
bacula/src/cats/protos.h
bacula/src/cats/sql.c
bacula/src/cats/sql_create.c
bacula/src/cats/sql_find.c
bacula/src/cats/sql_get.c
bacula/src/cats/sql_list.c
bacula/src/cats/sqlite.c
bacula/src/console/console.c
bacula/src/dird/Makefile.in
bacula/src/dird/backup.c
bacula/src/dird/dird.c
bacula/src/dird/dird_conf.h
bacula/src/dird/fd_cmds.c
bacula/src/dird/getmsg.c
bacula/src/dird/inc_conf.c
bacula/src/dird/msgchan.c
bacula/src/dird/protos.h
bacula/src/dird/query.sql
bacula/src/dird/restore.c
bacula/src/dird/sql_cmds.c
bacula/src/dird/ua.h
bacula/src/dird/ua_cmds.c
bacula/src/dird/ua_input.c
bacula/src/dird/ua_output.c
bacula/src/dird/ua_query.c [new file with mode: 0644]
bacula/src/dird/ua_restore.c
bacula/src/dird/ua_select.c
bacula/src/dird/verify.c
bacula/src/filed/filed_conf.h
bacula/src/lib/Makefile.in
bacula/src/lib/edit.c
bacula/src/lib/message.c
bacula/src/lib/parse_conf.c
bacula/src/lib/parse_conf.h
bacula/src/lib/protos.h
bacula/src/lib/scan.c [new file with mode: 0644]
bacula/src/lib/smartall.c
bacula/src/lib/util.c
bacula/src/stored/acquire.c
bacula/src/stored/askdir.c
bacula/src/stored/block.c
bacula/src/stored/block.h
bacula/src/stored/bls.c
bacula/src/stored/bsr.h
bacula/src/stored/dev.c
bacula/src/stored/device.c
bacula/src/stored/dircmd.c
bacula/src/stored/job.c
bacula/src/stored/label.c
bacula/src/stored/mount.c
bacula/src/stored/parse_bsr.c
bacula/src/stored/read.c
bacula/src/stored/read_record.c
bacula/src/stored/record.h
bacula/src/stored/stored_conf.h
bacula/src/version.h

index fa4ee40bcbd9c5cfdde9f0b9c4dac192e72ce847..6e6a4cf09b6c0e6d9b491b220947c1aeeb32263f 100644 (file)
@@ -1,7 +1,7 @@
 
           Release Notes for Bacula 1.31
 
-  Bacula code: Total files = 241 Total lines = 69,771 (*.h *.c *.in)
+  Bacula code: Total files = 243 Total lines = 70,151 (*.h *.c *.in)
 
 Major Changes this Release:
 - Support to save and restore all files on WinNT/2K/XP systems 
@@ -41,4 +41,3 @@ Items to note:  !!!!!
   option on the ./configure.
 - Version 1.31 and 1.30 daemons/Director are not compatible. You must
   upgrade all or nothing.
-
index fec3d93a0e5e891f3fff278dc81b97e103251b77..48a7507f33a2cd5b402886c3a6e31c306dc8da75 100644 (file)
@@ -1,5 +1,5 @@
                  Kern's ToDo List
-                  26 May  2003 
+                  30 May  2003 
 
 Documentation to do: (any release a little bit at a time)
 - Document running a test version.
@@ -13,6 +13,9 @@ Documentation to do: (any release a little bit at a time)
   hours of operation.
 - Lookup HP cleaning recommendations.
 - Lookup HP tape replacement recommendations (see trouble shooting autochanger)
+- Document FInclude ...
+- Document need to add "-u root" to most of MySQL script calls
+  (./create_mys... ./make_my...).
 
           
 Testing to do: (painful)
@@ -22,39 +25,74 @@ Testing to do: (painful)
 - Test if rewind at end of tape waits for tape to rewind.
 - Test cancel at EOM.       
 - Test not zeroing Autochanger slot when it is wrong.
+- Test multiple simultaneous Volumes
 
 - Figure out how to use ssh or stunnel to protect Bacula communications.
 
 For 1.31 release:
-- Currently in mount.c:236 the SD simply creates a Volume. It should have
-  explicit permission to do so.  It should also mark the tape in error
-  if there is an error.
+- Implement FileSet VolIndex.
+- Sort JobIds entered into recover tree.
+- Should Bacula make an Append tape as Purged when purging?
+- Test a second language e.g. french.
+- Start working on Base jobs.
+- Make "make binary-release" work from any directory.
+- Document c:/working directory better than /working directory.
+- Unsaved Flag in Job record.
+- Base Flag in Job record.
+- Implement UnsavedFiles DB record.
+- The "List last 20 Jobs run" doesnt work correctly.
+  It doesnt show the last 20 jobs , but some older ones.
 - The bsr for Dan's job has file indexes covering the whole range rather
   than only the range contained on the volume.
   Constrain FileIndex to be within range for Volume.
+- Fix Verify VolumeToCatalog to use BSRs -- it is broken.
+- Use switch() in backup.c and restore.c in FD instead of giant if statement.
+- Implement argc/argv for daemon command line scanning using table driven
+  stuff below.
+- Implement table driven single argc/argv scanner to pickup all arguments.
+  Much like xxx_conf.c scan table.
+  keyword, handler(store_routine), store_address, code, flags, default.
+- Make | and < work on FD side.
+- Pass prefix_links to FD.
+- Implement a M_SECURITY message class.
+- From Phil Stracchino:
+  It would probably be a per-client option, and would be called
+  something like, say, "Automatically purge obsoleted jobs".  What it
+  would do is, when you successfully complete a Differential backup of a
+  client, it would automatically purge all Incremental backups for that
+  client that are rendered redundant by that Differential.  Likewise,
+  when a Full backup on a client completed, it would automatically purge
+  all Differential and Incremental jobs obsoleted by that Full backup.
+  This would let people minimize the number of tapes they're keeping on
+  hand without having to master the art of retention times.
+- Prohibit backing up archive device (findlib/find_one.c:128)
+- Make Restore report an error if FD or SD term codes are not OK.
+- Add JobLevel in FD status (but make sure it is defined).
+- Make Pool resource handle Counter resources.
+- Restrict characters permitted in a Resource name, and don't permit
+  duplicate names.
+- Implement new serialize subroutines
+   send(socket, "string", &Vol, "uint32", &i, NULL)
+- Audit all UA commands to ensure that we always prompt where possible.
+
+
+After 1.31:
+- Currently in mount.c:236 the SD simply creates a Volume. It should have
+  explicit permission to do so.  It should also mark the tape in error
+  if there is an error.
 - Make sure all restore counters are working correctly in the FD.
 - SD Bytes Read is wrong.
 - Configure mtx-changer to have correct path to mtx.
 - Look at ALL higher level routines that call block.c to be sure
   they don't expect something in errmsg.
-
-- Fix Verify VolumeToCatalog to use BSRs -- it is broken.
-
-- Use switch() in backup.c and restore.c in FD instead of giant if statement.
 - Investigate doing RAW backup of Win32 partition.
 - Add JobName= to VerifyToCatalog so that all verifies can be done at the end.
 - Add thread specific data to hold the jcr -- send error messages from
   low level routines by accessing it and using Jmsg().
-- Default duration with no qualifier is sec should be 1 day
-- Find a solution for the multiple FileSet problem (when it is changed). Add date?
 - Cancel waiting for Client connect in SD if FD goes away.
 - Testing Tibs job erred and hung director on Storage resource.  This was
   because there were a whole pile of jobs hanging around in the SD  
   waiting for a connection from the FD that was never coming.
-- Make restore more robust in counting error and not immediately bailing
-  out. Also print error message once, but try to continue.
-- Add code to check that blocks are sequential on restore.
-- Should Bacula make an Append tape as Purged when purging?
 - Possibly update all client records at startup.
 
 - Add Progress command that periodically reports the progress of
@@ -63,15 +101,8 @@ For 1.31 release:
 - One block was orphaned in the SD probably after cancel.
 - Add all command line arguments to "update", e.g. slot=nn volStatus=append, ...
 
-- Implement argc/argv for daemon command line scanning using table driven
-  stuff below.
-- Implement table driven single argc/argv scanner to pickup all arguments.
-  Much like xxx_conf.c scan table.
-  keyword, handler(store_routine), store_address, code, flags, default.
 
 - Examine Bare Metal restore problem (a FD crash exists somewhere ...).
-- Test multiple simultaneous Volumes
-- Document FInclude ...
 - Implement timeout in response() when it should come quickly.
 - Implement console @echo command.
 - Implement a Slot priority (loaded/not loaded).
@@ -93,30 +124,16 @@ For 1.31 release:
 - Implement restore "current system", but take all files without
   doing selection tree -- so that jobs without File records can
   be restored.
-- Make | and < work on FD side.
-- Pass prefix_links to FD.
-- Implement a M_SECURITY message class.
 - Implement disk spooling. Two parts: 1. Spool to disk then
   immediately to tape to speed up tape operations. 2. Spool to
   disk only when the tape is full, then when a tape is hung move
   it to tape.
-- From Phil Stracchino:
-  It would probably be a per-client option, and would be called
-  something like, say, "Automatically purge obsoleted jobs".  What it
-  would do is, when you successfully complete a Differential backup of a
-  client, it would automatically purge all Incremental backups for that
-  client that are rendered redundant by that Differential.  Likewise,
-  when a Full backup on a client completed, it would automatically purge
-  all Differential and Incremental jobs obsoleted by that Full backup.
-  This would let people minimize the number of tapes they're keeping on
-  hand without having to master the art of retention times.
 - Implement a relocatable bacula.spec 
 - Allow multiple Storage specifications (or multiple names on
   a single Storage specification) in the Job record. Thus a job 
   can be backed up to a number of storage devices.
 - Implement dump/print label to UA
 - Add prefixlinks to where or not where absolute links to FD.
-- Look at Python for a Bacula scripting language -- www.python.org
 - Issue message to mount a new tape before the rewind.
 - Simplified client job initiation for portables.
 - If SD cannot open a drive, make it periodically retry.
@@ -159,20 +176,16 @@ For 1.31 release:
 - Program files (i.e. execute a program to read/write files).
   Pass read date of last backup, size of file last time.
 - Add Signature type to File DB record.
-- Make Restore report an error if FD or SD term codes are not OK.
 - CD into subdirectory when open()ing files for backup to
   speed up things.  Test with testfind().
 - Priority job to go to top of list.
-- Find out why Full saves run slower and slower (hashing?)
 - Why are save/restore of device different sizes (sparse?)   Yup! Fix it.
 - Implement some way for the Console to dynamically create a job.
 - Restore to a particular time -- e.g. before date, after date. 
 - Solaris -I on tar for include list
-- Prohibit backing up archive device (findlib/find_one.c:128)
 - Need a verbose mode in restore, perhaps to bsr.
 - bscan without -v is too quiet -- perhaps show jobs.
 - Add code to reject whole blocks if not wanted on restore.
-- Start working on Base jobs.
 - Check if we can increase Bacula FD priorty in Win2000
 - Make sure the MaxVolFiles is fully implemented in SD
 - Check if both CatalogFiles and UseCatalog are set to SD.
@@ -183,17 +196,11 @@ For 1.31 release:
 - Possibly add email to Watchdog if drive is unmounted too
   long and a job is waiting on the drive.
 - Use read_record.c in SD code.
-- Why don't we get an error message from Win32 FD when bootstrap 
-  file cannot be created for restore command?
-- When Marking a file in Restore that is a hard link, also
-  mark the link so that the data will be reloaded.
 - Restore program that errors in SD due to no tape reports
   OK incorrectly in output.
 - After unmount, if restore job started, ask to mount.
 - Convert all %x substitution variables, which are hard to remember
   and read to %(variable-name).  Idea from TMDA.
-- Add JobLevel in FD status (but make sure it is defined).
-- Make Pool resource handle Counter resources.
 - Remove NextId for SQLite. Optimize.
 - Move all SQL statements into a single location.
 - Add UA rc and history files.
@@ -202,15 +209,11 @@ For 1.31 release:
 - Enhance time and size scanning routines.
 - Fix Autoprune for Volumes to respect need for full save.
 - Fix Win32 config file definition name on /install
-- No READLINE_SRC if found in alternate directory.
-- Test a second language e.g. french.
 - Compare tape to Client files (attributes, or attributes and data) 
 - Make all database Ids 64 bit.
 - Write an applet for Linux.
 - Add estimate to Console commands
-- Find solution to blank filename (i.e. path only) problem.
 - Implement new daemon communications protocol.
-- Remove PoolId from Job table, it exists in Media.
 - Allow console commands to detach or run in background.
 - Fix status delay on storage daemon during rewind.
 - Add SD message variables to control operator wait time
@@ -222,31 +225,20 @@ For 1.31 release:
   Verify level=Catalog, level=InitCatalog
 - Events file
 - Add keyword search to show command in Console.
-- Fix Win2000 error with no messages during startup.
 - Events : tape has more than xxx bytes.
-- Restrict characters permitted in a Resource name.
 - Complete code in Bacula Resources -- this will permit
   reading a new config file at any time.
 - Handle ctl-c in Console
 - Implement script driven addition of File daemon to config files.
 - Think about how to make Bacula work better with File (non-tape) archives.
 - Write Unix emulator for Windows.
-- Implement new serialize subroutines
-   send(socket, "string", &Vol, "uint32", &i, NULL)
-- Audit all UA commands to ensure that we always prompt where possible.
-- If ./btape is called without /dev, assume argument is a Storage resource name.
 - Put memory utilization in Status output of each daemon
   if full status requested or if some level of debug on.
 - Make database type selectable by .conf files i.e. at runtime
 - Set flag for uname -a.  Add to Volume label.
 - Implement throttled work queue.
-- Check for EOT at ENOSPC or EIO or ENXIO (unix Pc)
 - Restore files modified after date
 - Restore file modified before date
-- Emergency restore info:
-  - Backup Bacula
-  - Backup working directory
-  - Backup Catalog
 - Restore -- do nothing but show what would happen
 - SET LD_RUN_PATH=$HOME/mysql/lib/mysql
 - Implement Restore FileSet=
@@ -254,16 +246,11 @@ For 1.31 release:
   are concentrated.
 - Remove duplicate fields from jcr (e.g. jcr.level and jcr.jr.Level, ...).
 - Timout a job or terminate if link goes down, or reopen link and query.
-- Find general solution for sscanf size problems (as well
-  as sprintf. Do at run time?
 - Concept of precious tapes (cannot be reused).
 - Make bcopy copy with a single tape drive.
 - Permit changing ownership during restore.
 
 - Autolabel should be specified by DIR instead of SD.
-- Find out how to get the system tape block limits, e.g.:
-  Apr 22 21:22:10 polymatou kernel: st1: Block limits 1 - 245760 bytes.  
-  Apr 22 21:22:10 polymatou kernel: st0: Block limits 2 - 16777214 bytes.
 - Storage daemon    
   - Add media capacity
   - AutoScan (check checksum of tape)
@@ -302,13 +289,6 @@ For 1.31 release:
   times out jobs by asking the deamons where they are.
 - Enhance Jmsg code to permit buffering and saving to disk.
 - device driver = "xxxx" for drives.
-- restart: paranoid: read label fsf to
-  eom read append block, and go
-  super-paranoid: read label, read all files
-  in between, read append block, and go
-  verify: backspace, read append block, and go
-  permissive: same as above but frees drive
-  if tape is not valid.
 - Verify from Volume
 - Ensure that /dev/null works
 - Need report class for messages. Perhaps
@@ -317,7 +297,7 @@ For 1.31 release:
   fill in code for "since" option 
 - Director needs a time after which the report status is sent
   anyway -- or better yet, a retry time for the job.
-  Don't reschedule a job if previous incarnation is still running.
+- Don't reschedule a job if previous incarnation is still running.
 - Some way to automatically backup everything is needed????
 - Need a structure for pending actions:
   - buffered messages
@@ -332,9 +312,6 @@ For 1.31 release:
 Longer term to do:
 - Design at hierarchial storage for Bacula. Migration and Clone. 
 - Implement FSM (File System Modules).
-- Identify unchanged or "system" files and save them to a
-  special tape thus removing them from the standard 
-  backup FileSet -- BASE backup.
 - Audit M_ error codes to ensure they are correct and consistent.
 - Add variable break characters to lex analyzer.
   Either a bit mask or a string of chars so that
@@ -917,3 +894,23 @@ Done: (see kernsdone for more)
 - Shell expansion fails for working_directory in SD from time to time.
 - File the Automatically selected: xxx
   to say Automatically selected Pool: xxx
+- Default duration with no qualifier is sec should be 1 day
+- zap sd_auth_key in SD after FD connection.
+- Find a solution for the multiple FileSet problem (when it is changed). Add date?
+- Look at Python for a Bacula scripting language -- www.python.org
+- When Marking a file in Restore that is a hard link, also
+  mark the link so that the data will be reloaded.
+- Emergency restore info:
+  - Backup Bacula
+  - Backup working directory
+  - Backup Catalog
+- Why don't we get an error message from Win32 FD when bootstrap 
+  file cannot be created for restore command?
+- Fix Win2000 error with no messages during startup.
+- Make restore more robust in counting error and not immediately bailing
+  out. Also print error message once, but try to continue.
+- Add code to check that blocks are sequential on restore.
+- Remove "rufus" and such references from regress.
+- No READLINE_SRC if found in alternate directory.
+- If ./btape is called without /dev, assume argument is a Storage resource name.
+- Find general solution for sscanf size problems (as well as sprintf. Do at run time?
index 39da83fb00181c74c9d256344a7a0ebf9fafcd9c..980a12b8e1af14c0897ec1a84af2101ce5303a04 100644 (file)
@@ -44,7 +44,7 @@
 
 #ifdef HAVE_BACULA_DB
 
-char catalog_db[] = "Interal";
+uint32_t bacula_db_version = 0;
 
 /* Forward referenced functions */
 
@@ -228,6 +228,7 @@ Please reinitialize the working directory.\n"),
         BDB_VERSION, mdb->control.bdb_version);
       badctl = 1;
    }
+   bacula_db_version = mdb->control.bdb_version;
    if (badctl) {
       V(mutex);
       return 0;
index 2dba3e01c0c55a35c845117f1341d9902653d2b1..a56e7d5fb5a3cf7b9686dee03c4d8a6e4af05036 100644 (file)
@@ -278,31 +278,31 @@ void db_list_client_records(void *jcr, B_DB *mdb, DB_LIST_HANDLER *sendit, void
 { }
 
 int db_list_sql_query(void *jcr, B_DB *mdb, char *query, DB_LIST_HANDLER *sendit, 
-                     void *ctx, int verbose, int full)
+                     void *ctx, int verbose, e_list_type type)
 {
    return 0;
 }
 
 void
-db_list_pool_records(void *jcr, B_DB *mdb, DB_LIST_HANDLER *sendit, void *ctx, int full
+db_list_pool_records(void *jcr, B_DB *mdb, DB_LIST_HANDLER *sendit, void *ctx, e_list_type type
 { }
 
 void
 db_list_media_records(void *jcr, B_DB *mdb, MEDIA_DBR *mdbr, 
-                     DB_LIST_HANDLER *sendit, void *ctx, int full)
+                     DB_LIST_HANDLER *sendit, void *ctx, e_list_type type)
 { }
 
 void db_list_jobmedia_records(void *jcr, B_DB *mdb, uint32_t JobId, 
-                             DB_LIST_HANDLER *sendit, void *ctx, int full)
+                             DB_LIST_HANDLER *sendit, void *ctx, e_list_type type)
 { }
 
 void
 db_list_job_records(void *jcr, B_DB *mdb, JOB_DBR *jr, DB_LIST_HANDLER *sendit, 
-                   void *ctx, int full)
+                   void *ctx, e_list_type type)
 { }
 
 void
-db_list_client_records(void *jcr, B_DB *mdb, DB_LIST_HANDLER *sendit, void *ctx, int full)
+db_list_client_records(void *jcr, B_DB *mdb, DB_LIST_HANDLER *sendit, void *ctx, e_list_type type)
 { }
 
 
index 37c09504a6dd1855e91d874c063a56828708b85b..a3c1da5bcb5ee5b5cf3d1ce691d1645f6b964d54 100644 (file)
@@ -48,7 +48,7 @@ typedef int (DB_RESULT_HANDLER)(void *, int, char **);
 
 #ifdef HAVE_SQLITE
 
-#define BDB_VERSION 5
+#define BDB_VERSION 6
 
 #include <sqlite.h>
 
@@ -57,70 +57,70 @@ struct sqlite {
    char dummy;
 };
 
-#define IS_NUM(x)             ((x) == 1)
-#define IS_NOT_NULL(x)        ((x) == 1)
+#define IS_NUM(x)            ((x) == 1)
+#define IS_NOT_NULL(x)       ((x) == 1)
 
 typedef struct s_sql_field {
-   char *name;                        /* name of column */
-   uint32_t length;                   /* length */
-   uint32_t max_length;               /* max length */
-   uint32_t type;                     /* type */
-   uint32_t flags;                    /* flags */
+   char *name;                       /* name of column */
+   uint32_t length;                  /* length */
+   uint32_t max_length;              /* max length */
+   uint32_t type;                    /* type */
+   uint32_t flags;                   /* flags */
 } SQL_FIELD;
 
 /*
  * This is the "real" definition that should only be
  * used inside sql.c and associated database interface
  * subroutines.
- *                    S Q L I T E
+ *                   S Q L I T E
  */
 typedef struct s_db {
-   BQUEUE bq;                         /* queue control */
-   brwlock_t lock;                    /* transaction lock */
+   BQUEUE bq;                        /* queue control */
+   brwlock_t lock;                   /* transaction lock */
    struct sqlite *db;
    char **result;
-   int nrow;                          /* nrow returned from sqlite */
-   int ncolumn;                       /* ncolum returned from sqlite */
-   int num_rows;                      /* used by code */
-   int row;                           /* seek row */
-   int have_insert_id;                /* do not have insert id */
-   int fields_defined;                /* set when fields defined */
-   int field;                         /* seek field */
-   SQL_FIELD **fields;                /* defined fields */
+   int nrow;                         /* nrow returned from sqlite */
+   int ncolumn;                      /* ncolum returned from sqlite */
+   int num_rows;                     /* used by code */
+   int row;                          /* seek row */
+   int have_insert_id;               /* do not have insert id */
+   int fields_defined;               /* set when fields defined */
+   int field;                        /* seek field */
+   SQL_FIELD **fields;               /* defined fields */
    int ref_count;
    char *db_name;
    char *db_user;
-   char *db_address;                  /* host name address */
-   char *db_socket;                   /* socket for local access */
+   char *db_address;                 /* host name address */
+   char *db_socket;                  /* socket for local access */
    char *db_password;
-   int  db_port;                      /* port for host name address */
+   int db_port;                      /* port for host name address */
    int connected;
-   char *sqlite_errmsg;               /* error message returned by sqlite */
-   POOLMEM *errmsg;                   /* nicely edited error message */
-   POOLMEM *cmd;                      /* SQL command string */
-   POOLMEM *cached_path;              /* cached path name */
-   int cached_path_len;               /* length of cached path */
-   uint32_t cached_path_id;           /* cached path id */
-   int transaction;                   /* transaction started */
-   int changes;                       /* changes during transaction */
-   POOLMEM *fname;                    /* Filename only */
-   POOLMEM *path;                     /* Path only */
-   POOLMEM *esc_name;                 /* Escaped file/path name */
-   int fnl;                           /* file name length */
-   int pnl;                           /* path name length */
+   char *sqlite_errmsg;              /* error message returned by sqlite */
+   POOLMEM *errmsg;                  /* nicely edited error message */
+   POOLMEM *cmd;                     /* SQL command string */
+   POOLMEM *cached_path;             /* cached path name */
+   int cached_path_len;              /* length of cached path */
+   uint32_t cached_path_id;          /* cached path id */
+   int transaction;                  /* transaction started */
+   int changes;                      /* changes during transaction */
+   POOLMEM *fname;                   /* Filename only */
+   POOLMEM *path;                    /* Path only */
+   POOLMEM *esc_name;                /* Escaped file/path name */
+   int fnl;                          /* file name length */
+   int pnl;                          /* path name length */
 } B_DB;
 
 
 /* 
  * "Generic" names for easier conversion   
  *
- *                    S Q L I T E
+ *                   S Q L I T E
  */
 #define sql_store_result(x)   x->result
 #define sql_free_result(x)    my_sqlite_free_table(x)
 #define sql_fetch_row(x)      my_sqlite_fetch_row(x)
 #define sql_query(x, y)       my_sqlite_query(x, y)
-#define sql_close(x)          sqlite_close((x)->db)  
+#define sql_close(x)         sqlite_close((x)->db)  
 #define sql_strerror(x)       (x)->sqlite_errmsg?(x)->sqlite_errmsg:"unknown"
 #define sql_num_rows(x)       (x)->nrow
 #define sql_data_seek(x, i)   (x)->row = i
@@ -129,7 +129,7 @@ typedef struct s_db {
 #define sql_field_seek(x, y)  my_sqlite_field_seek(x, y)
 #define sql_fetch_field(x)    my_sqlite_fetch_field(x)
 #define sql_num_fields(x)     (unsigned)((x)->ncolumn)
-#define SQL_ROW               char**   
+#define SQL_ROW              char**   
 
 
 
@@ -142,7 +142,7 @@ extern void my_sqlite_free_table(B_DB *mdb);
 
 #ifdef HAVE_MYSQL
 
-#define BDB_VERSION 5
+#define BDB_VERSION 6
 
 #include <mysql.h>
 
@@ -151,11 +151,11 @@ extern void my_sqlite_free_table(B_DB *mdb);
  * used inside sql.c and associated database interface
  * subroutines.
  *
- *                     M Y S Q L
+ *                    M Y S Q L
  */
 typedef struct s_db {
-   BQUEUE bq;                         /* queue control */
-   brwlock_t lock;                    /* transaction lock */
+   BQUEUE bq;                        /* queue control */
+   brwlock_t lock;                   /* transaction lock */
    MYSQL mysql;
    MYSQL *db;
    MYSQL_RES *result;
@@ -164,22 +164,22 @@ typedef struct s_db {
    char *db_name;
    char *db_user;
    char *db_password;
-   char *db_address;                  /* host address */
-   char *db_socket;                   /* socket for local access */
-   int db_port;                       /* port of host address */
-   int have_insert_id;                /* do have insert_id() */
+   char *db_address;                 /* host address */
+   char *db_socket;                  /* socket for local access */
+   int db_port;                      /* port of host address */
+   int have_insert_id;               /* do have insert_id() */
    int connected;
-   POOLMEM *errmsg;                   /* nicely edited error message */
-   POOLMEM *cmd;                      /* SQL command string */
+   POOLMEM *errmsg;                  /* nicely edited error message */
+   POOLMEM *cmd;                     /* SQL command string */
    POOLMEM *cached_path;
-   int cached_path_len;               /* length of cached path */
+   int cached_path_len;              /* length of cached path */
    uint32_t cached_path_id;
-   int changes;                       /* changes made to db */
-   POOLMEM *fname;                    /* Filename only */
-   POOLMEM *path;                     /* Path only */
-   POOLMEM *esc_name;                 /* Escaped file/path name */
-   int fnl;                           /* file name length */
-   int pnl;                           /* path name length */
+   int changes;                      /* changes made to db */
+   POOLMEM *fname;                   /* Filename only */
+   POOLMEM *path;                    /* Path only */
+   POOLMEM *esc_name;                /* Escaped file/path name */
+   int fnl;                          /* file name length */
+   int pnl;                          /* path name length */
 } B_DB;
 
 
@@ -188,7 +188,7 @@ typedef struct s_db {
 #define sql_free_result(x)    mysql_free_result((x)->result)
 #define sql_fetch_row(x)      mysql_fetch_row((x)->result)
 #define sql_query(x, y)       mysql_query((x)->db, y)
-#define sql_close(x)          mysql_close((x)->db)  
+#define sql_close(x)         mysql_close((x)->db)  
 #define sql_strerror(x)       mysql_error((x)->db)
 #define sql_num_rows(x)       mysql_num_rows((x)->result)
 #define sql_data_seek(x, i)   mysql_data_seek((x)->result, i)
@@ -197,8 +197,8 @@ typedef struct s_db {
 #define sql_field_seek(x, y)  mysql_field_seek((x)->result, y)
 #define sql_fetch_field(x)    mysql_fetch_field((x)->result)
 #define sql_num_fields(x)     mysql_num_fields((x)->result)
-#define SQL_ROW               MYSQL_ROW
-#define SQL_FIELD             MYSQL_FIELD
+#define SQL_ROW              MYSQL_ROW
+#define SQL_FIELD            MYSQL_FIELD
 
 #else  /* USE BACULA DB routines */
 
@@ -207,17 +207,17 @@ typedef struct s_db {
 /* Change this each time there is some incompatible
  * file format change!!!!
  */
-#define BDB_VERSION 1               /* file version number */
+#define BDB_VERSION 12               /* file version number */
 
 struct s_control {
-   int bdb_version;                   /* Version number */
-   uint32_t JobId;                    /* next Job Id */
-   uint32_t PoolId;                   /* next Pool Id */
-   uint32_t MediaId;                  /* next Media Id */
-   uint32_t JobMediaId;               /* next JobMedia Id */
-   uint32_t ClientId;                 /* next Client Id */
-   uint32_t FileSetId;                /* nest FileSet Id */
-   time_t time;                       /* time file written */
+   int bdb_version;                  /* Version number */
+   uint32_t JobId;                   /* next Job Id */
+   uint32_t PoolId;                  /* next Pool Id */
+   uint32_t MediaId;                 /* next Media Id */
+   uint32_t JobMediaId;              /* next JobMedia Id */
+   uint32_t ClientId;                /* next Client Id */
+   uint32_t FileSetId;               /* nest FileSet Id */
+   time_t time;                      /* time file written */
 };
 
 
@@ -225,23 +225,23 @@ struct s_control {
  *  Bacula internal DB
  */
 typedef struct s_db {
-   BQUEUE bq;                         /* queue control */
-/* pthread_mutex_t mutex;  */         /* single thread lock */
-   brwlock_t lock;                    /* transaction lock */
-   int ref_count;                     /* number of times opened */
-   struct s_control control;          /* control file structure */
-   int cfd;                           /* control file device */
-   FILE *jobfd;                       /* Jobs records file descriptor */
-   FILE *poolfd;                      /* Pool records fd */
-   FILE *mediafd;                     /* Media records fd */
-   FILE *jobmediafd;                  /* JobMedia records fd */
-   FILE *clientfd;                    /* Client records fd */
-   FILE *filesetfd;                   /* FileSet records fd */
-   char *db_name;                     /* name of database */
-   POOLMEM *errmsg;                   /* nicely edited error message */
-   POOLMEM *cmd;                      /* Command string */
+   BQUEUE bq;                        /* queue control */
+/* pthread_mutex_t mutex;  */        /* single thread lock */
+   brwlock_t lock;                   /* transaction lock */
+   int ref_count;                    /* number of times opened */
+   struct s_control control;         /* control file structure */
+   int cfd;                          /* control file device */
+   FILE *jobfd;                      /* Jobs records file descriptor */
+   FILE *poolfd;                     /* Pool records fd */
+   FILE *mediafd;                    /* Media records fd */
+   FILE *jobmediafd;                 /* JobMedia records fd */
+   FILE *clientfd;                   /* Client records fd */
+   FILE *filesetfd;                  /* FileSet records fd */
+   char *db_name;                    /* name of database */
+   POOLMEM *errmsg;                  /* nicely edited error message */
+   POOLMEM *cmd;                     /* Command string */
    POOLMEM *cached_path;
-   int cached_path_len;               /* length of cached path */
+   int cached_path_len;              /* length of cached path */
    uint32_t cached_path_id;
 } B_DB;
 
@@ -255,19 +255,21 @@ typedef struct s_db {
 #define DELETE_DB(jcr, db, cmd) DeleteDB(__FILE__, __LINE__, jcr, db, cmd)
 
 
-#else    /* not __SQL_C */
+#else   /* not __SQL_C */
 
 /* This is a "dummy" definition for use outside of sql.c
  */
-typedef struct s_db {     
-   int dummy;                         /* for SunOS compiler */
+typedef struct s_db {    
+   int dummy;                        /* for SunOS compiler */
 } B_DB;  
 
 #endif /*  __SQL_C */
 
+extern uint32_t bacula_db_version;
+
 /* ***FIXME*** FileId_t should be uint64_t */
 typedef uint32_t FileId_t;
-typedef uint32_t DBId_t;              /* general DB id type */
+typedef uint32_t DBId_t;             /* general DB id type */
 typedef uint32_t JobId_t;
       
 #define faddr_t long
@@ -281,18 +283,18 @@ typedef uint32_t JobId_t;
 /* Job record */
 struct JOB_DBR {
    JobId_t JobId;
-   char Job[MAX_NAME_LENGTH];         /* Job unique name */
-   char Name[MAX_NAME_LENGTH];        /* Job base name */
-   int Type;                          /* actually char(1) */
-   int Level;                         /* actually char(1) */
-   int JobStatus;                     /* actually char(1) */
-   uint32_t ClientId;                 /* Id of client */
-   uint32_t PoolId;                   /* Id of pool */
-   uint32_t FileSetId;                /* Id of FileSet */
-   time_t SchedTime;                  /* Time job scheduled */
-   time_t StartTime;                  /* Job start time */
-   time_t EndTime;                    /* Job termination time */
-   utime_t JobTDate;                  /* Backup time/date in seconds */
+   char Job[MAX_NAME_LENGTH];        /* Job unique name */
+   char Name[MAX_NAME_LENGTH];       /* Job base name */
+   int Type;                         /* actually char(1) */
+   int Level;                        /* actually char(1) */
+   int JobStatus;                    /* actually char(1) */
+   uint32_t ClientId;                /* Id of client */
+   uint32_t PoolId;                  /* Id of pool */
+   uint32_t FileSetId;               /* Id of FileSet */
+   time_t SchedTime;                 /* Time job scheduled */
+   time_t StartTime;                 /* Job start time */
+   time_t EndTime;                   /* Job termination time */
+   utime_t JobTDate;                 /* Backup time/date in seconds */
    uint32_t VolSessionId;
    uint32_t VolSessionTime;
    uint32_t JobFiles;
@@ -303,8 +305,8 @@ struct JOB_DBR {
    /* Note, FirstIndex, LastIndex, Start/End File and Block
     * are only used in the JobMedia record.
     */
-   uint32_t FirstIndex;               /* First index this Volume */
-   uint32_t LastIndex;                /* Last index this Volume */
+   uint32_t FirstIndex;              /* First index this Volume */
+   uint32_t LastIndex;               /* Last index this Volume */
    uint32_t StartFile;
    uint32_t EndFile;
    uint32_t StartBlock;
@@ -322,28 +324,28 @@ struct JOB_DBR {
  */
 /* JobMedia record */
 struct JOBMEDIA_DBR {
-   uint32_t JobMediaId;               /* record id */
-   JobId_t  JobId;                    /* JobId */
-   uint32_t MediaId;                  /* MediaId */
-   uint32_t FirstIndex;               /* First index this Volume */
-   uint32_t LastIndex;                /* Last index this Volume */
-   uint32_t StartFile;                /* File for start of data */
-   uint32_t EndFile;                  /* End file on Volume */
-   uint32_t StartBlock;               /* start block on tape */
-   uint32_t EndBlock;                 /* last block */
+   uint32_t JobMediaId;              /* record id */
+   JobId_t  JobId;                   /* JobId */
+   uint32_t MediaId;                 /* MediaId */
+   uint32_t FirstIndex;              /* First index this Volume */
+   uint32_t LastIndex;               /* Last index this Volume */
+   uint32_t StartFile;               /* File for start of data */
+   uint32_t EndFile;                 /* End file on Volume */
+   uint32_t StartBlock;              /* start block on tape */
+   uint32_t EndBlock;                /* last block */
 };
 
 
 /* Volume Parameter structure */
 struct VOL_PARAMS {
    char VolumeName[MAX_NAME_LENGTH];  /* Volume name */
-   uint32_t VolIndex;                 /* Volume seqence no. */ 
-   uint32_t FirstIndex;               /* First index this Volume */
-   uint32_t LastIndex;                /* Last index this Volume */
-   uint32_t StartFile;                /* File for start of data */
-   uint32_t EndFile;                  /* End file on Volume */
-   uint32_t StartBlock;               /* start block on tape */
-   uint32_t EndBlock;                 /* last block */
+   uint32_t VolIndex;                /* Volume seqence no. */ 
+   uint32_t FirstIndex;              /* First index this Volume */
+   uint32_t LastIndex;               /* Last index this Volume */
+   uint32_t StartFile;               /* File for start of data */
+   uint32_t EndFile;                 /* End file on Volume */
+   uint32_t StartBlock;              /* start block on tape */
+   uint32_t EndBlock;                /* last block */
 };
 
 
@@ -352,9 +354,9 @@ struct VOL_PARAMS {
  *  records (e.g. pathname, filename, fileattributes).
  */
 struct ATTR_DBR {
-   char *fname;                       /* full path & filename */
-   char *link;                        /* link if any */
-   char *attr;                        /* attributes statp */
+   char *fname;                      /* full path & filename */
+   char *link;                       /* link if any */
+   char *attr;                       /* attributes statp */
    uint32_t FileIndex;
    uint32_t Stream;
    JobId_t  JobId;
@@ -376,26 +378,26 @@ struct FILE_DBR {
    char LStat[256];
 /*   int Status; */
    char SIG[50];
-   int SigType;                       /* NO_SIG/MD5_SIG/SHA1_SIG */
+   int SigType;                      /* NO_SIG/MD5_SIG/SHA1_SIG */
 };
 
 /* Pool record -- same format as database */
 struct POOL_DBR {
    uint32_t PoolId;
-   char Name[MAX_NAME_LENGTH];        /* Pool name */
-   uint32_t NumVols;                  /* total number of volumes */
-   uint32_t MaxVols;                  /* max allowed volumes */
-   int UseOnce;                       /* set to use once only */
-   int UseCatalog;                    /* set to use catalog */
-   int AcceptAnyVolume;               /* set to accept any volume sequence */
-   int AutoPrune;                     /* set to prune automatically */
-   int Recycle;                       /* default Vol recycle flag */
-   utime_t  VolRetention;             /* retention period in seconds */
-   utime_t  VolUseDuration;           /* time in secs volume can be used */
-   uint32_t MaxVolJobs;               /* Max Jobs on Volume */
-   uint32_t MaxVolFiles;              /* Max files on Volume */
-   uint64_t MaxVolBytes;              /* Max bytes on Volume */
-   char PoolType[MAX_NAME_LENGTH];             
+   char Name[MAX_NAME_LENGTH];       /* Pool name */
+   uint32_t NumVols;                 /* total number of volumes */
+   uint32_t MaxVols;                 /* max allowed volumes */
+   int UseOnce;                      /* set to use once only */
+   int UseCatalog;                   /* set to use catalog */
+   int AcceptAnyVolume;              /* set to accept any volume sequence */
+   int AutoPrune;                    /* set to prune automatically */
+   int Recycle;                      /* default Vol recycle flag */
+   utime_t  VolRetention;            /* retention period in seconds */
+   utime_t  VolUseDuration;          /* time in secs volume can be used */
+   uint32_t MaxVolJobs;              /* Max Jobs on Volume */
+   uint32_t MaxVolFiles;             /* Max files on Volume */
+   uint64_t MaxVolBytes;             /* Max bytes on Volume */
+   char PoolType[MAX_NAME_LENGTH];            
    char LabelFormat[MAX_NAME_LENGTH];
    /* Extra stuff not in DB */
    faddr_t rec_addr;
@@ -403,34 +405,34 @@ struct POOL_DBR {
 
 /* Media record -- same as the database */
 struct MEDIA_DBR {
-   uint32_t MediaId;                  /* Unique volume id */
+   uint32_t MediaId;                 /* Unique volume id */
    char VolumeName[MAX_NAME_LENGTH];  /* Volume name */
    char MediaType[MAX_NAME_LENGTH];   /* Media type */
-   uint32_t PoolId;                   /* Pool id */
-   time_t   FirstWritten;             /* Time Volume first written */
-   time_t   LastWritten;              /* Time Volume last written */
-   time_t   LabelDate;                /* Date/Time Volume labeled */
-   uint32_t VolJobs;                  /* number of jobs on this medium */
-   uint32_t VolFiles;                 /* Number of files */
-   uint32_t VolBlocks;                /* Number of blocks */
-   uint32_t VolMounts;                /* Number of times mounted */
-   uint32_t VolErrors;                /* Number of read/write errors */
-   uint32_t VolWrites;                /* Number of writes */
-   uint32_t VolReads;                 /* Number of reads */
-   uint64_t VolBytes;                 /* Number of bytes written */
-   uint64_t MaxVolBytes;              /* Max bytes to write to Volume */
-   uint64_t VolCapacityBytes;         /* capacity estimate */
-   utime_t  VolRetention;             /* Volume retention in seconds */
-   utime_t  VolUseDuration;           /* time in secs volume can be used */
-   uint32_t MaxVolJobs;               /* Max Jobs on Volume */
-   uint32_t MaxVolFiles;              /* Max files on Volume */
-   int      Recycle;                  /* recycle yes/no */
-   int32_t  Slot;                     /* slot in changer */
-   char VolStatus[20];                /* Volume status */
+   uint32_t PoolId;                  /* Pool id */
+   time_t   FirstWritten;            /* Time Volume first written */
+   time_t   LastWritten;             /* Time Volume last written */
+   time_t   LabelDate;               /* Date/Time Volume labeled */
+   uint32_t VolJobs;                 /* number of jobs on this medium */
+   uint32_t VolFiles;                /* Number of files */
+   uint32_t VolBlocks;               /* Number of blocks */
+   uint32_t VolMounts;               /* Number of times mounted */
+   uint32_t VolErrors;               /* Number of read/write errors */
+   uint32_t VolWrites;               /* Number of writes */
+   uint32_t VolReads;                /* Number of reads */
+   uint64_t VolBytes;                /* Number of bytes written */
+   uint64_t MaxVolBytes;             /* Max bytes to write to Volume */
+   uint64_t VolCapacityBytes;        /* capacity estimate */
+   utime_t  VolRetention;            /* Volume retention in seconds */
+   utime_t  VolUseDuration;          /* time in secs volume can be used */
+   uint32_t MaxVolJobs;              /* Max Jobs on Volume */
+   uint32_t MaxVolFiles;             /* Max files on Volume */
+   int     Recycle;                  /* recycle yes/no */
+   int32_t  Slot;                    /* slot in changer */
+   char VolStatus[20];               /* Volume status */
    /* Extra stuff not in DB */
-   faddr_t rec_addr;                  /* found record address */
+   faddr_t rec_addr;                 /* found record address */
    /* Since the database returns times as strings, this is how we pass
-    *   them back.
+    *  them back.
     */
    char    cFirstWritten[MAX_TIME_LENGTH];  /* FirstWritten returned from DB */
    char    cLastWritten[MAX_TIME_LENGTH];  /* LastWritten returned from DB */
@@ -439,19 +441,26 @@ struct MEDIA_DBR {
 
 /* Client record -- same as the database */
 struct CLIENT_DBR {
-   uint32_t ClientId;                 /* Unique Client id */
+   uint32_t ClientId;                /* Unique Client id */
    int AutoPrune;
    utime_t FileRetention;
    utime_t JobRetention;
-   char Name[MAX_NAME_LENGTH];        /* Client name */
-   char Uname[256];                   /* Uname for client */
+   char Name[MAX_NAME_LENGTH];       /* Client name */
+   char Uname[256];                  /* Uname for client */
 };
 
 /* FileSet record -- same as the database */
 struct FILESET_DBR {
-   uint32_t FileSetId;                /* Unique FileSet id */
+   uint32_t FileSetId;               /* Unique FileSet id */
    char FileSet[MAX_NAME_LENGTH];     /* FileSet name */
-   char MD5[50];                      /* MD5 signature of include/exclude */
+   char MD5[50];                     /* MD5 signature of include/exclude */
+   time_t CreateTime;                /* date created */
+   /*
+    * This is where we return CreateTime
+    */
+   char cCreateTime[MAX_TIME_LENGTH]; /* CreateTime as returned from DB */
+   /* Not in DB but returned by db_create_fileset() */
+   bool created;                     /* set when record newly created */
 };
 
 
index e538d2ed1362646a4a19243e683be0d33dd39f8b..ff97be8fadbfc86af903ac0b69e3eab88bae25e5 100644 (file)
@@ -20,6 +20,8 @@ DROP TABLE IF EXISTS FileSave;
 DROP TABLE IF EXISTS FileSet;  
 DROP TABLE IF EXISTS Version;
 DROP TABLE IF EXISTS Counters;
+DROP TABLE IF EXISTS BaseFiles;
+DROP TABLE IF EXISTS UnsavedFiles;
 END-OF-DATA
 then
    echo "Deletion of Bacula MySQL tables succeeded."
index a6ffa0a139a87749b904ed8a843f8c2946b869ef..e9b63202f0ec9b9596cc96e4ecbfeb2cd3e7d21f 100644 (file)
@@ -27,7 +27,7 @@ CREATE TABLE File (
    FileIndex INTEGER UNSIGNED NOT NULL,
    JobId INTEGER UNSIGNED NOT NULL REFERENCES Job,
    PathId INTEGER UNSIGNED NOT NULL REFERENCES Path,
-   FilenameId INTEGER NOT NULL REFERENCES Filename,
+   FilenameId INTEGER UNSIGNED NOT NULL REFERENCES Filename,
    MarkId INTEGER UNSIGNED NOT NULL DEFAULT 0,
    LStat TINYBLOB NOT NULL,
    MD5 TINYBLOB NOT NULL,
@@ -42,7 +42,6 @@ CREATE TABLE Job (
    JobId INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
    Job TINYBLOB NOT NULL,
    Name TINYBLOB NOT NULL,
-   PurgedFiles TINYINT NOT NULL DEFAULT 0,
    Type BINARY(1) NOT NULL,
    Level BINARY(1) NOT NULL,
    ClientId INTEGER NOT NULL REFERENCES Client,
@@ -59,6 +58,8 @@ CREATE TABLE Job (
    JobMissingFiles INTEGER UNSIGNED NOT NULL,
    PoolId INTEGER UNSIGNED NOT NULL REFERENCES Pool,
    FileSetId INTEGER UNSIGNED NOT NULL REFERENCES FileSet,
+   PurgedFiles TINYINT NOT NULL DEFAULT 0,
+   HasBase TINYINT NOT NULL DEFAULT 0,
    PRIMARY KEY(JobId),
    INDEX (Name(128))
    );
@@ -68,6 +69,7 @@ CREATE TABLE FileSet (
    FileSetId INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
    FileSet TINYBLOB NOT NULL,
    MD5 TINYBLOB NOT NULL,
+   CreateTime DATETIME NOT NULL,
    PRIMARY KEY(FileSetId)
    );
 
@@ -81,6 +83,7 @@ CREATE TABLE JobMedia (
    EndFile INTEGER UNSIGNED NOT NULL,
    StartBlock INTEGER UNSIGNED NOT NULL,
    EndBlock INTEGER UNSIGNED NOT NULL,
+   VolIndex INTEGER UNSIGNED NOT NULL,
    PRIMARY KEY(JobMediaId),
    INDEX (JobId, MediaId)
    );
@@ -148,12 +151,29 @@ CREATE TABLE Client (
    PRIMARY KEY(ClientId)
    );
 
+CREATE TABLE BaseFiles (
+   BaseId INTEGER UNSIGNED AUTO_INCREMENT,
+   JobId INTEGER UNSIGNED NOT NULL REFERENCES Job,
+   FileId INTEGER UNSIGNED NOT NULL REFERENCES File,
+   FileIndex INTEGER UNSIGNED,
+   PRIMARY KEY(BaseId)
+   );
+
+CREATE TABLE UnsavedFiles (
+   UnsavedId INTEGER UNSIGNED AUTO_INCREMENT,
+   JobId INTEGER UNSIGNED NOT NULL REFERENCES Job,
+   PathId INTEGER UNSIGNED NOT NULL REFERENCES Path,
+   FilenameId INTEGER UNSIGNED NOT NULL REFERENCES Filename,
+   PRIMARY KEY (UnsavedId)
+   );
+
+
 CREATE TABLE Version (
    VersionId INTEGER UNSIGNED NOT NULL 
    );
 
 -- Initialize Version           
-INSERT INTO Version (VersionId) VALUES (5);
+INSERT INTO Version (VersionId) VALUES (6);
 
 CREATE TABLE Counters (
    Counter TINYBLOB NOT NULL,
@@ -164,40 +184,11 @@ CREATE TABLE Counters (
    WrapCounter TINYBLOB NOT NULL
    );
 
-## Experimental
-#CREATE TABLE FileSave (
-#   FileSaveId INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
-#   FileIndex INTEGER UNSIGNED NOT NULL,
-#   JobId INTEGER UNSIGNED NOT NULL REFERENCES Job,
-#   FileId INTEGER UNSIGNED NOT NULL REFERENCES File,
-#   VLStat TINYBLOB NOT NULL,
-#   PRIMARY KEY(FileSaveId),
-#   );
-
-# Experimental stuff below. Not used.
-# Invariant part of File
-#CREATE TABLE BaseFile (
-#   FileId INTEGER UNSIGNED AUTOINCREMENT,
-#   PathId INTEGER UNSIGNED REFERENCES Path NOT NULL,
-#   FilenameId INTEGER REFERENCES Filename NOT NULL,
-#   LStat VARCHAR(255) NOT NULL,
-#   MD5 VARCHAR(25) NOT NULL,
-#   PRIMARY KEY(FileId) 
-#   );
-
-# Variable part of File
-#CREATE TABLE FileSave (
-#   FileId INTEGER UNSIGNED REFERENCES BaseFile NOT NULL,
-#   FileIndex INTEGER UNSIGNED NOT NULL,
-#   JobId INTEGER UNSIGNED REFERENCES Job NOT NULL,
-#   PRIMARY KEY(FileId) 
-#   );
-
 
 END-OF-DATA
 then
-   echo "Creation of Bacula tables succeeded."
+   echo "Creation of Bacula MySQL tables succeeded."
 else
-   echo "Creation of Bacula tables failed."
+   echo "Creation of Bacula MySQL tables failed."
 fi
 exit 0
index 4859d35540aa10809d6849aed25ab9294c764320..2275f4659c8ed2ad0d37971c98d66c4b0a239c32 100644 (file)
@@ -28,7 +28,7 @@ CREATE TABLE File (
    FileIndex INTEGER UNSIGNED NOT NULL,
    JobId INTEGER UNSIGNED REFERENCES Job NOT NULL,
    PathId INTEGER UNSIGNED REFERENCES Path NOT NULL,
-   FilenameId INTEGER REFERENCES Filename NOT NULL,
+   FilenameId INTEGER UNSIGNED REFERENCES Filename NOT NULL,
    MarkId INTEGER UNSIGNED DEFAULT 0,
    LStat VARCHAR(255) NOT NULL,
    MD5 VARCHAR(255) NOT NULL,
@@ -43,7 +43,6 @@ CREATE TABLE Job (
    JobId INTEGER UNSIGNED NOT NULL,
    Job VARCHAR(128) NOT NULL,
    Name VARCHAR(128) NOT NULL,
-   PurgedFiles TINYINT DEFAULT 0,
    Type CHAR NOT NULL,
    Level CHAR NOT NULL,
    ClientId INTEGER REFERENCES Client DEFAULT 0,
@@ -60,6 +59,8 @@ CREATE TABLE Job (
    JobMissingFiles INTEGER UNSIGNED DEFAULT 0,
    PoolId INTEGER UNSIGNED REFERENCES Pool DEFAULT 0,
    FileSetId INTEGER UNSIGNED REFERENCES FileSet DEFAULT 0,
+   PurgedFiles TINYINT DEFAULT 0,
+   HasBase TINYINT DEFAULT 0,
    PRIMARY KEY(JobId) 
    );
 
@@ -69,6 +70,7 @@ CREATE TABLE FileSet (
    FileSetId INTEGER UNSIGNED AUTOINCREMENT,
    FileSet VARCHAR(128) NOT NULL,
    MD5 VARCHAR(25) NOT NULL,
+   CreateTime DATETIME DEFAULT 0,
    PRIMARY KEY(FileSetId)
    );
 
@@ -82,6 +84,7 @@ CREATE TABLE JobMedia (
    EndFile INTEGER UNSIGNED DEFAULT 0,
    StartBlock INTEGER UNSIGNED DEFAULT 0,
    EndBlock INTEGER UNSIGNED DEFAULT 0,
+   VolIndex INTEGER UNSIGNED DEFAULT 0,
    PRIMARY KEY(JobMediaId) 
    );
 
@@ -150,6 +153,23 @@ CREATE TABLE Client (
    PRIMARY KEY(ClientId)
    );
 
+CREATE TABLE BaseFiles (
+   BaseId INTEGER UNSIGNED AUTOINCREMENT,
+   JobId INTEGER UNSIGNED REFERENCES Job NOT NULL,
+   FileId INTEGER UNSIGNED REFERENCES File NOT NULL,
+   FileIndex INTEGER UNSIGNED,
+   PRIMARY KEY(BaseId)
+   );
+
+CREATE TABLE UnsavedFiles (
+   UnsavedId INTEGER UNSIGNED AUTOINCREMENT,
+   JobId INTEGER UNSIGNED REFERENCES Job NOT NULL,
+   PathId INTEGER UNSIGNED REFERENCES Path NOT NULL,
+   FilenameId INTEGER UNSIGNED REFERENCES Filename NOT NULL,
+   PRIMARY KEY (UnsavedId)
+   );
+
+
 CREATE TABLE NextId (
    id INTEGER UNSIGNED DEFAULT 0,
    TableName TEXT NOT NULL,
@@ -164,7 +184,7 @@ CREATE TABLE Version (
    );
 
 -- Initialize Version           
-INSERT INTO Version (VersionId) VALUES (5);
+INSERT INTO Version (VersionId) VALUES (6);
 
 CREATE TABLE Counters (
    Counter TEXT NOT NULL,     
index 2a860263400016201376272457a53d85528f5c2c..fff10ba24da79854e3297649bc978942f1b854cd 100644 (file)
@@ -352,7 +352,7 @@ list_dashes(B_DB *mdb, DB_LIST_HANDLER *send, void *ctx)
  * list on one line horizontally.      
  */
 void
-list_result(B_DB *mdb, DB_LIST_HANDLER *send, void *ctx, int full_list)
+list_result(B_DB *mdb, DB_LIST_HANDLER *send, void *ctx, e_list_type type)
 {
    SQL_FIELD *field;
    SQL_ROW row;
@@ -368,7 +368,7 @@ list_result(B_DB *mdb, DB_LIST_HANDLER *send, void *ctx, int full_list)
    for (i = 0; i < sql_num_fields(mdb); i++) {
       field = sql_fetch_field(mdb);
       col_len = strlen(field->name);
-      if (full_list) {
+      if (type == VERT_LIST) {
         if (col_len > max_len) {
            max_len = col_len;
         }
@@ -386,8 +386,8 @@ list_result(B_DB *mdb, DB_LIST_HANDLER *send, void *ctx, int full_list)
       }
    }
 
-   if (full_list) {
-      goto horizontal_list;
+   if (type == VERT_LIST) {
+      goto vertical_list;
    }
 
    list_dashes(mdb, send, ctx);
@@ -421,7 +421,7 @@ list_result(B_DB *mdb, DB_LIST_HANDLER *send, void *ctx, int full_list)
    list_dashes(mdb, send, ctx);
    return;
 
-horizontal_list:
+vertical_list:
    
    while ((row = sql_fetch_row(mdb)) != NULL) {
       sql_field_seek(mdb, 0);
index 1f292d364d091ce890f159aeabef7fdfab6452df..90822e26796a6d2c940b188b6dfb6e3eb2f70348 100644 (file)
@@ -81,14 +81,18 @@ int db_get_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cdbr);
 
 
 /* list.c */
-void db_list_pool_records(JCR *jcr, B_DB *db, DB_LIST_HANDLER sendit, void *ctx, int full);
-void db_list_job_records(JCR *jcr, B_DB *db, JOB_DBR *jr, DB_LIST_HANDLER sendit, void *ctx, int full);
+enum e_list_type {
+   HORZ_LIST,
+   VERT_LIST
+};
+void db_list_pool_records(JCR *jcr, B_DB *db, DB_LIST_HANDLER sendit, void *ctx, e_list_type type);
+void db_list_job_records(JCR *jcr, B_DB *db, JOB_DBR *jr, DB_LIST_HANDLER sendit, void *ctx, e_list_type type);
 void db_list_job_totals(JCR *jcr, B_DB *db, JOB_DBR *jr, DB_LIST_HANDLER sendit, void *ctx);
 void db_list_files_for_job(JCR *jcr, B_DB *db, uint32_t jobid, DB_LIST_HANDLER sendit, void *ctx);
-void db_list_media_records(JCR *jcr, B_DB *mdb, MEDIA_DBR *mdbr, DB_LIST_HANDLER *sendit, void *ctx, int full);
-void db_list_jobmedia_records(JCR *jcr, B_DB *mdb, uint32_t JobId, DB_LIST_HANDLER *sendit, void *ctx, int full);
-int  db_list_sql_query(JCR *jcr, B_DB *mdb, char *query, DB_LIST_HANDLER *sendit, void *ctx, int verbose, int full);
-void db_list_client_records(JCR *jcr, B_DB *mdb, DB_LIST_HANDLER *sendit, void *ctx, int full);
+void db_list_media_records(JCR *jcr, B_DB *mdb, MEDIA_DBR *mdbr, DB_LIST_HANDLER *sendit, void *ctx, e_list_type type);
+void db_list_jobmedia_records(JCR *jcr, B_DB *mdb, uint32_t JobId, DB_LIST_HANDLER *sendit, void *ctx, e_list_type type);
+int  db_list_sql_query(JCR *jcr, B_DB *mdb, char *query, DB_LIST_HANDLER *sendit, void *ctx, int verbose, e_list_type type);
+void db_list_client_records(JCR *jcr, B_DB *mdb, DB_LIST_HANDLER *sendit, void *ctx, e_list_type type);
 
 /* update.c */
 int  db_update_job_start_record(JCR *jcr, B_DB *db, JOB_DBR *jr);
index cf2dd5792dd4a3c86ab9b8c0313a531c21f51dcd..d8eb522741272dc6432082f05de91a76b42a5ff4 100644 (file)
 
 #if    HAVE_MYSQL | HAVE_SQLITE
 
-#ifdef HAVE_MYSQL
-char catalog_db[] = "MySQL";
-#else
-char catalog_db[] = "SQLite";
-#endif
+uint32_t bacula_db_version = 0;
 
 /* Forward referenced subroutines */
 void print_dashes(B_DB *mdb);
@@ -73,14 +69,13 @@ static int int_handler(void *ctx, int num_fields, char **row)
 /* Check that the tables correspond to the version we want */
 int check_tables_version(JCR *jcr, B_DB *mdb)
 {
-   uint32_t version;
    char *query = "SELECT VersionId FROM Version";
   
-   version = 0;
-   db_sql_query(mdb, query, int_handler, (void *)&version);
-   if (version != BDB_VERSION) {
+   bacula_db_version = 0;
+   db_sql_query(mdb, query, int_handler, (void *)&bacula_db_version);
+   if (bacula_db_version != BDB_VERSION) {
       Mmsg(&mdb->errmsg, "Version error for database \"%s\". Wanted %d, got %d\n",
-        mdb->db_name, BDB_VERSION, version);
+        mdb->db_name, BDB_VERSION, bacula_db_version);
       Jmsg(jcr, M_FATAL, 0, "%s", mdb->errmsg);
       return 0;
    }
index 55b7eb13a571c06e6fbc568758a5607b84b1282d..0cc5deb0e2a8ae4858926264b584b03338fdbcd3 100644 (file)
@@ -360,10 +360,12 @@ int db_create_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr)
 {
    SQL_ROW row;
    int stat;
+   struct tm tm;
 
    db_lock(mdb);
-   Mmsg(&mdb->cmd, "SELECT FileSetId FROM FileSet WHERE \
-FileSet='%s' and MD5='%s'", fsr->FileSet, fsr->MD5);
+   fsr->created = false;
+   Mmsg(&mdb->cmd, "SELECT FileSetId,CreateTime FROM FileSet WHERE "
+"FileSet='%s' AND MD5='%s'", fsr->FileSet, fsr->MD5);
 
    fsr->FileSetId = 0;
    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
@@ -383,6 +385,11 @@ FileSet='%s' and MD5='%s'", fsr->FileSet, fsr->MD5);
            return 0;
         }
         fsr->FileSetId = atoi(row[0]);
+        if (row[1] == NULL) {
+           fsr->cCreateTime[0] = 0;
+        } else {
+           bstrncpy(fsr->cCreateTime, row[1], sizeof(fsr->cCreateTime));
+        }
         sql_free_result(mdb);
         db_unlock(mdb);
         return 1;
@@ -390,9 +397,15 @@ FileSet='%s' and MD5='%s'", fsr->FileSet, fsr->MD5);
       sql_free_result(mdb);
    }
 
+   if (fsr->CreateTime == 0 && fsr->cCreateTime[0] == 0) {
+      fsr->CreateTime = time(NULL);
+   }
+   localtime_r(&fsr->CreateTime, &tm);
+   strftime(fsr->cCreateTime, sizeof(fsr->cCreateTime), "%Y-%m-%d %T", &tm);
+
    /* Must create it */
-   Mmsg(&mdb->cmd, "INSERT INTO FileSet (FileSet, MD5) VALUES \
-('%s', '%s')", fsr->FileSet, fsr->MD5);
+      Mmsg(&mdb->cmd, "INSERT INTO FileSet (FileSet,MD5,CreateTime) "
+"VALUES ('%s','%s','%s')", fsr->FileSet, fsr->MD5, fsr->cCreateTime);
 
    if (!INSERT_DB(jcr, mdb, mdb->cmd)) {
       Mmsg2(&mdb->errmsg, _("Create DB FileSet record %s failed. ERR=%s\n"),
@@ -402,6 +415,7 @@ FileSet='%s' and MD5='%s'", fsr->FileSet, fsr->MD5);
       stat = 0;
    } else {
       fsr->FileSetId = sql_insert_id(mdb);
+      fsr->created = true;
       stat = 1;
    }
 
index 1f7f8e12eb24290cbd5657425e3d10d485cd6fc9..8ed28dd9b6b47aa24855af556a3f4e34571c650a 100644 (file)
@@ -63,7 +63,7 @@ int
 db_find_job_start_time(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM **stime)
 {
    SQL_ROW row;
-   int JobId;
+   uint32_t JobId;
 
    db_lock(mdb);
 
@@ -73,16 +73,16 @@ db_find_job_start_time(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM **stime)
       /* Differential is since last Full backup */
       if (jr->Level == L_DIFFERENTIAL) {
         Mmsg(&mdb->cmd, 
-"SELECT JobId FROM Job WHERE JobStatus='T' AND Type='%c' AND \
-Level='%c' AND Name='%s' AND ClientId=%d AND FileSetId=%d \
-ORDER BY StartTime DESC LIMIT 1",
+"SELECT JobId FROM Job WHERE JobStatus='T' AND Type='%c' AND "
+"Level='%c' AND Name='%s' AND ClientId=%u AND FileSetId=%u "
+"ORDER BY StartTime DESC LIMIT 1",
           jr->Type, L_FULL, jr->Name, jr->ClientId, jr->FileSetId);
       /* Incremental is since last Full, Incremental, or Differential */
       } else if (jr->Level == L_INCREMENTAL) {
         Mmsg(&mdb->cmd, 
-"SELECT JobId FROM Job WHERE JobStatus='T' AND Type='%c' AND \
-Level IN ('%c','%c','%c') AND Name='%s' AND ClientId=%d \
-ORDER BY StartTime DESC LIMIT 1",
+"SELECT JobId FROM Job WHERE JobStatus='T' AND Type='%c' AND "
+"Level IN ('%c','%c','%c') AND Name='%s' AND ClientId=%u "
+"ORDER BY StartTime DESC LIMIT 1",
           jr->Type, L_INCREMENTAL, L_DIFFERENTIAL, L_FULL, jr->Name,
           jr->ClientId);
       } else {
@@ -92,12 +92,14 @@ ORDER BY StartTime DESC LIMIT 1",
       }
       Dmsg1(100, "Submitting: %s\n", mdb->cmd);
       if (!QUERY_DB(jcr, mdb, mdb->cmd)) {
-         Mmsg1(&mdb->errmsg, _("Query error for start time request: %s\n"), mdb->cmd);
+         Mmsg2(&mdb->errmsg, _("Query error for start time request: ERR=%s\nCMD=%s\n"), 
+           sql_strerror(mdb), mdb->cmd);
         db_unlock(mdb);
         return 0;
       }
       if ((row = sql_fetch_row(mdb)) == NULL) {
         sql_free_result(mdb);
+         Mmsg0(&mdb->errmsg, _("No Job Found.\n"));
         db_unlock(mdb);
         return 0;
       }
@@ -108,17 +110,18 @@ ORDER BY StartTime DESC LIMIT 1",
    }
 
    Dmsg1(100, "Submitting: %s\n", mdb->cmd);
-   Mmsg(&mdb->cmd, "SELECT StartTime FROM Job WHERE Job.JobId=%d", JobId);
+   Mmsg(&mdb->cmd, "SELECT StartTime FROM Job WHERE Job.JobId=%u", JobId);
 
    if (!QUERY_DB(jcr, mdb, mdb->cmd)) {
-      Mmsg1(&mdb->errmsg, _("Query error for start time request: %s\n"), mdb->cmd);
+      pm_strcpy(stime, "");                   /* set EOS */
+      Mmsg2(&mdb->errmsg, _("Query error for start time request: ERR=%s\nCMD=%s\n"),
+        sql_strerror(mdb),  mdb->cmd);
       db_unlock(mdb);
       return 0;
    }
 
    if ((row = sql_fetch_row(mdb)) == NULL) {
-      pm_strcpy(stime, "");                   /* set EOS */
-      Mmsg2(&mdb->errmsg, _("No Job found for JobId=%d: %s\n"), JobId, sql_strerror(mdb));
+      Mmsg2(&mdb->errmsg, _("No Job found for JobId=%u: ERR=%s\n"), JobId, sql_strerror(mdb));
       sql_free_result(mdb);
       db_unlock(mdb);
       return 0;
@@ -149,13 +152,13 @@ db_find_last_jobid(JCR *jcr, B_DB *mdb, JOB_DBR *jr)
    db_lock(mdb);
    if (jr->Level == L_VERIFY_CATALOG) {
       Mmsg(&mdb->cmd, 
-"SELECT JobId FROM Job WHERE Type='%c' AND Level='%c' AND Name='%s' AND \
-ClientId=%d ORDER BY StartTime DESC LIMIT 1",
+"SELECT JobId FROM Job WHERE Type='%c' AND Level='%c' AND Name='%s' AND "
+"ClientId=%u ORDER BY StartTime DESC LIMIT 1",
           JT_VERIFY, L_VERIFY_INIT, jr->Name, jr->ClientId);
    } else if (jr->Level == L_VERIFY_VOLUME_TO_CATALOG) {
       Mmsg(&mdb->cmd, 
-"SELECT JobId FROM Job WHERE Type='%c' AND \
-ClientId=%d ORDER BY StartTime DESC LIMIT 1",
+"SELECT JobId FROM Job WHERE Type='%c' AND "
+"ClientId=%u ORDER BY StartTime DESC LIMIT 1",
           JT_BACKUP, jr->ClientId);
    } else {
       Mmsg1(&mdb->errmsg, _("Unknown Job level=%c\n"), jr->Level);
index 1863060138f81bb2e3b0ce00c5a44a718f343b31..1adaa39e2e9bfff1b97d7053d25cdf9198af43bd 100644 (file)
@@ -623,11 +623,11 @@ int db_get_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr)
    db_lock(mdb);
    if (fsr->FileSetId != 0) {              /* find by id */
       Mmsg(&mdb->cmd, 
-           "SELECT FileSetId, FileSet, MD5 FROM FileSet "
+           "SELECT FileSetId,FileSet,MD5,CreateTime FROM FileSet "
            "WHERE FileSetId=%u", fsr->FileSetId);
    } else {                          /* find by name */
       Mmsg(&mdb->cmd, 
-           "SELECT FileSetId, FileSet, MD5 FROM FileSet "
+           "SELECT FileSetId,FileSet,CreateTime MD5,FROM FileSet "
            "WHERE FileSet='%s'", fsr->FileSet);
    }  
 
@@ -645,6 +645,7 @@ int db_get_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr)
         fsr->FileSetId = atoi(row[0]);
          bstrncpy(fsr->FileSet, row[1]!=NULL?row[1]:"", sizeof(fsr->FileSet));
          bstrncpy(fsr->MD5, row[2]!=NULL?row[2]:"", sizeof(fsr->MD5));
+         bstrncpy(fsr->cCreateTime, row[3]!=NULL?row[3]:"", sizeof(fsr->cCreateTime));
         stat = fsr->FileSetId;
       }
       sql_free_result(mdb);
index 7cf72d8209aeb3b8f24930e1e17b3a48c415c706..9ebd839f8017dab3d78acb6ac9713e750d88fd0e 100644 (file)
@@ -44,7 +44,7 @@
  */
 
 /* Imported subroutines */
-extern void list_result(B_DB *mdb, DB_LIST_HANDLER *sendit, void *ctx, int full_list);
+extern void list_result(B_DB *mdb, DB_LIST_HANDLER *sendit, void *ctx, e_list_type type);
 extern int QueryDB(char *file, int line, JCR *jcr, B_DB *db, char *select_cmd);
 
 
@@ -52,7 +52,7 @@ extern int QueryDB(char *file, int line, JCR *jcr, B_DB *db, char *select_cmd);
  * Submit general SQL query
  */
 int db_list_sql_query(JCR *jcr, B_DB *mdb, char *query, DB_LIST_HANDLER *sendit, 
-                     void *ctx, int verbose, int full)
+                     void *ctx, int verbose, e_list_type type)
 {
    db_lock(mdb);
    if (sql_query(mdb, query) != 0) {
@@ -67,7 +67,7 @@ int db_list_sql_query(JCR *jcr, B_DB *mdb, char *query, DB_LIST_HANDLER *sendit,
    mdb->result = sql_store_result(mdb);
 
    if (mdb->result) {
-      list_result(mdb, sendit, ctx, full);
+      list_result(mdb, sendit, ctx, type);
       sql_free_result(mdb);
    }
    db_unlock(mdb);
@@ -75,10 +75,10 @@ int db_list_sql_query(JCR *jcr, B_DB *mdb, char *query, DB_LIST_HANDLER *sendit,
 }
 
 void
-db_list_pool_records(JCR *jcr, B_DB *mdb, DB_LIST_HANDLER *sendit, void *ctx, int full
+db_list_pool_records(JCR *jcr, B_DB *mdb, DB_LIST_HANDLER *sendit, void *ctx, e_list_type type
 {
    db_lock(mdb);
-   if (full) {
+   if (type == VERT_LIST) {
       Mmsg(&mdb->cmd, "SELECT PoolId,Name,NumVols,MaxVols,UseOnce,UseCatalog,"
          "AcceptAnyVolume,VolRetention,VolUseDuration,MaxVolJobs,MaxVolBytes,"
          "AutoPrune,Recycle,PoolType,LabelFormat "
@@ -93,17 +93,17 @@ db_list_pool_records(JCR *jcr, B_DB *mdb, DB_LIST_HANDLER *sendit, void *ctx, in
       return;
    }
 
-   list_result(mdb, sendit, ctx, full);
+   list_result(mdb, sendit, ctx, type);
    
    sql_free_result(mdb);
    db_unlock(mdb);
 }
 
 void
-db_list_client_records(JCR *jcr, B_DB *mdb, DB_LIST_HANDLER *sendit, void *ctx, int full)
+db_list_client_records(JCR *jcr, B_DB *mdb, DB_LIST_HANDLER *sendit, void *ctx, e_list_type type)
 {
    db_lock(mdb);
-   if (full) {
+   if (type == VERT_LIST) {
       Mmsg(&mdb->cmd, "SELECT ClientId,Name,Uname,AutoPrune,FileRetention,"
          "FileRetention,JobRetention "
          "FROM Client ORDER BY ClientId");
@@ -117,7 +117,7 @@ db_list_client_records(JCR *jcr, B_DB *mdb, DB_LIST_HANDLER *sendit, void *ctx,
       return;
    }
 
-   list_result(mdb, sendit, ctx, full);
+   list_result(mdb, sendit, ctx, type);
    
    sql_free_result(mdb);
    db_unlock(mdb);
@@ -130,10 +130,10 @@ db_list_client_records(JCR *jcr, B_DB *mdb, DB_LIST_HANDLER *sendit, void *ctx,
  */
 void
 db_list_media_records(JCR *jcr, B_DB *mdb, MEDIA_DBR *mdbr, 
-                     DB_LIST_HANDLER *sendit, void *ctx, int full)
+                     DB_LIST_HANDLER *sendit, void *ctx, e_list_type type)
 {
    db_lock(mdb);
-   if (full) {
+   if (type == VERT_LIST) {
       if (mdbr->VolumeName[0] != 0) {
          Mmsg(&mdb->cmd, "SELECT MediaId,VolumeName,Slot,PoolId,"
             "MediaType,FirstWritten,LastWritten,LabelDate,VolJobs,"
@@ -166,17 +166,17 @@ db_list_media_records(JCR *jcr, B_DB *mdb, MEDIA_DBR *mdbr,
       return;
    }
 
-   list_result(mdb, sendit, ctx, full);
+   list_result(mdb, sendit, ctx, type);
    
    sql_free_result(mdb);
    db_unlock(mdb);
 }
 
 void db_list_jobmedia_records(JCR *jcr, B_DB *mdb, uint32_t JobId, 
-                             DB_LIST_HANDLER *sendit, void *ctx, int full)
+                             DB_LIST_HANDLER *sendit, void *ctx, e_list_type type)
 {
    db_lock(mdb);
-   if (full) {
+   if (type == VERT_LIST) {
       if (JobId > 0) {                  /* do by JobId */
          Mmsg(&mdb->cmd, "SELECT JobMediaId,JobId,MediaId,Media.VolumeName,"
             "FirstIndex,LastIndex,StartFile,EndFile,StartBlock,EndBlock "
@@ -203,7 +203,7 @@ void db_list_jobmedia_records(JCR *jcr, B_DB *mdb, uint32_t JobId,
       return;
    }
 
-   list_result(mdb, sendit, ctx, full);
+   list_result(mdb, sendit, ctx, type);
    
    sql_free_result(mdb);
    db_unlock(mdb);
@@ -219,10 +219,10 @@ void db_list_jobmedia_records(JCR *jcr, B_DB *mdb, uint32_t JobId,
  */
 void
 db_list_job_records(JCR *jcr, B_DB *mdb, JOB_DBR *jr, DB_LIST_HANDLER *sendit, 
-                   void *ctx, int full)
+                   void *ctx, e_list_type type)
 {
    db_lock(mdb);
-   if (full) {
+   if (type == VERT_LIST) {
       if (jr->JobId == 0 && jr->Job[0] == 0) {
         Mmsg(&mdb->cmd, 
             "SELECT JobId,Job,Job.Name,PurgedFiles,Type,Level,"
@@ -258,7 +258,7 @@ db_list_job_records(JCR *jcr, B_DB *mdb, JOB_DBR *jr, DB_LIST_HANDLER *sendit,
       db_unlock(mdb);
       return;
    }
-   list_result(mdb, sendit, ctx, full);
+   list_result(mdb, sendit, ctx, type);
    
    sql_free_result(mdb);
    db_unlock(mdb);
@@ -282,7 +282,7 @@ AS Files, sum(JobBytes) AS Bytes, Name AS Job FROM Job GROUP BY Name");
       return;
    }
 
-   list_result(mdb, sendit, ctx, 0);
+   list_result(mdb, sendit, ctx, HORZ_LIST);
    
    sql_free_result(mdb);
 
@@ -295,7 +295,7 @@ AS Files,sum(JobBytes) As Bytes FROM Job");
       return;
    }
 
-   list_result(mdb, sendit, ctx, 0);
+   list_result(mdb, sendit, ctx, HORZ_LIST);
    
    sql_free_result(mdb);
    db_unlock(mdb);
@@ -317,7 +317,7 @@ AND Path.PathId=File.PathId",
       return;
    }
 
-   list_result(mdb, sendit, ctx, 0);
+   list_result(mdb, sendit, ctx, HORZ_LIST);
    
    sql_free_result(mdb);
    db_unlock(mdb);
index d0bc1144db98aafb17af46766423e25c3f4443b2..928a43f864150b5d0b6839ae4176f741711af7e3 100644 (file)
@@ -406,7 +406,7 @@ list_dashes(B_DB *mdb, DB_LIST_HANDLER *send, void *ctx)
  * list on one line horizontally.      
  */
 void
-list_result(B_DB *mdb, DB_LIST_HANDLER *send, void *ctx, int full_list)
+list_result(B_DB *mdb, DB_LIST_HANDLER *send, void *ctx, e_list_type type)
 {
    SQL_FIELD *field;
    SQL_ROW row;
@@ -422,7 +422,7 @@ list_result(B_DB *mdb, DB_LIST_HANDLER *send, void *ctx, int full_list)
    for (i = 0; i < sql_num_fields(mdb); i++) {
       field = sql_fetch_field(mdb);
       col_len = strlen(field->name);
-      if (full_list) {
+      if (type == VERT_LIST) {
         if (col_len > max_len) {
            max_len = col_len;
         }
@@ -440,8 +440,8 @@ list_result(B_DB *mdb, DB_LIST_HANDLER *send, void *ctx, int full_list)
       }
    }
 
-   if (full_list) {
-      goto horizontal_list;
+   if (type == VERT_LIST) {
+      goto vertical_list;
    }
 
    list_dashes(mdb, send, ctx);
@@ -475,7 +475,7 @@ list_result(B_DB *mdb, DB_LIST_HANDLER *send, void *ctx, int full_list)
    list_dashes(mdb, send, ctx);
    return;
 
-horizontal_list:
+vertical_list:
    
    while ((row = sql_fetch_row(mdb)) != NULL) {
       sql_field_seek(mdb, 0);
index 64268bd653c972db850f5222a193e07e8e52eec1..a05ee37f0f0e5e0eed323f321bf8dade1fb5dc39 100644 (file)
@@ -76,7 +76,7 @@ static int sleepcmd(FILE *input, BSOCK *UA_sock);
 
 static void usage()
 {
-   fprintf(stderr,
+   fprintf(stderr, _(
 "\nVersion: " VERSION " (" BDATE ")\n\n"
 "Usage: console [-s] [-c config_file] [-d debug_level] [config_file]\n"
 "       -c <file>   set configuration file to file\n"
@@ -84,7 +84,7 @@ static void usage()
 "       -s          no signals\n"
 "       -t          test - read configuration and exit\n"
 "       -?          print this message.\n"  
-"\n");
+"\n"));
 
    exit(1);
 }
@@ -196,7 +196,7 @@ static void read_and_process_input(FILE *input, BSOCK *UA_sock)
         at_prompt = FALSE;
         /* @ => internal command for us */
          if (UA_sock->msg[0] == '@') {
-           parse_command_args(UA_sock->msg, args, &argc, argk, argv);
+           parse_args(UA_sock->msg, args, &argc, argk, argv, MAX_CMD_ARGS);
            if (!do_a_command(input, UA_sock)) {
               break;
            }
@@ -313,8 +313,8 @@ int main(int argc, char *argv[])
    }
    UnlockRes();
    if (ndir == 0) {
-      Emsg1(M_ERROR_TERM, 0, "No Director resource defined in %s\n\
-Without that I don't how to speak to the Director :-(\n", configfile);
+      Emsg1(M_ERROR_TERM, 0, _("No Director resource defined in %s\n\
+Without that I don't how to speak to the Director :-(\n"), configfile);
    }
 
    if (test_config) {
@@ -327,20 +327,20 @@ Without that I don't how to speak to the Director :-(\n", configfile);
    if (ndir > 1) {
       UA_sock = init_bsock(NULL, 0, "", "", 0);
 try_again:
-      sendit("Available Directors:\n");
+      sendit(_("Available Directors:\n"));
       LockRes();
       ndir = 0;
       for (dir = NULL; (dir = (DIRRES *)GetNextRes(R_DIRECTOR, (RES *)dir)); ) {
-         fprintf(output, "%d  %s at %s:%d\n", 1+ndir++, dir->hdr.name, dir->address,
+         fprintf(output, _("%d  %s at %s:%d\n"), 1+ndir++, dir->hdr.name, dir->address,
            dir->DIRport);
       }
       UnlockRes();
-      if (get_cmd(stdin, "Select Director: ", UA_sock, 600) < 0) {
+      if (get_cmd(stdin, _("Select Director: "), UA_sock, 600) < 0) {
         return 1;
       }
       item = atoi(UA_sock->msg);
       if (item < 0 || item > ndir) {
-         sendit("You must enter a number between 1 and %d\n", ndir);
+         sendit(_("You must enter a number between 1 and %d\n"), ndir);
         goto try_again;
       }
       LockRes();
@@ -357,7 +357,7 @@ try_again:
    }
       
 
-   sendit("Connecting to Director %s:%d\n", dir->address,dir->DIRport);
+   sendit(_("Connecting to Director %s:%d\n"), dir->address,dir->DIRport);
    UA_sock = bnet_connect(NULL, 5, 15, "Director daemon", dir->address, 
                          NULL, dir->DIRport, 0);
    if (UA_sock == NULL) {
@@ -512,16 +512,16 @@ static int inputcmd(FILE *input, BSOCK *UA_sock)
    FILE *fd;
 
    if (argc > 2) {
-      sendit("Too many arguments.\n");
+      sendit(_("Too many arguments.\n"));
       return 0;
    }
    if (argc == 1) {
-      sendit("First argument must be a filename.\n");
+      sendit(_("First argument must be a filename.\n"));
       return 0;
    }
    fd = fopen(argk[1], "r");
    if (!fd) {
-      sendit("Cannot open file. ERR=%s\n", strerror(errno));
+      sendit(_("Cannot open file. ERR=%s\n"), strerror(errno));
       return 0; 
    }
    read_and_process_input(fd, UA_sock);
@@ -548,7 +548,7 @@ static int do_outputcmd(FILE *input, BSOCK *UA_sock)
    char *mode = "a+";
 
    if (argc > 3) {
-      sendit("Too many arguments.\n");
+      sendit(_("Too many arguments.\n"));
       return 1;
    }
    if (argc == 1) {
@@ -564,7 +564,7 @@ static int do_outputcmd(FILE *input, BSOCK *UA_sock)
    }
    fd = fopen(argk[1], mode);
    if (!fd) {
-      sendit("Cannot open file. ERR=%s\n", strerror(errno));
+      sendit(_("Cannot open file. ERR=%s\n"), strerror(errno));
       return 1; 
    }
    output = fd;
index 30208e19caf5c3386e4c731b6e200cc2bbad470d..bb8a01711a635abfd0e1dc5e7517f4f5c0f138ce 100644 (file)
@@ -30,7 +30,7 @@ SVRSRCS = dird.c admin.c authenticate.c \
          recycle.c restore.c run_conf.c \
          scheduler.c sql_cmds.c \
          ua_cmds.c ua_dotcmds.c \
-         ua_db_query.c ua_retention.c \
+         ua_query.c ua_retention.c \
          ua_input.c ua_label.c ua_output.c ua_prune.c \
          ua_purge.c ua_restore.c ua_run.c \
          ua_select.c ua_server.c \
@@ -43,7 +43,7 @@ SVROBJS = dird.o admin.o authenticate.o \
          recycle.o restore.o run_conf.o \
          scheduler.o sql_cmds.o \
          ua_cmds.o ua_dotcmds.o \
-         ua_db_query.o ua_retention.o \
+         ua_query.o ua_retention.o \
          ua_input.o ua_label.o ua_output.o ua_prune.o \
          ua_purge.o ua_restore.o ua_run.o \
          ua_select.o ua_server.o \
index 277537a8569611a8c36f8eed97e1684da7a61406..ea8782c279d8d79459b399ce541ee378a502c53a 100644 (file)
@@ -52,7 +52,7 @@ static char EndBackup[] = "2801 End Backup Job TermCode=%d JobFiles=%u "
 
 
 /* Forward referenced functions */
-static void backup_cleanup(JCR *jcr, int TermCode, char *since);
+static void backup_cleanup(JCR *jcr, int TermCode, char *since, FILESET_DBR *fsr);
 static int wait_for_job_termination(JCR *jcr);              
 
 /* External functions */
@@ -83,24 +83,28 @@ int do_backup(JCR *jcr)
     * Get or Create FileSet record
     */
    memset(&fsr, 0, sizeof(fsr));
-   strcpy(fsr.FileSet, jcr->fileset->hdr.name);
+   bstrncpy(fsr.FileSet, jcr->fileset->hdr.name, sizeof(fsr.FileSet));
    if (jcr->fileset->have_MD5) {
       struct MD5Context md5c;
       unsigned char signature[16];
       memcpy(&md5c, &jcr->fileset->md5c, sizeof(md5c));
       MD5Final(signature, &md5c);
       bin_to_base64(fsr.MD5, (char *)signature, 16); /* encode 16 bytes */
-      strcpy(jcr->fileset->MD5, fsr.MD5);
+      bstrncpy(jcr->fileset->MD5, fsr.MD5, sizeof(jcr->fileset->MD5));
    } else {
       Jmsg(jcr, M_WARNING, 0, _("FileSet MD5 signature not found.\n"));
    }
    if (!db_create_fileset_record(jcr, jcr->db, &fsr)) {
-      Jmsg(jcr, M_ERROR, 0, _("Could not create FileSet record. ERR=%s\n"), 
-        db_strerror(jcr->db));
+      Jmsg(jcr, M_ERROR, 0, _("Could not create FileSet \"%s\" record. ERR=%s\n"), 
+        fsr.FileSet, db_strerror(jcr->db));
       goto bail_out;
    }   
    jcr->jr.FileSetId = fsr.FileSetId;
-   Dmsg2(119, "Created FileSet %s record %d\n", jcr->fileset->hdr.name, 
+   if (fsr.created) {
+      Jmsg(jcr, M_INFO, 0, _("Created new FileSet record \"%s\" at %s\n"), 
+        fsr.FileSet, fsr.cCreateTime);
+   }
+   Dmsg2(119, "Created FileSet %s record %u\n", jcr->fileset->hdr.name, 
       jcr->jr.FileSetId);
 
    /* Look up the last
@@ -116,10 +120,13 @@ int do_backup(JCR *jcr)
         /* Look up start time of last job */
         jcr->jr.JobId = 0;
         if (!db_find_job_start_time(jcr, jcr->db, &jcr->jr, &jcr->stime)) {
+            Jmsg(jcr, M_INFO, 0, "%s", db_strerror(jcr->db));
             Jmsg(jcr, M_INFO, 0, _("No prior or suitable FULL backup found. Doing FULL backup.\n"));
+            bsnprintf(since, sizeof(since), " (upgraded from %s)", 
+              level_to_str(jcr->jr.Level));
            jcr->JobLevel = jcr->jr.Level = L_FULL;
         } else {
-            strcpy(since, ", since=");
+            bstrncpy(since, ", since=", sizeof(since));
            bstrncat(since, jcr->stime, sizeof(since));
         }
          Dmsg1(115, "Last start time = %s\n", jcr->stime);
@@ -136,17 +143,17 @@ int do_backup(JCR *jcr)
    jcr->fname = (char *) get_pool_memory(PM_FNAME);
 
    /* Print Job Start message */
-   Jmsg(jcr, M_INFO, 0, _("Start Backup JobId %d, Job=%s\n"),
+   Jmsg(jcr, M_INFO, 0, _("Start Backup JobId %u, Job=%s\n"),
        jcr->JobId, jcr->Job);
 
    /* 
     * Get the Pool record  
     */
    memset(&pr, 0, sizeof(pr));
-   strcpy(pr.Name, jcr->pool->hdr.name);
+   bstrncpy(pr.Name, jcr->pool->hdr.name, sizeof(pr.Name));
    while (!db_get_pool_record(jcr, jcr->db, &pr)) { /* get by Name */
       /* Try to create the pool */
-      if (create_pool(jcr, jcr->db, jcr->pool, 1) < 0) {
+      if (create_pool(jcr, jcr->db, jcr->pool, POOL_OP_CREATE) < 0) {
          Jmsg(jcr, M_FATAL, 0, _("Pool %s not in database. %s"), pr.Name, 
            db_strerror(jcr->db));
         goto bail_out;
@@ -209,7 +216,7 @@ int do_backup(JCR *jcr)
    }
    bnet_fsend(fd, storaddr, jcr->store->address, jcr->store->SDDport,
              jcr->store->enable_ssl);
-   if (!response(fd, OKstore, "Storage", 1)) {
+   if (!response(jcr, fd, OKstore, "Storage", DISPLAY_ERROR)) {
       goto bail_out;
    }
 
@@ -236,19 +243,19 @@ int do_backup(JCR *jcr)
         goto bail_out;
    }
    Dmsg1(120, ">filed: %s", fd->msg);
-   if (!response(fd, OKlevel, "Level", 1)) {
+   if (!response(jcr, fd, OKlevel, "Level", DISPLAY_ERROR)) {
       goto bail_out;
    }
 
    /* Send backup command */
    bnet_fsend(fd, backupcmd);
-   if (!response(fd, OKbackup, "backup", 1)) {
+   if (!response(jcr, fd, OKbackup, "backup", DISPLAY_ERROR)) {
       goto bail_out;
    }
 
    /* Pickup Job termination data */       
    stat = wait_for_job_termination(jcr);
-   backup_cleanup(jcr, stat, since);
+   backup_cleanup(jcr, stat, since, &fsr);
    return 1;
 
 bail_out:
@@ -256,7 +263,7 @@ bail_out:
       free_pool_memory(jcr->stime);
       jcr->stime = NULL;
    }
-   backup_cleanup(jcr, JS_ErrorTerminated, since);
+   backup_cleanup(jcr, JS_ErrorTerminated, since, &fsr);
    return 0;
 
 }
@@ -309,7 +316,7 @@ static int wait_for_job_termination(JCR *jcr)
 /*
  * Release resources allocated during backup.
  */
-static void backup_cleanup(JCR *jcr, int TermCode, char *since)
+static void backup_cleanup(JCR *jcr, int TermCode, char *since, FILESET_DBR *fsr) 
 {
    char sdt[50], edt[50];
    char ec1[30], ec2[30], ec3[30], compress[50];
@@ -332,7 +339,7 @@ static void backup_cleanup(JCR *jcr, int TermCode, char *since)
       set_jcr_job_status(jcr, JS_ErrorTerminated);
    }
 
-   strcpy(mr.VolumeName, jcr->VolumeName);
+   bstrncpy(mr.VolumeName, jcr->VolumeName, sizeof(mr.VolumeName));
    if (!db_get_media_record(jcr, jcr->db, &mr)) {
       Jmsg(jcr, M_WARNING, 0, _("Error getting Media record for Volume \"%s\": ERR=%s"), 
         mr.VolumeName, db_strerror(jcr->db));
@@ -440,13 +447,13 @@ static void backup_cleanup(JCR *jcr, int TermCode, char *since)
    }
 
    if (jcr->ReadBytes == 0) {
-      strcpy(compress, "None");
+      bstrncpy(compress, "None", sizeof(compress));
    } else {
       compression = (double)100 - 100.0 * ((double)jcr->JobBytes / (double)jcr->ReadBytes);
       if (compression < 0.5) {
-         strcpy(compress, "None");
+         bstrncpy(compress, "None", sizeof(compress));
       } else {
-         sprintf(compress, "%.1f %%", (float)compression);
+         bsnprintf(compress, sizeof(compress), "%.1f %%", (float)compression);
       }
    }
    jobstatus_to_ascii(jcr->FDJobStatus, fd_term_msg, sizeof(fd_term_msg));
@@ -455,9 +462,9 @@ static void backup_cleanup(JCR *jcr, int TermCode, char *since)
    Jmsg(jcr, msg_type, 0, _("Bacula " VERSION " (" LSMDATE "): %s\n\
 JobId:                  %d\n\
 Job:                    %s\n\
-FileSet:                %s\n\
 Backup Level:           %s%s\n\
 Client:                 %s\n\
+FileSet:                \"%s\" %s\n\
 Start time:             %s\n\
 End time:               %s\n\
 Files Written:          %s\n\
@@ -475,9 +482,9 @@ Termination:            %s\n\n"),
        edt,
        jcr->jr.JobId,
        jcr->jr.Job,
-       jcr->fileset->hdr.name,
        level_to_str(jcr->JobLevel), since,
        jcr->client->hdr.name,
+       jcr->fileset->hdr.name, fsr->cCreateTime,
        sdt,
        edt,
        edit_uint64_with_commas(jcr->jr.JobFiles, ec1),
index ae26f68e16ca32e9f7a0ddbb79527a7aac89a139..0df270545d8ec17f8706ef3b3c6979807cb7cb7c 100644 (file)
@@ -370,13 +370,13 @@ Without that I don't know who I am :-(\n"), configfile);
                            catalog->db_password, catalog->db_address,
                            catalog->db_port, catalog->db_socket);
         if (!db_open_database(NULL, db)) {
-            Jmsg(NULL, M_FATAL,  0, "%s", db_strerror(db));
+           OK = FALSE;             /* Error message already printed */
         } else {
            /* If a pool is defined for this job, create the pool DB       
             *  record if it is not already created. 
             */
            if (job->pool) {
-              create_pool(NULL, db, job->pool, 0);  /* update request */
+              create_pool(NULL, db, job->pool, POOL_OP_UPDATE);  /* update request */
            }
            db_close_database(NULL, db);
         }
index 62531405afcbc01badfd810d629289c6ad9a0697..f9f28dca6c4f01491e27795d669b90ffc0c687d6 100644 (file)
 /*
  * Resource codes -- they must be sequential for indexing   
  */
-#define R_FIRST                       1001
-
-#define R_DIRECTOR                    1001
-#define R_CLIENT                      1002
-#define R_JOB                         1003
-#define R_STORAGE                     1004
-#define R_CATALOG                     1005
-#define R_SCHEDULE                    1006
-#define R_FILESET                     1007
-#define R_GROUP                       1008
-#define R_POOL                        1009
-#define R_MSGS                        1010
-#define R_COUNTER                     1011
-#define R_CONSOLE                     1012
-
-#define R_LAST                        R_CONSOLE
+#define R_FIRST               1001
+
+#define R_DIRECTOR            1001
+#define R_CLIENT              1002
+#define R_JOB                 1003
+#define R_STORAGE             1004
+#define R_CATALOG             1005
+#define R_SCHEDULE            1006
+#define R_FILESET             1007
+#define R_GROUP               1008
+#define R_POOL                1009
+#define R_MSGS                1010
+#define R_COUNTER             1011
+#define R_CONSOLE             1012
+
+#define R_LAST                R_CONSOLE
 
 /*
  * Some resource attributes
  */
-#define R_NAME                        1020
-#define R_ADDRESS                     1021
-#define R_PASSWORD                    1022
-#define R_TYPE                        1023
-#define R_BACKUP                      1024
+#define R_NAME                1020
+#define R_ADDRESS             1021
+#define R_PASSWORD            1022
+#define R_TYPE                1023
+#define R_BACKUP              1024
 
 
 /* Used for certain KeyWord tables */
@@ -99,7 +99,7 @@ struct DIRRES {
    char *pid_directory;               /* PidDirectory */
    char *subsys_directory;            /* SubsysDirectory */
    int require_ssl;                   /* Require SSL for all connections */
-   struct s_res_msgs *messages;       /* Daemon message handler */
+   MSGS *messages;                    /* Daemon message handler */
    uint32_t MaxConcurrentJobs;        /* Max concurrent jobs for whole director */
    utime_t FDConnectTimeout;          /* timeout for connect in seconds */
    utime_t SDConnectTimeout;          /* timeout in seconds */
@@ -306,19 +306,19 @@ struct POOL {
  * resource structure definitions.
  */
 union URES {
-   DIRRES               res_dir;
-   CONRES               res_con;
-   CLIENT               res_client;
-   STORE                res_store;
-   CAT                  res_cat;
-   JOB                  res_job;
-   FILESET              res_fs;
-   SCHED                res_sch;
-   GROUP                res_group;
-   POOL                 res_pool;
-   MSGS                 res_msgs;
-   COUNTER              res_counter;
-   RES hdr;
+   DIRRES     res_dir;
+   CONRES     res_con;
+   CLIENT     res_client;
+   STORE      res_store;
+   CAT        res_cat;
+   JOB        res_job;
+   FILESET    res_fs;
+   SCHED      res_sch;
+   GROUP      res_group;
+   POOL       res_pool;
+   MSGS       res_msgs;
+   COUNTER    res_counter;
+   RES        hdr;
 };
 
 
index 7b2440e450551853d25f01a3128f23efc8589055..2d08770bc42209224d74752cb3f26b10f58cfe97 100644 (file)
@@ -233,10 +233,10 @@ static int send_list(JCR *jcr, int list)
    }
    bnet_sig(fd, BNET_EOD);           /* end of data */
    if (list == INC_LIST) {
-      if (!response(fd, OKinc, "Include", 1)) {
+      if (!response(jcr, fd, OKinc, "Include", DISPLAY_ERROR)) {
         goto bail_out;
       }
-   } else if (!response(fd, OKexc, "Exclude", 1)) {
+   } else if (!response(jcr, fd, OKexc, "Exclude", DISPLAY_ERROR)) {
        goto bail_out;
    }
    return 1;
index 37fd753b7fcb7705bfb84db5e22460d8d73973c3..0e5eceae069241d47010c9545910289b4cb41ccf 100644 (file)
@@ -209,7 +209,7 @@ static char *find_msg_start(char *msg)
  *  Returns: 0 on failure
  *          1 on success
  */
-int response(BSOCK *fd, char *resp, char *cmd, int prtmsg)
+int response(JCR *jcr, BSOCK *fd, char *resp, char *cmd, e_prtmsg prtmsg)
 {
    int n;
 
@@ -221,13 +221,13 @@ int response(BSOCK *fd, char *resp, char *cmd, int prtmsg)
       if (strcmp(fd->msg, resp) == 0) {
         return 1;
       }
-      if (prtmsg) {
-         Emsg3(M_FATAL, 0, _("FD gave bad response to %s command: wanted %s got: %s\n"),
+      if (prtmsg == DISPLAY_ERROR) {
+         Jmsg(jcr, M_FATAL, 0, _("FD gave bad response to %s command: wanted %s got: %s\n"),
            cmd, resp, fd->msg);
       }
       return 0;
    } 
-   Emsg2(M_FATAL, 0, _("Socket error from Filed on %s command: ERR=%s\n"),
+   Jmsg(jcr, M_FATAL, 0, _("Socket error from Filed on %s command: ERR=%s\n"),
         cmd, bnet_strerror(fd));
    return 0;
 }
index 78836276184bf4710c31f218f07793fa7abe08e2..4dcfe3f156fea4310679284b98cfca699bd3f1de 100644 (file)
@@ -297,7 +297,7 @@ void store_inc(LEX *lc, struct res_items *item, int index, int pass)
         }                                 
       }
       /* Note, MD5Final is done in backup.c */
-   } else { /* pass 1 */
+   } else { /* pass 2 */
       while (lex_get_token(lc, T_ALL) != T_EOB) 
         {}
    }
@@ -318,6 +318,10 @@ void store_finc(LEX *lc, struct res_items *item, int index, int pass)
    int token, i;
    INCEXE *incexe;
 
+   if (!res_all.res_fs.have_MD5) {
+      MD5Init(&res_all.res_fs.md5c);
+      res_all.res_fs.have_MD5 = TRUE;
+   }
    res_all.res_fs.finclude = TRUE;
    token = lex_get_token(lc, T_ALL);           
    if (token != T_BOB) {
index 808b63c42bd00b5c0ab8d81d1744728f14570bee..e3289d9b9d8402f620877e122bb9e09f77d976cc 100644 (file)
@@ -156,7 +156,7 @@ int start_storage_daemon_job(JCR *jcr)
       device_name_len + media_type_len + pool_type_len + pool_name_len);
    bnet_fsend(sd, use_device, device_name, media_type, pool_name, pool_type);
    Dmsg1(110, ">stored: %s", sd->msg);
-   status = response(sd, OK_device, "Use Device", 0);
+   status = response(jcr, sd, OK_device, "Use Device", NO_DISPLAY);
    if (!status) {
       pm_strcpy(&pool_type, sd->msg); /* save message */
       Jmsg(jcr, M_FATAL, 0, _("\n"
index 388511b0bf3c90a2830c385275a471f162af06f5..8a4fcd1dc19c00258a7dbc7eaad949dd92f5c159 100644 (file)
@@ -48,13 +48,20 @@ extern char *level_to_str(int level);
 
 /* fd_cmds.c */
 extern int connect_to_file_daemon(JCR *jcr, int retry_interval,
-                                  int max_retry_time, int verbose);
+                                 int max_retry_time, int verbose);
 extern int send_include_list(JCR *jcr);
 extern int send_exclude_list(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);
 extern int put_file_into_catalog(JCR *jcr, long file_index, char *fname, 
-                          char *link, char *attr, int stream);
+                         char *link, char *attr, int stream);
+
+/* getmsg.c */
+enum e_prtmsg {
+   DISPLAY_ERROR,
+   NO_DISPLAY
+};
+extern int response(JCR *jcr, BSOCK *fd, char *resp, char *cmd, e_prtmsg prtmsg);
 
 /* job.c */
 extern void set_jcr_defaults(JCR *jcr, JOB *job);
@@ -67,11 +74,10 @@ extern void mount_request(JCR *jcr, BSOCK *bs, char *buf);
 
 /* msgchan.c */
 extern int connect_to_storage_daemon(JCR *jcr, int retry_interval,    
-                              int max_retry_time, int verbose);
+                             int max_retry_time, int verbose);
 extern int start_storage_daemon_job(JCR *jcr);
 extern int start_storage_daemon_message_thread(JCR *jcr);
 extern int bget_dirmsg(BSOCK *bs);
-extern int response(BSOCK *fd, char *resp, char *cmd, int prtmsg);
 extern void wait_for_storage_daemon_termination(JCR *jcr);
 
 /* newvol.c */
@@ -83,7 +89,11 @@ int do_a_dot_command(UAContext *ua, char *cmd);
 int qmessagescmd(UAContext *ua, char *cmd);
 int open_db(UAContext *ua);
 void close_db(UAContext *ua);
-int create_pool(JCR *jcr, B_DB *db, POOL *pool, int create);
+enum e_pool_op {
+   POOL_OP_UPDATE, 
+   POOL_OP_CREATE
+};
+int create_pool(JCR *jcr, B_DB *db, POOL *pool, e_pool_op op);
 void set_pool_dbr_defaults_in_media_dbr(MEDIA_DBR *mr, POOL_DBR *pr);
 
 /* ua_input.c */
@@ -102,28 +112,28 @@ void prtit(void *ctx, char *msg);
 void bsendmsg(void *sock, char *fmt, ...);
 
 /* ua_select.c */
-STORE   *select_storage_resource(UAContext *ua);
-JOB     *select_job_resource(UAContext *ua);
-JOB     *select_restore_job_resource(UAContext *ua);
-CLIENT  *select_client_resource(UAContext *ua);
+STORE  *select_storage_resource(UAContext *ua);
+JOB    *select_job_resource(UAContext *ua);
+JOB    *select_restore_job_resource(UAContext *ua);
+CLIENT *select_client_resource(UAContext *ua);
 FILESET *select_fileset_resource(UAContext *ua);
-int     select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr);
-int     select_media_dbr(UAContext *ua, MEDIA_DBR *mr);
-int     select_pool_dbr(UAContext *ua, POOL_DBR *pr);
-int     select_client_dbr(UAContext *ua, CLIENT_DBR *cr);
-
-void    start_prompt(UAContext *ua, char *msg);
-void    add_prompt(UAContext *ua, char *prompt);
-int     do_prompt(UAContext *ua, char *automsg, char *msg, char *prompt, int max_prompt);
-CAT    *get_catalog_resource(UAContext *ua);           
+int    select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr);
+int    select_media_dbr(UAContext *ua, MEDIA_DBR *mr);
+int    select_pool_dbr(UAContext *ua, POOL_DBR *pr);
+int    select_client_dbr(UAContext *ua, CLIENT_DBR *cr);
+
+void   start_prompt(UAContext *ua, char *msg);
+void   add_prompt(UAContext *ua, char *prompt);
+int    do_prompt(UAContext *ua, char *automsg, char *msg, char *prompt, int max_prompt);
+CAT    *get_catalog_resource(UAContext *ua);          
 STORE  *get_storage_resource(UAContext *ua, int use_default);
-int     get_media_type(UAContext *ua, char *MediaType, int max_media);
-int     get_pool_dbr(UAContext *ua, POOL_DBR *pr);
-int     get_client_dbr(UAContext *ua, CLIENT_DBR *cr);
+int    get_media_type(UAContext *ua, char *MediaType, int max_media);
+int    get_pool_dbr(UAContext *ua, POOL_DBR *pr);
+int    get_client_dbr(UAContext *ua, CLIENT_DBR *cr);
 POOL   *get_pool_resource(UAContext *ua);
 POOL   *select_pool_resource(UAContext *ua);
 CLIENT *get_client_resource(UAContext *ua);
-int     get_job_dbr(UAContext *ua, JOB_DBR *jr);
+int    get_job_dbr(UAContext *ua, JOB_DBR *jr);
 
 int find_arg_keyword(UAContext *ua, char **list);
 int find_arg(UAContext *ua, char *keyword);
index 11b09a2ad7bc15a50f746a3aa9583ed7d4a987d4..0cecb5b45f19d41042293bd9836ae8fc3f9cbda8 100644 (file)
@@ -41,7 +41,7 @@ SELECT Job.JobId, StartTime AS JobStartTime, VolumeName, Client.Name AS ClientNa
 :List last 20 Full Backups for a Client:
 *Enter Client name:
 Select Job.JobId,Client.Name as Client,StartTime,JobFiles,JobBytes,
-JobMedia.StartFile as VolFile, VolumeName
+JobMedia.StartFile as VolFile,VolumeName
  FROM Client,Job,JobMedia,Media
  WHERE Client.Name='%1'
  AND Client.ClientId=Job.ClientId
index 38dc16ba16542e4695cad7f4a577725aef6a3fea..a866320387d4c596975de99816b07db731d83bf8 100644 (file)
@@ -192,7 +192,7 @@ int do_restore(JCR *jcr)
    }
    bnet_fsend(fd, storaddr, jcr->store->address, jcr->store->SDDport);
    Dmsg1(6, "dird>filed: %s\n", fd->msg);
-   if (!response(fd, OKstore, "Storage", 1)) {
+   if (!response(jcr, fd, OKstore, "Storage", DISPLAY_ERROR)) {
       restore_cleanup(jcr, JS_ErrorTerminated);
       return 0;
    }
@@ -219,7 +219,7 @@ int do_restore(JCR *jcr)
                rjr.VolSessionId, rjr.VolSessionTime, 
                rjr.StartFile, rjr.EndFile, rjr.StartBlock, 
                rjr.EndBlock);
-      if (!response(fd, OKsession, "Session", 1)) {
+      if (!response(jcr, fd, OKsession, "Session", DISPLAY_ERROR)) {
         restore_cleanup(jcr, JS_ErrorTerminated);
         return 0;
       }
@@ -246,7 +246,7 @@ int do_restore(JCR *jcr)
    bnet_fsend(fd, restorecmd, replace, where);
    unbash_spaces(where);
 
-   if (!response(fd, OKrestore, "Restore", 1)) {
+   if (!response(jcr, fd, OKrestore, "Restore", DISPLAY_ERROR)) {
       restore_cleanup(jcr, JS_ErrorTerminated);
       return 0;
    }
@@ -385,7 +385,7 @@ static int send_bootstrap_file(JCR *jcr)
    }
    bnet_sig(fd, BNET_EOD);
    fclose(bs);
-   if (!response(fd, OKbootstrap, "Bootstrap", 1)) {
+   if (!response(jcr, fd, OKbootstrap, "Bootstrap", DISPLAY_ERROR)) {
       set_jcr_job_status(jcr, JS_ErrorTerminated);
       return 0;
    }
index e77ad0497825204782f0df64a9df8b4bc23f8d38..1e4d0a2e7cf74c5c12720a5606f281efa7dcd97e 100644 (file)
@@ -227,7 +227,7 @@ char *uar_sel_all_temp1 = "SELECT * FROM temp1";
 
 /* Select filesets for this Client */
 char *uar_sel_fileset = 
-   "SELECT FileSet.FileSetId,FileSet.FileSet,FileSet.MD5 FROM Job,"
+   "SELECT FileSet.FileSetId,FileSet.FileSet,FileSet.CreateTime FROM Job,"
    "Client,FileSet WHERE Job.FileSetId=FileSet.FileSetId "
    "AND Job.ClientId=%u AND Client.ClientId=%u "
    "GROUP BY FileSet.FileSetId ORDER BY FileSet.FileSetId";
index 73aa81f9ff988fa38cbe6b339c2269053fc8df37..f46992802be9aeb8a90879bebb9ec230d59050cc 100644 (file)
@@ -29,7 +29,7 @@
 #define __UA_H_ 1
 
 
-typedef struct s_ua_context {
+struct UAContext {
    BSOCK *UA_sock;
    BSOCK *sd;
    JCR *jcr;
@@ -50,6 +50,6 @@ typedef struct s_ua_context {
    int verbose;                       /* set for normal UA verbosity */
    uint32_t pint32_val;               /* positive integer */
    int32_t  int32_val;                /* positive/negative */
-} UAContext;
+};          
 
 #endif
index f39890d5739ef83cc6bdb5a31d2234e00ca5cc4a..62a6ada498f294e4cbf5decf22f4922e7ba02462 100644 (file)
@@ -211,7 +211,7 @@ static int addcmd(UAContext *ua, char *cmd)
 
    /* Get media type */
    if ((store = get_storage_resource(ua, 0)) != NULL) {
-      strcpy(mr.MediaType, store->media_type);
+      bstrncpy(mr.MediaType, store->media_type, sizeof(mr.MediaType));
    } else if (!get_media_type(ua, mr.MediaType, sizeof(mr.MediaType))) {
       return 1;
    }
@@ -223,7 +223,7 @@ static int addcmd(UAContext *ua, char *cmd)
    }
    for (;;) {
       char buf[100]; 
-      sprintf(buf, _("Enter number of Volumes to create. 0=>fixed name. Max=%d: "), max);
+      bsnprintf(buf, sizeof(buf), _("Enter number of Volumes to create. 0=>fixed name. Max=%d: "), max);
       if (!get_pint(ua, buf)) {
         return 1;
       }
@@ -257,7 +257,7 @@ getVolName:
       goto getVolName;
    }
 
-   strcpy(name, ua->cmd);
+   bstrncpy(name, ua->cmd, sizeof(name));
    if (num > 0) {
       strcat(name, "%04d");
 
@@ -286,7 +286,7 @@ getVolName:
           
    set_pool_dbr_defaults_in_media_dbr(&mr, &pr);
    for (i=startnum; i < num+startnum; i++) { 
-      sprintf(mr.VolumeName, name, i);
+      bsnprintf(mr.VolumeName, sizeof(mr.VolumeName), name, i);
       mr.Slot = slot++;
       Dmsg1(200, "Create Volume %s\n", mr.VolumeName);
       if (!db_create_media_record(ua->jcr, ua->db, &mr)) {
@@ -484,10 +484,10 @@ static int cancelcmd(UAContext *ua, char *cmd)
  *   depending on if we are creating the Pool or we are
  *   simply bringing it into agreement with the resource (updage).
  */
-void set_pooldbr_from_poolres(POOL_DBR *pr, POOL *pool, int create)
+static void set_pooldbr_from_poolres(POOL_DBR *pr, POOL *pool, e_pool_op op)
 {
    strcpy(pr->PoolType, pool->pool_type);
-   if (create) {
+   if (op == POOL_OP_CREATE) {
       pr->MaxVols = pool->max_volumes;
       pr->NumVols = 0;
    } else {         /* update pool */
@@ -523,7 +523,7 @@ void set_pooldbr_from_poolres(POOL_DBR *pr, POOL *pool, int create)
  *          1  record created
  */
 
-int create_pool(JCR *jcr, B_DB *db, POOL *pool, int create)
+int create_pool(JCR *jcr, B_DB *db, POOL *pool, e_pool_op op)
 {
    POOL_DBR  pr;
 
@@ -533,14 +533,14 @@ int create_pool(JCR *jcr, B_DB *db, POOL *pool, int create)
 
    if (db_get_pool_record(jcr, db, &pr)) {
       /* Pool Exists */
-      if (!create) {  /* update request */
-        set_pooldbr_from_poolres(&pr, pool, 0);
+      if (op == POOL_OP_UPDATE) {  /* update request */
+        set_pooldbr_from_poolres(&pr, pool, op);
         db_update_pool_record(jcr, db, &pr);
       }
       return 0;                      /* exists */
    }
 
-   set_pooldbr_from_poolres(&pr, pool, 1);
+   set_pooldbr_from_poolres(&pr, pool, op);
 
    if (!db_create_pool_record(jcr, db, &pr)) {
       return -1;                     /* error */
@@ -567,7 +567,7 @@ static int createcmd(UAContext *ua, char *cmd)
       return 1;
    }
 
-   switch (create_pool(ua->jcr, ua->db, pool, 1)) {
+   switch (create_pool(ua->jcr, ua->db, pool, POOL_OP_CREATE)) {
    case 0:
       bsendmsg(ua, _("Error: Pool %s already exists.\n\
 Use update to change it.\n"), pool->hdr.name);
@@ -911,7 +911,7 @@ static int update_pool(UAContext *ua)
       return 0;
    }
 
-   set_pooldbr_from_poolres(&pr, pool, 0); /* update */
+   set_pooldbr_from_poolres(&pr, pool, POOL_OP_UPDATE); /* update */
 
    id = db_update_pool_record(ua->jcr, ua->db, &pr);
    if (id <= 0) {
@@ -920,7 +920,7 @@ static int update_pool(UAContext *ua)
    }
    query = get_pool_memory(PM_MESSAGE);
    Mmsg(&query, list_pool, pr.PoolId);
-   db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, 0);
+   db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST);
    free_pool_memory(query);
    bsendmsg(ua, _("Pool DB record updated from resource.\n"));
    return 1;
index 646d34919590d9246c0816f451539d67301b4d52..65505a716ce8084ca9dd31cc16428a6668e65867 100644 (file)
@@ -131,5 +131,5 @@ int get_yesno(UAContext *ua, char *prompt)
 
 void parse_ua_args(UAContext *ua)
 {
-   return parse_command_args(ua->cmd, ua->args, &ua->argc, ua->argk, ua->argv);
+   parse_args(ua->cmd, ua->args, &ua->argc, ua->argk, ua->argv, MAX_CMD_ARGS);
 }
index a2edf426bbfe2150fe8b33456515bf9dcf5436a2..76045c70387c6e624b58cfe82b637dd8da731994 100644 (file)
@@ -46,7 +46,7 @@ extern brwlock_t con_lock;
 /* Imported functions */
 
 /* Forward referenced functions */
-static int do_listcmd(UAContext *ua, char *cmd, int llist);
+static int do_listcmd(UAContext *ua, char *cmd, e_list_type llist);
 
 
 /*
@@ -194,16 +194,16 @@ int showcmd(UAContext *ua, char *cmd)
 /* Do long or full listing */
 int llistcmd(UAContext *ua, char *cmd)
 {
-   return do_listcmd(ua, cmd, 1);
+   return do_listcmd(ua, cmd, VERT_LIST);
 }
 
 /* Do short or summary listing */
 int listcmd(UAContext *ua, char *cmd)
 {
-   return do_listcmd(ua, cmd, 0);
+   return do_listcmd(ua, cmd, HORZ_LIST);
 }
 
-static int do_listcmd(UAContext *ua, char *cmd, int llist) 
+static int do_listcmd(UAContext *ua, char *cmd, e_list_type llist)
 {
    POOLMEM *VolumeName;
    int jobid, n;
diff --git a/bacula/src/dird/ua_query.c b/bacula/src/dird/ua_query.c
new file mode 100644 (file)
index 0000000..8cffb37
--- /dev/null
@@ -0,0 +1,287 @@
+/*
+ *
+ *   Bacula Director -- User Agent Database Query Commands
+ *
+ *     Kern Sibbald, December MMI
+ *
+ *   Version $Id$
+ */
+
+/*
+   Copyright (C) 2000-2003 Kern Sibbald and John Walker
+
+   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.
+
+   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.
+
+ */
+
+#include "bacula.h"
+#include "dird.h"
+
+extern DIRRES *director;
+
+static char *substitute_prompts(UAContext *ua, 
+                      char *query, char **prompt, int nprompt);
+
+/*
+ * Read a file containing SQL queries and prompt
+ *  the user to select which one.
+ *
+ *   File format:
+ *   # => comment
+ *   :prompt for query
+ *   *prompt for subst %1
+ *   *prompt for subst %2
+ *   ...
+ *   SQL statement possibly terminated by ;
+ *   :next query prompt
+ */
+int querycmd(UAContext *ua, char *cmd)
+{
+   FILE *fd;
+   POOLMEM *query = get_pool_memory(PM_MESSAGE);
+   char line[1000];
+   int i, item, len;
+   char *prompt[9];
+   int nprompt;
+   char *query_file = director->query_file;
+   
+   if (!open_db(ua)) {
+      free_pool_memory(query);
+      return 1;
+   }
+   if ((fd=fopen(query_file, "r")) == NULL) {
+      bsendmsg(ua, "Could not open %s: ERR=%s\n", query_file,
+        strerror(errno));
+      free_pool_memory(query);
+      return 1;
+   }
+
+   start_prompt(ua, _("Available queries:\n"));
+   while (fgets(line, sizeof(line), fd) != NULL) {
+      if (line[0] == ':') {
+        strip_trailing_junk(line);
+        add_prompt(ua, line+1);
+      }
+   }
+   if ((item=do_prompt(ua, "", _("Choose a query"), NULL, 0)) < 0) {
+      fclose(fd);
+      free_pool_memory(query);
+      return 1;
+   }
+   rewind(fd);
+   i = -1;
+   while (fgets(line, sizeof(line), fd) != NULL) {
+      if (line[0] == ':') {
+        i++;
+      }
+      if (i == item) {
+        break;
+      }
+   }
+   if (i != item) {
+      bsendmsg(ua, _("Could not find query.\n"));
+      fclose(fd);
+      free_pool_memory(query);
+      return 1;
+   }
+   query[0] = 0;
+   for (i=0; i<9; i++) {
+      prompt[i] = NULL;
+   }
+   nprompt = 0;
+   while (fgets(line, sizeof(line), fd) != NULL) {
+      if (line[0] == '#') {
+        continue;
+      }
+      if (line[0] == ':') {
+        break;
+      }
+      strip_trailing_junk(line);
+      len = strlen(line);
+      if (line[0] == '*') {            /* prompt */
+        if (nprompt >= 9) {
+            bsendmsg(ua, _("Too many prompts in query, max is 9.\n"));
+        } else {
+            line[len++] = ' ';
+           line[len] = 0;
+           prompt[nprompt++] = bstrdup(line+1);
+           continue;
+        }
+      }  
+      query = check_pool_memory_size(query, len + 1);
+      if (*query != 0) {
+         strcat(query, " ");
+      }
+      strcat(query, line);
+      if (line[len-1] != ';') {
+        continue;
+      }
+      line[len-1] = 0;            /* zap ; */
+      if (query[0] != 0) {
+        query = substitute_prompts(ua, query, prompt, nprompt);
+         Dmsg1(100, "Query2=%s\n", query);
+         if (query[0] == '!') {
+           db_list_sql_query(ua->jcr, ua->db, query+1, prtit, ua, 0, VERT_LIST);
+        } else if (!db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST)) {
+            bsendmsg(ua, "%s\n", query);
+        }
+        query[0] = 0;
+      }
+   } /* end while */
+
+   if (query[0] != 0) {
+      query = substitute_prompts(ua, query, prompt, nprompt);
+      Dmsg1(100, "Query2=%s\n", query);
+         if (query[0] == '!') {
+           db_list_sql_query(ua->jcr, ua->db, query+1, prtit, ua, 0, VERT_LIST);
+        } else if (!db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST)) {
+            bsendmsg(ua, "%s\n", query);
+        }
+   }
+   free_pool_memory(query);
+   for (i=0; i<nprompt; i++) {
+      free(prompt[i]);
+   }
+   return 1;
+}
+
+static char *substitute_prompts(UAContext *ua, 
+                      char *query, char **prompt, int nprompt)
+{
+   char *new_query, *p, *q, *o;
+   int i, n, len, olen;
+   char *subst[9];
+
+   if (nprompt == 0) {
+      return query;
+   }
+   for (i=0; i<9; i++) {
+      subst[i] = NULL;
+   }
+   new_query = (char *)get_pool_memory(PM_MESSAGE);
+   new_query = (char *)check_pool_memory_size(new_query, strlen(query) +100);
+   o = new_query;
+   olen = 0;
+   for (q=query; (p=strchr(q, '%')); ) {
+      if (p) {
+        while (q < p) {              /* copy up to % */
+           *o++ = *q++;
+           olen++;
+        }
+        p++;
+        switch (*p) {
+         case '1':
+         case '2':
+         case '3':
+         case '4':
+         case '5':
+         case '6':
+         case '7':
+         case '8':
+         case '9':
+            n = (int)(*p) - (int)'1';
+           if (prompt[n]) {
+              if (!subst[n]) {
+                 if (!get_cmd(ua, prompt[n])) {
+                    q += 2;
+                    break;
+                 }
+              }
+              len = strlen(ua->cmd);
+              p = (char *)malloc(len * 2 + 1);
+              db_escape_string(p, ua->cmd, len);
+              subst[n] = p;
+              o = (char *)check_pool_memory_size(o, olen + strlen(p) + 1);
+              while (*p) {
+                 *o++ = *p++;
+                 olen++;
+              }
+           } else {
+               bsendmsg(ua, _("Warning prompt %d missing.\n"), n+1);
+           }
+           q += 2;
+           break;
+         case '%':
+            *o++ = '%';
+           olen++;
+           q += 2;
+           break;
+        default:
+            *o++ = '%';
+           olen++;
+           q++;
+           break;
+        }
+      }
+   }
+   o = (char *)check_pool_memory_size(o, olen + strlen(q) + 1);
+   while (*q) {
+      *o++ = *q++;
+   }
+   *o = 0;
+   for (i=0; i<9; i++) {
+      if (subst[i]) {
+        free(subst[i]);
+      }
+   }
+   free_pool_memory(query);
+   return new_query;
+}
+
+/*
+ * Get general SQL query for Catalog
+ */
+int sqlquerycmd(UAContext *ua, char *cmd)
+{
+   POOLMEM *query = get_pool_memory(PM_MESSAGE);
+   int len;
+   char *msg;
+
+   if (!open_db(ua)) {
+      free_pool_memory(query);
+      return 1;
+   }
+   *query = 0;
+
+   bsendmsg(ua, _("Entering SQL query mode.\n\
+Terminate each query with a semicolon.\n\
+Terminate query mode with a blank line.\n"));
+   msg = "Enter SQL query: ";
+   while (get_cmd(ua, msg)) {
+      len = strlen(ua->cmd);
+      Dmsg2(400, "len=%d cmd=%s:\n", len, ua->cmd);
+      if (len == 0) {
+        break;
+      }
+      query = check_pool_memory_size(query, len + 1);
+      if (*query != 0) {
+         strcat(query, " ");
+      }
+      strcat(query, ua->cmd);
+      if (ua->cmd[len-1] == ';') {
+        ua->cmd[len-1] = 0;          /* zap ; */
+        /* Submit query */
+        db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST);
+        *query = 0;                  /* start new query */
+         msg = _("Enter SQL query: ");
+      } else {
+         msg = _("Add to SQL query: ");
+      }
+   }
+   free_pool_memory(query);
+   bsendmsg(ua, _("End query mode.\n"));
+   return 1; 
+}
index 47bc7401f2b6c7d45722a7864c9d7cb59c62be6b..40428f5512e403a7cc500cae4f528f7f3c6d97a7 100644 (file)
@@ -341,7 +341,7 @@ static int user_select_jobids(UAContext *ua, JOBIDS *ji)
       case -1:                       /* error */
         return 0;
       case 0:                        /* list last 20 Jobs run */
-        db_list_sql_query(ua->jcr, ua->db, uar_list_jobs, prtit, ua, 1, 0);
+        db_list_sql_query(ua->jcr, ua->db, uar_list_jobs, prtit, ua, 1, HORZ_LIST);
         done = 0;
         break;
       case 1:                        /* list where a file is saved */
@@ -356,7 +356,7 @@ static int user_select_jobids(UAContext *ua, JOBIDS *ji)
         query = get_pool_memory(PM_MESSAGE);
         Mmsg(&query, uar_file, fname);
         free(fname);
-        db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, 0);
+        db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST);
         free_pool_memory(query);
         done = 0;
         break;
@@ -370,7 +370,7 @@ static int user_select_jobids(UAContext *ua, JOBIDS *ji)
          if (!get_cmd(ua, _("Enter SQL list command: "))) {
            return 0;
         }
-        db_list_sql_query(ua->jcr, ua->db, ua->cmd, prtit, ua, 1, 0);
+        db_list_sql_query(ua->jcr, ua->db, ua->cmd, prtit, ua, 1, HORZ_LIST);
         done = 0;
         break;
       case 4:                        /* Select the most recent backups */
@@ -438,7 +438,7 @@ static int user_select_jobids(UAContext *ua, JOBIDS *ji)
             bsendmsg(ua, "%s\n", db_strerror(ua->db));
         }
         free_pool_memory(query);
-        db_list_sql_query(ua->jcr, ua->db, uar_list_temp, prtit, ua, 1, 0);
+        db_list_sql_query(ua->jcr, ua->db, uar_list_temp, prtit, ua, 1, HORZ_LIST);
 
         if (!db_sql_query(ua->db, uar_sel_jobid_temp, jobid_handler, (void *)ji)) {
             bsendmsg(ua, "%s\n", db_strerror(ua->db));
index b6ec85e84cfae9251d8a71968b62a4055057bf3f..39cf261c8ca8ea410b7ba7164ad5655d5c5f83e1 100644 (file)
@@ -489,7 +489,7 @@ int select_media_dbr(UAContext *ua, MEDIA_DBR *mr)
         return 0;
       }
       mr->PoolId = pr.PoolId;
-      db_list_media_records(ua->jcr, ua->db, mr, prtit, ua, 0);
+      db_list_media_records(ua->jcr, ua->db, mr, prtit, ua, HORZ_LIST);
       if (!get_cmd(ua, _("Enter MediaId or Volume name: "))) {
         return 0;
       }
@@ -554,7 +554,7 @@ POOL *get_pool_resource(UAContext *ua)
  */
 int select_job_dbr(UAContext *ua, JOB_DBR *jr)
 {
-   db_list_job_records(ua->jcr, ua->db, jr, prtit, ua, 0);
+   db_list_job_records(ua->jcr, ua->db, jr, prtit, ua, HORZ_LIST);
    if (!get_pint(ua, _("Enter the JobId to select: "))) {
       return 0;
    }
index 85b5d245019247e4eeb56a97931a3ce2c542d0ee..4df5ca6eb6feb6138dc8e7d40c574e1aa271d7e1 100644 (file)
@@ -220,7 +220,7 @@ int do_verify(JCR *jcr)
            jcr->store->SDDport = jcr->store->SDport;
         }
         bnet_fsend(fd, storaddr, jcr->store->address, jcr->store->SDDport);
-         if (!response(fd, OKstore, "Storage", 1)) {
+         if (!response(jcr, fd, OKstore, "Storage", DISPLAY_ERROR)) {
            goto bail_out;
         }
         /*
@@ -232,7 +232,7 @@ int do_verify(JCR *jcr)
                   jr.VolSessionId, jr.VolSessionTime, 
                   jr.StartFile, jr.EndFile, jr.StartBlock, 
                   jr.EndBlock);
-         if (!response(fd, OKsession, "Session", 1)) {
+         if (!response(jcr, fd, OKsession, "Session", DISPLAY_ERROR)) {
            goto bail_out;
         }
          level = "volume";
@@ -249,7 +249,7 @@ int do_verify(JCR *jcr)
     * Send verify command/level to File daemon
     */
    bnet_fsend(fd, verifycmd, level);
-   if (!response(fd, OKverify, "Verify", 1)) {
+   if (!response(jcr, fd, OKverify, "Verify", DISPLAY_ERROR)) {
       goto bail_out;
    }
 
index 377c8c0a987b73e89ddbe837fb553f279b4ea942..2e27898dd5e3fea60e047b5ab1e1da89581176c9 100644 (file)
 
 
 /* Definition of the contents of each Resource */
-struct s_res_dir {
+struct DIRRES {
    RES   hdr;
    char *password;                    /* Director password */
    char *address;                     /* Director address or zero */
    int enable_ssl;                    /* Use SSL for this Director */
 };
-typedef struct s_res_dir DIRRES;
 
-struct s_res_client {
+struct CLIENT {
    RES   hdr;
    int   FDport;                      /* where we listen for Directors */ 
    char *FDaddr;                      /* bind address */
@@ -62,22 +61,20 @@ struct s_res_client {
    char *pid_directory;
    char *subsys_directory;
    int require_ssl;                   /* Require SSL on all connections */
-   struct s_res_msgs *messages;       /* daemon message handler */
+   MSGS *messages;                    /* daemon message handler */
    int MaxConcurrentJobs;
    utime_t heartbeat_interval;        /* Interval to send heartbeats to Dir */
 };
-typedef struct s_res_client CLIENT;
 
 
 
 /* Define the Union of all the above
  * resource structure definitions.
  */
-union u_res {
-   struct s_res_dir     res_dir;
-   struct s_res_client  res_client;
-   struct s_res_msgs    res_msgs;
-   RES hdr;
+union URES {
+   DIRRES res_dir;
+   CLIENT res_client;
+   MSGS   res_msgs;
+   RES    hdr;
 };
 
-typedef union u_res URES;
index 367b49e30354077b7a7dcd62f81e3472b2aa478f..03fccf1956b18087d8d065dc5124d7ee500bd0ae 100644 (file)
@@ -37,11 +37,10 @@ LIBSRCS = alloc.c base64.c bsys.c bget_msg.c \
          cram-md5.c crc32.c daemon.c edit.c fnmatch.c \
          hmac.c idcache.c jcr.c lex.c  \
          md5.c message.c mem_pool.c parse_conf.c \
-         queue.c rwlock.c serial.c sha1.c \
+         queue.c rwlock.c scan.c serial.c sha1.c \
          semlock.c signal.c smartall.c tree.c \
          util.c watchdog.c workq.c  
 
-#        immortal.c filesys.c
 
 LIBOBJS = alloc.o base64.o bsys.o bget_msg.o \
          bnet.o bnet_server.o \
@@ -49,11 +48,10 @@ LIBOBJS = alloc.o base64.o bsys.o bget_msg.o \
          cram-md5.o crc32.o daemon.o edit.o fnmatch.o \
          hmac.o idcache.o jcr.o lex.o  \
          md5.o message.o mem_pool.o parse_conf.o \
-         queue.o rwlock.o serial.o sha1.o \
+         queue.o rwlock.o scan.o serial.o sha1.o \
          semlock.o signal.o smartall.o tree.o \
          util.o watchdog.o workq.o
 
-#        immortal.o filesys.o
 
 EXTRAOBJS = @OBJLIST@
 
index b601c53c068e8139463156c9adecee1fe5672da0..0e147bcf936b48f7cca10e086300064f6c845451 100644 (file)
@@ -27,6 +27,7 @@
  */
 
 #include "bacula.h"
+#include <math.h>
 
 /* We assume ASCII input and don't worry about overflow */
 uint64_t str_to_uint64(char *str) 
@@ -189,7 +190,7 @@ int size_to_uint64(char *str, int str_len, uint64_t *rtn_value)
                      1099511627776};/* terabyte */
 #endif
 
-   Dmsg0(400, "Enter sized to uint64\n");
+   Dmsg1(400, "Enter sized to uint64 str=%s\n", str);
 
    /* Look for modifier */
    ch = str[str_len - 1];
@@ -209,16 +210,15 @@ int size_to_uint64(char *str, int str_len, uint64_t *rtn_value)
    if (mod[i] == 0 || !is_a_number(str)) {
       return 0;
    }
-   Dmsg3(400, "size str=:%s: %f i=%d\n", str, strtod(str, NULL), i);
+   Dmsg3(400, "size str=:%s: %lf i=%d\n", str, strtod(str, NULL), i);
 
-   value = (uint64_t)strtod(str, NULL);
-   Dmsg1(400, "Int value = %d\n", (int)value);
+   value = strtod(str, NULL);
    if (errno != 0 || value < 0) {
       return 0;
    }
    *rtn_value = (uint64_t)(value * mult[i]);
-   Dmsg2(400, "Full value = %f %" lld "\n", strtod(str, NULL) * mult[i],
-       value *mult[i]);
+   Dmsg2(400, "Full value = %lf %" lld "\n", value * mult[i],  
+      (uint64_t)(value * mult[i]));
    return 1;
 }
 
@@ -228,13 +228,13 @@ int size_to_uint64(char *str, int str_len, uint64_t *rtn_value)
  */
 int is_a_number(const char *n)
 {
-   int digit_seen = 0;
+   bool digit_seen = false;
 
    if( *n == '-' || *n == '+' ) {
       n++;
    }
    while (B_ISDIGIT(*n)) {
-      digit_seen = 1;
+      digit_seen = true;
       n++;
    }
    if (digit_seen && *n == '.') {
@@ -254,9 +254,9 @@ int is_a_number(const char *n)
  */
 int is_an_integer(const char *n)
 {
-   int digit_seen = 0;
+   bool digit_seen = false;
    while (B_ISDIGIT(*n)) {
-      digit_seen = 1;
+      digit_seen = true;
       n++;
    }
    return digit_seen && *n==0;
index 80676ef253e4950c73c5e731215ab7aba451c300..da1c76c3b7ac73ae5138d4744eee971bef904675 100755 (executable)
 
 #define FULL_LOCATION 1              /* set for file:line in Debug messages */
 
+/* 
+ *  This is where we define "Globals" because all the
+ *    daemons include this file.
+ */
 char *working_directory = NULL;       /* working directory path stored here */
 int verbose = 0;                     /* increase User messages */
 int debug_level = 0;                 /* debug level */
 time_t daemon_start_time = 0;        /* Daemon start time */
 char *version = VERSION " (" BDATE ")";
-
-char my_name[20];                    /* daemon name is stored here */
+char my_name[30];                    /* daemon name is stored here */
 char *exepath = (char *)NULL;
 char *exename = (char *)NULL;
 int console_msg_pending = 0;
 char con_fname[500];                 /* Console filename */
 FILE *con_fd = NULL;                 /* Console file descriptor */
 brwlock_t con_lock;                  /* Console lock structure */
-
 FILE *trace_fd = NULL;
 
+#ifdef HAVE_MYSQL
+char catalog_db[] = "MySQL";
+#endif
+#ifdef HAVE_SQLITE
+char catalog_db[] = "SQLite";
+#endif
+#ifdef HAVE_BACULA_DB
+char catlog_db[] = "Internal";
+#endif
+
+
 /* Forward referenced functions */
 
 /* Imported functions */
index 6a13469ded81ac30e95122d8c240590652965dc8..217a4d50e626c85c572e0b8c112afe699dfb5c4b 100755 (executable)
@@ -456,7 +456,6 @@ void store_int64(LEX *lc, struct res_items *item, int index, int pass)
 void store_size(LEX *lc, struct res_items *item, int index, int pass)
 {
    int token;
-   double dvalue;
    uint64_t uvalue;
 
    Dmsg0(400, "Enter store_size\n");
@@ -464,13 +463,6 @@ void store_size(LEX *lc, struct res_items *item, int index, int pass)
    errno = 0;
    switch (token) {
    case T_NUMBER:
-      Dmsg2(400, "size num=:%s: %f\n", lc->str, strtod(lc->str, NULL)); 
-      dvalue = strtod(lc->str, NULL);
-      if (errno != 0 || token < 0) {
-         scan_err1(lc, "expected a size number, got: %s", lc->str);
-      }
-      *(uint64_t *)(item->value) = (uint64_t)dvalue;
-      break;
    case T_IDENTIFIER:
    case T_UNQUOTED_STRING:
       if (!size_to_uint64(lc->str, lc->str_len, &uvalue)) {
@@ -492,19 +484,12 @@ void store_size(LEX *lc, struct res_items *item, int index, int pass)
 void store_time(LEX *lc, struct res_items *item, int index, int pass)
 {
    int token; 
-   double value;
    utime_t utime;
 
    token = lex_get_token(lc, T_ALL);
    errno = 0;
    switch (token) {
    case T_NUMBER:
-      value = strtod(lc->str, NULL);
-      if (errno != 0 || value < 0) {
-         scan_err1(lc, "expected a time period, got: %s", lc->str);
-      }
-      *(utime_t *)(item->value) = (utime_t)value;
-      break;
    case T_IDENTIFIER:
    case T_UNQUOTED_STRING:
       if (!duration_to_utime(lc->str, &utime)) {
index 9f2f47ff3e8f5dc7a802aec30970081f11683d02..ea51399922a069d63129b19942a39069698b1403 100644 (file)
@@ -47,8 +47,8 @@ struct res_items {
  * at the beginning of every resource
  * record.
  */
-struct s_reshdr {
-   struct s_reshdr *next;             /* pointer to next resource of this type */
+struct RES {
+   RES *next;                         /* pointer to next resource of this type */
    char *name;                        /* resource name */
    char *desc;                        /* resource description */
    int   rcode;                       /* resource id or type */
@@ -56,7 +56,6 @@ struct s_reshdr {
    char  item_present[MAX_RES_ITEMS]; /* set if item is present in conf file */
 };
 
-typedef struct s_reshdr RES;
 
 /* 
  * Master Resource configuration structure definition
@@ -79,26 +78,23 @@ struct s_res {
 #define ITEM_NO_EQUALS   0x4          /* Don't scan = after name */
 
 /* Message Resource */
-struct s_res_msgs {
+struct MSGS {
    RES   hdr;
    char *mail_cmd;                    /* mail command */
    char *operator_cmd;                /* Operator command */
    DEST *dest_chain;                  /* chain of destinations */
    char send_msg[nbytes_for_bits(M_MAX+1)];  /* bit array of types */
 };
-typedef struct s_res_msgs MSGS;
 
 
 /* Define the Union of all the above common
  * resource structure definitions.
  */
-union cu_res {
-   struct s_res_msgs    res_msgs;
+union CURES {
+   MSGS  res_msgs;
    RES hdr;
 };
 
-typedef union cu_res CURES;
-
 
 /* Configuration routines */
 void  parse_config(char *cf);
index 513bd45e8ee4a5edab58cd06391ae145ce59eca8..d7cffe259cf1e8ed17425e2fd2f40e56d516d1f5 100644 (file)
@@ -31,7 +31,7 @@ int       to_base64              (intmax_t value, char *where);
 int       from_base64            (intmax_t *value, char *where);
 int       bin_to_base64          (char *buf, char *bin, int len);
 
-/* bmisc.c */
+/* bsys.c */
 char     *bstrncpy               (char *dest, const char *src, int maxlen);
 char     *bstrncat               (char *dest, const char *src, int maxlen);
 void     *b_malloc               (char *file, int line, size_t size);
@@ -78,6 +78,11 @@ void       bnet_suppress_error_messages(BSOCK *bsock, int flag);
 /* bget_msg.c */
 int      bget_msg(BSOCK *sock);
 
+/* bpipe.c */
+BPIPE *          open_bpipe(char *prog, int wait, char *mode);
+int              close_wpipe(BPIPE *bpipe);
+int              close_bpipe(BPIPE *bpipe);
+
 /* cram-md5.c */
 int cram_md5_get_auth(BSOCK *bs, char *password, int ssl_need);
 int cram_md5_auth(BSOCK *bs, char *password, int ssl_need);
@@ -138,19 +143,24 @@ BSOCK *          bnet_accept             (BSOCK *bsock, char *who);
 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);
+/* scan.c */
 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);
+int              parse_args(POOLMEM *cmd, POOLMEM *args, int *argc, 
+                        char **argk, char **argv, int max_args);
+char            *next_arg(char **s);
+
+/* util.c */
+int              is_buf_zero             (char *buf, int len);
+void             lcase                   (char *str);
+void             bash_spaces             (char *str);
+void             unbash_spaces           (char *str);
 char *           encode_time             (time_t time, char *buf);
 char *           encode_mode             (mode_t mode, char *buf);
 int              do_shell_expansion      (char *name, int name_len);
-int              is_buf_zero             (char *buf, int len);
 void             jobstatus_to_ascii      (int JobStatus, char *msg, int maxlen);
 void             pm_strcat               (POOLMEM **pm, char *str);
 void             pm_strcpy               (POOLMEM **pm, char *str);
@@ -158,16 +168,11 @@ 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);
-BPIPE *          open_bpipe(char *prog, int wait, char *mode);
-int              close_wpipe(BPIPE *bpipe);
-int              close_bpipe(BPIPE *bpipe);
+void             make_session_key        (char *key, char *seed, int mode);
 POOLMEM         *edit_job_codes(JCR *jcr, char *omsg, char *imsg, char *to);  
-void             parse_command_args(POOLMEM *cmd, POOLMEM *args, int *argc, 
-                        char **argk, char **argv);
-char            *next_arg(char **s);
 void             set_working_directory(char *wd);
 
+
 /* watchdog.c */
 int start_watchdog(void);
 int stop_watchdog(void);
diff --git a/bacula/src/lib/scan.c b/bacula/src/lib/scan.c
new file mode 100644 (file)
index 0000000..376e3fd
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ *   scan.c -- scanning routines for Bacula
+ * 
+ *    Kern Sibbald, MM separated from util.c MMIII
+ *
+ *   Version $Id$
+ */
+
+/*
+   Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+
+   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.
+
+   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.
+
+ */
+
+#include "bacula.h"
+#include "jcr.h"
+#include "findlib/find.h"
+
+
+/* Strip any trailing junk from the command */
+void strip_trailing_junk(char *cmd)
+{
+   char *p;
+   p = cmd + strlen(cmd) - 1;
+
+   /* strip trailing junk from command */
+   while ((p >= cmd) && (*p == '\n' || *p == '\r' || *p == ' '))
+      *p-- = 0;
+}
+
+/* Strip any trailing slashes from a directory path */
+void strip_trailing_slashes(char *dir)
+{
+   char *p;
+   p = dir + strlen(dir) - 1;
+
+   /* strip trailing slashes */
+   while ((p >= dir) && (*p == '/'))
+      *p-- = 0;
+}
+
+/*
+ * Skip spaces
+ *  Returns: 0 on failure (EOF)            
+ *          1 on success
+ *          new address in passed parameter 
+ */
+int skip_spaces(char **msg)
+{
+   char *p = *msg;
+   if (!p) {
+      return 0;
+   }
+   while (*p && *p == ' ') {
+      p++;
+   }
+   *msg = p;
+   return *p ? 1 : 0;
+}
+
+/*
+ * Skip nonspaces
+ *  Returns: 0 on failure (EOF)            
+ *          1 on success
+ *          new address in passed parameter 
+ */
+int skip_nonspaces(char **msg)
+{
+   char *p = *msg;
+
+   if (!p) {
+      return 0;
+   }
+   while (*p && *p != ' ') {
+      p++;
+   }
+   *msg = p;
+   return *p ? 1 : 0;
+}
+
+/* folded search for string - case insensitive */
+int
+fstrsch(char *a, char *b)   /* folded case search */
+{
+   register char *s1,*s2;
+   register char c1, c2;
+
+   s1=a;
+   s2=b;
+   while (*s1) {                     /* do it the fast way */
+      if ((*s1++ | 0x20) != (*s2++ | 0x20))
+        return 0;                    /* failed */
+   }
+   while (*a) {                      /* do it over the correct slow way */
+      if (B_ISUPPER(c1 = *a)) {
+        c1 = tolower((int)c1);
+      }
+      if (B_ISUPPER(c2 = *b)) {
+        c2 = tolower((int)c2);
+      }
+      if (c1 != c2) {
+        return 0;
+      }
+      a++;
+      b++;
+   }
+   return 1;
+}
+
+
+/* 
+ * Return next argument from command line.  Note, this
+ * routine is destructive.
+ */
+char *next_arg(char **s)
+{
+   char *p, *q, *n;
+   bool in_quote = false;
+
+   /* skip past spaces to next arg */
+   for (p=*s; *p && B_ISSPACE(*p); ) {
+      p++;
+   }   
+   Dmsg1(400, "Next arg=%s\n", p);
+   for (n = q = p; *p ; ) {
+      if (*p == '\\') {
+        p++;
+        if (*p) {
+           *q++ = *p++;
+        } else {
+           *q++ = *p;
+        }
+        continue;
+      }
+      if (*p == '"') {                  /* start or end of quote */
+        if (in_quote) {
+           p++;                        /* skip quote */
+           in_quote = false;
+           continue;
+        }
+        in_quote = true;
+        p++;
+        continue;
+      }
+      if (!in_quote && B_ISSPACE(*p)) {     /* end of field */
+        p++;
+        break;
+      }
+      *q++ = *p++;
+   }
+   *q = 0;
+   *s = p;
+   Dmsg2(400, "End arg=%s next=%s\n", n, p);
+   return n;
+}   
+
+/*
+ * This routine parses the input command line.
+ * It makes a copy in args, then builds an
+ *  argc, argv like list where
+ *    
+ *  argc = count of arguments
+ *  argk[i] = argument keyword (part preceding =)
+ *  argv[i] = argument value (part after =)
+ *
+ *  example:  arg1 arg2=abc arg3=
+ *
+ *  argc = c
+ *  argk[0] = arg1
+ *  argv[0] = NULL
+ *  argk[1] = arg2
+ *  argv[1] = abc
+ *  argk[2] = arg3
+ *  argv[2] = 
+ */
+
+int parse_args(POOLMEM *cmd, POOLMEM *args, int *argc, 
+              char **argk, char **argv, int max_args) 
+{
+   char *p, *q, *n;
+   int len;
+
+   len = strlen(cmd) + 1;
+   args = check_pool_memory_size(args, len);
+   bstrncpy(args, cmd, len);
+   strip_trailing_junk(args);
+   *argc = 0;
+   p = args;
+   /* Pick up all arguments */
+   while (*argc < max_args) {
+      n = next_arg(&p);   
+      if (*n) {
+        argk[*argc] = n;
+        argv[(*argc)++] = NULL;
+      } else {
+        break;
+      }
+   }
+   /* Separate keyword and value */
+   for (int i=0; i < *argc; i++) {
+      p = strchr(argk[i], '=');
+      if (p) {
+        *p++ = 0;                    /* terminate keyword and point to value */
+        /* Unquote quoted values */
+         if (*p == '"') {
+            for (n = q = ++p; *p && *p != '"'; ) {
+               if (*p == '\\') {
+                 p++;
+              }
+              *q++ = *p++;
+           }
+           *q = 0;                   /* terminate string */
+           p = n;                    /* point to string */
+        }
+        if (strlen(p) > MAX_NAME_LENGTH-1) {
+           p[MAX_NAME_LENGTH-1] = 0; /* truncate to max len */
+        }
+      }
+      argv[i] = p;                   /* save ptr to value or NULL */
+   }
+   return 1;
+#ifdef xxxx
+   for (i=0; i<argc; i++) {
+      Dmsg3(000, "Arg %d: kw=%s val=%s\n", i, argk[i], argv[i]?argv[i]:"NULL");
+   }
+#endif
+}
index 1f876670c7cbf1065e9f9f19854f911537983d52..32aa392f0758bded4e64ba0d2dc5232b49b04a87 100644 (file)
@@ -63,14 +63,14 @@ typedef unsigned short sm_ushort;
 /*  Memory allocation control structures and storage.  */
 
 struct abufhead {
-       struct b_queue abq;          /* Links on allocated queue */
-       unsigned ablen;            /* Buffer length in bytes */
-       char *abfname;             /* File name pointer */
-       sm_ushort ablineno;        /* Line number of allocation */ 
+   struct b_queue abq;        /* Links on allocated queue */
+   unsigned ablen;            /* Buffer length in bytes */
+   char *abfname;             /* File name pointer */
+   sm_ushort ablineno;        /* Line number of allocation */ 
 };
 
 static struct b_queue abqueue = {    /* Allocated buffer queue */
-       &abqueue, &abqueue
+   &abqueue, &abqueue
 };
 
 static Boolean bufimode = False;   /* Buffers not tracked when True */
@@ -83,35 +83,35 @@ static Boolean bufimode = False;   /* Buffers not tracked when True */
 
 static void *smalloc(char *fname, int lineno, unsigned int nbytes)
 {
-       char *buf;
-
-       /* Note:  Unix  MALLOC  actually  permits  a zero length to be
-          passed and allocates a valid block with  zero  user  bytes.
-          Such  a  block  can  later  be expanded with realloc().  We
-           disallow this based on the belief that it's better to  make
-          a  special case and allocate one byte in the rare case this
-          is desired than to miss all the erroneous occurrences where
-          buffer length calculation code results in a zero.  */
-
-       ASSERT(nbytes > 0);
-
-       nbytes += HEAD_SIZE + 1;
-       if ((buf = (char *)malloc(nbytes)) != NULL) {
-          P(mutex);
-          /* Enqueue buffer on allocated list */
-          qinsert(&abqueue, (struct b_queue *) buf);
-          ((struct abufhead *) buf)->ablen = nbytes;
-          ((struct abufhead *) buf)->abfname = bufimode ? NULL : fname;
-          ((struct abufhead *) buf)->ablineno = (sm_ushort) lineno;
-          /* Emplace end-clobber detector at end of buffer */
-          buf[nbytes - 1] = (((long) buf) & 0xFF) ^ 0xC5;
-          buf += HEAD_SIZE;  /* Increment to user data start */
-          V(mutex);
-       } else {
-           Emsg0(M_ABORT, 0, _("Out of memory\n"));
-       }
-        Dmsg4(1150, "smalloc %d at %x from %s:%d\n", nbytes, buf, fname, lineno);
-       return (void *)buf;
+   char *buf;
+
+   /* Note:  Unix  MALLOC  actually  permits  a zero length to be
+      passed and allocates a valid block with  zero  user  bytes.
+      Such  a  block  can  later  be expanded with realloc().  We
+      disallow this based on the belief that it's better to  make
+      a  special case and allocate one byte in the rare case this
+      is desired than to miss all the erroneous occurrences where
+      buffer length calculation code results in a zero.  */
+
+   ASSERT(nbytes > 0);
+
+   nbytes += HEAD_SIZE + 1;
+   if ((buf = (char *)malloc(nbytes)) != NULL) {
+      P(mutex);
+      /* Enqueue buffer on allocated list */
+      qinsert(&abqueue, (struct b_queue *) buf);
+      ((struct abufhead *) buf)->ablen = nbytes;
+      ((struct abufhead *) buf)->abfname = bufimode ? NULL : fname;
+      ((struct abufhead *) buf)->ablineno = (sm_ushort) lineno;
+      /* Emplace end-clobber detector at end of buffer */
+      buf[nbytes - 1] = (((long) buf) & 0xFF) ^ 0xC5;
+      buf += HEAD_SIZE;  /* Increment to user data start */
+      V(mutex);
+   } else {
+      Emsg0(M_ABORT, 0, _("Out of memory\n"));
+   }
+   Dmsg4(1150, "smalloc %d at %x from %s:%d\n", nbytes, buf, fname, lineno);
+   return (void *)buf;
 }
 
 /*  SM_NEW_OWNER -- Update the File and line number for a buffer
@@ -119,10 +119,10 @@ static void *smalloc(char *fname, int lineno, unsigned int nbytes)
 
 void sm_new_owner(char *fname, int lineno, char *buf)
 {
-       buf -= HEAD_SIZE;  /* Decrement to header */
-       ((struct abufhead *)buf)->abfname = bufimode ? NULL : fname;
-       ((struct abufhead *)buf)->ablineno = (sm_ushort) lineno;
-       return;
+   buf -= HEAD_SIZE;  /* Decrement to header */
+   ((struct abufhead *)buf)->abfname = bufimode ? NULL : fname;
+   ((struct abufhead *)buf)->ablineno = (sm_ushort) lineno;
+   return;
 }
 
 /*  SM_FREE  --  Update free pool availability.  FREE is never called
@@ -132,55 +132,55 @@ void sm_new_owner(char *fname, int lineno, char *buf)
 
 void sm_free(char *file, int line, void *fp)
 {
-       char *cp = (char *) fp;
-       struct b_queue *qp;
-
-       if (cp == NULL) {
-           Emsg2(M_ABORT, 0, "Attempt to free NULL called from %s:%d\n", file, line);
-       }
-
-       cp -= HEAD_SIZE;
-       qp = (struct b_queue *) cp;
-
-       P(mutex);
-        Dmsg4(1150, "sm_free %d at %x from %s:%d\n", 
-             ((struct abufhead *)cp)->ablen, fp, 
-             ((struct abufhead *)cp)->abfname, ((struct abufhead *)cp)->ablineno);
-
-       /* The following assertions will catch virtually every release
-           of an address which isn't an allocated buffer. */
-       if (qp->qnext->qprev != qp) {
-          V(mutex);
-           Emsg2(M_ABORT, 0, "qp->qnext->qprev != qp called from %s:%d\n", file, line);
-       }
-       if (qp->qprev->qnext != qp) {
-          V(mutex);
-           Emsg2(M_ABORT, 0, "qp->qprev->qnext != qp called from %s:%d\n", file, line);
-       }
-
-       /* The following assertion detects storing off the  end  of  the
-          allocated  space in the buffer by comparing the end of buffer
-          checksum with the address of the buffer.  */
-
-       if (((unsigned char *) cp)[((struct abufhead *) cp)->ablen - 1] !=
-                ((((long) cp) & 0xFF) ^ 0xC5)) {
-          V(mutex);
-           Emsg2(M_ABORT, 0, "Buffer overrun called from %s:%d\n", file, line);
-       }
-
-
-       qdchain(qp);
-       V(mutex);
-
-       /* Now we wipe the contents of  the  just-released  buffer  with
-           "designer  garbage"  (Duff  Kurland's  phrase) of alternating
-          bits.  This is intended to ruin the day for any miscreant who
-           attempts to access data through a pointer into storage that's
-          been previously released. */
-
-       memset(cp, 0xAA, (int) ((struct abufhead *) cp)->ablen);
-
-       free(cp);
+   char *cp = (char *) fp;
+   struct b_queue *qp;
+
+   if (cp == NULL) {
+      Emsg2(M_ABORT, 0, "Attempt to free NULL called from %s:%d\n", file, line);
+   }
+
+   cp -= HEAD_SIZE;
+   qp = (struct b_queue *) cp;
+
+   P(mutex);
+   Dmsg4(1150, "sm_free %d at %x from %s:%d\n", 
+        ((struct abufhead *)cp)->ablen, fp, 
+        ((struct abufhead *)cp)->abfname, ((struct abufhead *)cp)->ablineno);
+
+   /* The following assertions will catch virtually every release
+      of an address which isn't an allocated buffer. */
+   if (qp->qnext->qprev != qp) {
+      V(mutex);
+      Emsg2(M_ABORT, 0, "qp->qnext->qprev != qp called from %s:%d\n", file, line);
+   }
+   if (qp->qprev->qnext != qp) {
+      V(mutex);
+      Emsg2(M_ABORT, 0, "qp->qprev->qnext != qp called from %s:%d\n", file, line);
+   }
+
+   /* The following assertion detects storing off the  end  of the
+      allocated  space in the buffer by comparing the end of buffer
+      checksum with the address of the buffer. */
+
+   if (((unsigned char *) cp)[((struct abufhead *) cp)->ablen - 1] !=
+           ((((long) cp) & 0xFF) ^ 0xC5)) {
+      V(mutex);
+      Emsg2(M_ABORT, 0, "Buffer overrun called from %s:%d\n", file, line);
+   }
+
+
+   qdchain(qp);
+   V(mutex);
+
+   /* Now we wipe the contents of  the just-released  buffer  with
+      "designer  garbage"  (Duff  Kurland's  phrase) of alternating
+      bits.  This is intended to ruin the day for any miscreant who
+      attempts to access data through a pointer into storage that's
+      been previously released. */
+
+   memset(cp, 0xAA, (int) ((struct abufhead *) cp)->ablen);
+
+   free(cp);
 }
 
 /*  SM_MALLOC  --  Allocate buffer.  NULL is returned if no memory
@@ -188,19 +188,19 @@ void sm_free(char *file, int line, void *fp)
 
 void *sm_malloc(char *fname, int lineno, unsigned int nbytes)
 {
-       void *buf;
+   void *buf;
 
-       if ((buf = smalloc(fname, lineno, nbytes)) != NULL) {
+   if ((buf = smalloc(fname, lineno, nbytes)) != NULL) {
 
-          /* To catch sloppy code that assumes  buffers  obtained  from
-             malloc()  are  zeroed,  we  preset  the buffer contents to
-              "designer garbage" consisting of alternating bits.  */
+      /* To catch sloppy code that assumes  buffers  obtained  from
+        malloc()  are  zeroed,  we  preset  the buffer contents to
+         "designer garbage" consisting of alternating bits.  */
 
-          memset(buf, 0x55, (int) nbytes);
-       } else {
-           Emsg0(M_ABORT, 0, _("Out of memory\n"));
-       }
-       return buf;
+      memset(buf, 0x55, (int) nbytes);
+   } else {
+      Emsg0(M_ABORT, 0, _("Out of memory\n"));
+   }
+   return buf;
 }
 
 /*  SM_CALLOC  --  Allocate an array and clear it to zero.  */
@@ -208,14 +208,14 @@ void *sm_malloc(char *fname, int lineno, unsigned int nbytes)
 void *sm_calloc(char *fname, int lineno,
                unsigned int nelem, unsigned int elsize)
 {
-       void *buf;
-
-       if ((buf = smalloc(fname, lineno, nelem * elsize)) != NULL) {
-          memset(buf, 0, (int) (nelem * elsize));
-       } else {
-           Emsg0(M_ABORT, 0, _("Out of memory\n"));
-       }
-       return buf;
+   void *buf;
+
+   if ((buf = smalloc(fname, lineno, nelem * elsize)) != NULL) {
+      memset(buf, 0, (int) (nelem * elsize));
+   } else {
+      Emsg0(M_ABORT, 0, _("Out of memory\n"));
+   }
+   return buf;
 }
 
 /*  SM_REALLOC --  Adjust the size of a  previously  allocated  buffer.
@@ -229,51 +229,51 @@ void *sm_calloc(char *fname, int lineno,
 
 void *sm_realloc(char *fname, int lineno, void *ptr, unsigned int size)
 {
-       unsigned osize;
-       void *buf;
-       char *cp = (char *) ptr;
-
-        Dmsg4(400, "sm_realloc %s:%d 0x%x %d\n", fname, lineno, ptr, size);
-       if (size <= 0) {
-           e_msg(fname, lineno, M_ABORT, 0, "sm_realloc size: %d\n", size);
-       }
-
-       /*  If  the  old  block  pointer  is  NULL, treat realloc() as a
-          malloc().  SVID is silent  on  this,  but  many  C  libraries
-          permit this.  */
-
-       if (ptr == NULL) {
-          return sm_malloc(fname, lineno, size);
-       }
-
-       /* If the old and new sizes are the same, be a nice guy and just
-          return the buffer passed in.  */
-
-       cp -= HEAD_SIZE;
-       osize = ((struct abufhead *) cp)->ablen - (HEAD_SIZE + 1);
-       if (size == osize) {
-          return ptr;
-       }
-
-       /* Sizes differ.  Allocate a new buffer of the  requested  size.
-           If  we  can't  obtain  such a buffer, act as defined in SVID:
-          return NULL from  realloc()  and  leave  the  buffer  in  PTR
-          intact.  */
-
-       if ((buf = smalloc(fname, lineno, size)) != NULL) {
-          memcpy(buf, ptr, (int) sm_min(size, osize));
-          /* If the new buffer is larger than the old, fill the balance
-              of it with "designer garbage". */
-          if (size > osize) {
-             memset(((char *) buf) + osize, 0x55, (int) (size - osize));
-          }
-
-          /* All done.  Free and dechain the original buffer. */
-
-          sm_free(__FILE__, __LINE__, ptr);
-       }
-        Dmsg4(150, "sm_realloc %d at %x from %s:%d\n", size, buf, fname, lineno);
-       return buf;
+   unsigned osize;
+   void *buf;
+   char *cp = (char *) ptr;
+
+   Dmsg4(400, "sm_realloc %s:%d 0x%x %d\n", fname, lineno, ptr, size);
+   if (size <= 0) {
+      e_msg(fname, lineno, M_ABORT, 0, "sm_realloc size: %d\n", size);
+   }
+
+   /*  If  the old  block  pointer  is  NULL, treat realloc() as a
+      malloc().  SVID is silent  on  this,  but  many  C  libraries
+      permit this.  */
+
+   if (ptr == NULL) {
+      return sm_malloc(fname, lineno, size);
+   }
+
+   /* If the old and new sizes are the same, be a nice guy and just
+      return the buffer passed in.  */
+
+   cp -= HEAD_SIZE;
+   osize = ((struct abufhead *) cp)->ablen - (HEAD_SIZE + 1);
+   if (size == osize) {
+      return ptr;
+   }
+
+   /* Sizes differ.  Allocate a new buffer of the  requested  size.
+      If  we  can't  obtain  such a buffer, act as defined in SVID:
+      return NULL from realloc()  and  leave  the  buffer  in  PTR
+      intact.  */
+
+   if ((buf = smalloc(fname, lineno, size)) != NULL) {
+      memcpy(buf, ptr, (int) sm_min(size, osize));
+      /* If the new buffer is larger than the old, fill the balance
+         of it with "designer garbage". */
+      if (size > osize) {
+        memset(((char *) buf) + osize, 0x55, (int) (size - osize));
+      }
+
+      /* All done.  Free and dechain the original buffer. */
+
+      sm_free(__FILE__, __LINE__, ptr);
+   }
+   Dmsg4(150, "sm_realloc %d at %x from %s:%d\n", size, buf, fname, lineno);
+   return buf;
 }
 
 /*  ACTUALLYMALLOC  -- Call the system malloc() function to obtain
@@ -283,7 +283,7 @@ void *sm_realloc(char *fname, int lineno, void *ptr, unsigned int size)
 
 void *actuallymalloc(unsigned int size)
 {
-       return malloc(size);
+   return malloc(size);
 }
 
 /*  ACTUALLYCALLOC  -- Call the system calloc() function to obtain
@@ -293,7 +293,7 @@ void *actuallymalloc(unsigned int size)
 
 void *actuallycalloc(unsigned int nelem, unsigned int elsize)
 {
-       return calloc(nelem, elsize);
+   return calloc(nelem, elsize);
 }
 
 /*  ACTUALLYREALLOC  --  Call the system realloc() function to obtain
@@ -303,8 +303,8 @@ void *actuallycalloc(unsigned int nelem, unsigned int elsize)
 
 void *actuallyrealloc(void *ptr, unsigned int size)
 {
-        Dmsg2(400, "Actuallyrealloc 0x%x %d\n", ptr, size);
-       return realloc(ptr, size);
+   Dmsg2(400, "Actuallyrealloc 0x%x %d\n", ptr, size);
+   return realloc(ptr, size);
 }
 
 /*  ACTUALLYFREE  --  Interface to system free() function to release
@@ -312,7 +312,7 @@ void *actuallyrealloc(void *ptr, unsigned int size)
 
 void actuallyfree(void *cp)
 {
-       free(cp);
+   free(cp);
 }
 
 /*  SM_DUMP  --  Print orphaned buffers (and dump them if BUFDUMP is
@@ -322,58 +322,58 @@ void actuallyfree(void *cp)
  */
 void sm_dump(Boolean bufdump)
 {
-       struct abufhead *ap;
-
-       P(mutex);
-
-       ap = (struct abufhead *)abqueue.qnext;
-
-       while (ap != (struct abufhead *) &abqueue) {
-
-          if ((ap == NULL) ||
-              (ap->abq.qnext->qprev != (struct b_queue *) ap) || 
-              (ap->abq.qprev->qnext != (struct b_queue *) ap)) {
-             fprintf(stderr,
-                 "\nOrphaned buffers exist.  Dump terminated following\n");
-             fprintf(stderr,
-                 "  discovery of bad links in chain of orphaned buffers.\n");
-             fprintf(stderr,
-                 "  Buffer address with bad links: %lx\n", (long) ap);
-             break;
-          }
-
-          if (ap->abfname != NULL) {
-             unsigned memsize = ap->ablen - (HEAD_SIZE + 1);
-             char errmsg[80];
-
-             sprintf(errmsg,
-                "Orphaned buffer:  %6u bytes allocated at line %d of %s %s\n",
-                memsize, ap->ablineno, my_name, ap->abfname
-             );
-              fprintf(stderr, "%s", errmsg);
-             if (bufdump) {
-                unsigned llen = 0;
-                char *cp = ((char *) ap) + HEAD_SIZE;
-
-                errmsg[0] = EOS;
-                while (memsize) {
-                   if (llen >= 16) {
-                       strcat(errmsg, "\n");
-                      llen = 0;
-                       fprintf(stderr, "%s", errmsg);
-                      errmsg[0] = EOS;
-                   }
-                    sprintf(errmsg + strlen(errmsg), " %02X",
-                      (*cp++) & 0xFF);
-                   llen++;
-                   memsize--;
-                }
-                 fprintf(stderr, "%s\n", errmsg);
-             }
-          }
-          ap = (struct abufhead *) ap->abq.qnext;
-       }
-       V(mutex);
+   struct abufhead *ap;
+
+   P(mutex);
+
+   ap = (struct abufhead *)abqueue.qnext;
+
+   while (ap != (struct abufhead *) &abqueue) {
+
+      if ((ap == NULL) ||
+         (ap->abq.qnext->qprev != (struct b_queue *) ap) || 
+         (ap->abq.qprev->qnext != (struct b_queue *) ap)) {
+        fprintf(stderr,
+            "\nOrphaned buffers exist.  Dump terminated following\n");
+        fprintf(stderr,
+            "  discovery of bad links in chain of orphaned buffers.\n");
+        fprintf(stderr,
+            "  Buffer address with bad links: %lx\n", (long) ap);
+        break;
+      }
+
+      if (ap->abfname != NULL) {
+        unsigned memsize = ap->ablen - (HEAD_SIZE + 1);
+        char errmsg[80];
+
+        sprintf(errmsg,
+           "Orphaned buffer:  %6u bytes allocated at line %d of %s %s\n",
+           memsize, ap->ablineno, my_name, ap->abfname
+        );
+         fprintf(stderr, "%s", errmsg);
+        if (bufdump) {
+           unsigned llen = 0;
+           char *cp = ((char *) ap) + HEAD_SIZE;
+
+           errmsg[0] = EOS;
+           while (memsize) {
+              if (llen >= 16) {
+                  strcat(errmsg, "\n");
+                 llen = 0;
+                  fprintf(stderr, "%s", errmsg);
+                 errmsg[0] = EOS;
+              }
+               sprintf(errmsg + strlen(errmsg), " %02X",
+                 (*cp++) & 0xFF);
+              llen++;
+              memsize--;
+           }
+            fprintf(stderr, "%s\n", errmsg);
+        }
+      }
+      ap = (struct abufhead *) ap->abq.qnext;
+   }
+   V(mutex);
 }
 
 #undef sm_check
@@ -390,79 +390,79 @@ void sm_check(char *fname, int lineno, Boolean bufdump)
 /*  SM_CHECK_RTN -- Check the buffers and return 1 if OK otherwise 0 */
 int sm_check_rtn(char *fname, int lineno, Boolean bufdump)
 {
-       struct abufhead *ap;
-       int bad, badbuf = 0;
-
-       P(mutex);
-       ap = (struct abufhead *) abqueue.qnext;
-       while (ap != (struct abufhead *) &abqueue) {
-          bad = 0;
-          if ((ap == NULL) ||
-              (ap->abq.qnext->qprev != (struct b_queue *) ap)) {
-             bad = 0x1;
-          }
-          if (ap->abq.qprev->qnext != (struct b_queue *) ap) { 
-             bad |= 0x2;
-          }
-          if (((unsigned char *) ap)[((struct abufhead *) ap)->ablen - 1] !=
-               ((((long) ap) & 0xFF) ^ 0xC5)) {
-             bad |= 0x4;
-          }
-          badbuf |= bad;
-          if (bad) {
-             fprintf(stderr,
-                 "\nDamaged buffers found at %s:%d\n", fname, lineno);
-
-             if (bad & 0x1) {
-                 fprintf(stderr, "  discovery of bad prev link.\n");
-             }
-             if (bad & 0x2) {
-                 fprintf(stderr, "  discovery of bad next link.\n");
-             }
-             if (bad & 0x4) {
-                 fprintf(stderr, "  discovery of data overrun.\n");
-             }
-
-              fprintf(stderr, "  Buffer address: %lx\n", (long) ap);
-
-             if (ap->abfname != NULL) {
-                unsigned memsize = ap->ablen - (HEAD_SIZE + 1);
-                char errmsg[80];
-
-                fprintf(stderr,
-                   "Damaged buffer:  %6u bytes allocated at line %d of %s %s\n",
-                   memsize, ap->ablineno, my_name, ap->abfname
-                );
-                if (bufdump) {
-                   unsigned llen = 0;
-                   char *cp = ((char *) ap) + HEAD_SIZE;
-
-                   errmsg[0] = EOS;
-                   while (memsize) {
-                      if (llen >= 16) {
-                          strcat(errmsg, "\n");
-                         llen = 0;
-                          fprintf(stderr, "%s", errmsg);
-                         errmsg[0] = EOS;
-                      }
-                      if (*cp < 0x20) {
-                          sprintf(errmsg + strlen(errmsg), " %02X",
-                            (*cp++) & 0xFF);
-                      } else {
-                          sprintf(errmsg + strlen(errmsg), " %c ",
-                            (*cp++) & 0xFF);
-                      }
-                      llen++;
-                      memsize--;
-                   }
-                    fprintf(stderr, "%s\n", errmsg);
-                }
-             }
-          }
-          ap = (struct abufhead *) ap->abq.qnext;
-       }
-       V(mutex);
-       return badbuf ? 0 : 1;
+   struct abufhead *ap;
+   int bad, badbuf = 0;
+
+   P(mutex);
+   ap = (struct abufhead *) abqueue.qnext;
+   while (ap != (struct abufhead *) &abqueue) {
+      bad = 0;
+      if ((ap == NULL) ||
+         (ap->abq.qnext->qprev != (struct b_queue *) ap)) {
+        bad = 0x1;
+      }
+      if (ap->abq.qprev->qnext != (struct b_queue *) ap) { 
+        bad |= 0x2;
+      }
+      if (((unsigned char *) ap)[((struct abufhead *) ap)->ablen - 1] !=
+          ((((long) ap) & 0xFF) ^ 0xC5)) {
+        bad |= 0x4;
+      }
+      badbuf |= bad;
+      if (bad) {
+        fprintf(stderr,
+            "\nDamaged buffers found at %s:%d\n", fname, lineno);
+
+        if (bad & 0x1) {
+            fprintf(stderr, "  discovery of bad prev link.\n");
+        }
+        if (bad & 0x2) {
+            fprintf(stderr, "  discovery of bad next link.\n");
+        }
+        if (bad & 0x4) {
+            fprintf(stderr, "  discovery of data overrun.\n");
+        }
+
+         fprintf(stderr, "  Buffer address: %lx\n", (long) ap);
+
+        if (ap->abfname != NULL) {
+           unsigned memsize = ap->ablen - (HEAD_SIZE + 1);
+           char errmsg[80];
+
+           fprintf(stderr,
+              "Damaged buffer:  %6u bytes allocated at line %d of %s %s\n",
+              memsize, ap->ablineno, my_name, ap->abfname
+           );
+           if (bufdump) {
+              unsigned llen = 0;
+              char *cp = ((char *) ap) + HEAD_SIZE;
+
+              errmsg[0] = EOS;
+              while (memsize) {
+                 if (llen >= 16) {
+                     strcat(errmsg, "\n");
+                    llen = 0;
+                     fprintf(stderr, "%s", errmsg);
+                    errmsg[0] = EOS;
+                 }
+                 if (*cp < 0x20) {
+                     sprintf(errmsg + strlen(errmsg), " %02X",
+                       (*cp++) & 0xFF);
+                 } else {
+                     sprintf(errmsg + strlen(errmsg), " %c ",
+                       (*cp++) & 0xFF);
+                 }
+                 llen++;
+                 memsize--;
+              }
+               fprintf(stderr, "%s\n", errmsg);
+           }
+        }
+      }
+      ap = (struct abufhead *) ap->abq.qnext;
+   }
+   V(mutex);
+   return badbuf ? 0 : 1;
 }
 
 
@@ -475,7 +475,22 @@ int sm_check_rtn(char *fname, int lineno, Boolean bufdump)
 
 void sm_static(int mode)
 {
-       bufimode = (Boolean) (mode != 0);
+   bufimode = (Boolean) (mode != 0);
+}
+
+/* 
+ * Here we overload C++'s global new and delete operators
+ *  so that the memory is allocated through smartalloc.
+ */
+
+void * operator new(size_t size)
+{
+   return sm_malloc(__FILE__, __LINE__, size);
+}
+
+void operator delete(void *buf)
+{
+   sm_free(__FILE__, __LINE__, buf);
 }
 
 #endif
index 4433febb4f2e559190200a67100d50aeff7c6774..8331f3899b1d066636c3caa2aa552c181b408b14 100644 (file)
@@ -95,96 +95,6 @@ unbash_spaces(char *str)
    }
 }
 
-/* Strip any trailing junk from the command */
-void strip_trailing_junk(char *cmd)
-{
-   char *p;
-   p = cmd + strlen(cmd) - 1;
-
-   /* strip trailing junk from command */
-   while ((p >= cmd) && (*p == '\n' || *p == '\r' || *p == ' '))
-      *p-- = 0;
-}
-
-/* Strip any trailing slashes from a directory path */
-void strip_trailing_slashes(char *dir)
-{
-   char *p;
-   p = dir + strlen(dir) - 1;
-
-   /* strip trailing slashes */
-   while ((p >= dir) && (*p == '/'))
-      *p-- = 0;
-}
-
-/*
- * Skip spaces
- *  Returns: 0 on failure (EOF)            
- *          1 on success
- *          new address in passed parameter 
- */
-int skip_spaces(char **msg)
-{
-   char *p = *msg;
-   if (!p) {
-      return 0;
-   }
-   while (*p && *p == ' ') {
-      p++;
-   }
-   *msg = p;
-   return *p ? 1 : 0;
-}
-
-/*
- * Skip nonspaces
- *  Returns: 0 on failure (EOF)            
- *          1 on success
- *          new address in passed parameter 
- */
-int skip_nonspaces(char **msg)
-{
-   char *p = *msg;
-
-   if (!p) {
-      return 0;
-   }
-   while (*p && *p != ' ') {
-      p++;
-   }
-   *msg = p;
-   return *p ? 1 : 0;
-}
-
-/* folded search for string - case insensitive */
-int
-fstrsch(char *a, char *b)   /* folded case search */
-{
-   register char *s1,*s2;
-   register char c1, c2;
-
-   s1=a;
-   s2=b;
-   while (*s1) {                     /* do it the fast way */
-      if ((*s1++ | 0x20) != (*s2++ | 0x20))
-        return 0;                    /* failed */
-   }
-   while (*a) {                      /* do it over the correct slow way */
-      if (B_ISUPPER(c1 = *a)) {
-        c1 = tolower((int)c1);
-      }
-      if (B_ISUPPER(c2 = *b)) {
-        c2 = tolower((int)c2);
-      }
-      if (c1 != c2) {
-        return 0;
-      }
-      a++;
-      b++;
-   }
-   return 1;
-}
-
 
 char *encode_time(time_t time, char *buf)
 {
@@ -513,7 +423,7 @@ int do_shell_expansion(char *name, int name_len)
 
     from SpeakFreely by John Walker */
 
-void makeSessionKey(char *key, char *seed, int mode)
+void make_session_key(char *key, char *seed, int mode)
 {
      int j, k;
      struct MD5Context md5c;
@@ -657,123 +567,6 @@ POOLMEM *edit_job_codes(JCR *jcr, char *omsg, char *imsg, char *to)
    return omsg;
 }
 
-/* 
- * Return next argument from command line.  Note, this
- * routine is destructive.
- */
-char *next_arg(char **s)
-{
-   char *p, *q, *n;
-   int in_quote = 0;
-
-   /* skip past spaces to next arg */
-   for (p=*s; *p && *p == ' '; ) {
-      p++;
-   }   
-   Dmsg1(400, "Next arg=%s\n", p);
-   for (n = q = p; *p ; ) {
-      if (*p == '\\') {
-        p++;
-        if (*p) {
-           *q++ = *p++;
-        } else {
-           *q++ = *p;
-        }
-        continue;
-      }
-      if (*p == '"') {                  /* start or end of quote */
-        if (in_quote) {
-           p++;                        /* skip quote */
-           in_quote = 0;
-           continue;
-        }
-        in_quote = 1;
-        p++;
-        continue;
-      }
-      if (!in_quote && *p == ' ') {     /* end of field */
-        p++;
-        break;
-      }
-      *q++ = *p++;
-   }
-   *q = 0;
-   *s = p;
-   Dmsg2(400, "End arg=%s next=%s\n", n, p);
-   return n;
-}   
-
-/*
- * This routine parses the input command line.
- * It makes a copy in args, then builds an
- *  argc, argv like list where
- *    
- *  argc = count of arguments
- *  argk[i] = argument keyword (part preceding =)
- *  argv[i] = argument value (part after =)
- *
- *  example:  arg1 arg2=abc arg3=
- *
- *  argc = c
- *  argk[0] = arg1
- *  argv[0] = NULL
- *  argk[1] = arg2
- *  argv[1] = abc
- *  argk[2] = arg3
- *  argv[2] = 
- */
-
-void parse_command_args(POOLMEM *cmd, POOLMEM *args, int *argc, 
-                       char **argk, char **argv) 
-{
-   char *p, *q, *n;
-   int len;
-
-   len = strlen(cmd) + 1;
-   args = check_pool_memory_size(args, len);
-   bstrncpy(args, cmd, len);
-   strip_trailing_junk(args);
-   *argc = 0;
-   p = args;
-   /* Pick up all arguments */
-   while (*argc < MAX_CMD_ARGS) {
-      n = next_arg(&p);   
-      if (*n) {
-        argk[*argc] = n;
-        argv[(*argc)++] = NULL;
-      } else {
-        break;
-      }
-   }
-   /* Separate keyword and value */
-   for (int i=0; i < *argc; i++) {
-      p = strchr(argk[i], '=');
-      if (p) {
-        *p++ = 0;                    /* terminate keyword and point to value */
-        /* Unquote quoted values */
-         if (*p == '"') {
-            for (n = q = ++p; *p && *p != '"'; ) {
-               if (*p == '\\') {
-                 p++;
-              }
-              *q++ = *p++;
-           }
-           *q = 0;                   /* terminate string */
-           p = n;                    /* point to string */
-        }
-        if (strlen(p) > MAX_NAME_LENGTH-1) {
-           p[MAX_NAME_LENGTH-1] = 0; /* truncate to max len */
-        }
-      }
-      argv[i] = p;                   /* save ptr to value or NULL */
-   }
-#ifdef xxxx
-   for (i=0; i<argc; i++) {
-      Dmsg3(000, "Arg %d: kw=%s val=%s\n", i, argk[i], argv[i]?argv[i]:"NULL");
-   }
-#endif
-}
-
 void set_working_directory(char *wd)
 {
    struct stat stat_buf; 
index fac59855312d8afdd77e7670ac6ab6cf36fe3f4c..42ae4747ea5c2547fbad32b6f88fcf6d0364c180 100644 (file)
@@ -183,7 +183,7 @@ DEVICE * acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
        *   otherwise mount desired volume obtained from
        *    dir_find_next_appendable_volume
        */
-      strcpy(jcr->VolumeName, dev->VolHdr.VolName);
+      pm_strcpy(&jcr->VolumeName, dev->VolHdr.VolName);
       if (!dir_get_volume_info(jcr, 1) &&
          !(dir_find_next_appendable_volume(jcr) &&
            strcmp(dev->VolHdr.VolName, jcr->VolumeName) == 0)) { /* wrong tape mounted */
index 59286b8ad40903987500cc677179d50224d941c3..781ee94941f0e4d8d8de2c71d3ae8c3b9aa809e3 100644 (file)
@@ -115,7 +115,7 @@ int dir_get_volume_info(JCR *jcr, int writing)
 {
     BSOCK *dir = jcr->dir_bsock;
 
-    strcpy(jcr->VolCatInfo.VolCatName, jcr->VolumeName);
+    bstrncpy(jcr->VolCatInfo.VolCatName, jcr->VolumeName, sizeof(jcr->VolCatInfo.VolCatName));
     Dmsg1(200, "dir_get_volume_info=%s\n", jcr->VolCatInfo.VolCatName);
     bash_spaces(jcr->VolCatInfo.VolCatName);
     bnet_fsend(dir, Get_Vol_Info, jcr->Job, jcr->VolCatInfo.VolCatName, writing);
index 95a424d24b84ca4d648c6ebffe3dafa79e814249..0eeea9e4af8b7b4a40acca6e148aafe1ea2f85d1 100644 (file)
@@ -144,7 +144,8 @@ void empty_block(DEV_BLOCK *block)
    block->binbuf = WRITE_BLKHDR_LENGTH;
    block->bufp = block->buf + block->binbuf;
    block->read_len = 0;
-   block->failed_write = FALSE;
+   block->write_failed = false;
+   block->block_read = false;
 }
 
 /*
@@ -355,7 +356,7 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
       }
       Jmsg(jcr, M_INFO, 0, _("User defined maximum volume capacity %s exceeded on device %s.\n"),
            edit_uint64(max_cap, ed1),  dev->dev_name);
-      block->failed_write = TRUE;
+      block->write_failed = true;
       dev->EndBlock = dev->block_num;
       dev->EndFile  = dev->file;
       weof_dev(dev, 1);              /* end the tape */
@@ -401,7 +402,7 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
          Jmsg3(jcr, M_INFO, 0, _("End of medium on device %s. Write of %u bytes got %d.\n"), 
            dev->dev_name, wlen, stat);
       }  
-      block->failed_write = TRUE;
+      block->write_failed = true;
       dev->EndBlock = dev->block_num;
       dev->EndFile  = dev->file;
       weof_dev(dev, 1);              /* end the tape */
@@ -516,7 +517,7 @@ reread:
       if (retry == 1) {
         dev->VolCatInfo.VolCatErrors++;   
       }
-   } while (stat == -1 && (errno == EINTR || errno == EIO) && retry++ < 6);
+   } while (stat == -1 && (errno == EINTR || errno == EIO) && retry++ < 11);
    if (stat < 0) {
       Dmsg1(90, "Read device got: ERR=%s\n", strerror(errno));
       clrerror_dev(dev, -1);
@@ -524,13 +525,16 @@ reread:
       Mmsg2(&dev->errmsg, _("Read error on device %s. ERR=%s.\n"), 
         dev->dev_name, strerror(dev->dev_errno));
       Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
+      if (dev->state & ST_EOF) {  /* EOF just seen? */
+        dev->state |= ST_EOT;    /* yes, error => EOT */
+      }
       return 0;
    }
    Dmsg1(90, "Read device got %d bytes\n", stat);
    if (stat == 0) {            /* Got EOF ! */
       dev->block_num = block->read_len = 0;
       Mmsg1(&dev->errmsg, _("Read zero bytes on device %s.\n"), dev->dev_name);
-      if (dev->state & ST_EOF) { /* EOF alread read? */
+      if (dev->state & ST_EOF) { /* EOF already read? */
         dev->state |= ST_EOT;  /* yes, 2 EOFs => EOT */
         block->read_len = 0;
         return 0;
@@ -557,15 +561,6 @@ reread:
       return 0;
    }
 
-#ifdef somehow_working
-   if (check_block_numbers) {
-      if (BlockNumber != block->BlockNumber) {
-         Jmsg(jcr, M_ERROR, 0, _("Incorrect block sequence number. Expected %u, got %u\n"),
-           BlockNumber, block->BlockNumber);
-      }
-   }
-#endif
-
    /*
     * If the block is bigger than the buffer, we reposition for
     *  re-reading the block, allocate a buffer of the correct size,
@@ -640,5 +635,6 @@ reread:
    }
    Dmsg2(200, "Exit read_block read_len=%d block_len=%d\n",
       block->read_len, block->block_len);
+   block->block_read = true;
    return 1;
 }
index 9d9c98267c5690d133e42e09edbc2d8ac4bd2f4e..551804c20d68e4453935dbc41587f6f6cf9d042c 100644 (file)
@@ -82,8 +82,8 @@
  *
  *  This is the memory structure for a device block.
  */
-typedef struct s_dev_block {
-   struct s_dev_block *next;          /* pointer to next one */
+struct DEV_BLOCK {
+   DEV_BLOCK *next;                   /* pointer to next one */
    void *dev;                         /* pointer to device (DEVICE not defined yet) */
    /* binbuf is the number of bytes remaining
     * in the buffer. For writes, it is bytes not yet written.
@@ -97,12 +97,13 @@ typedef struct s_dev_block {
    uint32_t VolSessionId;             /* */
    uint32_t VolSessionTime;           /* */
    int      BlockVer;                 /* block version 1 or 2 */
-   int failed_write;                  /* set if write failed */
+   bool     write_failed;             /* set if write failed */
+   bool     block_read;               /* set when block read */
    char *bufp;                        /* pointer into buffer */
    POOLMEM *buf;                      /* actual data buffer. This is a 
                                        * Pool buffer!   
                                        */
-} DEV_BLOCK;
+};
 
 #define block_is_empty(block) !((block)->read_len)
 
index cdb642de8e23f40c406ed6f8fb69b9215a5841dd..1e0a3b908a389b5b1689e00b80e9c9c48cd4cafd 100644 (file)
@@ -239,7 +239,8 @@ static void do_blocks(char *infname)
          Dmsg1(100, "!read_block(): ERR=%s\n", strerror_dev(dev));
         if (dev->state & ST_EOT) {
            if (!mount_next_read_volume(jcr, dev, block)) {
-               printf("End of File on device\n");
+               Jmsg(jcr, M_INFO, 0, _("Got EOM at file %u on device %s, Volume \"%s\"\n"), 
+                 dev->file, dev_name(dev), jcr->VolumeName);
               break;
            }
            /* Read and discard Volume label */
@@ -249,10 +250,11 @@ static void do_blocks(char *infname)
            read_record_from_block(block, record);
            get_session_record(dev, record, &sessrec);
            free_record(record);
-            printf("Volume %s mounted.\n", jcr->VolumeName);
+            Jmsg(jcr, M_INFO, 0, _("Mounted Volume \"%s\".\n"), jcr->VolumeName);
            
         } else if (dev->state & ST_EOF) {
-            Jmsg(jcr, M_INFO, 0, "Got EOF on device %s\n", dev_name(dev));
+            Jmsg(jcr, M_INFO, 0, _("Got EOF at file %u on device %s, Volume \"%s\"\n"), 
+              dev->file, dev_name(dev), jcr->VolumeName);
             Dmsg0(20, "read_record got eof. try again\n");
            continue;
         } else if (dev->state & ST_SHORT) {
index c0d1c433e93411683f4f7db022d01401ae463cdd..8dcaf57f0eb2d360d307b66201cf5cc2de6c4054 100644 (file)
  * List of Volume names to be read by Storage daemon.
  *  Formed by Storage daemon from BSR  
  */
-struct s_vol_list {
-   struct s_vol_list *next;
+struct VOL_LIST {
+   VOL_LIST *next;
    char VolumeName[MAX_NAME_LENGTH];
    int Slot; 
    int start_file;
 };
-typedef struct s_vol_list VOL_LIST;
 
 
 /*
@@ -52,80 +51,80 @@ typedef struct s_vol_list VOL_LIST;
  * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  */
 
-typedef struct s_bsr_volume {
-   struct s_bsr_volume *next;
+struct BSR_VOLUME {
+   BSR_VOLUME *next;
    char VolumeName[MAX_NAME_LENGTH];
-} BSR_VOLUME;
+};           
 
-typedef struct s_bsr_client {
-   struct s_bsr_client *next;
+struct BSR_CLIENT {
+   BSR_CLIENT *next;
    char ClientName[MAX_NAME_LENGTH];
-} BSR_CLIENT;
+};           
 
-typedef struct s_bsr_sessid {
-   struct s_bsr_sessid *next;
+struct BSR_SESSID {
+   BSR_SESSID *next;
    uint32_t sessid;
    uint32_t sessid2;
    int done;                          /* local done */
-} BSR_SESSID;
+};
 
-typedef struct s_bsr_sesstime {
-   struct s_bsr_sesstime *next;
+struct BSR_SESSTIME {
+   BSR_SESSTIME *next;
    uint32_t sesstime;
    int done;                          /* local done */
-} BSR_SESSTIME;
+};             
 
-typedef struct s_bsr_volfile {
-   struct s_bsr_volfile *next;
+struct BSR_VOLFILE {
+   BSR_VOLFILE *next;
    uint32_t sfile;                    /* start file */
    uint32_t efile;                    /* end file */
    int done;                          /* local done */
-} BSR_VOLFILE;
+};
 
-typedef struct s_bsr_volblock {
-   struct s_bsr_volblock *next;
+struct BSR_VOLBLOCK {
+   BSR_VOLBLOCK *next;
    uint32_t sblock;                   /* start block */
    uint32_t eblock;                   /* end block */
    int done;                          /* local done */
-} BSR_VOLBLOCK;
+};             
 
 
-typedef struct s_bsr_findex {
-   struct s_bsr_findex *next;
+struct BSR_FINDEX {
+   BSR_FINDEX *next;
    int32_t findex;                    /* start file index */
    int32_t findex2;                   /* end file index */
    int done;                          /* local done */
-} BSR_FINDEX;
+};           
 
-typedef struct s_bsr_jobid {
-   struct s_bsr_jobid *next;
+struct BSR_JOBID {
+   BSR_JOBID *next;
    uint32_t JobId;
    uint32_t JobId2;
-} BSR_JOBID;
+};          
 
-typedef struct s_bsr_jobtype {
-   struct s_bsr_jobtype *next;
+struct BSR_JOBTYPE {
+   BSR_JOBTYPE *next;
    uint32_t JobType;
-} BSR_JOBTYPE;
+};            
 
-typedef struct s_bsr_joblevel {
-   struct s_bsr_joblevel *next;
+struct BSR_JOBLEVEL {
+   BSR_JOBLEVEL *next;
    uint32_t JobLevel;
-} BSR_JOBLEVEL;
+};             
 
-typedef struct s_bsr_job {
-   struct s_bsr_job *next;
+struct BSR_JOB {
+   BSR_JOB *next;
    char Job[MAX_NAME_LENGTH];
    int done;
-} BSR_JOB;
+};
 
-typedef struct s_bsr_stream {
-   struct s_bsr_stream *next;
+struct BSR_STREAM {
+   BSR_STREAM *next;
    int32_t stream;                    /* stream desired */
-} BSR_STREAM;
+};           
 
-typedef struct s_bsr {
-   struct s_bsr *next;                /* pointer to next one */
+struct BSR {
+   BSR          *next;                /* pointer to next one */
    int           done;                /* set when everything found */
    BSR_VOLUME   *volume;
    int32_t       Slot;                /* Slot */
@@ -142,7 +141,7 @@ typedef struct s_bsr {
    BSR_JOBTYPE  *JobType;
    BSR_JOBLEVEL *JobLevel;
    BSR_STREAM   *stream;
-} BSR;
+};
 
 
 #endif
index 104e70cbf06abd7532ff82328f8134f23d459ff5..eeb8a84dd0a71637aec20de29df9dc38e854db4f 100644 (file)
@@ -227,7 +227,7 @@ open_dev(DEVICE *dev, char *VolName, int mode)
       return dev->fd;
    }
    if (VolName) {
-      strcpy(dev->VolCatInfo.VolCatName, VolName);
+      bstrncpy(dev->VolCatInfo.VolCatName, VolName, sizeof(dev->VolCatInfo.VolCatName));
    }
 
    Dmsg3(29, "open_dev: tape=%d dev_name=%s vol=%s\n", dev_is_tape(dev), 
@@ -288,6 +288,11 @@ open_dev(DEVICE *dev, char *VolName, int mode)
       /*
        * Handle opening of File Archive (not a tape)
        */
+      if (VolName == NULL || *VolName == 0) {
+         Mmsg(&dev->errmsg, _("Could not open file device %s. No Volume name given.\n"),
+           dev->dev_name);
+        return -1;
+      }
       archive_name = get_pool_memory(PM_FNAME);
       pm_strcpy(&archive_name, dev->dev_name);
       if (archive_name[strlen(archive_name)] != '/') {
@@ -1199,8 +1204,12 @@ term_dev(DEVICE *dev)
    }
 }
 
-
-
+/*
+ * We attach a jcr to the device so that when
+ *   the Volume is full during writing, a  
+ *   JobMedia record will be created for this 
+ *   Job.
+ */
 void attach_jcr_to_device(DEVICE *dev, JCR *jcr)
 {
    jcr->prev_dev = (JCR *)NULL;
index c7a355b00dc8fe5817f1dbb6e1c40dbc70c48946..939e052a0c66e8d56d151e16fdc79475d688e0ac 100644 (file)
@@ -91,6 +91,9 @@ int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
        */
       Dmsg1(100, "Walk attached jcrs. Volume=%s\n", dev->VolCatInfo.VolCatName);
       for (JCR *mjcr=NULL; (mjcr=next_attached_jcr(dev, mjcr)); ) {
+        if (mjcr->JobId == 0) {
+           continue;                 /* ignore console */
+        }
          Dmsg1(100, "create JobMedia for Job %s\n", mjcr->Job);
         if (dev->state & ST_TAPE) {
            mjcr->EndBlock = dev->EndBlock;
index 433940f7a2f109397b1504365c9231b125322e09..03c260a0f333c6c4dacb7462dd6b8103446e853c 100644 (file)
@@ -361,7 +361,7 @@ static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *oldname,
    
    steal_device_lock(dev, &hold, BST_WRITING_LABEL);
    
-   strcpy(jcr->VolumeName, newname);
+   pm_strcpy(&jcr->VolumeName, newname);
    jcr->VolCatInfo.Slot = slot;
    autoload_device(jcr, dev, 0, dir);     /* autoload if possible */
    block = new_block(dev);
@@ -695,7 +695,10 @@ static int autochanger_cmd(JCR *jcr)
         jcr->device = device;
         dev = device->dev;
         P(dev->mutex);               /* Use P to avoid indefinite block */
-        if (!(dev->state & ST_OPENED)) {
+        if (!dev_is_tape(dev)) {
+            bnet_fsend(dir, _("3995 Device %s is not an autochanger.\n"), 
+              dev_name(dev));
+        } else if (!(dev->state & ST_OPENED)) {
            if (open_dev(dev, NULL, READ_WRITE) < 0) {
                bnet_fsend(dir, _("3994 Connot open device: %s\n"), strerror_dev(dev));
            } else {
@@ -723,7 +726,7 @@ static int autochanger_cmd(JCR *jcr)
       } else {
          bnet_fsend(dir, _("3999 Device %s not found\n"), devname);
       }
-   } else {
+   } else {  /* error on scanf */
       pm_strcpy(&jcr->errmsg, dir->msg);
       bnet_fsend(dir, _("3907 Error scanning autocharger list command: %s\n"),
         jcr->errmsg);
index e0846894e5c9c02d3fea64815edeac6930df0f1e..04e7ff3a9659cece823b7b7658854b06f6980024 100644 (file)
@@ -136,16 +136,18 @@ int job_cmd(JCR *jcr)
    srandom(tv.tv_usec + tv.tv_sec);
    sprintf(auth_key, "%ld", (long)random());
 #endif
-   makeSessionKey(auth_key, NULL, 1);
+   make_session_key(auth_key, NULL, 1);
    bnet_fsend(dir, OKjob, jcr->VolSessionId, jcr->VolSessionTime, auth_key);
    Dmsg1(110, ">dird: %s", dir->msg);
    jcr->sd_auth_key = bstrdup(auth_key);
+   memset(auth_key, 0, sizeof(auth_key));    
 
    /*
     * Wait for the device, media, and pool information
     */
    if (!use_device_cmd(jcr)) {
       set_jcr_job_status(jcr, JS_ErrorTerminated);
+      memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
       return 0;
    }
 
@@ -171,6 +173,8 @@ int job_cmd(JCR *jcr)
    }
    V(jcr->mutex);
 
+   memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
+
    if (jcr->authenticated && !job_canceled(jcr)) {
       run_job(jcr);                  /* Run the job */
    }
@@ -181,7 +185,7 @@ int job_cmd(JCR *jcr)
  * This entry point is only called if we have a separate
  *   Storage Daemon Data port. Otherwise, the connection
  *   is made to the main port, and if it is a File daemon
- *   calling, handl_filed_connection() is called directly.
+ *   calling, handle_filed_connection() is called directly.
  */
 void connection_from_filed(void *arg)
 {
@@ -236,7 +240,7 @@ void handle_filed_connection(BSOCK *fd, char *job_name)
 
    P(jcr->mutex);
    if (!jcr->authenticated) {
-      jcr->JobStatus = JS_ErrorTerminated;
+      set_jcr_job_status(jcr, JS_ErrorTerminated);
    }
    pthread_cond_signal(&jcr->job_start_wait); /* wake waiting job */
    V(jcr->mutex);
index 74ea5157b2d3d8653f208a3458c8894c07e43f02..3867976b5d34f34bba051ac2e431d927094cefa4 100644 (file)
@@ -68,7 +68,7 @@ int read_dev_volume_label(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
    if (dev->state & ST_LABEL) {       /* did we already read label? */
       /* Compare Volume Names allow special wild card */
       if (VolName && *VolName && *VolName != '*' && strcmp(dev->VolHdr.VolName, VolName) != 0) {
-         Mmsg(&jcr->errmsg, _("Volume name mismatch on device %s: Wanted %s got %s\n"),
+         Mmsg(&jcr->errmsg, _("Wrong Volume mounted on device %s: Wanted %s have %s\n"),
            dev_name(dev), VolName, dev->VolHdr.VolName);
         /*
          * Cancel Job if too many label errors
@@ -134,8 +134,8 @@ because:\n   %s"), dev_name(dev), strerror_dev(dev));
    /* Compare Volume Names */
    Dmsg2(30, "Compare Vol names: VolName=%s hdr=%s\n", VolName?VolName:"*", dev->VolHdr.VolName);
    if (VolName && *VolName && *VolName != '*' && strcmp(dev->VolHdr.VolName, VolName) != 0) {
-      Mmsg(&jcr->errmsg, _("Volume name mismatch. Wanted %s got %s\n"),
-        VolName, dev->VolHdr.VolName);
+      Mmsg(&jcr->errmsg, _("Wrong Volume mounted on device %s: Wanted %s have %s\n"),
+          dev_name(dev), VolName, dev->VolHdr.VolName);
       /*
        * Cancel Job if too many label errors
        *  => we are in a loop
index 609fea59e81655d0541a7a9e71330322bfb5b24a..1ebf5ed269564f1fd9c24c715d9a6251a539fcea 100644 (file)
@@ -356,7 +356,7 @@ mount_error:
                 dev_file(dev));
         } else {
             Jmsg(jcr, M_ERROR, 0, _("I canot write on this volume because:\n\
-The number of files mismatch! Volume=%d Catalog=%d\n"), 
+The number of files mismatch! Volume=%u Catalog=%u\n"), 
                 dev_file(dev), dev->VolCatInfo.VolCatFiles);
             strcpy(dev->VolCatInfo.VolCatStatus, "Error");
             Dmsg0(200, "dir_update_vol_info. Set Error.\n");
@@ -386,7 +386,7 @@ int mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
       close_dev(dev);
       dev->state &= ~ST_READ; 
       if (!acquire_device_for_read(jcr, dev, block)) {
-         Emsg2(M_FATAL, 0, "Cannot open Dev=%s, Vol=%s\n", dev_name(dev),
+         Jmsg2(jcr, M_FATAL, 0, "Cannot open Dev=%s, Vol=%s\n", dev_name(dev),
               jcr->VolumeName);
         return 0;
       }
index 270747760047d0f0fd5321863a11266ad20ee2d8..73e76e16e9ac92dee5cae91d35472d5ca1381b1a 100755 (executable)
@@ -191,7 +191,7 @@ static BSR *store_vol(LEX *lc, BSR *bsr)
       }
       volume = (BSR_VOLUME *)malloc(sizeof(BSR_VOLUME));
       memset(volume, 0, sizeof(BSR_VOLUME));
-      strcpy(volume->VolumeName, p);
+      bstrncpy(volume->VolumeName, p, sizeof(volume->VolumeName));
       /* Add it to the end of the volume chain */
       if (!bsr->volume) {
         bsr->volume = volume;
@@ -218,7 +218,7 @@ static BSR *store_client(LEX *lc, BSR *bsr)
       }
       client = (BSR_CLIENT *)malloc(sizeof(BSR_CLIENT));
       memset(client, 0, sizeof(BSR_CLIENT));
-      strcpy(client->ClientName, lc->str);
+      bstrncpy(client->ClientName, lc->str, sizeof(client->ClientName));
       /* Add it to the end of the client chain */
       if (!bsr->client) {
         bsr->client = client;
@@ -248,7 +248,7 @@ static BSR *store_job(LEX *lc, BSR *bsr)
       }
       job = (BSR_JOB *)malloc(sizeof(BSR_JOB));
       memset(job, 0, sizeof(BSR_JOB));
-      strcpy(job->Job, lc->str);
+      bstrncpy(job->Job, lc->str, sizeof(job->Job));
       /* Add it to the end of the client chain */
       if (!bsr->job) {
         bsr->job = job;
@@ -801,7 +801,7 @@ void create_vol_list(JCR *jcr)
         /* Now add volumes for this bsr */
         for (bsrvol = bsr->volume; bsrvol; bsrvol=bsrvol->next) {
            vol = new_vol();
-           strcpy(vol->VolumeName, bsrvol->VolumeName);
+           bstrncpy(vol->VolumeName, bsrvol->VolumeName, sizeof(vol->VolumeName));
            vol->start_file = sfile;
            if (add_vol(jcr, vol)) {
               jcr->NumVolumes++;
@@ -821,7 +821,7 @@ void create_vol_list(JCR *jcr)
            *n++ = 0;                    /* Terminate name */
         }
         vol = new_vol();
-        strcpy(vol->VolumeName, p);
+        bstrncpy(vol->VolumeName, p, sizeof(vol->VolumeName));
         if (add_vol(jcr, vol)) {
            jcr->NumVolumes++;
         } else {
index 332125d7ddd1ec748dfb766693259d5d34d3b2b5..3434eb260c053f5d0ceee7ab38c10dbcdfbbf58c 100644 (file)
 /* Forward referenced subroutines */
 static void get_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *sessrec);
 
-/* Variables used by Child process */
-/* Global statistics */
-/* Note, these probably should be in shared memory so that 
- * they are truly global for all processes
- */
-extern struct s_shm *shm;            /* shared memory structure */
-extern int  FiledDataChan;           /* File daemon data channel (port) */
-
 
 /* Responses sent to the File daemon */
 static char OK_data[]    = "3000 OK data\n";
 static char rec_header[] = "rechdr %ld %ld %ld %ld %ld";
 
-
 /* 
  *  Read Data and send to File Daemon
  *   Returns: 0 on failure
@@ -61,6 +52,7 @@ int do_read_data(JCR *jcr)
    DEV_BLOCK *block;
    POOLMEM *hdr; 
    SESSION_LABEL sessrec;             /* session record */
+   uint32_t BlockNumber = 0;
    
    Dmsg0(20, "Start read data.\n");
 
@@ -195,13 +187,24 @@ int do_read_data(JCR *jcr)
            }
         }
 
+        if (block->block_read) {
+           if (++BlockNumber != block->BlockNumber) {
+               Jmsg(jcr, M_ERROR, 0, _("Invalid block number. Expected %u, got %u\n"),
+                   BlockNumber, block->BlockNumber);
+           }
+           BlockNumber = block->BlockNumber;
+           block->block_read = false;
+        }
+
         if (is_partial_record(rec)) {
            break;                    /* Go read full record */
         }
          
-        /* Generate Header parameters and send to File daemon
+        /*
+          * We "finally" have a full record here. Now
+         *   generate Header parameters and send to File daemon
          * Note, we build header in hdr buffer to avoid wiping
-         * out the data record
+         *   out the data record
          */
         ds->msg = hdr;
          Dmsg5(400, "Send to FD: SessId=%u SessTim=%u FI=%d Strm=%d, len=%d\n",
@@ -212,6 +215,8 @@ int do_read_data(JCR *jcr)
             Dmsg1(30, ">filed: Error Hdr=%s\n", ds->msg);
            hdr = ds->msg;
            ds->msg = rec->data;
+            Jmsg1(jcr, M_FATAL, 0, _("Error sending to File daemon. ERR=%s\n"),
+              bnet_strerror(ds));
            ok = FALSE;
            break;
         } else {
@@ -233,8 +238,8 @@ int do_read_data(JCR *jcr)
            ok = FALSE;
            break;
         }
-      }
-   }
+      } /* end for loop reading records */
+   } /* end for loop reading blocks */
    /* Send end of data to FD */
    bnet_sig(ds, BNET_EOD);
 
index d2287dea606fafbf69181605ee56310d2422ea1f..273be3d2d9f4ea7de2e9a2d6fe35d4bed80aebb9 100644 (file)
@@ -94,8 +94,8 @@ int read_records(JCR *jcr,  DEVICE *dev,
            goto next_record;         /* go read new tape */
 
         } else if (dev->state & ST_EOF) {
-            Jmsg(jcr, M_INFO, 0, "Got EOF on device %s, Volume \"%s\"\n", 
-                 dev_name(dev), jcr->VolumeName);
+            Jmsg(jcr, M_INFO, 0, "Got EOF at file %u  on device %s, Volume \"%s\"\n", 
+                 dev->file, dev_name(dev), jcr->VolumeName);
             Dmsg0(20, "read_record got eof. try again\n");
            continue;
         } else if (dev->state & ST_SHORT) {
index 327b2d525e6b06de46b773138416ef8bab8a92d5..4da29976d0d94b90c36ad55841aa08d96e117871 100644 (file)
  */
 
 /* Record state bit definitions */
-#define REC_NO_HEADER        0x01     /* No header read */
-#define REC_PARTIAL_RECORD   0x02     /* returning partial record */
-#define REC_BLOCK_EMPTY      0x04     /* not enough data in block */
-#define REC_NO_MATCH         0x08     /* No match on continuation data */
-#define REC_CONTINUATION     0x10     /* Continuation record found */
-#define REC_ISTAPE           0x20     /* Set if device is tape */
+#define REC_NO_HEADER        (1<<0)   /* No header read */
+#define REC_PARTIAL_RECORD   (1<<1)   /* returning partial record */
+#define REC_BLOCK_EMPTY      (1<<2)   /* not enough data in block */
+#define REC_NO_MATCH         (1<<3)   /* No match on continuation data */
+#define REC_CONTINUATION     (1<<4)   /* Continuation record found */
+#define REC_ISTAPE           (1<<5)   /* Set if device is tape */
 
 #define is_partial_record(r) ((r)->state & REC_PARTIAL_RECORD)
 #define is_block_empty(r)    ((r)->state & REC_BLOCK_EMPTY)
@@ -77,7 +77,7 @@
  * 
  *  This is the memory structure for the record header.
  */
-typedef struct s_dev_rec {
+struct DEV_RECORD {
    int      sync;                     /* synchronous */
    /* File and Block are always returned on reading records, but
     *  only returned on writing if sync is set (obviously).
@@ -93,7 +93,7 @@ typedef struct s_dev_rec {
    uint32_t state;                    /* state bits */
    uint8_t  ser_buf[WRITE_RECHDR_LENGTH];   /* serialized record header goes here */
    POOLMEM *data;                     /* Record data. This MUST be a memory pool item */
-} DEV_RECORD;
+};           
 
 
 /*
index 9dcd977b1eb65fe81288327c5776d2857a39ca38..14ac5972f5462d530a245785925cc789ea684c23 100644 (file)
@@ -62,7 +62,7 @@ struct s_res_store {
    char *subsys_directory;
    int require_ssl;                   /* Require SSL on all connections */
    uint32_t max_concurrent_jobs;      /* maximum concurrent jobs to run */
-   struct s_res_msgs *messages;       /* Daemon message handler */
+   MSGS *messages;                    /* Daemon message handler */
    utime_t heartbeat_interval;        /* Interval to send hb to FD */
 };
 typedef struct s_res_store STORES;
index 959ec6f3d84e3cf01b2dd52f96be1d30366a362b..8dfa9bb2824a7a154ab412da4a55256d2c8ff740 100644 (file)
@@ -1,8 +1,8 @@
 /* */
 #define VERSION "1.31"
 #define VSTRING "1"
-#define BDATE   "26 May 2003"
-#define LSMDATE "26May03"
+#define BDATE   "30 May 2003"
+#define LSMDATE "30May03"
 
 /* Debug flags */
 #define DEBUG 1