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)
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;
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)
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;
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)
423 Dmsg1(120, "diecmd:%s:\n", cmd);
426 for (i=1; i<ua->argc; i++) {
427 if (strcasecmp(ua->argk[i], "dir") == 0 ||
428 strcasecmp(ua->argk[i], "director") == 0) {
429 ua->send_msg(_("The Director will segment fault.\n"));
430 a = jcr->JobId; /* ref NULL pointer */
431 jcr->JobId = 1000; /* another ref NULL pointer */
434 if (strcasecmp(ua->argk[i], "client") == 0 ||
435 strcasecmp(ua->argk[i], "fd") == 0) {
438 client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[i]);
440 do_client_die(ua, client);
444 client = select_client_resource(ua);
446 do_client_die(ua, client);
451 if (strcasecmp(ua->argk[i], NT_("store")) == 0 ||
452 strcasecmp(ua->argk[i], NT_("storage")) == 0 ||
453 strcasecmp(ua->argk[i], NT_("sd")) == 0) {
456 store = (STORE *)GetResWithName(R_STORAGE, ua->argv[i]);
458 do_storage_die(ua, store);
462 store = get_storage_resource(ua, false/*no default*/);
464 do_storage_die(ua, store);
470 * We didn't find an appropriate keyword above, so
473 start_prompt(ua, _("Available daemons are: \n"));
474 add_prompt(ua, _("Director"));
475 add_prompt(ua, _("Storage"));
476 add_prompt(ua, _("Client"));
477 switch(do_prompt(ua, "", _("Select daemon type to make die"), NULL, 0)) {
478 case 0: /* Director */
479 ua->send_msg(_("The Director will segment fault.\n"));
480 a = jcr->JobId; /* ref NULL pointer */
481 jcr->JobId = 1000; /* another ref NULL pointer */
484 store = get_storage_resource(ua, false/*no default*/);
486 do_storage_die(ua, store);
490 client = select_client_resource(ua);
492 do_client_die(ua, client);
504 * Dummy routine for non-development version
506 static bool diecmd(UAContext *ua, const char *cmd)
514 * Can use an argument to filter on JobType
517 static bool jobscmd(UAContext *ua, const char *cmd)
522 if ((pos = find_arg_with_value(ua, "type")) >= 0) {
523 type = ua->argv[pos][0];
526 foreach_res(job, R_JOB) {
527 if (!type || type == job->JobType) {
528 if (acl_access_ok(ua, Job_ACL, job->name())) {
529 ua->send_msg("%s\n", job->name());
537 static bool filesetscmd(UAContext *ua, const char *cmd)
541 foreach_res(fs, R_FILESET) {
542 if (acl_access_ok(ua, FileSet_ACL, fs->name())) {
543 ua->send_msg("%s\n", fs->name());
550 static bool clientscmd(UAContext *ua, const char *cmd)
554 foreach_res(client, R_CLIENT) {
555 if (acl_access_ok(ua, Client_ACL, client->name())) {
556 ua->send_msg("%s\n", client->name());
563 static bool msgscmd(UAContext *ua, const char *cmd)
567 foreach_res(msgs, R_MSGS) {
568 ua->send_msg("%s\n", msgs->name());
574 static bool poolscmd(UAContext *ua, const char *cmd)
578 foreach_res(pool, R_POOL) {
579 if (acl_access_ok(ua, Pool_ACL, pool->name())) {
580 ua->send_msg("%s\n", pool->name());
587 static bool storagecmd(UAContext *ua, const char *cmd)
591 foreach_res(store, R_STORAGE) {
592 if (acl_access_ok(ua, Storage_ACL, store->name())) {
593 ua->send_msg("%s\n", store->name());
600 static bool aopcmd(UAContext *ua, const char *cmd)
602 ua->send_msg("None\n");
603 ua->send_msg("Truncate\n");
607 static bool typescmd(UAContext *ua, const char *cmd)
609 ua->send_msg("Backup\n");
610 ua->send_msg("Restore\n");
611 ua->send_msg("Admin\n");
612 ua->send_msg("Verify\n");
613 ua->send_msg("Migrate\n");
618 * If this command is called, it tells the director that we
619 * are a program that wants a sort of API, and hence,
620 * we will probably suppress certain output, include more
621 * error codes, and most of all send back a good number
622 * of new signals that indicate whether or not the command
625 static bool api_cmd(UAContext *ua, const char *cmd)
628 ua->api = atoi(ua->argk[1]);
635 static int client_backups_handler(void *ctx, int num_field, char **row)
637 UAContext *ua = (UAContext *)ctx;
638 ua->send_msg("| %s | %s | %s | %s | %s | %s | %s | %s |\n",
639 row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8]);
644 * Return the backups for this client
646 * .backups client=xxx fileset=yyy
649 static bool backupscmd(UAContext *ua, const char *cmd)
651 if (!open_client_db(ua)) {
654 if (ua->argc != 3 || strcmp(ua->argk[1], "client") != 0 ||
655 strcmp(ua->argk[2], "fileset") != 0) {
658 if (!acl_access_ok(ua, Client_ACL, ua->argv[1]) ||
659 !acl_access_ok(ua, FileSet_ACL, ua->argv[2])) {
660 ua->error_msg(_("Access to specified Client or FileSet not allowed.\n"));
663 Mmsg(ua->cmd, client_backups, ua->argv[1], ua->argv[2]);
664 if (!db_sql_query(ua->db, ua->cmd, client_backups_handler, (void *)ua)) {
665 ua->error_msg(_("Query failed: %s. ERR=%s\n"), ua->cmd, db_strerror(ua->db));
671 static int sql_handler(void *ctx, int num_field, char **row)
673 UAContext *ua = (UAContext *)ctx;
674 POOL_MEM rows(PM_MESSAGE);
676 /* Check for nonsense */
677 if (num_field == 0 || row == NULL || row[0] == NULL) {
678 return 0; /* nothing returned */
680 for (int i=0; num_field--; i++) {
682 pm_strcpy(rows, NPRT(row[0]));
684 pm_strcat(rows, NPRT(row[i]));
686 pm_strcat(rows, "\t");
688 if (!rows.c_str() || !*rows.c_str()) {
691 ua->send_msg("%s", rows.c_str());
696 static bool sql_cmd(UAContext *ua, const char *cmd)
699 if (!open_client_db(ua)) {
702 index = find_arg_with_value(ua, "query");
704 ua->error_msg(_("query keyword not found.\n"));
707 if (!db_sql_query(ua->db, ua->argv[index], sql_handler, (void *)ua)) {
708 Dmsg1(100, "Query failed: ERR=%s\n", db_strerror(ua->db));
709 ua->error_msg(_("Query failed: %s. ERR=%s\n"), ua->cmd, db_strerror(ua->db));
715 static int one_handler(void *ctx, int num_field, char **row)
717 UAContext *ua = (UAContext *)ctx;
718 ua->send_msg("%s\n", row[0]);
722 static bool mediatypescmd(UAContext *ua, const char *cmd)
724 if (!open_client_db(ua)) {
727 if (!db_sql_query(ua->db,
728 "SELECT DISTINCT MediaType FROM MediaType ORDER BY MediaType",
729 one_handler, (void *)ua))
731 ua->error_msg(_("List MediaType failed: ERR=%s\n"), db_strerror(ua->db));
736 static bool mediacmd(UAContext *ua, const char *cmd)
738 if (!open_client_db(ua)) {
741 if (!db_sql_query(ua->db,
742 "SELECT DISTINCT Media.VolumeName FROM Media ORDER BY VolumeName",
743 one_handler, (void *)ua))
745 ua->error_msg(_("List Media failed: ERR=%s\n"), db_strerror(ua->db));
750 static bool locationscmd(UAContext *ua, const char *cmd)
752 if (!open_client_db(ua)) {
755 if (!db_sql_query(ua->db,
756 "SELECT DISTINCT Location FROM Location ORDER BY Location",
757 one_handler, (void *)ua))
759 ua->error_msg(_("List Location failed: ERR=%s\n"), db_strerror(ua->db));
764 static bool levelscmd(UAContext *ua, const char *cmd)
766 ua->send_msg("Incremental\n");
767 ua->send_msg("Full\n");
768 ua->send_msg("Differential\n");
769 ua->send_msg("VirtualFull\n");
770 ua->send_msg("Catalog\n");
771 ua->send_msg("InitCatalog\n");
772 ua->send_msg("VolumeToCatalog\n");
776 static bool volstatuscmd(UAContext *ua, const char *cmd)
778 ua->send_msg("Append\n");
779 ua->send_msg("Full\n");
780 ua->send_msg("Used\n");
781 ua->send_msg("Recycle\n");
782 ua->send_msg("Purged\n");
783 ua->send_msg("Cleaning\n");
784 ua->send_msg("Error\n");
789 * Return default values for a job
791 static bool defaultscmd(UAContext *ua, const char *cmd)
799 if (ua->argc != 2 || !ua->argv[1]) {
804 if (strcmp(ua->argk[1], "job") == 0) {
805 if (!acl_access_ok(ua, Job_ACL, ua->argv[1])) {
808 job = (JOB *)GetResWithName(R_JOB, ua->argv[1]);
811 ua->send_msg("job=%s", job->name());
812 ua->send_msg("pool=%s", job->pool->name());
813 ua->send_msg("messages=%s", job->messages->name());
814 ua->send_msg("client=%s", job->client->name());
815 get_job_storage(&store, job, NULL);
816 ua->send_msg("storage=%s", store.store->name());
817 ua->send_msg("where=%s", job->RestoreWhere?job->RestoreWhere:"");
818 ua->send_msg("level=%s", level_to_str(job->JobLevel));
819 ua->send_msg("type=%s", job_type_to_str(job->JobType));
820 ua->send_msg("fileset=%s", job->fileset->name());
821 ua->send_msg("enabled=%d", job->enabled);
822 ua->send_msg("catalog=%s", job->client->catalog->name());
825 /* Client defaults */
826 else if (strcmp(ua->argk[1], "client") == 0) {
827 if (!acl_access_ok(ua, Client_ACL, ua->argv[1])) {
830 client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[1]);
832 ua->send_msg("client=%s", client->name());
833 ua->send_msg("address=%s", client->address);
834 ua->send_msg("fdport=%d", client->FDport);
835 ua->send_msg("file_retention=%s", edit_uint64(client->FileRetention, ed1));
836 ua->send_msg("job_retention=%s", edit_uint64(client->JobRetention, ed1));
837 ua->send_msg("autoprune=%d", client->AutoPrune);
838 ua->send_msg("catalog=%s", client->catalog->name());
841 /* Storage defaults */
842 else if (strcmp(ua->argk[1], "storage") == 0) {
843 if (!acl_access_ok(ua, Storage_ACL, ua->argv[1])) {
846 storage = (STORE *)GetResWithName(R_STORAGE, ua->argv[1]);
849 ua->send_msg("storage=%s", storage->name());
850 ua->send_msg("address=%s", storage->address);
851 ua->send_msg("enabled=%d", storage->enabled);
852 ua->send_msg("media_type=%s", storage->media_type);
853 ua->send_msg("sdport=%d", storage->SDport);
854 device = (DEVICE *)storage->device->first();
855 ua->send_msg("device=%s", device->name());
856 if (storage->device->size() > 1) {
857 while ((device = (DEVICE *)storage->device->next())) {
858 ua->send_msg(",%s", device->name());
864 else if (strcmp(ua->argk[1], "pool") == 0) {
865 if (!acl_access_ok(ua, Pool_ACL, ua->argv[1])) {
868 pool = (POOL *)GetResWithName(R_POOL, ua->argv[1]);
870 ua->send_msg("pool=%s", pool->name());
871 ua->send_msg("pool_type=%s", pool->pool_type);
872 ua->send_msg("label_format=%s", pool->label_format?pool->label_format:"");
873 ua->send_msg("use_volume_once=%d", pool->use_volume_once);
874 ua->send_msg("purge_oldest_volume=%d", pool->purge_oldest_volume);
875 ua->send_msg("recycle_oldest_volume=%d", pool->recycle_oldest_volume);
876 ua->send_msg("recycle_current_volume=%d", pool->recycle_current_volume);
877 ua->send_msg("max_volumes=%d", pool->max_volumes);
878 ua->send_msg("vol_retention=%s", edit_uint64(pool->VolRetention, ed1));
879 ua->send_msg("vol_use_duration=%s", edit_uint64(pool->VolUseDuration, ed1));
880 ua->send_msg("max_vol_jobs=%d", pool->MaxVolJobs);
881 ua->send_msg("max_vol_files=%d", pool->MaxVolFiles);
882 ua->send_msg("max_vol_bytes=%s", edit_uint64(pool->MaxVolBytes, ed1));
883 ua->send_msg("auto_prune=%d", pool->AutoPrune);
884 ua->send_msg("recycle=%d", pool->Recycle);
885 ua->send_msg("file_retention=%s", edit_uint64(pool->FileRetention, ed1));
886 ua->send_msg("job_retention=%s", edit_uint64(pool->JobRetention, ed1));