X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fdird%2Fua_cmds.c;h=2baa3438e3d8a62facca795c3cee1639ab0c0315;hb=9f01506e19567ce5c8fae5699016a1d512647f55;hp=c455d086b4c2069b68ab4a33b8b7d3b55ecb6226;hpb=a83d4155ca138d917b0b2dc33e90dcee325527e7;p=bacula%2Fbacula diff --git a/bacula/src/dird/ua_cmds.c b/bacula/src/dird/ua_cmds.c index c455d086b4..2baa3438e3 100644 --- a/bacula/src/dird/ua_cmds.c +++ b/bacula/src/dird/ua_cmds.c @@ -8,7 +8,7 @@ */ /* - Copyright (C) 2000-2003 Kern Sibbald and John Walker + Copyright (C) 2000-2004 Kern Sibbald and John Walker This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -39,6 +39,7 @@ extern struct s_res resources[]; extern char my_name[]; extern jobq_t job_queue; /* job queue */ + extern char *list_pool; /* Imported functions */ @@ -47,7 +48,8 @@ extern int list_cmd(UAContext *ua, char *cmd); extern int llist_cmd(UAContext *ua, char *cmd); extern int show_cmd(UAContext *ua, char *cmd); extern int messagescmd(UAContext *ua, char *cmd); -extern int autodisplaycmd(UAContext *ua, char *cmd); +extern int autodisplay_cmd(UAContext *ua, char *cmd); +extern int gui_cmd(UAContext *ua, char *cmd); extern int sqlquerycmd(UAContext *ua, char *cmd); extern int querycmd(UAContext *ua, char *cmd); extern int run_cmd(UAContext *ua, char *cmd); @@ -64,6 +66,7 @@ static int add_cmd(UAContext *ua, char *cmd); static int create_cmd(UAContext *ua, char *cmd); static int cancel_cmd(UAContext *ua, char *cmd); static int setdebug_cmd(UAContext *ua, char *cmd); +static int trace_cmd(UAContext *ua, char *cmd); static int var_cmd(UAContext *ua, char *cmd); static int estimate_cmd(UAContext *ua, char *cmd); static int help_cmd(UAContext *ua, char *cmd); @@ -71,14 +74,17 @@ static int delete_cmd(UAContext *ua, char *cmd); static int use_cmd(UAContext *ua, char *cmd), unmount_cmd(UAContext *ua, char *cmd); static int version_cmd(UAContext *ua, char *cmd), automount_cmd(UAContext *ua, char *cmd); static int time_cmd(UAContext *ua, char *cmd); +static int reload_cmd(UAContext *ua, char *cmd); static int update_volume(UAContext *ua); static int update_pool(UAContext *ua); static int delete_volume(UAContext *ua); static int delete_pool(UAContext *ua); +static int delete_job(UAContext *ua); static int mount_cmd(UAContext *ua, char *cmd); static int release_cmd(UAContext *ua, char *cmd); static int update_cmd(UAContext *ua, char *cmd); static int wait_cmd(UAContext *ua, char *cmd); +static int setip_cmd(UAContext *ua, char *cmd); int quit_cmd(UAContext *ua, char *cmd); @@ -86,32 +92,36 @@ int quit_cmd(UAContext *ua, char *cmd); struct cmdstruct { char *key; int (*func)(UAContext *ua, char *cmd); char *help; }; static struct cmdstruct commands[] = { { N_("add"), add_cmd, _("add media to a pool")}, - { N_("autodisplay"), autodisplaycmd, _("autodisplay [on/off] -- console messages")}, + { N_("autodisplay"), autodisplay_cmd, _("autodisplay [on/off] -- console messages")}, { N_("automount"), automount_cmd, _("automount [on/off] -- after label")}, { N_("cancel"), cancel_cmd, _("cancel job=nnn -- cancel a job")}, { N_("create"), create_cmd, _("create DB Pool from resource")}, { N_("delete"), delete_cmd, _("delete [pool= | media volume=]")}, { N_("estimate"), estimate_cmd, _("performs FileSet estimate, listing gives full listing")}, { N_("exit"), quit_cmd, _("exit = quit")}, + { N_("gui"), gui_cmd, _("gui [on/off] -- non-interactive gui mode")}, { N_("help"), help_cmd, _("print this command")}, + { N_("list"), list_cmd, _("list [pools | jobs | jobtotals | media | files jobid=]; from catalog")}, { N_("label"), label_cmd, _("label a tape")}, - { N_("list"), list_cmd, _("list [pools | jobs | jobtotals | media | files job=]; from catalog")}, { N_("llist"), llist_cmd, _("full or long list like list command")}, { N_("messages"), messagescmd, _("messages")}, { N_("mount"), mount_cmd, _("mount ")}, { N_("prune"), prunecmd, _("prune expired records from catalog")}, { N_("purge"), purgecmd, _("purge records from catalog")}, - { N_("query"), querycmd, _("query catalog")}, { N_("quit"), quit_cmd, _("quit")}, + { N_("query"), querycmd, _("query catalog")}, + { N_("restore"), restore_cmd, _("restore files")}, { N_("relabel"), relabel_cmd, _("relabel a tape")}, { N_("release"), release_cmd, _("release ")}, - { N_("restore"), restore_cmd, _("restore files")}, + { N_("reload"), reload_cmd, _("reload conf file")}, { N_("run"), run_cmd, _("run ")}, + { N_("status"), status_cmd, _("status [storage | client]=")}, { N_("setdebug"), setdebug_cmd, _("sets debug level")}, + { N_("setip"), setip_cmd, _("sets new client address -- if authorized")}, { N_("show"), show_cmd, _("show (resource records) [jobs | pools | ... | all]")}, { N_("sqlquery"), sqlquerycmd, _("use SQL to query catalog")}, - { N_("status"), status_cmd, _("status [storage | client]=")}, { N_("time"), time_cmd, _("print current time")}, + { N_("trace"), trace_cmd, _("turn on/off trace to file")}, { N_("unmount"), unmount_cmd, _("unmount ")}, { N_("update"), update_cmd, _("update Volume or Pool")}, { N_("use"), use_cmd, _("use catalog xxx")}, @@ -128,12 +138,11 @@ int do_a_command(UAContext *ua, char *cmd) { unsigned int i; int len, stat; - int found; + bool found = false; - found = 0; stat = 1; - Dmsg1(120, "Command: %s\n", ua->UA_sock->msg); + Dmsg1(200, "Command: %s\n", ua->UA_sock->msg); if (ua->argc == 0) { return 1; } @@ -141,15 +150,16 @@ int do_a_command(UAContext *ua, char *cmd) len = strlen(ua->argk[0]); for (i=0; iargk[0], _(commands[i].key), len) == 0) { + if (!acl_access_ok(ua, Command_ACL, ua->argk[0], len)) { + break; + } stat = (*commands[i].func)(ua, cmd); /* go execute command */ - found = 1; + found = true; break; } } if (!found) { - pm_strcat(&ua->UA_sock->msg, _(": is an illegal command\n")); - ua->UA_sock->msglen = strlen(ua->UA_sock->msg); - bnet_send(ua->UA_sock); + bnet_fsend(ua->UA_sock, _("%s: is an illegal command.\n"), ua->argk[0]); } return stat; } @@ -183,7 +193,7 @@ static int add_cmd(UAContext *ua, char *cmd) int first_id = 0; char name[MAX_NAME_LENGTH]; STORE *store; - int slot = 0; + int Slot = 0, InChanger = 0; bsendmsg(ua, _( "You probably don't want to be using this command since it\n" @@ -286,13 +296,18 @@ getVolName: if (!get_pint(ua, _("Enter slot (0 for none): "))) { return 1; } - slot = ua->pint32_val; + Slot = ua->pint32_val; + if (!get_yesno(ua, _("InChanger? yes/no: "))) { + return 1; + } + InChanger = ua->pint32_val; } set_pool_dbr_defaults_in_media_dbr(&mr, &pr); for (i=startnum; i < num+startnum; i++) { bsnprintf(mr.VolumeName, sizeof(mr.VolumeName), name, i); - mr.Slot = slot++; + mr.Slot = Slot++; + mr.InChanger = InChanger; Dmsg1(200, "Create Volume %s\n", mr.VolumeName); if (!db_create_media_record(ua->jcr, ua->db, &mr)) { bsendmsg(ua, db_strerror(ua->db)); @@ -342,9 +357,8 @@ int automount_cmd(UAContext *ua, char *cmd) */ static int cancel_cmd(UAContext *ua, char *cmd) { - int i; + int i, ret; int njobs = 0; - BSOCK *sd, *fd; JCR *jcr = NULL; char JobName[MAX_NAME_LENGTH]; @@ -354,11 +368,13 @@ static int cancel_cmd(UAContext *ua, char *cmd) for (i=1; iargc; i++) { if (strcasecmp(ua->argk[i], _("jobid")) == 0) { + uint32_t JobId; if (!ua->argv[i]) { break; } - if (!(jcr=get_jcr_by_id(atoi(ua->argv[i])))) { - bsendmsg(ua, _("JobId %d is not running.\n"), atoi(ua->argv[i])); + JobId = str_to_int64(ua->argv[i]); + if (!(jcr=get_jcr_by_id(JobId))) { + bsendmsg(ua, _("JobId %d is not running.\n"), JobId); return 1; } break; @@ -379,13 +395,13 @@ static int cancel_cmd(UAContext *ua, char *cmd) if (!jcr) { /* Count Jobs running */ lock_jcr_chain(); - for (jcr=NULL; (jcr=get_next_jcr(jcr)); njobs++) { + foreach_jcr(jcr) { if (jcr->JobId == 0) { /* this is us */ free_locked_jcr(jcr); - njobs--; continue; } free_locked_jcr(jcr); + njobs++; } unlock_jcr_chain(); @@ -395,7 +411,7 @@ static int cancel_cmd(UAContext *ua, char *cmd) } start_prompt(ua, _("Select Job:\n")); lock_jcr_chain(); - for (jcr=NULL; (jcr=get_next_jcr(jcr)); ) { + foreach_jcr(jcr) { if (jcr->JobId == 0) { /* this is us */ free_locked_jcr(jcr); continue; @@ -413,72 +429,18 @@ static int cancel_cmd(UAContext *ua, char *cmd) return 1; } } + /* NOTE! This increments the ref_count */ jcr = get_jcr_by_full_name(JobName); if (!jcr) { bsendmsg(ua, _("Job %s not found.\n"), JobName); return 1; } } - - switch (jcr->JobStatus) { - case JS_Created: - case JS_WaitJobRes: - case JS_WaitClientRes: - case JS_WaitStoreRes: - case JS_WaitPriority: - case JS_WaitMaxJobs: - case JS_WaitStartTime: - set_jcr_job_status(jcr, JS_Canceled); - bsendmsg(ua, _("JobId %d, Job %s marked to be canceled.\n"), - jcr->JobId, jcr->Job); - jobq_remove(&job_queue, jcr); /* attempt to remove it from queue */ - free_jcr(jcr); /* this decrements the use count only */ - return 1; - - default: - set_jcr_job_status(jcr, JS_Canceled); - - /* Cancel File daemon */ - if (jcr->file_bsock) { - ua->jcr->client = jcr->client; - if (!connect_to_file_daemon(ua->jcr, 10, FDConnectTimeout, 1)) { - bsendmsg(ua, _("Failed to connect to File daemon.\n")); - free_jcr(jcr); - return 1; - } - Dmsg0(200, "Connected to file daemon\n"); - fd = ua->jcr->file_bsock; - bnet_fsend(fd, "cancel Job=%s\n", jcr->Job); - while (bnet_recv(fd) >= 0) { - bsendmsg(ua, "%s", fd->msg); - } - bnet_sig(fd, BNET_TERMINATE); - bnet_close(fd); - ua->jcr->file_bsock = NULL; - } - /* Cancel Storage daemon */ - if (jcr->store_bsock) { - ua->jcr->store = jcr->store; - if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) { - bsendmsg(ua, _("Failed to connect to Storage daemon.\n")); - free_jcr(jcr); - return 1; - } - Dmsg0(200, "Connected to storage daemon\n"); - sd = ua->jcr->store_bsock; - bnet_fsend(sd, "cancel Job=%s\n", jcr->Job); - while (bnet_recv(sd) >= 0) { - bsendmsg(ua, "%s", sd->msg); - } - bnet_sig(sd, BNET_TERMINATE); - bnet_close(sd); - ua->jcr->store_bsock = NULL; - } - } + ret = cancel_job(ua, jcr); free_jcr(jcr); - return 1; + return ret; } /* @@ -575,8 +537,8 @@ static int create_cmd(UAContext *ua, char *cmd) switch (create_pool(ua->jcr, ua->db, pool, POOL_OP_CREATE)) { case 0: - bsendmsg(ua, _("Error: Pool %s already exists.\n\ -Use update to change it.\n"), pool->hdr.name); + bsendmsg(ua, _("Error: Pool %s already exists.\n" + "Use update to change it.\n"), pool->hdr.name); break; case -1: @@ -591,6 +553,35 @@ Use update to change it.\n"), pool->hdr.name); } +/* + * Set a new address in a Client resource. We do this only + * if the Console name is the same as the Client name + * and the Console can access the client. + */ +static int setip_cmd(UAContext *ua, char *cmd) +{ + CLIENT *client; + if (!ua->cons || !acl_access_ok(ua, Client_ACL, ua->cons->hdr.name)) { + bsendmsg(ua, _("Illegal command from this console.\n")); + return 1; + } + LockRes(); + client = (CLIENT *)GetResWithName(R_CLIENT, ua->cons->hdr.name); + + if (!client) { + bsendmsg(ua, _("Client \"%s\" not found.\n"), ua->cons->hdr.name); + goto get_out; + } + if (client->address) { + free(client->address); + } + client->address = bstrdup(inet_ntoa(ua->UA_sock->client_addr.sin_addr)); + bsendmsg(ua, _("Client \"%s\" address set to %s\n"), + client->hdr.name, client->address); +get_out: + UnlockRes(); + return 1; +} /* @@ -601,6 +592,8 @@ Use update to change it.\n"), pool->hdr.name); * updates pool from Pool resource * update media pool= volume= * changes pool info for volume + * update slots [scan=...] + * updates autochanger slots */ static int update_cmd(UAContext *ua, char *cmd) { @@ -793,12 +786,60 @@ static void update_volrecycle(UAContext *ua, char *val, MEDIA_DBR *mr) if (!db_sql_query(ua->db, query, NULL, NULL)) { bsendmsg(ua, "%s", db_strerror(ua->db)); } else { - bsendmsg(ua, _("New recycle flag is: %s\n"), + bsendmsg(ua, _("New Recycle flag is: %s\n"), mr->Recycle==1?_("yes"):_("no")); } free_pool_memory(query); } +/* Modify the Pool in which this Volume is located */ +static void update_volpool(UAContext *ua, char *val, MEDIA_DBR *mr) +{ + POOL_DBR pr; + POOLMEM *query; + + memset(&pr, 0, sizeof(pr)); + bstrncpy(pr.Name, val, sizeof(pr.Name)); + if (!get_pool_dbr(ua, &pr)) { + return; + } + mr->PoolId = pr.PoolId; /* set new PoolId */ + /* + */ + query = get_pool_memory(PM_MESSAGE); + db_lock(ua->db); + Mmsg(&query, "UPDATE Media SET PoolId=%d WHERE MediaId=%u", + mr->PoolId, mr->MediaId); + if (!db_sql_query(ua->db, query, NULL, NULL)) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + } else { + bsendmsg(ua, _("New Pool is: %s\n"), pr.Name); + } + db_make_inchanger_unique(ua->jcr, ua->db, mr); + db_unlock(ua->db); + free_pool_memory(query); +} + +static void update_volfrompool(UAContext *ua, MEDIA_DBR *mr) +{ + POOL_DBR pr; + char VolStatus[50]; + + memset(&pr, 0, sizeof(pr)); + pr.PoolId = mr->PoolId; + if (!get_pool_dbr(ua, &pr)) { + return; + } + bstrncpy(VolStatus, mr->VolStatus, sizeof(VolStatus)); + set_pool_dbr_defaults_in_media_dbr(mr, &pr); + bstrncpy(mr->VolStatus, VolStatus, sizeof(mr->VolStatus)); + if (!db_update_media_record(ua->jcr, ua->db, mr)) { + bsendmsg(ua, _("Error updating Volume record: ERR=%s"), db_strerror(ua->db)); + } else { + bsendmsg(ua, _("Volume defaults updated from Pool record.\n")); + } +} + /* * Update a media record -- allows you to change the * Volume status. E.g. if you want Bacula to stop @@ -808,6 +849,7 @@ static void update_volrecycle(UAContext *ua, char *val, MEDIA_DBR *mr) static int update_volume(UAContext *ua) { MEDIA_DBR mr; + POOL_DBR pr; POOLMEM *query; char ed1[30]; bool done = false; @@ -819,6 +861,8 @@ static int update_volume(UAContext *ua) N_("MaxVolFiles"), /* 4 */ N_("MaxVolBytes"), /* 5 */ N_("Recycle"), /* 6 */ + N_("Pool"), /* 7 */ + N_("FromPool"), /* 8 */ NULL }; for (int i=0; kw[i]; i++) { @@ -849,6 +893,12 @@ static int update_volume(UAContext *ua) case 6: update_volrecycle(ua, ua->argv[j], &mr); break; + case 7: + update_volpool(ua, ua->argv[j], &mr); + break; + case 8: + update_volfrompool(ua, &mr); + break; } done = true; } @@ -868,7 +918,9 @@ static int update_volume(UAContext *ua) add_prompt(ua, _("Maximum Volume Bytes")); add_prompt(ua, _("Recycle Flag")); add_prompt(ua, _("Slot")); + add_prompt(ua, _("InChanger Flag")); add_prompt(ua, _("Volume Files")); + add_prompt(ua, _("Pool")); add_prompt(ua, _("Done")); switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) { case 0: /* Volume Status */ @@ -943,8 +995,7 @@ static int update_volume(UAContext *ua) break; case 7: /* Slot */ - int slot; - POOL_DBR pr; + int Slot; memset(&pr, 0, sizeof(POOL_DBR)); pr.PoolId = mr.PoolId; @@ -956,24 +1007,43 @@ static int update_volume(UAContext *ua) if (!get_pint(ua, _("Enter new Slot: "))) { return 0; } - slot = ua->pint32_val; - if (pr.MaxVols > 0 && slot > (int)pr.MaxVols) { + Slot = ua->pint32_val; + if (pr.MaxVols > 0 && Slot > (int)pr.MaxVols) { bsendmsg(ua, _("Invalid slot, it must be between 0 and %d\n"), pr.MaxVols); break; } - query = get_pool_memory(PM_MESSAGE); - Mmsg(&query, "UPDATE Media SET Slot=%d WHERE MediaId=%u", - slot, mr.MediaId); - if (!db_sql_query(ua->db, query, NULL, NULL)) { - bsendmsg(ua, "%s", db_strerror(ua->db)); + mr.Slot = Slot; + /* + * Make sure to use db_update... rather than doing this directly, + * so that any Slot is handled correctly. + */ + if (!db_update_media_record(ua->jcr, ua->db, &mr)) { + bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db)); } else { - bsendmsg(ua, "New Slot is: %d\n", slot); + bsendmsg(ua, _("New Slot is: %d\n"), mr.Slot); + } + break; + + case 8: /* InChanger */ + bsendmsg(ua, _("Current InChanger flag is: %d\n"), mr.InChanger); + if (!get_yesno(ua, _("Set InChanger flag? yes/no: "))) { + return 0; + } + mr.InChanger = ua->pint32_val; + /* + * Make sure to use db_update... rather than doing this directly, + * so that any Slot is handled correctly. + */ + if (!db_update_media_record(ua->jcr, ua->db, &mr)) { + bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db)); + } else { + bsendmsg(ua, _("New InChanger flag is: %d\n"), mr.InChanger); } - free_pool_memory(query); break; - case 8: /* Volume Files */ + + case 9: /* Volume Files */ int32_t VolFiles; bsendmsg(ua, _("Warning changing Volume Files can result\n" "in loss of data on your Volume\n\n")); @@ -999,6 +1069,20 @@ static int update_volume(UAContext *ua) free_pool_memory(query); break; + case 10: /* Volume's Pool */ + memset(&pr, 0, sizeof(POOL_DBR)); + pr.PoolId = mr.PoolId; + if (!db_get_pool_record(ua->jcr, ua->db, &pr)) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + return 0; + } + bsendmsg(ua, _("Current Pool is: %s\n"), pr.Name); + if (!get_cmd(ua, _("Enter new Pool name: "))) { + return 0; + } + update_volpool(ua, ua->cmd, &mr); + return 1; + default: /* Done or error */ bsendmsg(ua, "Selection done.\n"); return 1; @@ -1044,7 +1128,7 @@ static int update_pool(UAContext *ua) } -static void do_storage_setdebug(UAContext *ua, STORE *store, int level) +static void do_storage_setdebug(UAContext *ua, STORE *store, int level, int trace_flag) { BSOCK *sd; @@ -1058,7 +1142,7 @@ static void do_storage_setdebug(UAContext *ua, STORE *store, int level) } Dmsg0(120, _("Connected to storage daemon\n")); sd = ua->jcr->store_bsock; - bnet_fsend(sd, "setdebug=%d\n", level); + bnet_fsend(sd, "setdebug=%d trace=%d\n", level, trace_flag); if (bnet_recv(sd) >= 0) { bsendmsg(ua, "%s", sd->msg); } @@ -1068,7 +1152,7 @@ static void do_storage_setdebug(UAContext *ua, STORE *store, int level) return; } -static void do_client_setdebug(UAContext *ua, CLIENT *client, int level) +static void do_client_setdebug(UAContext *ua, CLIENT *client, int level, int trace_flag) { BSOCK *fd; @@ -1084,7 +1168,7 @@ static void do_client_setdebug(UAContext *ua, CLIENT *client, int level) } Dmsg0(120, "Connected to file daemon\n"); fd = ua->jcr->file_bsock; - bnet_fsend(fd, "setdebug=%d\n", level); + bnet_fsend(fd, "setdebug=%d trace=%d\n", level, trace_flag); if (bnet_recv(fd) >= 0) { bsendmsg(ua, "%s", fd->msg); } @@ -1095,7 +1179,7 @@ static void do_client_setdebug(UAContext *ua, CLIENT *client, int level) } -static void do_all_setdebug(UAContext *ua, int level) +static void do_all_setdebug(UAContext *ua, int level, int trace_flag) { STORE *store, **unique_store; CLIENT *client, **unique_client; @@ -1132,7 +1216,7 @@ static void do_all_setdebug(UAContext *ua, int level) /* Call each unique Storage daemon */ for (j=0; jpint32_val; } + /* Look for trace flag. -1 => not change */ + i = find_arg_with_value(ua, _("trace")); + if (i >= 0) { + trace_flag = atoi(ua->argv[i]); + if (trace_flag > 0) { + trace_flag = 1; + } + } + /* General debug? */ for (i=1; iargc; i++) { if (strcasecmp(ua->argk[i], _("all")) == 0) { - do_all_setdebug(ua, level); + do_all_setdebug(ua, level, trace_flag); return 1; } if (strcasecmp(ua->argk[i], _("dir")) == 0 || strcasecmp(ua->argk[i], _("director")) == 0) { debug_level = level; + set_trace(trace_flag); return 1; } - if (strcasecmp(ua->argk[i], _("client")) == 0) { + if (strcasecmp(ua->argk[i], _("client")) == 0 || + strcasecmp(ua->argk[i], _("fd")) == 0) { client = NULL; if (ua->argv[i]) { client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[i]); if (client) { - do_client_setdebug(ua, client, level); + do_client_setdebug(ua, client, level, trace_flag); return 1; } } client = select_client_resource(ua); if (client) { - do_client_setdebug(ua, client, level); + do_client_setdebug(ua, client, level, trace_flag); return 1; } } if (strcasecmp(ua->argk[i], _("store")) == 0 || - strcasecmp(ua->argk[i], _("storage")) == 0) { + strcasecmp(ua->argk[i], _("storage")) == 0 || + strcasecmp(ua->argk[i], _("sd")) == 0) { store = NULL; if (ua->argv[i]) { store = (STORE *)GetResWithName(R_STORAGE, ua->argv[i]); if (store) { - do_storage_setdebug(ua, store, level); + do_storage_setdebug(ua, store, level, trace_flag); return 1; } } store = get_storage_resource(ua, 0); if (store) { - do_storage_setdebug(ua, store, level); + do_storage_setdebug(ua, store, level, trace_flag); return 1; } } @@ -1252,21 +1349,22 @@ static int setdebug_cmd(UAContext *ua, char *cmd) switch(do_prompt(ua, "", _("Select daemon type to set debug level"), NULL, 0)) { case 0: /* Director */ debug_level = level; + set_trace(trace_flag); break; case 1: store = get_storage_resource(ua, 0); if (store) { - do_storage_setdebug(ua, store, level); + do_storage_setdebug(ua, store, level, trace_flag); } break; case 2: client = select_client_resource(ua); if (client) { - do_client_setdebug(ua, client, level); + do_client_setdebug(ua, client, level, trace_flag); } break; case 3: - do_all_setdebug(ua, level); + do_all_setdebug(ua, level, trace_flag); break; default: break; @@ -1274,6 +1372,27 @@ static int setdebug_cmd(UAContext *ua, char *cmd) return 1; } +/* + * Turn debug tracing to file on/off + */ +static int trace_cmd(UAContext *ua, char *cmd) +{ + char *onoff; + + if (ua->argc != 2) { + if (!get_cmd(ua, _("Turn on or off? "))) { + return 1; + } + onoff = ua->cmd; + } else { + onoff = ua->argk[1]; + } + + set_trace((strcasecmp(onoff, _("off")) == 0) ? false : true); + return 1; + +} + static int var_cmd(UAContext *ua, char *cmd) { POOLMEM *val = get_pool_memory(PM_FNAME); @@ -1305,7 +1424,8 @@ static int estimate_cmd(UAContext *ua, char *cmd) char since[MAXSTRING]; for (int i=1; iargc; i++) { - if (strcasecmp(ua->argk[i], _("client")) == 0) { + if (strcasecmp(ua->argk[i], _("client")) == 0 || + strcasecmp(ua->argk[i], _("fd")) == 0) { if (ua->argv[i]) { client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[i]); continue; @@ -1401,39 +1521,62 @@ static int time_cmd(UAContext *ua, char *cmd) return 1; } +/* + * reload the conf file + */ +extern void reload_config(int sig); + +static int reload_cmd(UAContext *ua, char *cmd) +{ + reload_config(1); + return 1; +} + /* * Delete Pool records (should purge Media with it). * * delete pool= - * delete media pool= volume= + * delete volume pool= volume= + * delete job jobid=xxx */ static int delete_cmd(UAContext *ua, char *cmd) { static char *keywords[] = { N_("volume"), N_("pool"), + N_("job"), + N_("jobid"), NULL}; if (!open_db(ua)) { return 1; } - bsendmsg(ua, _( -"In general it is not a good idea to delete either a\n" -"Pool or a Volume since they may contain data.\n\n")); - - switch (find_arg_keyword(ua, keywords)) { + switch (find_arg_keyword(ua, keywords)) { case 0: delete_volume(ua); return 1; case 1: delete_pool(ua); return 1; + case 2: + case 3: + int i; + while ((i=find_arg(ua, _("jobid"))) > 0) { + delete_job(ua); + *ua->argk[i] = 0; /* zap keyword already visited */ + } + return 1; default: break; } + + bsendmsg(ua, _( +"In general it is not a good idea to delete either a\n" +"Pool or a Volume since they may contain data.\n\n")); + switch (do_keyword_prompt(ua, _("Choose catalog item to delete"), keywords)) { case 0: delete_volume(ua); @@ -1441,6 +1584,9 @@ static int delete_cmd(UAContext *ua, char *cmd) case 1: delete_pool(ua); break; + case 2: + delete_job(ua); + return 1; default: bsendmsg(ua, _("Nothing done.\n")); break; @@ -1448,6 +1594,30 @@ static int delete_cmd(UAContext *ua, char *cmd) return 1; } +static int delete_job(UAContext *ua) +{ + POOLMEM *query = get_pool_memory(PM_MESSAGE); + JobId_t JobId; + + int i = find_arg_with_value(ua, _("jobid")); + if (i >= 0) { + JobId = str_to_int64(ua->argv[i]); + } else if (!get_pint(ua, _("Enter JobId to delete: "))) { + return 0; + } else { + JobId = ua->pint32_val; + } + Mmsg(&query, "DELETE FROM Job WHERE JobId=%u", JobId); + db_sql_query(ua->db, query, NULL, (void *)NULL); + Mmsg(&query, "DELETE FROM File WHERE JobId=%u", JobId); + db_sql_query(ua->db, query, NULL, (void *)NULL); + Mmsg(&query, "DELETE FROM JobMedia WHERE JobId=%u", JobId); + db_sql_query(ua->db, query, NULL, (void *)NULL); + free_pool_memory(query); + bsendmsg(ua, _("Job %u and associated records deleted from the catalog.\n"), JobId); + return 1; +} + /* * Delete media records from database -- dangerous */ @@ -1595,13 +1765,14 @@ int quit_cmd(UAContext *ua, char *cmd) */ int wait_cmd(UAContext *ua, char *cmd) { + JCR *jcr; bmicrosleep(0, 200000); /* let job actually start */ - for (int running=1; running; ) { - running = 0; + for (bool running=true; running; ) { + running = false; lock_jcr_chain(); - for (JCR *jcr=NULL; (jcr=get_next_jcr(jcr)); ) { + foreach_jcr(jcr) { if (jcr->JobId != 0) { - running = 1; + running = true; free_locked_jcr(jcr); break; } @@ -1620,12 +1791,11 @@ static int help_cmd(UAContext *ua, char *cmd) { unsigned int i; -/* usage(); */ bsendmsg(ua, _(" Command Description\n ======= ===========\n")); for (i=0; idb) { db_close_database(ua->jcr, ua->db); + ua->db = NULL; + if (ua->jcr) { + ua->jcr->db = NULL; + } } - ua->db = NULL; }