]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/dird/ua_tree.c
update configure
[bacula/bacula] / bacula / src / dird / ua_tree.c
index 2a5b75e735938a9bbfe2afa6e87e1154c7cba4d4..84c0898585efa0335919bece58440f5625e374a2 100644 (file)
@@ -1,12 +1,12 @@
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2002-2008 Free Software Foundation Europe e.V.
+   Copyright (C) 2002-2011 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
+   modify it under the terms of version three of the GNU Affero General Public
    License as published by the Free Software Foundation and included
    in the file LICENSE.
 
@@ -15,7 +15,7 @@
    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
+   You should have received a copy of the GNU Affero 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.
@@ -33,7 +33,6 @@
  *
  *     Kern Sibbald, July MMII
  *
- *   Version $Id$
  */
 
 #include "bacula.h"
@@ -65,12 +64,17 @@ static int unmarkcmd(UAContext *ua, TREE_CTX *tree);
 static int unmarkdircmd(UAContext *ua, TREE_CTX *tree);
 static int quitcmd(UAContext *ua, TREE_CTX *tree);
 static int donecmd(UAContext *ua, TREE_CTX *tree);
-
+static int dot_lsdircmd(UAContext *ua, TREE_CTX *tree);
+static int dot_lscmd(UAContext *ua, TREE_CTX *tree);
+static int dot_helpcmd(UAContext *ua, TREE_CTX *tree);
+static int dot_lsmarkcmd(UAContext *ua, TREE_CTX *tree);
 
 struct cmdstruct { const char *key; int (*func)(UAContext *ua, TREE_CTX *tree); const char *help; };
 static struct cmdstruct commands[] = {
+ { NT_("add"),        markcmd,      _("add dir/file to be restored recursively, wildcards allowed")},
  { NT_("cd"),         cdcmd,        _("change current directory")},
  { NT_("count"),      countcmd,     _("count marked files in and below the cd")},
+ { NT_("delete"),     unmarkcmd,    _("delete dir/file to be restored recursively in dir")},
  { NT_("dir"),        dircmd,       _("long list current directory, wildcards allowed")},
  { NT_(".dir"),       dot_dircmd,   _("long list current directory, wildcards allowed")},
  { NT_("done"),       donecmd,      _("leave file selection mode")},
@@ -79,7 +83,10 @@ static struct cmdstruct commands[] = {
  { NT_("find"),       findcmd,      _("find files, wildcards allowed")},
  { NT_("help"),       helpcmd,      _("print help")},
  { NT_("ls"),         lscmd,        _("list current directory, wildcards allowed")},
+ { NT_(".ls"),        dot_lscmd,    _("list current directory, wildcards allowed")},
+ { NT_(".lsdir"),     dot_lsdircmd, _("list subdir in current directory, wildcards allowed")},
  { NT_("lsmark"),     lsmarkcmd,    _("list the marked files in and below the cd")},
+ { NT_(".lsmark"),    dot_lsmarkcmd,_("list the marked files in")},
  { NT_("mark"),       markcmd,      _("mark dir/file to be restored recursively, wildcards allowed")},
  { NT_("markdir"),    markdircmd,   _("mark directory name to be restored (no files)")},
  { NT_("pwd"),        pwdcmd,       _("print current working directory")},
@@ -87,6 +94,7 @@ static struct cmdstruct commands[] = {
  { NT_("unmark"),     unmarkcmd,    _("unmark dir/file to be restored recursively in dir")},
  { NT_("unmarkdir"),  unmarkdircmd, _("unmark directory name only no recursion")},
  { NT_("quit"),       quitcmd,      _("quit and do not do restore")},
+ { NT_(".help"),      dot_helpcmd,  _("print help")},
  { NT_("?"),          helpcmd,      _("print help")},
              };
 #define comsize ((int)(sizeof(commands)/sizeof(struct cmdstruct)))
@@ -121,13 +129,13 @@ bool user_select_files_from_tree(TREE_CTX *tree)
    ua->send_msg(_("cwd is: %s\n"), cwd);
    for ( ;; ) {
       int found, len, i;
-      if (!get_cmd(ua, "$ ")) {
+      if (!get_cmd(ua, "$ ", true)) {
          break;
       }
       if (ua->api) user->signal(BNET_CMD_BEGIN);
       parse_args_only(ua->cmd, &ua->args, &ua->argc, ua->argk, ua->argv, MAX_CMD_ARGS);
       if (ua->argc == 0) {
-         ua->warning_msg(_("Invalid command. Enter \"done\" to exit.\n"));
+         ua->warning_msg(_("Invalid command \"%s\". Enter \"done\" to exit.\n"), ua->cmd);
          if (ua->api) user->signal(BNET_CMD_FAILED);
          continue;
       }
@@ -136,13 +144,17 @@ bool user_select_files_from_tree(TREE_CTX *tree)
       found = 0;
       stat = false;
       for (i=0; i<comsize; i++)       /* search for command */
-         if (strncasecmp(ua->argk[0],  _(commands[i].key), len) == 0) {
+         if (strncasecmp(ua->argk[0],  commands[i].key, len) == 0) {
             stat = (*commands[i].func)(ua, tree);   /* go execute command */
             found = 1;
             break;
          }
       if (!found) {
-         ua->warning_msg(_("Invalid command. Enter \"done\" to exit.\n"));
+         if (*ua->argk[0] == '.') {
+            /* Some unknow dot command -- probably .messages, ignore it */
+            continue;
+         }
+         ua->warning_msg(_("Invalid command \"%s\". Enter \"done\" to exit.\n"), ua->cmd);
          if (ua->api) user->signal(BNET_CMD_FAILED);
          continue;
       }
@@ -169,7 +181,7 @@ bool user_select_files_from_tree(TREE_CTX *tree)
  *
  *   See uar_sel_files in sql_cmds.c for query that calls us.
  *      row[0]=Path, row[1]=Filename, row[2]=FileIndex
- *      row[3]=JobId row[4]=LStat
+ *      row[3]=JobId row[4]=LStat row[5]=DeltaSeq
  */
 int insert_tree_handler(void *ctx, int num_fields, char **row)
 {
@@ -179,10 +191,11 @@ int insert_tree_handler(void *ctx, int num_fields, char **row)
    int type;
    bool hard_link, ok;
    int FileIndex;
+   int32_t delta_seq;
    JobId_t JobId;
 
-   Dmsg4(400, "Path=%s%s FI=%s JobId=%s\n", row[0], row[1],
-      row[2], row[3]);
+   Dmsg4(100, "Path=%s%s FI=%s JobId=%s\n", row[0], row[1],
+         row[2], row[3]);
    if (*row[1] == 0) {                 /* no filename => directory */
       if (!IsPathSeparator(*row[0])) { /* Must be Win32 directory */
          type = TN_DIR_NLS;
@@ -192,10 +205,32 @@ int insert_tree_handler(void *ctx, int num_fields, char **row)
    } else {
       type = TN_FILE;
    }
-   hard_link = (decode_LinkFI(row[4], &statp) != 0);
+   hard_link = (decode_LinkFI(row[4], &statp, sizeof(statp)) != 0);
    node = insert_tree_node(row[0], row[1], type, tree->root, NULL);
    JobId = str_to_int64(row[3]);
    FileIndex = str_to_int64(row[2]);
+   delta_seq = str_to_int64(row[5]);
+   Dmsg5(100, "node=0x%p JobId=%s FileIndex=%s Delta=%s node.delta=%d\n",
+         node, row[3], row[2], row[5], node->delta_seq);
+
+   /* TODO: check with hardlinks */
+   if (delta_seq > 0) {
+      if (delta_seq == (node->delta_seq + 1)) {
+         tree_add_delta_part(tree->root, node, node->JobId, node->FileIndex);
+
+      } else {
+         /* File looks to be deleted */
+         if (node->delta_seq == -1) { /* just created */
+            tree_remove_node(tree->root, node);
+
+         } else {
+            Dmsg3(0, "Something is wrong with Delta, skipt it "
+                  "fname=%s d1=%d d2=%d\n", 
+                  row[1], node->delta_seq, delta_seq);
+         }
+         return 0;
+      }
+   }
    /*
     * - The first time we see a file (node->inserted==true), we accept it.
     * - In the same JobId, we accept only the first copy of a
@@ -219,6 +254,8 @@ int insert_tree_handler(void *ctx, int num_fields, char **row)
       node->JobId = JobId;
       node->type = type;
       node->soft_link = S_ISLNK(statp.st_mode) != 0;
+      node->delta_seq = delta_seq;
+
       if (tree->all) {
          node->extract = true;          /* extract all by default */
          if (type == TN_DIR || type == TN_DIR_NLS) {
@@ -285,7 +322,7 @@ static int set_extract(UAContext *ua, TREE_NODE *node, TREE_CTX *tree, bool extr
       fdbr.JobId = node->JobId;
       if (node->hard_link && db_get_file_attributes_record(ua->jcr, ua->db, cwd, NULL, &fdbr)) {
          int32_t LinkFI;
-         decode_stat(fdbr.LStat, &statp, &LinkFI); /* decode stat pkt */
+         decode_stat(fdbr.LStat, &statp, sizeof(statp), &LinkFI); /* decode stat pkt */
          /*
           * If we point to a hard linked file, traverse the tree to
           * find that file, and mark it to be restored as well. It
@@ -433,7 +470,52 @@ static int findcmd(UAContext *ua, TREE_CTX *tree)
    return 1;
 }
 
+static int dot_lsdircmd(UAContext *ua, TREE_CTX *tree)
+{
+   TREE_NODE *node;
+
+   if (!tree_node_has_child(tree->node)) {
+      return 1;
+   }
+
+   foreach_child(node, tree->node) {
+      if (ua->argc == 1 || fnmatch(ua->argk[1], node->fname, 0) == 0) {
+         if (tree_node_has_child(node)) {
+            ua->send_msg("%s/\n", node->fname);
+         }
+      }
+   }
+   return 1;
+}
+
+static int dot_helpcmd(UAContext *ua, TREE_CTX *tree)
+{
+   for (int i=0; i<comsize; i++) {
+      /* List only non-dot commands */
+      if (commands[i].key[0] != '.') {
+         ua->send_msg("%s\n", commands[i].key);
+      }
+   }
+   return 1;
+}
+
+static int dot_lscmd(UAContext *ua, TREE_CTX *tree)
+{
+   TREE_NODE *node;
+
+   if (!tree_node_has_child(tree->node)) {
+      return 1;
+   }
 
+   foreach_child(node, tree->node) {
+      if (ua->argc == 1 || fnmatch(ua->argk[1], node->fname, 0) == 0) {
+         ua->send_msg("%s%s\n", node->fname, tree_node_has_child(node)?"/":"");
+      }
+   }
+   return 1;
+}
 
 static int lscmd(UAContext *ua, TREE_CTX *tree)
 {
@@ -461,12 +543,40 @@ static int lscmd(UAContext *ua, TREE_CTX *tree)
 /*
  * Ls command that lists only the marked files
  */
-static void rlsmark(UAContext *ua, TREE_NODE *tnode)
+static int dot_lsmarkcmd(UAContext *ua, TREE_CTX *tree)
+{
+   TREE_NODE *node;
+   if (!tree_node_has_child(tree->node)) {
+      return 1;
+   }
+   foreach_child(node, tree->node) {
+      if ((ua->argc == 1 || fnmatch(ua->argk[1], node->fname, 0) == 0) &&
+          (node->extract || node->extract_dir)) {
+         ua->send_msg("%s%s\n", node->fname, tree_node_has_child(node)?"/":"");
+      }
+   }
+   return 1;
+}
+
+/*
+ * This recursive ls command that lists only the marked files
+ */
+static void rlsmark(UAContext *ua, TREE_NODE *tnode, int level)
 {
    TREE_NODE *node;
+   const int max_level = 100;
+   char indent[max_level*2+1];
+   int i, j;
    if (!tree_node_has_child(tnode)) {
       return;
    }
+   level = MIN(level, max_level);
+   j = 0;
+   for (i=0; i<level; i++) {
+      indent[j++] = ' ';
+      indent[j++] = ' ';
+   }
+   indent[j] = 0;
    foreach_child(node, tnode) {
       if ((ua->argc == 1 || fnmatch(ua->argk[1], node->fname, 0) == 0) &&
           (node->extract || node->extract_dir)) {
@@ -478,9 +588,9 @@ static void rlsmark(UAContext *ua, TREE_NODE *tnode)
          } else {
             tag = "";
          }
-         ua->send_msg("%s%s%s\n", tag, node->fname, tree_node_has_child(node)?"/":"");
+         ua->send_msg("%s%s%s%s\n", indent, tag, node->fname, tree_node_has_child(node)?"/":"");
          if (tree_node_has_child(node)) {
-            rlsmark(ua, node);
+            rlsmark(ua, node, level+1);
          }
       }
    }
@@ -488,7 +598,7 @@ static void rlsmark(UAContext *ua, TREE_NODE *tnode)
 
 static int lsmarkcmd(UAContext *ua, TREE_CTX *tree)
 {
-   rlsmark(ua, tree->node);
+   rlsmark(ua, tree->node, 0);
    return 1;
 }
 
@@ -527,7 +637,7 @@ static void ls_output(guid_list *guid, char *buf, const char *fname, const char
                   guid->uid_to_name(statp->st_uid, en1, sizeof(en1)),
                   guid->gid_to_name(statp->st_gid, en2, sizeof(en2)));
       p += n;
-      n = sprintf(p, "%10.10s  ", edit_int64(statp->st_size, ec1));
+      n = sprintf(p, "%12.12s  ", edit_int64(statp->st_size, ec1));
       p += n;
       if (statp->st_ctime > statp->st_mtime) {
          time = statp->st_ctime;
@@ -595,7 +705,7 @@ static int do_dircmd(UAContext *ua, TREE_CTX *tree, bool dot_cmd)
          }
          if (db_get_file_attributes_record(ua->jcr, ua->db, pcwd, NULL, &fdbr)) {
             int32_t LinkFI;
-            decode_stat(fdbr.LStat, &statp, &LinkFI); /* decode stat pkt */
+            decode_stat(fdbr.LStat, &statp, sizeof(statp), &LinkFI); /* decode stat pkt */
          } else {
             /* Something went wrong getting attributes -- print name */
             memset(&statp, 0, sizeof(statp));
@@ -640,7 +750,7 @@ static int estimatecmd(UAContext *ua, TREE_CTX *tree)
             fdbr.JobId = node->JobId;
             if (db_get_file_attributes_record(ua->jcr, ua->db, cwd, NULL, &fdbr)) {
                int32_t LinkFI;
-               decode_stat(fdbr.LStat, &statp, &LinkFI); /* decode stat pkt */
+               decode_stat(fdbr.LStat, &statp, sizeof(statp), &LinkFI); /* decode stat pkt */
                if (S_ISREG(statp.st_mode) && statp.st_size > 0) {
                   total_bytes += statp.st_size;
                }