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 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 Prompt and Selection code
32 * Kern Sibbald, October MMI
40 /* Imported variables */
41 extern struct s_jl joblevels[];
45 * Confirm a retention period
47 int confirm_retention(UAContext *ua, utime_t *ret, const char *msg)
52 int yes_in_arg = find_arg(ua, NT_("yes"));
55 ua->info_msg(_("The current %s retention period is: %s\n"),
56 msg, edit_utime(*ret, ed1, sizeof(ed1)));
57 if (yes_in_arg != -1) {
60 if (!get_cmd(ua, _("Continue? (yes/mod/no): "))) {
63 if (strcasecmp(ua->cmd, _("mod")) == 0) {
64 if (!get_cmd(ua, _("Enter new retention period: "))) {
67 if (!duration_to_utime(ua->cmd, ret)) {
68 ua->error_msg(_("Invalid period.\n"));
73 if (is_yesno(ua->cmd, &val)) {
74 return val; /* is 1 for yes, 0 for no */
81 * Given a list of keywords, find the first one
82 * that is in the argument list.
83 * Returns: -1 if not found
84 * index into list (base 0) on success
86 int find_arg_keyword(UAContext *ua, const char **list)
88 for (int i=1; i<ua->argc; i++) {
89 for(int j=0; list[j]; j++) {
90 if (strcasecmp(list[j], ua->argk[i]) == 0) {
99 * Given one keyword, find the first one that
100 * is in the argument list.
101 * Returns: argk index (always gt 0)
104 int find_arg(UAContext *ua, const char *keyword)
106 for (int i=1; i<ua->argc; i++) {
107 if (strcasecmp(keyword, ua->argk[i]) == 0) {
115 * Given a single keyword, find it in the argument list, but
116 * it must have a value
117 * Returns: -1 if not found or no value
118 * list index (base 0) on success
120 int find_arg_with_value(UAContext *ua, const char *keyword)
122 for (int i=1; i<ua->argc; i++) {
123 if (strcasecmp(keyword, ua->argk[i]) == 0) {
135 * Given a list of keywords, prompt the user
138 * Returns: -1 on failure
139 * index into list (base 0) on success
141 int do_keyword_prompt(UAContext *ua, const char *msg, const char **list)
144 start_prompt(ua, _("You have the following choices:\n"));
145 for (i=0; list[i]; i++) {
146 add_prompt(ua, list[i]);
148 return do_prompt(ua, "", msg, NULL, 0);
153 * Select a Storage resource from prompt list
155 STORE *select_storage_resource(UAContext *ua)
157 char name[MAX_NAME_LENGTH];
160 start_prompt(ua, _("The defined Storage resources are:\n"));
162 foreach_res(store, R_STORAGE) {
163 if (acl_access_ok(ua, Storage_ACL, store->name())) {
164 add_prompt(ua, store->name());
168 if (do_prompt(ua, _("Storage"), _("Select Storage resource"), name, sizeof(name)) < 0) {
171 store = (STORE *)GetResWithName(R_STORAGE, name);
176 * Select a FileSet resource from prompt list
178 FILESET *select_fileset_resource(UAContext *ua)
180 char name[MAX_NAME_LENGTH];
183 start_prompt(ua, _("The defined FileSet resources are:\n"));
185 foreach_res(fs, R_FILESET) {
186 if (acl_access_ok(ua, FileSet_ACL, fs->name())) {
187 add_prompt(ua, fs->name());
191 if (do_prompt(ua, _("FileSet"), _("Select FileSet resource"), name, sizeof(name)) < 0) {
194 fs = (FILESET *)GetResWithName(R_FILESET, name);
200 * Get a catalog resource from prompt list
202 CAT *get_catalog_resource(UAContext *ua)
204 char name[MAX_NAME_LENGTH];
208 for (i=1; i<ua->argc; i++) {
209 if (strcasecmp(ua->argk[i], NT_("catalog")) == 0 && ua->argv[i]) {
210 if (acl_access_ok(ua, Catalog_ACL, ua->argv[i])) {
211 catalog = (CAT *)GetResWithName(R_CATALOG, ua->argv[i]);
216 if (ua->gui && !catalog) {
218 catalog = (CAT *)GetNextRes(R_CATALOG, NULL);
221 ua->error_msg(_("Could not find a Catalog resource\n"));
223 } else if (!acl_access_ok(ua, Catalog_ACL, catalog->name())) {
224 ua->error_msg(_("You must specify a \"use <catalog-name>\" command before continuing.\n"));
230 start_prompt(ua, _("The defined Catalog resources are:\n"));
232 foreach_res(catalog, R_CATALOG) {
233 if (acl_access_ok(ua, Catalog_ACL, catalog->name())) {
234 add_prompt(ua, catalog->name());
238 if (do_prompt(ua, _("Catalog"), _("Select Catalog resource"), name, sizeof(name)) < 0) {
241 catalog = (CAT *)GetResWithName(R_CATALOG, name);
248 * Select a job to enable or disable
250 JOB *select_enable_disable_job_resource(UAContext *ua, bool enable)
252 char name[MAX_NAME_LENGTH];
256 start_prompt(ua, _("The defined Job resources are:\n"));
257 foreach_res(job, R_JOB) {
258 if (!acl_access_ok(ua, Job_ACL, job->name())) {
261 if (job->enabled == enable) { /* Already enabled/disabled? */
262 continue; /* yes, skip */
264 add_prompt(ua, job->name());
267 if (do_prompt(ua, _("Job"), _("Select Job resource"), name, sizeof(name)) < 0) {
270 job = (JOB *)GetResWithName(R_JOB, name);
275 * Select a Job resource from prompt list
277 JOB *select_job_resource(UAContext *ua)
279 char name[MAX_NAME_LENGTH];
282 start_prompt(ua, _("The defined Job resources are:\n"));
284 foreach_res(job, R_JOB) {
285 if (acl_access_ok(ua, Job_ACL, job->name())) {
286 add_prompt(ua, job->name());
290 if (do_prompt(ua, _("Job"), _("Select Job resource"), name, sizeof(name)) < 0) {
293 job = (JOB *)GetResWithName(R_JOB, name);
298 * Select a Restore Job resource from prompt list
300 JOB *select_restore_job_resource(UAContext *ua)
302 char name[MAX_NAME_LENGTH];
305 start_prompt(ua, _("The defined Restore Job resources are:\n"));
307 foreach_res(job, R_JOB) {
308 if (job->JobType == JT_RESTORE && acl_access_ok(ua, Job_ACL, job->name())) {
309 add_prompt(ua, job->name());
313 if (do_prompt(ua, _("Job"), _("Select Restore Job"), name, sizeof(name)) < 0) {
316 job = (JOB *)GetResWithName(R_JOB, name);
323 * Select a client resource from prompt list
325 CLIENT *select_client_resource(UAContext *ua)
327 char name[MAX_NAME_LENGTH];
330 start_prompt(ua, _("The defined Client resources are:\n"));
332 foreach_res(client, R_CLIENT) {
333 if (acl_access_ok(ua, Client_ACL, client->name())) {
334 add_prompt(ua, client->name());
338 if (do_prompt(ua, _("Client"), _("Select Client (File daemon) resource"), name, sizeof(name)) < 0) {
341 client = (CLIENT *)GetResWithName(R_CLIENT, name);
346 * Get client resource, start by looking for
347 * client=<client-name>
348 * if we don't find the keyword, we prompt the user.
350 CLIENT *get_client_resource(UAContext *ua)
352 CLIENT *client = NULL;
355 for (i=1; i<ua->argc; i++) {
356 if ((strcasecmp(ua->argk[i], NT_("client")) == 0 ||
357 strcasecmp(ua->argk[i], NT_("fd")) == 0) && ua->argv[i]) {
358 if (!acl_access_ok(ua, Client_ACL, ua->argv[i])) {
361 client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[i]);
365 ua->error_msg(_("Error: Client resource %s does not exist.\n"), ua->argv[i]);
369 return select_client_resource(ua);
372 /* Scan what the user has entered looking for:
374 * client=<client-name>
376 * if error or not found, put up a list of client DBRs
379 * returns: 0 on error
380 * 1 on success and fills in CLIENT_DBR
382 bool get_client_dbr(UAContext *ua, CLIENT_DBR *cr)
386 if (cr->Name[0]) { /* If name already supplied */
387 if (db_get_client_record(ua->jcr, ua->db, cr)) {
390 ua->error_msg(_("Could not find Client %s: ERR=%s"), cr->Name, db_strerror(ua->db));
392 for (i=1; i<ua->argc; i++) {
393 if ((strcasecmp(ua->argk[i], NT_("client")) == 0 ||
394 strcasecmp(ua->argk[i], NT_("fd")) == 0) && ua->argv[i]) {
395 if (!acl_access_ok(ua, Client_ACL, ua->argv[i])) {
398 bstrncpy(cr->Name, ua->argv[i], sizeof(cr->Name));
399 if (!db_get_client_record(ua->jcr, ua->db, cr)) {
400 ua->error_msg(_("Could not find Client \"%s\": ERR=%s"), ua->argv[i],
401 db_strerror(ua->db));
408 if (!select_client_dbr(ua, cr)) { /* try once more by proposing a list */
415 * Select a Client record from the catalog
416 * Returns 1 on success
419 bool select_client_dbr(UAContext *ua, CLIENT_DBR *cr)
422 char name[MAX_NAME_LENGTH];
428 if (!db_get_client_ids(ua->jcr, ua->db, &num_clients, &ids)) {
429 ua->error_msg(_("Error obtaining client ids. ERR=%s\n"), db_strerror(ua->db));
432 if (num_clients <= 0) {
433 ua->error_msg(_("No clients defined. You must run a job before using this command.\n"));
437 start_prompt(ua, _("Defined Clients:\n"));
438 for (i=0; i < num_clients; i++) {
439 ocr.ClientId = ids[i];
440 if (!db_get_client_record(ua->jcr, ua->db, &ocr) ||
441 !acl_access_ok(ua, Client_ACL, ocr.Name)) {
444 add_prompt(ua, ocr.Name);
447 if (do_prompt(ua, _("Client"), _("Select the Client"), name, sizeof(name)) < 0) {
450 memset(&ocr, 0, sizeof(ocr));
451 bstrncpy(ocr.Name, name, sizeof(ocr.Name));
453 if (!db_get_client_record(ua->jcr, ua->db, &ocr)) {
454 ua->error_msg(_("Could not find Client \"%s\": ERR=%s"), name, db_strerror(ua->db));
457 memcpy(cr, &ocr, sizeof(ocr));
461 /* Scan what the user has entered looking for:
465 * where argk can be : pool, recyclepool, scratchpool, nextpool etc..
467 * if error or not found, put up a list of pool DBRs
470 * returns: false on error
471 * true on success and fills in POOL_DBR
473 bool get_pool_dbr(UAContext *ua, POOL_DBR *pr, const char *argk)
475 if (pr->Name[0]) { /* If name already supplied */
476 if (db_get_pool_record(ua->jcr, ua->db, pr) &&
477 acl_access_ok(ua, Pool_ACL, pr->Name)) {
480 ua->error_msg(_("Could not find Pool \"%s\": ERR=%s"), pr->Name, db_strerror(ua->db));
482 if (!select_pool_dbr(ua, pr, argk)) { /* try once more */
489 * Select a Pool record from catalog
490 * argk can be pool, recyclepool, scratchpool etc..
492 bool select_pool_dbr(UAContext *ua, POOL_DBR *pr, const char *argk)
495 char name[MAX_NAME_LENGTH];
499 for (i=1; i<ua->argc; i++) {
500 if (strcasecmp(ua->argk[i], argk) == 0 && ua->argv[i] &&
501 acl_access_ok(ua, Pool_ACL, ua->argv[i])) {
502 bstrncpy(pr->Name, ua->argv[i], sizeof(pr->Name));
503 if (!db_get_pool_record(ua->jcr, ua->db, pr)) {
504 ua->error_msg(_("Could not find Pool \"%s\": ERR=%s"), ua->argv[i],
505 db_strerror(ua->db));
514 if (!db_get_pool_ids(ua->jcr, ua->db, &num_pools, &ids)) {
515 ua->error_msg(_("Error obtaining pool ids. ERR=%s\n"), db_strerror(ua->db));
518 if (num_pools <= 0) {
519 ua->error_msg(_("No pools defined. Use the \"create\" command to create one.\n"));
523 start_prompt(ua, _("Defined Pools:\n"));
524 if (bstrcmp(argk, NT_("recyclepool"))) {
525 add_prompt(ua, _("*None*"));
527 for (i=0; i < num_pools; i++) {
529 if (!db_get_pool_record(ua->jcr, ua->db, &opr) ||
530 !acl_access_ok(ua, Pool_ACL, opr.Name)) {
533 add_prompt(ua, opr.Name);
536 if (do_prompt(ua, _("Pool"), _("Select the Pool"), name, sizeof(name)) < 0) {
540 memset(&opr, 0, sizeof(opr));
541 /* *None* is only returned when selecting a recyclepool, and in that case
542 * the calling code is only interested in opr.Name, so then we can leave
545 if (!bstrcmp(name, _("*None*"))) {
546 bstrncpy(opr.Name, name, sizeof(opr.Name));
548 if (!db_get_pool_record(ua->jcr, ua->db, &opr)) {
549 ua->error_msg(_("Could not find Pool \"%s\": ERR=%s"), name, db_strerror(ua->db));
554 memcpy(pr, &opr, sizeof(opr));
559 * Select a Pool and a Media (Volume) record from the database
561 int select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr)
564 if (!select_media_dbr(ua, mr)) {
567 memset(pr, 0, sizeof(POOL_DBR));
568 pr->PoolId = mr->PoolId;
569 if (!db_get_pool_record(ua->jcr, ua->db, pr)) {
570 ua->error_msg("%s", db_strerror(ua->db));
573 if (!acl_access_ok(ua, Pool_ACL, pr->Name)) {
574 ua->error_msg(_("No access to Pool \"%s\"\n"), pr->Name);
580 /* Select a Media (Volume) record from the database */
581 int select_media_dbr(UAContext *ua, MEDIA_DBR *mr)
585 memset(mr, 0, sizeof(MEDIA_DBR));
587 i = find_arg_with_value(ua, "volume");
589 bstrncpy(mr->VolumeName, ua->argv[i], sizeof(mr->VolumeName));
591 if (mr->VolumeName[0] == 0) {
593 memset(&pr, 0, sizeof(pr));
594 /* Get the pool from pool=<pool-name> */
595 if (!get_pool_dbr(ua, &pr)) {
598 mr->PoolId = pr.PoolId;
599 db_list_media_records(ua->jcr, ua->db, mr, prtit, ua, HORZ_LIST);
600 if (!get_cmd(ua, _("Enter *MediaId or Volume name: "))) {
603 if (ua->cmd[0] == '*' && is_a_number(ua->cmd+1)) {
604 mr->MediaId = str_to_int64(ua->cmd+1);
606 bstrncpy(mr->VolumeName, ua->cmd, sizeof(mr->VolumeName));
610 if (!db_get_media_record(ua->jcr, ua->db, mr)) {
611 ua->error_msg("%s", db_strerror(ua->db));
619 * Select a pool resource from prompt list
621 POOL *select_pool_resource(UAContext *ua)
623 char name[MAX_NAME_LENGTH];
626 start_prompt(ua, _("The defined Pool resources are:\n"));
628 foreach_res(pool, R_POOL) {
629 if (acl_access_ok(ua, Pool_ACL, pool->name())) {
630 add_prompt(ua, pool->name());
634 if (do_prompt(ua, _("Pool"), _("Select Pool resource"), name, sizeof(name)) < 0) {
637 pool = (POOL *)GetResWithName(R_POOL, name);
643 * If you are thinking about using it, you
644 * probably want to use select_pool_dbr()
645 * or get_pool_dbr() above.
647 POOL *get_pool_resource(UAContext *ua)
652 i = find_arg_with_value(ua, "pool");
653 if (i >= 0 && acl_access_ok(ua, Pool_ACL, ua->argv[i])) {
654 pool = (POOL *)GetResWithName(R_POOL, ua->argv[i]);
658 ua->error_msg(_("Error: Pool resource \"%s\" does not exist.\n"), ua->argv[i]);
660 return select_pool_resource(ua);
664 * List all jobs and ask user to select one
666 int select_job_dbr(UAContext *ua, JOB_DBR *jr)
668 db_list_job_records(ua->jcr, ua->db, jr, prtit, ua, HORZ_LIST);
669 if (!get_pint(ua, _("Enter the JobId to select: "))) {
672 jr->JobId = ua->int64_val;
673 if (!db_get_job_record(ua->jcr, ua->db, jr)) {
674 ua->error_msg("%s", db_strerror(ua->db));
682 /* Scan what the user has entered looking for:
686 * if error or not found, put up a list of Jobs
689 * returns: 0 on error
690 * JobId on success and fills in JOB_DBR
692 int get_job_dbr(UAContext *ua, JOB_DBR *jr)
696 for (i=1; i<ua->argc; i++) {
697 if (strcasecmp(ua->argk[i], NT_("ujobid")) == 0 && ua->argv[i]) {
699 bstrncpy(jr->Job, ua->argv[i], sizeof(jr->Job));
700 } else if (strcasecmp(ua->argk[i], NT_("jobid")) == 0 && ua->argv[i]) {
701 jr->JobId = str_to_int64(ua->argv[i]);
706 if (!db_get_job_record(ua->jcr, ua->db, jr)) {
707 ua->error_msg(_("Could not find Job \"%s\": ERR=%s"), ua->argv[i],
708 db_strerror(ua->db));
718 for (i=1; i<ua->argc; i++) {
719 if ((strcasecmp(ua->argk[i], NT_("jobname")) == 0 ||
720 strcasecmp(ua->argk[i], NT_("job")) == 0) && ua->argv[i]) {
722 bstrncpy(jr->Name, ua->argv[i], sizeof(jr->Name));
726 if (!select_job_dbr(ua, jr)) { /* try once more */
733 * Implement unique set of prompts
735 void start_prompt(UAContext *ua, const char *msg)
737 if (ua->max_prompts == 0) {
738 ua->max_prompts = 10;
739 ua->prompt = (char **)bmalloc(sizeof(char *) * ua->max_prompts);
742 ua->prompt[0] = bstrdup(msg);
746 * Add to prompts -- keeping them unique
748 void add_prompt(UAContext *ua, const char *prompt)
751 if (ua->num_prompts == ua->max_prompts) {
752 ua->max_prompts *= 2;
753 ua->prompt = (char **)brealloc(ua->prompt, sizeof(char *) *
756 for (i=1; i < ua->num_prompts; i++) {
757 if (strcmp(ua->prompt[i], prompt) == 0) {
761 ua->prompt[ua->num_prompts++] = bstrdup(prompt);
765 * Display prompts and get user's choice
767 * Returns: -1 on error
768 * index base 0 on success, and choice
769 * is copied to prompt if not NULL
770 * prompt is set to the chosen prompt item string
772 int do_prompt(UAContext *ua, const char *automsg, const char *msg,
773 char *prompt, int max_prompt)
776 char pmsg[MAXSTRING];
777 BSOCK *user = ua->UA_sock;
782 if (ua->num_prompts == 2) {
785 bstrncpy(prompt, ua->prompt[1], max_prompt);
787 ua->send_msg(_("Automatically selected %s: %s\n"), automsg, ua->prompt[1]);
790 /* If running non-interactive, bail out */
792 /* First print the choices he wanted to make */
793 ua->send_msg(ua->prompt[0]);
794 for (i=1; i < ua->num_prompts; i++) {
795 ua->send_msg("%6d: %s\n", i, ua->prompt[i]);
797 /* Now print error message */
798 ua->send_msg(_("Your request has multiple choices for \"%s\". Selection is not possible in batch mode.\n"), automsg);
802 if (ua->api) user->signal(BNET_START_SELECT);
803 ua->send_msg(ua->prompt[0]);
804 for (i=1; i < ua->num_prompts; i++) {
806 ua->send_msg("%s", ua->prompt[i]);
808 ua->send_msg("%6d: %s\n", i, ua->prompt[i]);
811 if (ua->api) user->signal(BNET_END_SELECT);
814 /* First item is the prompt string, not the items */
815 if (ua->num_prompts == 1) {
816 ua->error_msg(_("Selection list for \"%s\" is empty!\n"), automsg);
817 item = -1; /* list is empty ! */
820 if (ua->num_prompts == 2) {
822 ua->send_msg(_("Automatically selected: %s\n"), ua->prompt[1]);
824 bstrncpy(prompt, ua->prompt[1], max_prompt);
828 sprintf(pmsg, "%s (1-%d): ", msg, ua->num_prompts-1);
830 /* Either a . or an @ will get you out of the loop */
831 if (ua->api) user->signal(BNET_SELECT_INPUT);
832 if (!get_pint(ua, pmsg)) {
833 item = -1; /* error */
834 ua->info_msg(_("Selection aborted, nothing done.\n"));
837 item = ua->pint32_val;
838 if (item < 1 || item >= ua->num_prompts) {
839 ua->warning_msg(_("Please enter a number between 1 and %d\n"), ua->num_prompts-1);
843 bstrncpy(prompt, ua->prompt[item], max_prompt);
849 for (i=0; i < ua->num_prompts; i++) {
853 return item>0 ? item-1 : item;
858 * We scan what the user has entered looking for
859 * storage=<storage-resource>
862 * ? (prompt him with storage list)
863 * <some-error> (prompt him with storage list)
865 * If use_default is set, we assume that any keyword without a value
866 * is the name of the Storage resource wanted.
868 STORE *get_storage_resource(UAContext *ua, bool use_default)
870 char *store_name = NULL;
877 for (i=1; i<ua->argc; i++) {
878 if (use_default && !ua->argv[i]) {
879 /* Ignore slots, scan and barcode(s) keywords */
880 if (strcasecmp("scan", ua->argk[i]) == 0 ||
881 strcasecmp("barcode", ua->argk[i]) == 0 ||
882 strcasecmp("barcodes", ua->argk[i]) == 0 ||
883 strcasecmp("slots", ua->argk[i]) == 0) {
886 /* Default argument is storage */
888 ua->error_msg(_("Storage name given twice.\n"));
891 store_name = ua->argk[i];
892 if (*store_name == '?') {
897 if (strcasecmp(ua->argk[i], NT_("storage")) == 0 ||
898 strcasecmp(ua->argk[i], NT_("sd")) == 0) {
899 store_name = ua->argv[i];
902 } else if (strcasecmp(ua->argk[i], NT_("jobid")) == 0) {
903 jobid = str_to_int64(ua->argv[i]);
905 ua->error_msg(_("Expecting jobid=nn command, got: %s\n"), ua->argk[i]);
908 if (!(jcr=get_jcr_by_id(jobid))) {
909 ua->error_msg(_("JobId %s is not running.\n"), edit_int64(jobid, ed1));
916 } else if (strcasecmp(ua->argk[i], NT_("job")) == 0 ||
917 strcasecmp(ua->argk[i], NT_("jobname")) == 0) {
919 ua->error_msg(_("Expecting job=xxx, got: %s.\n"), ua->argk[i]);
922 if (!(jcr=get_jcr_by_partial_name(ua->argv[i]))) {
923 ua->error_msg(_("Job \"%s\" is not running.\n"), ua->argv[i]);
929 } else if (strcasecmp(ua->argk[i], NT_("ujobid")) == 0) {
931 ua->error_msg(_("Expecting ujobid=xxx, got: %s.\n"), ua->argk[i]);
934 if (!(jcr=get_jcr_by_full_name(ua->argv[i]))) {
935 ua->error_msg(_("Job \"%s\" is not running.\n"), ua->argv[i]);
944 if (store && !acl_access_ok(ua, Storage_ACL, store->name())) {
948 if (!store && store_name && store_name[0] != 0) {
949 store = (STORE *)GetResWithName(R_STORAGE, store_name);
951 ua->error_msg(_("Storage resource \"%s\": not found\n"), store_name);
954 if (store && !acl_access_ok(ua, Storage_ACL, store->name())) {
957 /* No keywords found, so present a selection list */
959 store = select_storage_resource(ua);
964 /* Get drive that we are working with for this storage */
965 int get_storage_drive(UAContext *ua, STORE *store)
968 /* Get drive for autochanger if possible */
969 i = find_arg_with_value(ua, "drive");
971 drive = atoi(ua->argv[i]);
972 } else if (store && store->autochanger) {
973 /* If our structure is not set ask SD for # drives */
974 if (store->drives == 0) {
975 store->drives = get_num_drives_from_SD(ua);
977 /* If only one drive, default = 0 */
978 if (store->drives == 1) {
981 /* Ask user to enter drive number */
983 if (!get_cmd(ua, _("Enter autochanger drive[0]: "))) {
984 drive = -1; /* None */
986 drive = atoi(ua->cmd);
993 /* Get slot that we are working with for this storage */
994 int get_storage_slot(UAContext *ua, STORE *store)
997 /* Get slot for autochanger if possible */
998 i = find_arg_with_value(ua, "slot");
1000 slot = atoi(ua->argv[i]);
1001 } else if (store && store->autochanger) {
1002 /* Ask user to enter slot number */
1004 if (!get_cmd(ua, _("Enter autochanger slot: "))) {
1005 slot = -1; /* None */
1007 slot = atoi(ua->cmd);
1016 * Scan looking for mediatype=
1018 * if not found or error, put up selection list
1020 * Returns: 0 on error
1021 * 1 on success, MediaType is set
1023 int get_media_type(UAContext *ua, char *MediaType, int max_media)
1028 i = find_arg_with_value(ua, "mediatype");
1030 bstrncpy(MediaType, ua->argv[i], max_media);
1034 start_prompt(ua, _("Media Types defined in conf file:\n"));
1036 foreach_res(store, R_STORAGE) {
1037 add_prompt(ua, store->media_type);
1040 return (do_prompt(ua, _("Media Type"), _("Select the Media Type"), MediaType, max_media) < 0) ? 0 : 1;
1043 bool get_level_from_name(JCR *jcr, const char *level_name)
1045 /* Look up level name and pull code */
1047 for (int i=0; joblevels[i].level_name; i++) {
1048 if (strcasecmp(level_name, joblevels[i].level_name) == 0) {
1049 jcr->set_JobLevel(joblevels[i].level);