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);
78 static bool api_cmd(UAContext *ua, const char *cmd);
79 static bool sql_cmd(UAContext *ua, const char *cmd);
80 static bool dot_quit_cmd(UAContext *ua, const char *cmd);
81 static bool dot_help_cmd(UAContext *ua, const char *cmd);
83 struct cmdstruct { const char *key; bool (*func)(UAContext *ua, const char *cmd); const char *help;const bool use_in_rs;};
84 static struct cmdstruct commands[] = { /* help */ /* can be used in runscript */
85 { NT_(".api"), api_cmd, NULL, false},
86 { NT_(".backups"), backupscmd, NULL, false},
87 { NT_(".clients"), clientscmd, NULL, true},
88 { NT_(".defaults"), defaultscmd, NULL, false},
89 { NT_(".die"), admin_cmds, NULL, false},
90 { NT_(".dump"), admin_cmds, NULL, false},
91 { NT_(".exit"), admin_cmds, NULL, false},
92 { NT_(".filesets"), filesetscmd, NULL, false},
93 { NT_(".help"), dot_help_cmd, NULL, false},
94 { NT_(".jobs"), jobscmd, NULL, true},
95 { NT_(".levels"), levelscmd, NULL, false},
96 { NT_(".messages"), getmsgscmd, NULL, false},
97 { NT_(".msgs"), msgscmd, NULL, false},
98 { NT_(".pools"), poolscmd, NULL, true},
99 { NT_(".quit"), dot_quit_cmd, NULL, false},
100 { NT_(".sql"), sql_cmd, NULL, false},
101 { NT_(".status"), dot_status_cmd, NULL, false},
102 { NT_(".storage"), storagecmd, NULL, true},
103 { NT_(".volstatus"), volstatuscmd, NULL, true},
104 { NT_(".media"), mediacmd, NULL, true},
105 { NT_(".mediatypes"), mediatypescmd, NULL, true},
106 { NT_(".locations"), locationscmd, NULL, true},
107 { NT_(".actiononpurge"),aopcmd, NULL, true},
108 { NT_(".bvfs_lsdirs"), dot_bvfs_lsdirs, NULL, true},
109 { NT_(".bvfs_lsfiles"),dot_bvfs_lsfiles,NULL, true},
110 { NT_(".bvfs_update"), dot_bvfs_update, NULL, true},
111 { NT_(".bvfs_get_jobids"), dot_bvfs_get_jobids,NULL,true},
112 { NT_(".types"), typescmd, NULL, false}
114 #define comsize ((int)(sizeof(commands)/sizeof(struct cmdstruct)))
117 * Execute a command from the UA
119 bool do_a_dot_command(UAContext *ua)
125 BSOCK *user = ua->UA_sock;
127 Dmsg1(1400, "Dot command: %s\n", user->msg);
132 len = strlen(ua->argk[0]);
134 if (ua->api) user->signal(BNET_CMD_BEGIN);
135 if (ua->api) user->signal(BNET_CMD_OK);
136 return true; /* no op */
138 for (i=0; i<comsize; i++) { /* search for command */
139 if (strncasecmp(ua->argk[0], _(commands[i].key), len) == 0) {
140 /* Check if this command is authorized in RunScript */
141 if (ua->runscript && !commands[i].use_in_rs) {
142 ua->error_msg(_("Can't use %s command in a runscript"), ua->argk[0]);
146 /* Check if command permitted, but "quit" is always OK */
147 if (strcmp(ua->argk[0], NT_(".quit")) != 0 &&
148 !acl_access_ok(ua, Command_ACL, ua->argk[0], len)) {
151 Dmsg1(100, "Cmd: %s\n", ua->cmd);
153 if (ua->api) user->signal(BNET_CMD_BEGIN);
154 ok = (*commands[i].func)(ua, ua->cmd); /* go execute command */
155 if (ua->api) user->signal(ok?BNET_CMD_OK:BNET_CMD_FAILED);
162 pm_strcat(user->msg, _(": is an invalid command.\n"));
163 ua->error_msg("%s", user->msg);
169 static bool dot_bvfs_update(UAContext *ua, const char *cmd)
171 if (!open_new_client_db(ua)) {
175 int pos = find_arg_with_value(ua, "jobid");
176 if (pos != -1 && is_a_number_list(ua->argv[pos])) {
178 pm_strcpy(jobids, ua->argv[pos]);
179 bvfs_update_path_hierarchy_cache(ua->jcr, ua->db, jobids.c_str());
181 /* update cache for all jobids */
182 bvfs_update_cache(ua->jcr, ua->db);
189 static int bvfs_result_handler(void *ctx, int fields, char **row)
191 UAContext *ua = (UAContext *)ctx;
194 char *fileid=row[BVFS_FileId];
195 char *lstat=row[BVFS_LStat];
196 char *jobid=row[BVFS_JobId];
198 char empty[] = "A A A A A A A A A A A A A A";
201 /* We need to deal with non existant path */
202 if (!fileid || !is_a_number(fileid)) {
208 memset(&statp, 0, sizeof(struct stat));
209 decode_stat(lstat, &statp, &LinkFI);
211 Dmsg1(100, "type=%s\n", row[0]);
212 if (bvfs_is_dir(row)) {
213 char *path = bvfs_basename_dir(row[BVFS_Name]);
214 ua->send_msg("%s\t0\t%s\t%s\t%s\t%s\n", row[BVFS_PathId], fileid,
217 } else if (bvfs_is_file(row)) {
218 ua->send_msg("%s\t%s\t%s\t%s\t%s\t%s\n", row[BVFS_PathId],
219 row[BVFS_FilenameId], fileid, jobid,
220 lstat, row[BVFS_Name]);
226 static bool bvfs_parse_arg(UAContext *ua,
227 DBId_t *pathid, char **path, char **jobid,
228 int *limit, int *offset)
236 for (int i=1; i<ua->argc; i++) {
237 if (strcasecmp(ua->argk[i], NT_("pathid")) == 0) {
238 if (is_a_number(ua->argv[i])) {
239 *pathid = str_to_int64(ua->argv[i]);
242 if (strcasecmp(ua->argk[i], NT_("path")) == 0) {
246 if (strcasecmp(ua->argk[i], NT_("jobid")) == 0) {
247 if (is_a_number_list(ua->argv[i])) {
248 *jobid = ua->argv[i];
252 if (strcasecmp(ua->argk[i], NT_("limit")) == 0) {
253 if (is_a_number(ua->argv[i])) {
254 *limit = str_to_int64(ua->argv[i]);
258 if (strcasecmp(ua->argk[i], NT_("offset")) == 0) {
259 if (is_a_number(ua->argv[i])) {
260 *offset = str_to_int64(ua->argv[i]);
265 if (!((*pathid || *path) && *jobid)) {
269 if (!open_client_db(ua)) {
277 * .bvfs_lsfiles jobid=1,2,3,4 pathid=10
278 * .bvfs_lsfiles jobid=1,2,3,4 path=/
280 static bool dot_bvfs_lsfiles(UAContext *ua, const char *cmd)
283 int limit=2000, offset=0;
284 char *path=NULL, *jobid=NULL;
286 if (!bvfs_parse_arg(ua, &pathid, &path, &jobid,
289 ua->error_msg("Can't find jobid, pathid or path argument\n");
290 return true; /* not enough param */
293 Bvfs fs(ua->jcr, ua->db);
294 fs.set_jobids(jobid);
295 fs.set_handler(bvfs_result_handler, ua);
304 fs.set_offset(offset);
312 * .bvfs_lsdirs jobid=1,2,3,4 pathid=10
313 * .bvfs_lsdirs jobid=1,2,3,4 path=/
314 * .bvfs_lsdirs jobid=1,2,3,4 path=
316 static bool dot_bvfs_lsdirs(UAContext *ua, const char *cmd)
319 int limit=2000, offset=0;
320 char *path=NULL, *jobid=NULL;
322 if (!bvfs_parse_arg(ua, &pathid, &path, &jobid,
325 ua->error_msg("Can't find jobid, pathid or path argument\n");
326 return true; /* not enough param */
329 Bvfs fs(ua->jcr, ua->db);
330 fs.set_jobids(jobid);
332 fs.set_handler(bvfs_result_handler, ua);
340 fs.set_offset(offset);
342 fs.ls_special_dirs();
348 static bool dot_bvfs_get_jobids(UAContext *ua, const char *cmd)
354 if (!open_client_db(ua)) {
358 memset(&jr, 0, sizeof(JOB_DBR));
359 if ((pos = find_arg_with_value(ua, "jobid")) >= 0) {
360 jr.JobId = str_to_int64(ua->argv[pos]);
363 if (!db_get_job_record(ua->jcr, ua->db, &jr)) {
364 ua->error_msg(_("Unable to get Job record for JobId=%s: ERR=%s\n"),
365 ua->cmd, db_strerror(ua->db));
368 jr.JobLevel = L_INCREMENTAL; /* Take Full+Diff+Incr */
369 if (!db_accurate_get_jobids(ua->jcr, ua->db, &jr, &jobids)) {
372 ua->send_msg("%s\n", jobids.list);
376 static bool dot_quit_cmd(UAContext *ua, const char *cmd)
382 static bool dot_help_cmd(UAContext *ua, const char *cmd)
388 static bool getmsgscmd(UAContext *ua, const char *cmd)
390 if (console_msg_pending) {
391 do_messages(ua, cmd);
397 static void do_storage_cmd(UAContext *ua, STORE *store, const char *cmd)
403 lstore.store = store;
404 pm_strcpy(lstore.store_source, _("unknown source"));
405 set_wstorage(jcr, &lstore);
406 /* Try connecting for up to 15 seconds */
407 ua->send_msg(_("Connecting to Storage daemon %s at %s:%d\n"),
408 store->name(), store->address, store->SDport);
409 if (!connect_to_storage_daemon(jcr, 1, 15, 0)) {
410 ua->error_msg(_("Failed to connect to Storage daemon.\n"));
413 Dmsg0(120, _("Connected to storage daemon\n"));
414 sd = jcr->store_bsock;
415 sd->fsend("%s", cmd);
416 if (sd->recv() >= 0) {
417 ua->send_msg("%s", sd->msg);
419 sd->signal(BNET_TERMINATE);
421 jcr->store_bsock = NULL;
425 static void do_client_cmd(UAContext *ua, CLIENT *client, const char *cmd)
429 /* Connect to File daemon */
431 ua->jcr->client = client;
432 /* Try to connect for 15 seconds */
433 ua->send_msg(_("Connecting to Client %s at %s:%d\n"),
434 client->name(), client->address, client->FDport);
435 if (!connect_to_file_daemon(ua->jcr, 1, 15, 0)) {
436 ua->error_msg(_("Failed to connect to Client.\n"));
439 Dmsg0(120, "Connected to file daemon\n");
440 fd = ua->jcr->file_bsock;
441 fd->fsend("%s", cmd);
442 if (fd->recv() >= 0) {
443 ua->send_msg("%s", fd->msg);
445 fd->signal(BNET_TERMINATE);
447 ua->jcr->file_bsock = NULL;
454 * .exit (no arg => .quit)
456 static bool admin_cmds(UAContext *ua, const char *cmd)
458 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
462 bool do_deadlock=false;
463 const char *remote_cmd;
467 if (strncmp(ua->argk[0], ".die", 4) == 0) {
468 if (find_arg(ua, "deadlock") > 0) {
470 remote_cmd = ".die deadlock";
474 } else if (strncmp(ua->argk[0], ".dump", 5) == 0) {
475 remote_cmd = "sm_dump";
476 } else if (strncmp(ua->argk[0], ".exit", 5) == 0) {
479 ua->error_msg(_("Unknown command: %s\n"), ua->argk[0]);
483 for (i=1; i<ua->argc; i++) {
484 if (strcasecmp(ua->argk[i], "dir") == 0 ||
485 strcasecmp(ua->argk[i], "director") == 0) {
488 if (strcasecmp(ua->argk[i], "client") == 0 ||
489 strcasecmp(ua->argk[i], "fd") == 0) {
492 client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[i]);
495 client = select_client_resource(ua);
499 if (strcasecmp(ua->argk[i], NT_("store")) == 0 ||
500 strcasecmp(ua->argk[i], NT_("storage")) == 0 ||
501 strcasecmp(ua->argk[i], NT_("sd")) == 0) {
504 store = (STORE *)GetResWithName(R_STORAGE, ua->argv[i]);
507 store = get_storage_resource(ua, false/*no default*/);
512 if (!dir && !store && !client) {
514 * We didn't find an appropriate keyword above, so
517 start_prompt(ua, _("Available daemons are: \n"));
518 add_prompt(ua, _("Director"));
519 add_prompt(ua, _("Storage"));
520 add_prompt(ua, _("Client"));
521 switch(do_prompt(ua, "", _("Select daemon type to make die"), NULL, 0)) {
522 case 0: /* Director */
526 store = get_storage_resource(ua, false/*no default*/);
529 client = select_client_resource(ua);
537 do_storage_cmd(ua, store, remote_cmd);
541 do_client_cmd(ua, client, remote_cmd);
545 if (strncmp(remote_cmd, ".die", 4) == 0) {
547 ua->send_msg(_("The Director will generate a deadlock.\n"));
551 ua->send_msg(_("The Director will segment fault.\n"));
552 a = jcr->JobId; /* ref NULL pointer */
553 jcr->JobId = 1000; /* another ref NULL pointer */
555 } else if (strncmp(remote_cmd, ".dump", 5) == 0) {
556 sm_dump(false, true);
557 } else if (strncmp(remote_cmd, ".exit", 5) == 0) {
558 dot_quit_cmd(ua, cmd);
568 * Dummy routine for non-development version
570 static bool admin_cmds(UAContext *ua, const char *cmd)
572 ua->error_msg(_("Unknown command: %s\n"), ua->argk[0]);
579 * Can use an argument to filter on JobType
582 static bool jobscmd(UAContext *ua, const char *cmd)
587 if ((pos = find_arg_with_value(ua, "type")) >= 0) {
588 type = ua->argv[pos][0];
591 foreach_res(job, R_JOB) {
592 if (!type || type == job->JobType) {
593 if (acl_access_ok(ua, Job_ACL, job->name())) {
594 ua->send_msg("%s\n", job->name());
602 static bool filesetscmd(UAContext *ua, const char *cmd)
606 foreach_res(fs, R_FILESET) {
607 if (acl_access_ok(ua, FileSet_ACL, fs->name())) {
608 ua->send_msg("%s\n", fs->name());
615 static bool clientscmd(UAContext *ua, const char *cmd)
619 foreach_res(client, R_CLIENT) {
620 if (acl_access_ok(ua, Client_ACL, client->name())) {
621 ua->send_msg("%s\n", client->name());
628 static bool msgscmd(UAContext *ua, const char *cmd)
632 foreach_res(msgs, R_MSGS) {
633 ua->send_msg("%s\n", msgs->name());
639 static bool poolscmd(UAContext *ua, const char *cmd)
643 foreach_res(pool, R_POOL) {
644 if (acl_access_ok(ua, Pool_ACL, pool->name())) {
645 ua->send_msg("%s\n", pool->name());
652 static bool storagecmd(UAContext *ua, const char *cmd)
656 foreach_res(store, R_STORAGE) {
657 if (acl_access_ok(ua, Storage_ACL, store->name())) {
658 ua->send_msg("%s\n", store->name());
665 static bool aopcmd(UAContext *ua, const char *cmd)
667 ua->send_msg("None\n");
668 ua->send_msg("Truncate\n");
672 static bool typescmd(UAContext *ua, const char *cmd)
674 ua->send_msg("Backup\n");
675 ua->send_msg("Restore\n");
676 ua->send_msg("Admin\n");
677 ua->send_msg("Verify\n");
678 ua->send_msg("Migrate\n");
679 ua->send_msg("Copy\n");
684 * If this command is called, it tells the director that we
685 * are a program that wants a sort of API, and hence,
686 * we will probably suppress certain output, include more
687 * error codes, and most of all send back a good number
688 * of new signals that indicate whether or not the command
691 static bool api_cmd(UAContext *ua, const char *cmd)
694 ua->api = atoi(ua->argk[1]);
701 static int client_backups_handler(void *ctx, int num_field, char **row)
703 UAContext *ua = (UAContext *)ctx;
704 ua->send_msg("| %s | %s | %s | %s | %s | %s | %s | %s |\n",
705 row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8]);
710 * Return the backups for this client
712 * .backups client=xxx fileset=yyy
715 static bool backupscmd(UAContext *ua, const char *cmd)
717 if (!open_client_db(ua)) {
720 if (ua->argc != 3 || strcmp(ua->argk[1], "client") != 0 ||
721 strcmp(ua->argk[2], "fileset") != 0) {
724 if (!acl_access_ok(ua, Client_ACL, ua->argv[1]) ||
725 !acl_access_ok(ua, FileSet_ACL, ua->argv[2])) {
726 ua->error_msg(_("Access to specified Client or FileSet not allowed.\n"));
729 Mmsg(ua->cmd, client_backups, ua->argv[1], ua->argv[2]);
730 if (!db_sql_query(ua->db, ua->cmd, client_backups_handler, (void *)ua)) {
731 ua->error_msg(_("Query failed: %s. ERR=%s\n"), ua->cmd, db_strerror(ua->db));
737 static int sql_handler(void *ctx, int num_field, char **row)
739 UAContext *ua = (UAContext *)ctx;
740 POOL_MEM rows(PM_MESSAGE);
742 /* Check for nonsense */
743 if (num_field == 0 || row == NULL || row[0] == NULL) {
744 return 0; /* nothing returned */
746 for (int i=0; num_field--; i++) {
748 pm_strcpy(rows, NPRT(row[0]));
750 pm_strcat(rows, NPRT(row[i]));
752 pm_strcat(rows, "\t");
754 if (!rows.c_str() || !*rows.c_str()) {
757 ua->send_msg("%s", rows.c_str());
762 static bool sql_cmd(UAContext *ua, const char *cmd)
765 if (!open_client_db(ua)) {
768 index = find_arg_with_value(ua, "query");
770 ua->error_msg(_("query keyword not found.\n"));
773 if (!db_sql_query(ua->db, ua->argv[index], sql_handler, (void *)ua)) {
774 Dmsg1(100, "Query failed: ERR=%s\n", db_strerror(ua->db));
775 ua->error_msg(_("Query failed: %s. ERR=%s\n"), ua->cmd, db_strerror(ua->db));
781 static int one_handler(void *ctx, int num_field, char **row)
783 UAContext *ua = (UAContext *)ctx;
784 ua->send_msg("%s\n", row[0]);
788 static bool mediatypescmd(UAContext *ua, const char *cmd)
790 if (!open_client_db(ua)) {
793 if (!db_sql_query(ua->db,
794 "SELECT DISTINCT MediaType FROM MediaType ORDER BY MediaType",
795 one_handler, (void *)ua))
797 ua->error_msg(_("List MediaType failed: ERR=%s\n"), db_strerror(ua->db));
802 static bool mediacmd(UAContext *ua, const char *cmd)
804 if (!open_client_db(ua)) {
807 if (!db_sql_query(ua->db,
808 "SELECT DISTINCT Media.VolumeName FROM Media ORDER BY VolumeName",
809 one_handler, (void *)ua))
811 ua->error_msg(_("List Media failed: ERR=%s\n"), db_strerror(ua->db));
816 static bool locationscmd(UAContext *ua, const char *cmd)
818 if (!open_client_db(ua)) {
821 if (!db_sql_query(ua->db,
822 "SELECT DISTINCT Location FROM Location ORDER BY Location",
823 one_handler, (void *)ua))
825 ua->error_msg(_("List Location failed: ERR=%s\n"), db_strerror(ua->db));
830 static bool levelscmd(UAContext *ua, const char *cmd)
832 ua->send_msg("Incremental\n");
833 ua->send_msg("Full\n");
834 ua->send_msg("Differential\n");
835 ua->send_msg("VirtualFull\n");
836 ua->send_msg("Catalog\n");
837 ua->send_msg("InitCatalog\n");
838 ua->send_msg("VolumeToCatalog\n");
839 ua->send_msg("Base\n");
843 static bool volstatuscmd(UAContext *ua, const char *cmd)
845 ua->send_msg("Append\n");
846 ua->send_msg("Full\n");
847 ua->send_msg("Used\n");
848 ua->send_msg("Recycle\n");
849 ua->send_msg("Purged\n");
850 ua->send_msg("Cleaning\n");
851 ua->send_msg("Error\n");
856 * Return default values for a job
858 static bool defaultscmd(UAContext *ua, const char *cmd)
866 if (ua->argc != 2 || !ua->argv[1]) {
871 if (strcmp(ua->argk[1], "job") == 0) {
872 if (!acl_access_ok(ua, Job_ACL, ua->argv[1])) {
875 job = (JOB *)GetResWithName(R_JOB, ua->argv[1]);
878 ua->send_msg("job=%s", job->name());
879 ua->send_msg("pool=%s", job->pool->name());
880 ua->send_msg("messages=%s", job->messages->name());
881 ua->send_msg("client=%s", job->client->name());
882 get_job_storage(&store, job, NULL);
883 ua->send_msg("storage=%s", store.store->name());
884 ua->send_msg("where=%s", job->RestoreWhere?job->RestoreWhere:"");
885 ua->send_msg("level=%s", level_to_str(job->JobLevel));
886 ua->send_msg("type=%s", job_type_to_str(job->JobType));
887 ua->send_msg("fileset=%s", job->fileset->name());
888 ua->send_msg("enabled=%d", job->enabled);
889 ua->send_msg("catalog=%s", job->client->catalog->name());
892 /* Client defaults */
893 else if (strcmp(ua->argk[1], "client") == 0) {
894 if (!acl_access_ok(ua, Client_ACL, ua->argv[1])) {
897 client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[1]);
899 ua->send_msg("client=%s", client->name());
900 ua->send_msg("address=%s", client->address);
901 ua->send_msg("fdport=%d", client->FDport);
902 ua->send_msg("file_retention=%s", edit_uint64(client->FileRetention, ed1));
903 ua->send_msg("job_retention=%s", edit_uint64(client->JobRetention, ed1));
904 ua->send_msg("autoprune=%d", client->AutoPrune);
905 ua->send_msg("catalog=%s", client->catalog->name());
908 /* Storage defaults */
909 else if (strcmp(ua->argk[1], "storage") == 0) {
910 if (!acl_access_ok(ua, Storage_ACL, ua->argv[1])) {
913 storage = (STORE *)GetResWithName(R_STORAGE, ua->argv[1]);
916 ua->send_msg("storage=%s", storage->name());
917 ua->send_msg("address=%s", storage->address);
918 ua->send_msg("enabled=%d", storage->enabled);
919 ua->send_msg("media_type=%s", storage->media_type);
920 ua->send_msg("sdport=%d", storage->SDport);
921 device = (DEVICE *)storage->device->first();
922 ua->send_msg("device=%s", device->name());
923 if (storage->device->size() > 1) {
924 while ((device = (DEVICE *)storage->device->next())) {
925 ua->send_msg(",%s", device->name());
931 else if (strcmp(ua->argk[1], "pool") == 0) {
932 if (!acl_access_ok(ua, Pool_ACL, ua->argv[1])) {
935 pool = (POOL *)GetResWithName(R_POOL, ua->argv[1]);
937 ua->send_msg("pool=%s", pool->name());
938 ua->send_msg("pool_type=%s", pool->pool_type);
939 ua->send_msg("label_format=%s", pool->label_format?pool->label_format:"");
940 ua->send_msg("use_volume_once=%d", pool->use_volume_once);
941 ua->send_msg("purge_oldest_volume=%d", pool->purge_oldest_volume);
942 ua->send_msg("recycle_oldest_volume=%d", pool->recycle_oldest_volume);
943 ua->send_msg("recycle_current_volume=%d", pool->recycle_current_volume);
944 ua->send_msg("max_volumes=%d", pool->max_volumes);
945 ua->send_msg("vol_retention=%s", edit_uint64(pool->VolRetention, ed1));
946 ua->send_msg("vol_use_duration=%s", edit_uint64(pool->VolUseDuration, ed1));
947 ua->send_msg("max_vol_jobs=%d", pool->MaxVolJobs);
948 ua->send_msg("max_vol_files=%d", pool->MaxVolFiles);
949 ua->send_msg("max_vol_bytes=%s", edit_uint64(pool->MaxVolBytes, ed1));
950 ua->send_msg("auto_prune=%d", pool->AutoPrune);
951 ua->send_msg("recycle=%d", pool->Recycle);
952 ua->send_msg("file_retention=%s", edit_uint64(pool->FileRetention, ed1));
953 ua->send_msg("job_retention=%s", edit_uint64(pool->JobRetention, ed1));