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 two of the GNU 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 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);
77 static bool api_cmd(UAContext *ua, const char *cmd);
78 static bool sql_cmd(UAContext *ua, const char *cmd);
79 static bool dot_quit_cmd(UAContext *ua, const char *cmd);
80 static bool dot_help_cmd(UAContext *ua, const char *cmd);
82 struct cmdstruct { const char *key; bool (*func)(UAContext *ua, const char *cmd); const char *help;const bool use_in_rs;};
83 static struct cmdstruct commands[] = { /* help */ /* can be used in runscript */
84 { NT_(".api"), api_cmd, NULL, false},
85 { NT_(".backups"), backupscmd, NULL, false},
86 { NT_(".clients"), clientscmd, NULL, true},
87 { NT_(".defaults"), defaultscmd, NULL, false},
88 { NT_(".die"), admin_cmds, NULL, false},
89 { NT_(".dump"), admin_cmds, NULL, false},
90 { NT_(".exit"), admin_cmds, NULL, false},
91 { NT_(".filesets"), filesetscmd, NULL, false},
92 { NT_(".help"), dot_help_cmd, NULL, false},
93 { NT_(".jobs"), jobscmd, NULL, true},
94 { NT_(".levels"), levelscmd, NULL, false},
95 { NT_(".messages"), getmsgscmd, NULL, false},
96 { NT_(".msgs"), msgscmd, NULL, false},
97 { NT_(".pools"), poolscmd, NULL, true},
98 { NT_(".quit"), dot_quit_cmd, NULL, false},
99 { NT_(".sql"), sql_cmd, NULL, false},
100 { NT_(".status"), dot_status_cmd, NULL, false},
101 { NT_(".storage"), storagecmd, NULL, true},
102 { NT_(".volstatus"), volstatuscmd, NULL, true},
103 { NT_(".media"), mediacmd, NULL, true},
104 { NT_(".mediatypes"), mediatypescmd, NULL, true},
105 { NT_(".locations"), locationscmd, NULL, true},
106 { NT_(".actiononpurge"),aopcmd, NULL, true},
107 { NT_(".bvfs_lsdirs"), dot_bvfs_lsdirs, NULL, true},
108 { NT_(".bvfs_lsfiles"),dot_bvfs_lsfiles,NULL, true},
109 { NT_(".bvfs_update"), dot_bvfs_update, NULL, true},
110 { NT_(".types"), typescmd, NULL, false}
112 #define comsize ((int)(sizeof(commands)/sizeof(struct cmdstruct)))
115 * Execute a command from the UA
117 bool do_a_dot_command(UAContext *ua)
123 BSOCK *user = ua->UA_sock;
125 Dmsg1(1400, "Dot command: %s\n", user->msg);
130 len = strlen(ua->argk[0]);
132 if (ua->api) user->signal(BNET_CMD_BEGIN);
133 if (ua->api) user->signal(BNET_CMD_OK);
134 return true; /* no op */
136 for (i=0; i<comsize; i++) { /* search for command */
137 if (strncasecmp(ua->argk[0], _(commands[i].key), len) == 0) {
138 /* Check if this command is authorized in RunScript */
139 if (ua->runscript && !commands[i].use_in_rs) {
140 ua->error_msg(_("Can't use %s command in a runscript"), ua->argk[0]);
144 /* Check if command permitted, but "quit" is always OK */
145 if (strcmp(ua->argk[0], NT_(".quit")) != 0 &&
146 !acl_access_ok(ua, Command_ACL, ua->argk[0], len)) {
149 Dmsg1(100, "Cmd: %s\n", ua->cmd);
151 if (ua->api) user->signal(BNET_CMD_BEGIN);
152 ok = (*commands[i].func)(ua, ua->cmd); /* go execute command */
153 if (ua->api) user->signal(ok?BNET_CMD_OK:BNET_CMD_FAILED);
160 pm_strcat(user->msg, _(": is an invalid command.\n"));
161 ua->error_msg("%s", user->msg);
167 static bool dot_bvfs_update(UAContext *ua, const char *cmd)
169 if (!open_new_client_db(ua)) {
173 int pos = find_arg_with_value(ua, "jobid");
174 if (pos != -1 && is_a_number_list(ua->argv[pos])) {
176 pm_strcpy(jobids, ua->argv[pos]);
177 bvfs_update_path_hierarchy_cache(ua->jcr, ua->db, jobids.c_str());
179 /* update cache for all jobids */
180 bvfs_update_cache(ua->jcr, ua->db);
187 static int bvfs_result_handler(void *ctx, int fields, char **row)
189 UAContext *ua = (UAContext *)ctx;
192 char *fileid=row[BVFS_FileId];
193 char *lstat=row[BVFS_LStat];
194 char *jobid=row[BVFS_JobId];
196 char empty[] = "A A A A A A A A A A A A A A";
199 /* We need to deal with non existant path */
200 if (!fileid || !is_a_number(fileid)) {
206 memset(&statp, 0, sizeof(struct stat));
207 decode_stat(lstat, &statp, &LinkFI);
209 Dmsg1(100, "type=%s\n", row[0]);
210 if (bvfs_is_dir(row)) {
211 char *path = bvfs_basename_dir(row[BVFS_Name]);
212 ua->send_msg("%s\t0\t%s\t%s\t%s\t%s\n", row[BVFS_PathId], fileid,
215 } else if (bvfs_is_file(row)) {
216 ua->send_msg("%s\t%s\t%s\t%s\t%s\t%s\n", row[BVFS_PathId],
217 row[BVFS_FilenameId], fileid, jobid,
218 lstat, row[BVFS_Name]);
224 static bool bvfs_parse_arg(UAContext *ua,
225 DBId_t *pathid, char **path, char **jobid,
226 int *limit, int *offset)
234 for (int i=1; i<ua->argc; i++) {
235 if (strcasecmp(ua->argk[i], NT_("pathid")) == 0) {
236 if (is_a_number(ua->argv[i])) {
237 *pathid = str_to_int64(ua->argv[i]);
240 if (strcasecmp(ua->argk[i], NT_("path")) == 0) {
244 if (strcasecmp(ua->argk[i], NT_("jobid")) == 0) {
245 if (is_a_number_list(ua->argv[i])) {
246 *jobid = ua->argv[i];
250 if (strcasecmp(ua->argk[i], NT_("limit")) == 0) {
251 if (is_a_number(ua->argv[i])) {
252 *limit = str_to_int64(ua->argv[i]);
256 if (strcasecmp(ua->argk[i], NT_("offset")) == 0) {
257 if (is_a_number(ua->argv[i])) {
258 *offset = str_to_int64(ua->argv[i]);
263 if (!((*pathid || *path) && *jobid)) {
267 if (!open_client_db(ua)) {
275 * .bvfs_lsfiles jobid=1,2,3,4 pathid=10
276 * .bvfs_lsfiles jobid=1,2,3,4 path=/
278 static bool dot_bvfs_lsfiles(UAContext *ua, const char *cmd)
281 int limit=2000, offset=0;
282 char *path=NULL, *jobid=NULL;
284 if (!bvfs_parse_arg(ua, &pathid, &path, &jobid,
287 ua->error_msg("Can't find jobid, pathid or path argument\n");
288 return true; /* not enough param */
291 Bvfs fs(ua->jcr, ua->db);
292 fs.set_jobids(jobid);
293 fs.set_handler(bvfs_result_handler, ua);
302 fs.set_offset(offset);
310 * .bvfs_lsdirs jobid=1,2,3,4 pathid=10
311 * .bvfs_lsdirs jobid=1,2,3,4 path=/
312 * .bvfs_lsdirs jobid=1,2,3,4 path=
314 static bool dot_bvfs_lsdirs(UAContext *ua, const char *cmd)
317 int limit=2000, offset=0;
318 char *path=NULL, *jobid=NULL;
320 if (!bvfs_parse_arg(ua, &pathid, &path, &jobid,
323 ua->error_msg("Can't find jobid, pathid or path argument\n");
324 return true; /* not enough param */
327 Bvfs fs(ua->jcr, ua->db);
328 fs.set_jobids(jobid);
330 fs.set_handler(bvfs_result_handler, ua);
338 fs.set_offset(offset);
340 fs.ls_special_dirs();
346 static bool dot_quit_cmd(UAContext *ua, const char *cmd)
352 static bool dot_help_cmd(UAContext *ua, const char *cmd)
358 static bool getmsgscmd(UAContext *ua, const char *cmd)
360 if (console_msg_pending) {
361 do_messages(ua, cmd);
367 static void do_storage_cmd(UAContext *ua, STORE *store, const char *cmd)
373 lstore.store = store;
374 pm_strcpy(lstore.store_source, _("unknown source"));
375 set_wstorage(jcr, &lstore);
376 /* Try connecting for up to 15 seconds */
377 ua->send_msg(_("Connecting to Storage daemon %s at %s:%d\n"),
378 store->name(), store->address, store->SDport);
379 if (!connect_to_storage_daemon(jcr, 1, 15, 0)) {
380 ua->error_msg(_("Failed to connect to Storage daemon.\n"));
383 Dmsg0(120, _("Connected to storage daemon\n"));
384 sd = jcr->store_bsock;
385 sd->fsend("%s", cmd);
386 if (sd->recv() >= 0) {
387 ua->send_msg("%s", sd->msg);
389 sd->signal(BNET_TERMINATE);
391 jcr->store_bsock = NULL;
395 static void do_client_cmd(UAContext *ua, CLIENT *client, const char *cmd)
399 /* Connect to File daemon */
401 ua->jcr->client = client;
402 /* Try to connect for 15 seconds */
403 ua->send_msg(_("Connecting to Client %s at %s:%d\n"),
404 client->name(), client->address, client->FDport);
405 if (!connect_to_file_daemon(ua->jcr, 1, 15, 0)) {
406 ua->error_msg(_("Failed to connect to Client.\n"));
409 Dmsg0(120, "Connected to file daemon\n");
410 fd = ua->jcr->file_bsock;
411 fd->fsend("%s", cmd);
412 if (fd->recv() >= 0) {
413 ua->send_msg("%s", fd->msg);
415 fd->signal(BNET_TERMINATE);
417 ua->jcr->file_bsock = NULL;
424 * .exit (no arg => .quit)
426 static bool admin_cmds(UAContext *ua, const char *cmd)
428 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
432 bool do_deadlock=false;
433 const char *remote_cmd;
437 if (strncmp(ua->argk[0], ".die", 4) == 0) {
438 if (find_arg(ua, "deadlock") > 0) {
440 remote_cmd = ".die deadlock";
444 } else if (strncmp(ua->argk[0], ".dump", 5) == 0) {
445 remote_cmd = "sm_dump";
446 } else if (strncmp(ua->argk[0], ".exit", 5) == 0) {
449 ua->error_msg(_("Unknown command: %s\n"), ua->argk[0]);
453 for (i=1; i<ua->argc; i++) {
454 if (strcasecmp(ua->argk[i], "dir") == 0 ||
455 strcasecmp(ua->argk[i], "director") == 0) {
458 if (strcasecmp(ua->argk[i], "client") == 0 ||
459 strcasecmp(ua->argk[i], "fd") == 0) {
462 client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[i]);
465 client = select_client_resource(ua);
469 if (strcasecmp(ua->argk[i], NT_("store")) == 0 ||
470 strcasecmp(ua->argk[i], NT_("storage")) == 0 ||
471 strcasecmp(ua->argk[i], NT_("sd")) == 0) {
474 store = (STORE *)GetResWithName(R_STORAGE, ua->argv[i]);
477 store = get_storage_resource(ua, false/*no default*/);
482 if (!dir && !store && !client) {
484 * We didn't find an appropriate keyword above, so
487 start_prompt(ua, _("Available daemons are: \n"));
488 add_prompt(ua, _("Director"));
489 add_prompt(ua, _("Storage"));
490 add_prompt(ua, _("Client"));
491 switch(do_prompt(ua, "", _("Select daemon type to make die"), NULL, 0)) {
492 case 0: /* Director */
496 store = get_storage_resource(ua, false/*no default*/);
499 client = select_client_resource(ua);
507 do_storage_cmd(ua, store, remote_cmd);
511 do_client_cmd(ua, client, remote_cmd);
515 if (strncmp(remote_cmd, ".die", 4) == 0) {
517 ua->send_msg(_("The Director will generate a deadlock.\n"));
521 ua->send_msg(_("The Director will segment fault.\n"));
522 a = jcr->JobId; /* ref NULL pointer */
523 jcr->JobId = 1000; /* another ref NULL pointer */
525 } else if (strncmp(remote_cmd, ".dump", 5) == 0) {
526 sm_dump(false, true);
527 } else if (strncmp(remote_cmd, ".exit", 5) == 0) {
528 dot_quit_cmd(ua, cmd);
538 * Dummy routine for non-development version
540 static bool die_or_dump_cmd(UAContext *ua, const char *cmd)
548 * Can use an argument to filter on JobType
551 static bool jobscmd(UAContext *ua, const char *cmd)
556 if ((pos = find_arg_with_value(ua, "type")) >= 0) {
557 type = ua->argv[pos][0];
560 foreach_res(job, R_JOB) {
561 if (!type || type == job->JobType) {
562 if (acl_access_ok(ua, Job_ACL, job->name())) {
563 ua->send_msg("%s\n", job->name());
571 static bool filesetscmd(UAContext *ua, const char *cmd)
575 foreach_res(fs, R_FILESET) {
576 if (acl_access_ok(ua, FileSet_ACL, fs->name())) {
577 ua->send_msg("%s\n", fs->name());
584 static bool clientscmd(UAContext *ua, const char *cmd)
588 foreach_res(client, R_CLIENT) {
589 if (acl_access_ok(ua, Client_ACL, client->name())) {
590 ua->send_msg("%s\n", client->name());
597 static bool msgscmd(UAContext *ua, const char *cmd)
601 foreach_res(msgs, R_MSGS) {
602 ua->send_msg("%s\n", msgs->name());
608 static bool poolscmd(UAContext *ua, const char *cmd)
612 foreach_res(pool, R_POOL) {
613 if (acl_access_ok(ua, Pool_ACL, pool->name())) {
614 ua->send_msg("%s\n", pool->name());
621 static bool storagecmd(UAContext *ua, const char *cmd)
625 foreach_res(store, R_STORAGE) {
626 if (acl_access_ok(ua, Storage_ACL, store->name())) {
627 ua->send_msg("%s\n", store->name());
634 static bool aopcmd(UAContext *ua, const char *cmd)
636 ua->send_msg("None\n");
637 ua->send_msg("Truncate\n");
641 static bool typescmd(UAContext *ua, const char *cmd)
643 ua->send_msg("Backup\n");
644 ua->send_msg("Restore\n");
645 ua->send_msg("Admin\n");
646 ua->send_msg("Verify\n");
647 ua->send_msg("Migrate\n");
648 ua->send_msg("Copy\n");
653 * If this command is called, it tells the director that we
654 * are a program that wants a sort of API, and hence,
655 * we will probably suppress certain output, include more
656 * error codes, and most of all send back a good number
657 * of new signals that indicate whether or not the command
660 static bool api_cmd(UAContext *ua, const char *cmd)
663 ua->api = atoi(ua->argk[1]);
670 static int client_backups_handler(void *ctx, int num_field, char **row)
672 UAContext *ua = (UAContext *)ctx;
673 ua->send_msg("| %s | %s | %s | %s | %s | %s | %s | %s |\n",
674 row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8]);
679 * Return the backups for this client
681 * .backups client=xxx fileset=yyy
684 static bool backupscmd(UAContext *ua, const char *cmd)
686 if (!open_client_db(ua)) {
689 if (ua->argc != 3 || strcmp(ua->argk[1], "client") != 0 ||
690 strcmp(ua->argk[2], "fileset") != 0) {
693 if (!acl_access_ok(ua, Client_ACL, ua->argv[1]) ||
694 !acl_access_ok(ua, FileSet_ACL, ua->argv[2])) {
695 ua->error_msg(_("Access to specified Client or FileSet not allowed.\n"));
698 Mmsg(ua->cmd, client_backups, ua->argv[1], ua->argv[2]);
699 if (!db_sql_query(ua->db, ua->cmd, client_backups_handler, (void *)ua)) {
700 ua->error_msg(_("Query failed: %s. ERR=%s\n"), ua->cmd, db_strerror(ua->db));
706 static int sql_handler(void *ctx, int num_field, char **row)
708 UAContext *ua = (UAContext *)ctx;
709 POOL_MEM rows(PM_MESSAGE);
711 /* Check for nonsense */
712 if (num_field == 0 || row == NULL || row[0] == NULL) {
713 return 0; /* nothing returned */
715 for (int i=0; num_field--; i++) {
717 pm_strcpy(rows, NPRT(row[0]));
719 pm_strcat(rows, NPRT(row[i]));
721 pm_strcat(rows, "\t");
723 if (!rows.c_str() || !*rows.c_str()) {
726 ua->send_msg("%s", rows.c_str());
731 static bool sql_cmd(UAContext *ua, const char *cmd)
734 if (!open_client_db(ua)) {
737 index = find_arg_with_value(ua, "query");
739 ua->error_msg(_("query keyword not found.\n"));
742 if (!db_sql_query(ua->db, ua->argv[index], sql_handler, (void *)ua)) {
743 Dmsg1(100, "Query failed: ERR=%s\n", db_strerror(ua->db));
744 ua->error_msg(_("Query failed: %s. ERR=%s\n"), ua->cmd, db_strerror(ua->db));
750 static int one_handler(void *ctx, int num_field, char **row)
752 UAContext *ua = (UAContext *)ctx;
753 ua->send_msg("%s\n", row[0]);
757 static bool mediatypescmd(UAContext *ua, const char *cmd)
759 if (!open_client_db(ua)) {
762 if (!db_sql_query(ua->db,
763 "SELECT DISTINCT MediaType FROM MediaType ORDER BY MediaType",
764 one_handler, (void *)ua))
766 ua->error_msg(_("List MediaType failed: ERR=%s\n"), db_strerror(ua->db));
771 static bool mediacmd(UAContext *ua, const char *cmd)
773 if (!open_client_db(ua)) {
776 if (!db_sql_query(ua->db,
777 "SELECT DISTINCT Media.VolumeName FROM Media ORDER BY VolumeName",
778 one_handler, (void *)ua))
780 ua->error_msg(_("List Media failed: ERR=%s\n"), db_strerror(ua->db));
785 static bool locationscmd(UAContext *ua, const char *cmd)
787 if (!open_client_db(ua)) {
790 if (!db_sql_query(ua->db,
791 "SELECT DISTINCT Location FROM Location ORDER BY Location",
792 one_handler, (void *)ua))
794 ua->error_msg(_("List Location failed: ERR=%s\n"), db_strerror(ua->db));
799 static bool levelscmd(UAContext *ua, const char *cmd)
801 ua->send_msg("Incremental\n");
802 ua->send_msg("Full\n");
803 ua->send_msg("Differential\n");
804 ua->send_msg("VirtualFull\n");
805 ua->send_msg("Catalog\n");
806 ua->send_msg("InitCatalog\n");
807 ua->send_msg("VolumeToCatalog\n");
808 ua->send_msg("Base\n");
812 static bool volstatuscmd(UAContext *ua, const char *cmd)
814 ua->send_msg("Append\n");
815 ua->send_msg("Full\n");
816 ua->send_msg("Used\n");
817 ua->send_msg("Recycle\n");
818 ua->send_msg("Purged\n");
819 ua->send_msg("Cleaning\n");
820 ua->send_msg("Error\n");
825 * Return default values for a job
827 static bool defaultscmd(UAContext *ua, const char *cmd)
835 if (ua->argc != 2 || !ua->argv[1]) {
840 if (strcmp(ua->argk[1], "job") == 0) {
841 if (!acl_access_ok(ua, Job_ACL, ua->argv[1])) {
844 job = (JOB *)GetResWithName(R_JOB, ua->argv[1]);
847 ua->send_msg("job=%s", job->name());
848 ua->send_msg("pool=%s", job->pool->name());
849 ua->send_msg("messages=%s", job->messages->name());
850 ua->send_msg("client=%s", job->client->name());
851 get_job_storage(&store, job, NULL);
852 ua->send_msg("storage=%s", store.store->name());
853 ua->send_msg("where=%s", job->RestoreWhere?job->RestoreWhere:"");
854 ua->send_msg("level=%s", level_to_str(job->JobLevel));
855 ua->send_msg("type=%s", job_type_to_str(job->JobType));
856 ua->send_msg("fileset=%s", job->fileset->name());
857 ua->send_msg("enabled=%d", job->enabled);
858 ua->send_msg("catalog=%s", job->client->catalog->name());
861 /* Client defaults */
862 else if (strcmp(ua->argk[1], "client") == 0) {
863 if (!acl_access_ok(ua, Client_ACL, ua->argv[1])) {
866 client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[1]);
868 ua->send_msg("client=%s", client->name());
869 ua->send_msg("address=%s", client->address);
870 ua->send_msg("fdport=%d", client->FDport);
871 ua->send_msg("file_retention=%s", edit_uint64(client->FileRetention, ed1));
872 ua->send_msg("job_retention=%s", edit_uint64(client->JobRetention, ed1));
873 ua->send_msg("autoprune=%d", client->AutoPrune);
874 ua->send_msg("catalog=%s", client->catalog->name());
877 /* Storage defaults */
878 else if (strcmp(ua->argk[1], "storage") == 0) {
879 if (!acl_access_ok(ua, Storage_ACL, ua->argv[1])) {
882 storage = (STORE *)GetResWithName(R_STORAGE, ua->argv[1]);
885 ua->send_msg("storage=%s", storage->name());
886 ua->send_msg("address=%s", storage->address);
887 ua->send_msg("enabled=%d", storage->enabled);
888 ua->send_msg("media_type=%s", storage->media_type);
889 ua->send_msg("sdport=%d", storage->SDport);
890 device = (DEVICE *)storage->device->first();
891 ua->send_msg("device=%s", device->name());
892 if (storage->device->size() > 1) {
893 while ((device = (DEVICE *)storage->device->next())) {
894 ua->send_msg(",%s", device->name());
900 else if (strcmp(ua->argk[1], "pool") == 0) {
901 if (!acl_access_ok(ua, Pool_ACL, ua->argv[1])) {
904 pool = (POOL *)GetResWithName(R_POOL, ua->argv[1]);
906 ua->send_msg("pool=%s", pool->name());
907 ua->send_msg("pool_type=%s", pool->pool_type);
908 ua->send_msg("label_format=%s", pool->label_format?pool->label_format:"");
909 ua->send_msg("use_volume_once=%d", pool->use_volume_once);
910 ua->send_msg("purge_oldest_volume=%d", pool->purge_oldest_volume);
911 ua->send_msg("recycle_oldest_volume=%d", pool->recycle_oldest_volume);
912 ua->send_msg("recycle_current_volume=%d", pool->recycle_current_volume);
913 ua->send_msg("max_volumes=%d", pool->max_volumes);
914 ua->send_msg("vol_retention=%s", edit_uint64(pool->VolRetention, ed1));
915 ua->send_msg("vol_use_duration=%s", edit_uint64(pool->VolUseDuration, ed1));
916 ua->send_msg("max_vol_jobs=%d", pool->MaxVolJobs);
917 ua->send_msg("max_vol_files=%d", pool->MaxVolFiles);
918 ua->send_msg("max_vol_bytes=%s", edit_uint64(pool->MaxVolBytes, ed1));
919 ua->send_msg("auto_prune=%d", pool->AutoPrune);
920 ua->send_msg("recycle=%d", pool->Recycle);
921 ua->send_msg("file_retention=%s", edit_uint64(pool->FileRetention, ed1));
922 ua->send_msg("job_retention=%s", edit_uint64(pool->JobRetention, ed1));