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;
190 char *fileid=row[BVFS_FileId];
191 char *lstat=row[BVFS_LStat];
192 char *jobid=row[BVFS_JobId];
194 char empty[] = "A A A A A A A A A A A A A A";
197 /* We need to deal with non existant path */
198 if (!fileid || !is_a_number(fileid)) {
204 memset(&statp, 0, sizeof(struct stat));
205 decode_stat(lstat, &statp, &LinkFI);
207 Dmsg1(100, "type=%s\n", row[0]);
208 if (bvfs_is_dir(row)) {
209 char *path = bvfs_basename_dir(row[BVFS_Name]);
210 ua->send_msg("%s\t0\t%s\t%s\t%s\t%s\n", row[BVFS_PathId], fileid,
213 } else if (bvfs_is_file(row)) {
214 ua->send_msg("%s\t%s\t%s\t%s\t%s\t%s\n", row[BVFS_PathId],
215 row[BVFS_FilenameId], fileid, jobid,
216 lstat, row[BVFS_Name]);
222 static bool bvfs_parse_arg(UAContext *ua,
223 DBId_t *pathid, char **path, char **jobid,
224 int *limit, int *offset)
232 for (int i=1; i<ua->argc; i++) {
233 if (strcasecmp(ua->argk[i], NT_("pathid")) == 0) {
234 if (is_a_number(ua->argv[i])) {
235 *pathid = str_to_int64(ua->argv[i]);
238 if (strcasecmp(ua->argk[i], NT_("path")) == 0) {
242 if (strcasecmp(ua->argk[i], NT_("jobid")) == 0) {
243 if (is_a_number_list(ua->argv[i])) {
244 *jobid = ua->argv[i];
248 if (strcasecmp(ua->argk[i], NT_("limit")) == 0) {
249 if (is_a_number(ua->argv[i])) {
250 *limit = str_to_int64(ua->argv[i]);
254 if (strcasecmp(ua->argk[i], NT_("offset")) == 0) {
255 if (is_a_number(ua->argv[i])) {
256 *offset = str_to_int64(ua->argv[i]);
261 if (!((*pathid || *path) && *jobid)) {
265 if (!open_client_db(ua)) {
273 * .bvfs_lsfiles jobid=1,2,3,4 pathid=10
274 * .bvfs_lsfiles jobid=1,2,3,4 path=/
276 static bool dot_bvfs_lsfiles(UAContext *ua, const char *cmd)
279 int limit=2000, offset=0;
280 char *path=NULL, *jobid=NULL;
282 if (!bvfs_parse_arg(ua, &pathid, &path, &jobid,
285 ua->error_msg("Can't find jobid, pathid or path argument\n");
286 return true; /* not enough param */
289 Bvfs fs(ua->jcr, ua->db);
290 fs.set_jobids(jobid);
291 fs.set_handler(bvfs_result_handler, ua);
300 fs.set_offset(offset);
308 * .bvfs_lsdirs jobid=1,2,3,4 pathid=10
309 * .bvfs_lsdirs jobid=1,2,3,4 path=/
310 * .bvfs_lsdirs jobid=1,2,3,4 path=
312 static bool dot_bvfs_lsdirs(UAContext *ua, const char *cmd)
315 int limit=2000, offset=0;
316 char *path=NULL, *jobid=NULL;
318 if (!bvfs_parse_arg(ua, &pathid, &path, &jobid,
321 ua->error_msg("Can't find jobid, pathid or path argument\n");
322 return true; /* not enough param */
325 Bvfs fs(ua->jcr, ua->db);
326 fs.set_jobids(jobid);
328 fs.set_handler(bvfs_result_handler, ua);
336 fs.set_offset(offset);
338 fs.ls_special_dirs();
344 static bool dot_quit_cmd(UAContext *ua, const char *cmd)
350 static bool dot_help_cmd(UAContext *ua, const char *cmd)
356 static bool getmsgscmd(UAContext *ua, const char *cmd)
358 if (console_msg_pending) {
359 do_messages(ua, cmd);
365 static void do_storage_die(UAContext *ua, STORE *store)
371 lstore.store = store;
372 pm_strcpy(lstore.store_source, _("unknown source"));
373 set_wstorage(jcr, &lstore);
374 /* Try connecting for up to 15 seconds */
375 ua->send_msg(_("Connecting to Storage daemon %s at %s:%d\n"),
376 store->name(), store->address, store->SDport);
377 if (!connect_to_storage_daemon(jcr, 1, 15, 0)) {
378 ua->error_msg(_("Failed to connect to Storage daemon.\n"));
381 Dmsg0(120, _("Connected to storage daemon\n"));
382 sd = jcr->store_bsock;
384 if (sd->recv() >= 0) {
385 ua->send_msg("%s", sd->msg);
387 sd->signal(BNET_TERMINATE);
389 jcr->store_bsock = NULL;
393 static void do_client_die(UAContext *ua, CLIENT *client)
397 /* Connect to File daemon */
399 ua->jcr->client = client;
400 /* Try to connect for 15 seconds */
401 ua->send_msg(_("Connecting to Client %s at %s:%d\n"),
402 client->name(), client->address, client->FDport);
403 if (!connect_to_file_daemon(ua->jcr, 1, 15, 0)) {
404 ua->error_msg(_("Failed to connect to Client.\n"));
407 Dmsg0(120, "Connected to file daemon\n");
408 fd = ua->jcr->file_bsock;
410 if (fd->recv() >= 0) {
411 ua->send_msg("%s", fd->msg);
413 fd->signal(BNET_TERMINATE);
415 ua->jcr->file_bsock = NULL;
420 * Create segmentation fault
422 static bool diecmd(UAContext *ua, const char *cmd)
430 Dmsg1(120, "diecmd:%s:\n", cmd);
433 for (i=1; i<ua->argc; i++) {
434 if (strcasecmp(ua->argk[i], "dir") == 0 ||
435 strcasecmp(ua->argk[i], "director") == 0) {
436 ua->send_msg(_("The Director will segment fault.\n"));
437 a = jcr->JobId; /* ref NULL pointer */
438 jcr->JobId = 1000; /* another ref NULL pointer */
441 if (strcasecmp(ua->argk[i], "client") == 0 ||
442 strcasecmp(ua->argk[i], "fd") == 0) {
445 client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[i]);
447 do_client_die(ua, client);
451 client = select_client_resource(ua);
453 do_client_die(ua, client);
458 if (strcasecmp(ua->argk[i], NT_("store")) == 0 ||
459 strcasecmp(ua->argk[i], NT_("storage")) == 0 ||
460 strcasecmp(ua->argk[i], NT_("sd")) == 0) {
463 store = (STORE *)GetResWithName(R_STORAGE, ua->argv[i]);
465 do_storage_die(ua, store);
469 store = get_storage_resource(ua, false/*no default*/);
471 do_storage_die(ua, store);
477 * We didn't find an appropriate keyword above, so
480 start_prompt(ua, _("Available daemons are: \n"));
481 add_prompt(ua, _("Director"));
482 add_prompt(ua, _("Storage"));
483 add_prompt(ua, _("Client"));
484 switch(do_prompt(ua, "", _("Select daemon type to make die"), NULL, 0)) {
485 case 0: /* Director */
486 ua->send_msg(_("The Director will segment fault.\n"));
487 a = jcr->JobId; /* ref NULL pointer */
488 jcr->JobId = 1000; /* another ref NULL pointer */
491 store = get_storage_resource(ua, false/*no default*/);
493 do_storage_die(ua, store);
497 client = select_client_resource(ua);
499 do_client_die(ua, client);
511 * Dummy routine for non-development version
513 static bool diecmd(UAContext *ua, const char *cmd)
521 * Can use an argument to filter on JobType
524 static bool jobscmd(UAContext *ua, const char *cmd)
529 if ((pos = find_arg_with_value(ua, "type")) >= 0) {
530 type = ua->argv[pos][0];
533 foreach_res(job, R_JOB) {
534 if (!type || type == job->JobType) {
535 if (acl_access_ok(ua, Job_ACL, job->name())) {
536 ua->send_msg("%s\n", job->name());
544 static bool filesetscmd(UAContext *ua, const char *cmd)
548 foreach_res(fs, R_FILESET) {
549 if (acl_access_ok(ua, FileSet_ACL, fs->name())) {
550 ua->send_msg("%s\n", fs->name());
557 static bool clientscmd(UAContext *ua, const char *cmd)
561 foreach_res(client, R_CLIENT) {
562 if (acl_access_ok(ua, Client_ACL, client->name())) {
563 ua->send_msg("%s\n", client->name());
570 static bool msgscmd(UAContext *ua, const char *cmd)
574 foreach_res(msgs, R_MSGS) {
575 ua->send_msg("%s\n", msgs->name());
581 static bool poolscmd(UAContext *ua, const char *cmd)
585 foreach_res(pool, R_POOL) {
586 if (acl_access_ok(ua, Pool_ACL, pool->name())) {
587 ua->send_msg("%s\n", pool->name());
594 static bool storagecmd(UAContext *ua, const char *cmd)
598 foreach_res(store, R_STORAGE) {
599 if (acl_access_ok(ua, Storage_ACL, store->name())) {
600 ua->send_msg("%s\n", store->name());
607 static bool aopcmd(UAContext *ua, const char *cmd)
609 ua->send_msg("None\n");
610 ua->send_msg("Truncate\n");
614 static bool typescmd(UAContext *ua, const char *cmd)
616 ua->send_msg("Backup\n");
617 ua->send_msg("Restore\n");
618 ua->send_msg("Admin\n");
619 ua->send_msg("Verify\n");
620 ua->send_msg("Migrate\n");
625 * If this command is called, it tells the director that we
626 * are a program that wants a sort of API, and hence,
627 * we will probably suppress certain output, include more
628 * error codes, and most of all send back a good number
629 * of new signals that indicate whether or not the command
632 static bool api_cmd(UAContext *ua, const char *cmd)
635 ua->api = atoi(ua->argk[1]);
642 static int client_backups_handler(void *ctx, int num_field, char **row)
644 UAContext *ua = (UAContext *)ctx;
645 ua->send_msg("| %s | %s | %s | %s | %s | %s | %s | %s |\n",
646 row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8]);
651 * Return the backups for this client
653 * .backups client=xxx fileset=yyy
656 static bool backupscmd(UAContext *ua, const char *cmd)
658 if (!open_client_db(ua)) {
661 if (ua->argc != 3 || strcmp(ua->argk[1], "client") != 0 ||
662 strcmp(ua->argk[2], "fileset") != 0) {
665 if (!acl_access_ok(ua, Client_ACL, ua->argv[1]) ||
666 !acl_access_ok(ua, FileSet_ACL, ua->argv[2])) {
667 ua->error_msg(_("Access to specified Client or FileSet not allowed.\n"));
670 Mmsg(ua->cmd, client_backups, ua->argv[1], ua->argv[2]);
671 if (!db_sql_query(ua->db, ua->cmd, client_backups_handler, (void *)ua)) {
672 ua->error_msg(_("Query failed: %s. ERR=%s\n"), ua->cmd, db_strerror(ua->db));
678 static int sql_handler(void *ctx, int num_field, char **row)
680 UAContext *ua = (UAContext *)ctx;
681 POOL_MEM rows(PM_MESSAGE);
683 /* Check for nonsense */
684 if (num_field == 0 || row == NULL || row[0] == NULL) {
685 return 0; /* nothing returned */
687 for (int i=0; num_field--; i++) {
689 pm_strcpy(rows, NPRT(row[0]));
691 pm_strcat(rows, NPRT(row[i]));
693 pm_strcat(rows, "\t");
695 if (!rows.c_str() || !*rows.c_str()) {
698 ua->send_msg("%s", rows.c_str());
703 static bool sql_cmd(UAContext *ua, const char *cmd)
706 if (!open_client_db(ua)) {
709 index = find_arg_with_value(ua, "query");
711 ua->error_msg(_("query keyword not found.\n"));
714 if (!db_sql_query(ua->db, ua->argv[index], sql_handler, (void *)ua)) {
715 Dmsg1(100, "Query failed: ERR=%s\n", db_strerror(ua->db));
716 ua->error_msg(_("Query failed: %s. ERR=%s\n"), ua->cmd, db_strerror(ua->db));
722 static int one_handler(void *ctx, int num_field, char **row)
724 UAContext *ua = (UAContext *)ctx;
725 ua->send_msg("%s\n", row[0]);
729 static bool mediatypescmd(UAContext *ua, const char *cmd)
731 if (!open_client_db(ua)) {
734 if (!db_sql_query(ua->db,
735 "SELECT DISTINCT MediaType FROM MediaType ORDER BY MediaType",
736 one_handler, (void *)ua))
738 ua->error_msg(_("List MediaType failed: ERR=%s\n"), db_strerror(ua->db));
743 static bool mediacmd(UAContext *ua, const char *cmd)
745 if (!open_client_db(ua)) {
748 if (!db_sql_query(ua->db,
749 "SELECT DISTINCT Media.VolumeName FROM Media ORDER BY VolumeName",
750 one_handler, (void *)ua))
752 ua->error_msg(_("List Media failed: ERR=%s\n"), db_strerror(ua->db));
757 static bool locationscmd(UAContext *ua, const char *cmd)
759 if (!open_client_db(ua)) {
762 if (!db_sql_query(ua->db,
763 "SELECT DISTINCT Location FROM Location ORDER BY Location",
764 one_handler, (void *)ua))
766 ua->error_msg(_("List Location failed: ERR=%s\n"), db_strerror(ua->db));
771 static bool levelscmd(UAContext *ua, const char *cmd)
773 ua->send_msg("Incremental\n");
774 ua->send_msg("Full\n");
775 ua->send_msg("Differential\n");
776 ua->send_msg("VirtualFull\n");
777 ua->send_msg("Catalog\n");
778 ua->send_msg("InitCatalog\n");
779 ua->send_msg("VolumeToCatalog\n");
780 ua->send_msg("Base\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));