2 Bacula® - The Network Backup Solution
4 Copyright (C) 2002-2007 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation plus additions
11 that are listed in the file LICENSE.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of John Walker.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
30 * Bacula Director -- User Agent Commands
31 * These are "dot" commands, i.e. commands preceded
32 * by a period. These commands are meant to be used
33 * by a program, so there is no prompting, and the
34 * returned results are (supposed to be) predictable.
36 * Kern Sibbald, April MMII
44 /* Imported variables */
47 extern struct s_res resources[];
49 /* Imported functions */
50 extern void do_messages(UAContext *ua, const char *cmd);
51 extern int quit_cmd(UAContext *ua, const char *cmd);
52 extern int qhelp_cmd(UAContext *ua, const char *cmd);
53 extern bool dot_status_cmd(UAContext *ua, const char *cmd);
56 /* Forward referenced functions */
57 static bool diecmd(UAContext *ua, const char *cmd);
58 static bool jobscmd(UAContext *ua, const char *cmd);
59 static bool filesetscmd(UAContext *ua, const char *cmd);
60 static bool clientscmd(UAContext *ua, const char *cmd);
61 static bool msgscmd(UAContext *ua, const char *cmd);
62 static bool poolscmd(UAContext *ua, const char *cmd);
63 static bool storagecmd(UAContext *ua, const char *cmd);
64 static bool defaultscmd(UAContext *ua, const char *cmd);
65 static bool typescmd(UAContext *ua, const char *cmd);
66 static bool backupscmd(UAContext *ua, const char *cmd);
67 static bool levelscmd(UAContext *ua, const char *cmd);
68 static bool getmsgscmd(UAContext *ua, const char *cmd);
70 static bool api_cmd(UAContext *ua, const char *cmd);
71 static bool dot_quit_cmd(UAContext *ua, const char *cmd);
72 static bool dot_help_cmd(UAContext *ua, const char *cmd);
74 struct cmdstruct { const char *key; bool (*func)(UAContext *ua, const char *cmd); const char *help; };
75 static struct cmdstruct commands[] = {
76 { NT_(".api"), api_cmd, NULL},
77 { NT_(".backups"), backupscmd, NULL},
78 { NT_(".clients"), clientscmd, NULL},
79 { NT_(".defaults"), defaultscmd, NULL},
80 { NT_(".die"), diecmd, NULL},
81 { NT_(".exit"), dot_quit_cmd, NULL},
82 { NT_(".filesets"), filesetscmd, NULL},
83 { NT_(".help"), dot_help_cmd, NULL},
84 { NT_(".jobs"), jobscmd, NULL},
85 { NT_(".levels"), levelscmd, NULL},
86 { NT_(".messages"), getmsgscmd, NULL},
87 { NT_(".msgs"), msgscmd, NULL},
88 { NT_(".pools"), poolscmd, NULL},
89 { NT_(".quit"), dot_quit_cmd, NULL},
90 { NT_(".status"), dot_status_cmd, NULL},
91 { NT_(".storage"), storagecmd, NULL},
92 { NT_(".types"), typescmd, NULL}
94 #define comsize (sizeof(commands)/sizeof(struct cmdstruct))
97 * Execute a command from the UA
99 int do_a_dot_command(UAContext *ua, const char *cmd)
105 BSOCK *sock = ua->UA_sock;
107 Dmsg1(1400, "Dot command: %s\n", ua->UA_sock->msg);
112 len = strlen(ua->argk[0]);
114 return 1; /* no op */
116 for (i=0; i<(int)comsize; i++) { /* search for command */
117 if (strncasecmp(ua->argk[0], _(commands[i].key), len) == 0) {
121 sock->signal(BNET_CMD_BEGIN);
123 ok = (*commands[i].func)(ua, cmd); /* go execute command */
130 pm_strcat(sock->msg, _(": is an invalid command\n"));
131 sock->msglen = strlen(sock->msg);
133 sock->signal(BNET_INVALID_CMD);
135 sock->signal(ok?BNET_CMD_OK:BNET_CMD_FAILED);
139 static bool dot_quit_cmd(UAContext *ua, const char *cmd)
145 static bool dot_help_cmd(UAContext *ua, const char *cmd)
151 static bool getmsgscmd(UAContext *ua, const char *cmd)
153 if (console_msg_pending) {
154 do_messages(ua, cmd);
160 * Create segmentation fault
162 static bool diecmd(UAContext *ua, const char *cmd)
167 bsendmsg(ua, _("The Director will segment fault.\n"));
168 a = jcr->JobId; /* ref NULL pointer */
169 jcr->JobId = 1000; /* another ref NULL pointer */
173 static bool jobscmd(UAContext *ua, const char *cmd)
177 while ( (job = (JOB *)GetNextRes(R_JOB, (RES *)job)) ) {
178 if (acl_access_ok(ua, Job_ACL, job->name())) {
179 bsendmsg(ua, "%s\n", job->name());
186 static bool filesetscmd(UAContext *ua, const char *cmd)
190 while ( (fs = (FILESET *)GetNextRes(R_FILESET, (RES *)fs)) ) {
191 if (acl_access_ok(ua, FileSet_ACL, fs->name())) {
192 bsendmsg(ua, "%s\n", fs->name());
199 static bool clientscmd(UAContext *ua, const char *cmd)
201 CLIENT *client = NULL;
203 while ( (client = (CLIENT *)GetNextRes(R_CLIENT, (RES *)client)) ) {
204 if (acl_access_ok(ua, Client_ACL, client->name())) {
205 bsendmsg(ua, "%s\n", client->name());
212 static bool msgscmd(UAContext *ua, const char *cmd)
216 while ( (msgs = (MSGS *)GetNextRes(R_MSGS, (RES *)msgs)) ) {
217 bsendmsg(ua, "%s\n", msgs->name());
223 static bool poolscmd(UAContext *ua, const char *cmd)
227 while ( (pool = (POOL *)GetNextRes(R_POOL, (RES *)pool)) ) {
228 if (acl_access_ok(ua, Pool_ACL, pool->name())) {
229 bsendmsg(ua, "%s\n", pool->name());
236 static bool storagecmd(UAContext *ua, const char *cmd)
240 while ( (store = (STORE *)GetNextRes(R_STORAGE, (RES *)store)) ) {
241 if (acl_access_ok(ua, Storage_ACL, store->name())) {
242 bsendmsg(ua, "%s\n", store->name());
250 static bool typescmd(UAContext *ua, const char *cmd)
252 bsendmsg(ua, "Backup\n");
253 bsendmsg(ua, "Restore\n");
254 bsendmsg(ua, "Admin\n");
255 bsendmsg(ua, "Verify\n");
256 bsendmsg(ua, "Migrate\n");
260 static int client_backups_handler(void *ctx, int num_field, char **row)
262 UAContext *ua = (UAContext *)ctx;
263 bsendmsg(ua, "| %s | %s | %s | %s | %s | %s | %s | %s |\n",
264 row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8]);
269 * If this command is called, it tells the director that we
270 * are a program that wants a sort of API, and hence,
271 * we will probably suppress certain output, include more
272 * error codes, and most of all send back a good number
273 * of new signals that indicate whether or not the command
276 static bool api_cmd(UAContext *ua, const char *cmd)
278 /* Eventually we will probably have several levels or
279 * capabilities enabled by this.
286 * Return the backups for this client
288 static bool backupscmd(UAContext *ua, const char *cmd)
290 if (!open_client_db(ua)) {
293 if (ua->argc != 3 || strcmp(ua->argk[1], "client") != 0 || strcmp(ua->argk[2], "fileset") != 0) {
296 if (!acl_access_ok(ua, Client_ACL, ua->argv[1]) ||
297 !acl_access_ok(ua, FileSet_ACL, ua->argv[2])) {
300 Mmsg(ua->cmd, client_backups, ua->argv[1], ua->argv[2]);
301 if (!db_sql_query(ua->db, ua->cmd, client_backups_handler, (void *)ua)) {
302 bsendmsg(ua, _("Query failed: %s. ERR=%s\n"), ua->cmd, db_strerror(ua->db));
310 static bool levelscmd(UAContext *ua, const char *cmd)
312 bsendmsg(ua, "Incremental\n");
313 bsendmsg(ua, "Full\n");
314 bsendmsg(ua, "Differential\n");
315 bsendmsg(ua, "Catalog\n");
316 bsendmsg(ua, "InitCatalog\n");
317 bsendmsg(ua, "VolumeToCatalog\n");
322 * Return default values for a job
324 static bool defaultscmd(UAContext *ua, const char *cmd)
331 if (ua->argc != 2 || !ua->argv[1]) {
336 if (strcmp(ua->argk[1], "job") == 0) {
337 if (!acl_access_ok(ua, Job_ACL, ua->argv[1])) {
340 job = (JOB *)GetResWithName(R_JOB, ua->argv[1]);
343 bsendmsg(ua, "job=%s", job->name());
344 bsendmsg(ua, "pool=%s", job->pool->name());
345 bsendmsg(ua, "messages=%s", job->messages->name());
346 bsendmsg(ua, "client=%s", job->client->name());
347 get_job_storage(&store, job, NULL);
348 bsendmsg(ua, "storage=%s", store.store->name());
349 bsendmsg(ua, "where=%s", job->RestoreWhere?job->RestoreWhere:"");
350 bsendmsg(ua, "level=%s", level_to_str(job->JobLevel));
351 bsendmsg(ua, "type=%s", job_type_to_str(job->JobType));
352 bsendmsg(ua, "fileset=%s", job->fileset->name());
353 bsendmsg(ua, "enabled=%d", job->enabled);
354 bsendmsg(ua, "catalog=%s", job->client->catalog->name());
357 /* Client defaults */
358 else if (strcmp(ua->argk[1], "client") == 0) {
359 if (!acl_access_ok(ua, Client_ACL, ua->argv[1])) {
362 client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[1]);
364 bsendmsg(ua, "client=%s", client->name());
365 bsendmsg(ua, "address=%s", client->address);
366 bsendmsg(ua, "fdport=%d", client->FDport);
367 bsendmsg(ua, "file_retention=%d", client->FileRetention);
368 bsendmsg(ua, "job_retention=%d", client->JobRetention);
369 bsendmsg(ua, "autoprune=%d", client->AutoPrune);
370 bsendmsg(ua, "catalog=%s", client->catalog->name());
373 /* Storage defaults */
374 else if (strcmp(ua->argk[1], "storage") == 0) {
375 if (!acl_access_ok(ua, Storage_ACL, ua->argv[1])) {
378 storage = (STORE *)GetResWithName(R_STORAGE, ua->argv[1]);
381 bsendmsg(ua, "storage=%s", storage->name());
382 bsendmsg(ua, "address=%s", storage->address);
383 bsendmsg(ua, "enabled=%d", storage->enabled);
384 bsendmsg(ua, "media_type=%s", storage->media_type);
385 bsendmsg(ua, "sdport=%d", storage->SDport);
386 device = (DEVICE *)storage->device->first();
387 bsendmsg(ua, "device=%s", device->name());
388 if (storage->device->size() > 1) {
389 while ((device = (DEVICE *)storage->device->next())) {
390 bsendmsg(ua, ",%s", device->name());
396 else if (strcmp(ua->argk[1], "pool") == 0) {
397 if (!acl_access_ok(ua, Pool_ACL, ua->argv[1])) {
400 pool = (POOL *)GetResWithName(R_POOL, ua->argv[1]);
402 bsendmsg(ua, "pool=%s", pool->name());
403 bsendmsg(ua, "pool_type=%s", pool->pool_type);
404 bsendmsg(ua, "label_format=%s", pool->label_format?pool->label_format:"");
405 bsendmsg(ua, "use_volume_once=%d", pool->use_volume_once);
406 bsendmsg(ua, "purge_oldest_volume=%d", pool->purge_oldest_volume);
407 bsendmsg(ua, "recycle_oldest_volume=%d", pool->recycle_oldest_volume);
408 bsendmsg(ua, "recycle_current_volume=%d", pool->recycle_current_volume);
409 bsendmsg(ua, "max_volumes=%d", pool->max_volumes);
410 bsendmsg(ua, "vol_retention=%d", pool->VolRetention);
411 bsendmsg(ua, "vol_use_duration=%d", pool->VolUseDuration);
412 bsendmsg(ua, "max_vol_jobs=%d", pool->MaxVolJobs);
413 bsendmsg(ua, "max_vol_files=%d", pool->MaxVolFiles);
414 bsendmsg(ua, "max_vol_bytes=%d", pool->MaxVolBytes);
415 bsendmsg(ua, "auto_prune=%d", pool->AutoPrune);
416 bsendmsg(ua, "recycle=%d", pool->Recycle);