]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/tools/dbcheck.c
Fix compiler warning
[bacula/bacula] / bacula / src / tools / dbcheck.c
index 07f4d8c4e4bc7152d19e0ebe007a59db02bd5fb3..7299371805a6476d54942ece9fcd762b89b4f4d5 100644 (file)
@@ -1,29 +1,20 @@
 /*
-   Bacula® - The Network Backup Solution
-
-   Copyright (C) 2002-2008 Free Software Foundation Europe e.V.
-
-   The main author of Bacula is Kern Sibbald, with contributions from
-   many others, a complete list can be found in the file AUTHORS.
-   This program is Free Software; you can redistribute it and/or
-   modify it under the terms of version two of the GNU General Public
-   License as published by the Free Software Foundation and included
-   in the file LICENSE.
-
-   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., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.
-
-   Bacula® is a registered trademark of Kern Sibbald.
-   The licensor of Bacula is the Free Software Foundation Europe
-   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
-   Switzerland, email:ftf@fsfeurope.org.
+   Bacula(R) - The Network Backup Solution
+
+   Copyright (C) 2000-2016 Kern Sibbald
+
+   The original author of Bacula is Kern Sibbald, with contributions
+   from many others, a complete list can be found in the file AUTHORS.
+
+   You may use this file and others of this release according to the
+   license defined in the LICENSE file, which includes the Affero General
+   Public License, v3.0 ("AGPLv3") and some additional permissions and
+   terms pursuant to its AGPLv3 Section 7.
+
+   This notice must be preserved when any source code is 
+   conveyed and/or propagated.
+
+   Bacula(R) is a registered trademark of Kern Sibbald.
 */
 /*
  *
@@ -32,8 +23,6 @@
  *
  *   Kern E. Sibbald, August 2002
  *
- *   Version $Id$
- *
  */
 
 #include "bacula.h"
 
 extern bool parse_dir_config(CONFIG *config, const char *configfile, int exit_code);
 
-/* Dummy functions */
-int generate_daemon_event(JCR *jcr, const char *event) 
-   { return 1; }
-
 typedef struct s_id_ctx {
    int64_t *Id;                       /* ids to be modified */
    int num_ids;                       /* ids stored */
@@ -63,19 +48,21 @@ typedef struct s_name_ctx {
    int tot_ids;                       /* total to process */
 } NAME_LIST;
 
-/* Global variables */
+/* Global variables */ 
+
 static bool fix = false;
 static bool batch = false;
-static B_DB *db;
+static BDB *db;
 static ID_LIST id_list;
 static NAME_LIST name_list;
 static char buf[20000];
 static bool quit = false;
 static CONFIG *config;
+static const char *idx_tmp_name; 
 
 #define MAX_ID_LIST_LEN 10000000
 
-/* Forward referenced functions */
+/* Forward referenced functions */ 
 static int make_id_list(const char *query, ID_LIST *id_list);
 static int delete_id_list(const char *query, ID_LIST *id_list);
 static int make_name_list(const char *query, NAME_LIST *name_list);
@@ -99,29 +86,28 @@ static void do_interactive_mode();
 static bool yes_no(const char *prompt);
 static bool check_idx(const char *col_name);
 static bool create_tmp_idx(const char *idx_name, const char *table_name, 
-              const char *col_name);
+               const char *col_name);
 static bool drop_tmp_idx(const char *idx_name, const char *table_name);
-#ifdef HAVE_MYSQL
 static int check_idx_handler(void *ctx, int num_fields, char **row);
