]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/cats/bvfs.c
Add more debug in src/cats/bvfs.c
[bacula/bacula] / bacula / src / cats / bvfs.c
index 349407380ce2a16bc28ba00f9443f41e791e3fe9..6b97bb21f96eae48b9d5c9ccbcfccf9daa490b9a 100644 (file)
@@ -1,8 +1,7 @@
 /*
    Bacula(R) - The Network Backup Solution
 
-   Copyright (C) 2000-2015 Kern Sibbald
-   Copyright (C) 2009-2014 Free Software Foundation Europe e.V.
+   Copyright (C) 2000-2017 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.
@@ -12,7 +11,7 @@
    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 
+   This notice must be preserved when any source code is
    conveyed and/or propagated.
 
    Bacula(R) is a registered trademark of Kern Sibbald.
 #include "lib/htable.h"
 #include "bvfs.h"
 
+#define can_access(x) (true)
+
+/* from libbacfind */
+extern int decode_stat(char *buf, struct stat *statp, int stat_size, int32_t *LinkFI);
+
 #define dbglevel      DT_BVFS|10
 #define dbglevel_sql  DT_SQL|15
 
@@ -45,7 +49,8 @@ static int result_handler(void *ctx, int fields, char **row)
    return 0;
 }
 
-Bvfs::Bvfs(JCR *j, BDB *mdb) {
+Bvfs::Bvfs(JCR *j, BDB *mdb)
+{
    jcr = j;
    jcr->inc_use_count();
    db = mdb;                 /* need to inc ref count */
@@ -56,14 +61,19 @@ Bvfs::Bvfs(JCR *j, BDB *mdb) {
    tmp = get_pool_memory(PM_NAME);
    escaped_list = get_pool_memory(PM_NAME);
    *filename = *jobids = *prev_dir = *pattern = 0;
-   dir_filenameid = pwd_id = offset = 0;
+   pwd_id = offset = 0;
    see_copies = see_all_versions = false;
+   compute_delta = true;
    limit = 1000;
    attr = new_attr(jcr);
    list_entries = result_handler;
    user_data = this;
    username = NULL;
    job_acl = client_acl = pool_acl = fileset_acl = NULL;
+   last_dir_acl = NULL;
+   dir_acl = NULL;
+   use_acl = false;
+   dir_filenameid = 0;       /* special FilenameId where Name='' */
 }
 
 Bvfs::~Bvfs() {
@@ -78,6 +88,9 @@ Bvfs::~Bvfs() {
    }
    free_attr(attr);
    jcr->dec_use_count();
+   if (dir_acl) {
+      delete dir_acl;
+   }
 }
 
 char *Bvfs::escape_list(alist *lst)
@@ -114,7 +127,8 @@ char *Bvfs::escape_list(alist *lst)
    return escaped_list;
 }
 
-void Bvfs::filter_jobid()
+/* Returns the number of jobids in the result */
+int Bvfs::filter_jobid()
 {
    POOL_MEM query;
    POOL_MEM sub_where;
@@ -123,7 +137,14 @@ void Bvfs::filter_jobid()
    /* No ACL, no username, no check */
    if (!job_acl && !fileset_acl && !client_acl && !pool_acl && !username) {
       Dmsg0(dbglevel_sql, "No ACL\n");
-      return;
+      /* Just count the number of items in the list */
+      int nb = (*jobids != 0) ? 1 : 0;
+      for (char *p=jobids; *p ; p++) {
+         if (*p == ',') {
+            nb++;
+         }
+      }
+      return nb;
    }
 
    if (job_acl) {
@@ -173,18 +194,21 @@ void Bvfs::filter_jobid()
    Dmsg1(dbglevel_sql, "q=%s\n", query.c_str());
    db->bdb_sql_query(query.c_str(), db_list_handler, &ctx);
    pm_strcpy(jobids, ctx.list);
+   return ctx.count;
 }
 
-void Bvfs::set_jobid(JobId_t id)
+/* Return the number of jobids after the filter */
+int Bvfs::set_jobid(JobId_t id)
 {
    Mmsg(jobids, "%lld", (uint64_t)id);
-   filter_jobid();
+   return filter_jobid();
 }
 
-void Bvfs::set_jobids(char *ids)
+/* Return the number of jobids after the filter */
+int Bvfs::set_jobids(char *ids)
 {
    pm_strcpy(jobids, ids);
-   filter_jobid();
+   return filter_jobid();
 }
 
 /*
@@ -219,7 +243,7 @@ public:
       nb_node = 0;
       table_node = New(alist(5, owned_by_alist));
       table_node->append(nodes);
-   }
+   };
 
    hlink *get_hlink() {
       if (++nb_node >= max_node) {
@@ -228,23 +252,23 @@ public:
          table_node->append(nodes);
       }
       return nodes + nb_node;
-   }
+   };
 
    bool lookup(char *pathid) {
       bool ret = cache_ppathid->lookup(pathid) != NULL;
       return ret;
-   }
+   };
 
    void insert(char *pathid) {
       hlink *h = get_hlink();
       cache_ppathid->insert(pathid, h);
-   }
+   };
 
    ~pathid_cache() {
       cache_ppathid->destroy();
       free(cache_ppathid);
       delete table_node;
-   }
+   };
 private:
    pathid_cache(const pathid_cache &); /* prohibit pass by value */
    pathid_cache &operator= (const pathid_cache &);/* prohibit class assignment*/
@@ -481,7 +505,7 @@ static int update_path_hierarchy_cache(JCR *jcr,
       "AND h.PPathId NOT IN (SELECT PathId FROM PathVisibility WHERE JobId=%s)",
            jobid, jobid, jobid );
 
-   }  else if (mdb->bdb_get_type_index() == SQL_TYPE_MYSQL) {
+   } else if (mdb->bdb_get_type_index() == SQL_TYPE_MYSQL) {
       Mmsg(mdb->cmd,
   "INSERT INTO PathVisibility (PathId, JobId)  "
    "SELECT a.PathId,%s "
@@ -493,7 +517,7 @@ static int update_path_hierarchy_cache(JCR *jcr,
       "LEFT JOIN PathVisibility AS b ON (b.JobId=%s and a.PathId = b.PathId) "
       "WHERE b.PathId IS NULL",  jobid, jobid, jobid);
 
-   } else {                     /* TODO: Test the MYSQL Query with PostgreSQL */
+   } else {
       Mmsg(mdb->cmd,
   "INSERT INTO PathVisibility (PathId, JobId)  "
    "SELECT a.PathId,%s "
@@ -513,7 +537,7 @@ static int update_path_hierarchy_cache(JCR *jcr,
    } while (ret && mdb->sql_affected_rows() > 0);
 
    Mmsg(mdb->cmd, "UPDATE Job SET HasCache=1 WHERE JobId=%s", jobid);
-   ret = mdb->UpdateDB(jcr, mdb->cmd);
+   ret = mdb->UpdateDB(jcr, mdb->cmd, false);
 
 bail_out:
    mdb->bdb_end_transaction(jcr);
@@ -530,21 +554,6 @@ bail_out:
    return ret;
 }
 
-/* 
- * Find an store the filename descriptor for empty directories Filename.Name=''
- */
-DBId_t Bvfs::get_dir_filenameid()
-{
-   uint32_t id;
-   if (dir_filenameid) {
-      return dir_filenameid;
-   }
-   Mmsg(db->cmd, "SELECT FilenameId FROM Filename WHERE Name = ''");
-   db_sql_query(db, db->cmd, db_int_handler, &id);
-   dir_filenameid = id;
-   return dir_filenameid;
-}
-
 /* Compute the cache for the bfileview compoment */
 void Bvfs::fv_update_cache()
 {
@@ -577,6 +586,21 @@ void Bvfs::fv_update_cache()
    db->bdb_unlock();
 }
 
+/* 
+ * Find an store the filename descriptor for empty directories Filename.Name=''
+ */
+DBId_t Bvfs::get_dir_filenameid()
+{
+   uint32_t id;
+   if (dir_filenameid) {
+      return dir_filenameid;
+   }
+   Mmsg(db->cmd, "SELECT FilenameId FROM Filename WHERE Name = ''");
+   db_sql_query(db, db->cmd, db_int_handler, &id);
+   dir_filenameid = id;
+   return dir_filenameid;
+}
+
 /* Not yet working */
 void Bvfs::fv_get_big_files(int64_t pathid, int64_t min_size, int32_t limit)
 {
@@ -593,6 +617,7 @@ void Bvfs::fv_get_big_files(int64_t pathid, int64_t min_size, int32_t limit)
      "LIMIT %d ", pathid, jobids, min_size, limit);
 }
 
+
 /* Get the current path size and files count */
 void Bvfs::fv_get_current_size_and_count(int64_t pathid, int64_t *size, int64_t *count)
 {
@@ -694,7 +719,7 @@ void Bvfs::fv_update_size_and_count(int64_t pathid, int64_t size, int64_t count)
         " WHERE JobId = %s "
         " AND PathId = %lld ", count, size, jobids, pathid);
 
-   db->UpdateDB(jcr, db->cmd);
+   db->UpdateDB(jcr, db->cmd, false);
 }
 
 void bvfs_update_cache(JCR *jcr, BDB *mdb)
@@ -828,12 +853,22 @@ void Bvfs::update_cache()
    bvfs_update_path_hierarchy_cache(jcr, db, jobids);
 }
 
