]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/dird/ua_tree.c
Add optional type= argument to .jobs command. You can list only Backup, Restore,...
[bacula/bacula] / bacula / src / dird / ua_tree.c
index 33a1766680fe268e09a0a93397c4d0882e201917..6c10c749bc1b9b135bd584e7135dc8eea7618518 100644 (file)
@@ -1,14 +1,14 @@
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2002-2007 Free Software Foundation Europe e.V.
+   Copyright (C) 2002-2009 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 plus additions
-   that are listed in the file LICENSE.
+   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
@@ -20,7 +20,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Bacula® is a registered trademark of John Walker.
+   Bacula® is a registered trademark of Kern Sibbald.
    The licensor of Bacula is the Free Software Foundation Europe
    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
    Switzerland, email:ftf@fsfeurope.org.
@@ -65,12 +65,16 @@ 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);
 
 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,6 +83,8 @@ 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_("mark"),       markcmd,      _("mark dir/file to be restored recursively, wildcards allowed")},
  { NT_("markdir"),    markdircmd,   _("mark directory name to be restored (no files)")},
@@ -87,6 +93,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)))
@@ -106,18 +113,19 @@ bool user_select_files_from_tree(TREE_CTX *tree)
    ua->api = tree->ua->api;           /* keep API flag too */
    BSOCK *user = ua->UA_sock;
 
-   bsendmsg(tree->ua, _(
+   ua->send_msg(_(
       "\nYou are now entering file selection mode where you add (mark) and\n"
       "remove (unmark) files to be restored. No files are initially added, unless\n"
       "you used the \"all\" keyword on the command line.\n"
       "Enter \"done\" to leave this mode.\n\n"));
+   if (ua->api) user->signal(BNET_START_RTREE);
    /*
     * Enter interactive command handler allowing selection
     *  of individual files.
     */
    tree->node = (TREE_NODE *)tree->root;
    tree_getpath(tree->node, cwd, sizeof(cwd));
-   bsendmsg(tree->ua, _("cwd is: %s\n"), cwd);
+   ua->send_msg(_("cwd is: %s\n"), cwd);
    for ( ;; ) {
       int found, len, i;
       if (!get_cmd(ua, "$ ")) {
@@ -126,7 +134,7 @@ bool user_select_files_from_tree(TREE_CTX *tree)
       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) {
-         bsendmsg(tree->ua, _("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;
       }
@@ -135,13 +143,13 @@ 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) {
-         bsendmsg(tree->ua, _("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;
       }
@@ -150,6 +158,7 @@ bool user_select_files_from_tree(TREE_CTX *tree)
          break;
       }
    }
+   if (ua->api) user->signal(BNET_END_RTREE);
    ua->UA_sock = NULL;                /* don't release restore socket */
    stat = !ua->quit;
    ua->quit = false;
@@ -179,8 +188,8 @@ int insert_tree_handler(void *ctx, int num_fields, char **row)
    int FileIndex;
    JobId_t JobId;
 
-// Dmsg4(000, "Path=%s%s FI=%s JobId=%s\n", row[0], row[1],
-//    row[2], row[3]);
+   Dmsg4(400, "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;
@@ -194,6 +203,7 @@ int insert_tree_handler(void *ctx, int num_fields, char **row)
    node = insert_tree_node(row[0], row[1], type, tree->root, NULL);
    JobId = str_to_int64(row[3]);
    FileIndex = str_to_int64(row[2]);
+   Dmsg2(400, "JobId=%s FileIndex=%s\n", row[3], row[2]);
    /*
     * - 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
@@ -227,7 +237,7 @@ int insert_tree_handler(void *ctx, int num_fields, char **row)
    if (node->inserted) {
       tree->FileCount++;
       if (tree->DeltaCount > 0 && (tree->FileCount-tree->LastCount) > tree->DeltaCount) {
-         bsendmsg(tree->ua, "+");
+         tree->ua->send_msg("+");
          tree->LastCount = tree->FileCount;
       }
    }
@@ -431,7 +441,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)
 {
@@ -490,17 +545,11 @@ static int lsmarkcmd(UAContext *ua, TREE_CTX *tree)
    return 1;
 }
 
-
-
-extern char *getuser(uid_t uid, char *name, int len);
-extern char *getgroup(gid_t gid, char *name, int len);
-
 /*
  * This is actually the long form used for "dir"
  */
-static void ls_output(char *buf, const char *fname, const char *tag, 
+static void ls_output(guid_list *guid, char *buf, const char *fname, const char *tag, 
                       struct stat *statp, bool dot_cmd) 
-                    
 {
    char *p;
    const char *f;
@@ -514,10 +563,11 @@ static void ls_output(char *buf, const char *fname, const char *tag,
       *p++ = ',';
       n = sprintf(p, "%d,", (uint32_t)statp->st_nlink);
       p += n;
-      n = sprintf(p, "%s,%s,", getuser(statp->st_uid, en1, sizeof(en1)),
-                  getgroup(statp->st_gid, en2, sizeof(en2)));
+      n = sprintf(p, "%s,%s,", 
+                  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, "%s,", edit_uint64(statp->st_size, ec1));
+      n = sprintf(p, "%s,", edit_int64(statp->st_size, ec1));
       p += n;
       p = encode_time(statp->st_mtime, p);
       *p++ = ',';
@@ -526,10 +576,11 @@ static void ls_output(char *buf, const char *fname, const char *tag,
    } else {
       n = sprintf(p, "  %2d ", (uint32_t)statp->st_nlink);
       p += n;
-      n = sprintf(p, "%-8.8s %-8.8s", getuser(statp->st_uid, en1, sizeof(en1)),
-                  getgroup(statp->st_gid, en2, sizeof(en2)));
+      n = sprintf(p, "%-8.8s %-8.8s", 
+                  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_uint64(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;
@@ -557,12 +608,14 @@ static int do_dircmd(UAContext *ua, TREE_CTX *tree, bool dot_cmd)
    struct stat statp;
    char buf[1100];
    char cwd[1100], *pcwd;
+   guid_list *guid;
 
    if (!tree_node_has_child(tree->node)) {
       ua->send_msg(_("Node %s has no children.\n"), tree->node->fname);
       return 1;
    }
 
+   guid = new_guid_list();
    foreach_child(node, tree->node) {
       const char *tag;
       if (ua->argc == 1 || fnmatch(ua->argk[1], node->fname, 0) == 0) {
@@ -600,10 +653,11 @@ static int do_dircmd(UAContext *ua, TREE_CTX *tree, bool dot_cmd)
             /* Something went wrong getting attributes -- print name */
             memset(&statp, 0, sizeof(statp));
          }
-         ls_output(buf, cwd, tag, &statp, dot_cmd);
+         ls_output(guid, buf, cwd, tag, &statp, dot_cmd);
          ua->send_msg("%s\n", buf);
       }
    }
+   free_guid_list(guid);
    return 1;
 }