-#endif
-
-
-/* Global variables */
-static const char *idx_tmp_name;
 
 static void usage()
 {
    fprintf(stderr,
-"Usage: dbcheck [-c config ] [-B] [-C catalog name] [-d debug_level] <working-directory> <bacula-database> <user> <password> [<dbhost>] [<dbport>]\n"
+PROG_COPYRIGHT
+"\n%sVersion: %s (%s)\n\n"
+"Usage: dbcheck [-c config ] [-B] [-C catalog name] [-d debug_level] <working-directory> <bacula-database> <user> <password> [<dbhost>] [<dbport>] [<dbport>] [<dbsslmode>] [<dbsslkey>] [<dbsslcert>] [<dbsslca>]\n"
 "       -b              batch mode\n"
 "       -C              catalog name in the director conf file\n"
 "       -c              Director conf filename\n"
 "       -B              print catalog configuration and exit\n"
 "       -d <nn>         set debug level to <nn>\n"
-"       -dt             print timestamp in debug output\n"
+"       -dt             print timestamp in debug output\n"
 "       -f              fix inconsistencies\n"
+"       -t              test if client library is thread-safe\n"
 "       -v              verbose\n"
-"       -?              print this message\n\n");
+"       -?              print this message\n"
+"\n", 2002, "", VERSION, BDATE);
+
    exit(1);
 }
 