+
+bool Bvfs::ch_dir(DBId_t pathid)
+{
+   reset_offset();
+
+   pwd_id = pathid;
+   return pwd_id != 0;
+}
+
+
 /* Change the current directory, returns true if the path exists */
 bool Bvfs::ch_dir(const char *path)
 {
+   db->bdb_lock();
    pm_strcpy(db->path, path);
    db->pnl = strlen(db->path);
-   db->bdb_lock();
    ch_dir(db->bdb_get_path_record(jcr));
    db->bdb_unlock();
    return pwd_id != 0;
@@ -858,9 +893,9 @@ void Bvfs::get_all_file_versions(DBId_t pathid, FileId_t fnid, const char *clien
    POOL_MEM query;
 
    Mmsg(query,//    1           2              3       
-"SELECT 'V', File.PathId, File.FilenameId,  File.Md5, "
-//         4          5           6
-        "File.JobId, File.LStat, File.FileId, "
+"SELECT 'V', File.PathId, File.FilenameId,  File.JobId, "
+//           4          5           6
+        "File.LStat, File.FileId, File.Md5, "
 //         7                    8
        "Media.VolumeName, Media.InChanger "
 "FROM File, Job, Client, JobMedia, Media "
@@ -880,6 +915,108 @@ void Bvfs::get_all_file_versions(DBId_t pathid, FileId_t fnid, const char *clien
    db->bdb_sql_query(query.c_str(), list_entries, user_data);
 }
 
+/*
+ * Get all file versions for a specified client
+ * TODO: Handle basejobs using different client
+ */
+bool Bvfs::get_delta(FileId_t fileid)
+{
+   Dmsg1(dbglevel, "get_delta(%lld)\n", (uint64_t)fileid);
+   char ed1[50];
+   int32_t num;
+   SQL_ROW row;
+   POOL_MEM q;
+   POOL_MEM query;
+   char *fn = NULL;
+   bool ret = false;
+   db->bdb_lock();
+
+   /* Check if some FileId have DeltaSeq > 0
+    * Foreach of them we need to get the accurate_job list, and compute
+    * what are dependencies
+    */
+   Mmsg(query,
+        "SELECT F.JobId, FN.Name, F.PathId, F.DeltaSeq "
+        "FROM File AS F, Filename AS FN WHERE FileId = %lld "
+        "AND FN.FilenameId = F.FilenameId AND DeltaSeq > 0", fileid);
+
+   if (!db->QueryDB(jcr, query.c_str())) {
+      Dmsg1(dbglevel_sql, "Can't execute query=%s\n", query.c_str());
+      goto bail_out;
+   }
+
+   /* TODO: Use an other DB connection can avoid to copy the result of the
+    * previous query into a temporary buffer
+    */
+   num = db->sql_num_rows();
+   Dmsg2(dbglevel, "Found %d Delta parts q=%s\n",
+         num, query.c_str());
+
+   if (num > 0 && (row = db->sql_fetch_row())) {
+      JOB_DBR jr, jr2;
+      db_list_ctx lst;
+      memset(&jr, 0, sizeof(jr));
+      memset(&jr2, 0, sizeof(jr2));
+
+      fn = bstrdup(row[1]);               /* Filename */
+      int64_t jid = str_to_int64(row[0]);     /* JobId */
+      int64_t pid = str_to_int64(row[2]);     /* PathId */
+
+      /* Need to limit the query to StartTime, Client/Fileset */
+      jr2.JobId = jid;
+      if (!db->bdb_get_job_record(jcr, &jr2)) {
+         Dmsg1(0, "Unable to get job record for jobid %d\n", jid);
+         goto bail_out;
+      }
+
+      jr.JobId = jid;
+      jr.ClientId = jr2.ClientId;
+      jr.FileSetId = jr2.FileSetId;
+      jr.JobLevel = L_INCREMENTAL;
+      jr.StartTime = jr2.StartTime;
+
+      /* Get accurate jobid list */
+      if (!db->bdb_get_accurate_jobids(jcr, &jr, &lst)) {
+         Dmsg1(0, "Unable to get Accurate list for jobid %d\n", jid);
+         goto bail_out;
+      }
+
+      /* Escape filename */
+      db->fnl = strlen(fn);
+      db->esc_name = check_pool_memory_size(db->esc_name, 2*db->fnl+2);
+      db->bdb_escape_string(jcr, db->esc_name, fn, db->fnl);
+
+      edit_int64(pid, ed1);     /* pathid */
+
+      int id=db->bdb_get_type_index();
+      Mmsg(query, bvfs_select_delta_version_with_basejob_and_delta[id],
+           lst.list, db->esc_name, ed1,
+           lst.list, db->esc_name, ed1,
+           lst.list, lst.list);
+
+      Mmsg(db->cmd,
+           //       0     1     2   3      4      5      6            7
+           "SELECT 'd', PathId, 0, JobId, LStat, FileId, DeltaSeq, JobTDate"
+           " FROM (%s) AS F1 "
+           "ORDER BY DeltaSeq ASC",
+           query.c_str());
+
+      Dmsg1(dbglevel_sql, "q=%s\n", db->cmd);
+
+      if (!db->bdb_sql_query(db->cmd, list_entries, user_data)) {
+         Dmsg1(dbglevel_sql, "Can't exec q=%s\n", db->cmd);
+         goto bail_out;
+      }
+   }
+   ret = true;
+bail_out:
+   if (fn) {
+      free(fn);
+   }
+   db->bdb_unlock();
+   return ret;
+}
+
 /*
  * Get all volumes for a specific file
  */
@@ -925,6 +1062,12 @@ int Bvfs::_handle_path(void *ctx, int fields, char **row)
       /* can have the same path 2 times */
       if (strcmp(row[BVFS_PathId], prev_dir)) {
          pm_strcpy(prev_dir, row[BVFS_PathId]);
+         if (strcmp(NPRTB(row[BVFS_FileIndex]), "0") == 0 &&
+             strcmp(NPRTB(row[BVFS_FileId]), "0") != 0)
+         {
+            /* The directory was probably deleted */
+            return 0;
+         }
          return list_entries(user_data, fields, row);
       }
    }
@@ -950,23 +1093,27 @@ void Bvfs::ls_special_dirs()
 
    POOL_MEM query;
    Mmsg(query,
-"(SELECT PPathId AS PathId, '..' AS Path "
-    "FROM  PathHierarchy "
-   "WHERE  PathId = %s "
+"(SELECT PathHierarchy.PPathId AS PathId, '..' AS Path "
+    "FROM  PathHierarchy JOIN PathVisibility USING (PathId) "
+   "WHERE  PathHierarchy.PathId = %s "
+   "AND PathVisibility.JobId IN (%s) "
 "UNION "
  "SELECT %s AS PathId, '.' AS Path)",
-        edit_uint64(pwd_id, ed1), ed1);
+        edit_uint64(pwd_id, ed1), jobids, ed1);
 
    POOL_MEM query2;
-   Mmsg(query2,// 1      2     3        4     5       6
-"SELECT 'D', tmp.PathId, 0, tmp.Path, JobId, LStat, FileId "
+   Mmsg(query2,// 1          2     3        4     5 
+"SELECT 'D', tmp.PathId, tmp.Path, JobId, LStat, FileId, FileIndex "
   "FROM %s AS tmp  LEFT JOIN ( " // get attributes if any
        "SELECT File1.PathId AS PathId, File1.JobId AS JobId, "
-              "File1.LStat AS LStat, File1.FileId AS FileId FROM File AS File1 "
+              "File1.LStat AS LStat, File1.FileId AS FileId, "
+              "File1.FileIndex AS FileIndex, "
+              "Job1.JobTDate AS JobTDate "
+      "FROM File AS File1 JOIN Job AS Job1 USING (JobId)"
        "WHERE File1.FilenameId = %s "
        "AND File1.JobId IN (%s)) AS listfile1 "
   "ON (tmp.PathId = listfile1.PathId) "
-  "ORDER BY tmp.Path, JobId DESC ",
+  "ORDER BY tmp.Path, JobTDate DESC ",
         query.c_str(), edit_uint64(dir_filenameid, ed2), jobids);
 
    Dmsg1(dbglevel_sql, "q=%s\n", query2.c_str());
@@ -1004,12 +1151,14 @@ bool Bvfs::ls_dirs()
     */
    /* Then we get all the dir entries from File ... */
    Mmsg(query,
-//       0     1     2   3      4     5       6
-"SELECT 'D', PathId, 0, Path, JobId, LStat, FileId FROM ( "
+//       0     1      2      3      4     5       6
+"SELECT 'D', PathId, Path, JobId, LStat, FileId, FileIndex FROM ( "
     "SELECT Path1.PathId AS PathId, Path1.Path AS Path, "
            "lower(Path1.Path) AS lpath, "
            "listfile1.JobId AS JobId, listfile1.LStat AS LStat, "
-           "listfile1.FileId AS FileId "
+           "listfile1.FileId AS FileId, "
+           "listfile1.JobTDate AS JobTDate, "
+           "listfile1.FileIndex AS FileIndex "
     "FROM ( "
       "SELECT DISTINCT PathHierarchy1.PathId AS PathId "
       "FROM PathHierarchy AS PathHierarchy1 "
@@ -1025,11 +1174,13 @@ bool Bvfs::ls_dirs()
 
    "LEFT JOIN ( " /* get attributes if any */
        "SELECT File1.PathId AS PathId, File1.JobId AS JobId, "
-              "File1.LStat AS LStat, File1.FileId AS FileId FROM File AS File1 "
+              "File1.LStat AS LStat, File1.FileId AS FileId, "
+              "File1.FileIndex, Job1.JobTDate AS JobTDate "
+     "FROM File AS File1 JOIN Job AS Job1 USING (JobId) "
        "WHERE File1.FilenameId = %s "
        "AND File1.JobId IN (%s)) AS listfile1 "
        "ON (listpath1.PathId = listfile1.PathId) "
-    ") AS A ORDER BY 2,3 DESC LIMIT %d OFFSET %d",
+    ") AS A ORDER BY Path,JobTDate DESC LIMIT %d OFFSET %d",
         edit_uint64(pwd_id, ed1),
         jobids,
         filter.c_str(),
@@ -1191,9 +1342,11 @@ bool Bvfs::compute_restore_list(char *fileid, char *dirid, char *hardlink,
        (*hardlink && !is_a_number_list(hardlink))||
        (!*hardlink && !*fileid && !*dirid && !*hardlink))
    {
+      Dmsg0(dbglevel, "ERROR: One or more of FileId, DirId or HardLink is not given or not a number.\n");
       return false;
    }
    if (!check_temp(output_table)) {
+      Dmsg0(dbglevel, "ERROR: Wrong format for table name (in path field).\n");
       return false;
    }
 
@@ -1210,9 +1363,10 @@ bool Bvfs::compute_restore_list(char *fileid, char *dirid, char *hardlink,
 
    if (*fileid) {               /* Select files with their direct id */
       init=true;
-      Mmsg(tmp,"SELECT Job.JobId, JobTDate, FileIndex, FilenameId, "
+      Mmsg(tmp,"SELECT Job.JobId, JobTDate, FileIndex, Filename.Name, "
                       "PathId, FileId "
-                 "FROM File JOIN Job USING (JobId) WHERE FileId IN (%s)",
+                 "FROM File,Job,Filename WHERE Job.JobId=File.Jobid "
+                 "AND File.FilenameId=Filename.FilenameId AND  FileId IN (%s)",
            fileid);
       pm_strcat(query, tmp.c_str());
    }
@@ -1222,12 +1376,13 @@ bool Bvfs::compute_restore_list(char *fileid, char *dirid, char *hardlink,
       Mmsg(tmp, "SELECT Path FROM Path WHERE PathId=%lld", id);
 
       if (!db->bdb_sql_query(tmp.c_str(), get_path_handler, (void *)&tmp2)) {
-         Dmsg0(dbglevel, "Can't search for path\n");
+         Dmsg3(dbglevel, "ERROR: Path not found %lld q=%s s=%s\n",
+               id, tmp.c_str(), tmp2.c_str());
          /* print error */
          goto bail_out;
       }
       if (!strcmp(tmp2.c_str(), "")) { /* path not found */
-         Dmsg3(dbglevel, "Path not found %lld q=%s s=%s\n",
+         Dmsg3(dbglevel, "ERROR: Path not found %lld q=%s s=%s\n",
                id, tmp.c_str(), tmp2.c_str());
          break;
       }
@@ -1279,7 +1434,7 @@ bool Bvfs::compute_restore_list(char *fileid, char *dirid, char *hardlink,
    prev_jobid=0;
    while (get_next_id_from_list(&hardlink, &jobid) == 1) {
       if (get_next_id_from_list(&hardlink, &id) != 1) {
-         Dmsg0(dbglevel, "hardlink should be two by two\n");
+         Dmsg0(dbglevel, "ERROR: hardlink should be two by two\n");
          goto bail_out;
       }
       if (jobid != prev_jobid) { /* new job */
@@ -1312,7 +1467,7 @@ bool Bvfs::compute_restore_list(char *fileid, char *dirid, char *hardlink,
    Dmsg1(dbglevel_sql, "query=%s\n", query.c_str());
 
    if (!db->bdb_sql_query(query.c_str(), NULL, NULL)) {
-      Dmsg1(dbglevel, "Can't execute query=%s\n", query.c_str());
+      Dmsg1(dbglevel, "ERROR executing query=%s\n", query.c_str());
       goto bail_out;
    }
 
@@ -1322,7 +1477,7 @@ bool Bvfs::compute_restore_list(char *fileid, char *dirid, char *hardlink,
    /* TODO: handle jobid filter */
    Dmsg1(dbglevel_sql, "query=%s\n", query.c_str());
    if (!db->bdb_sql_query(query.c_str(), NULL, NULL)) {
-      Dmsg1(dbglevel, "Can't execute query=%s\n", query.c_str());
+      Dmsg1(dbglevel, "ERROR executing query=%s\n", query.c_str());
       goto bail_out;
    }
 
@@ -1332,7 +1487,7 @@ bool Bvfs::compute_restore_list(char *fileid, char *dirid, char *hardlink,
            output_table, output_table);
       Dmsg1(dbglevel_sql, "query=%s\n", query.c_str());
       if (!db->bdb_sql_query(query.c_str(), NULL, NULL)) {
-         Dmsg1(dbglevel, "Can't execute query=%s\n", query.c_str());
+         Dmsg1(dbglevel, "ERROR executing query=%s\n", query.c_str());
          goto bail_out; 
       } 
    }
@@ -1366,7 +1521,7 @@ bool Bvfs::compute_restore_list(char *fileid, char *dirid, char *hardlink,
          result[i++] = str_to_int64(row[1]); /* JobId */
          result[i++] = str_to_int64(row[2]); /* FilenameId */
          result[i++] = str_to_int64(row[3]); /* PathId */
-      }
+      } 
 
       i=0;
       while (num > 0) {
@@ -1385,10 +1540,10 @@ bail_out:
    db->bdb_unlock();
    return ret;
 }
+
 void Bvfs::insert_missing_delta(char *output_table, int64_t *res)
 {
-   char ed1[50], ed2[50];
+   char ed1[50];
    db_list_ctx lst;
    POOL_MEM query;
    JOB_DBR jr, jr2;
@@ -1422,13 +1577,17 @@ void Bvfs::insert_missing_delta(char *output_table, int64_t *res)
 
    Dmsg1(dbglevel_sql, "JobId list after strip is %s\n", lst.list);
 
-   edit_int64(res[2], ed1);     /* fnid */
-   edit_int64(res[3], ed2);     /* pathid */
+   /* Escape filename */
+   db->fnl = strlen((char *)res[2]);
+   db->esc_name = check_pool_memory_size(db->esc_name, 2*db->fnl+2);
+   db->bdb_escape_string(jcr, db->esc_name, (char *)res[2], db->fnl);
+
+   edit_int64(res[3], ed1);     /* pathid */
 
    int id=db->bdb_get_type_index();
    Mmsg(query, bvfs_select_delta_version_with_basejob_and_delta[id],
-        lst.list, ed1, ed2, 
-        lst.list, ed1, ed2, 
+        lst.list, db->esc_name, ed1,
+        lst.list, db->esc_name, ed1,
         lst.list, lst.list);
 
    Mmsg(db->cmd, "INSERT INTO %s "