2 Bacula® - The Network Backup Solution
4 Copyright (C) 2001-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 three of the GNU Affero 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 Affero 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 Prompt and Selection code
32 * Kern Sibbald, October MMI
39 /* Imported variables */
40 extern struct s_jl joblevels[];
44 * Confirm a retention period
46 int confirm_retention(UAContext *ua, utime_t *ret, const char *msg)
51 int yes_in_arg = find_arg(ua, NT_("yes"));
54 ua->info_msg(_("The current %s retention period is: %s\n"),
55 msg, edit_utime(*ret, ed1, sizeof(ed1)));
56 if (yes_in_arg != -1) {
59 if (!get_cmd(ua, _("Continue? (yes/mod/no): "))) {
62 if (strcasecmp(ua->cmd, _("mod")) == 0) {
63 if (!get_cmd(ua, _("Enter new retention period: "))) {
66 if (!duration_to_utime(ua->cmd, ret)) {
67 ua->error_msg(_("Invalid period.\n"));
72 if (is_yesno(ua->cmd, &val)) {
73 return val; /* is 1 for yes, 0 for no */
80 * Given a list of keywords, find the first one
81 * that is in the argument list.
82 * Returns: -1 if not found
83 * index into list (base 0) on success
85 int find_arg_keyword(UAContext *ua, const char **list)
87 for (int i=1; i<ua->argc; i++) {
88 for(int j=0; list[j]; j++) {
89 if (strcasecmp(list[j], ua->argk[i]) == 0) {
98 * Given one keyword, find the first one that
99 * is in the argument list.
100 * Returns: argk index (always gt 0)
103 int find_arg(UAContext *ua, const char *keyword)
105 for (int i=1; i<ua->argc; i++) {
106 if (strcasecmp(keyword, ua->argk[i]) == 0) {
114 * Given a single keyword, find it in the argument list, but
115 * it must have a value
116 * Returns: -1 if not found or no value
117 * list index (base 0) on success
119 int find_arg_with_value(UAContext *ua, const char *keyword)
121 for (int i=1; i<ua->argc; i++) {
122 if (strcasecmp(keyword, ua->argk[i]) == 0) {
134 * Given a list of keywords, prompt the user
137 * Returns: -1 on failure
138 * index into list (base 0) on success
140 int do_keyword_prompt(UAContext *ua, const char *msg, const char **list)
143 start_prompt(ua, _("You have the following choices:\n"));
144 for (i=0; list[i]; i++) {
145 add_prompt(ua, list[i]);
147 return do_prompt(ua, "", msg, NULL, 0);
152 * Select a Storage resource from prompt list
154 STORE *select_storage_resource(UAContext *ua)
156 char name[MAX_NAME_LENGTH];
159 start_prompt(ua, _("The defined Storage resources are:\n"));
161 foreach_res(store, R_STORAGE) {
162 if (acl_access_ok(ua, Storage_ACL, store->name())) {
163 add_prompt(ua, store->name());
167 if (do_prompt(ua, _("Storage"), _("Select Storage resource"), name, sizeof(name)) < 0) {
170 store = (STORE *)GetResWithName(R_STORAGE, name);
175 * Select a FileSet resource from prompt list
177 FILESET *select_fileset_resource(UAContext *ua)
179 char name[MAX_NAME_LENGTH];
182 start_prompt(ua, _("The defined FileSet resources are:\n"));
184 foreach_res(fs, R_FILESET) {
185 if (acl_access_ok(ua, FileSet_ACL, fs->name())) {
186 add_prompt(ua, fs->name());
190 if (do_prompt(ua, _("FileSet"), _("Select FileSet resource"), name, sizeof(name)) < 0) {
193 fs = (FILESET *)GetResWithName(R_FILESET, name);
199 * Get a catalog resource from prompt list
201 CAT *get_catalog_resource(UAContext *ua)
203 char name[MAX_NAME_LENGTH];
207 for (i=1; i<ua->argc; i++) {
208 if (strcasecmp(ua->argk[i], NT_("catalog")) == 0 && ua->argv[i]) {
209 if (acl_access_ok(ua, Catalog_ACL, ua->argv[i])) {
210 catalog = (CAT *)GetResWithName(R_CATALOG, ua->argv[i]);
215 if (ua->gui && !catalog) {
217 catalog = (CAT *)GetNextRes(R_CATALOG, NULL);
220 ua->error_msg(_("Could not find a Catalog resource\n"));
222 } else if (!acl_access_ok(ua, Catalog_ACL, catalog->name())) {
223 ua->error_msg(_("You must specify a \"use <catalog-name>\" command before continuing.\n"));
229 start_prompt(ua, _("The defined Catalog resources are:\n"));
231 foreach_res(catalog, R_CATALOG) {
232 if (acl_access_ok(ua, Catalog_ACL, catalog->name())) {
233 add_prompt(ua, catalog->name());
237 if (do_prompt(ua, _("Catalog"), _("Select Catalog resource"), name, sizeof(name)) < 0) {
240 catalog = (CAT *)GetResWithName(R_CATALOG, name);
247 * Select a job to enable or disable
249 JOB *select_enable_disable_job_resource(UAContext *ua, bool enable)
251 char name[MAX_NAME_LENGTH];
255 start_prompt(ua, _("The defined Job resources are:\n"));
256 foreach_res(job, R_JOB) {
257 if (!acl_access_ok(ua, Job_ACL, job->name())) {
260 if (job->enabled == enable) { /* Already enabled/disabled? */
261 continue; /* yes, skip */
263 add_prompt(ua, job->name());
266 if (do_prompt(ua, _("Job"), _("Select Job resource"), name, sizeof(name)) < 0) {
269 job = (JOB *)GetResWithName(R_JOB, name);
274 * Select a Job resource from prompt list
276 JOB *select_job_resource(UAContext *ua)
278 char name[MAX_NAME_LENGTH];
281 start_prompt(ua, _("The defined Job resources are:\n"));
283 foreach_res(job, R_JOB) {
284 if (acl_access_ok(ua, Job_ACL, job->name())) {
285 add_prompt(ua, job->name());
289 if (do_prompt(ua, _("Job"), _("Select Job resource"), name, sizeof(name)) < 0) {
292 job = (JOB *)GetResWithName(R_JOB, name);
297 * Select a Restore Job resource from prompt list
299 JOB *select_restore_job_resource(UAContext *ua)
301 char name[MAX_NAME_LENGTH];
304 start_prompt(ua, _("The defined Restore Job resources are:\n"));
306 foreach_res(job, R_JOB) {
307 if (job->JobType == JT_RESTORE && acl_access_ok(ua, Job_ACL, job->name())) {
308 add_prompt(ua, job->name());
312 if (do_prompt(ua, _("Job"), _("Select Restore Job"), name, sizeof(name)) < 0) {
315 job = (JOB *)GetResWithName(R_JOB, name);
322 * Select a client resource from prompt list
324 CLIENT *select_client_resource(UAContext *ua)
326 char name[MAX_NAME_LENGTH];
329 start_prompt(ua, _("The defined Client resources are:\n"));
331 foreach_res(client, R_CLIENT) {
332 if (acl_access_ok(ua, Client_ACL, client->name())) {
333 add_prompt(ua, client->name());
337 if (do_prompt(ua, _("Client"), _("Select Client (File daemon) resource"), name, sizeof(name)) < 0) {
340 client = (CLIENT *)GetResWithName(R_CLIENT, name);
345 * Get client resource, start by looking for
346 * client=<client-name>
347 * if we don't find the keyword, we prompt the user.
349 CLIENT *get_client_resource(UAContext *ua)
351 CLIENT *client = NULL;
354 for (i=1; i<ua->argc; i++) {
355 if ((strcasecmp(ua->argk[i], NT_("client")) == 0 ||
356 strcasecmp(ua->argk[i], NT_("fd")) == 0) && ua->argv[i]) {
357 if (!acl_access_ok(ua, Client_ACL, ua->argv[i])) {
360 client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[i]);
364 ua->error_msg(_("Error: Client resource %s does not exist.\n"), ua->argv[i]);
368 return select_client_resource(ua);
371 /* Scan what the user has entered looking for:
373 * client=<client-name>
375 * if error or not found, put up a list of client DBRs
378 * returns: 0 on error
379 * 1 on success and fills in CLIENT_DBR
381 bool get_client_dbr(UAContext *ua, CLIENT_DBR *cr)
385 if (cr->Name[0]) { /* If name already supplied */
386 if (db_get_client_record(ua->jcr, ua->db, cr)) {
389 ua->error_msg(_("Could not find Client %s: ERR=%s"), cr->Name, db_strerror(ua->db));
391 for (i=1; i<ua->argc; i++) {
392 if ((strcasecmp(ua->argk[i], NT_("client")) == 0 ||
393 strcasecmp(ua->argk[i], NT_("fd")) == 0) && ua->argv[i]) {
394 if (!acl_access_ok(ua, Client_ACL, ua->argv[i])) {
397 bstrncpy(cr->Name, ua->argv[i], sizeof(cr->Name));
398 if (!db_get_client_record(ua->jcr, ua->db, cr)) {
399 ua->error_msg(_("Could not find Client \"%s\": ERR=%s"), ua->argv[i],
400 db_strerror(ua->db));
407 if (!select_client_dbr(ua, cr)) { /* try once more by proposing a list */
414 * Select a Client record from the catalog
415 * Returns 1 on success
418 bool select_client_dbr(UAContext *ua, CLIENT_DBR *cr)
421 char name[MAX_NAME_LENGTH];
427 if (!db_get_client_ids(ua->jcr, ua->db, &num_clients, &ids)) {
428 ua->error_msg(_("Error obtaining client ids. ERR=%s\n"), db_strerror(ua->db));
431 if (num_clients <= 0) {
432 ua->error_msg(_("No clients defined. You must run a job before using this command.\n"));
436 start_prompt(ua, _("Defined Clients:\n"));
437 for (i=0; i < num_clients; i++) {
438 ocr.ClientId = ids[i];
439 if (!db_get_client_record(ua->jcr, ua->db, &ocr) ||
440 !acl_access_ok(ua, Client_ACL, ocr.Name)) {
443 add_prompt(ua, ocr.Name);
446 if (do_prompt(ua, _("Client"), _("Select the Client"), name, sizeof(name)) < 0) {
449 memset(&ocr, 0, sizeof(ocr));
450 bstrncpy(ocr.Name, name, sizeof(ocr.Name));
452 if (!db_get_client_record(ua->jcr, ua->db, &ocr)) {
453 ua->error_msg(_("Could not find Client \"%s\": ERR=%s"), name, db_strerror(ua->db));
456 memcpy(cr, &ocr, sizeof(ocr));
460 /* Scan what the user has entered looking for:
464 * where argk can be : pool, recyclepool, scratchpool, nextpool etc..
466 * if error or not found, put up a list of pool DBRs
469 * returns: false on error
470 * true on success and fills in POOL_DBR
472 bool get_pool_dbr(UAContext *ua, POOL_DBR *pr, const char *argk)
474 if (pr->Name[0]) { /* If name already supplied */
475 if (db_get_pool_record(ua->jcr, ua->db, pr) &&
476 acl_access_ok(ua, Pool_ACL, pr->Name)) {
479 ua->error_msg(_("Could not find Pool \"%s\": ERR=%s"), pr->Name, db_strerror(ua->db));
481 if (!select_pool_dbr(ua, pr, argk)) { /* try once more */
488 * Select a Pool record from catalog
489 * argk can be pool, recyclepool, scratchpool etc..
491 bool select_pool_dbr(UAContext *ua, POOL_DBR *pr, const char *argk)
494 char name[MAX_NAME_LENGTH];
498 for (i=1; i<ua->argc; i++) {
499 if (strcasecmp(ua->argk[i], argk) == 0 && ua->argv[i] &&
500 acl_access_ok(ua, Pool_ACL, ua->argv[i])) {
501 bstrncpy(pr->Name, ua->argv[i], sizeof(pr->Name));
502 if (!db_get_pool_record(ua->jcr, ua->db, pr)) {
503 ua->error_msg(_("Could not find Pool \"%s\": ERR=%s"), ua->argv[i],
504 db_strerror(ua->db));
513 if (!db_get_pool_ids(ua->jcr, ua->db, &num_pools, &ids)) {
514 ua->error_msg(_("Error obtaining pool ids. ERR=%s\n"), db_strerror(ua->db));
517 if (num_pools <= 0) {
518 ua->error_msg(_("No pools defined. Use the \"create\" command to create one.\n"));
522 start_prompt(ua, _("Defined Pools:\n"));
523 if (bstrcmp(argk, NT_("recyclepool"))) {
524 add_prompt(ua, _("*None*"));
526 for (i=0; i < num_pools; i++) {
528 if (!db_get_pool_record(ua->jcr, ua->db, &opr) ||
529 !acl_access_ok(ua, Pool_ACL, opr.Name)) {
532 add_prompt(ua, opr.Name);
535 if (do_prompt(ua, _("Pool"), _("Select the Pool"), name, sizeof(name)) < 0) {
539 memset(&opr, 0, sizeof(opr));
540 /* *None* is only returned when selecting a recyclepool, and in that case
541 * the calling code is only interested in opr.Name, so then we can leave
544 if (!bstrcmp(name, _("*None*"))) {
545 bstrncpy(opr.Name, name, sizeof(opr.Name));
547 if (!db_get_pool_record(ua->jcr, ua->db, &opr)) {
548 ua->error_msg(_("Could not find Pool \"%s\": ERR=%s"), name, db_strerror(ua->db));
553 memcpy(pr, &opr, sizeof(opr));
558 * Select a Pool and a Media (Volume) record from the database
560 int select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr)
563 if (!select_media_dbr(ua, mr)) {
566 memset(pr, 0, sizeof(POOL_DBR));
567 pr->PoolId = mr->PoolId;
568 if (!db_get_pool_record(ua->jcr, ua->db, pr)) {
569 ua->error_msg("%s", db_strerror(ua->db));
572 if (!acl_access_ok(ua, Pool_ACL, pr->Name)) {
573 ua->error_msg(_("No access to Pool \"%s\"\n"), pr->Name);
579 /* Select a Media (Volume) record from the database */
580 int select_media_dbr(UAContext *ua, MEDIA_DBR *mr)
585 POOLMEM *err = get_pool_memory(PM_FNAME);
586 memset(mr, 0, sizeof(MEDIA_DBR));
588 i = find_arg_with_value(ua, "volume");
590 if (is_name_valid(ua->argv[i], &err)) {
591 bstrncpy(mr->VolumeName, ua->argv[i], sizeof(mr->VolumeName));
596 if (mr->VolumeName[0] == 0) {
598 memset(&pr, 0, sizeof(pr));
599 /* Get the pool from pool=<pool-name> */
600 if (!get_pool_dbr(ua, &pr)) {
603 mr->PoolId = pr.PoolId;
604 db_list_media_records(ua->jcr, ua->db, mr, prtit, ua, HORZ_LIST);
605 if (!get_cmd(ua, _("Enter *MediaId or Volume name: "))) {
608 if (ua->cmd[0] == '*' && is_a_number(ua->cmd+1)) {
609 mr->MediaId = str_to_int64(ua->cmd+1);
610 } else if (is_name_valid(ua->cmd, &err)) {
611 bstrncpy(mr->VolumeName, ua->cmd, sizeof(mr->VolumeName));
617 if (!db_get_media_record(ua->jcr, ua->db, mr)) {
618 pm_strcpy(err, db_strerror(ua->db));
625 ua->error_msg("%s", err);
627 free_pool_memory(err);
633 * Select a pool resource from prompt list
635 POOL *select_pool_resource(UAContext *ua)
637 char name[MAX_NAME_LENGTH];
640 start_prompt(ua, _("The defined Pool resources are:\n"));
642 foreach_res(pool, R_POOL) {
643 if (acl_access_ok(ua, Pool_ACL, pool->name())) {
644 add_prompt(ua, pool->name());
648 if (do_prompt(ua, _("Pool"), _("Select Pool resource"), name, sizeof(name)) < 0) {
651 pool = (POOL *)GetResWithName(R_POOL, name);
657 * If you are thinking about using it, you
658 * probably want to use select_pool_dbr()
659 * or get_pool_dbr() above.
661 POOL *get_pool_resource(UAContext *ua)
666 i = find_arg_with_value(ua, "pool");
667 if (i >= 0 && acl_access_ok(ua, Pool_ACL, ua->argv[i])) {
668 pool = (POOL *)GetResWithName(R_POOL, ua->argv[i]);
672 ua->error_msg(_("Error: Pool resource \"%s\" does not exist.\n"), ua->argv[i]);
674 return select_pool_resource(ua);
678 * List all jobs and ask user to select one
680 int select_job_dbr(UAContext *ua, JOB_DBR *jr)
682 db_list_job_records(ua->jcr, ua->db, jr, prtit, ua, HORZ_LIST);
683 if (!get_pint(ua, _("Enter the JobId to select: "))) {
686 jr->JobId = ua->int64_val;
687 if (!db_get_job_record(ua->jcr, ua->db, jr)) {
688 ua->error_msg("%s", db_strerror(ua->db));
696 /* Scan what the user has entered looking for:
700 * if error or not found, put up a list of Jobs
703 * returns: 0 on error
704 * JobId on success and fills in JOB_DBR
706 int get_job_dbr(UAContext *ua, JOB_DBR *jr)
710 for (i=1; i<ua->argc; i++) {
711 if (strcasecmp(ua->argk[i], NT_("ujobid")) == 0 && ua->argv[i]) {
713 bstrncpy(jr->Job, ua->argv[i], sizeof(jr->Job));
714 } else if (strcasecmp(ua->argk[i], NT_("jobid")) == 0 && ua->argv[i]) {
715 jr->JobId = str_to_int64(ua->argv[i]);
720 if (!db_get_job_record(ua->jcr, ua->db, jr)) {
721 ua->error_msg(_("Could not find Job \"%s\": ERR=%s"), ua->argv[i],
722 db_strerror(ua->db));
732 for (i=1; i<ua->argc; i++) {
733 if ((strcasecmp(ua->argk[i], NT_("jobname")) == 0 ||
734 strcasecmp(ua->argk[i], NT_("job")) == 0) && ua->argv[i]) {
736 bstrncpy(jr->Name, ua->argv[i], sizeof(jr->Name));
740 if (!select_job_dbr(ua, jr)) { /* try once more */
747 * Implement unique set of prompts
749 void start_prompt(UAContext *ua, const char *msg)
751 if (ua->max_prompts == 0) {
752 ua->max_prompts = 10;
753 ua->prompt = (char **)bmalloc(sizeof(char *) * ua->max_prompts);
756 ua->prompt[0] = bstrdup(msg);
760 * Add to prompts -- keeping them unique
762 void add_prompt(UAContext *ua, const char *prompt)
765 if (ua->num_prompts == ua->max_prompts) {
766 ua->max_prompts *= 2;
767 ua->prompt = (char **)brealloc(ua->prompt, sizeof(char *) *
770 for (i=1; i < ua->num_prompts; i++) {
771 if (strcmp(ua->prompt[i], prompt) == 0) {
775 ua->prompt[ua->num_prompts++] = bstrdup(prompt);
779 * Display prompts and get user's choice
781 * Returns: -1 on error
782 * index base 0 on success, and choice
783 * is copied to prompt if not NULL
784 * prompt is set to the chosen prompt item string
786 int do_prompt(UAContext *ua, const char *automsg, const char *msg,
787 char *prompt, int max_prompt)
790 char pmsg[MAXSTRING];
791 BSOCK *user = ua->UA_sock;
796 if (ua->num_prompts == 2) {
799 bstrncpy(prompt, ua->prompt[1], max_prompt);
801 ua->send_msg(_("Automatically selected %s: %s\n"), automsg, ua->prompt[1]);
804 /* If running non-interactive, bail out */
806 /* First print the choices he wanted to make */
807 ua->send_msg(ua->prompt[0]);
808 for (i=1; i < ua->num_prompts; i++) {
809 ua->send_msg("%6d: %s\n", i, ua->prompt[i]);
811 /* Now print error message */
812 ua->send_msg(_("Your request has multiple choices for \"%s\". Selection is not possible in batch mode.\n"), automsg);
816 if (ua->api) user->signal(BNET_START_SELECT);
817 ua->send_msg(ua->prompt[0]);
818 for (i=1; i < ua->num_prompts; i++) {
820 ua->send_msg("%s", ua->prompt[i]);
822 ua->send_msg("%6d: %s\n", i, ua->prompt[i]);
825 if (ua->api) user->signal(BNET_END_SELECT);
828 /* First item is the prompt string, not the items */
829 if (ua->num_prompts == 1) {
830 ua->error_msg(_("Selection list for \"%s\" is empty!\n"), automsg);
831 item = -1; /* list is empty ! */
834 if (ua->num_prompts == 2) {
836 ua->send_msg(_("Automatically selected: %s\n"), ua->prompt[1]);
838 bstrncpy(prompt, ua->prompt[1], max_prompt);
842 sprintf(pmsg, "%s (1-%d): ", msg, ua->num_prompts-1);
844 /* Either a . or an @ will get you out of the loop */
845 if (ua->api) user->signal(BNET_SELECT_INPUT);
846 if (!get_pint(ua, pmsg)) {
847 item = -1; /* error */
848 ua->info_msg(_("Selection aborted, nothing done.\n"));
851 item = ua->pint32_val;
852 if (item < 1 || item >= ua->num_prompts) {
853 ua->warning_msg(_("Please enter a number between 1 and %d\n"), ua->num_prompts-1);
857 bstrncpy(prompt, ua->prompt[item], max_prompt);
863 for (i=0; i < ua->num_prompts; i++) {
867 return item>0 ? item-1 : item;
872 * We scan what the user has entered looking for
873 * storage=<storage-resource>
876 * ? (prompt him with storage list)
877 * <some-error> (prompt him with storage list)
879 * If use_default is set, we assume that any keyword without a value
880 * is the name of the Storage resource wanted.
882 STORE *get_storage_resource(UAContext *ua, bool use_default)
884 char *store_name = NULL;
891 for (i=1; i<ua->argc; i++) {
892 if (use_default && !ua->argv[i]) {
893 /* Ignore slots, scan and barcode(s) keywords */
894 if (strcasecmp("scan", ua->argk[i]) == 0 ||
895 strcasecmp("barcode", ua->argk[i]) == 0 ||
896 strcasecmp("barcodes", ua->argk[i]) == 0 ||
897 strcasecmp("slots", ua->argk[i]) == 0) {
900 /* Default argument is storage */
902 ua->error_msg(_("Storage name given twice.\n"));
905 store_name = ua->argk[i];
906 if (*store_name == '?') {
911 if (strcasecmp(ua->argk[i], NT_("storage")) == 0 ||
912 strcasecmp(ua->argk[i], NT_("sd")) == 0) {
913 store_name = ua->argv[i];
916 } else if (strcasecmp(ua->argk[i], NT_("jobid")) == 0) {
917 jobid = str_to_int64(ua->argv[i]);
919 ua->error_msg(_("Expecting jobid=nn command, got: %s\n"), ua->argk[i]);
922 if (!(jcr=get_jcr_by_id(jobid))) {
923 ua->error_msg(_("JobId %s is not running.\n"), edit_int64(jobid, ed1));
930 } else if (strcasecmp(ua->argk[i], NT_("job")) == 0 ||
931 strcasecmp(ua->argk[i], NT_("jobname")) == 0) {
933 ua->error_msg(_("Expecting job=xxx, got: %s.\n"), ua->argk[i]);
936 if (!(jcr=get_jcr_by_partial_name(ua->argv[i]))) {
937 ua->error_msg(_("Job \"%s\" is not running.\n"), ua->argv[i]);
943 } else if (strcasecmp(ua->argk[i], NT_("ujobid")) == 0) {
945 ua->error_msg(_("Expecting ujobid=xxx, got: %s.\n"), ua->argk[i]);
948 if (!(jcr=get_jcr_by_full_name(ua->argv[i]))) {
949 ua->error_msg(_("Job \"%s\" is not running.\n"), ua->argv[i]);
958 if (store && !acl_access_ok(ua, Storage_ACL, store->name())) {
962 if (!store && store_name && store_name[0] != 0) {
963 store = (STORE *)GetResWithName(R_STORAGE, store_name);
965 ua->error_msg(_("Storage resource \"%s\": not found\n"), store_name);
968 if (store && !acl_access_ok(ua, Storage_ACL, store->name())) {
971 /* No keywords found, so present a selection list */
973 store = select_storage_resource(ua);
978 /* Get drive that we are working with for this storage */
979 int get_storage_drive(UAContext *ua, STORE *store)
982 /* Get drive for autochanger if possible */
983 i = find_arg_with_value(ua, "drive");
985 drive = atoi(ua->argv[i]);
986 } else if (store && store->autochanger) {
987 /* If our structure is not set ask SD for # drives */
988 if (store->drives == 0) {
989 store->drives = get_num_drives_from_SD(ua);
991 /* If only one drive, default = 0 */
992 if (store->drives == 1) {
995 /* Ask user to enter drive number */
997 if (!get_cmd(ua, _("Enter autochanger drive[0]: "))) {
998 drive = -1; /* None */
1000 drive = atoi(ua->cmd);
1007 /* Get slot that we are working with for this storage */
1008 int get_storage_slot(UAContext *ua, STORE *store)
1011 /* Get slot for autochanger if possible */
1012 i = find_arg_with_value(ua, "slot");
1014 slot = atoi(ua->argv[i]);
1015 } else if (store && store->autochanger) {
1016 /* Ask user to enter slot number */
1018 if (!get_cmd(ua, _("Enter autochanger slot: "))) {
1019 slot = -1; /* None */
1021 slot = atoi(ua->cmd);
1030 * Scan looking for mediatype=
1032 * if not found or error, put up selection list
1034 * Returns: 0 on error
1035 * 1 on success, MediaType is set
1037 int get_media_type(UAContext *ua, char *MediaType, int max_media)
1042 i = find_arg_with_value(ua, "mediatype");
1044 bstrncpy(MediaType, ua->argv[i], max_media);
1048 start_prompt(ua, _("Media Types defined in conf file:\n"));
1050 foreach_res(store, R_STORAGE) {
1051 add_prompt(ua, store->media_type);
1054 return (do_prompt(ua, _("Media Type"), _("Select the Media Type"), MediaType, max_media) < 0) ? 0 : 1;
1057 bool get_level_from_name(JCR *jcr, const char *level_name)
1059 /* Look up level name and pull code */
1061 for (int i=0; joblevels[i].level_name; i++) {
1062 if (strcasecmp(level_name, joblevels[i].level_name) == 0) {
1063 jcr->set_JobLevel(joblevels[i].level);