@@ -129,6 +115,8 @@ int main (int argc, char *argv[])
 {
    int ch;
    const char *user, *password, *db_name, *dbhost;
+   const char *dbsslmode = NULL, *dbsslkey = NULL, *dbsslcert = NULL, *dbsslca = NULL;
+   const char *dbsslcapath = NULL, *dbsslcipher = NULL;
    int dbport = 0;
    bool print_catalog=false;
    char *configfile = NULL;
@@ -138,31 +126,28 @@ int main (int argc, char *argv[])
    setlocale(LC_ALL, "");
    bindtextdomain("bacula", LOCALEDIR);
    textdomain("bacula");
+   lmgr_init_thread();
 
    my_name_is(argc, argv, "dbcheck");
-   init_msg(NULL, NULL);              /* setup message handler */
+   init_msg(NULL, NULL);             /* setup message handler */
 
    memset(&id_list, 0, sizeof(id_list));
    memset(&name_list, 0, sizeof(name_list));
 
-   while ((ch = getopt(argc, argv, "bc:C:d:fvB?")) != -1) {
+   while ((ch = getopt(argc, argv, "bc:C:d:fvB?")) != -1) { 
       switch (ch) {
       case 'B':
          print_catalog = true;     /* get catalog information from config */
          break;
-
       case 'b':                    /* batch */
          batch = true;
          break;
-
       case 'C':                    /* CatalogName */
           catalogname = optarg;
          break;
-
       case 'c':                    /* configfile */
           configfile = optarg;
          break;
-
       case 'd':                    /* debug level */
          if (*optarg == 't') {
             dbg_timestamp = true;
@@ -173,15 +158,12 @@ int main (int argc, char *argv[])
             }
          }
          break;
-
       case 'f':                    /* fix inconsistencies */
          fix = true;
          break;
-
       case 'v':
          verbose++;
          break;
-
       case '?':
       default:
          usage();
@@ -198,7 +180,7 @@ int main (int argc, char *argv[])
       if (argc > 0) {
          Pmsg0(0, _("Warning skipping the additional parameters for working directory/dbname/user/password/host.\n"));
       }
-      config = new_config_parser();
+      config = New(CONFIG());
       parse_dir_config(config, configfile, M_ERROR_TERM);
       LockRes();
       foreach_res(catalog, R_CATALOG) {
@@ -231,10 +213,23 @@ int main (int argc, char *argv[])
 
          /* Print catalog information and exit (-B) */
          if (print_catalog) {
-            POOLMEM *buf = get_pool_memory(PM_MESSAGE);
-            printf("%sdb_type=%s\nworking_dir=%s\n", catalog->display(buf),
-                   db_get_type(), working_directory);
-            free_pool_memory(buf);
+
+            POOLMEM *catalog_details = get_pool_memory(PM_MESSAGE);
+            db = db_init_database(NULL, catalog->db_driver, catalog->db_name, catalog->db_user,
+                    catalog->db_password, catalog->db_address,
+                    catalog->db_port, catalog->db_socket,
+                    catalog->db_ssl_mode,
+                    catalog->db_ssl_key, catalog->db_ssl_cert, 
+                    catalog->db_ssl_ca,
+                    catalog->db_ssl_capath, catalog->db_ssl_cipher,
+                    catalog->mult_db_connections,
+                    catalog->disable_batch_insert);
+            if (db) {
+               printf("%sdb_type=%s\nworking_dir=%s\n", catalog->display(catalog_details),
+                  db_get_engine_name(db), working_directory);
+               db_close_database(NULL, db);
+            }
+            free_pool_memory(catalog_details);
             exit(0);
          }
 
@@ -246,9 +241,15 @@ int main (int argc, char *argv[])
             dbhost = NULL;
          }
          dbport = catalog->db_port;
+         dbsslmode = catalog->db_ssl_mode;
+         dbsslkey = catalog->db_ssl_key;
+         dbsslcert = catalog->db_ssl_cert;
+         dbsslca = catalog->db_ssl_ca;
+         dbsslcapath = catalog->db_ssl_capath;
+         dbsslcipher = catalog->db_ssl_cipher;
       }
    } else {
-      if (argc > 6) {
+      if (argc > 10) {
          Pmsg0(0, _("Wrong number of arguments.\n"));
          usage();
       }
@@ -265,45 +266,55 @@ int main (int argc, char *argv[])
       password = "";
       dbhost = NULL;
 
-      if (argc == 2) {
+      if (argc >= 2) {
          db_name = argv[1];
          user = db_name;
-      } else if (argc == 3) {
-         db_name = argv[1];
-         user = argv[2];
-      } else if (argc == 4) {
-         db_name = argv[1];
-         user = argv[2];
-         password = argv[3];
-      } else if (argc == 5) {
-         db_name = argv[1];
-         user = argv[2];
-         password = argv[3];
-         dbhost = argv[4];
-      } else if (argc == 6) {
-         db_name = argv[1];
-         user = argv[2];
-         password = argv[3];
-         dbhost = argv[4];
-         errno = 0;
-         dbport = strtol(argv[5], &endptr, 10);
-         if (*endptr != '\0') {
-            Pmsg0(0, _("Database port must be a numeric value.\n"));
-            exit(1);
-         } else if (errno == ERANGE) {
-            Pmsg0(0, _("Database port must be a int value.\n"));
-            exit(1);
-         }
-      }
+         if (argc >= 3) {
+            user = argv[2];
+            if (argc >= 4) {
+               password = argv[3];
+               if (argc >= 5) {
+                  dbhost = argv[4];
+                  if (argc >= 6) {
+                     errno = 0;
+                     dbport = strtol(argv[5], &endptr, 10);
+                     if (*endptr != '\0') {
+                        Pmsg0(0, _("Database port must be a numeric value.\n"));
+                        exit(1);
+                     } else if (errno == ERANGE) {
+                        Pmsg0(0, _("Database port must be a int value.\n"));
+                        exit(1);
+                     }
+                     if (argc >= 7) {
+                        dbsslmode = argv[6];
+                        if (argc >= 8) {
+                           dbsslkey = argv[7];
+                           dbsslcert = argv[8];
+                           if (argc == 10) {
+                              dbsslca = argv[9];
+                           } /* if (argc == 10) */
+                        } /* if (argc >= 8) */
+                     } /* if (argc >= 7) */
+                  } /* if (argc >= 6) */
+               } /* if (argc >= 5) */
+            } /* if (argc >= 4) */
+         } /* if (argc >= 3) */
+      } /* if (argc >= 2) */
    }
 
    /* Open database */
-   db = db_init_database(NULL, db_name, user, password, dbhost, dbport, NULL, 0);
-   if (!db_open_database(NULL, db)) {
+   db = db_init_database(NULL, NULL, db_name, user, password, dbhost,
+          dbport, NULL, dbsslmode, dbsslkey, dbsslcert, dbsslca,
+           dbsslcapath, dbsslcipher, false, false);
+
+   if (!db || !db_open_database(NULL, db)) {
       Emsg1(M_FATAL, 0, "%s", db_strerror(db));
           return 1;
    }
 
+   /* Drop temporary index idx_tmp_name if it already exists */
+   drop_tmp_idx("idxPIchk", "File");
+
    if (batch) {
       repair_bad_paths();
       repair_bad_filenames();
@@ -322,12 +333,39 @@ int main (int argc, char *argv[])
       do_interactive_mode();
    }
 
-   db_close_database(NULL, db);
+   /* Drop temporary index idx_tmp_name */
+   drop_tmp_idx("idxPIchk", "File");
+
+   if (db) db_close_database(NULL, db);
    close_msg(NULL);
    term_msg();
+   lmgr_cleanup_main();
    return 0;
 }
 
+void print_catalog_details(CAT *catalog, const char *working_dir)
+{
+   POOLMEM *catalog_details = get_pool_memory(PM_MESSAGE);
+
+   /*
+    * Instantiate a BDB class and see what db_type gets assigned to it.
+    */
+   db = db_init_database(NULL, catalog->db_driver, catalog->db_name, catalog->db_user,
+                         catalog->db_password, catalog->db_address,
+                         catalog->db_port, catalog->db_socket,
+                         catalog->db_ssl_mode, catalog->db_ssl_key, 
+                         catalog->db_ssl_cert, catalog->db_ssl_ca,
+                         catalog->db_ssl_capath, catalog->db_ssl_cipher,
+                         catalog->mult_db_connections,
+                         catalog->disable_batch_insert);
+   if (db) {
+      printf("%sdb_type=%s\nworking_dir=%s\n", catalog->display(catalog_details),
+             db_get_engine_name(db), working_directory);
+      db_close_database(NULL, db);
+   }
+   free_pool_memory(catalog_details);
+}
+
 static void do_interactive_mode()
 {
    const char *cmd;
@@ -342,7 +380,7 @@ static void do_interactive_mode()
    else
       printf(_(" Verbose is off.\n"));
 
-   printf(_("Please select the fuction you want to perform.\n"));
+   printf(_("Please select the function you want to perform.\n"));
 
    while (!quit) {
       if (fix) {
@@ -489,7 +527,6 @@ static int print_job_handler(void *ctx, int num_fields, char **row)
    return 0;
 }
 
-
 static int print_jobmedia_handler(void *ctx, int num_fields, char **row)
 {
    printf(_("Orphaned JobMediaId=%s JobId=%s Volume=\"%s\"\n"),
@@ -518,7 +555,6 @@ static int print_client_handler(void *ctx, int num_fields, char **row)
    return 0;
 }
 
-
 /*
  * Called here with each id to be added to the list
  */
@@ -597,7 +633,6 @@ static int name_list_handler(void *ctx, int num_fields, char **row)
    return 0;
 }
 
-
 /*
  * Construct name list
  */
@@ -624,7 +659,6 @@ static void print_name_list(NAME_LIST *name_list)
    }
 }
 
-
 /*
  * Free names in the list
  */
@@ -701,7 +735,6 @@ static void eliminate_duplicate_paths()
    printf(_("Checking for duplicate Path entries.\n"));
 
    /* Make list of duplicated names */
-
    query = "SELECT Path, count(Path) as Count FROM Path "
            "GROUP BY Path HAVING count(Path) > 1";
 
@@ -719,7 +752,7 @@ static void eliminate_duplicate_paths()
       /* Loop through list of duplicate names */
       for (int i=0; i<name_list.num_ids; i++) {
          /* Get all the Ids of each name */
-         db_escape_string(NULL, db, esc_name, name_list.name[i], strlen(name_list.name[i]));
+         db_escape_string(NULL, db,  esc_name, name_list.name[i], strlen(name_list.name[i]));
          bsnprintf(buf, sizeof(buf), "SELECT PathId FROM Path WHERE Path='%s'", esc_name);
          if (verbose > 1) {
             printf("%s\n", buf);
@@ -768,7 +801,7 @@ static void eliminate_orphaned_jobmedia_records()
             char ed1[50];
             bsnprintf(buf, sizeof(buf),
 "SELECT JobMedia.JobMediaId,JobMedia.JobId,Media.VolumeName FROM JobMedia,Media "
-"WHERE JobMedia.JobMediaId=%s AND Media.MediaId=JobMedia.MediaId", 
+        "WHERE JobMedia.JobMediaId=%s AND Media.MediaId=JobMedia.MediaId",
                edit_int64(id_list.Id[i], ed1));
             if (!db_sql_query(db, buf, print_jobmedia_handler, NULL)) {
                printf("%s\n", db_strerror(db));
@@ -812,7 +845,7 @@ static void eliminate_orphaned_file_records()
             char ed1[50];
             bsnprintf(buf, sizeof(buf),
 "SELECT File.FileId,File.JobId,Filename.Name FROM File,Filename "
-"WHERE File.FileId=%s AND File.FilenameId=Filename.FilenameId", 
+   "WHERE File.FileId=%s AND File.FilenameId=Filename.FilenameId",
                edit_int64(id_list.Id[i], ed1));
             if (!db_sql_query(db, buf, print_file_handler, NULL)) {
                printf("%s\n", db_strerror(db));
@@ -836,11 +869,21 @@ static void eliminate_orphaned_file_records()
 
 static void eliminate_orphaned_path_records()
 {
+   db_int64_ctx lctx;
+   lctx.count=0;
+   db_sql_query(db, "SELECT 1 FROM Job WHERE HasCache=1 LIMIT 1", 
+                db_int64_handler, &lctx);
+   
+   if (lctx.count == 1) {
+      printf(_("Pruning orphaned Path entries isn't possible when using BVFS.\n"));
+      return;
+   }
+
    idx_tmp_name = NULL;
-   /* check the existence of the required "one column" index */
+   /* Check the existence of the required "one column" index */
    if (!check_idx("PathId"))  {
       if (yes_no(_("Create temporary index? (yes/no): "))) {
-         /* create temporary index PathId  */
+         /* create temporary index PathId */
          create_tmp_idx("idxPIchk", "File", "PathId");
       }
    }
@@ -880,17 +923,17 @@ static void eliminate_orphaned_path_records()
          exit(1);
       }
    } 
-   /* drop temporary index idx_tmp_name */
+   /* Drop temporary index idx_tmp_name */
    drop_tmp_idx("idxPIchk", "File");
 }
 
 static void eliminate_orphaned_filename_records()
 {
    idx_tmp_name = NULL;
-   /* check the existence of the required "one column" index */
+   /* Check the existence of the required "one column" index */
    if (!check_idx("FilenameId") )      {
       if (yes_no(_("Create temporary index? (yes/no): "))) {
-         /* create temporary index FilenameId  */
+         /* Create temporary index FilenameId */
          create_tmp_idx("idxFIchk", "File", "FilenameId");
       }
    }
@@ -930,7 +973,7 @@ static void eliminate_orphaned_filename_records()
          exit(1);
       }
    }
-   /* drop temporary index idx_tmp_name */
+   /* Drop temporary index idx_tmp_name */
    drop_tmp_idx("idxFIchk", "File");
 
 }
@@ -1055,7 +1098,6 @@ static void eliminate_orphaned_job_records()
    }
 }
 
