2 Bacula® - The Network Backup Solution
4 Copyright (C) 2002-2009 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 diecmd(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"), diecmd, NULL, false},
89 { NT_(".exit"), dot_quit_cmd, NULL, false},
90 { NT_(".filesets"), filesetscmd, NULL, false},
91 { NT_(".help"), dot_help_cmd, NULL, false},
92 { NT_(".jobs"), jobscmd, NULL, true},
93 { NT_(".levels"), levelscmd, NULL, false},
94 { NT_(".messages"), getmsgscmd, NULL, false},
95 { NT_(".msgs"), msgscmd, NULL, false},
96 { NT_(".pools"), poolscmd, NULL, true},
97 { NT_(".quit"), dot_quit_cmd, NULL, false},
98 { NT_(".sql"), sql_cmd, NULL, false},
99 { NT_(".status"), dot_status_cmd, NULL, false},
100 { NT_(".storage"), storagecmd, NULL, true},
101 { NT_(".volstatus"), volstatuscmd, NULL, true},
102 { NT_(".media"), mediacmd, NULL, true},
103 { NT_(".mediatypes"), mediatypescmd, NULL, true},
104 { NT_(".locations"), locationscmd, NULL, true},
105 { NT_(".actiononpurge"),aopcmd, NULL, true},
106 { NT_(".bvfs_lsdirs"), dot_bvfs_lsdirs, NULL, true},
107 { NT_(".bvfs_lsfiles"),dot_bvfs_lsfiles,NULL, true},
108 { NT_(".bvfs_update"), dot_bvfs_update, NULL, true},
109 { NT_(".types"), typescmd, NULL, false}
111 #define comsize ((int)(sizeof(commands)/sizeof(struct cmdstruct)))
114 * Execute a command from the UA
116 bool do_a_dot_command(UAContext *ua)
122 BSOCK *user = ua->UA_sock;
124 Dmsg1(1400, "Dot command: %s\n", user->msg);
129 len = strlen(ua->argk[0]);
131 if (ua->api) user->signal(BNET_CMD_BEGIN);
132 if (ua->api) user->signal(BNET_CMD_OK);
133 return true; /* no op */
135 for (i=0; i<comsize; i++) { /* search for command */
136 if (strncasecmp(ua->argk[0], _(commands[i].key), len) == 0) {
137 /* Check if this command is authorized in RunScript */
138 if (ua->runscript && !commands[i].use_in_rs) {
139 ua->error_msg(_("Can't use %s command in a runscript"), ua->argk[0]);
143 /* Check if command permitted, but "quit" is always OK */
144 if (strcmp(ua->argk[0], NT_(".quit")) != 0 &&
145 !acl_access_ok(ua, Command_ACL, ua->argk[0], len)) {
148 Dmsg1(100, "Cmd: %s\n", ua->cmd);
150 if (ua->api) user->signal(BNET_CMD_BEGIN);
151 ok = (*commands[i].func)(ua, ua->cmd); /* go execute command */
152 if (ua->api) user->signal(ok?BNET_CMD_OK:BNET_CMD_FAILED);
159 pm_strcat(user->msg, _(": is an invalid command.\n"));
160 ua->error_msg("%s", user->msg);
166 static bool dot_bvfs_update(UAContext *ua, const char *cmd)
169 if (!open_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);
185 static int bvfs_result_handler(void *ctx, int fields, char **row)
187 UAContext *ua = (UAContext *)ctx;
192 char empty[] = "A A A A A A A A A A A A A A";
194 lstat = (row[BVFS_LStat] && row[BVFS_LStat][0])?row[BVFS_LStat]:empty;
195 fileid = (row[BVFS_FileId] && row[BVFS_FileId][0])?row[BVFS_FileId]:"0";
197 memset(&statp, 0, sizeof(struct stat));
198 decode_stat(lstat, &statp, &LinkFI);
200 Dmsg1(100, "type=%s\n", row[0]);
201 if (bvfs_is_dir(row)) {
202 char *path = bvfs_basename_dir(row[BVFS_Name]);
203 ua->send_msg("%s\t0\t%s\t%s\t%s\t%s\n", row[BVFS_PathId], fileid,
204 row[BVFS_JobId], row[BVFS_LStat], path);
206 } else if (bvfs_is_file(row)) {
207 ua->send_msg("%s\t%s\t%s\t%s\t%s\t%s\n", row[BVFS_PathId],
208 row[BVFS_FilenameId], fileid, row[BVFS_JobId],
209 row[BVFS_LStat], row[BVFS_Name]);
215 static bool bvfs_parse_arg(UAContext *ua,
216 DBId_t *pathid, char **path, char **jobid,
217 int *limit, int *offset)
225 for (int i=1; i<ua->argc; i++) {
226 if (strcasecmp(ua->argk[i], NT_("pathid")) == 0) {
227 if (is_a_number(ua->argv[i])) {
228 *pathid = str_to_int64(ua->argv[i]);
231 if (strcasecmp(ua->argk[i], NT_("path")) == 0) {
235 if (strcasecmp(ua->argk[i], NT_("jobid")) == 0) {
236 if (is_a_number_list(ua->argv[i])) {
237 *jobid = ua->argv[i];
241 if (strcasecmp(ua->argk[i], NT_("limit")) == 0) {
242 if (is_a_number(ua->argv[i])) {
243 *limit = str_to_int64(ua->argv[i]);
247 if (strcasecmp(ua->argk[i], NT_("offset")) == 0) {
248 if (is_a_number(ua->argv[i])) {
249 *offset = str_to_int64(ua->argv[i]);
254 if (!((*pathid || *path) && *jobid)) {
258 if (!open_client_db(ua)) {
266 * .bvfs_lsfiles jobid=1,2,3,4 pathid=10
267 * .bvfs_lsfiles jobid=1,2,3,4 path=/
269 static bool dot_bvfs_lsfiles(UAContext *ua, const char *cmd)
272 int limit=2000, offset=0;
273 char *path=NULL, *jobid=NULL;
275 if (!bvfs_parse_arg(ua, &pathid, &path, &jobid,
278 ua->error_msg("Can't find jobid, pathid or path argument\n");
279 return true; /* not enough param */
282 Bvfs fs(ua->jcr, ua->db);
283 fs.set_jobids(jobid);
284 fs.set_handler(bvfs_result_handler, ua);
293 fs.set_offset(offset);
301 * .bvfs_lsdirs jobid=1,2,3,4 pathid=10
302 * .bvfs_lsdirs jobid=1,2,3,4 path=/
303 * .bvfs_lsdirs jobid=1,2,3,4 path=
305 static bool dot_bvfs_lsdirs(UAContext *ua, const char *cmd)
308 int limit=2000, offset=0;
309 char *path=NULL, *jobid=NULL;
311 if (!bvfs_parse_arg(ua, &pathid, &path, &jobid,
314 ua->error_msg("Can't find jobid, pathid or path argument\n");
315 return true; /* not enough param */
318 Bvfs fs(ua->jcr, ua->db);
319 fs.set_jobids(jobid);
321 fs.set_handler(bvfs_result_handler, ua);
329 fs.set_offset(offset);
331 fs.ls_special_dirs();
337 static bool dot_quit_cmd(UAContext *ua, const char *cmd)
343 static bool dot_help_cmd(UAContext *ua, const char *cmd)
349 static bool getmsgscmd(UAContext *ua, const char *cmd)
351 if (console_msg_pending) {
352 do_messages(ua, cmd);
358 static void do_storage_die(UAContext *ua, STORE *store, const char *cmd)
364 lstore.store = store;
365 pm_strcpy(lstore.store_source, _("unknown source"));
366 set_wstorage(jcr, &lstore);
367 /* Try connecting for up to 15 seconds */
368 ua->send_msg(_("Connecting to Storage daemon %s at %s:%d\n"),
369 store->name(), store->address, store->SDport);
370 if (!connect_to_storage_daemon(jcr, 1, 15, 0)) {
371 ua->error_msg(_("Failed to connect to Storage daemon.\n"));
374 Dmsg0(120, _("Connected to storage daemon\n"));
375 sd = jcr->store_bsock;
376 sd->fsend("%s", cmd);
377 if (sd->recv() >= 0) {
378 ua->send_msg("%s", sd->msg);
380 sd->signal(BNET_TERMINATE);
382 jcr->store_bsock = NULL;
386 static void do_client_die(UAContext *ua, CLIENT *client, const char *cmd)
390 /* Connect to File daemon */
392 ua->jcr->client = client;
393 /* Try to connect for 15 seconds */
394 ua->send_msg(_("Connecting to Client %s at %s:%d\n"),
395 client->name(), client->address, client->FDport);
396 if (!connect_to_file_daemon(ua->jcr, 1, 15, 0)) {
397 ua->error_msg(_("Failed to connect to Client.\n"));
400 Dmsg0(120, "Connected to file daemon\n");
401 fd = ua->jcr->file_bsock;
402 fd->fsend("%s", cmd);
403 if (fd->recv() >= 0) {
404 ua->send_msg("%s", fd->msg);
406 fd->signal(BNET_TERMINATE);
408 ua->jcr->file_bsock = NULL;
413 * Create segmentation fault
415 static bool diecmd(UAContext *ua, const char *cmd)
417 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
421 bool do_deadlock=false;
422 const char *remote_cmd=".die";
427 Dmsg1(120, "diecmd:%s:\n", cmd);
430 for (i=1; i<ua->argc; i++) {
431 if (strcasecmp(ua->argk[i], "deadlock") == 0) {
433 remote_cmd = ".die deadlock";
435 if (strcasecmp(ua->argk[i], "dir") == 0 ||
436 strcasecmp(ua->argk[i], "director") == 0) {
439 if (strcasecmp(ua->argk[i], "client") == 0 ||
440 strcasecmp(ua->argk[i], "fd") == 0) {
443 client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[i]);
446 client = select_client_resource(ua);
450 if (strcasecmp(ua->argk[i], NT_("store")) == 0 ||
451 strcasecmp(ua->argk[i], NT_("storage")) == 0 ||
452 strcasecmp(ua->argk[i], NT_("sd")) == 0) {
455 store = (STORE *)GetResWithName(R_STORAGE, ua->argv[i]);
458 store = get_storage_resource(ua, false/*no default*/);
463 if (!dir && !store && !client) {
465 * We didn't find an appropriate keyword above, so
468 start_prompt(ua, _("Available daemons are: \n"));
469 add_prompt(ua, _("Director"));
470 add_prompt(ua, _("Storage"));
471 add_prompt(ua, _("Client"));
472 switch(do_prompt(ua, "", _("Select daemon type to make die"), NULL, 0)) {
473 case 0: /* Director */
477 store = get_storage_resource(ua, false/*no default*/);
480 client = select_client_resource(ua);
488 do_storage_die(ua, store, remote_cmd);
492 do_client_die(ua, client, remote_cmd);
497 ua->send_msg(_("The Director will generate a deadlock.\n"));
501 ua->send_msg(_("The Director will segment fault.\n"));
502 a = jcr->JobId; /* ref NULL pointer */
503 jcr->JobId = 1000; /* another ref NULL pointer */
512 * Dummy routine for non-development version
514 static bool diecmd(UAContext *ua, const char *cmd)
522 * Can use an argument to filter on JobType
525 static bool jobscmd(UAContext *ua, const char *cmd)
530 if ((pos = find_arg_with_value(ua, "type")) >= 0) {
531 type = ua->argv[pos][0];
534 foreach_res(job, R_JOB) {
535 if (!type || type == job->JobType) {
536 if (acl_access_ok(ua, Job_ACL, job->name())) {
537 ua->send_msg("%s\n", job->name());
545 static bool filesetscmd(UAContext *ua, const char *cmd)
549 foreach_res(fs, R_FILESET) {
550 if (acl_access_ok(ua, FileSet_ACL, fs->name())) {
551 ua->send_msg("%s\n", fs->name());
558 static bool clientscmd(UAContext *ua, const char *cmd)
562 foreach_res(client, R_CLIENT) {
563 if (acl_access_ok(ua, Client_ACL, client->name())) {
564 ua->send_msg("%s\n", client->name());
571 static bool msgscmd(UAContext *ua, const char *cmd)
575 foreach_res(msgs, R_MSGS) {
576 ua->send_msg("%s\n", msgs->name());
582 static bool poolscmd(UAContext *ua, const char *cmd)
586 foreach_res(pool, R_POOL) {
587 if (acl_access_ok(ua, Pool_ACL, pool->name())) {
588 ua->send_msg("%s\n", pool->name());
595 static bool storagecmd(UAContext *ua, const char *cmd)
599 foreach_res(store, R_STORAGE) {
600 if (acl_access_ok(ua, Storage_ACL, store->name())) {
601 ua->send_msg("%s\n", store->name());
608 static bool aopcmd(UAContext *ua, const char *cmd)
610 ua->send_msg("None\n");
611 ua->send_msg("Truncate\n");
615 static bool typescmd(UAContext *ua, const char *cmd)
617 ua->send_msg("Backup\n");
618 ua->send_msg("Restore\n");
619 ua->send_msg("Admin\n");
620 ua->send_msg("Verify\n");
621 ua->send_msg("Migrate\n");
626 * If this command is called, it tells the director that we
627 * are a program that wants a sort of API, and hence,
628 * we will probably suppress certain output, include more
629 * error codes, and most of all send back a good number
630 * of new signals that indicate whether or not the command
633 static bool api_cmd(UAContext *ua, const char *cmd)
636 ua->api = atoi(ua->argk[1]);
643 static int client_backups_handler(void *ctx, int num_field, char **row)
645 UAContext *ua = (UAContext *)ctx;
646 ua->send_msg("| %s | %s | %s | %s | %s | %s | %s | %s |\n",
647 row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8]);
652 * Return the backups for this client
654 * .backups client=xxx fileset=yyy
657 static bool backupscmd(UAContext *ua, const char *cmd)
659 if (!open_client_db(ua)) {
662 if (ua->argc != 3 || strcmp(ua->argk[1], "client") != 0 ||
663 strcmp(ua->argk[2], "fileset") != 0) {
666 if (!acl_access_ok(ua, Client_ACL, ua->argv[1]) ||
667 !acl_access_ok(ua, FileSet_ACL, ua->argv[2])) {
668 ua->error_msg(_("Access to specified Client or FileSet not allowed.\n"));
671 Mmsg(ua->cmd, client_backups, ua->argv[1], ua->argv[2]);
672 if (!db_sql_query(ua->db, ua->cmd, client_backups_handler, (void *)ua)) {
673 ua->error_msg(_("Query failed: %s. ERR=%s\n"), ua->cmd, db_strerror(ua->db));
679 static int sql_handler(void *ctx, int num_field, char **row)
681 UAContext *ua = (UAContext *)ctx;
682 POOL_MEM rows(PM_MESSAGE);
684 /* Check for nonsense */
685 if (num_field == 0 || row == NULL || row[0] == NULL) {
686 return 0; /* nothing returned */
688 for (int i=0; num_field--; i++) {
690 pm_strcpy(rows, NPRT(row[0]));
692 pm_strcat(rows, NPRT(row[i]));
694 pm_strcat(rows, "\t");
696 if (!rows.c_str() || !*rows.c_str()) {
699 ua->send_msg("%s", rows.c_str());
704 static bool sql_cmd(UAContext *ua, const char *cmd)
707 if (!open_client_db(ua)) {
710 index = find_arg_with_value(ua, "query");
712 ua->error_msg(_("query keyword not found.\n"));
715 if (!db_sql_query(ua->db, ua->argv[index], sql_handler, (void *)ua)) {
716 Dmsg1(100, "Query failed: ERR=%s\n", db_strerror(ua->db));
717 ua->error_msg(_("Query failed: %s. ERR=%s\n"), ua->cmd, db_strerror(ua->db));
723 static int one_handler(void *ctx, int num_field, char **row)
725 UAContext *ua = (UAContext *)ctx;
726 ua->send_msg("%s\n", row[0]);
730 static bool mediatypescmd(UAContext *ua, const char *cmd)
732 if (!open_client_db(ua)) {
735 if (!db_sql_query(ua->db,
736 "SELECT DISTINCT MediaType FROM MediaType ORDER BY MediaType",
737 one_handler, (void *)ua))
739 ua->error_msg(_("List MediaType failed: ERR=%s\n"), db_strerror(ua->db));
744 static bool mediacmd(UAContext *ua, const char *cmd)
746 if (!open_client_db(ua)) {
749 if (!db_sql_query(ua->db,
750 "SELECT DISTINCT Media.VolumeName FROM Media ORDER BY VolumeName",
751 one_handler, (void *)ua))
753 ua->error_msg(_("List Media failed: ERR=%s\n"), db_strerror(ua->db));
758 static bool locationscmd(UAContext *ua, const char *cmd)
760 if (!open_client_db(ua)) {
763 if (!db_sql_query(ua->db,
764 "SELECT DISTINCT Location FROM Location ORDER BY Location",
765 one_handler, (void *)ua))
767 ua->error_msg(_("List Location failed: ERR=%s\n"), db_strerror(ua->db));
772 static bool levelscmd(UAContext *ua, const char *cmd)
774 ua->send_msg("Incremental\n");
775 ua->send_msg("Full\n");
776 ua->send_msg("Differential\n");
777 ua->send_msg("VirtualFull\n");
778 ua->send_msg("Catalog\n");
779 ua->send_msg("InitCatalog\n");
780 ua->send_msg("VolumeToCatalog\n");
784 static bool volstatuscmd(UAContext *ua, const char *cmd)
786 ua->send_msg("Append\n");
787 ua->send_msg("Full\n");
788 ua->send_msg("Used\n");
789 ua->send_msg("Recycle\n");
790 ua->send_msg("Purged\n");
791 ua->send_msg("Cleaning\n");
792 ua->send_msg("Error\n");
797 * Return default values for a job
799 static bool defaultscmd(UAContext *ua, const char *cmd)
807 if (ua->argc != 2 || !ua->argv[1]) {
812 if (strcmp(ua->argk[1], "job") == 0) {
813 if (!acl_access_ok(ua, Job_ACL, ua->argv[1])) {
816 job = (JOB *)GetResWithName(R_JOB, ua->argv[1]);
819 ua->send_msg("job=%s", job->name());
820 ua->send_msg("pool=%s", job->pool->name());
821 ua->send_msg("messages=%s", job->messages->name());
822 ua->send_msg("client=%s", job->client->name());
823 get_job_storage(&store, job, NULL);
824 ua->send_msg("storage=%s", store.store->name());
825 ua->send_msg("where=%s", job->RestoreWhere?job->RestoreWhere:"");
826 ua->send_msg("level=%s", level_to_str(job->JobLevel));
827 ua->send_msg("type=%s", job_type_to_str(job->JobType));
828 ua->send_msg("fileset=%s", job->fileset->name());
829 ua->send_msg("enabled=%d", job->enabled);
830 ua->send_msg("catalog=%s", job->client->catalog->name());
833 /* Client defaults */
834 else if (strcmp(ua->argk[1], "client") == 0) {
835 if (!acl_access_ok(ua, Client_ACL, ua->argv[1])) {
838 client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[1]);
840 ua->send_msg("client=%s", client->name());
841 ua->send_msg("address=%s", client->address);
842 ua->send_msg("fdport=%d", client->FDport);
843 ua->send_msg("file_retention=%s", edit_uint64(client->FileRetention, ed1));
844 ua->send_msg("job_retention=%s", edit_uint64(client->JobRetention, ed1));
845 ua->send_msg("autoprune=%d", client->AutoPrune);
846 ua->send_msg("catalog=%s", client->catalog->name());
849 /* Storage defaults */
850 else if (strcmp(ua->argk[1], "storage") == 0) {
851 if (!acl_access_ok(ua, Storage_ACL, ua->argv[1])) {
854 storage = (STORE *)GetResWithName(R_STORAGE, ua->argv[1]);
857 ua->send_msg("storage=%s", storage->name());
858 ua->send_msg("address=%s", storage->address);
859 ua->send_msg("enabled=%d", storage->enabled);
860 ua->send_msg("media_type=%s", storage->media_type);
861 ua->send_msg("sdport=%d", storage->SDport);
862 device = (DEVICE *)storage->device->first();
863 ua->send_msg("device=%s", device->name());
864 if (storage->device->size() > 1) {
865 while ((device = (DEVICE *)storage->device->next())) {
866 ua->send_msg(",%s", device->name());
872 else if (strcmp(ua->argk[1], "pool") == 0) {
873 if (!acl_access_ok(ua, Pool_ACL, ua->argv[1])) {
876 pool = (POOL *)GetResWithName(R_POOL, ua->argv[1]);
878 ua->send_msg("pool=%s", pool->name());
879 ua->send_msg("pool_type=%s", pool->pool_type);
880 ua->send_msg("label_format=%s", pool->label_format?pool->label_format:"");
881 ua->send_msg("use_volume_once=%d", pool->use_volume_once);
882 ua->send_msg("purge_oldest_volume=%d", pool->purge_oldest_volume);
883 ua->send_msg("recycle_oldest_volume=%d", pool->recycle_oldest_volume);
884 ua->send_msg("recycle_current_volume=%d", pool->recycle_current_volume);
885 ua->send_msg("max_volumes=%d", pool->max_volumes);
886 ua->send_msg("vol_retention=%s", edit_uint64(pool->VolRetention, ed1));
887 ua->send_msg("vol_use_duration=%s", edit_uint64(pool->VolUseDuration, ed1));
888 ua->send_msg("max_vol_jobs=%d", pool->MaxVolJobs);
889 ua->send_msg("max_vol_files=%d", pool->MaxVolFiles);
890 ua->send_msg("max_vol_bytes=%s", edit_uint64(pool->MaxVolBytes, ed1));
891 ua->send_msg("auto_prune=%d", pool->AutoPrune);
892 ua->send_msg("recycle=%d", pool->Recycle);
893 ua->send_msg("file_retention=%s", edit_uint64(pool->FileRetention, ed1));
894 ua->send_msg("job_retention=%s", edit_uint64(pool->JobRetention, ed1));