]> git.sur5r.net Git - bacula/bacula/commitdiff
Fix RestoreObject for PostgreSQL
authorEric Bollengier <eric@eb.homelinux.org>
Sun, 2 May 2010 13:24:01 +0000 (15:24 +0200)
committerEric Bollengier <eric@eb.homelinux.org>
Mon, 2 Aug 2010 14:53:47 +0000 (16:53 +0200)
bacula/src/cats/cats.h
bacula/src/cats/make_postgresql_tables.in
bacula/src/cats/mysql.c
bacula/src/cats/postgresql.c
bacula/src/cats/protos.h
bacula/src/cats/sql_create.c
bacula/src/cats/sqlite.c
bacula/src/dird/fd_cmds.c
bacula/src/filed/job.c

index 79581201d6585ac7e3f1d22b3ec930ace31a7cdf..a33650ba69c78996dd4321ed2d8aea1c83917d80 100644 (file)
@@ -149,6 +149,7 @@ struct B_DB {
    POOLMEM *path;                     /* Path only */
    POOLMEM *esc_name;                 /* Escaped file name */
    POOLMEM *esc_path;                 /* Escaped path name */
+   POOLMEM *esc_obj;                  /* Escaped restore object */
    int fnl;                           /* file name length */
    int pnl;                           /* path name length */
 };
@@ -270,6 +271,7 @@ struct B_DB {
    POOLMEM *path;                     /* Path only */
    POOLMEM *esc_name;                 /* Escaped file name */
    POOLMEM *esc_path;                 /* Escaped path name */
+   POOLMEM *esc_obj;                  /* Escaped restore object */
    int fnl;                           /* file name length */
    int pnl;                           /* path name length */
 };
@@ -374,6 +376,7 @@ struct B_DB {
    POOLMEM *path;                     /* Path only */
    POOLMEM *esc_name;                 /* Escaped file name */
    POOLMEM *esc_path;                 /* Escaped path name */
+   POOLMEM *esc_obj;                  /* Escaped restore object */
    int fnl;                           /* file name length */
    int pnl;                           /* path name length */
 };
@@ -478,6 +481,7 @@ struct B_DB {
    POOLMEM *path;                 /* Path only */
    POOLMEM *esc_name;             /* Escaped file name */
    POOLMEM *esc_path;             /* Escaped path name */
+   unsigned char *esc_obj;        /* Escaped restore object */
    int fnl;                       /* file name length */
    int pnl;                       /* path name length */
 };
@@ -715,6 +719,7 @@ struct B_DB {
    POOLMEM *path;                 /* Path only */
    POOLMEM *esc_name;             /* Escaped file name */
    POOLMEM *esc_path;             /* Escaped path name */
+   POOLMEM *esc_obj;              /* Escaped restore object */
    int fnl;                       /* file name length */
    int pnl;                       /* path name length */
 };
