2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2007 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 John Walker.
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 -- Update command processing
31 * Split from ua_cmds.c March 2005
33 * Kern Sibbald, September MM
41 /* Forward referenced functions */
42 static int update_volume(UAContext *ua);
43 static bool update_pool(UAContext *ua);
44 static bool update_job(UAContext *ua);
47 * Update a Pool Record in the database.
48 * It is always updated from the Resource record.
50 * update pool=<pool-name>
51 * updates pool from Pool resource
52 * update media pool=<pool-name> volume=<volume-name>
53 * changes pool info for volume
54 * update slots [scan=...]
55 * updates autochanger slots
57 int update_cmd(UAContext *ua, const char *cmd)
59 static const char *kw[] = {
61 NT_("volume"), /* 1 */
67 if (!open_client_db(ua)) {
71 switch (find_arg_keyword(ua, kw)) {
89 start_prompt(ua, _("Update choice:\n"));
90 add_prompt(ua, _("Volume parameters"));
91 add_prompt(ua, _("Pool from resource"));
92 add_prompt(ua, _("Slots from autochanger"));
93 switch (do_prompt(ua, _("item"), _("Choose catalog item to update"), NULL, 0)) {
109 static void update_volstatus(UAContext *ua, const char *val, MEDIA_DBR *mr)
111 POOL_MEM query(PM_MESSAGE);
126 for (i=0; kw[i]; i++) {
127 if (strcasecmp(val, kw[i]) == 0) {
133 ua->error_msg(_("Invalid VolStatus specified: %s\n"), val);
136 bstrncpy(mr->VolStatus, kw[i], sizeof(mr->VolStatus));
137 Mmsg(query, "UPDATE Media SET VolStatus='%s' WHERE MediaId=%s",
138 mr->VolStatus, edit_int64(mr->MediaId,ed1));
139 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
140 ua->error_msg("%s", db_strerror(ua->db));
142 ua->info_msg(_("New Volume status is: %s\n"), mr->VolStatus);
147 static void update_volretention(UAContext *ua, char *val, MEDIA_DBR *mr)
149 char ed1[150], ed2[50];
150 POOL_MEM query(PM_MESSAGE);
151 if (!duration_to_utime(val, &mr->VolRetention)) {
152 ua->error_msg(_("Invalid retention period specified: %s\n"), val);
155 Mmsg(query, "UPDATE Media SET VolRetention=%s WHERE MediaId=%s",
156 edit_uint64(mr->VolRetention, ed1), edit_int64(mr->MediaId,ed2));
157 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
158 ua->error_msg("%s", db_strerror(ua->db));
160 ua->info_msg(_("New retention period is: %s\n"),
161 edit_utime(mr->VolRetention, ed1, sizeof(ed1)));
165 static void update_voluseduration(UAContext *ua, char *val, MEDIA_DBR *mr)
167 char ed1[150], ed2[50];
168 POOL_MEM query(PM_MESSAGE);
170 if (!duration_to_utime(val, &mr->VolUseDuration)) {
171 ua->error_msg(_("Invalid use duration specified: %s\n"), val);
174 Mmsg(query, "UPDATE Media SET VolUseDuration=%s WHERE MediaId=%s",
175 edit_uint64(mr->VolUseDuration, ed1), edit_int64(mr->MediaId,ed2));
176 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
177 ua->error_msg("%s", db_strerror(ua->db));
179 ua->info_msg(_("New use duration is: %s\n"),
180 edit_utime(mr->VolUseDuration, ed1, sizeof(ed1)));
184 static void update_volmaxjobs(UAContext *ua, char *val, MEDIA_DBR *mr)
186 POOL_MEM query(PM_MESSAGE);
188 Mmsg(query, "UPDATE Media SET MaxVolJobs=%s WHERE MediaId=%s",
189 val, edit_int64(mr->MediaId,ed1));
190 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
191 ua->error_msg("%s", db_strerror(ua->db));
193 ua->info_msg(_("New max jobs is: %s\n"), val);
197 static void update_volmaxfiles(UAContext *ua, char *val, MEDIA_DBR *mr)
199 POOL_MEM query(PM_MESSAGE);
201 Mmsg(query, "UPDATE Media SET MaxVolFiles=%s WHERE MediaId=%s",
202 val, edit_int64(mr->MediaId, ed1));
203 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
204 ua->error_msg("%s", db_strerror(ua->db));
206 ua->info_msg(_("New max files is: %s\n"), val);
210 static void update_volmaxbytes(UAContext *ua, char *val, MEDIA_DBR *mr)
213 char ed1[50], ed2[50];
214 POOL_MEM query(PM_MESSAGE);
216 if (!size_to_uint64(val, strlen(val), &maxbytes)) {
217 ua->error_msg(_("Invalid max. bytes specification: %s\n"), val);
220 Mmsg(query, "UPDATE Media SET MaxVolBytes=%s WHERE MediaId=%s",
221 edit_uint64(maxbytes, ed1), edit_int64(mr->MediaId, ed2));
222 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
223 ua->error_msg("%s", db_strerror(ua->db));
225 ua->info_msg(_("New Max bytes is: %s\n"), edit_uint64(maxbytes, ed1));
229 static void update_volrecycle(UAContext *ua, char *val, MEDIA_DBR *mr)
234 POOL_MEM query(PM_MESSAGE);
235 if (!is_yesno(val, &recycle)) {
236 ua->error_msg(_("Invalid value. It must be yes or no.\n"));
239 Mmsg(query, "UPDATE Media SET Recycle=%d WHERE MediaId=%s",
240 recycle, edit_int64(mr->MediaId, ed1));
241 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
242 ua->error_msg("%s", db_strerror(ua->db));
244 ua->info_msg(_("New Recycle flag is: %s\n"),
245 mr->Recycle==1?_("yes"):_("no"));
249 static void update_volinchanger(UAContext *ua, char *val, MEDIA_DBR *mr)
254 POOL_MEM query(PM_MESSAGE);
255 if (!is_yesno(val, &InChanger)) {
256 ua->error_msg(_("Invalid value. It must be yes or no.\n"));
259 Mmsg(query, "UPDATE Media SET InChanger=%d WHERE MediaId=%s",
260 InChanger, edit_int64(mr->MediaId, ed1));
261 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
262 ua->error_msg("%s", db_strerror(ua->db));
264 ua->info_msg(_("New InChanger flag is: %s\n"),
265 mr->InChanger==1?_("yes"):_("no"));
270 static void update_volslot(UAContext *ua, char *val, MEDIA_DBR *mr)
274 memset(&pr, 0, sizeof(POOL_DBR));
275 pr.PoolId = mr->PoolId;
276 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
277 ua->error_msg("%s", db_strerror(ua->db));
280 mr->Slot = atoi(val);
281 if (pr.MaxVols > 0 && mr->Slot > (int)pr.MaxVols) {
282 ua->error_msg(_("Invalid slot, it must be between 0 and MaxVols=%d\n"),
287 * Make sure to use db_update... rather than doing this directly,
288 * so that any Slot is handled correctly.
290 if (!db_update_media_record(ua->jcr, ua->db, mr)) {
291 ua->error_msg(_("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
293 ua->info_msg(_("New Slot is: %d\n"), mr->Slot);
297 /* Modify the Pool in which this Volume is located */
298 void update_vol_pool(UAContext *ua, char *val, MEDIA_DBR *mr, POOL_DBR *opr)
301 POOL_MEM query(PM_MESSAGE);
302 char ed1[50], ed2[50];
304 memset(&pr, 0, sizeof(pr));
305 bstrncpy(pr.Name, val, sizeof(pr.Name));
306 if (!get_pool_dbr(ua, &pr)) {
309 mr->PoolId = pr.PoolId; /* set new PoolId */
313 Mmsg(query, "UPDATE Media SET PoolId=%s WHERE MediaId=%s",
314 edit_int64(mr->PoolId, ed1), edit_int64(mr->MediaId, ed2));
315 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
316 ua->error_msg("%s", db_strerror(ua->db));
318 ua->info_msg(_("New Pool is: %s\n"), pr.Name);
320 if (!db_update_pool_record(ua->jcr, ua->db, opr)) {
321 ua->error_msg("%s", db_strerror(ua->db));
324 if (!db_update_pool_record(ua->jcr, ua->db, &pr)) {
325 ua->error_msg("%s", db_strerror(ua->db));
331 /* Modify the RecyclePool of a Volume */
332 void update_vol_recyclepool(UAContext *ua, char *val, MEDIA_DBR *mr)
335 POOL_MEM query(PM_MESSAGE);
336 char ed1[50], ed2[50];
338 memset(&pr, 0, sizeof(pr));
339 bstrncpy(pr.Name, val, sizeof(pr.Name));
340 if (!get_pool_dbr(ua, &pr, NT_("recyclepool"))) {
343 /* pool = select_pool_resource(ua); */
344 mr->RecyclePoolId = pr.PoolId; /* get the PoolId */
347 Mmsg(query, "UPDATE Media SET RecyclePoolId=%s WHERE MediaId=%s",
348 edit_int64(mr->RecyclePoolId, ed1), edit_int64(mr->MediaId, ed2));
349 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
350 ua->error_msg("%s", db_strerror(ua->db));
352 ua->info_msg(_("New RecyclePool is: %s\n"), pr.Name);
358 * Refresh the Volume information from the Pool record
360 static void update_vol_from_pool(UAContext *ua, MEDIA_DBR *mr)
364 memset(&pr, 0, sizeof(pr));
365 pr.PoolId = mr->PoolId;
366 if (!db_get_pool_record(ua->jcr, ua->db, &pr) ||
367 !acl_access_ok(ua, Pool_ACL, pr.Name)) {
370 set_pool_dbr_defaults_in_media_dbr(mr, &pr);
371 if (!db_update_media_defaults(ua->jcr, ua->db, mr)) {
372 ua->error_msg(_("Error updating Volume record: ERR=%s"), db_strerror(ua->db));
374 ua->info_msg(_("Volume defaults updated from \"%s\" Pool record.\n"),
380 * Refresh the Volume information from the Pool record
383 static void update_all_vols_from_pool(UAContext *ua, const char *pool_name)
388 memset(&pr, 0, sizeof(pr));
389 memset(&mr, 0, sizeof(mr));
391 bstrncpy(pr.Name, pool_name, sizeof(pr.Name));
392 if (!get_pool_dbr(ua, &pr)) {
395 set_pool_dbr_defaults_in_media_dbr(&mr, &pr);
396 mr.PoolId = pr.PoolId;
397 if (!db_update_media_defaults(ua->jcr, ua->db, &mr)) {
398 ua->error_msg(_("Error updating Volume records: ERR=%s"), db_strerror(ua->db));
400 ua->info_msg(_("All Volume defaults updated from \"%s\" Pool record.\n"),
405 static void update_volenabled(UAContext *ua, char *val, MEDIA_DBR *mr)
407 mr->Enabled = get_enabled(ua, val);
408 if (mr->Enabled < 0) {
411 if (!db_update_media_record(ua->jcr, ua->db, mr)) {
412 ua->error_msg(_("Error updating media record Enabled: ERR=%s"), db_strerror(ua->db));
414 ua->info_msg(_("New Enabled is: %d\n"), mr->Enabled);
421 * Update a media record -- allows you to change the
422 * Volume status. E.g. if you want Bacula to stop
423 * writing on the volume, set it to anything other
426 static int update_volume(UAContext *ua)
436 NT_("VolStatus"), /* 0 */
437 NT_("VolRetention"), /* 1 */
438 NT_("VolUse"), /* 2 */
439 NT_("MaxVolJobs"), /* 3 */
440 NT_("MaxVolFiles"), /* 4 */
441 NT_("MaxVolBytes"), /* 5 */
442 NT_("Recycle"), /* 6 */
443 NT_("InChanger"), /* 7 */
446 NT_("FromPool"), /* 10 */
447 NT_("AllFromPool"), /* 11 !!! see below !!! */
448 NT_("Enabled"), /* 12 */
449 NT_("RecyclePool"), /* 13 */
452 #define AllFromPool 11 /* keep this updated with above */
454 for (i=0; kw[i]; i++) {
457 if ((j=find_arg_with_value(ua, kw[i])) > 0) {
458 /* If all from pool don't select a media record */
459 if (i != AllFromPool && !select_media_dbr(ua, &mr)) {
464 update_volstatus(ua, ua->argv[j], &mr);
467 update_volretention(ua, ua->argv[j], &mr);
470 update_voluseduration(ua, ua->argv[j], &mr);
473 update_volmaxjobs(ua, ua->argv[j], &mr);
476 update_volmaxfiles(ua, ua->argv[j], &mr);
479 update_volmaxbytes(ua, ua->argv[j], &mr);
482 update_volrecycle(ua, ua->argv[j], &mr);
485 update_volinchanger(ua, ua->argv[j], &mr);
488 update_volslot(ua, ua->argv[j], &mr);
491 memset(&pr, 0, sizeof(POOL_DBR));
492 pr.PoolId = mr.PoolId;
493 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
494 ua->error_msg("%s", db_strerror(ua->db));
497 update_vol_pool(ua, ua->argv[j], &mr, &pr);
500 update_vol_from_pool(ua, &mr);
503 update_all_vols_from_pool(ua, ua->argv[j]);
506 update_volenabled(ua, ua->argv[j], &mr);
509 update_vol_recyclepool(ua, ua->argv[j], &mr);
517 start_prompt(ua, _("Parameters to modify:\n"));
518 add_prompt(ua, _("Volume Status")); /* 0 */
519 add_prompt(ua, _("Volume Retention Period")); /* 1 */
520 add_prompt(ua, _("Volume Use Duration")); /* 2 */
521 add_prompt(ua, _("Maximum Volume Jobs")); /* 3 */
522 add_prompt(ua, _("Maximum Volume Files")); /* 4 */
523 add_prompt(ua, _("Maximum Volume Bytes")); /* 5 */
524 add_prompt(ua, _("Recycle Flag")); /* 6 */
525 add_prompt(ua, _("Slot")); /* 7 */
526 add_prompt(ua, _("InChanger Flag")); /* 8 */
527 add_prompt(ua, _("Volume Files")); /* 9 */
528 add_prompt(ua, _("Pool")); /* 10 */
529 add_prompt(ua, _("Volume from Pool")); /* 11 */
530 add_prompt(ua, _("All Volumes from Pool")); /* 12 */
531 add_prompt(ua, _("Enabled")), /* 13 */
532 add_prompt(ua, _("RecyclePool")), /* 14 */
533 add_prompt(ua, _("Done")); /* 15 */
534 i = do_prompt(ua, "", _("Select parameter to modify"), NULL, 0);
536 /* For All Volumes from Pool and Done, we don't need a Volume record */
537 if (i != 12 && i != 15) {
538 if (!select_media_dbr(ua, &mr)) { /* Get Volume record */
541 ua->info_msg(_("Updating Volume \"%s\"\n"), mr.VolumeName);
544 case 0: /* Volume Status */
545 /* Modify Volume Status */
546 ua->info_msg(_("Current Volume status is: %s\n"), mr.VolStatus);
547 start_prompt(ua, _("Possible Values are:\n"));
548 add_prompt(ua, NT_("Append"));
549 add_prompt(ua, NT_("Archive"));
550 add_prompt(ua, NT_("Disabled"));
551 add_prompt(ua, NT_("Full"));
552 add_prompt(ua, NT_("Used"));
553 add_prompt(ua, NT_("Cleaning"));
554 if (strcmp(mr.VolStatus, NT_("Purged")) == 0) {
555 add_prompt(ua, NT_("Recycle"));
557 add_prompt(ua, NT_("Read-Only"));
558 if (do_prompt(ua, "", _("Choose new Volume Status"), ua->cmd, sizeof(mr.VolStatus)) < 0) {
561 update_volstatus(ua, ua->cmd, &mr);
563 case 1: /* Retention */
564 ua->info_msg(_("Current retention period is: %s\n"),
565 edit_utime(mr.VolRetention, ed1, sizeof(ed1)));
566 if (!get_cmd(ua, _("Enter Volume Retention period: "))) {
569 update_volretention(ua, ua->cmd, &mr);
572 case 2: /* Use Duration */
573 ua->info_msg(_("Current use duration is: %s\n"),
574 edit_utime(mr.VolUseDuration, ed1, sizeof(ed1)));
575 if (!get_cmd(ua, _("Enter Volume Use Duration: "))) {
578 update_voluseduration(ua, ua->cmd, &mr);
581 case 3: /* Max Jobs */
582 ua->info_msg(_("Current max jobs is: %u\n"), mr.MaxVolJobs);
583 if (!get_pint(ua, _("Enter new Maximum Jobs: "))) {
586 update_volmaxjobs(ua, ua->cmd, &mr);
589 case 4: /* Max Files */
590 ua->info_msg(_("Current max files is: %u\n"), mr.MaxVolFiles);
591 if (!get_pint(ua, _("Enter new Maximum Files: "))) {
594 update_volmaxfiles(ua, ua->cmd, &mr);
597 case 5: /* Max Bytes */
598 ua->info_msg(_("Current value is: %s\n"), edit_uint64(mr.MaxVolBytes, ed1));
599 if (!get_cmd(ua, _("Enter new Maximum Bytes: "))) {
602 update_volmaxbytes(ua, ua->cmd, &mr);
606 case 6: /* Recycle */
607 ua->info_msg(_("Current recycle flag is: %s\n"),
608 mr.Recycle==1?_("yes"):_("no"));
609 if (!get_yesno(ua, _("Enter new Recycle status: "))) {
612 update_volrecycle(ua, ua->cmd, &mr);
616 ua->info_msg(_("Current Slot is: %d\n"), mr.Slot);
617 if (!get_pint(ua, _("Enter new Slot: "))) {
620 update_volslot(ua, ua->cmd, &mr);
623 case 8: /* InChanger */
624 ua->info_msg(_("Current InChanger flag is: %d\n"), mr.InChanger);
625 if (!get_yesno(ua, _("Set InChanger flag? yes/no: "))) {
628 mr.InChanger = ua->pint32_val;
630 * Make sure to use db_update... rather than doing this directly,
631 * so that any Slot is handled correctly.
633 if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
634 ua->error_msg(_("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
636 ua->info_msg(_("New InChanger flag is: %d\n"), mr.InChanger);
641 case 9: /* Volume Files */
643 ua->warning_msg(_("Warning changing Volume Files can result\n"
644 "in loss of data on your Volume\n\n"));
645 ua->info_msg(_("Current Volume Files is: %u\n"), mr.VolFiles);
646 if (!get_pint(ua, _("Enter new number of Files for Volume: "))) {
649 VolFiles = ua->pint32_val;
650 if (VolFiles != (int)(mr.VolFiles + 1)) {
651 ua->warning_msg(_("Normally, you should only increase Volume Files by one!\n"));
652 if (!get_yesno(ua, _("Continue? (yes/no): ")) || ua->pint32_val == 0) {
656 query = get_pool_memory(PM_MESSAGE);
657 Mmsg(query, "UPDATE Media SET VolFiles=%u WHERE MediaId=%s",
658 VolFiles, edit_int64(mr.MediaId, ed1));
659 if (!db_sql_query(ua->db, query, NULL, NULL)) {
660 ua->error_msg("%s", db_strerror(ua->db));
662 ua->info_msg(_("New Volume Files is: %u\n"), VolFiles);
664 free_pool_memory(query);
667 case 10: /* Volume's Pool */
668 memset(&pr, 0, sizeof(POOL_DBR));
669 pr.PoolId = mr.PoolId;
670 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
671 ua->error_msg("%s", db_strerror(ua->db));
674 ua->info_msg(_("Current Pool is: %s\n"), pr.Name);
675 if (!get_cmd(ua, _("Enter new Pool name: "))) {
678 update_vol_pool(ua, ua->cmd, &mr, &pr);
682 update_vol_from_pool(ua, &mr);
685 pool = select_pool_resource(ua);
687 update_all_vols_from_pool(ua, pool->name());
692 ua->info_msg(_("Current Enabled is: %d\n"), mr.Enabled);
693 if (!get_cmd(ua, _("Enter new Enabled: "))) {
696 if (strcasecmp(ua->cmd, "yes") == 0 || strcasecmp(ua->cmd, "true") == 0) {
698 } else if (strcasecmp(ua->cmd, "no") == 0 || strcasecmp(ua->cmd, "false") == 0) {
700 } else if (strcasecmp(ua->cmd, "archived") == 0) {
703 mr.Enabled = atoi(ua->cmd);
705 update_volenabled(ua, ua->cmd, &mr);
709 memset(&pr, 0, sizeof(POOL_DBR));
710 pr.PoolId = mr.RecyclePoolId;
711 if (db_get_pool_record(ua->jcr, ua->db, &pr)) {
712 ua->info_msg(_("Current RecyclePool is: %s\n"), pr.Name);
714 ua->warning_msg(_("No current RecyclePool\n"));
716 if (!get_cmd(ua, _("Enter new RecyclePool name: "))) {
719 update_vol_recyclepool(ua, ua->cmd, &mr);
722 default: /* Done or error */
723 ua->info_msg(_("Selection terminated.\n"));
731 * Update pool record -- pull info from current POOL resource
733 static bool update_pool(UAContext *ua)
741 pool = get_pool_resource(ua);
746 memset(&pr, 0, sizeof(pr));
747 bstrncpy(pr.Name, pool->name(), sizeof(pr.Name));
748 if (!get_pool_dbr(ua, &pr)) {
752 set_pooldbr_from_poolres(&pr, pool, POOL_OP_UPDATE); /* update */
753 set_pooldbr_recyclepoolid(ua->jcr, ua->db, &pr, pool);
755 id = db_update_pool_record(ua->jcr, ua->db, &pr);
757 ua->error_msg(_("db_update_pool_record returned %d. ERR=%s\n"),
758 id, db_strerror(ua->db));
760 query = get_pool_memory(PM_MESSAGE);
761 Mmsg(query, list_pool, edit_int64(pr.PoolId, ed1));
762 db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST);
763 free_pool_memory(query);
764 ua->info_msg(_("Pool DB record updated from resource.\n"));
769 * Update a Job record -- allows you to change the
770 * date fields in a Job record. This helps when
771 * providing migration from other vendors.
773 static bool update_job(UAContext *ua)
776 char ed1[50], ed2[50];
777 POOL_MEM cmd(PM_MESSAGE);
781 char *client_name = NULL;
782 char *start_time = NULL;
784 NT_("starttime"), /* 0 */
785 NT_("client"), /* 1 */
788 Dmsg1(200, "cmd=%s\n", ua->cmd);
789 i = find_arg_with_value(ua, NT_("jobid"));
791 ua->error_msg(_("Expect JobId keyword, not found.\n"));
794 memset(&jr, 0, sizeof(jr));
795 memset(&cr, 0, sizeof(cr));
796 jr.JobId = str_to_int64(ua->argv[i]);
797 if (!db_get_job_record(ua->jcr, ua->db, &jr)) {
798 ua->error_msg("%s", db_strerror(ua->db));
802 for (i=0; kw[i]; i++) {
804 if ((j=find_arg_with_value(ua, kw[i])) >= 0) {
806 case 0: /* start time */
807 start_time = ua->argv[j];
809 case 1: /* Client name */
810 client_name = ua->argv[j];
815 if (!client_name && !start_time) {
816 ua->error_msg(_("Neither Client nor StartTime specified.\n"));
820 if (!get_client_dbr(ua, &cr)) {
823 jr.ClientId = cr.ClientId;
828 StartTime = str_to_utime(start_time);
829 if (StartTime == 0) {
830 ua->error_msg(_("Improper date format: %s\n"), ua->argv[i]);
833 delta_start = StartTime - jr.StartTime;
834 Dmsg3(200, "ST=%d jr.ST=%d delta=%d\n", (time_t)StartTime,
835 (time_t)jr.StartTime, (time_t)delta_start);
836 jr.StartTime = (time_t)StartTime;
837 jr.SchedTime += (time_t)delta_start;
838 jr.EndTime += (time_t)delta_start;
839 jr.JobTDate += delta_start;
840 /* Convert to DB times */
841 bstrutime(jr.cStartTime, sizeof(jr.cStartTime), jr.StartTime);
842 bstrutime(jr.cSchedTime, sizeof(jr.cSchedTime), jr.SchedTime);
843 bstrutime(jr.cEndTime, sizeof(jr.cEndTime), jr.EndTime);
845 Mmsg(cmd, "UPDATE Job SET ClientId=%s,StartTime='%s',SchedTime='%s',"
846 "EndTime='%s',JobTDate=%s WHERE JobId=%s",
847 edit_int64(jr.ClientId, ed1),
851 edit_uint64(jr.JobTDate, ed1),
852 edit_int64(jr.JobId, ed2));
853 if (!db_sql_query(ua->db, cmd.c_str(), NULL, NULL)) {
854 ua->error_msg("%s", db_strerror(ua->db));