2 Bacula® - The Network Backup Solution
4 Copyright (C) 2002-2010 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 three of the GNU Affero General Public
10 License as published by the Free Software Foundation and included
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 Affero 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 Kern Sibbald.
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
42 #include "cats/bvfs.h"
43 #include "findlib/find.h"
45 /* Imported variables */
47 /* Imported functions */
48 extern void do_messages(UAContext *ua, const char *cmd);
49 extern int quit_cmd(UAContext *ua, const char *cmd);
50 extern int qhelp_cmd(UAContext *ua, const char *cmd);
51 extern bool dot_status_cmd(UAContext *ua, const char *cmd);
54 /* Forward referenced functions */
55 static bool admin_cmds(UAContext *ua, const char *cmd);
56 static bool jobscmd(UAContext *ua, const char *cmd);
57 static bool filesetscmd(UAContext *ua, const char *cmd);
58 static bool clientscmd(UAContext *ua, const char *cmd);
59 static bool msgscmd(UAContext *ua, const char *cmd);
60 static bool poolscmd(UAContext *ua, const char *cmd);
61 static bool storagecmd(UAContext *ua, const char *cmd);
62 static bool defaultscmd(UAContext *ua, const char *cmd);
63 static bool typescmd(UAContext *ua, const char *cmd);
64 static bool backupscmd(UAContext *ua, const char *cmd);
65 static bool levelscmd(UAContext *ua, const char *cmd);
66 static bool getmsgscmd(UAContext *ua, const char *cmd);
67 static bool volstatuscmd(UAContext *ua, const char *cmd);
68 static bool mediatypescmd(UAContext *ua, const char *cmd);
69 static bool locationscmd(UAContext *ua, const char *cmd);
70 static bool mediacmd(UAContext *ua, const char *cmd);
71 static bool aopcmd(UAContext *ua, const char *cmd);
73 static bool dot_bvfs_lsdirs(UAContext *ua, const char *cmd);
74 static bool dot_bvfs_lsfiles(UAContext *ua, const char *cmd);
75 static bool dot_bvfs_update(UAContext *ua, const char *cmd);
76 static bool dot_bvfs_get_jobids(UAContext *ua, const char *cmd);
77 static bool dot_bvfs_versions(UAContext *ua, const char *cmd);
79 static bool api_cmd(UAContext *ua, const char *cmd);
80 static bool sql_cmd(UAContext *ua, const char *cmd);
81 static bool dot_quit_cmd(UAContext *ua, const char *cmd);
82 static bool dot_help_cmd(UAContext *ua, const char *cmd);
84 struct cmdstruct { const char *key; bool (*func)(UAContext *ua, const char *cmd); const char *help;const bool use_in_rs;};
85 static struct cmdstruct commands[] = { /* help */ /* can be used in runscript */
86 { NT_(".api"), api_cmd, NULL, false},
87 { NT_(".backups"), backupscmd, NULL, false},
88 { NT_(".clients"), clientscmd, NULL, true},
89 { NT_(".defaults"), defaultscmd, NULL, false},
90 { NT_(".die"), admin_cmds, NULL, false},
91 { NT_(".dump"), admin_cmds, NULL, false},
92 { NT_(".exit"), admin_cmds, NULL, false},
93 { NT_(".filesets"), filesetscmd, NULL, false},
94 { NT_(".help"), dot_help_cmd, NULL, false},
95 { NT_(".jobs"), jobscmd, NULL, true},
96 { NT_(".levels"), levelscmd, NULL, false},
97 { NT_(".messages"), getmsgscmd, NULL, false},
98 { NT_(".msgs"), msgscmd, NULL, false},
99 { NT_(".pools"), poolscmd, NULL, true},
100 { NT_(".quit"), dot_quit_cmd, NULL, false},
101 { NT_(".sql"), sql_cmd, NULL, false},
102 { NT_(".status"), dot_status_cmd, NULL, false},
103 { NT_(".storage"), storagecmd, NULL, true},
104 { NT_(".volstatus"), volstatuscmd, NULL, true},
105 { NT_(".media"), mediacmd, NULL, true},
106 { NT_(".mediatypes"), mediatypescmd, NULL, true},
107 { NT_(".locations"), locationscmd, NULL, true},
108 { NT_(".actiononpurge"),aopcmd, NULL, true},
109 { NT_(".bvfs_lsdirs"), dot_bvfs_lsdirs, NULL, true},
110 { NT_(".bvfs_lsfiles"),dot_bvfs_lsfiles, NULL, true},
111 { NT_(".bvfs_update"), dot_bvfs_update, NULL, true},
112 { NT_(".bvfs_get_jobids"), dot_bvfs_get_jobids, NULL, true},
113 { NT_(".bvfs_versions"), dot_bvfs_versions, NULL, true},
114 { NT_(".types"), typescmd, NULL, false}
116 #define comsize ((int)(sizeof(commands)/sizeof(struct cmdstruct)))
119 * Execute a command from the UA
121 bool do_a_dot_command(UAContext *ua)
127 BSOCK *user = ua->UA_sock;
129 Dmsg1(1400, "Dot command: %s\n", user->msg);
134 len = strlen(ua->argk[0]);
136 if (ua->api) user->signal(BNET_CMD_BEGIN);
137 if (ua->api) user->signal(BNET_CMD_OK);
138 return true; /* no op */
140 for (i=0; i<comsize; i++) { /* search for command */
141 if (strncasecmp(ua->argk[0], _(commands[i].key), len) == 0) {
142 /* Check if this command is authorized in RunScript */
143 if (ua->runscript && !commands[i].use_in_rs) {
144 ua->error_msg(_("Can't use %s command in a runscript"), ua->argk[0]);
148 /* Check if command permitted, but "quit" is always OK */
149 if (strcmp(ua->argk[0], NT_(".quit")) != 0 &&
150 !acl_access_ok(ua, Command_ACL, ua->argk[0], len)) {
153 Dmsg1(100, "Cmd: %s\n", ua->cmd);
155 if (ua->api) user->signal(BNET_CMD_BEGIN);
156 ok = (*commands[i].func)(ua, ua->cmd); /* go execute command */
157 if (ua->api) user->signal(ok?BNET_CMD_OK:BNET_CMD_FAILED);
164 pm_strcat(user->msg, _(": is an invalid command.\n"));
165 ua->error_msg("%s", user->msg);
171 static bool dot_bvfs_update(UAContext *ua, const char *cmd)
173 if (!open_new_client_db(ua)) {
177 int pos = find_arg_with_value(ua, "jobid");
178 if (pos != -1 && is_a_number_list(ua->argv[pos])) {
180 pm_strcpy(jobids, ua->argv[pos]);
181 bvfs_update_path_hierarchy_cache(ua->jcr, ua->db, jobids.c_str());
183 /* update cache for all jobids */
184 bvfs_update_cache(ua->jcr, ua->db);
191 static int bvfs_result_handler(void *ctx, int fields, char **row)
193 UAContext *ua = (UAContext *)ctx;
196 char *fileid=row[BVFS_FileId];
197 char *lstat=row[BVFS_LStat];
198 char *jobid=row[BVFS_JobId];
200 char empty[] = "A A A A A A A A A A A A A A";
203 /* We need to deal with non existant path */
204 if (!fileid || !is_a_number(fileid)) {
210 memset(&statp, 0, sizeof(struct stat));
211 decode_stat(lstat, &statp, &LinkFI);
213 Dmsg1(100, "type=%s\n", row[0]);
214 if (bvfs_is_dir(row)) {
215 char *path = bvfs_basename_dir(row[BVFS_Name]);
216 ua->send_msg("%s\t0\t%s\t%s\t%s\t%s\n", row[BVFS_PathId], fileid,
219 } else if (bvfs_is_version(row)) {
220 ua->send_msg("%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n", row[BVFS_PathId],
221 row[BVFS_FilenameId], fileid, jobid,
222 lstat, row[BVFS_Md5], row[BVFS_VolName],
223 row[BVFS_VolInchanger]);
225 } else if (bvfs_is_file(row)) {
226 ua->send_msg("%s\t%s\t%s\t%s\t%s\t%s\n", row[BVFS_PathId],
227 row[BVFS_FilenameId], fileid, jobid,
228 lstat, row[BVFS_Name]);
234 static bool bvfs_parse_arg_version(UAContext *ua,
245 for (int i=1; i<ua->argc; i++) {
246 if (fnid && strcasecmp(ua->argk[i], NT_("fnid")) == 0) {
247 if (is_a_number(ua->argv[i])) {
248 *fnid = str_to_int64(ua->argv[i]);
252 if (strcasecmp(ua->argk[i], NT_("client")) == 0) {
253 *client = ua->argv[i];
256 if (copies && strcasecmp(ua->argk[i], NT_("copies")) == 0) {
260 if (versions && strcasecmp(ua->argk[i], NT_("versions")) == 0) {
264 return (*client && *fnid > 0);
267 static bool bvfs_parse_arg(UAContext *ua,
268 DBId_t *pathid, char **path, char **jobid,
269 int *limit, int *offset)
277 for (int i=1; i<ua->argc; i++) {
278 if (strcasecmp(ua->argk[i], NT_("pathid")) == 0) {
279 if (is_a_number(ua->argv[i])) {
280 *pathid = str_to_int64(ua->argv[i]);
284 if (strcasecmp(ua->argk[i], NT_("path")) == 0) {
288 if (strcasecmp(ua->argk[i], NT_("jobid")) == 0) {
289 if (is_a_number_list(ua->argv[i])) {
290 *jobid = ua->argv[i];
294 if (strcasecmp(ua->argk[i], NT_("limit")) == 0) {
295 if (is_a_number(ua->argv[i])) {
296 *limit = str_to_int64(ua->argv[i]);
300 if (strcasecmp(ua->argk[i], NT_("offset")) == 0) {
301 if (is_a_number(ua->argv[i])) {
302 *offset = str_to_int64(ua->argv[i]);
307 if (!((*pathid || *path) && *jobid)) {
311 if (!open_client_db(ua)) {
319 * .bvfs_lsfiles jobid=1,2,3,4 pathid=10
320 * .bvfs_lsfiles jobid=1,2,3,4 path=/
322 static bool dot_bvfs_lsfiles(UAContext *ua, const char *cmd)
325 int limit=2000, offset=0;
326 char *path=NULL, *jobid=NULL;
328 if (!bvfs_parse_arg(ua, &pathid, &path, &jobid,
331 ua->error_msg("Can't find jobid, pathid or path argument\n");
332 return true; /* not enough param */
335 Bvfs fs(ua->jcr, ua->db);
336 fs.set_jobids(jobid);
337 fs.set_handler(bvfs_result_handler, ua);
346 fs.set_offset(offset);
354 * .bvfs_lsdirs jobid=1,2,3,4 pathid=10
355 * .bvfs_lsdirs jobid=1,2,3,4 path=/
356 * .bvfs_lsdirs jobid=1,2,3,4 path=
358 static bool dot_bvfs_lsdirs(UAContext *ua, const char *cmd)
361 int limit=2000, offset=0;
362 char *path=NULL, *jobid=NULL;
364 if (!bvfs_parse_arg(ua, &pathid, &path, &jobid,
367 ua->error_msg("Can't find jobid, pathid or path argument\n");
368 return true; /* not enough param */
371 Bvfs fs(ua->jcr, ua->db);
372 fs.set_jobids(jobid);
374 fs.set_handler(bvfs_result_handler, ua);
382 fs.set_offset(offset);
384 fs.ls_special_dirs();
391 * .bvfs_versions jobid=x filenameid=10 pathid=10 copies versions
394 static bool dot_bvfs_versions(UAContext *ua, const char *cmd)
396 DBId_t pathid=0, fnid=0;
397 int limit=2000, offset=0;
398 char *path=NULL, *jobid=NULL, *client=NULL;
399 bool copies=false, versions=false;
400 if (!bvfs_parse_arg(ua, &pathid, &path, &jobid,
403 ua->error_msg("Can't find jobid, pathid or path argument\n");
404 return true; /* not enough param */
407 if (!bvfs_parse_arg_version(ua, &client, &fnid, &versions, &copies))
409 ua->error_msg("Can't find client or filenameid argument\n");
410 return true; /* not enough param */
413 Bvfs fs(ua->jcr, ua->db);
415 fs.set_see_all_versions(versions);
416 fs.set_see_copies(copies);
417 fs.set_handler(bvfs_result_handler, ua);
418 fs.set_offset(offset);
419 fs.get_all_file_versions(pathid, fnid, client);
424 /* .bvfs_get_jobids jobid=1
425 * -> returns needed jobids to restore
426 * .bvfs_get_jobids jobid=1 all
427 * -> returns needed jobids to restore with all filesets a JobId=1 time
429 static bool dot_bvfs_get_jobids(UAContext *ua, const char *cmd)
432 db_list_ctx jobids, tempids;
436 dbid_list ids; /* Store all FileSetIds for this client */
438 if (!open_client_db(ua)) {
442 memset(&jr, 0, sizeof(JOB_DBR));
443 if ((pos = find_arg_with_value(ua, "jobid")) >= 0) {
444 jr.JobId = str_to_int64(ua->argv[pos]);
447 if (!db_get_job_record(ua->jcr, ua->db, &jr)) {
448 ua->error_msg(_("Unable to get Job record for JobId=%s: ERR=%s\n"),
449 ua->cmd, db_strerror(ua->db));
453 /* If we have the "all" option, we do a search on all defined fileset
456 if (find_arg(ua, "all") > 0) {
457 edit_int64(jr.ClientId, ed1);
458 Mmsg(query, uar_sel_filesetid, ed1);
459 db_get_query_dbids(ua->jcr, ua->db, query, ids);
462 ids.DBId[0] = jr.FileSetId;
465 jr.JobLevel = L_INCREMENTAL; /* Take Full+Diff+Incr */
467 /* Foreach different FileSet, we build a restore jobid list */
468 for (int i=0; i < ids.num_ids; i++) {
469 jr.FileSetId = ids.DBId[i];
470 if (!db_accurate_get_jobids(ua->jcr, ua->db, &jr, &tempids)) {
476 ua->send_msg("%s\n", jobids.list);
480 static bool dot_quit_cmd(UAContext *ua, const char *cmd)
486 static bool dot_help_cmd(UAContext *ua, const char *cmd)
492 static bool getmsgscmd(UAContext *ua, const char *cmd)
494 if (console_msg_pending) {
495 do_messages(ua, cmd);
501 static void do_storage_cmd(UAContext *ua, STORE *store, const char *cmd)
507 lstore.store = store;
508 pm_strcpy(lstore.store_source, _("unknown source"));
509 set_wstorage(jcr, &lstore);
510 /* Try connecting for up to 15 seconds */
511 ua->send_msg(_("Connecting to Storage daemon %s at %s:%d\n"),
512 store->name(), store->address, store->SDport);
513 if (!connect_to_storage_daemon(jcr, 1, 15, 0)) {
514 ua->error_msg(_("Failed to connect to Storage daemon.\n"));
517 Dmsg0(120, _("Connected to storage daemon\n"));
518 sd = jcr->store_bsock;
519 sd->fsend("%s", cmd);
520 if (sd->recv() >= 0) {
521 ua->send_msg("%s", sd->msg);
523 sd->signal(BNET_TERMINATE);
525 jcr->store_bsock = NULL;
529 static void do_client_cmd(UAContext *ua, CLIENT *client, const char *cmd)
533 /* Connect to File daemon */
535 ua->jcr->client = client;
536 /* Try to connect for 15 seconds */
537 ua->send_msg(_("Connecting to Client %s at %s:%d\n"),
538 client->name(), client->address, client->FDport);
539 if (!connect_to_file_daemon(ua->jcr, 1, 15, 0)) {
540 ua->error_msg(_("Failed to connect to Client.\n"));
543 Dmsg0(120, "Connected to file daemon\n");
544 fd = ua->jcr->file_bsock;
545 fd->fsend("%s", cmd);
546 if (fd->recv() >= 0) {
547 ua->send_msg("%s", fd->msg);
549 fd->signal(BNET_TERMINATE);
551 ua->jcr->file_bsock = NULL;
558 * .exit (no arg => .quit)
560 static bool admin_cmds(UAContext *ua, const char *cmd)
562 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
566 bool do_deadlock=false;
567 const char *remote_cmd;
571 if (strncmp(ua->argk[0], ".die", 4) == 0) {
572 if (find_arg(ua, "deadlock") > 0) {
574 remote_cmd = ".die deadlock";
578 } else if (strncmp(ua->argk[0], ".dump", 5) == 0) {
579 remote_cmd = "sm_dump";
580 } else if (strncmp(ua->argk[0], ".exit", 5) == 0) {
583 ua->error_msg(_("Unknown command: %s\n"), ua->argk[0]);
587 for (i=1; i<ua->argc; i++) {
588 if (strcasecmp(ua->argk[i], "dir") == 0 ||
589 strcasecmp(ua->argk[i], "director") == 0) {
592 if (strcasecmp(ua->argk[i], "client") == 0 ||
593 strcasecmp(ua->argk[i], "fd") == 0) {
596 client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[i]);
599 client = select_client_resource(ua);
603 if (strcasecmp(ua->argk[i], NT_("store")) == 0 ||
604 strcasecmp(ua->argk[i], NT_("storage")) == 0 ||
605 strcasecmp(ua->argk[i], NT_("sd")) == 0) {
608 store = (STORE *)GetResWithName(R_STORAGE, ua->argv[i]);
611 store = get_storage_resource(ua, false/*no default*/);
616 if (!dir && !store && !client) {
618 * We didn't find an appropriate keyword above, so
621 start_prompt(ua, _("Available daemons are: \n"));
622 add_prompt(ua, _("Director"));
623 add_prompt(ua, _("Storage"));
624 add_prompt(ua, _("Client"));
625 switch(do_prompt(ua, "", _("Select daemon type to make die"), NULL, 0)) {
626 case 0: /* Director */
630 store = get_storage_resource(ua, false/*no default*/);
633 client = select_client_resource(ua);
641 do_storage_cmd(ua, store, remote_cmd);
645 do_client_cmd(ua, client, remote_cmd);
649 if (strncmp(remote_cmd, ".die", 4) == 0) {
651 ua->send_msg(_("The Director will generate a deadlock.\n"));
655 ua->send_msg(_("The Director will segment fault.\n"));
656 a = jcr->JobId; /* ref NULL pointer */
657 jcr->JobId = 1000; /* another ref NULL pointer */
659 } else if (strncmp(remote_cmd, ".dump", 5) == 0) {
660 sm_dump(false, true);
661 } else if (strncmp(remote_cmd, ".exit", 5) == 0) {
662 dot_quit_cmd(ua, cmd);
672 * Dummy routine for non-development version
674 static bool admin_cmds(UAContext *ua, const char *cmd)
676 ua->error_msg(_("Unknown command: %s\n"), ua->argk[0]);
683 * Can use an argument to filter on JobType
686 static bool jobscmd(UAContext *ua, const char *cmd)
691 if ((pos = find_arg_with_value(ua, "type")) >= 0) {
692 type = ua->argv[pos][0];
695 foreach_res(job, R_JOB) {
696 if (!type || type == job->JobType) {
697 if (acl_access_ok(ua, Job_ACL, job->name())) {
698 ua->send_msg("%s\n", job->name());
706 static bool filesetscmd(UAContext *ua, const char *cmd)
710 foreach_res(fs, R_FILESET) {
711 if (acl_access_ok(ua, FileSet_ACL, fs->name())) {
712 ua->send_msg("%s\n", fs->name());
719 static bool clientscmd(UAContext *ua, const char *cmd)
723 foreach_res(client, R_CLIENT) {
724 if (acl_access_ok(ua, Client_ACL, client->name())) {
725 ua->send_msg("%s\n", client->name());
732 static bool msgscmd(UAContext *ua, const char *cmd)
736 foreach_res(msgs, R_MSGS) {
737 ua->send_msg("%s\n", msgs->name());
743 static bool poolscmd(UAContext *ua, const char *cmd)
747 foreach_res(pool, R_POOL) {
748 if (acl_access_ok(ua, Pool_ACL, pool->name())) {
749 ua->send_msg("%s\n", pool->name());
756 static bool storagecmd(UAContext *ua, const char *cmd)
760 foreach_res(store, R_STORAGE) {
761 if (acl_access_ok(ua, Storage_ACL, store->name())) {
762 ua->send_msg("%s\n", store->name());
769 static bool aopcmd(UAContext *ua, const char *cmd)
771 ua->send_msg("None\n");
772 ua->send_msg("Truncate\n");
776 static bool typescmd(UAContext *ua, const char *cmd)
778 ua->send_msg("Backup\n");
779 ua->send_msg("Restore\n");
780 ua->send_msg("Admin\n");
781 ua->send_msg("Verify\n");
782 ua->send_msg("Migrate\n");
783 ua->send_msg("Copy\n");
788 * If this command is called, it tells the director that we
789 * are a program that wants a sort of API, and hence,
790 * we will probably suppress certain output, include more
791 * error codes, and most of all send back a good number
792 * of new signals that indicate whether or not the command
795 static bool api_cmd(UAContext *ua, const char *cmd)
798 ua->api = atoi(ua->argk[1]);
805 static int client_backups_handler(void *ctx, int num_field, char **row)
807 UAContext *ua = (UAContext *)ctx;
808 ua->send_msg("| %s | %s | %s | %s | %s | %s | %s | %s |\n",
809 row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8]);
814 * Return the backups for this client
816 * .backups client=xxx fileset=yyy
819 static bool backupscmd(UAContext *ua, const char *cmd)
821 if (!open_client_db(ua)) {
824 if (ua->argc != 3 || strcmp(ua->argk[1], "client") != 0 ||
825 strcmp(ua->argk[2], "fileset") != 0) {
828 if (!acl_access_ok(ua, Client_ACL, ua->argv[1]) ||
829 !acl_access_ok(ua, FileSet_ACL, ua->argv[2])) {
830 ua->error_msg(_("Access to specified Client or FileSet not allowed.\n"));
833 Mmsg(ua->cmd, client_backups, ua->argv[1], ua->argv[2]);
834 if (!db_sql_query(ua->db, ua->cmd, client_backups_handler, (void *)ua)) {
835 ua->error_msg(_("Query failed: %s. ERR=%s\n"), ua->cmd, db_strerror(ua->db));
841 static int sql_handler(void *ctx, int num_field, char **row)
843 UAContext *ua = (UAContext *)ctx;
844 POOL_MEM rows(PM_MESSAGE);
846 /* Check for nonsense */
847 if (num_field == 0 || row == NULL || row[0] == NULL) {
848 return 0; /* nothing returned */
850 for (int i=0; num_field--; i++) {
852 pm_strcpy(rows, NPRT(row[0]));
854 pm_strcat(rows, NPRT(row[i]));
856 pm_strcat(rows, "\t");
858 if (!rows.c_str() || !*rows.c_str()) {
861 ua->send_msg("%s", rows.c_str());
866 static bool sql_cmd(UAContext *ua, const char *cmd)
869 if (!open_client_db(ua)) {
872 index = find_arg_with_value(ua, "query");
874 ua->error_msg(_("query keyword not found.\n"));
877 if (!db_sql_query(ua->db, ua->argv[index], sql_handler, (void *)ua)) {
878 Dmsg1(100, "Query failed: ERR=%s\n", db_strerror(ua->db));
879 ua->error_msg(_("Query failed: %s. ERR=%s\n"), ua->cmd, db_strerror(ua->db));
885 static int one_handler(void *ctx, int num_field, char **row)
887 UAContext *ua = (UAContext *)ctx;
888 ua->send_msg("%s\n", row[0]);
892 static bool mediatypescmd(UAContext *ua, const char *cmd)
894 if (!open_client_db(ua)) {
897 if (!db_sql_query(ua->db,
898 "SELECT DISTINCT MediaType FROM MediaType ORDER BY MediaType",
899 one_handler, (void *)ua))
901 ua->error_msg(_("List MediaType failed: ERR=%s\n"), db_strerror(ua->db));
906 static bool mediacmd(UAContext *ua, const char *cmd)
908 if (!open_client_db(ua)) {
911 if (!db_sql_query(ua->db,
912 "SELECT DISTINCT Media.VolumeName FROM Media ORDER BY VolumeName",
913 one_handler, (void *)ua))
915 ua->error_msg(_("List Media failed: ERR=%s\n"), db_strerror(ua->db));
920 static bool locationscmd(UAContext *ua, const char *cmd)
922 if (!open_client_db(ua)) {
925 if (!db_sql_query(ua->db,
926 "SELECT DISTINCT Location FROM Location ORDER BY Location",
927 one_handler, (void *)ua))
929 ua->error_msg(_("List Location failed: ERR=%s\n"), db_strerror(ua->db));
934 static bool levelscmd(UAContext *ua, const char *cmd)
936 ua->send_msg("Incremental\n");
937 ua->send_msg("Full\n");
938 ua->send_msg("Differential\n");
939 ua->send_msg("VirtualFull\n");
940 ua->send_msg("Catalog\n");
941 ua->send_msg("InitCatalog\n");
942 ua->send_msg("VolumeToCatalog\n");
943 ua->send_msg("Base\n");
947 static bool volstatuscmd(UAContext *ua, const char *cmd)
949 ua->send_msg("Append\n");
950 ua->send_msg("Full\n");
951 ua->send_msg("Used\n");
952 ua->send_msg("Recycle\n");
953 ua->send_msg("Purged\n");
954 ua->send_msg("Cleaning\n");
955 ua->send_msg("Error\n");
960 * Return default values for a job
962 static bool defaultscmd(UAContext *ua, const char *cmd)
970 if (ua->argc != 2 || !ua->argv[1]) {
975 if (strcmp(ua->argk[1], "job") == 0) {
976 if (!acl_access_ok(ua, Job_ACL, ua->argv[1])) {
979 job = (JOB *)GetResWithName(R_JOB, ua->argv[1]);
982 ua->send_msg("job=%s", job->name());
983 ua->send_msg("pool=%s", job->pool->name());
984 ua->send_msg("messages=%s", job->messages->name());
985 ua->send_msg("client=%s", job->client->name());
986 get_job_storage(&store, job, NULL);
987 ua->send_msg("storage=%s", store.store->name());
988 ua->send_msg("where=%s", job->RestoreWhere?job->RestoreWhere:"");
989 ua->send_msg("level=%s", level_to_str(job->JobLevel));
990 ua->send_msg("type=%s", job_type_to_str(job->JobType));
991 ua->send_msg("fileset=%s", job->fileset->name());
992 ua->send_msg("enabled=%d", job->enabled);
993 ua->send_msg("catalog=%s", job->client->catalog->name());
996 /* Client defaults */
997 else if (strcmp(ua->argk[1], "client") == 0) {
998 if (!acl_access_ok(ua, Client_ACL, ua->argv[1])) {
1001 client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[1]);
1003 ua->send_msg("client=%s", client->name());
1004 ua->send_msg("address=%s", client->address);
1005 ua->send_msg("fdport=%d", client->FDport);
1006 ua->send_msg("file_retention=%s", edit_uint64(client->FileRetention, ed1));
1007 ua->send_msg("job_retention=%s", edit_uint64(client->JobRetention, ed1));
1008 ua->send_msg("autoprune=%d", client->AutoPrune);
1009 ua->send_msg("catalog=%s", client->catalog->name());
1012 /* Storage defaults */
1013 else if (strcmp(ua->argk[1], "storage") == 0) {
1014 if (!acl_access_ok(ua, Storage_ACL, ua->argv[1])) {
1017 storage = (STORE *)GetResWithName(R_STORAGE, ua->argv[1]);
1020 ua->send_msg("storage=%s", storage->name());
1021 ua->send_msg("address=%s", storage->address);
1022 ua->send_msg("enabled=%d", storage->enabled);
1023 ua->send_msg("media_type=%s", storage->media_type);
1024 ua->send_msg("sdport=%d", storage->SDport);
1025 device = (DEVICE *)storage->device->first();
1026 ua->send_msg("device=%s", device->name());
1027 if (storage->device->size() > 1) {
1028 while ((device = (DEVICE *)storage->device->next())) {
1029 ua->send_msg(",%s", device->name());
1035 else if (strcmp(ua->argk[1], "pool") == 0) {
1036 if (!acl_access_ok(ua, Pool_ACL, ua->argv[1])) {
1039 pool = (POOL *)GetResWithName(R_POOL, ua->argv[1]);
1041 ua->send_msg("pool=%s", pool->name());
1042 ua->send_msg("pool_type=%s", pool->pool_type);
1043 ua->send_msg("label_format=%s", pool->label_format?pool->label_format:"");
1044 ua->send_msg("use_volume_once=%d", pool->use_volume_once);
1045 ua->send_msg("purge_oldest_volume=%d", pool->purge_oldest_volume);
1046 ua->send_msg("recycle_oldest_volume=%d", pool->recycle_oldest_volume);
1047 ua->send_msg("recycle_current_volume=%d", pool->recycle_current_volume);
1048 ua->send_msg("max_volumes=%d", pool->max_volumes);
1049 ua->send_msg("vol_retention=%s", edit_uint64(pool->VolRetention, ed1));
1050 ua->send_msg("vol_use_duration=%s", edit_uint64(pool->VolUseDuration, ed1));
1051 ua->send_msg("max_vol_jobs=%d", pool->MaxVolJobs);
1052 ua->send_msg("max_vol_files=%d", pool->MaxVolFiles);
1053 ua->send_msg("max_vol_bytes=%s", edit_uint64(pool->MaxVolBytes, ed1));
1054 ua->send_msg("auto_prune=%d", pool->AutoPrune);
1055 ua->send_msg("recycle=%d", pool->Recycle);
1056 ua->send_msg("file_retention=%s", edit_uint64(pool->FileRetention, ed1));
1057 ua->send_msg("job_retention=%s", edit_uint64(pool->JobRetention, ed1));