2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2008 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
32 * Kern Sibbald, September MM
42 #undef _POSIX_C_SOURCE
45 #include "lib/pythonlib.h"
47 /* Imported Functions */
48 extern PyObject *job_getattr(PyObject *self, char *attrname);
49 extern int job_setattr(PyObject *self, char *attrname, PyObject *value);
51 #endif /* HAVE_PYTHON */
53 /* Imported subroutines */
55 /* Imported variables */
56 extern jobq_t job_queue; /* job queue */
59 /* Imported functions */
60 extern int autodisplay_cmd(UAContext *ua, const char *cmd);
61 extern int gui_cmd(UAContext *ua, const char *cmd);
62 extern int label_cmd(UAContext *ua, const char *cmd);
63 extern int list_cmd(UAContext *ua, const char *cmd);
64 extern int llist_cmd(UAContext *ua, const char *cmd);
65 extern int messagescmd(UAContext *ua, const char *cmd);
66 extern int prunecmd(UAContext *ua, const char *cmd);
67 extern int purgecmd(UAContext *ua, const char *cmd);
68 extern int querycmd(UAContext *ua, const char *cmd);
69 extern int relabel_cmd(UAContext *ua, const char *cmd);
70 extern int restore_cmd(UAContext *ua, const char *cmd);
71 extern int retentioncmd(UAContext *ua, const char *cmd);
72 extern int show_cmd(UAContext *ua, const char *cmd);
73 extern int sqlquerycmd(UAContext *ua, const char *cmd);
74 extern int status_cmd(UAContext *ua, const char *cmd);
75 extern int update_cmd(UAContext *ua, const char *cmd);
77 /* Forward referenced functions */
78 static int add_cmd(UAContext *ua, const char *cmd);
79 static int automount_cmd(UAContext *ua, const char *cmd);
80 static int cancel_cmd(UAContext *ua, const char *cmd);
81 static int create_cmd(UAContext *ua, const char *cmd);
82 static int delete_cmd(UAContext *ua, const char *cmd);
83 static int disable_cmd(UAContext *ua, const char *cmd);
84 static int enable_cmd(UAContext *ua, const char *cmd);
85 static int estimate_cmd(UAContext *ua, const char *cmd);
86 static int help_cmd(UAContext *ua, const char *cmd);
87 static int memory_cmd(UAContext *ua, const char *cmd);
88 static int mount_cmd(UAContext *ua, const char *cmd);
89 static int python_cmd(UAContext *ua, const char *cmd);
90 static int release_cmd(UAContext *ua, const char *cmd);
91 static int reload_cmd(UAContext *ua, const char *cmd);
92 static int setdebug_cmd(UAContext *ua, const char *cmd);
93 static int setip_cmd(UAContext *ua, const char *cmd);
94 static int time_cmd(UAContext *ua, const char *cmd);
95 static int trace_cmd(UAContext *ua, const char *cmd);
96 static int unmount_cmd(UAContext *ua, const char *cmd);
97 static int use_cmd(UAContext *ua, const char *cmd);
98 static int var_cmd(UAContext *ua, const char *cmd);
99 static int version_cmd(UAContext *ua, const char *cmd);
100 static int wait_cmd(UAContext *ua, const char *cmd);
102 static void do_job_delete(UAContext *ua, JobId_t JobId);
103 static void delete_job_id_range(UAContext *ua, char *tok);
104 static int delete_volume(UAContext *ua);
105 static int delete_pool(UAContext *ua);
106 static void delete_job(UAContext *ua);
108 int qhelp_cmd(UAContext *ua, const char *cmd);
109 int quit_cmd(UAContext *ua, const char *cmd);
112 struct cmdstruct { const char *key; int (*func)(UAContext *ua, const char *cmd); const char *help; const bool use_in_rs;};
113 static struct cmdstruct commands[] = { /* Can use it in Console RunScript*/
114 { NT_("add"), add_cmd, _("add media to a pool"), false},
115 { NT_("autodisplay"), autodisplay_cmd, _("autodisplay [on|off] -- console messages"),false},
116 { NT_("automount"), automount_cmd, _("automount [on|off] -- after label"), false},
117 { NT_("cancel"), cancel_cmd, _("cancel [<jobid=nnn> | <job=name>] -- cancel a job"), false},
118 { NT_("create"), create_cmd, _("create DB Pool from resource"), false},
119 { NT_("delete"), delete_cmd, _("delete [pool=<pool-name> | media volume=<volume-name>]"), true},
120 { NT_("disable"), disable_cmd, _("disable <job=name> -- disable a job"), true},
121 { NT_("enable"), enable_cmd, _("enable <job=name> -- enable a job"), true},
122 { NT_("estimate"), estimate_cmd, _("performs FileSet estimate, listing gives full listing"), true},
123 { NT_("exit"), quit_cmd, _("exit = quit"), false},
124 { NT_("gui"), gui_cmd, _("gui [on|off] -- non-interactive gui mode"), false},
125 { NT_("help"), help_cmd, _("print this command"), false},
126 { NT_("list"), list_cmd, _("list [pools | jobs | jobtotals | media <pool=pool-name> | files <jobid=nn>]; from catalog"), true},
127 { NT_("label"), label_cmd, _("label a tape"), false},
128 { NT_("llist"), llist_cmd, _("full or long list like list command"), true},
129 { NT_("messages"), messagescmd, _("messages"), false},
130 { NT_("memory"), memory_cmd, _("print current memory usage"), true},
131 { NT_("mount"), mount_cmd, _("mount <storage-name>"), false},
132 { NT_("prune"), prunecmd, _("prune expired records from catalog"), true},
133 { NT_("purge"), purgecmd, _("purge records from catalog"), true},
134 { NT_("python"), python_cmd, _("python control commands"), false},
135 { NT_("quit"), quit_cmd, _("quit"), false},
136 { NT_("query"), querycmd, _("query catalog"), false},
137 { NT_("restore"), restore_cmd, _("restore files"), false},
138 { NT_("relabel"), relabel_cmd, _("relabel a tape"), false},
139 { NT_("release"), release_cmd, _("release <storage-name>"), false},
140 { NT_("reload"), reload_cmd, _("reload conf file"), true},
141 { NT_("run"), run_cmd, _("run <job-name>"), false}, /* need to be check */
142 { NT_("status"), status_cmd, _("status [storage | client]=<name>"), true},
143 { NT_("setdebug"), setdebug_cmd, _("sets debug level"), true},
144 { NT_("setip"), setip_cmd, _("sets new client address -- if authorized"), false},
145 { NT_("show"), show_cmd, _("show (resource records) [jobs | pools | ... | all]"), true},
146 { NT_("sqlquery"), sqlquerycmd, _("use SQL to query catalog"), false},
147 { NT_("time"), time_cmd, _("print current time"), true},
148 { NT_("trace"), trace_cmd, _("turn on/off trace to file"), true},
149 { NT_("unmount"), unmount_cmd, _("unmount <storage-name>"), false},
150 { NT_("umount"), unmount_cmd, _("umount <storage-name> for old-time Unix guys"),false},
151 { NT_("update"), update_cmd, _("update Volume, Pool or slots"), true},
152 { NT_("use"), use_cmd, _("use catalog xxx"), false},
153 { NT_("var"), var_cmd, _("does variable expansion"), false},
154 { NT_("version"), version_cmd, _("print Director version"), true},
155 { NT_("wait"), wait_cmd, _("wait until no jobs are running [<jobname=name> | <jobid=nnn> | <ujobid=complete_name>]"), false},
157 #define comsize (sizeof(commands)/sizeof(struct cmdstruct))
160 * Execute a command from the UA
162 bool do_a_command(UAContext *ua)
168 BSOCK *user = ua->UA_sock;
171 Dmsg1(900, "Command: %s\n", ua->argk[0]);
176 while (ua->jcr->wstorage->size()) {
177 ua->jcr->wstorage->remove(0);
180 len = strlen(ua->argk[0]);
181 for (i=0; i<comsize; i++) { /* search for command */
182 if (strncasecmp(ua->argk[0], commands[i].key, len) == 0) {
183 /* Check if command permitted, but "quit" is always OK */
184 if (strcmp(ua->argk[0], NT_("quit")) != 0 &&
185 !acl_access_ok(ua, Command_ACL, ua->argk[0], len)) {
188 /* Check if this command is authorized in RunScript */
189 if (ua->runscript && !commands[i].use_in_rs) {
190 ua->error_msg(_("Can't use %s command in a runscript"), ua->argk[0]);
193 if (ua->api) user->signal(BNET_CMD_BEGIN);
194 ok = (*commands[i].func)(ua, ua->cmd); /* go execute command */
200 ua->error_msg(_("%s: is an invalid command.\n"), ua->argk[0]);
203 if (ua->api) user->signal(ok?BNET_CMD_OK:BNET_CMD_FAILED);
208 * This is a common routine used to stuff the Pool DB record defaults
209 * into the Media DB record just before creating a media (Volume)
212 void set_pool_dbr_defaults_in_media_dbr(MEDIA_DBR *mr, POOL_DBR *pr)
214 mr->PoolId = pr->PoolId;
215 bstrncpy(mr->VolStatus, NT_("Append"), sizeof(mr->VolStatus));
216 mr->Recycle = pr->Recycle;
217 mr->VolRetention = pr->VolRetention;
218 mr->VolUseDuration = pr->VolUseDuration;
219 mr->RecyclePoolId = pr->RecyclePoolId;
220 mr->MaxVolJobs = pr->MaxVolJobs;
221 mr->MaxVolFiles = pr->MaxVolFiles;
222 mr->MaxVolBytes = pr->MaxVolBytes;
223 mr->LabelType = pr->LabelType;
229 * Add Volumes to an existing Pool
231 static int add_cmd(UAContext *ua, const char *cmd)
235 int num, i, max, startnum;
237 char name[MAX_NAME_LENGTH];
239 int Slot = 0, InChanger = 0;
242 "You probably don't want to be using this command since it\n"
243 "creates database records without labeling the Volumes.\n"
244 "You probably want to use the \"label\" command.\n\n"));
246 if (!open_client_db(ua)) {
250 memset(&pr, 0, sizeof(pr));
251 memset(&mr, 0, sizeof(mr));
253 if (!get_pool_dbr(ua, &pr)) {
257 Dmsg4(120, "id=%d Num=%d Max=%d type=%s\n", pr.PoolId, pr.NumVols,
258 pr.MaxVols, pr.PoolType);
260 while (pr.MaxVols > 0 && pr.NumVols >= pr.MaxVols) {
261 ua->warning_msg(_("Pool already has maximum volumes=%d\n"), pr.MaxVols);
262 if (!get_pint(ua, _("Enter new maximum (zero for unlimited): "))) {
265 pr.MaxVols = ua->pint32_val;
269 if ((store = get_storage_resource(ua, false/*no default*/)) != NULL) {
270 bstrncpy(mr.MediaType, store->media_type, sizeof(mr.MediaType));
271 } else if (!get_media_type(ua, mr.MediaType, sizeof(mr.MediaType))) {
275 if (pr.MaxVols == 0) {
278 max = pr.MaxVols - pr.NumVols;
282 bsnprintf(buf, sizeof(buf), _("Enter number of Volumes to create. 0=>fixed name. Max=%d: "), max);
283 if (!get_pint(ua, buf)) {
286 num = ua->pint32_val;
287 if (num < 0 || num > max) {
288 ua->warning_msg(_("The number must be between 0 and %d\n"), max);
296 if (!get_cmd(ua, _("Enter Volume name: "))) {
300 if (!get_cmd(ua, _("Enter base volume name: "))) {
304 /* Don't allow | in Volume name because it is the volume separator character */
305 if (!is_volume_name_legal(ua, ua->cmd)) {
308 if (strlen(ua->cmd) >= MAX_NAME_LENGTH-10) {
309 ua->warning_msg(_("Volume name too long.\n"));
312 if (strlen(ua->cmd) == 0) {
313 ua->warning_msg(_("Volume name must be at least one character long.\n"));
319 bstrncpy(name, ua->cmd, sizeof(name));
321 bstrncat(name, "%04d", sizeof(name));
324 if (!get_pint(ua, _("Enter the starting number: "))) {
327 startnum = ua->pint32_val;
329 ua->warning_msg(_("Start number must be greater than zero.\n"));
339 if (store && store->autochanger) {
340 if (!get_pint(ua, _("Enter slot (0 for none): "))) {
343 Slot = ua->pint32_val;
344 if (!get_yesno(ua, _("InChanger? yes/no: "))) {
347 InChanger = ua->pint32_val;
350 set_pool_dbr_defaults_in_media_dbr(&mr, &pr);
351 for (i=startnum; i < num+startnum; i++) {
352 bsnprintf(mr.VolumeName, sizeof(mr.VolumeName), name, i);
354 mr.InChanger = InChanger;
355 mr.StorageId = store->StorageId;
357 Dmsg1(200, "Create Volume %s\n", mr.VolumeName);
358 if (!db_create_media_record(ua->jcr, ua->db, &mr)) {
359 ua->error_msg("%s", db_strerror(ua->db));
363 first_id = mr.PoolId;
367 Dmsg0(200, "Update pool record.\n");
368 if (db_update_pool_record(ua->jcr, ua->db, &pr) != 1) {
369 ua->warning_msg("%s", db_strerror(ua->db));
372 ua->send_msg(_("%d Volumes created in pool %s\n"), num, pr.Name);
378 * Turn auto mount on/off
383 int automount_cmd(UAContext *ua, const char *cmd)
388 if (!get_cmd(ua, _("Turn on or off? "))) {
396 ua->automount = (strcasecmp(onoff, NT_("off")) == 0) ? 0 : 1;
404 static int cancel_cmd(UAContext *ua, const char *cmd)
409 char JobName[MAX_NAME_LENGTH];
411 for (i=1; i<ua->argc; i++) {
412 if (strcasecmp(ua->argk[i], NT_("jobid")) == 0) {
417 JobId = str_to_int64(ua->argv[i]);
418 if (!(jcr=get_jcr_by_id(JobId))) {
419 ua->error_msg(_("JobId %s is not running. Use Job name to cancel inactive jobs.\n"), ua->argv[i]);
423 } else if (strcasecmp(ua->argk[i], NT_("job")) == 0) {
427 if (!(jcr=get_jcr_by_partial_name(ua->argv[i]))) {
428 ua->warning_msg(_("Warning Job %s is not running. Continuing anyway ...\n"), ua->argv[i]);
429 jcr = new_jcr(sizeof(JCR), dird_free_jcr);
430 bstrncpy(jcr->Job, ua->argv[i], sizeof(jcr->Job));
433 } else if (strcasecmp(ua->argk[i], NT_("ujobid")) == 0) {
437 if (!(jcr=get_jcr_by_full_name(ua->argv[i]))) {
438 ua->warning_msg(_("Warning Job %s is not running. Continuing anyway ...\n"), ua->argv[i]);
439 jcr = new_jcr(sizeof(JCR), dird_free_jcr);
440 bstrncpy(jcr->Job, ua->argv[i], sizeof(jcr->Job));
447 if (jcr->job && !acl_access_ok(ua, Job_ACL, jcr->job->name())) {
448 ua->error_msg(_("Unauthorized command from this console.\n"));
453 * If we still do not have a jcr,
454 * throw up a list and ask the user to select one.
457 int tjobs = 0; /* total # number jobs */
458 /* Count Jobs running */
460 if (jcr->JobId == 0) { /* this is us */
463 tjobs++; /* count of all jobs */
464 if (!acl_access_ok(ua, Job_ACL, jcr->job->name())) {
465 continue; /* skip not authorized */
467 njobs++; /* count of authorized jobs */
471 if (njobs == 0) { /* no authorized */
473 ua->send_msg(_("No Jobs running.\n"));
475 ua->send_msg(_("None of your jobs are running.\n"));
480 start_prompt(ua, _("Select Job:\n"));
483 if (jcr->JobId == 0) { /* this is us */
486 if (!acl_access_ok(ua, Job_ACL, jcr->job->name())) {
487 continue; /* skip not authorized */
489 bsnprintf(buf, sizeof(buf), _("JobId=%s Job=%s"), edit_int64(jcr->JobId, ed1), jcr->Job);
494 if (do_prompt(ua, _("Job"), _("Choose Job to cancel"), buf, sizeof(buf)) < 0) {
497 if (ua->api && njobs == 1) {
499 bsnprintf(nbuf, sizeof(nbuf), _("Cancel: %s\n\n%s"), buf,
500 _("Confirm cancel?"));
501 if (!get_yesno(ua, nbuf) || ua->pint32_val == 0) {
506 if (!get_yesno(ua, _("Confirm cancel (yes/no): ")) || ua->pint32_val == 0) {
511 sscanf(buf, "JobId=%d Job=%127s", &njobs, JobName);
512 jcr = get_jcr_by_full_name(JobName);
514 ua->warning_msg(_("Job \"%s\" not found.\n"), JobName);
519 ret = cancel_job(ua, jcr);
525 * This is a common routine to create or update a
526 * Pool DB base record from a Pool Resource. We handle
527 * the setting of MaxVols and NumVols slightly differently
528 * depending on if we are creating the Pool or we are
529 * simply bringing it into agreement with the resource (updage).
531 * Caution : RecyclePoolId isn't setup in this function.
532 * You can use set_pooldbr_recyclepoolid();
535 void set_pooldbr_from_poolres(POOL_DBR *pr, POOL *pool, e_pool_op op)
537 bstrncpy(pr->PoolType, pool->pool_type, sizeof(pr->PoolType));
538 if (op == POOL_OP_CREATE) {
539 pr->MaxVols = pool->max_volumes;
541 } else { /* update pool */
542 if (pr->MaxVols != pool->max_volumes) {
543 pr->MaxVols = pool->max_volumes;
545 if (pr->MaxVols != 0 && pr->MaxVols < pr->NumVols) {
546 pr->MaxVols = pr->NumVols;
549 pr->LabelType = pool->LabelType;
550 pr->UseOnce = pool->use_volume_once;
551 pr->UseCatalog = pool->use_catalog;
552 pr->Recycle = pool->Recycle;
553 pr->VolRetention = pool->VolRetention;
554 pr->VolUseDuration = pool->VolUseDuration;
555 pr->MaxVolJobs = pool->MaxVolJobs;
556 pr->MaxVolFiles = pool->MaxVolFiles;
557 pr->MaxVolBytes = pool->MaxVolBytes;
558 pr->AutoPrune = pool->AutoPrune;
559 pr->Recycle = pool->Recycle;
560 if (pool->label_format) {
561 bstrncpy(pr->LabelFormat, pool->label_format, sizeof(pr->LabelFormat));
563 bstrncpy(pr->LabelFormat, "*", sizeof(pr->LabelFormat)); /* none */
567 /* set/update Pool.RecyclePoolId in Catalog */
568 int update_pool_recyclepool(JCR *jcr, B_DB *db, POOL *pool)
572 if (!pool->RecyclePool) {
576 memset(&pr, 0, sizeof(POOL_DBR));
577 bstrncpy(pr.Name, pool->name(), sizeof(pr.Name));
579 if (!db_get_pool_record(jcr, db, &pr)) {
580 return -1; /* not exists in database */
583 set_pooldbr_from_poolres(&pr, pool, POOL_OP_UPDATE);
585 if (!set_pooldbr_recyclepoolid(jcr, db, &pr, pool)) {
586 return -1; /* error */
589 if (!db_update_pool_record(jcr, db, &pr)) {
590 return -1; /* error */
595 /* set POOL_DBR.RecyclePoolId from Pool resource
596 * works with set_pooldbr_from_poolres
598 bool set_pooldbr_recyclepoolid(JCR *jcr, B_DB *db, POOL_DBR *pr, POOL *pool)
603 if (pool->RecyclePool) {
604 memset(&rpool, 0, sizeof(POOL_DBR));
606 bstrncpy(rpool.Name, pool->RecyclePool->name(), sizeof(rpool.Name));
607 if (db_get_pool_record(jcr, db, &rpool)) {
608 pr->RecyclePoolId = rpool.PoolId;
610 Jmsg(jcr, M_WARNING, 0,
611 _("Can't set %s RecyclePool to %s, %s is not in database.\n" \
612 "Try to update it with 'update pool=%s'\n"),
613 pool->name(), rpool.Name, rpool.Name,pool->name());
617 } else { /* no RecyclePool used, set it to 0 */
618 pr->RecyclePoolId = 0;
625 * Create a pool record from a given Pool resource
626 * Also called from backup.c
627 * Returns: -1 on error
628 * 0 record already exists
632 int create_pool(JCR *jcr, B_DB *db, POOL *pool, e_pool_op op)
636 memset(&pr, 0, sizeof(POOL_DBR));
638 bstrncpy(pr.Name, pool->name(), sizeof(pr.Name));
640 if (db_get_pool_record(jcr, db, &pr)) {
642 if (op == POOL_OP_UPDATE) { /* update request */
643 set_pooldbr_from_poolres(&pr, pool, op);
644 db_update_pool_record(jcr, db, &pr);
646 return 0; /* exists */
649 set_pooldbr_from_poolres(&pr, pool, op);
651 if (!db_create_pool_record(jcr, db, &pr)) {
652 return -1; /* error */
660 * Create a Pool Record in the database.
661 * It is always created from the Resource record.
663 static int create_cmd(UAContext *ua, const char *cmd)
667 if (!open_client_db(ua)) {
671 pool = get_pool_resource(ua);
676 switch (create_pool(ua->jcr, ua->db, pool, POOL_OP_CREATE)) {
678 ua->error_msg(_("Error: Pool %s already exists.\n"
679 "Use update to change it.\n"), pool->name());
683 ua->error_msg("%s", db_strerror(ua->db));
689 ua->send_msg(_("Pool %s created.\n"), pool->name());
694 extern DIRRES *director;
695 extern char *configfile;
698 * Python control command
699 * python restart (restarts interpreter)
701 static int python_cmd(UAContext *ua, const char *cmd)
704 init_python_interpreter_args python_args;
706 if (ua->argc >= 2 && strcasecmp(ua->argk[1], NT_("restart")) == 0) {
707 term_python_interpreter();
709 python_args.progname = director->name();
710 python_args.scriptdir = director->scripts_directory;
711 python_args.modulename = "DirStartUp";
712 python_args.configfile = configfile;
713 python_args.workingdir = director->working_directory;
714 python_args.job_getattr = job_getattr;
715 python_args.job_setattr = job_setattr;
717 init_python_interpreter(&python_args);
719 ua->send_msg(_("Python interpreter restarted.\n"));
721 #endif /* HAVE_PYTHON */
722 ua->warning_msg(_("Nothing done.\n"));
725 #endif /* HAVE_PYTHON */
731 * Set a new address in a Client resource. We do this only
732 * if the Console name is the same as the Client name
733 * and the Console can access the client.
735 static int setip_cmd(UAContext *ua, const char *cmd)
739 if (!ua->cons || !acl_access_ok(ua, Client_ACL, ua->cons->name())) {
740 ua->error_msg(_("Unauthorized command from this console.\n"));
744 client = GetClientResWithName(ua->cons->name());
747 ua->error_msg(_("Client \"%s\" not found.\n"), ua->cons->name());
750 if (client->address) {
751 free(client->address);
753 /* MA Bug 6 remove ifdef */
754 sockaddr_to_ascii(&(ua->UA_sock->client_addr), buf, sizeof(buf));
755 client->address = bstrdup(buf);
756 ua->send_msg(_("Client \"%s\" address set to %s\n"),
757 client->name(), client->address);
764 static void do_en_disable_cmd(UAContext *ua, bool setting)
769 i = find_arg_with_value(ua, NT_("job"));
771 job = select_job_resource(ua);
777 job = GetJobResWithName(ua->argv[i]);
781 ua->error_msg(_("Job \"%s\" not found.\n"), ua->argv[i]);
785 if (!acl_access_ok(ua, Job_ACL, job->name())) {
786 ua->error_msg(_("Unauthorized command from this console.\n"));
789 job->enabled = setting;
790 ua->send_msg(_("Job \"%s\" %sabled\n"), job->name(), setting?"en":"dis");
794 static int enable_cmd(UAContext *ua, const char *cmd)
796 do_en_disable_cmd(ua, true);
800 static int disable_cmd(UAContext *ua, const char *cmd)
802 do_en_disable_cmd(ua, false);
807 static void do_storage_setdebug(UAContext *ua, STORE *store, int level, int trace_flag)
813 lstore.store = store;
814 pm_strcpy(lstore.store_source, _("unknown source"));
815 set_wstorage(jcr, &lstore);
816 /* Try connecting for up to 15 seconds */
817 ua->send_msg(_("Connecting to Storage daemon %s at %s:%d\n"),
818 store->name(), store->address, store->SDport);
819 if (!connect_to_storage_daemon(jcr, 1, 15, 0)) {
820 ua->error_msg(_("Failed to connect to Storage daemon.\n"));
823 Dmsg0(120, _("Connected to storage daemon\n"));
824 sd = jcr->store_bsock;
825 sd->fsend("setdebug=%d trace=%d\n", level, trace_flag);
826 if (sd->recv() >= 0) {
827 ua->send_msg("%s", sd->msg);
829 sd->signal(BNET_TERMINATE);
831 jcr->store_bsock = NULL;
835 static void do_client_setdebug(UAContext *ua, CLIENT *client, int level, int trace_flag)
839 /* Connect to File daemon */
841 ua->jcr->client = client;
842 /* Try to connect for 15 seconds */
843 ua->send_msg(_("Connecting to Client %s at %s:%d\n"),
844 client->name(), client->address, client->FDport);
845 if (!connect_to_file_daemon(ua->jcr, 1, 15, 0)) {
846 ua->error_msg(_("Failed to connect to Client.\n"));
849 Dmsg0(120, "Connected to file daemon\n");
850 fd = ua->jcr->file_bsock;
851 fd->fsend("setdebug=%d trace=%d\n", level, trace_flag);
852 if (fd->recv() >= 0) {
853 ua->send_msg("%s", fd->msg);
855 fd->signal(BNET_TERMINATE);
857 ua->jcr->file_bsock = NULL;
862 static void do_all_setdebug(UAContext *ua, int level, int trace_flag)
864 STORE *store, **unique_store;
865 CLIENT *client, **unique_client;
871 /* Count Storage items */
875 foreach_res(store, R_STORAGE) {
878 unique_store = (STORE **) malloc(i * sizeof(STORE));
879 /* Find Unique Storage address/port */
880 store = (STORE *)GetNextRes(R_STORAGE, NULL);
882 unique_store[i++] = store;
883 while ((store = (STORE *)GetNextRes(R_STORAGE, (RES *)store))) {
885 for (j=0; j<i; j++) {
886 if (strcmp(unique_store[j]->address, store->address) == 0 &&
887 unique_store[j]->SDport == store->SDport) {
893 unique_store[i++] = store;
894 Dmsg2(140, "Stuffing: %s:%d\n", store->address, store->SDport);
899 /* Call each unique Storage daemon */
900 for (j=0; j<i; j++) {
901 do_storage_setdebug(ua, unique_store[j], level, trace_flag);
905 /* Count Client items */
909 foreach_res(client, R_CLIENT) {
912 unique_client = (CLIENT **) malloc(i * sizeof(CLIENT));
913 /* Find Unique Client address/port */
914 client = (CLIENT *)GetNextRes(R_CLIENT, NULL);
916 unique_client[i++] = client;
917 while ((client = (CLIENT *)GetNextRes(R_CLIENT, (RES *)client))) {
919 for (j=0; j<i; j++) {
920 if (strcmp(unique_client[j]->address, client->address) == 0 &&
921 unique_client[j]->FDport == client->FDport) {
927 unique_client[i++] = client;
928 Dmsg2(140, "Stuffing: %s:%d\n", client->address, client->FDport);
933 /* Call each unique File daemon */
934 for (j=0; j<i; j++) {
935 do_client_setdebug(ua, unique_client[j], level, trace_flag);
941 * setdebug level=nn all trace=1/0
943 static int setdebug_cmd(UAContext *ua, const char *cmd)
951 Dmsg1(120, "setdebug:%s:\n", cmd);
954 i = find_arg_with_value(ua, "level");
956 level = atoi(ua->argv[i]);
959 if (!get_pint(ua, _("Enter new debug level: "))) {
962 level = ua->pint32_val;
965 /* Look for trace flag. -1 => not change */
966 i = find_arg_with_value(ua, "trace");
968 trace_flag = atoi(ua->argv[i]);
969 if (trace_flag > 0) {
975 for (i=1; i<ua->argc; i++) {
976 if (strcasecmp(ua->argk[i], "all") == 0) {
977 do_all_setdebug(ua, level, trace_flag);
980 if (strcasecmp(ua->argk[i], "dir") == 0 ||
981 strcasecmp(ua->argk[i], "director") == 0) {
983 set_trace(trace_flag);
986 if (strcasecmp(ua->argk[i], "client") == 0 ||
987 strcasecmp(ua->argk[i], "fd") == 0) {
990 client = GetClientResWithName(ua->argv[i]);
992 do_client_setdebug(ua, client, level, trace_flag);
996 client = select_client_resource(ua);
998 do_client_setdebug(ua, client, level, trace_flag);
1003 if (strcasecmp(ua->argk[i], NT_("store")) == 0 ||
1004 strcasecmp(ua->argk[i], NT_("storage")) == 0 ||
1005 strcasecmp(ua->argk[i], NT_("sd")) == 0) {
1008 store = GetStoreResWithName(ua->argv[i]);
1010 do_storage_setdebug(ua, store, level, trace_flag);
1014 store = get_storage_resource(ua, false/*no default*/);
1016 do_storage_setdebug(ua, store, level, trace_flag);
1022 * We didn't find an appropriate keyword above, so
1025 start_prompt(ua, _("Available daemons are: \n"));
1026 add_prompt(ua, _("Director"));
1027 add_prompt(ua, _("Storage"));
1028 add_prompt(ua, _("Client"));
1029 add_prompt(ua, _("All"));
1030 switch(do_prompt(ua, "", _("Select daemon type to set debug level"), NULL, 0)) {
1031 case 0: /* Director */
1032 debug_level = level;
1033 set_trace(trace_flag);
1036 store = get_storage_resource(ua, false/*no default*/);
1038 do_storage_setdebug(ua, store, level, trace_flag);
1042 client = select_client_resource(ua);
1044 do_client_setdebug(ua, client, level, trace_flag);
1048 do_all_setdebug(ua, level, trace_flag);
1057 * Turn debug tracing to file on/off
1059 static int trace_cmd(UAContext *ua, const char *cmd)
1063 if (ua->argc != 2) {
1064 if (!get_cmd(ua, _("Turn on or off? "))) {
1069 onoff = ua->argk[1];
1072 set_trace((strcasecmp(onoff, NT_("off")) == 0) ? false : true);
1077 static int var_cmd(UAContext *ua, const char *cmd)
1079 POOLMEM *val = get_pool_memory(PM_FNAME);
1082 if (!open_client_db(ua)) {
1085 for (var=ua->cmd; *var != ' '; ) { /* skip command */
1088 while (*var == ' ') { /* skip spaces */
1091 Dmsg1(100, "Var=%s:\n", var);
1092 variable_expansion(ua->jcr, var, &val);
1093 ua->send_msg("%s\n", val);
1094 free_pool_memory(val);
1098 static int estimate_cmd(UAContext *ua, const char *cmd)
1101 CLIENT *client = NULL;
1102 FILESET *fileset = NULL;
1104 char since[MAXSTRING];
1107 jcr->set_JobLevel(L_FULL);
1108 for (int i=1; i<ua->argc; i++) {
1109 if (strcasecmp(ua->argk[i], NT_("client")) == 0 ||
1110 strcasecmp(ua->argk[i], NT_("fd")) == 0) {
1112 client = GetClientResWithName(ua->argv[i]);
1114 ua->error_msg(_("Client \"%s\" not found.\n"), ua->argv[i]);
1119 ua->error_msg(_("Client name missing.\n"));
1123 if (strcasecmp(ua->argk[i], NT_("job")) == 0) {
1125 job = GetJobResWithName(ua->argv[i]);
1127 ua->error_msg(_("Job \"%s\" not found.\n"), ua->argv[i]);
1130 if (!acl_access_ok(ua, Job_ACL, job->name())) {
1131 ua->error_msg(_("No authorization for Job \"%s\"\n"), job->name());
1136 ua->error_msg(_("Job name missing.\n"));
1141 if (strcasecmp(ua->argk[i], NT_("fileset")) == 0) {
1143 fileset = GetFileSetResWithName(ua->argv[i]);
1145 ua->error_msg(_("Fileset \"%s\" not found.\n"), ua->argv[i]);
1148 if (!acl_access_ok(ua, FileSet_ACL, fileset->name())) {
1149 ua->error_msg(_("No authorization for FileSet \"%s\"\n"), fileset->name());
1154 ua->error_msg(_("Fileset name missing.\n"));
1158 if (strcasecmp(ua->argk[i], NT_("listing")) == 0) {
1162 if (strcasecmp(ua->argk[i], NT_("level")) == 0) {
1164 if (!get_level_from_name(ua->jcr, ua->argv[i])) {
1165 ua->error_msg(_("Level \"%s\" not valid.\n"), ua->argv[i]);
1169 ua->error_msg(_("Level value missing.\n"));
1174 if (!job && !(client && fileset)) {
1175 if (!(job = select_job_resource(ua))) {
1180 job = GetJobResWithName(ua->argk[1]);
1182 ua->error_msg(_("No job specified.\n"));
1185 if (!acl_access_ok(ua, Job_ACL, job->name())) {
1186 ua->error_msg(_("No authorization for Job \"%s\"\n"), job->name());
1191 client = job->client;
1194 fileset = job->fileset;
1196 jcr->client = client;
1197 jcr->fileset = fileset;
1199 if (job->pool->catalog) {
1200 ua->catalog = job->pool->catalog;
1202 ua->catalog = client->catalog;
1210 jcr->set_JobType(JT_BACKUP);
1211 init_jcr_job_record(jcr);
1213 if (!get_or_create_client_record(jcr)) {
1216 if (!get_or_create_fileset_record(jcr)) {
1220 get_level_since_time(ua->jcr, since, sizeof(since));
1222 ua->send_msg(_("Connecting to Client %s at %s:%d\n"),
1223 jcr->client->name(), jcr->client->address, jcr->client->FDport);
1224 if (!connect_to_file_daemon(jcr, 1, 15, 0)) {
1225 ua->error_msg(_("Failed to connect to Client.\n"));
1229 if (!send_include_list(jcr)) {
1230 ua->error_msg(_("Error sending include list.\n"));
1234 if (!send_exclude_list(jcr)) {
1235 ua->error_msg(_("Error sending exclude list.\n"));
1239 if (!send_level_command(jcr)) {
1243 bnet_fsend(jcr->file_bsock, "estimate listing=%d\n", listing);
1244 while (bnet_recv(jcr->file_bsock) >= 0) {
1245 ua->send_msg("%s", jcr->file_bsock->msg);
1249 if (jcr->file_bsock) {
1250 bnet_sig(jcr->file_bsock, BNET_TERMINATE);
1251 bnet_close(jcr->file_bsock);
1252 jcr->file_bsock = NULL;
1261 static int time_cmd(UAContext *ua, const char *cmd)
1264 time_t ttime = time(NULL);
1266 (void)localtime_r(&ttime, &tm);
1267 strftime(sdt, sizeof(sdt), "%d-%b-%Y %H:%M:%S", &tm);
1268 ua->send_msg("%s\n", sdt);
1273 * reload the conf file
1275 extern "C" void reload_config(int sig);
1277 static int reload_cmd(UAContext *ua, const char *cmd)
1284 * Delete Pool records (should purge Media with it).
1286 * delete pool=<pool-name>
1287 * delete volume pool=<pool-name> volume=<name>
1290 static int delete_cmd(UAContext *ua, const char *cmd)
1292 static const char *keywords[] = {
1298 if (!open_client_db(ua)) {
1302 switch (find_arg_keyword(ua, keywords)) {
1311 while ((i=find_arg(ua, "jobid")) > 0) {
1313 *ua->argk[i] = 0; /* zap keyword already visited */
1321 "In general it is not a good idea to delete either a\n"
1322 "Pool or a Volume since they may contain data.\n\n"));
1324 switch (do_keyword_prompt(ua, _("Choose catalog item to delete"), keywords)) {
1335 ua->warning_msg(_("Nothing done.\n"));
1343 * delete_job has been modified to parse JobID lists like the
1345 * delete JobID=3,4,6,7-11,14
1347 * Thanks to Phil Stracchino for the above addition.
1350 static void delete_job(UAContext *ua)
1355 int i = find_arg_with_value(ua, NT_("jobid"));
1357 if (strchr(ua->argv[i], ',') != NULL || strchr(ua->argv[i], '-') != NULL) {
1358 s = bstrdup(ua->argv[i]);
1361 * We could use strtok() here. But we're not going to, because:
1362 * (a) strtok() is deprecated, having been replaced by strsep();
1363 * (b) strtok() is broken in significant ways.
1364 * we could use strsep() instead, but it's not universally available.
1365 * so we grow our own using strchr().
1367 sep = strchr(tok, ',');
1368 while (sep != NULL) {
1370 if (strchr(tok, '-')) {
1371 delete_job_id_range(ua, tok);
1373 JobId = str_to_int64(tok);
1374 do_job_delete(ua, JobId);
1377 sep = strchr(tok, ',');
1379 /* pick up the last token */
1380 if (strchr(tok, '-')) {
1381 delete_job_id_range(ua, tok);
1383 JobId = str_to_int64(tok);
1384 do_job_delete(ua, JobId);
1389 JobId = str_to_int64(ua->argv[i]);
1390 do_job_delete(ua, JobId);
1392 } else if (!get_pint(ua, _("Enter JobId to delete: "))) {
1395 JobId = ua->int64_val;
1396 do_job_delete(ua, JobId);
1401 * we call delete_job_id_range to parse range tokens and iterate over ranges
1403 static void delete_job_id_range(UAContext *ua, char *tok)
1408 tok2 = strchr(tok, '-');
1411 j1 = str_to_int64(tok);
1412 j2 = str_to_int64(tok2);
1413 for (j=j1; j<=j2; j++) {
1414 do_job_delete(ua, j);
1419 * do_job_delete now performs the actual delete operation atomically
1421 static void do_job_delete(UAContext *ua, JobId_t JobId)
1425 edit_int64(JobId, ed1);
1426 purge_jobs_from_catalog(ua, ed1);
1427 ua->send_msg(_("Job %s and associated records deleted from the catalog.\n"), ed1);
1431 * Delete media records from database -- dangerous
1433 static int delete_volume(UAContext *ua)
1438 if (!select_media_dbr(ua, &mr)) {
1441 ua->warning_msg(_("\nThis command will delete volume %s\n"
1442 "and all Jobs saved on that volume from the Catalog\n"),
1445 if (find_arg(ua, "yes") >= 0) {
1446 ua->pint32_val = 1; /* Have "yes" on command line already" */
1448 bsnprintf(buf, sizeof(buf), _("Are you sure you want to delete Volume \"%s\"? (yes/no): "),
1450 if (!get_yesno(ua, buf)) {
1454 if (ua->pint32_val) {
1455 db_delete_media_record(ua->jcr, ua->db, &mr);
1461 * Delete a pool record from the database -- dangerous
1463 static int delete_pool(UAContext *ua)
1468 memset(&pr, 0, sizeof(pr));
1470 if (!get_pool_dbr(ua, &pr)) {
1473 bsnprintf(buf, sizeof(buf), _("Are you sure you want to delete Pool \"%s\"? (yes/no): "),
1475 if (!get_yesno(ua, buf)) {
1478 if (ua->pint32_val) {
1479 db_delete_pool_record(ua->jcr, ua->db, &pr);
1484 int memory_cmd(UAContext *ua, const char *cmd)
1486 list_dir_status_header(ua);
1487 sm_dump(false, true);
1491 static void do_mount_cmd(UAContext *ua, const char *command)
1496 char dev_name[MAX_NAME_LENGTH];
1500 if (!open_client_db(ua)) {
1503 Dmsg2(120, "%s: %s\n", command, ua->UA_sock->msg);
1505 store.store = get_storage_resource(ua, true/*arg is storage*/);
1509 pm_strcpy(store.store_source, _("unknown source"));
1510 set_wstorage(jcr, &store);
1511 drive = get_storage_drive(ua, store.store);
1512 if (strcmp(command, "mount") == 0) {
1513 slot = get_storage_slot(ua, store.store);
1516 Dmsg3(120, "Found storage, MediaType=%s DevName=%s drive=%d\n",
1517 store.store->media_type, store.store->dev_name(), drive);
1519 if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) {
1520 ua->error_msg(_("Failed to connect to Storage daemon.\n"));
1523 sd = jcr->store_bsock;
1524 bstrncpy(dev_name, store.store->dev_name(), sizeof(dev_name));
1525 bash_spaces(dev_name);
1527 bnet_fsend(sd, "%s %s drive=%d slot=%d", command, dev_name, drive, slot);
1529 bnet_fsend(sd, "%s %s drive=%d", command, dev_name, drive);
1531 while (bnet_recv(sd) >= 0) {
1532 ua->send_msg("%s", sd->msg);
1534 bnet_sig(sd, BNET_TERMINATE);
1536 jcr->store_bsock = NULL;
1540 * mount [storage=<name>] [drive=nn] [slot=mm]
1542 static int mount_cmd(UAContext *ua, const char *cmd)
1544 do_mount_cmd(ua, "mount"); /* mount */
1550 * unmount [storage=<name>] [drive=nn]
1552 static int unmount_cmd(UAContext *ua, const char *cmd)
1554 do_mount_cmd(ua, "unmount"); /* unmount */
1560 * release [storage=<name>] [drive=nn]
1562 static int release_cmd(UAContext *ua, const char *cmd)
1564 do_mount_cmd(ua, "release"); /* release */
1571 * use catalog=<name>
1573 static int use_cmd(UAContext *ua, const char *cmd)
1575 CAT *oldcatalog, *catalog;
1578 close_db(ua); /* close any previously open db */
1579 oldcatalog = ua->catalog;
1581 if (!(catalog = get_catalog_resource(ua))) {
1582 ua->catalog = oldcatalog;
1584 ua->catalog = catalog;
1587 ua->send_msg(_("Using Catalog name=%s DB=%s\n"),
1588 ua->catalog->name(), ua->catalog->db_name);
1593 int quit_cmd(UAContext *ua, const char *cmd)
1599 /* Handler to get job status */
1600 static int status_handler(void *ctx, int num_fields, char **row)
1602 char *val = (char *)ctx;
1607 *val = '?'; /* Unknown by default */
1614 * Wait until no job is running
1616 int wait_cmd(UAContext *ua, const char *cmd)
1620 time_t stop_time = 0;
1624 * Wait until no job is running
1626 if (ua->argc == 1) {
1627 bmicrosleep(0, 200000); /* let job actually start */
1628 for (bool running=true; running; ) {
1631 if (jcr->JobId != 0) {
1645 i = find_arg_with_value(ua, NT_("timeout"));
1646 if (i > 0 && ua->argv[i]) {
1647 stop_time = time(NULL) + str_to_int64(ua->argv[i]);
1650 /* we have jobid, jobname or ujobid argument */
1652 uint32_t jobid = 0 ;
1654 if (!open_client_db(ua)) {
1655 ua->error_msg(_("ERR: Can't open db\n")) ;
1659 for (int i=1; i<ua->argc; i++) {
1660 if (strcasecmp(ua->argk[i], "jobid") == 0) {
1664 jobid = str_to_int64(ua->argv[i]);
1666 } else if (strcasecmp(ua->argk[i], "jobname") == 0 ||
1667 strcasecmp(ua->argk[i], "job") == 0) {
1671 jcr=get_jcr_by_partial_name(ua->argv[i]) ;
1673 jobid = jcr->JobId ;
1677 } else if (strcasecmp(ua->argk[i], "ujobid") == 0) {
1681 jcr=get_jcr_by_full_name(ua->argv[i]) ;
1683 jobid = jcr->JobId ;
1687 /* Wait for a mount request */
1688 } else if (strcasecmp(ua->argk[i], "mount") == 0) {
1689 for (bool waiting=false; !waiting; ) {
1691 if (jcr->JobId != 0 &&
1692 (jcr->JobStatus == JS_WaitMedia || jcr->JobStatus == JS_WaitMount)) {
1701 if (stop_time && (time(NULL) >= stop_time)) {
1702 ua->warning_msg(_("Wait on mount timed out\n"));
1712 ua->error_msg(_("ERR: Job was not found\n"));
1717 * We wait the end of a specific job
1720 bmicrosleep(0, 200000); /* let job actually start */
1721 for (bool running=true; running; ) {
1724 jcr=get_jcr_by_id(jobid) ;
1737 * We have to get JobStatus
1741 char jobstatus = '?'; /* Unknown by default */
1744 bsnprintf(buf, sizeof(buf),
1745 "SELECT JobStatus FROM Job WHERE JobId='%i'", jobid);
1748 db_sql_query(ua->db, buf,
1749 status_handler, (void *)&jobstatus);
1751 switch (jobstatus) {
1753 status = 1 ; /* Warning */
1757 case JS_ErrorTerminated:
1759 status = 2 ; /* Critical */
1763 status = 0 ; /* Ok */
1767 status = 3 ; /* Unknown */
1771 ua->send_msg("JobId=%i\n", jobid) ;
1772 ua->send_msg("JobStatus=%s (%c)\n",
1773 job_status_to_str(jobstatus),
1776 if (ua->gui || ua->api) {
1777 ua->send_msg("ExitStatus=%i\n", status) ;
1784 static int help_cmd(UAContext *ua, const char *cmd)
1788 ua->send_msg(_(" Command Description\n ======= ===========\n"));
1789 for (i=0; i<comsize; i++) {
1790 ua->send_msg(_(" %-10s %s\n"), _(commands[i].key), _(commands[i].help));
1792 ua->send_msg(_("\nWhen at a prompt, entering a period cancels the command.\n\n"));
1796 int qhelp_cmd(UAContext *ua, const char *cmd)
1800 for (i=0; i<comsize; i++) {
1801 ua->send_msg("%s %s\n", commands[i].key, _(commands[i].help));
1807 static int version_cmd(UAContext *ua, const char *cmd)
1809 ua->send_msg(_("%s Version: %s (%s) %s %s %s %s\n"), my_name, VERSION, BDATE,
1810 NPRTB(director->verid), HOST_OS, DISTNAME, DISTVER);
1815 * Test code -- turned on only for debug testing
1817 static int version_cmd(UAContext *ua, const char *cmd)
1820 POOL_MEM query(PM_MESSAGE);
1822 Mmsg(query, "select MediaId from Media,Pool where Pool.PoolId=Media.PoolId and Pool.Name='Full'");
1823 db_get_query_dbids(ua->jcr, ua->db, query, ids);
1824 ua->send_msg("num_ids=%d max_ids=%d tot_ids=%d\n", ids.num_ids, ids.max_ids, ids.tot_ids);
1825 for (int i=0; i < ids.num_ids; i++) {
1826 ua->send_msg("id=%d\n", ids.DBId[i]);
1834 * This call explicitly checks for a catalog=xxx and
1835 * if given, opens that catalog. It also checks for
1836 * client=xxx and if found, opens the catalog
1837 * corresponding to that client. If we still don't
1838 * have a catalog, look for a Job keyword and get the
1839 * catalog from its client record.
1841 bool open_client_db(UAContext *ua)
1848 /* Try for catalog keyword */
1849 i = find_arg_with_value(ua, NT_("catalog"));
1851 if (!acl_access_ok(ua, Catalog_ACL, ua->argv[i])) {
1852 ua->error_msg(_("No authorization for Catalog \"%s\"\n"), ua->argv[i]);
1855 catalog = GetCatalogResWithName(ua->argv[i]);
1857 if (ua->catalog && ua->catalog != catalog) {
1860 ua->catalog = catalog;
1865 /* Try for client keyword */
1866 i = find_arg_with_value(ua, NT_("client"));
1868 if (!acl_access_ok(ua, Client_ACL, ua->argv[i])) {
1869 ua->error_msg(_("No authorization for Client \"%s\"\n"), ua->argv[i]);
1872 client = GetClientResWithName(ua->argv[i]);
1874 catalog = client->catalog;
1875 if (ua->catalog && ua->catalog != catalog) {
1878 if (!acl_access_ok(ua, Catalog_ACL, catalog->name())) {
1879 ua->error_msg(_("No authorization for Catalog \"%s\"\n"), catalog->name());
1882 ua->catalog = catalog;
1887 /* Try for Job keyword */
1888 i = find_arg_with_value(ua, NT_("job"));
1890 if (!acl_access_ok(ua, Job_ACL, ua->argv[i])) {
1891 ua->error_msg(_("No authorization for Job \"%s\"\n"), ua->argv[i]);
1894 job = GetJobResWithName(ua->argv[i]);
1896 catalog = job->client->catalog;
1897 if (ua->catalog && ua->catalog != catalog) {
1900 if (!acl_access_ok(ua, Catalog_ACL, catalog->name())) {
1901 ua->error_msg(_("No authorization for Catalog \"%s\"\n"), catalog->name());
1904 ua->catalog = catalog;
1914 * Open the catalog database.
1916 bool open_db(UAContext *ua)
1922 ua->catalog = get_catalog_resource(ua);
1924 ua->error_msg( _("Could not find a Catalog resource\n"));
1929 ua->jcr->catalog = ua->catalog;
1931 Dmsg0(100, "UA Open database\n");
1932 ua->db = db_init(ua->jcr, ua->catalog->db_driver, ua->catalog->db_name,
1933 ua->catalog->db_user,
1934 ua->catalog->db_password, ua->catalog->db_address,
1935 ua->catalog->db_port, ua->catalog->db_socket,
1936 ua->catalog->mult_db_connections);
1937 if (!ua->db || !db_open_database(ua->jcr, ua->db)) {
1938 ua->error_msg(_("Could not open catalog database \"%s\".\n"),
1939 ua->catalog->db_name);
1941 ua->error_msg("%s", db_strerror(ua->db));
1946 ua->jcr->db = ua->db;
1948 ua->send_msg(_("Using Catalog \"%s\"\n"), ua->catalog->name());
1950 Dmsg1(150, "DB %s opened\n", ua->catalog->db_name);
1954 void close_db(UAContext *ua)
1957 db_close_database(ua->jcr, ua->db);