-
 static void eliminate_admin_records()
 {
    const char *query;
@@ -1122,9 +1164,6 @@ static void eliminate_restore_records()
    }
 }
 
-
-
-
 static void repair_bad_filenames()
 {
    const char *query;
@@ -1186,6 +1225,7 @@ static void repair_bad_filenames()
          }
          db_sql_query(db, buf, NULL, NULL);
       }
+      free_pool_memory(name); 
    }
 }
 
@@ -1235,7 +1275,7 @@ static void repair_bad_paths()
          }
          /* Add trailing slash */
          len = pm_strcat(&name, "/");
-         db_escape_string(NULL, db, esc_name, name, len);
+         db_escape_string(NULL, db,  esc_name, name, len);
          bsnprintf(buf, sizeof(buf), "UPDATE Path SET Path='%s' WHERE PathId=%s",
             esc_name, edit_int64(id_list.Id[i], ed1));
          if (verbose > 1) {
@@ -1243,10 +1283,10 @@ static void repair_bad_paths()
          }
          db_sql_query(db, buf, NULL, NULL);
       }
+      free_pool_memory(name); 
    }
 }
 
-
 /*
  * Gen next input command from the terminal
  */
@@ -1277,13 +1317,11 @@ static bool yes_no(const char *prompt)
 
 bool python_set_prog(JCR*, char const*) { return false; }
 
