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);
71 static bool mediacmd(UAContext *ua, const char *cmd);
72 static bool aopcmd(UAContext *ua, const char *cmd);
74 static bool dot_bvfs_lsdirs(UAContext *ua, const char *cmd);
75 static bool dot_bvfs_lsfiles(UAContext *ua, const char *cmd);
76 static bool dot_bvfs_update(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"), diecmd, NULL, false},
90 { NT_(".exit"), dot_quit_cmd, 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)
170 if (!open_client_db(ua)) {
174 int pos = find_arg_with_value(ua, "jobid");
175 if (pos != -1 && is_a_number_list(ua->argv[pos])) {
177 pm_strcpy(jobids, ua->argv[pos]);
178 bvfs_update_path_hierarchy_cache(ua->jcr, ua->db, jobids.c_str());
180 /* update cache for all jobids */
181 bvfs_update_cache(ua->jcr, ua->db);
186 static int bvfs_result_handler(void *ctx, int fields, char **row)
188 UAContext *ua = (UAContext *)ctx;
193 char empty[] = "A A A A A A A A A A A A A A";
195 lstat = (row[BVFS_LStat] && row[BVFS_LStat][0])?row[BVFS_LStat]:empty;
196 fileid = (row[BVFS_FileId] && row[BVFS_FileId][0])?row[BVFS_FileId]:"0";
198 memset(&statp, 0, sizeof(struct stat));
199 decode_stat(lstat, &statp, &LinkFI);
201 Dmsg1(0, "type=%s\n", row[0]);
202 if (bvfs_is_dir(row)) {
203 char *path = bvfs_basename_dir(row[BVFS_Name]);
204 ua->send_msg("%s\t0\t%s\t%s\t%s\t%s\n", row[BVFS_PathId], fileid,
205 row[BVFS_JobId], row[BVFS_LStat], path);
207 } else if (bvfs_is_file(row)) {
208 ua->send_msg("%s\t%s\t%s\t%s\t%s\t%s\n", row[BVFS_PathId],
209 row[BVFS_FilenameId], fileid, row[BVFS_JobId],
210 row[BVFS_LStat], row[BVFS_Name]);
216 static bool bvfs_parse_arg(UAContext *ua,
217 DBId_t *pathid, char **path, char **jobid,
218 int *limit, int *offset)
226 for (int i=1; i<ua->argc; i++) {
227 if (strcasecmp(ua->argk[i], NT_("pathid")) == 0) {
228 if (is_a_number(ua->argv[i])) {
229 *pathid = str_to_int64(ua->argv[i]);
232 if (strcasecmp(ua->argk[i], NT_("path")) == 0) {
236 if (strcasecmp(ua->argk[i], NT_("jobid")) == 0) {
237 if (is_a_number_list(ua->argv[i])) {
238 *jobid = ua->argv[i];
242 if (strcasecmp(ua->argk[i], NT_("limit")) == 0) {
243 if (is_a_number(ua->argv[i])) {
244 *limit = str_to_int64(ua->argv[i]);
248 if (strcasecmp(ua->argk[i], NT_("offset")) == 0) {
249 if (is_a_number(ua->argv[i])) {
250 *offset = str_to_int64(ua->argv[i]);
255 if (!((*pathid || *path) && *jobid)) {
259 if (!open_client_db(ua)) {
267 * .bvfs_lsfiles jobid=1,2,3,4 pathid=10
268 * .bvfs_lsfiles jobid=1,2,3,4 path=/
270 static bool dot_bvfs_lsfiles(UAContext *ua, const char *cmd)
273 int limit=2000, offset=0;
274 char *path=NULL, *jobid=NULL;
276 if (!bvfs_parse_arg(ua, &pathid, &path, &jobid,
279 ua->error_msg("Can't find jobid, pathid or path argument\n");
280 return true; /* not enough param */
283 Bvfs fs(ua->jcr, ua->db);
284 fs.set_jobids(jobid);
285 fs.set_handler(bvfs_result_handler, ua);
294 fs.set_offset(offset);
302 * .bvfs_lsdirs jobid=1,2,3,4 pathid=10
303 * .bvfs_lsdirs jobid=1,2,3,4 path=/
304 * .bvfs_lsdirs jobid=1,2,3,4 path=
306 static bool dot_bvfs_lsdirs(UAContext *ua, const char *cmd)
309 int limit=2000, offset=0;
310 char *path=NULL, *jobid=NULL;
312 if (!bvfs_parse_arg(ua, &pathid, &path, &jobid,
315 ua->error_msg("Can't find jobid, pathid or path argument\n");
316 return true; /* not enough param */
319 Bvfs fs(ua->jcr, ua->db);
320 fs.set_jobids(jobid);
322 fs.set_handler(bvfs_result_handler, ua);
330 fs.set_offset(offset);
332 fs.ls_special_dirs();
338 static bool dot_quit_cmd(UAContext *ua, const char *cmd)
344 static bool dot_help_cmd(UAContext *ua, const char *cmd)
350 static bool getmsgscmd(UAContext *ua, const char *cmd)
352 if (console_msg_pending) {
353 do_messages(ua, cmd);
359 static void do_storage_die(UAContext *ua, STORE *store)
365 lstore.store = store;
366 pm_strcpy(lstore.store_source, _("unknown source"));
367 set_wstorage(jcr, &lstore);
368 /* Try connecting for up to 15 seconds */
369 ua->send_msg(_("Connecting to Storage daemon %s at %s:%d\n"),
370 store->name(), store->address, store->SDport);
371 if (!connect_to_storage_daemon(jcr, 1, 15, 0)) {
372 ua->error_msg(_("Failed to connect to Storage daemon.\n"));
375 Dmsg0(120, _("Connected to storage daemon\n"));
376 sd = jcr->store_bsock;
378 if (sd->recv() >= 0) {
379 ua->send_msg("%s", sd->msg);
381 sd->signal(BNET_TERMINATE);
383 jcr->store_bsock = NULL;
387 static void do_client_die(UAContext *ua, CLIENT *client)
391 /* Connect to File daemon */
393 ua->jcr->client = client;
394 /* Try to connect for 15 seconds */
395 ua->send_msg(_("Connecting to Client %s at %s:%d\n"),
396 client->name(), client->address, client->FDport);
397 if (!connect_to_file_daemon(ua->jcr, 1, 15, 0)) {
398 ua->error_msg(_("Failed to connect to Client.\n"));
401 Dmsg0(120, "Connected to file daemon\n");
402 fd = ua->jcr->file_bsock;
404 if (fd->recv() >= 0) {
405 ua->send_msg("%s", fd->msg);
407 fd->signal(BNET_TERMINATE);
409 ua->jcr->file_bsock = NULL;
414 * Create segmentation fault
416 static bool diecmd(UAContext *ua, const char *cmd)
424 Dmsg1(120, "diecmd:%s:\n", cmd);
427 for (i=1; i<ua->argc; i++) {
428 if (strcasecmp(ua->argk[i], "dir") == 0 ||
429 strcasecmp(ua->argk[i], "director") == 0) {
430 ua->send_msg(_("The Director will segment fault.\n"));
431 a = jcr->JobId; /* ref NULL pointer */
432 jcr->JobId = 1000; /* another ref NULL pointer */
435 if (strcasecmp(ua->argk[i], "client") == 0 ||
436 strcasecmp(ua->argk[i], "fd") == 0) {
439 client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[i]);
441 do_client_die(ua, client);
445 client = select_client_resource(ua);
447 do_client_die(ua, client);
452 if (strcasecmp(ua->argk[i], NT_("store")) == 0 ||
453 strcasecmp(ua->argk[i], NT_("storage")) == 0 ||
454 strcasecmp(ua->argk[i], NT_("sd")) == 0) {
457 store = (STORE *)GetResWithName(R_STORAGE, ua->argv[i]);
459 do_storage_die(ua, store);
463 store = get_storage_resource(ua, false/*no default*/);
465 do_storage_die(ua, store);
471 * We didn't find an appropriate keyword above, so
474 start_prompt(ua, _("Available daemons are: \n"));
475 add_prompt(ua, _("Director"));
476 add_prompt(ua, _("Storage"));
477 add_prompt(ua, _("Client"));
478 switch(do_prompt(ua, "", _("Select daemon type to make die"), NULL, 0)) {
479 case 0: /* Director */
480 ua->send_msg(_("The Director will segment fault.\n"));
481 a = jcr->JobId; /* ref NULL pointer */
482 jcr->JobId = 1000; /* another ref NULL pointer */
485 store = get_storage_resource(ua, false/*no default*/);
487 do_storage_die(ua, store);
491 client = select_client_resource(ua);
493 do_client_die(ua, client);
505 * Dummy routine for non-development version
507 static bool diecmd(UAContext *ua, const char *cmd)
515 * Can use an argument to filter on JobType
518 static bool jobscmd(UAContext *ua, const char *cmd)
523 if ((pos = find_arg_with_value(ua, "type")) >= 0) {
524 type = ua->argv[pos][0];
527 foreach_res(job, R_JOB) {
528 if (!type || type == job->JobType) {
529 if (acl_access_ok(ua, Job_ACL, job->name())) {
530 ua->send_msg("%s\n", job->name());
538 static bool filesetscmd(UAContext *ua, const char *cmd)
542 foreach_res(fs, R_FILESET) {
543 if (acl_access_ok(ua, FileSet_ACL, fs->name())) {
544 ua->send_msg("%s\n", fs->name());
551 static bool clientscmd(UAContext *ua, const char *cmd)
555 foreach_res(client, R_CLIENT) {
556 if (acl_access_ok(ua, Client_ACL, client->name())) {
557 ua->send_msg("%s\n", client->name());
564 static bool msgscmd(UAContext *ua, const char *cmd)
568 foreach_res(msgs, R_MSGS) {
569 ua->send_msg("%s\n", msgs->name());
575 static bool poolscmd(UAContext *ua, const char *cmd)
579 foreach_res(pool, R_POOL) {
580 if (acl_access_ok(ua, Pool_ACL, pool->name())) {
581 ua->send_msg("%s\n", pool->name());
588 static bool storagecmd(UAContext *ua, const char *cmd)
592 foreach_res(store, R_STORAGE) {
593 if (acl_access_ok(ua, Storage_ACL, store->name())) {
594 ua->send_msg("%s\n", store->name());
601 static bool aopcmd(UAContext *ua, const char *cmd)
603 ua->send_msg("None\n");
604 ua->send_msg("Truncate\n");
608 static bool typescmd(UAContext *ua, const char *cmd)
610 ua->send_msg("Backup\n");
611 ua->send_msg("Restore\n");
612 ua->send_msg("Admin\n");
613 ua->send_msg("Verify\n");
614 ua->send_msg("Migrate\n");
619 * If this command is called, it tells the director that we
620 * are a program that wants a sort of API, and hence,
621 * we will probably suppress certain output, include more
622 * error codes, and most of all send back a good number
623 * of new signals that indicate whether or not the command
626 static bool api_cmd(UAContext *ua, const char *cmd)
629 ua->api = atoi(ua->argk[1]);
636 static int client_backups_handler(void *ctx, int num_field, char **row)
638 UAContext *ua = (UAContext *)ctx;
639 ua->send_msg("| %s | %s | %s | %s | %s | %s | %s | %s |\n",
640 row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8]);
645 * Return the backups for this client
647 * .backups client=xxx fileset=yyy
650 static bool backupscmd(UAContext *ua, const char *cmd)
652 if (!open_client_db(ua)) {
655 if (ua->argc != 3 || strcmp(ua->argk[1], "client") != 0 ||
656 strcmp(ua->argk[2], "fileset") != 0) {
659 if (!acl_access_ok(ua, Client_ACL, ua->argv[1]) ||
660 !acl_access_ok(ua, FileSet_ACL, ua->argv[2])) {
661 ua->error_msg(_("Access to specified Client or FileSet not allowed.\n"));
664 Mmsg(ua->cmd, client_backups, ua->argv[1], ua->argv[2]);
665 if (!db_sql_query(ua->db, ua->cmd, client_backups_handler, (void *)ua)) {
666 ua->error_msg(_("Query failed: %s. ERR=%s\n"), ua->cmd, db_strerror(ua->db));
672 static int sql_handler(void *ctx, int num_field, char **row)
674 UAContext *ua = (UAContext *)ctx;
675 POOL_MEM rows(PM_MESSAGE);
677 /* Check for nonsense */
678 if (num_field == 0 || row == NULL || row[0] == NULL) {
679 return 0; /* nothing returned */
681 for (int i=0; num_field--; i++) {
683 pm_strcpy(rows, NPRT(row[0]));
685 pm_strcat(rows, NPRT(row[i]));
687 pm_strcat(rows, "\t");
689 if (!rows.c_str() || !*rows.c_str()) {
692 ua->send_msg("%s", rows.c_str());
697 static bool sql_cmd(UAContext *ua, const char *cmd)
700 if (!open_client_db(ua)) {
703 index = find_arg_with_value(ua, "query");
705 ua->error_msg(_("query keyword not found.\n"));
708 if (!db_sql_query(ua->db, ua->argv[index], sql_handler, (void *)ua)) {
709 Dmsg1(100, "Query failed: ERR=%s\n", db_strerror(ua->db));
710 ua->error_msg(_("Query failed: %s. ERR=%s\n"), ua->cmd, db_strerror(ua->db));
716 static int one_handler(void *ctx, int num_field, char **row)
718 UAContext *ua = (UAContext *)ctx;
719 ua->send_msg("%s\n", row[0]);
723 static bool mediatypescmd(UAContext *ua, const char *cmd)
725 if (!open_client_db(ua)) {
728 if (!db_sql_query(ua->db,
729 "SELECT DISTINCT MediaType FROM MediaType ORDER BY MediaType",
730 one_handler, (void *)ua))
732 ua->error_msg(_("List MediaType failed: ERR=%s\n"), db_strerror(ua->db));
737 static bool mediacmd(UAContext *ua, const char *cmd)
739 if (!open_client_db(ua)) {
742 if (!db_sql_query(ua->db,
743 "SELECT DISTINCT Media.VolumeName FROM Media ORDER BY VolumeName",
744 one_handler, (void *)ua))
746 ua->error_msg(_("List Media failed: ERR=%s\n"), db_strerror(ua->db));
751 static bool locationscmd(UAContext *ua, const char *cmd)
753 if (!open_client_db(ua)) {
756 if (!db_sql_query(ua->db,
757 "SELECT DISTINCT Location FROM Location ORDER BY Location",
758 one_handler, (void *)ua))
760 ua->error_msg(_("List Location failed: ERR=%s\n"), db_strerror(ua->db));
765 static bool levelscmd(UAContext *ua, const char *cmd)
767 ua->send_msg("Incremental\n");
768 ua->send_msg("Full\n");
769 ua->send_msg("Differential\n");
770 ua->send_msg("VirtualFull\n");
771 ua->send_msg("Catalog\n");
772 ua->send_msg("InitCatalog\n");
773 ua->send_msg("VolumeToCatalog\n");
777 static bool volstatuscmd(UAContext *ua, const char *cmd)
779 ua->send_msg("Append\n");
780 ua->send_msg("Full\n");
781 ua->send_msg("Used\n");
782 ua->send_msg("Recycle\n");
783 ua->send_msg("Purged\n");
784 ua->send_msg("Cleaning\n");
785 ua->send_msg("Error\n");
790 * Return default values for a job
792 static bool defaultscmd(UAContext *ua, const char *cmd)
800 if (ua->argc != 2 || !ua->argv[1]) {
805 if (strcmp(ua->argk[1], "job") == 0) {
806 if (!acl_access_ok(ua, Job_ACL, ua->argv[1])) {
809 job = (JOB *)GetResWithName(R_JOB, ua->argv[1]);
812 ua->send_msg("job=%s", job->name());
813 ua->send_msg("pool=%s", job->pool->name());
814 ua->send_msg("messages=%s", job->messages->name());
815 ua->send_msg("client=%s", job->client->name());
816 get_job_storage(&store, job, NULL);
817 ua->send_msg("storage=%s", store.store->name());
818 ua->send_msg("where=%s", job->RestoreWhere?job->RestoreWhere:"");
819 ua->send_msg("level=%s", level_to_str(job->JobLevel));
820 ua->send_msg("type=%s", job_type_to_str(job->JobType));
821 ua->send_msg("fileset=%s", job->fileset->name());
822 ua->send_msg("enabled=%d", job->enabled);
823 ua->send_msg("catalog=%s", job->client->catalog->name());
826 /* Client defaults */
827 else if (strcmp(ua->argk[1], "client") == 0) {
828 if (!acl_access_ok(ua, Client_ACL, ua->argv[1])) {
831 client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[1]);
833 ua->send_msg("client=%s", client->name());
834 ua->send_msg("address=%s", client->address);
835 ua->send_msg("fdport=%d", client->FDport);
836 ua->send_msg("file_retention=%s", edit_uint64(client->FileRetention, ed1));
837 ua->send_msg("job_retention=%s", edit_uint64(client->JobRetention, ed1));
838 ua->send_msg("autoprune=%d", client->AutoPrune);
839 ua->send_msg("catalog=%s", client->catalog->name());
842 /* Storage defaults */
843 else if (strcmp(ua->argk[1], "storage") == 0) {
844 if (!acl_access_ok(ua, Storage_ACL, ua->argv[1])) {
847 storage = (STORE *)GetResWithName(R_STORAGE, ua->argv[1]);
850 ua->send_msg("storage=%s", storage->name());
851 ua->send_msg("address=%s", storage->address);
852 ua->send_msg("enabled=%d", storage->enabled);
853 ua->send_msg("media_type=%s", storage->media_type);
854 ua->send_msg("sdport=%d", storage->SDport);
855 device = (DEVICE *)storage->device->first();
856 ua->send_msg("device=%s", device->name());
857 if (storage->device->size() > 1) {
858 while ((device = (DEVICE *)storage->device->next())) {
859 ua->send_msg(",%s", device->name());
865 else if (strcmp(ua->argk[1], "pool") == 0) {
866 if (!acl_access_ok(ua, Pool_ACL, ua->argv[1])) {
869 pool = (POOL *)GetResWithName(R_POOL, ua->argv[1]);
871 ua->send_msg("pool=%s", pool->name());
872 ua->send_msg("pool_type=%s", pool->pool_type);
873 ua->send_msg("label_format=%s", pool->label_format?pool->label_format:"");
874 ua->send_msg("use_volume_once=%d", pool->use_volume_once);
875 ua->send_msg("purge_oldest_volume=%d", pool->purge_oldest_volume);
876 ua->send_msg("recycle_oldest_volume=%d", pool->recycle_oldest_volume);
877 ua->send_msg("recycle_current_volume=%d", pool->recycle_current_volume);
878 ua->send_msg("max_volumes=%d", pool->max_volumes);
879 ua->send_msg("vol_retention=%s", edit_uint64(pool->VolRetention, ed1));
880 ua->send_msg("vol_use_duration=%s", edit_uint64(pool->VolUseDuration, ed1));
881 ua->send_msg("max_vol_jobs=%d", pool->MaxVolJobs);
882 ua->send_msg("max_vol_files=%d", pool->MaxVolFiles);
883 ua->send_msg("max_vol_bytes=%s", edit_uint64(pool->MaxVolBytes, ed1));
884 ua->send_msg("auto_prune=%d", pool->AutoPrune);
885 ua->send_msg("recycle=%d", pool->Recycle);