]> git.sur5r.net Git - bacula/bacula/commitdiff
Documentation + more work on restore -- kes12Aug02
authorKern Sibbald <kern@sibbald.com>
Tue, 13 Aug 2002 20:55:21 +0000 (20:55 +0000)
committerKern Sibbald <kern@sibbald.com>
Tue, 13 Aug 2002 20:55:21 +0000 (20:55 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@92 91ce42f0-d328-0410-95d8-f526ca767f89

bacula/kernstodo
bacula/src/cats/sql_get.c
bacula/src/dird/sql_cmds.c
bacula/src/dird/ua_restore.c
bacula/src/findlib/Makefile.in
bacula/src/tools/testfind.c [new file with mode: 0644]

index 613d013a13eee0e0ef8fd5f0e5750fcda7b6e593..67adbeedf0cec774d2934d3dfdc0b547393c95c4 100644 (file)
@@ -28,6 +28,8 @@ From Chuck:
 --sd.conf password does not match dir.conf storage password
 =======
 
+- Fix catalog filename truncation in sql_get and elsewhere. Use
+  only a single filename split routine.
 - Add command to reset VolFiles to a larger value (don't allow
   a smaller number or print big warning).
 - Make SD disallow writing on Volume with fewer files than in
index edd0840ce487aa17c441c5f106dab1159434689e..ec6ea58813a516175dd97f4cacb8f81b4f96c5b4 100644 (file)
@@ -133,11 +133,11 @@ int db_get_file_attributes_record(B_DB *mdb, char *fname, FILE_DBR *fdbr)
 
    db_escape_string(buf, file, fnl);
    fdbr->FilenameId = db_get_filename_record(mdb, buf);
-   Dmsg1(50, "db_get_filename_record FilenameId=%d\n", fdbr->FilenameId);
+   Dmsg2(100, "db_get_filename_record FilenameId=%d file=%s\n", fdbr->FilenameId, buf);
 
    db_escape_string(buf, spath, pnl);
    fdbr->PathId = db_get_path_record(mdb, buf);
-   Dmsg2(50, "db_get_path_record PathId=%d path=%s\n", fdbr->PathId, buf);
+   Dmsg2(100, "db_get_path_record PathId=%d path=%s\n", fdbr->PathId, buf);
 
    id = db_get_file_record(mdb, fdbr);
 
@@ -508,6 +508,51 @@ PoolType, LabelFormat FROM Pool WHERE Pool.Name='%s'", pdbr->Name);
    return stat;
 }
 
+/* Get FileSet Record  
+ * If the FileSetId is non-zero, we get its record,
+ *  otherwise, we search on the name
+ *
+ * Returns: 0 on failure
+ *         id on success 
+ */
+int db_get_fileset_record(B_DB *mdb, FILESET_DBR *fsr)
+{
+   SQL_ROW row;
+   int stat = 0;
+
+   db_lock(mdb);
+   if (fsr->FileSetId != 0) {              /* find by id */
+      Mmsg(&mdb->cmd, 
+           "SELECT FileSetId, FileSet, MD5 FROM FileSet "
+           "WHERE FileSetId=%u", fsr->FileSetId);
+   } else {                          /* find by name */
+      Mmsg(&mdb->cmd, 
+           "SELECT FileSetId, FileSet, MD5 FROM FileSet "
+           "WHERE FileSet='%s'", fsr->FileSet);
+   }  
+
+   if (QUERY_DB(mdb, mdb->cmd)) {
+      mdb->num_rows = sql_num_rows(mdb);
+      if (mdb->num_rows > 1) {
+        char ed1[30];
+         Mmsg1(&mdb->errmsg, _("More than one Pool!: %s\n"), 
+           edit_uint64(mdb->num_rows, ed1));
+      } else if (mdb->num_rows == 1) {
+        if ((row = sql_fetch_row(mdb)) == NULL) {
+            Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
+        } else {
+           fsr->FileSetId = atoi(row[0]);
+           strcpy(fsr->FileSet, row[1]);
+           strcpy(fsr->MD5, row[2]);
+           stat = fsr->FileSetId;
+        }
+      }
+      sql_free_result(mdb);
+   }
+   db_unlock(mdb);
+   return stat;
+}
+
 
 /* 
  * Get the number of Media records
index 05bcef6eb16e0155ed0a874ad888b7b6608604f7..a554a716ef9c21742f49f0b87b00540110fc07dd 100644 (file)
@@ -115,12 +115,16 @@ char *select_restore_del =
 
 /* ======= ua_restore.c */
 