-
 /*
  * The code below to add indexes is needed only for MySQL, and
  *  that to improve the performance.
  */
 
-#ifdef HAVE_MYSQL
 #define MAXIDX          100
 typedef struct s_idx_list {
    char *key_name;
@@ -1298,12 +1336,14 @@ static IDX_LIST idx_list[MAXIDX];
  */
 static int check_idx_handler(void *ctx, int num_fields, char **row)
 {
-   /* Table | Non_unique | Key_name | Seq_in_index | Column_name |...
+   /* 
+    * Table | Non_unique | Key_name | Seq_in_index | Column_name |... 
     * File  |          0 | PRIMARY  |            1 | FileId      |... 
-    */
+    */ 
    char *name, *key_name, *col_name;
    int i, len;
    int found = false;
    name = (char *)ctx;
    key_name = row[2];
    col_name = row[4];
@@ -1317,7 +1357,7 @@ static int check_idx_handler(void *ctx, int num_fields, char **row)
          break;
       }
    }
-   /* if the new Key_name, add it to the list */
+   /* If the new Key_name, add it to the list */
    if (!found) {
       len = strlen(key_name) + 1;
       idx_list[i].key_name = (char *)malloc(len);
@@ -1331,25 +1371,28 @@ static int check_idx_handler(void *ctx, int num_fields, char **row)
    }
    return 0;
 }