index 04e217f913f71057caccd3f46abe1dc8a54b937a..fd831d377440b197866a9bdc620718c26eff5a3c 100644 (file)
@@ -78,7 +78,7 @@ CREATE INDEX file_jobid_idx on File (JobId);
 CREATE TABLE RestoreObject (
    RestoreObjectId SERIAL NOT NULL,
    ObjectName TEXT NOT NULL,
-   RestoreObject TEXT NOT NULL,
+   RestoreObject BYTEA NOT NULL,
    PluginName TEXT NOT NULL,
    ObjectLength INTEGER DEFAULT 0,
    ObjectFullLength INTEGER DEFAULT 0,
index 9e34826b3a7af96631068db8f159225f8dc57c85..555bbf9cc02ec6aeea85389433468938b474a4ef 100644 (file)
@@ -125,6 +125,7 @@ db_init_database(JCR *jcr, const char *db_name, const char *db_user, const char
    mdb->path = get_pool_memory(PM_FNAME);
    mdb->esc_name = get_pool_memory(PM_FNAME);
    mdb->esc_path = get_pool_memory(PM_FNAME);
+   mdb->esc_obj = get_pool_memory(PM_FNAME);
    mdb->allow_transactions = mult_db_connections;
    db_list->append(mdb);                   /* put db in list */
    Dmsg3(100, "initdb ref=%d connected=%d db=%p\n", mdb->ref_count,
@@ -253,6 +254,7 @@ db_close_database(JCR *jcr, B_DB *mdb)
       free_pool_memory(mdb->path);
       free_pool_memory(mdb->esc_name);
       free_pool_memory(mdb->esc_path);
+      free_pool_memory(mdb->esc_obj);
       if (mdb->db_name) {
          free(mdb->db_name);
       }
@@ -315,6 +317,36 @@ int db_next_index(JCR *jcr, B_DB *mdb, char *table, char *index)
    return 1;
 }
 
+/*
+ * Escape binary object so that MySQL is happy
+ * Memory is stored in B_DB struct, no need to free it
+ */
+char *
+db_escape_object(JCR *jcr, B_DB *db, char *old, int len)
+{
+   mdb->esc_obj = check_pool_memory_size(mdb->esc_obj, len*2+1);
+   mysql_real_escape_string(mdb->db, mdb->esc_obj, old, len);
+   return mdb->esc_obj;
+}
+
+/*
+ * Unescape binary object so that MySQL is happy
+ */
+void
+db_unescape_object(JCR *jcr, B_DB *db, 
+                   char *from, int32_t expected_len, 
+                   POOLMEM **dest, int32_t *dest_len)
+{
+   if (!from) {
+      *dest[0] = 0;
+      *dest_len = 0;
+      return;
+   }
+   *dest = check_pool_memory_size(*dest, expected_len+1);
+   *dest_len = expected_len;
+   memcpy(*dest, from, expected_len);
+   (*dest)[expected_len]=0;
+}
 
 /*
  * Escape strings so that MySQL is happy
index f6919995cc11f3b3e23344515f8c48285d35bacc..a86f4e39e163661d89521cb3556173467e89a460 100644 (file)
@@ -126,7 +126,7 @@ db_init_database(JCR *jcr, const char *db_name, const char *db_user, const char
    mdb->fname          = get_pool_memory(PM_FNAME);
    mdb->path           = get_pool_memory(PM_FNAME);
    mdb->esc_name       = get_pool_memory(PM_FNAME);
-   mdb->esc_path      = get_pool_memory(PM_FNAME);
+   mdb->esc_path       = get_pool_memory(PM_FNAME);
    mdb->allow_transactions = mult_db_connections;
    db_list->append(mdb);                   /* put db in list */
    V(mutex);
@@ -290,6 +290,9 @@ db_close_database(JCR *jcr, B_DB *mdb)
       if (mdb->db_socket) {
          free(mdb->db_socket);
       }
+      if (mdb->esc_obj) {
+         PQfreemem(mdb->esc_obj);
+      }
       free(mdb);
       if (db_list->size() == 0) {
          delete db_list;
@@ -327,6 +330,61 @@ int db_next_index(JCR *jcr, B_DB *mdb, char *table, char *index)
    return 1;
 }
 
+/*
+ * Escape binary so that PostgreSQL is happy
+ *
+ */
+char *
+db_escape_object(JCR *jcr, B_DB *mdb, char *old, int len)
+{
+   size_t new_len;
+   if (mdb->esc_obj) {
+      PQfreemem(mdb->esc_obj);
+   }
+
+   mdb->esc_obj = PQescapeByteaConn(mdb->db, (unsigned const char *)old,
+                                    len, &new_len);
+
+   if (!mdb->esc_obj) {
+      Jmsg(jcr, M_FATAL, 0, _("PQescapeByteaConn returned NULL.\n"));
+   }
+
+   return (char *)mdb->esc_obj;
+}
+
+/*
+ * Unescape binary object so that PostgreSQL is happy
+ *
+ */
+void
+db_unescape_object(JCR *jcr, B_DB *mdb, 
+                   char *from, int32_t expected_len,
+                   POOLMEM **dest, int32_t *dest_len)
+{
+   size_t new_len;
+   unsigned char *obj;
+
+   if (!from) {
+      *dest[0] = 0;
+      *dest_len = 0;
+      return;
+   }
+
+   obj = PQunescapeBytea((unsigned const char *)from, &new_len);
+
+   if (!obj) {
+      Jmsg(jcr, M_FATAL, 0, _("PQunescapeByteaConn returned NULL.\n"));
+   }
+
+   *dest_len = new_len;
+   *dest = check_pool_memory_size(*dest, new_len+1);
+   memcpy(*dest, obj, new_len);
+   (*dest)[new_len]=0;
+   
+   PQfreemem(obj);
+
+   Dmsg1(000, "obj size: %d\n", *dest_len);
+}
 
 /*
  * Escape strings so that PostgreSQL is happy
@@ -653,7 +711,7 @@ static int my_postgresql_currval(B_DB *mdb, const char *table_name)
 
 bail_out:
    PQclear(result);
-
+   
    return id;
 }
 
index 35b8d849533c4f060ce3935f6b4d7c862c2f527f..5e0610776b5a4e0b2c62170f8c0c1e7cb171ad19 100644 (file)
@@ -51,6 +51,10 @@ int  db_open_database(JCR *jcr, B_DB *db);
 void db_close_database(JCR *jcr, B_DB *db);
 bool db_open_batch_connexion(JCR *jcr, B_DB *mdb);
 void db_escape_string(JCR *jcr, B_DB *db, char *snew, char *old, int len);
+char *db_escape_object(JCR *jcr, B_DB *db, char *old, int len);
+void db_unescape_object(JCR *jcr, B_DB *db, 
+                        char *from, int32_t expected_len, 
+                        POOLMEM **dest, int32_t *len);
 char *db_strerror(B_DB *mdb);
 int  db_next_index(JCR *jcr, B_DB *mdb, char *table, char *index);
 bool db_sql_query(B_DB *mdb, const char *cmd, DB_RESULT_HANDLER *result_handler, void *ctx);
index 1367056d04fb9f78c3a4420f5dcad29e2f84092a..b13e991b1c2d9f9b3ee0e844122878ac2d0268fe 100644 (file)
@@ -1229,7 +1229,6 @@ bool db_create_restore_object_record(JCR *jcr, B_DB *mdb, ROBJECT_DBR *ro)
 {
    bool stat;
    int plug_name_len;
-   POOLMEM *esc_obj = get_pool_memory(PM_MESSAGE);
    POOLMEM *esc_plug_name = get_pool_memory(PM_MESSAGE);
 
    db_lock(mdb);
@@ -1241,8 +1240,7 @@ bool db_create_restore_object_record(JCR *jcr, B_DB *mdb, ROBJECT_DBR *ro)
    mdb->esc_name = check_pool_memory_size(mdb->esc_name, mdb->fnl*2+1);
    db_escape_string(jcr, mdb, mdb->esc_name, ro->object_name, mdb->fnl);
    
-   esc_obj = check_pool_memory_size(esc_obj, ro->object_len*2+1);
-   db_escape_string(jcr, mdb, esc_obj, ro->object, ro->object_len);
+   db_escape_object(jcr, mdb, ro->object, ro->object_len);
 
    plug_name_len = strlen(ro->plugin_name);
    esc_plug_name = check_pool_memory_size(esc_plug_name, plug_name_len*2+1);
@@ -1253,7 +1251,7 @@ bool db_create_restore_object_record(JCR *jcr, B_DB *mdb, ROBJECT_DBR *ro)
         "ObjectLength,ObjectFullLength,ObjectIndex,ObjectType,"
         "ObjectCompression,FileIndex,JobId) "
         "VALUES ('%s','%s','%s',%d,%d,%d,%d,%d,%d,%u)",
-        mdb->esc_name, esc_plug_name, esc_obj,
+        mdb->esc_name, esc_plug_name, mdb->esc_obj,
         ro->object_len, ro->object_full_len, ro->object_index, 
         FT_RESTORE_FIRST, ro->object_compression, ro->FileIndex, ro->JobId);
 
@@ -1267,7 +1265,6 @@ bool db_create_restore_object_record(JCR *jcr, B_DB *mdb, ROBJECT_DBR *ro)
       stat = true;
    }
    db_unlock(mdb);
-   free_pool_memory(esc_obj);
    free_pool_memory(esc_plug_name);
    return stat;
 }
index 0a8619a3093d5867fdcc785ac97e79ca4197ad0e..c90195a35c47234b052163b525d9e626418a5e8c 100644 (file)
@@ -131,6 +131,7 @@ db_init_database(JCR *jcr, const char *db_name, const char *db_user, const char
    mdb->path = get_pool_memory(PM_FNAME);
    mdb->esc_name = get_pool_memory(PM_FNAME);
    mdb->esc_path = get_pool_memory(PM_FNAME);
+   mdb->esc_obj  = get_pool_memory(PM_FNAME);
    mdb->allow_transactions = mult_db_connections;
    db_list->append(mdb);
    V(mutex);
@@ -258,6 +259,7 @@ db_close_database(JCR *jcr, B_DB *mdb)
       free_pool_memory(mdb->path);
       free_pool_memory(mdb->esc_name);
       free_pool_memory(mdb->esc_path);
+      free_pool_memory(mdb->esc_obj);
       if (mdb->db_name) {
          free(mdb->db_name);
       }
@@ -299,6 +301,61 @@ int db_next_index(JCR *jcr, B_DB *mdb, char *table, char *index)
    return 1;
 }
 
+/*
+ * Escape binary object so that SQLite is happy
+ * Memory is stored in B_DB struct, no need to free it
+ *
+ * TODO: this should be implemented  (escape \0)
+ */
+char *
+db_escape_object(JCR *jcr, B_DB *db, char *old, int len)
+{
+   char *n, *o;
+
+   n = mdb->esc_obj = check_pool_memory_size(mdb->esc_obj, len*2+1);
+   o = old;
+   while (len--) {
+      switch (*o) {
+      case '\'':
+         *n++ = '\'';
+         *n++ = '\'';
+         o++;
+         break;
+      case 0:
+         *n++ = '\\';
+         *n++ = 0;
+         o++;
+         break;
+      default:
+         *n++ = *o++;
+         break;
+      }
+   }
+   *n = 0;
+   return mdb->esc_obj;
+}
+
+/*
+ * Unescape binary object so that SQLIte is happy
+ * Memory is stored in B_DB struct, no need to free it
+ *
+ * TODO: need to be implemented (escape \0)
+ */
+void
+db_unescape_object(JCR *jcr, B_DB *db, 
+                   char *from, int32_t expected_len, 
+                   POOLMEM **dest, int32_t *dest_len)
+{
+   if (!from) {
+      *dest[0] = 0;
+      *dest_len = 0;
+      return;
+   }
+   *dest = check_pool_memory_size(*dest, expected_len+1);
+   *dest_len = expected_len;
+   memcpy(*dest, from, expected_len);
+   (*dest)[expected_len]=0;
+}
 
 /*
  * Escape strings so that SQLite is happy
index 56085ccd2951219d7334fb3277387ce8a92ec99a..56f2f8fb9cc2eef2dcaeb548ff9271b2745f32b2 100644 (file)
@@ -672,7 +672,6 @@ static int restore_object_handler(void *ctx, int num_fields, char **row)
 {
    JCR *jcr = (JCR *)ctx;
    BSOCK *fd;
-   POOLMEM *msg_save;
 
    fd = jcr->file_bsock;
    if (jcr->is_job_canceled()) {
@@ -683,17 +682,27 @@ static int restore_object_handler(void *ctx, int num_fields, char **row)
 
    Dmsg1(000, "Send obj hdr=%s", fd->msg);
 
-   msg_save = fd->msg;
-   fd->msg = row[7] ? row[7] : (char *)"";
-   fd->msglen = strlen(fd->msg);
+   fd->msglen = pm_strcpy(fd->msg, row[7]);
    fd->send();                            /* send Object name */
+
    Dmsg1(000, "Send obj: %s\n", fd->msg);
 
-   fd->msg = row[8] ? row[8] : (char *)""; /* object */
-   fd->msglen = str_to_uint64(row[1]);   /* object length */
+//   fd->msglen = str_to_uint64(row[1]);   /* object length */
+//   Dmsg1(000, "obj size: %lld\n", (uint64_t)fd->msglen);
+
+   /* object */
+   db_unescape_object(jcr, jcr->db, 
+                      row[8],                /* Object  */
+                      str_to_uint64(row[1]), /* Object length */
+                      &fd->msg, &fd->msglen);
    fd->send();                           /* send object */
-// Dmsg1(000, "Send obj: %s\n", fd->msg);
-   fd->msg = msg_save;
+
+   if (debug_level) {
+      for (int i=0; i < fd->msglen; i++)
+         if (!fd->msg[i]) 
+            fd->msg[i] = ' ';
+      Dmsg1(000, "Send obj: %s\n", fd->msg);
+   }
 
    return 0;
 }
@@ -707,9 +716,12 @@ bool send_restore_objects(JCR *jcr)
    if (!jcr->JobIds || !jcr->JobIds[0]) {
       return true;
    }
-   Mmsg(query, "SELECT JobId,ObjectLength,ObjectFullLength,ObjectIndex,ObjectType,"
-        "ObjectCompression,FileIndex,ObjectName,RestoreObject FROM RestoreObject "
-        "WHERE JobId IN (%s) ORDER BY ObjectIndex ASC", jcr->JobIds);
+   Mmsg(query, "SELECT JobId,ObjectLength,ObjectFullLength,ObjectIndex,"
+                      "ObjectType,ObjectCompression,FileIndex,ObjectName,"
+                      "RestoreObject "
+               "FROM RestoreObject "
+              "WHERE JobId IN (%s) "
+              "ORDER BY ObjectIndex ASC", jcr->JobIds);
    
    /* restore_object_handler is called for each file found */
    db_sql_query(jcr->db, query.c_str(), restore_object_handler, (void *)jcr);
index f1421ceafdcd1e754911c87e37b0e90d3c9f4b85..8cac931472c1fa2ba485d80ec8ebca00af9666cf 100644 (file)
@@ -2083,6 +2083,7 @@ static int restore_cmd(JCR *jcr)
    if (jcr->VSS) {
       if (g_pVSSClient->InitializeForRestore(jcr, vss_restore_init_callback,
             (WCHAR *)jcr->job_metadata)) {
+
          /* inform user about writer states */
          int i;
          for (i=0; i < (int)g_pVSSClient->GetWriterCount(); i++) {
@@ -2097,6 +2098,11 @@ static int restore_cmd(JCR *jcr)
             }
          }
       } else {
+/*
+   int fd = open("C:\\eric.xml", O_CREAT | O_WRONLY | O_TRUNC, 0777);
+   write(fd, (WCHAR *)jcr->job_metadata, wcslen((WCHAR *)jcr->job_metadata) * sizeof(WCHAR));
+   close(fd);
+*/
          berrno be;
          Jmsg(jcr, M_WARNING, 0, _("VSS was not initialized properly. VSS support is disabled. ERR=%s\n"), be.bstrerror());
       }