+/* List last 20 Jobs */
 char *uar_list_jobs = 
    "SELECT JobId,Client.Name as Client,StartTime,Type as "
    "JobType,JobFiles,JobBytes "
    "FROM Client,Job WHERE Client.ClientId=Job.ClientId AND JobStatus='T' "
    "LIMIT 20";
 
+#ifdef HAVE_MYSQL
+/*  MYSQL IS NOT STANDARD SQL !!!!! */
+/* List Jobs where a particular file is saved */
 char *uar_file = 
    "SELECT Job.JobId as JobId, Client.Name as Client, "
    "CONCAT(Path.Path,Filename.Name) as Name, "
@@ -129,6 +133,18 @@ char *uar_file =
    "AND JobStatus='T' AND Job.JobId=File.JobId "
    "AND Path.PathId=File.PathId AND Filename.FilenameId=File.FilenameId "
    "AND Filename.Name='%s' LIMIT 20";
+#else
+/* List Jobs where a particular file is saved */
+char *uar_file = 
+   "SELECT Job.JobId as JobId, Client.Name as Client, "
+   "Path.Path||Filename.Name as Name, "
+   "StartTime,Type as JobType,JobFiles,JobBytes "
+   "FROM Client,Job,File,Filename,Path WHERE Client.ClientId=Job.ClientId "
+   "AND JobStatus='T' AND Job.JobId=File.JobId "
+   "AND Path.PathId=File.PathId AND Filename.FilenameId=File.FilenameId "
+   "AND Filename.Name='%s' LIMIT 20";
+#endif
+
 
 char *uar_sel_files = 
    "SELECT Path.Path,Filename.Name,FileIndex,JobId "
@@ -163,6 +179,7 @@ char *uar_last_full =
    "AND Level='F' AND JobStatus='T' "
    "AND JobMedia.JobId=Job.JobId "
    "AND JobMedia.MediaId=Media.MediaId "
+   "AND Job.FileSetId=%u "
    "ORDER BY Job.JobTDate DESC LIMIT 1";
 
 char *uar_full = 
@@ -183,6 +200,7 @@ char *uar_inc =
    "AND JobMedia.JobId=Job.JobId "
    "AND JobMedia.MediaId=Media.MediaId "
    "AND Job.Level='I' AND JobStatus='T' "
+   "AND Job.FileSetId=%u "
    "GROUP BY Job.JobId";
 
 char *uar_list_temp = 
@@ -192,3 +210,9 @@ char *uar_list_temp =
 char *uar_sel_jobid_temp = "SELECT JobId FROM temp";
 
 char *uar_sel_all_temp1 = "SELECT * FROM temp1";
+
+char *uar_sel_fileset = 
+   "SELECT FileSet.FileSetId,FileSet.FileSet FROM Job,"
+   "Client,FileSet WHERE Job.FileSetId=FileSet.FileSetId "
+   "AND Job.ClientId=Client.ClientId AND Client.Name='%s' "
+   "GROUP BY FileSetId";
index 7071a0b748ecf35b404fdfc7e8e1df10569357d8..797fb2ff348793371ce0a630b01ab6fb0207ce2d 100644 (file)
 extern int runcmd(UAContext *ua, char *cmd);
 
 /* Imported variables */