-#endif
 
 /*
  * Return TRUE if "one column" index over *col_name exists
  */
 static bool check_idx(const char *col_name)
 {
-#ifdef HAVE_MYSQL
    int i;
    int found = false;
+   const char *query = "SHOW INDEX FROM File";
 
+   if (db_get_type_index(db) != SQL_TYPE_MYSQL) {
+      return true;
+   }
+   /* Continue for MySQL */
    memset(&idx_list, 0, sizeof(idx_list));
-   connst char *query = "SHOW INDEX FROM File";
    if (!db_sql_query(db, query, check_idx_handler, (void *)col_name)) {
       printf("%s\n", db_strerror(db));
    }
-
-   for(i = 0; (idx_list[i].key_name != NULL) && (i < MAXIDX) ; i++) {
-      /* NOTE : if (idx_list[i].count_key > 1) then index idx_list[i].key_name is "multiple-column" index */
+   for (i = 0; (idx_list[i].key_name != NULL) && (i < MAXIDX) ; i++) {
+      /*
+       * NOTE : if (idx_list[i].count_key > 1) then index idx_list[i].key_name is "multiple-column" index
+       */
       if ((idx_list[i].count_key == 1) && (idx_list[i].count_col == 1)) {
          /* "one column" index over *col_name found */
          found = true;
@@ -1362,18 +1405,14 @@ static bool check_idx(const char *col_name)
    } else {
       printf(_("Note. Index over the %s column not found, that can greatly slow down dbcheck.\n"), col_name);
    }
-
    return found;
-#else
-   return true;
-#endif
 }
 
 /*
  * Create temporary one-column index
  */
 static bool create_tmp_idx(const char *idx_name, const char *table_name, 
-               const char *col_name)
+                           const char *col_name) 
 {
    idx_tmp_name = NULL;
    printf(_("Create temporary index... This may take some time!\n"));