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
43 #include "cats/bvfs.h"
44 #include "findlib/find.h"
46 /* Imported variables */
48 /* Imported functions */
49 extern void do_messages(UAContext *ua, const char *cmd);
50 extern int quit_cmd(UAContext *ua, const char *cmd);
51 extern int qhelp_cmd(UAContext *ua, const char *cmd);
52 extern bool dot_status_cmd(UAContext *ua, const char *cmd);
55 /* Forward referenced functions */
56 static bool diecmd(UAContext *ua, const char *cmd);
57 static bool jobscmd(UAContext *ua, const char *cmd);
58 static bool filesetscmd(UAContext *ua, const char *cmd);
59 static bool clientscmd(UAContext *ua, const char *cmd);
60 static bool msgscmd(UAContext *ua, const char *cmd);
61 static bool poolscmd(UAContext *ua, const char *cmd);
62 static bool storagecmd(UAContext *ua, const char *cmd);
63 static bool defaultscmd(UAContext *ua, const char *cmd);
64 static bool typescmd(UAContext *ua, const char *cmd);
65 static bool backupscmd(UAContext *ua, const char *cmd);
66 static bool levelscmd(UAContext *ua, const char *cmd);
67 static bool getmsgscmd(UAContext *ua, const char *cmd);
68 static bool volstatuscmd(UAContext *ua, const char *cmd);
69 static bool mediatypescmd(UAContext *ua, const char *cmd);
70 static bool locationscmd(UAContext *ua, const char *cmd);
72 static bool dot_bvfs_lsdirs(UAContext *ua, const char *cmd);
73 static bool dot_bvfs_lsfiles(UAContext *ua, const char *cmd);
74 static bool dot_bvfs_update(UAContext *ua, const char *cmd);
76 static bool api_cmd(UAContext *ua, const char *cmd);
77 static bool sql_cmd(UAContext *ua, const char *cmd);
78 static bool dot_quit_cmd(UAContext *ua, const char *cmd);
79 static bool dot_help_cmd(UAContext *ua, const char *cmd);
81 struct cmdstruct { const char *key; bool (*func)(UAContext *ua, const char *cmd); const char *help;const bool use_in_rs;};
82 static struct cmdstruct commands[] = { /* help */ /* can be used in runscript */
83 { NT_(".api"), api_cmd, NULL, false},
84 { NT_(".backups"), backupscmd, NULL, false},
85 { NT_(".clients"), clientscmd, NULL, true},
86 { NT_(".defaults"), defaultscmd, NULL, false},
87 { NT_(".die"), diecmd, NULL, false},
88 { NT_(".exit"), dot_quit_cmd, NULL, false},
89 { NT_(".filesets"), filesetscmd, NULL, false},
90 { NT_(".help"), dot_help_cmd, NULL, false},
91 { NT_(".jobs"), jobscmd, NULL, true},
92 { NT_(".levels"), levelscmd, NULL, false},
93 { NT_(".messages"), getmsgscmd, NULL, false},
94 { NT_(".msgs"), msgscmd, NULL, false},
95 { NT_(".pools"), poolscmd, NULL, true},
96 { NT_(".quit"), dot_quit_cmd, NULL, false},
97 { NT_(".sql"), sql_cmd, NULL, false},
98 { NT_(".status"), dot_status_cmd, NULL, false},
99 { NT_(".storage"), storagecmd, NULL, true},
100 { NT_(".volstatus"), volstatuscmd, NULL, true},
101 { NT_(".mediatypes"), mediatypescmd, NULL, true},
102 { NT_(".locations"), locationscmd, NULL, true},
103 { NT_(".bvfs_lsdirs"), dot_bvfs_lsdirs, NULL, true},
104 { NT_(".bvfs_lsfiles"),dot_bvfs_lsfiles,NULL, true},
105 { NT_(".bvfs_update"), dot_bvfs_update, NULL, true},
106 { NT_(".types"), typescmd, NULL, false}
108 #define comsize ((int)(sizeof(commands)/sizeof(struct cmdstruct)))
111 * Execute a command from the UA
113 bool do_a_dot_command(UAContext *ua)
119 BSOCK *user = ua->UA_sock;
121 Dmsg1(1400, "Dot command: %s\n", user->msg);
126 len = strlen(ua->argk[0]);
128 if (ua->api) user->signal(BNET_CMD_BEGIN);
129 if (ua->api) user->signal(BNET_CMD_OK);
130 return true; /* no op */
132 for (i=0; i<comsize; i++) { /* search for command */
133 if (strncasecmp(ua->argk[0], _(commands[i].key), len) == 0) {
134 /* Check if this command is authorized in RunScript */
135 if (ua->runscript && !commands[i].use_in_rs) {
136 ua->error_msg(_("Can't use %s command in a runscript"), ua->argk[0]);
140 /* Check if command permitted, but "quit" is always OK */
141 if (strcmp(ua->argk[0], NT_(".quit")) != 0 &&
142 !acl_access_ok(ua, Command_ACL, ua->argk[0], len)) {
145 Dmsg1(100, "Cmd: %s\n", ua->cmd);
147 if (ua->api) user->signal(BNET_CMD_BEGIN);
148 ok = (*commands[i].func)(ua, ua->cmd); /* go execute command */
149 if (ua->api) user->signal(ok?BNET_CMD_OK:BNET_CMD_FAILED);
156 pm_strcat(user->msg, _(": is an invalid command.\n"));
157 ua->error_msg("%s", user->msg);
163 static bool dot_bvfs_update(UAContext *ua, const char *cmd)
166 if (!open_client_db(ua)) {
170 int pos = find_arg_with_value(ua, "jobid");
171 if (pos != -1 && is_a_number_list(ua->argv[pos])) {
173 pm_strcpy(jobids, ua->argv[pos]);
174 bvfs_update_path_hierarchy_cache(ua->jcr, ua->db, jobids.c_str());
176 /* update cache for all jobids */
177 bvfs_update_cache(ua->jcr, ua->db);
182 static int bvfs_result_handler(void *ctx, int fields, char **row)
184 UAContext *ua = (UAContext *)ctx;
189 char empty[] = "A A A A A A A A A A A A A A";
191 lstat = (row[BVFS_LStat] && row[BVFS_LStat][0])?row[BVFS_LStat]:empty;
192 fileid = (row[BVFS_FileId] && row[BVFS_FileId][0])?row[BVFS_FileId]:"0";
194 memset(&statp, 0, sizeof(struct stat));
195 decode_stat(lstat, &statp, &LinkFI);
197 Dmsg1(0, "type=%s\n", row[0]);
198 if (bvfs_is_dir(row)) {
199 char *path = bvfs_basename_dir(row[BVFS_Name]);
200 ua->send_msg("%s\t0\t%s\t%s\t%s\t%s\n", row[BVFS_PathId], fileid,
201 row[BVFS_JobId], row[BVFS_LStat], path);
203 } else if (bvfs_is_file(row)) {
204 ua->send_msg("%s\t%s\t%s\t%s\t%s\t%s\n", row[BVFS_PathId],
205 row[BVFS_FilenameId], fileid, row[BVFS_JobId],
206 row[BVFS_LStat], row[BVFS_Name]);
212 static bool bvfs_parse_arg(UAContext *ua,
213 DBId_t *pathid, char **path, char **jobid,
214 int *limit, int *offset)
222 for (int i=1; i<ua->argc; i++) {
223 if (strcasecmp(ua->argk[i], NT_("pathid")) == 0) {
224 if (is_a_number(ua->argv[i])) {
225 *pathid = str_to_int64(ua->argv[i]);
228 if (strcasecmp(ua->argk[i], NT_("path")) == 0) {
232 if (strcasecmp(ua->argk[i], NT_("jobid")) == 0) {
233 if (is_a_number_list(ua->argv[i])) {
234 *jobid = ua->argv[i];
238 if (strcasecmp(ua->argk[i], NT_("limit")) == 0) {
239 if (is_a_number(ua->argv[i])) {
240 *limit = str_to_int64(ua->argv[i]);
244 if (strcasecmp(ua->argk[i], NT_("offset")) == 0) {
245 if (is_a_number(ua->argv[i])) {
246 *offset = str_to_int64(ua->argv[i]);
251 if (!((*pathid || *path) && *jobid)) {
255 if (!open_client_db(ua)) {
263 * .bvfs_lsfiles jobid=1,2,3,4 pathid=10
264 * .bvfs_lsfiles jobid=1,2,3,4 path=/
266 static bool dot_bvfs_lsfiles(UAContext *ua, const char *cmd)
269 int limit=2000, offset=0;
270 char *path=NULL, *jobid=NULL;
272 if (!bvfs_parse_arg(ua, &pathid, &path, &jobid,
275 ua->error_msg("Can't find jobid, pathid or path argument\n");
276 return true; /* not enough param */
279 Bvfs fs(ua->jcr, ua->db);
280 fs.set_jobids(jobid);
281 fs.set_handler(bvfs_result_handler, ua);
290 fs.set_offset(offset);
298 * .bvfs_lsdirs jobid=1,2,3,4 pathid=10
299 * .bvfs_lsdirs jobid=1,2,3,4 path=/
300 * .bvfs_lsdirs jobid=1,2,3,4 path=
302 static bool dot_bvfs_lsdirs(UAContext *ua, const char *cmd)
305 int limit=2000, offset=0;
306 char *path=NULL, *jobid=NULL;
308 if (!bvfs_parse_arg(ua, &pathid, &path, &jobid,
311 ua->error_msg("Can't find jobid, pathid or path argument\n");
312 return true; /* not enough param */
315 Bvfs fs(ua->jcr, ua->db);
316 fs.set_jobids(jobid);
318 fs.set_handler(bvfs_result_handler, ua);
326 fs.set_offset(offset);
328 fs.ls_special_dirs();
334 static bool dot_quit_cmd(UAContext *ua, const char *cmd)
340 static bool dot_help_cmd(UAContext *ua, const char *cmd)
346 static bool getmsgscmd(UAContext *ua, const char *cmd)
348 if (console_msg_pending) {
349 do_messages(ua, cmd);
355 static void do_storage_die(UAContext *ua, STORE *store)
361 lstore.store = store;
362 pm_strcpy(lstore.store_source, _("unknown source"));
363 set_wstorage(jcr, &lstore);
364 /* Try connecting for up to 15 seconds */
365 ua->send_msg(_("Connecting to Storage daemon %s at %s:%d\n"),
366 store->name(), store->address, store->SDport);
367 if (!connect_to_storage_daemon(jcr, 1, 15, 0)) {
368 ua->error_msg(_("Failed to connect to Storage daemon.\n"));
371 Dmsg0(120, _("Connected to storage daemon\n"));
372 sd = jcr->store_bsock;
374 if (sd->recv() >= 0) {
375 ua->send_msg("%s", sd->msg);
377 sd->signal(BNET_TERMINATE);
379 jcr->store_bsock = NULL;
383 static void do_client_die(UAContext *ua, CLIENT *client)
387 /* Connect to File daemon */
389 ua->jcr->client = client;
390 /* Try to connect for 15 seconds */
391 ua->send_msg(_("Connecting to Client %s at %s:%d\n"),
392 client->name(), client->address, client->FDport);
393 if (!connect_to_file_daemon(ua->jcr, 1, 15, 0)) {
394 ua->error_msg(_("Failed to connect to Client.\n"));
397 Dmsg0(120, "Connected to file daemon\n");
398 fd = ua->jcr->file_bsock;
400 if (fd->recv() >= 0) {
401 ua->send_msg("%s", fd->msg);
403 fd->signal(BNET_TERMINATE);
405 ua->jcr->file_bsock = NULL;
410 * Create segmentation fault
412 static bool diecmd(UAContext *ua, const char *cmd)
420 Dmsg1(120, "diecmd:%s:\n", cmd);
423 for (i=1; i<ua->argc; i++) {
424 if (strcasecmp(ua->argk[i], "dir") == 0 ||
425 strcasecmp(ua->argk[i], "director") == 0) {
426 ua->send_msg(_("The Director will segment fault.\n"));
427 a = jcr->JobId; /* ref NULL pointer */
428 jcr->JobId = 1000; /* another ref NULL pointer */
431 if (strcasecmp(ua->argk[i], "client") == 0 ||
432 strcasecmp(ua->argk[i], "fd") == 0) {
435 client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[i]);
437 do_client_die(ua, client);
441 client = select_client_resource(ua);
443 do_client_die(ua, client);
448 if (strcasecmp(ua->argk[i], NT_("store")) == 0 ||
449 strcasecmp(ua->argk[i], NT_("storage")) == 0 ||
450 strcasecmp(ua->argk[i], NT_("sd")) == 0) {
453 store = (STORE *)GetResWithName(R_STORAGE, ua->argv[i]);
455 do_storage_die(ua, store);
459 store = get_storage_resource(ua, false/*no default*/);
461 do_storage_die(ua, store);
467 * We didn't find an appropriate keyword above, so
470 start_prompt(ua, _("Available daemons are: \n"));
471 add_prompt(ua, _("Director"));
472 add_prompt(ua, _("Storage"));
473 add_prompt(ua, _("Client"));
474 switch(do_prompt(ua, "", _("Select daemon type to make die"), NULL, 0)) {
475 case 0: /* Director */
476 ua->send_msg(_("The Director will segment fault.\n"));
477 a = jcr->JobId; /* ref NULL pointer */
478 jcr->JobId = 1000; /* another ref NULL pointer */
481 store = get_storage_resource(ua, false/*no default*/);
483 do_storage_die(ua, store);
487 client = select_client_resource(ua);
489 do_client_die(ua, client);
501 * Dummy routine for non-development version
503 static bool diecmd(UAContext *ua, const char *cmd)
510 static bool jobscmd(UAContext *ua, const char *cmd)
514 foreach_res(job, R_JOB) {
515 if (acl_access_ok(ua, Job_ACL, job->name())) {
516 ua->send_msg("%s\n", job->name());
523 static bool filesetscmd(UAContext *ua, const char *cmd)
527 foreach_res(fs, R_FILESET) {
528 if (acl_access_ok(ua, FileSet_ACL, fs->name())) {
529 ua->send_msg("%s\n", fs->name());
536 static bool clientscmd(UAContext *ua, const char *cmd)
540 foreach_res(client, R_CLIENT) {
541 if (acl_access_ok(ua, Client_ACL, client->name())) {
542 ua->send_msg("%s\n", client->name());
549 static bool msgscmd(UAContext *ua, const char *cmd)
553 foreach_res(msgs, R_MSGS) {
554 ua->send_msg("%s\n", msgs->name());
560 static bool poolscmd(UAContext *ua, const char *cmd)
564 foreach_res(pool, R_POOL) {
565 if (acl_access_ok(ua, Pool_ACL, pool->name())) {
566 ua->send_msg("%s\n", pool->name());
573 static bool storagecmd(UAContext *ua, const char *cmd)
577 foreach_res(store, R_STORAGE) {
578 if (acl_access_ok(ua, Storage_ACL, store->name())) {
579 ua->send_msg("%s\n", store->name());
587 static bool typescmd(UAContext *ua, const char *cmd)
589 ua->send_msg("Backup\n");
590 ua->send_msg("Restore\n");
591 ua->send_msg("Admin\n");
592 ua->send_msg("Verify\n");
593 ua->send_msg("Migrate\n");
599 * If this command is called, it tells the director that we
600 * are a program that wants a sort of API, and hence,
601 * we will probably suppress certain output, include more
602 * error codes, and most of all send back a good number
603 * of new signals that indicate whether or not the command
606 static bool api_cmd(UAContext *ua, const char *cmd)
609 ua->api = atoi(ua->argk[1]);
616 static int client_backups_handler(void *ctx, int num_field, char **row)
618 UAContext *ua = (UAContext *)ctx;
619 ua->send_msg("| %s | %s | %s | %s | %s | %s | %s | %s |\n",
620 row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8]);
625 * Return the backups for this client
627 * .backups client=xxx fileset=yyy
630 static bool backupscmd(UAContext *ua, const char *cmd)
632 if (!open_client_db(ua)) {
635 if (ua->argc != 3 || strcmp(ua->argk[1], "client") != 0 ||
636 strcmp(ua->argk[2], "fileset") != 0) {
639 if (!acl_access_ok(ua, Client_ACL, ua->argv[1]) ||
640 !acl_access_ok(ua, FileSet_ACL, ua->argv[2])) {
641 ua->error_msg(_("Access to specified Client or FileSet not allowed.\n"));
644 Mmsg(ua->cmd, client_backups, ua->argv[1], ua->argv[2]);
645 if (!db_sql_query(ua->db, ua->cmd, client_backups_handler, (void *)ua)) {
646 ua->error_msg(_("Query failed: %s. ERR=%s\n"), ua->cmd, db_strerror(ua->db));
652 static int sql_handler(void *ctx, int num_field, char **row)
654 UAContext *ua = (UAContext *)ctx;
655 POOL_MEM rows(PM_MESSAGE);
657 /* Check for nonsense */
658 if (num_field == 0 || row == NULL || row[0] == NULL) {
659 return 0; /* nothing returned */
661 for (int i=0; num_field--; i++) {
663 pm_strcpy(rows, NPRT(row[0]));
665 pm_strcat(rows, NPRT(row[i]));
667 pm_strcat(rows, "\t");
669 if (!rows.c_str() || !*rows.c_str()) {
672 ua->send_msg("%s", rows.c_str());
677 static bool sql_cmd(UAContext *ua, const char *cmd)
680 if (!open_client_db(ua)) {
683 index = find_arg_with_value(ua, "query");
685 ua->error_msg(_("query keyword not found.\n"));
688 if (!db_sql_query(ua->db, ua->argv[index], sql_handler, (void *)ua)) {
689 Dmsg1(100, "Query failed: ERR=%s\n", db_strerror(ua->db));
690 ua->error_msg(_("Query failed: %s. ERR=%s\n"), ua->cmd, db_strerror(ua->db));
696 static int one_handler(void *ctx, int num_field, char **row)
698 UAContext *ua = (UAContext *)ctx;
699 ua->send_msg("%s\n", row[0]);
703 static bool mediatypescmd(UAContext *ua, const char *cmd)
705 if (!open_client_db(ua)) {
708 if (!db_sql_query(ua->db,
709 "SELECT DISTINCT MediaType FROM MediaType ORDER BY MediaType",
710 one_handler, (void *)ua))
712 ua->error_msg(_("List MediaType failed: ERR=%s\n"), db_strerror(ua->db));
717 static bool locationscmd(UAContext *ua, const char *cmd)
719 if (!open_client_db(ua)) {
722 if (!db_sql_query(ua->db,
723 "SELECT DISTINCT Location FROM Location ORDER BY Location",
724 one_handler, (void *)ua))
726 ua->error_msg(_("List Location failed: ERR=%s\n"), db_strerror(ua->db));
731 static bool levelscmd(UAContext *ua, const char *cmd)
733 ua->send_msg("Incremental\n");
734 ua->send_msg("Full\n");
735 ua->send_msg("Differential\n");
736 ua->send_msg("VirtualFull\n");
737 ua->send_msg("Catalog\n");
738 ua->send_msg("InitCatalog\n");
739 ua->send_msg("VolumeToCatalog\n");
743 static bool volstatuscmd(UAContext *ua, const char *cmd)
745 ua->send_msg("Append\n");
746 ua->send_msg("Full\n");
747 ua->send_msg("Used\n");
748 ua->send_msg("Recycle\n");
749 ua->send_msg("Purged\n");
750 ua->send_msg("Cleaning\n");
751 ua->send_msg("Error\n");
756 * Return default values for a job
758 static bool defaultscmd(UAContext *ua, const char *cmd)
766 if (ua->argc != 2 || !ua->argv[1]) {
771 if (strcmp(ua->argk[1], "job") == 0) {
772 if (!acl_access_ok(ua, Job_ACL, ua->argv[1])) {
775 job = (JOB *)GetResWithName(R_JOB, ua->argv[1]);
778 ua->send_msg("job=%s", job->name());
779 ua->send_msg("pool=%s", job->pool->name());
780 ua->send_msg("messages=%s", job->messages->name());
781 ua->send_msg("client=%s", job->client->name());
782 get_job_storage(&store, job, NULL);
783 ua->send_msg("storage=%s", store.store->name());
784 ua->send_msg("where=%s", job->RestoreWhere?job->RestoreWhere:"");
785 ua->send_msg("level=%s", level_to_str(job->JobLevel));
786 ua->send_msg("type=%s", job_type_to_str(job->JobType));
787 ua->send_msg("fileset=%s", job->fileset->name());
788 ua->send_msg("enabled=%d", job->enabled);
789 ua->send_msg("catalog=%s", job->client->catalog->name());
792 /* Client defaults */
793 else if (strcmp(ua->argk[1], "client") == 0) {
794 if (!acl_access_ok(ua, Client_ACL, ua->argv[1])) {
797 client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[1]);
799 ua->send_msg("client=%s", client->name());
800 ua->send_msg("address=%s", client->address);
801 ua->send_msg("fdport=%d", client->FDport);
802 ua->send_msg("file_retention=%s", edit_uint64(client->FileRetention, ed1));
803 ua->send_msg("job_retention=%s", edit_uint64(client->JobRetention, ed1));
804 ua->send_msg("autoprune=%d", client->AutoPrune);
805 ua->send_msg("catalog=%s", client->catalog->name());
808 /* Storage defaults */
809 else if (strcmp(ua->argk[1], "storage") == 0) {
810 if (!acl_access_ok(ua, Storage_ACL, ua->argv[1])) {
813 storage = (STORE *)GetResWithName(R_STORAGE, ua->argv[1]);
816 ua->send_msg("storage=%s", storage->name());
817 ua->send_msg("address=%s", storage->address);
818 ua->send_msg("enabled=%d", storage->enabled);
819 ua->send_msg("media_type=%s", storage->media_type);
820 ua->send_msg("sdport=%d", storage->SDport);
821 device = (DEVICE *)storage->device->first();
822 ua->send_msg("device=%s", device->name());
823 if (storage->device->size() > 1) {
824 while ((device = (DEVICE *)storage->device->next())) {
825 ua->send_msg(",%s", device->name());
831 else if (strcmp(ua->argk[1], "pool") == 0) {
832 if (!acl_access_ok(ua, Pool_ACL, ua->argv[1])) {
835 pool = (POOL *)GetResWithName(R_POOL, ua->argv[1]);
837 ua->send_msg("pool=%s", pool->name());
838 ua->send_msg("pool_type=%s", pool->pool_type);
839 ua->send_msg("label_format=%s", pool->label_format?pool->label_format:"");
840 ua->send_msg("use_volume_once=%d", pool->use_volume_once);
841 ua->send_msg("purge_oldest_volume=%d", pool->purge_oldest_volume);
842 ua->send_msg("recycle_oldest_volume=%d", pool->recycle_oldest_volume);
843 ua->send_msg("recycle_current_volume=%d", pool->recycle_current_volume);
844 ua->send_msg("max_volumes=%d", pool->max_volumes);
845 ua->send_msg("vol_retention=%s", edit_uint64(pool->VolRetention, ed1));
846 ua->send_msg("vol_use_duration=%s", edit_uint64(pool->VolUseDuration, ed1));
847 ua->send_msg("max_vol_jobs=%d", pool->MaxVolJobs);
848 ua->send_msg("max_vol_files=%d", pool->MaxVolFiles);
849 ua->send_msg("max_vol_bytes=%s", edit_uint64(pool->MaxVolBytes, ed1));
850 ua->send_msg("auto_prune=%d", pool->AutoPrune);
851 ua->send_msg("recycle=%d", pool->Recycle);