]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/tools/dbcheck.c
Change to inner joins. The outer joins don't get us any more resulting records
[bacula/bacula] / bacula / src / tools / dbcheck.c
index 9411818f387c77736df3c15ab11fb796fc5c6564..1963931e64efa15aa34ea67c379744c0ebc07b1d 100644 (file)
@@ -1,3 +1,30 @@
+/*
+   Bacula® - The Network Backup Solution
+
+   Copyright (C) 2002-2007 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 John Walker.
+   The licensor of Bacula is the Free Software Foundation Europe
+   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
+   Switzerland, email:ftf@fsfeurope.org.
+*/
 /*
  *
  *  Program to check a Bacula database for consistency and to
  *   Version $Id$
  *
  */
-/*
-   Copyright (C) 2002-2004 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 "cats/cats.h"
+#include "lib/runscript.h"
 #include "dird/dird_conf.h"
 
 /* Dummy functions */
@@ -37,7 +46,7 @@ int generate_daemon_event(JCR *jcr, const char *event)
    { return 1; }
 
 typedef struct s_id_ctx {
-   uint32_t *Id;                      /* ids to be modified */
+   int64_t *Id;                       /* ids to be modified */
    int num_ids;                       /* ids stored */
    int max_ids;                       /* size of array */
    int num_del;                       /* number deleted */
@@ -60,7 +69,8 @@ static bool batch = false;
 static B_DB *db;
 static ID_LIST id_list;
 static NAME_LIST name_list;
-static char buf[2000];
+static char buf[20000];
+static bool quit = false;
 
 #define MAX_ID_LIST_LEN 10000000
 
@@ -85,7 +95,7 @@ static void eliminate_restore_records();
 static void repair_bad_paths();
 static void repair_bad_filenames();
 static void do_interactive_mode();
-static int yes_no(const char *prompt);
+static bool yes_no(const char *prompt);
 
 
 static void usage()
@@ -109,6 +119,10 @@ int main (int argc, char *argv[])
    char *configfile = NULL;
    char *catalogname = NULL;
 
+   setlocale(LC_ALL, "");
+   bindtextdomain("bacula", LOCALEDIR);
+   textdomain("bacula");
+
    my_name_is(argc, argv, "dbcheck");
    init_msg(NULL, NULL);              /* setup message handler */
 
@@ -152,6 +166,8 @@ int main (int argc, char *argv[])
    argc -= optind;
    argv += optind;
 
+   OSDependentInit();
+
    if (configfile) {
       CAT *catalog = NULL;
       int found = 0;
@@ -172,9 +188,9 @@ int main (int argc, char *argv[])
       UnlockRes();
       if (!found) {
          if (catalogname) {
-            Pmsg2(0, "Error can not find the Catalog name[%s] in the given config file [%s]\n", catalogname, configfile);
+            Pmsg2(0, _("Error can not find the Catalog name[%s] in the given config file [%s]\n"), catalogname, configfile);
          } else {
-            Pmsg1(0, "Error there is no Catalog section in the given config file [%s]\n", configfile);
+            Pmsg1(0, _("Error there is no Catalog section in the given config file [%s]\n"), configfile);
          }
          exit(1);
       } else {
@@ -183,7 +199,7 @@ int main (int argc, char *argv[])
          director = (DIRRES *)GetNextRes(R_DIRECTOR, NULL);
          UnlockRes();
          if (!director) {
-            Pmsg0(0, "Error no Director resource defined.\n");
+            Pmsg0(0, _("Error no Director resource defined.\n"));
             exit(1);
          }
          set_working_directory(director->working_directory);
@@ -264,13 +280,19 @@ int main (int argc, char *argv[])
 
 static void do_interactive_mode()
 {
-   bool quit = false;
    const char *cmd;
 
-   printf("Hello, this is the database check/correct program.\n"
-"Modify database is %s. Verbose is %s.\n"
-"Please select the fuction you want to perform.\n",
-          fix?"On":"Off", verbose?"On":"Off");
+   printf(_("Hello, this is the database check/correct program.\n"));
+   if (fix)
+      printf(_("Modify database is on."));
+   else
+      printf(_("Modify database is off."));
+   if (verbose)
+      printf(_(" Verbose is on.\n"));
+   else
+      printf(_(" Verbose is off.\n"));
+
+   printf(_("Please select the fuction you want to perform.\n"));
 
    while (!quit) {
       if (fix) {
@@ -319,11 +341,17 @@ static void do_interactive_mode()
          switch (item) {
          case 1:
             fix = !fix;
-            printf(_("Database will %sbe modified.\n"), fix?"":_("NOT "));
+            if (fix)
+               printf(_("Database will be modified.\n"));
+            else
+               printf(_("Database will NOT be modified.\n"));
             break;
          case 2:
             verbose = verbose?0:1;
-            printf(_("Verbose is %s\n"), verbose?_("On"):_("Off"));
+            if (verbose)
+               printf(_(" Verbose is on.\n"));
+            else
+               printf(_(" Verbose is off.\n"));
             break;
          case 3:
             repair_bad_filenames();
@@ -453,14 +481,14 @@ static int id_list_handler(void *ctx, int num_fields, char **row)
    }
    if (lst->num_ids == lst->max_ids) {
       if (lst->max_ids == 0) {
-         lst->max_ids = 1000;
-         lst->Id = (uint32_t *)bmalloc(sizeof(uint32_t) * lst->max_ids);
+         lst->max_ids = 10000;
+         lst->Id = (int64_t *)bmalloc(sizeof(int64_t) * lst->max_ids);
       } else {
          lst->max_ids = (lst->max_ids * 3) / 2;
-         lst->Id = (uint32_t *)brealloc(lst->Id, sizeof(uint32_t) * lst->max_ids);
+         lst->Id = (int64_t *)brealloc(lst->Id, sizeof(int64_t) * lst->max_ids);
       }
    }
-   lst->Id[lst->num_ids++] = (uint32_t)strtod(row[0], NULL);
+   lst->Id[lst->num_ids++] = str_to_int64(row[0]);
    return 0;
 }
 
@@ -485,10 +513,11 @@ static int make_id_list(const char *query, ID_LIST *id_list)
  */
 static int delete_id_list(const char *query, ID_LIST *id_list)
 {
+   char ed1[50];
    for (int i=0; i < id_list->num_ids; i++) {
-      bsnprintf(buf, sizeof(buf), query, id_list->Id[i]);
+      bsnprintf(buf, sizeof(buf), query, edit_int64(id_list->Id[i], ed1));
       if (verbose) {
-         printf("Deleting: %s\n", buf);
+         printf(_("Deleting: %s\n"), buf);
       }
       db_sql_query(db, buf, NULL, NULL);
    }
@@ -507,7 +536,7 @@ static int name_list_handler(void *ctx, int num_fields, char **row)
    }
    if (name->num_ids == name->max_ids) {
       if (name->max_ids == 0) {
-         name->max_ids = 1000;
+         name->max_ids = 10000;
          name->name = (char **)bmalloc(sizeof(char *) * name->max_ids);
       } else {
          name->max_ids = (name->max_ids * 3) / 2;
@@ -562,7 +591,7 @@ static void eliminate_duplicate_filenames()
    const char *query;
    char esc_name[5000];
 
-   printf("Checking for duplicate Filename entries.\n");
+   printf(_("Checking for duplicate Filename entries.\n"));
 
    /* Make list of duplicated names */
    query = "SELECT Name, count(Name) as Count FROM Filename GROUP BY  Name "
@@ -571,10 +600,13 @@ static void eliminate_duplicate_filenames()
    if (!make_name_list(query, &name_list)) {
       exit(1);
    }
-   printf("Found %d duplicate Filename records.\n", name_list.num_ids);
-   if (name_list.num_ids && verbose && yes_no("Print the list? (yes/no): ")) {
+   printf(_("Found %d duplicate Filename records.\n"), name_list.num_ids);
+   if (name_list.num_ids && verbose && yes_no(_("Print the list? (yes/no): "))) {
       print_name_list(&name_list);
    }
+   if (quit) {
+      return;
+   }
    if (fix) {
       /* Loop through list of duplicate names */
       for (int i=0; i<name_list.num_ids; i++) {
@@ -588,18 +620,19 @@ static void eliminate_duplicate_filenames()
             exit(1);
          }
          if (verbose) {
-            printf("Found %d for: %s\n", id_list.num_ids, name_list.name[i]);
+            printf(_("Found %d for: %s\n"), id_list.num_ids, name_list.name[i]);
          }
          /* Force all records to use the first id then delete the other ids */
          for (int j=1; j<id_list.num_ids; j++) {
-            bsnprintf(buf, sizeof(buf), "UPDATE File SET FilenameId=%u WHERE FilenameId=%u",
-               id_list.Id[0], id_list.Id[j]);
+            char ed1[50], ed2[50];
+            bsnprintf(buf, sizeof(buf), "UPDATE File SET FilenameId=%s WHERE FilenameId=%s",
+               edit_int64(id_list.Id[0], ed1), edit_int64(id_list.Id[j], ed2));
             if (verbose > 1) {
                printf("%s\n", buf);
             }
             db_sql_query(db, buf, NULL, NULL);
-            bsnprintf(buf, sizeof(buf), "DELETE FROM Filename WHERE FilenameId=%u",
-               id_list.Id[j]);
+            bsnprintf(buf, sizeof(buf), "DELETE FROM Filename WHERE FilenameId=%s",
+               ed2);
             if (verbose > 2) {
                printf("%s\n", buf);
             }
@@ -625,10 +658,13 @@ static void eliminate_duplicate_paths()
    if (!make_name_list(query, &name_list)) {
       exit(1);
    }
-   printf("Found %d duplicate Path records.\n", name_list.num_ids);
-   if (name_list.num_ids && verbose && yes_no("Print them? (yes/no): ")) {
+   printf(_("Found %d duplicate Path records.\n"), name_list.num_ids);
+   if (name_list.num_ids && verbose && yes_no(_("Print them? (yes/no): "))) {
       print_name_list(&name_list);
    }
+   if (quit) {
+      return;
+   }
    if (fix) {
       /* Loop through list of duplicate names */
       for (int i=0; i<name_list.num_ids; i++) {
@@ -642,18 +678,18 @@ static void eliminate_duplicate_paths()
             exit(1);
          }
          if (verbose) {
-            printf("Found %d for: %s\n", id_list.num_ids, name_list.name[i]);
+            printf(_("Found %d for: %s\n"), id_list.num_ids, name_list.name[i]);
          }
          /* Force all records to use the first id then delete the other ids */
          for (int j=1; j<id_list.num_ids; j++) {
-            bsnprintf(buf, sizeof(buf), "UPDATE File SET PathId=%u WHERE PathId=%u",
-               id_list.Id[0], id_list.Id[j]);
+            char ed1[50], ed2[50];
+            bsnprintf(buf, sizeof(buf), "UPDATE File SET PathId=%s WHERE PathId=%s",
+               edit_int64(id_list.Id[0], ed1), edit_int64(id_list.Id[j], ed2));
             if (verbose > 1) {
                printf("%s\n", buf);
             }
             db_sql_query(db, buf, NULL, NULL);
-            bsnprintf(buf, sizeof(buf), "DELETE FROM Path WHERE PathId=%u",
-               id_list.Id[j]);
+            bsnprintf(buf, sizeof(buf), "DELETE FROM Path WHERE PathId=%s", ed2);
             if (verbose > 2) {
                printf("%s\n", buf);
             }
@@ -666,118 +702,163 @@ static void eliminate_duplicate_paths()
 
 static void eliminate_orphaned_jobmedia_records()
 {
-   const char *query;
+   const char *query = "SELECT JobMedia.JobMediaId,Job.JobId FROM JobMedia "
+                "LEFT OUTER JOIN Job ON (JobMedia.JobId=Job.JobId) "
+                "WHERE Job.JobId IS NULL LIMIT 300000";
 
-   printf("Checking for orphaned JobMedia entries.\n");
-   query = "SELECT JobMedia.JobMediaId,Job.JobId FROM JobMedia "
-           "LEFT OUTER JOIN Job ON (JobMedia.JobId=Job.JobId) "
-           "WHERE Job.JobId IS NULL";
+   printf(_("Checking for orphaned JobMedia entries.\n"));
    if (!make_id_list(query, &id_list)) {
       exit(1);
    }
-   printf("Found %d orphaned JobMedia records.\n", id_list.num_ids);
-   if (id_list.num_ids && verbose && yes_no("Print them? (yes/no): ")) {
-      for (int i=0; i < id_list.num_ids; i++) {
-         bsnprintf(buf, sizeof(buf),
+   /* Loop doing 300000 at a time */
+   while (id_list.num_ids != 0) {
+      printf(_("Found %d orphaned JobMedia records.\n"), id_list.num_ids);
+      if (id_list.num_ids && verbose && yes_no(_("Print them? (yes/no): "))) {
+         for (int i=0; i < id_list.num_ids; i++) {
+            char ed1[50];
+            bsnprintf(buf, sizeof(buf),
 "SELECT JobMedia.JobMediaId,JobMedia.JobId,Media.VolumeName FROM JobMedia,Media "
-"WHERE JobMedia.JobMediaId=%u AND Media.MediaId=JobMedia.MediaId", id_list.Id[i]);
-         if (!db_sql_query(db, buf, print_jobmedia_handler, NULL)) {
-            printf("%s\n", db_strerror(db));
+"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));
+            }
          }
       }
-   }
+      if (quit) {
+         return;
+      }
 
-   if (fix && id_list.num_ids > 0) {
-      printf("Deleting %d orphaned JobMedia records.\n", id_list.num_ids);
-      delete_id_list("DELETE FROM JobMedia WHERE JobMediaId=%u", &id_list);
+      if (fix && id_list.num_ids > 0) {
+         printf(_("Deleting %d orphaned JobMedia records.\n"), id_list.num_ids);
+         delete_id_list("DELETE FROM JobMedia WHERE JobMediaId=%s", &id_list);
+      } else {
+         break;                       /* get out if not updating db */
+      }
+      if (!make_id_list(query, &id_list)) {
+         exit(1);
+      }
    }
 }
 
 static void eliminate_orphaned_file_records()
 {
-   const char *query;
+   const char *query = "SELECT File.FileId,Job.JobId FROM File "
+                "LEFT OUTER JOIN Job ON (File.JobId=Job.JobId) "
+               "WHERE Job.JobId IS NULL LIMIT 300000";
 
-   printf("Checking for orphaned File entries. This may take some time!\n");
-   query = "SELECT File.FileId,Job.JobId FROM File "
-           "LEFT OUTER JOIN Job ON (File.JobId=Job.JobId) "
-           "WHERE Job.JobId IS NULL";
+   printf(_("Checking for orphaned File entries. This may take some time!\n"));
    if (verbose > 1) {
       printf("%s\n", query);
    }
    if (!make_id_list(query, &id_list)) {
       exit(1);
    }
-   printf("Found %d orphaned File records.\n", id_list.num_ids);
-   if (name_list.num_ids && verbose && yes_no("Print them? (yes/no): ")) {
-      for (int i=0; i < id_list.num_ids; i++) {
-         bsnprintf(buf, sizeof(buf),
+   /* Loop doing 300000 at a time */
+   while (id_list.num_ids != 0) {
+      printf(_("Found %d orphaned File records.\n"), id_list.num_ids);
+      if (name_list.num_ids && verbose && yes_no(_("Print them? (yes/no): "))) {
+         for (int i=0; i < id_list.num_ids; i++) {
+            char ed1[50];
+            bsnprintf(buf, sizeof(buf),
 "SELECT File.FileId,File.JobId,Filename.Name FROM File,Filename "
-"WHERE File.FileId=%u AND File.FilenameId=Filename.FilenameId", id_list.Id[i]);
-         if (!db_sql_query(db, buf, print_file_handler, NULL)) {
-            printf("%s\n", db_strerror(db));
+"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));
+            }
          }
       }
-   }
-
-   if (fix && id_list.num_ids > 0) {
-      printf("Deleting %d orphaned File records.\n", id_list.num_ids);
-      delete_id_list("DELETE FROM File WHERE FileId=%u", &id_list);
+      if (quit) {
+         return;
+      }
+      if (fix && id_list.num_ids > 0) {
+         printf(_("Deleting %d orphaned File records.\n"), id_list.num_ids);
+         delete_id_list("DELETE FROM File WHERE FileId=%s", &id_list);
+      } else {
+         break;                       /* get out if not updating db */
+      }
+      if (!make_id_list(query, &id_list)) {
+         exit(1);
+      }
    }
 }
 
 static void eliminate_orphaned_path_records()
 {
-   const char *query;
+   const char *query = "SELECT DISTINCT Path.PathId,File.PathId FROM Path "
+               "LEFT OUTER JOIN File ON (Path.PathId=File.PathId) "
+               "WHERE File.PathId IS NULL LIMIT 300000";
 
-   printf("Checking for orphaned Path entries. This may take some time!\n");
-   query = "SELECT DISTINCT Path.PathId,File.PathId FROM Path "
-           "LEFT OUTER JOIN File ON (Path.PathId=File.PathId) "
-           "WHERE File.PathId IS NULL";
+   printf(_("Checking for orphaned Path entries. This may take some time!\n"));
    if (verbose > 1) {
       printf("%s\n", query);
    }
    if (!make_id_list(query, &id_list)) {
       exit(1);
    }
-   printf("Found %d orphaned Path records.\n", id_list.num_ids);
-   if (id_list.num_ids && verbose && yes_no("Print them? (yes/no): ")) {
-      for (int i=0; i < id_list.num_ids; i++) {
-         bsnprintf(buf, sizeof(buf), "SELECT Path FROM Path WHERE PathId=%u", id_list.Id[i]);
-         db_sql_query(db, buf, print_name_handler, NULL);
+   /* Loop doing 300000 at a time */
+   while (id_list.num_ids != 0) {
+      printf(_("Found %d orphaned Path records.\n"), id_list.num_ids);
+      if (id_list.num_ids && verbose && yes_no(_("Print them? (yes/no): "))) {
+         for (int i=0; i < id_list.num_ids; i++) {
+            char ed1[50];
+            bsnprintf(buf, sizeof(buf), "SELECT Path FROM Path WHERE PathId=%s", 
+               edit_int64(id_list.Id[i], ed1));
+            db_sql_query(db, buf, print_name_handler, NULL);
+         }
+      }
+      if (quit) {
+         return;
+      }
+      if (fix && id_list.num_ids > 0) {
+         printf(_("Deleting %d orphaned Path records.\n"), id_list.num_ids);
+         delete_id_list("DELETE FROM Path WHERE PathId=%s", &id_list);
+      } else {
+         break;                       /* get out if not updating db */
+      }
+      if (!make_id_list(query, &id_list)) {
+         exit(1);
       }
-   }
-
-   if (fix && id_list.num_ids > 0) {
-      printf("Deleting %d orphaned Path records.\n", id_list.num_ids);
-      delete_id_list("DELETE FROM Path WHERE PathId=%u", &id_list);
    }
 }
 
 static void eliminate_orphaned_filename_records()
 {
-   const char *query;
+   const char *query = "SELECT Filename.FilenameId,File.FilenameId FROM Filename "
+                "LEFT OUTER JOIN File ON (Filename.FilenameId=File.FilenameId) "
+                "WHERE File.FilenameId IS NULL LIMIT 300000";
 
-   printf("Checking for orphaned Filename entries. This may take some time!\n");
-   query = "SELECT Filename.FilenameId,File.FilenameId FROM Filename "
-           "LEFT OUTER JOIN File ON (Filename.FilenameId=File.FilenameId) "
-           "WHERE File.FilenameId IS NULL";
+   printf(_("Checking for orphaned Filename entries. This may take some time!\n"));
    if (verbose > 1) {
       printf("%s\n", query);
    }
    if (!make_id_list(query, &id_list)) {
       exit(1);
    }
-   printf("Found %d orphaned Filename records.\n", id_list.num_ids);
-   if (id_list.num_ids && verbose && yes_no("Print them? (yes/no): ")) {
-      for (int i=0; i < id_list.num_ids; i++) {
-         bsnprintf(buf, sizeof(buf), "SELECT Name FROM Filename WHERE FilenameId=%u", id_list.Id[i]);
-         db_sql_query(db, buf, print_name_handler, NULL);
+   /* Loop doing 300000 at a time */
+   while (id_list.num_ids != 0) {
+      printf(_("Found %d orphaned Filename records.\n"), id_list.num_ids);
+      if (id_list.num_ids && verbose && yes_no(_("Print them? (yes/no): "))) {
+         for (int i=0; i < id_list.num_ids; i++) {
+            char ed1[50];
+            bsnprintf(buf, sizeof(buf), "SELECT Name FROM Filename WHERE FilenameId=%s", 
+               edit_int64(id_list.Id[i], ed1));
+            db_sql_query(db, buf, print_name_handler, NULL);
+         }
+      }
+      if (quit) {
+         return;
+      }
+      if (fix && id_list.num_ids > 0) {
+         printf(_("Deleting %d orphaned Filename records.\n"), id_list.num_ids);
+         delete_id_list("DELETE FROM Filename WHERE FilenameId=%s", &id_list);
+      } else {
+         break;                       /* get out if not updating db */
+      }
+      if (!make_id_list(query, &id_list)) {
+         exit(1);
       }
-   }
-
-   if (fix && id_list.num_ids > 0) {
-      printf("Deleting %d orphaned Filename records.\n", id_list.num_ids);
-      delete_id_list("DELETE FROM Filename WHERE FilenameId=%u", &id_list);
    }
 }
 
@@ -785,7 +866,7 @@ static void eliminate_orphaned_fileset_records()
 {
    const char *query;
 
-   printf("Checking for orphaned FileSet entries. This takes some time!\n");
+   printf(_("Checking for orphaned FileSet entries. This takes some time!\n"));
    query = "SELECT FileSet.FileSetId,Job.FileSetId FROM FileSet "
            "LEFT OUTER JOIN Job ON (FileSet.FileSetId=Job.FileSetId) "
            "WHERE Job.FileSetId IS NULL";
@@ -795,20 +876,23 @@ static void eliminate_orphaned_fileset_records()
    if (!make_id_list(query, &id_list)) {
       exit(1);
    }
-   printf("Found %d orphaned FileSet records.\n", id_list.num_ids);
-   if (id_list.num_ids && verbose && yes_no("Print them? (yes/no): ")) {
+   printf(_("Found %d orphaned FileSet records.\n"), id_list.num_ids);
+   if (id_list.num_ids && verbose && yes_no(_("Print them? (yes/no): "))) {
       for (int i=0; i < id_list.num_ids; i++) {
+         char ed1[50];
          bsnprintf(buf, sizeof(buf), "SELECT FileSetId,FileSet,MD5 FROM FileSet "
-                      "WHERE FileSetId=%u", id_list.Id[i]);
+                      "WHERE FileSetId=%s", edit_int64(id_list.Id[i], ed1));
          if (!db_sql_query(db, buf, print_fileset_handler, NULL)) {
             printf("%s\n", db_strerror(db));
          }
       }
    }
-
+   if (quit) {
+      return;
+   }
    if (fix && id_list.num_ids > 0) {
-      printf("Deleting %d orphaned FileSet records.\n", id_list.num_ids);
-      delete_id_list("DELETE FROM FileSet WHERE FileSetId=%u", &id_list);
+      printf(_("Deleting %d orphaned FileSet records.\n"), id_list.num_ids);
+      delete_id_list("DELETE FROM FileSet WHERE FileSetId=%s", &id_list);
    }
 }
 
@@ -816,7 +900,7 @@ static void eliminate_orphaned_client_records()
 {
    const char *query;
 
-   printf("Checking for orphaned Client entries.\n");
+   printf(_("Checking for orphaned Client entries.\n"));
    /* In English:
     *   Wiffle through Client for every Client
     *   joining with the Job table including every Client even if
@@ -833,20 +917,23 @@ static void eliminate_orphaned_client_records()
    if (!make_id_list(query, &id_list)) {
       exit(1);
    }
-   printf("Found %d orphaned Client records.\n", id_list.num_ids);
-   if (id_list.num_ids && verbose && yes_no("Print them? (yes/no): ")) {
+   printf(_("Found %d orphaned Client records.\n"), id_list.num_ids);
+   if (id_list.num_ids && verbose && yes_no(_("Print them? (yes/no): "))) {
       for (int i=0; i < id_list.num_ids; i++) {
+         char ed1[50];
          bsnprintf(buf, sizeof(buf), "SELECT ClientId,Name FROM Client "
-                      "WHERE ClientId=%u", id_list.Id[i]);
+                      "WHERE ClientId=%s", edit_int64(id_list.Id[i], ed1));
          if (!db_sql_query(db, buf, print_client_handler, NULL)) {
             printf("%s\n", db_strerror(db));
          }
       }
    }
-
+   if (quit) {
+      return;
+   }
    if (fix && id_list.num_ids > 0) {
-      printf("Deleting %d orphaned Client records.\n", id_list.num_ids);
-      delete_id_list("DELETE FROM Client WHERE ClientId=%u", &id_list);
+      printf(_("Deleting %d orphaned Client records.\n"), id_list.num_ids);
+      delete_id_list("DELETE FROM Client WHERE ClientId=%s", &id_list);
    }
 }
 
@@ -854,7 +941,7 @@ static void eliminate_orphaned_job_records()
 {
    const char *query;
 
-   printf("Checking for orphaned Job entries.\n");
+   printf(_("Checking for orphaned Job entries.\n"));
    /* In English:
     *   Wiffle through Job for every Job
     *   joining with the Client table including every Job even if
@@ -871,20 +958,27 @@ static void eliminate_orphaned_job_records()
    if (!make_id_list(query, &id_list)) {
       exit(1);
    }
-   printf("Found %d orphaned Job records.\n", id_list.num_ids);
-   if (id_list.num_ids && verbose && yes_no("Print them? (yes/no): ")) {
+   printf(_("Found %d orphaned Job records.\n"), id_list.num_ids);
+   if (id_list.num_ids && verbose && yes_no(_("Print them? (yes/no): "))) {
       for (int i=0; i < id_list.num_ids; i++) {
+         char ed1[50];
          bsnprintf(buf, sizeof(buf), "SELECT JobId,Name,StartTime FROM Job "
-                      "WHERE JobId=%u", id_list.Id[i]);
+                      "WHERE JobId=%s", edit_int64(id_list.Id[i], ed1));
          if (!db_sql_query(db, buf, print_job_handler, NULL)) {
             printf("%s\n", db_strerror(db));
          }
       }
    }
-
+   if (quit) {
+      return;
+   }
    if (fix && id_list.num_ids > 0) {
-      printf("Deleting %d orphaned Job records.\n", id_list.num_ids);
-      delete_id_list("DELETE FROM Job WHERE JobId=%u", &id_list);
+      printf(_("Deleting %d orphaned Job records.\n"), id_list.num_ids);
+      delete_id_list("DELETE FROM Job WHERE JobId=%s", &id_list);
+      printf(_("Deleting JobMedia records of orphaned Job records.\n"));
+      delete_id_list("DELETE FROM JobMedia WHERE JobId=%s", &id_list);
+      printf(_("Deleting Log records of orphaned Job records.\n"));
+      delete_id_list("DELETE FROM Log WHERE JobId=%s", &id_list);
    }
 }
 
@@ -893,7 +987,7 @@ static void eliminate_admin_records()
 {
    const char *query;
 
-   printf("Checking for Admin Job entries.\n");
+   printf(_("Checking for Admin Job entries.\n"));
    query = "SELECT Job.JobId FROM Job "
            "WHERE Job.Type='D'";
    if (verbose > 1) {
@@ -902,20 +996,23 @@ static void eliminate_admin_records()
    if (!make_id_list(query, &id_list)) {
       exit(1);
    }
-   printf("Found %d Admin Job records.\n", id_list.num_ids);
-   if (id_list.num_ids && verbose && yes_no("Print them? (yes/no): ")) {
+   printf(_("Found %d Admin Job records.\n"), id_list.num_ids);
+   if (id_list.num_ids && verbose && yes_no(_("Print them? (yes/no): "))) {
       for (int i=0; i < id_list.num_ids; i++) {
+         char ed1[50];
          bsnprintf(buf, sizeof(buf), "SELECT JobId,Name,StartTime FROM Job "
-                      "WHERE JobId=%u", id_list.Id[i]);
+                      "WHERE JobId=%s", edit_int64(id_list.Id[i], ed1));
          if (!db_sql_query(db, buf, print_job_handler, NULL)) {
             printf("%s\n", db_strerror(db));
          }
       }
    }
-
+   if (quit) {
+      return;
+   }
    if (fix && id_list.num_ids > 0) {
-      printf("Deleting %d Admin Job records.\n", id_list.num_ids);
-      delete_id_list("DELETE FROM Job WHERE JobId=%u", &id_list);
+      printf(_("Deleting %d Admin Job records.\n"), id_list.num_ids);
+      delete_id_list("DELETE FROM Job WHERE JobId=%s", &id_list);
    }
 }
 
@@ -923,7 +1020,7 @@ static void eliminate_restore_records()
 {
    const char *query;
 
-   printf("Checking for Restore Job entries.\n");
+   printf(_("Checking for Restore Job entries.\n"));
    query = "SELECT Job.JobId FROM Job "
            "WHERE Job.Type='R'";
    if (verbose > 1) {
@@ -932,20 +1029,23 @@ static void eliminate_restore_records()
    if (!make_id_list(query, &id_list)) {
       exit(1);
    }
-   printf("Found %d Restore Job records.\n", id_list.num_ids);
-   if (id_list.num_ids && verbose && yes_no("Print them? (yes/no): ")) {
+   printf(_("Found %d Restore Job records.\n"), id_list.num_ids);
+   if (id_list.num_ids && verbose && yes_no(_("Print them? (yes/no): "))) {
       for (int i=0; i < id_list.num_ids; i++) {
+         char ed1[50];
          bsnprintf(buf, sizeof(buf), "SELECT JobId,Name,StartTime FROM Job "
-                      "WHERE JobId=%u", id_list.Id[i]);
+                      "WHERE JobId=%s", edit_int64(id_list.Id[i], ed1));
          if (!db_sql_query(db, buf, print_job_handler, NULL)) {
             printf("%s\n", db_strerror(db));
          }
       }
    }
-
+   if (quit) {
+      return;
+   }
    if (fix && id_list.num_ids > 0) {
-      printf("Deleting %d Restore Job records.\n", id_list.num_ids);
-      delete_id_list("DELETE FROM Job WHERE JobId=%u", &id_list);
+      printf(_("Deleting %d Restore Job records.\n"), id_list.num_ids);
+      delete_id_list("DELETE FROM Job WHERE JobId=%s", &id_list);
    }
 }
 
@@ -957,7 +1057,7 @@ static void repair_bad_filenames()
    const char *query;
    int i;
 
-   printf("Checking for Filenames with a trailing slash\n");
+   printf(_("Checking for Filenames with a trailing slash\n"));
    query = "SELECT FilenameId,Name from Filename "
            "WHERE Name LIKE '%/'";
    if (verbose > 1) {
@@ -966,30 +1066,36 @@ static void repair_bad_filenames()
    if (!make_id_list(query, &id_list)) {
       exit(1);
    }
-   printf("Found %d bad Filename records.\n", id_list.num_ids);
-   if (id_list.num_ids && verbose && yes_no("Print them? (yes/no): ")) {
+   printf(_("Found %d bad Filename records.\n"), id_list.num_ids);
+   if (id_list.num_ids && verbose && yes_no(_("Print them? (yes/no): "))) {
       for (i=0; i < id_list.num_ids; i++) {
+         char ed1[50];
          bsnprintf(buf, sizeof(buf),
-            "SELECT Name FROM Filename WHERE FilenameId=%u", id_list.Id[i]);
+            "SELECT Name FROM Filename WHERE FilenameId=%s", 
+                edit_int64(id_list.Id[i], ed1));
          if (!db_sql_query(db, buf, print_name_handler, NULL)) {
             printf("%s\n", db_strerror(db));
          }
       }
    }
-
+   if (quit) {
+      return;
+   }
    if (fix && id_list.num_ids > 0) {
       POOLMEM *name = get_pool_memory(PM_FNAME);
       char esc_name[5000];
-      printf("Reparing %d bad Filename records.\n", id_list.num_ids);
+      printf(_("Reparing %d bad Filename records.\n"), id_list.num_ids);
       for (i=0; i < id_list.num_ids; i++) {
          int len;
+         char ed1[50];
          bsnprintf(buf, sizeof(buf),
-            "SELECT Name FROM Filename WHERE FilenameId=%u", id_list.Id[i]);
+            "SELECT Name FROM Filename WHERE FilenameId=%s", 
+               edit_int64(id_list.Id[i], ed1));
          if (!db_sql_query(db, buf, get_name_handler, name)) {
             printf("%s\n", db_strerror(db));
          }
          /* Strip trailing slash(es) */
-         for (len=strlen(name); len > 0 && name[len-1]=='/'; len--)
+         for (len=strlen(name); len > 0 && IsPathSeparator(name[len-1]); len--)
             {  }
          if (len == 0) {
             len = 1;
@@ -1000,8 +1106,8 @@ static void repair_bad_filenames()
             db_escape_string(esc_name, name, len);
          }
          bsnprintf(buf, sizeof(buf),
-            "UPDATE Filename SET Name='%s' WHERE FilenameId=%u",
-            esc_name, id_list.Id[i]);
+            "UPDATE Filename SET Name='%s' WHERE FilenameId=%s",
+            esc_name, edit_int64(id_list.Id[i], ed1));
          if (verbose > 1) {
             printf("%s\n", buf);
          }
@@ -1015,7 +1121,7 @@ static void repair_bad_paths()
    const char *query;
    int i;
 
-   printf("Checking for Paths without a trailing slash\n");
+   printf(_("Checking for Paths without a trailing slash\n"));
    query = "SELECT PathId,Path from Path "
            "WHERE Path NOT LIKE '%/'";
    if (verbose > 1) {
@@ -1024,25 +1130,29 @@ static void repair_bad_paths()
    if (!make_id_list(query, &id_list)) {
       exit(1);
    }
-   printf("Found %d bad Path records.\n", id_list.num_ids);
-   if (id_list.num_ids && verbose && yes_no("Print them? (yes/no): ")) {
+   printf(_("Found %d bad Path records.\n"), id_list.num_ids);
+   if (id_list.num_ids && verbose && yes_no(_("Print them? (yes/no): "))) {
       for (i=0; i < id_list.num_ids; i++) {
+         char ed1[50];
          bsnprintf(buf, sizeof(buf),
-            "SELECT Path FROM Path WHERE PathId=%u", id_list.Id[i]);
+            "SELECT Path FROM Path WHERE PathId=%s", edit_int64(id_list.Id[i], ed1));
          if (!db_sql_query(db, buf, print_name_handler, NULL)) {
             printf("%s\n", db_strerror(db));
          }
       }
    }
-
+   if (quit) {
+      return;
+   }
    if (fix && id_list.num_ids > 0) {
       POOLMEM *name = get_pool_memory(PM_FNAME);
       char esc_name[5000];
-      printf("Reparing %d bad Filename records.\n", id_list.num_ids);
+      printf(_("Reparing %d bad Filename records.\n"), id_list.num_ids);
       for (i=0; i < id_list.num_ids; i++) {
          int len;
+         char ed1[50];
          bsnprintf(buf, sizeof(buf),
-            "SELECT Path FROM Path WHERE PathId=%u", id_list.Id[i]);
+            "SELECT Path FROM Path WHERE PathId=%s", edit_int64(id_list.Id[i], ed1));
          if (!db_sql_query(db, buf, get_name_handler, name)) {
             printf("%s\n", db_strerror(db));
          }
@@ -1053,8 +1163,8 @@ static void repair_bad_paths()
          /* Add trailing slash */
          len = pm_strcat(&name, "/");
          db_escape_string(esc_name, name, len);
-         bsnprintf(buf, sizeof(buf), "UPDATE Path SET Path='%s' WHERE PathId=%u",
-            esc_name, id_list.Id[i]);
+         bsnprintf(buf, sizeof(buf), "UPDATE Path SET Path='%s' WHERE PathId=%s",
+            esc_name, edit_int64(id_list.Id[i], ed1));
          if (verbose > 1) {
             printf("%s\n", buf);
          }
@@ -1064,8 +1174,6 @@ static void repair_bad_paths()
 }
 
 
-
-
 /*
  * Gen next input command from the terminal
  */
@@ -1074,16 +1182,24 @@ static char *get_cmd(const char *prompt)
    static char cmd[1000];
 
    printf("%s", prompt);
-   if (fgets(cmd, sizeof(cmd), stdin) == NULL)
+   if (fgets(cmd, sizeof(cmd), stdin) == NULL) {
+      printf("\n");
+      quit = true;
       return NULL;
-   printf("\n");
+   }
    strip_trailing_junk(cmd);
    return cmd;
 }
 
-static int yes_no(const char *prompt)
+static bool yes_no(const char *prompt)
 {
    char *cmd;
    cmd = get_cmd(prompt);
-   return strcasecmp(cmd, "yes") == 0;
+   if (!cmd) {
+      quit = true;
+      return false;
+   }
+   return (strcasecmp(cmd, "yes") == 0) || (strcasecmp(cmd, _("yes")) == 0);
 }
+
+bool python_set_prog(JCR*, char const*) { return false; }