spoolfile name doesn't include that information. The date/time
stamp is useful (and should be retained).
+============= New Freature Requests after vote of 26 Jan 2007 ========
+Item n: Enable to relocate files and directories when restoring
+ Date: 2007-03-01
+ Origin: Eric Bollengier <eric@eb.homelinux.org>
+ Status:
+
+ What: The where= option is not powerful enough. It will be
+ a great feature if bacula can restore a file in the
+ same directory, but with a different name, or in
+ an other directory without recreating the full path.
+
+ Why: When i want to restore a production environment to a
+ development environment, i just want change the first
+ directory. ie restore /prod/data/file.dat to /rect/data/file.dat.
+ At this time, i have to move by hand files. You must have a big
+ dump space to restore and move data after.
+
+ When i use Linux or SAN snapshot, i mount them to /mnt/snap_xxx
+ so, when a restore a file, i have to move by hand
+ from /mnt/snap_xxx/file to /xxx/file. I can't replace a file
+ easily.
+
+ When a user ask me to restore a file in its personal folder,
+ (without replace the existing one), i can't restore from
+ my_file.txt to my_file.txt.old witch is very practical.
+
+
+ Notes: I think we can enhance the where= option very easily by
+ allowing regexp expression. (by replacing bregex by libpcre
+ see http://en.wikipedia.org/wiki/PCRE and http://www.pcre.org/)
+
+ Since, many users think that regexp are not user friendly, i think
+ that bat, bconsole or brestore must provide a simple way to
+ configure where= option (i think to something like in
+ openoffice "search and replace").
+
+ Ie, if user uses where=/tmp/bacula-restore, we keep the old
+ fashion.
+
+ If user uses something like where=s!/prod!/test!, files will
+ be restored from /prod/xxx to /test/xxx.
+
+ If user uses something like where=s/$/.old/, files will
+ be restored from /prod/xxx.txt to /prod/xxx.txt.old.
+
+ If user uses something like where=s/txt$/old.txt/, files will
+ be restored from /prod/xxx.txt to /prod/xxx.old.txt
+
+ if user uses something like where=s/([a-z]+)$/old.$1/, files will
+ be restored from /prod/xxx.ext to /prod/xxx.old.ext
+
============= Empty Feature Request form ===========
Item n: One line summary ...
Date: Date submitted
{
unsigned int i;
int len, stat;
+ bool ok = false;
bool found = false;
+ BSOCK *user = ua->UA_sock;
stat = 1;
!acl_access_ok(ua, Command_ACL, ua->argk[0], len)) {
break;
}
- stat = (*commands[i].func)(ua, cmd); /* go execute command */
+ if (ua->api) user->signal(BNET_CMD_BEGIN);
+ ok = (*commands[i].func)(ua, cmd); /* go execute command */
found = true;
break;
}
}
if (!found) {
- bnet_fsend(ua->UA_sock, _("%s: is an invalid command.\n"), ua->argk[0]);
+ user->fsend(_("%s: is an invalid command.\n"), ua->argk[0]);
}
- return stat;
+ if (ua->api) user->signal(ok?BNET_CMD_OK:BNET_CMD_FAILED);
+ return ok;
}
/*
int len;
bool ok = false;
bool found = false;
- BSOCK *sock = ua->UA_sock;
+ BSOCK *user = ua->UA_sock;
- Dmsg1(1400, "Dot command: %s\n", ua->UA_sock->msg);
+ Dmsg1(1400, "Dot command: %s\n", user->msg);
if (ua->argc == 0) {
return 1;
}
len = strlen(ua->argk[0]);
if (len == 1) {
+ if (ua->api) user->signal(BNET_CMD_BEGIN);
+ if (ua->api) user->signal(BNET_CMD_OK);
return 1; /* no op */
}
for (i=0; i<comsize; i++) { /* search for command */
if (strncasecmp(ua->argk[0], _(commands[i].key), len) == 0) {
bool gui = ua->gui;
+ /* Check if command permitted, but "quit" is always OK */
+ if (strcmp(ua->argk[0], NT_(".quit")) != 0 &&
+ !acl_access_ok(ua, Command_ACL, ua->argk[0], len)) {
+ break;
+ }
ua->gui = true;
- if (ua->api) sock->signal(BNET_CMD_BEGIN);
+ if (ua->api) user->signal(BNET_CMD_BEGIN);
ok = (*commands[i].func)(ua, cmd); /* go execute command */
ua->gui = gui;
found = true;
}
}
if (!found) {
- pm_strcat(sock->msg, _(": is an invalid command\n"));
- sock->msglen = strlen(sock->msg);
- sock->send();
- if (ua->api) sock->signal(BNET_INVALID_CMD);
+ pm_strcat(user->msg, _(": is an invalid command.\n"));
+ user->msglen = strlen(user->msg);
+ user->send();
}
- if (ua->api) sock->signal(ok?BNET_CMD_OK:BNET_CMD_FAILED);
+ if (ua->api) user->signal(ok?BNET_CMD_OK:BNET_CMD_FAILED);
return 1;
}
-/*
- *
- * Bacula Director -- User Agent Input and scanning code
- *
- * Kern Sibbald, October MMI
- *
- * Version $Id$
- */
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2001-2006 Free Software Foundation Europe e.V.
+ Copyright (C) 2001-2007 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.
(FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
Switzerland, email:ftf@fsfeurope.org.
*/
+/*
+ *
+ * Bacula Director -- User Agent Input and scanning code
+ *
+ * Kern Sibbald, October MMI
+ *
+ * Version $Id$
+ */
#include "bacula.h"
#include "dird.h"
if (!sock) { /* No UA */
return 0;
}
- bnet_fsend(sock, "%s", prompt);
- bnet_sig(sock, BNET_PROMPT); /* request more input */
+ sock->fsend("%s", prompt);
+ sock->signal(BNET_PROMPT); /* request more input */
for ( ;; ) {
- stat = bnet_recv(sock);
+ stat = sock->recv();
if (stat == BNET_SIGNAL) {
continue; /* ignore signals */
}
-/*
- *
- * Bacula Director -- User Agent Server
- *
- * Kern Sibbald, September MM
- *
- * Version $Id$
- */
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-2007 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.
(FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
Switzerland, email:ftf@fsfeurope.org.
*/
+/*
+ *
+ * Bacula Director -- User Agent Server
+ *
+ * Kern Sibbald, September MM
+ *
+ * Version $Id$
+ */
#include "bacula.h"
#include "dird.h"
{
pthread_detach(pthread_self());
- /* Permit 10 console connections */
- bnet_thread_server((dlist*)arg, 10, &ua_workq, handle_UA_client_request);
+ /* Permit 20 console connections */
+ bnet_thread_server((dlist*)arg, 20, &ua_workq, handle_UA_client_request);
return NULL;
}
int stat;
UAContext *ua;
JCR *jcr;
+ BSOCK *user = (BSOCK *)arg;
pthread_detach(pthread_self());
jcr = new_control_jcr("*Console*", JT_CONSOLE);
ua = new_ua_context(jcr);
- ua->UA_sock = (BSOCK *)arg;
+ ua->UA_sock = user;
- bnet_recv(ua->UA_sock); /* Get first message */
+ user->recv(); /* Get first message */
if (!authenticate_user_agent(ua)) {
goto getout;
}
while (!ua->quit) {
- stat = bnet_recv(ua->UA_sock);
+ stat = user->recv();
if (stat >= 0) {
pm_strcpy(ua->cmd, ua->UA_sock->msg);
parse_ua_args(ua);
if (ua->auto_display_messages) {
pm_strcpy(ua->cmd, "messages");
qmessagescmd(ua, ua->cmd);
- ua->user_notified_msg_pending = FALSE;
+ ua->user_notified_msg_pending = false;
} else if (!ua->gui && !ua->user_notified_msg_pending && console_msg_pending) {
bsendmsg(ua, _("You have messages.\n"));
- ua->user_notified_msg_pending = TRUE;
+ ua->user_notified_msg_pending = true;
}
}
- bnet_sig(ua->UA_sock, BNET_EOD); /* send end of command */
+ if (!ua->api) user->signal(BNET_EOD); /* send end of command */
}
- } else if (is_bnet_stop(ua->UA_sock)) {
+ } else if (is_bnet_stop(user)) {
ua->quit = true;
} else { /* signal */
- bnet_sig(ua->UA_sock, BNET_POLL);
+ user->signal(BNET_POLL);
}
}
-/*
- *
- * Bacula Director -- User Agent Database File tree for Restore
- * command. This file interacts with the user implementing the
- * UA tree commands.
- *
- * Kern Sibbald, July MMII
- *
- * Version $Id$
- */
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2002-2006 Free Software Foundation Europe e.V.
+ Copyright (C) 2002-2007 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.
(FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
Switzerland, email:ftf@fsfeurope.org.
*/
+/*
+ *
+ * Bacula Director -- User Agent Database File tree for Restore
+ * command. This file interacts with the user implementing the
+ * UA tree commands.
+ *
+ * Kern Sibbald, July MMII
+ *
+ * Version $Id$
+ */
#include "bacula.h"
#include "dird.h"
static int helpcmd(UAContext *ua, TREE_CTX *tree);
static int cdcmd(UAContext *ua, TREE_CTX *tree);
static int pwdcmd(UAContext *ua, TREE_CTX *tree);
+static int dot_pwdcmd(UAContext *ua, TREE_CTX *tree);
static int unmarkcmd(UAContext *ua, TREE_CTX *tree);
static int unmarkdircmd(UAContext *ua, TREE_CTX *tree);
static int quitcmd(UAContext *ua, TREE_CTX *tree);
{ 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")},
+ { NT_(".pwd"), dot_pwdcmd, _("print current working directory")},
{ 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_("?"), helpcmd, _("print help")},
};
-#define comsize (sizeof(commands)/sizeof(struct cmdstruct))
-
+#define comsize ((int)(sizeof(commands)/sizeof(struct cmdstruct)))
/*
* Enter a prompt mode where the user can select/deselect
len = strlen(ua->argk[0]);
found = 0;
stat = false;
- for (i=0; i<(int)comsize; i++) /* search for command */
+ for (i=0; i<comsize; i++) /* search for command */
if (strncasecmp(ua->argk[0], _(commands[i].key), len) == 0) {
stat = (*commands[i].func)(ua, tree); /* go execute command */
found = 1;
return count;
}
+static void strip_trailing_slash(char *arg)
+{
+ int len = strlen(arg);
+ if (len == 0) {
+ return;
+ }
+ len--;
+ if (arg[len] == '/') { /* strip any trailing slash */
+ arg[len] = 0;
+ }
+}
+
/*
* Recursively mark the current directory to be restored as
* well as all directories and files below it.
return 1;
}
for (int i=1; i < ua->argc; i++) {
+ strip_trailing_slash(ua->argk[i]);
foreach_child(node, tree->node) {
if (fnmatch(ua->argk[i], node->fname, 0) == 0) {
count += set_extract(ua, node, tree, true);
return 1;
}
for (int i=1; i < ua->argc; i++) {
+ strip_trailing_slash(ua->argk[i]);
foreach_child(node, tree->node) {
if (fnmatch(ua->argk[i], node->fname, 0) == 0) {
if (node->type == TN_DIR || node->type == TN_DIR_NLS) {
return 1;
}
+static int dot_pwdcmd(UAContext *ua, TREE_CTX *tree)
+{
+ char cwd[2000];
+ tree_getpath(tree->node, cwd, sizeof(cwd));
+ bsendmsg(ua, _("%s"), cwd);
+ return 1;
+}
static int unmarkcmd(UAContext *ua, TREE_CTX *tree)
{
return 1;
}
for (int i=1; i < ua->argc; i++) {
+ strip_trailing_slash(ua->argk[i]);
foreach_child(node, tree->node) {
if (fnmatch(ua->argk[i], node->fname, 0) == 0) {
count += set_extract(ua, node, tree, false);
}
for (int i=1; i < ua->argc; i++) {
+ strip_trailing_slash(ua->argk[i]);
foreach_child(node, tree->node) {
if (fnmatch(ua->argk[i], node->fname, 0) == 0) {
if (node->type == TN_DIR || node->type == TN_DIR_NLS) {
#undef VERSION
#define VERSION "2.1.4"
-#define BDATE "02 March 2007"
-#define LSMDATE "02Mar07"
+#define BDATE "05 March 2007"
+#define LSMDATE "05Mar07"
#define PROG_COPYRIGHT "Copyright (C) %d-2007 Free Software Foundation Europe e.V.\n"
#define BYEAR "2007" /* year for copyright messages in progs */
Technical notes on version 2.1
General:
+05Mar07
+kes Extend new GUI api code to tree commands.
+kes Ensure that tree and dot commands check console ACLs.
+kes Permit marking directory with trailing slash.
+kes Allow 20 console connections (instead of only 10).
04Mar07
kes Add smartctl call to bacula-sd.conf as an example of getting
tape alert info.