-extern char *uar_list_jobs;
-extern char *uar_file;
-extern char *uar_sel_files;
-extern char *uar_del_temp;
-extern char *uar_del_temp1;
-extern char *uar_create_temp;
-extern char *uar_create_temp1;
-extern char *uar_last_full;
-extern char *uar_full;
-extern char *uar_inc;
-extern char *uar_list_temp;
-extern char *uar_sel_jobid_temp;
-extern char *uar_sel_all_temp1;
+extern char *uar_list_jobs, *uar_file, *uar_sel_files;
+extern char *uar_del_temp, *uar_del_temp1, *uar_create_temp;
+extern char *uar_create_temp1, *uar_last_full, *uar_full;
+extern char *uar_inc, *uar_list_temp, *uar_sel_jobid_temp;
+extern char *uar_sel_all_temp1, *uar_sel_fileset;
 
 /* Context for insert_tree_handler() */
 typedef struct s_tree_ctx {
@@ -102,6 +94,7 @@ static int jobid_handler(void *ctx, int num_fields, char **row);
 static int next_jobid_from_list(char **p, uint32_t *JobId);
 static int user_select_jobids(UAContext *ua, JobIds *ji);
 static void user_select_files(TREE_CTX *tree);
+static int fileset_handler(void *ctx, int num_fields, char **row);
 
 
 /*
@@ -222,7 +215,7 @@ int restorecmd(UAContext *ua, char *cmd)
         job->hdr.name, working_directory);
    }
 
-   Dmsg1(000, "Submitting: %s\n", ua->cmd);
+   Dmsg1(400, "Submitting: %s\n", ua->cmd);
    
    parse_command_args(ua);
    runcmd(ua, ua->cmd);
@@ -238,7 +231,9 @@ int restorecmd(UAContext *ua, char *cmd)
  */
 static int user_select_jobids(UAContext *ua, JobIds *ji)
 {
+   char fileset_name[MAX_NAME_LENGTH];
    char *p;
+   FILESET_DBR fsr;
    JobId_t JobId;
    JOB_DBR jr;
    POOLMEM *query;
@@ -294,6 +289,7 @@ static int user_select_jobids(UAContext *ua, JobIds *ji)
         done = 0;
         break;
       case 4:                        /* Select the most recent backups */
+        query = get_pool_memory(PM_MESSAGE);
         db_sql_query(ua->db, uar_del_temp, NULL, NULL);
         db_sql_query(ua->db, uar_del_temp1, NULL, NULL);
         if (!db_sql_query(ua->db, uar_create_temp, NULL, NULL)) {
@@ -302,11 +298,34 @@ static int user_select_jobids(UAContext *ua, JobIds *ji)
         if (!db_sql_query(ua->db, uar_create_temp1, NULL, NULL)) {
             bsendmsg(ua, "%s\n", db_strerror(ua->db));
         }
+        /*
+         * Select Client 
+         */
         if (!(ji->client = get_client_resource(ua))) {
            return 0;
         }
-        query = get_pool_memory(PM_MESSAGE);
-        Mmsg(&query, uar_last_full, ji->client->hdr.name);
+
+        /*
+         * Select FileSet 
+         */
+        Mmsg(&query, uar_sel_fileset, ji->client->hdr.name);
+         start_prompt(ua, _("The defined FileSet resources are:\n"));
+        if (!db_sql_query(ua->db, query, fileset_handler, (void *)ua)) {
+            bsendmsg(ua, "%s\n", db_strerror(ua->db));
+        }
+         if (do_prompt(ua, _("Select FileSet resource"), fileset_name) < 0) {
+           free_pool_memory(query);
+           return 0;
+        }
+        fsr.FileSetId = 0;
+        strcpy(fsr.FileSet, fileset_name);
+        if (!db_get_fileset_record(ua->db, &fsr)) {
+            bsendmsg(ua, "%s\n", db_strerror(ua->db));
+           free_pool_memory(query);
+           return 0;
+        }
+
+        Mmsg(&query, uar_last_full, ji->client->hdr.name, fsr.FileSetId);
         /* Find JobId of full Backup of system */
         if (!db_sql_query(ua->db, query, NULL, NULL)) {
             bsendmsg(ua, "%s\n", db_strerror(ua->db));
@@ -322,7 +341,7 @@ static int user_select_jobids(UAContext *ua, JobIds *ji)
             bsendmsg(ua, "%s\n", db_strerror(ua->db));
         }
         /* Now find all Incremental Jobs */
-        Mmsg(&query, uar_inc, (uint32_t)ji->JobTDate, ji->ClientId);
+        Mmsg(&query, uar_inc, (uint32_t)ji->JobTDate, ji->ClientId, fsr.FileSetId);
         if (!db_sql_query(ua->db, query, NULL, NULL)) {
             bsendmsg(ua, "%s\n", db_strerror(ua->db));
         }
@@ -422,8 +441,14 @@ static int last_full_handler(void *ctx, int num_fields, char **row)
    return 0;
 }
 
-
-
+/*
+ * Callback handler build fileset prompt list
+ */
+static int fileset_handler(void *ctx, int num_fields, char **row)
+{
+   add_prompt((UAContext *)ctx, row[1]);
+   return 0;
+}
 
 /* Forward referenced commands */
 
@@ -431,6 +456,7 @@ static int markcmd(UAContext *ua, TREE_CTX *tree);
 static int countcmd(UAContext *ua, TREE_CTX *tree);
 static int findcmd(UAContext *ua, TREE_CTX *tree);
 static int lscmd(UAContext *ua, TREE_CTX *tree);
+static int dircmd(UAContext *ua, TREE_CTX *tree);
 static int helpcmd(UAContext *ua, TREE_CTX *tree);
 static int cdcmd(UAContext *ua, TREE_CTX *tree);
 static int pwdcmd(UAContext *ua, TREE_CTX *tree);
@@ -445,7 +471,7 @@ static struct cmdstruct commands[] = {
  { N_("cd"),         cdcmd,        _("change current directory")},
  { N_("pwd"),        pwdcmd,       _("print current working directory")},
  { N_("ls"),         lscmd,        _("list current directory")},    
- { N_("dir"),        lscmd,        _("list current directory")},    
+ { N_("dir"),        dircmd,       _("list current directory")},    
  { N_("count"),      countcmd,     _("count marked files")},
  { N_("find"),       findcmd,      _("find files")},
  { N_("done"),       quitcmd,      _("leave file selection mode")},
@@ -877,6 +903,60 @@ static int lscmd(UAContext *ua, TREE_CTX *tree)
    return 1;
 }
 
+extern char *getuser(uid_t uid);
+extern char *getgroup(gid_t gid);
+
+static void ls_output(char *buf, char *fname, struct stat *statp)
+{
+   char *p, *f;
+   int n;
+
+   p = encode_mode(statp->st_mode, buf);
+   n = sprintf(p, "  %2d ", (uint32_t)statp->st_nlink);
+   p += n;
+   n = sprintf(p, "%-8.8s %-8.8s", getuser(statp->st_uid), getgroup(statp->st_gid));
+   p += n;
+   n = sprintf(p, "%8ld  ", statp->st_size);
+   p += n;
+   p = encode_time(statp->st_ctime, p);
+   *p++ = ' ';
+   *p++ = ' ';
+   for (f=fname; *f; )
+      *p++ = *f++;
+   *p = 0;
+}
+
+
+/*
+ * Like ls command, but give more detail on each file
+ */
+static int dircmd(UAContext *ua, TREE_CTX *tree)
+{
+   TREE_NODE *node;
+   FILE_DBR fdbr;
+   struct stat statp;
+   char buf[1000];
+   char cwd[1100];
+
+   if (!tree->node->child) {    
+      return 1;
+   }
+   for (node = tree->node->child; node; node=node->sibling) {
+      if (ua->argc == 1 || fnmatch(ua->argk[1], node->fname, 0) == 0) {
+        tree_getpath(node, cwd, sizeof(cwd));
+        fdbr.FileId = 0;
+        fdbr.JobId = node->JobId;
+        if (db_get_file_attributes_record(ua->db, cwd, &fdbr)) {
+           decode_stat(fdbr.LStat, &statp); /* decode stat pkt */
+           ls_output(buf, cwd, &statp);
+            bsendmsg(ua, "%s\n", buf);
+        }
+      }
+   }
+   return 1;
+}
+
+
 static int helpcmd(UAContext *ua, TREE_CTX *tree) 
 {
    unsigned int i;
index be830fe1c18d07afc6f584adab31cf4252a71924..bc3b42717b0f9fe1332858b1148ee4e7b5c7cfa4 100644 (file)
@@ -23,9 +23,6 @@ dummy:
 LIBSRCS = find.c match.c find_one.c
 LIBOBJS = find.o match.o find_one.o
 
-FINDSRCS = testfind.c
-FINDOBJS = testfind.o
-
 .SUFFIXES:     .c .o
 .PHONY:
 .DONTCARE:
@@ -43,9 +40,6 @@ libfind.a: $(LIBOBJS)
        $(AR) cru $@ $(LIBOBJS)
        $(RANLIB) $@
 
-testfind: libfind.a $(FINDOBJS)
-       $(CC) -g $(LDFLAGS) -L. -L../lib -o $@ $(FINDOBJS) $(LIBS) $(DLIB) -lfind -lbac -lm
-
 Makefile: $(srcdir)/Makefile.in $(topdir)/config.status
        cd $(topdir) \
          && CONFIG_FILES=$(thisdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
@@ -56,7 +50,7 @@ uninstall:
 
 
 clean:
-       $(RMF) find testfind core a.out *.a *.o *.bak *~ *.intpro *.extpro 1 2 3
+       $(RMF) find core a.out *.a *.o *.bak *~ *.intpro *.extpro 1 2 3
 
 realclean: clean
        $(RMF) tags
diff --git a/bacula/src/tools/testfind.c b/bacula/src/tools/testfind.c
new file mode 100644 (file)
index 0000000..f98cf42
--- /dev/null
@@ -0,0 +1,249 @@
+/*  
+ * Test program for find files
+ */
+
+#include "bacula.h"
+#include "findlib/find.h"
+#include "jcr.h"
+
+
+/* Global variables */
+static int num_files = 0;
+static int max_file_len = 0;
+static int max_path_len = 0;
+static int trunc_fname = 0;
+static int trunc_path = 0;
+
+
+static int print_file(FF_PKT *ff, void *pkt);
+static void count_files(FF_PKT *ff);
+
+static void usage()
+{
+   fprintf(stderr, _(
+"\n"
+"Usage: testfind [-d debug_level] [-] [pattern1 ...]\n"
+"       -dnn        set debug level to nn\n"
+"       -           read pattern(s) from stdin\n"
+"       -?          print this message.\n"
+"\n"
+"Patterns are file inclusion -- normally directories.\n"
+"Debug level >= 1 prints each file found.\n"
+"Debug level >= 10 prints path/file for catalog.\n"
+"Errors always printed.\n"
+"Files/paths truncated is number with len > 255.\n"
+"Truncation is only in catalog.\n"
+"\n"));
+
+   exit(1);
+}
+
+
+int
+main (int argc, char *const *argv)
+{
+   FF_PKT *ff;
+   char name[1000];
+   int i, ch;
+
+   while ((ch = getopt(argc, argv, "d:?")) != -1) {
+      switch (ch) {
+         case 'd':                    /* set debug level */
+           debug_level = atoi(optarg);
+           if (debug_level <= 0) {
+              debug_level = 1; 
+           }
+           break;
+
+         case '?':
+        default:
+           usage();
+
+      }  
+   }
+   argc -= optind;
+   argv += optind;
+
+  ff = init_find_files();
+   if (argc == 0) {
+     add_fname_to_include_list(ff, 0, "/"); /* default to / */
+  } else {   
+      for (i=0; i < argc; i++) {
+        if (strcmp(argv[i], "-") == 0) {
+          while (fgets(name, sizeof(name)-1, stdin)) {
+             strip_trailing_junk(name);
+             add_fname_to_include_list(ff, 0, name); 
+          }
+          continue;
+       }
+       add_fname_to_include_list(ff, 0, argv[i]); 
+     }
+  }
+
+  find_files(ff, print_file, NULL);
+  term_find_files(ff);
+  
+   printf(_("\
+Total files    : %d\n\
+Max file length: %d\n\
+Max path length: %d\n\
+Files truncated: %d\n\
+Paths truncated: %d\n"),
+     num_files, max_file_len, max_path_len,
+     trunc_fname, trunc_path);
+  
+  sm_dump(False);
+  exit(0);
+}
+
+static int print_file(FF_PKT *ff, void *pkt)
+{
+   switch (ff->type) {
+   case FT_LNKSAVED:
+      if (debug_level == 1) {
+         printf("%s\n", ff->fname);
+      } else if (debug_level > 1) {
+         printf("Lnka: %s -> %s\n", ff->fname, ff->link);
+      }
+      break;
+   case FT_REGE:
+      if (debug_level == 1) {
+         printf("%s\n", ff->fname);
+      } else if (debug_level > 1) {
+         printf("Empty: %s\n", ff->fname);
+      }
+      count_files(ff);
+      break; 
+   case FT_REG:
+      if (debug_level == 1) {
+         printf("%s\n", ff->fname);
+      } else if (debug_level > 1) {
+         printf("Reg: %s\n", ff->fname);
+      }
+      count_files(ff);
+      break;
+   case FT_LNK:
+      if (debug_level == 1) {
+         printf("%s\n", ff->fname);
+      } else if (debug_level > 1) {
+         printf("Lnk: %s -> %s\n", ff->fname, ff->link);
+      }
+      count_files(ff);
+      break;
+   case FT_DIR:
+      if (debug_level == 1) {
+         printf("%s\n", ff->fname);
+      } else if (debug_level > 1) {
+         printf("Dir: %s\n", ff->fname);
+      }
+      count_files(ff);
+      break;
+   case FT_SPEC:
+      if (debug_level == 1) {
+         printf("%s\n", ff->fname);
+      } else if (debug_level > 1) {
+         printf("Spec: %s\n", ff->fname);
+      }
+      count_files(ff);
+      break;
+   case FT_NOACCESS:
+      printf(_("Err: Could not access %s: %s\n"), ff->fname, strerror(errno));
+      break;
+   case FT_NOFOLLOW:
+      printf(_("Err: Could not follow ff->link %s: %s\n"), ff->fname, strerror(errno));
+      break;
+   case FT_NOSTAT:
+      printf(_("Err: Could not stat %s: %s\n"), ff->fname, strerror(errno));
+      break;
+   case FT_NOCHG:
+      printf(_("Skip: File not saved. No change. %s\n"), ff->fname);
+      break;
+   case FT_ISARCH:
+      printf(_("Err: Attempt to backup archive. Not saved. %s\n"), ff->fname);
+      break;
+   case FT_NORECURSE:
+      printf(_("Recursion turned off. Directory not entered. %s\n"), ff->fname);
+      break;
+   case FT_NOFSCHG:
+      printf(_("Skip: File system change prohibited. Directory not entered. %s\n"), ff->fname);
+      break;
+   case FT_NOOPEN:
+      printf(_("Err: Could not open directory %s: %s\n"), ff->fname, strerror(errno));
+      break;
+   default:
+      printf(_("Err: Unknown file ff->type %d: %s\n"), ff->type, ff->fname);
+      break;
+   }
+   return 1;
+}
+
+static void count_files(FF_PKT *ar) 
+{
+   int fnl, pnl;
+   char *l, *p;
+   char file[MAXSTRING];
+   char spath[MAXSTRING];
+
+   num_files++;
+
+   /* Find path without the filename.  
+    * I.e. everything after the last / is a "filename".
+    * OK, maybe it is a directory name, but we treat it like
+    * a filename. If we don't find a / then the whole name
+    * must be a path name (e.g. c:).
+    */
+   for (p=l=ar->fname; *p; p++) {
+      if (*p == '/') {
+        l = p;                       /* set pos of last slash */
+      }
+   }
+   if (*l == '/') {                   /* did we find a slash? */
+      l++;                           /* yes, point to filename */
+   } else {                          /* no, whole thing must be path name */
+      l = p;
+   }
+
+   /* If filename doesn't exist (i.e. root directory), we
+    * simply create a blank name consisting of a single 
+    * space. This makes handling zero length filenames
+    * easier.
+    */
+   fnl = p - l;
+   if (fnl > max_file_len) {
+      max_file_len = fnl;
+   }
+   if (fnl > 255) {
+      printf(_("===== Filename truncated to 255 chars: %s\n"), l);
+      fnl = 255;
+      trunc_fname++;
+   }
+   if (fnl > 0) {
+      strncpy(file, l, fnl);         /* copy filename */
+      file[fnl] = 0;
+   } else {
+      file[0] = ' ';                  /* blank filename */
+      file[1] = 0;
+   }
+
+   pnl = l - ar->fname;    
+   if (pnl > max_path_len) {
+      max_path_len = pnl;
+   }
+   if (pnl > 255) {
+      printf(_("========== Path name truncated to 255 chars: %s\n"), ar->fname);
+      pnl = 255;
+      trunc_path++;
+   }
+   strncpy(spath, ar->fname, pnl);
+   spath[pnl] = 0;
+   if (pnl == 0) {
+      spath[0] = ' ';
+      spath[1] = 0;
+      printf(_("========== Path length is zero. File=%s\n"), ar->fname);
+   }
+   if (debug_level >= 10) {
+      printf("Path: %s\n", spath);
+      printf("File: %s\n", file);
+   }
+
+}