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 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 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)
437 NT_("VolStatus"), /* 0 */
438 NT_("VolRetention"), /* 1 */
439 NT_("VolUse"), /* 2 */
440 NT_("MaxVolJobs"), /* 3 */
441 NT_("MaxVolFiles"), /* 4 */
442 NT_("MaxVolBytes"), /* 5 */
443 NT_("Recycle"), /* 6 */
444 NT_("InChanger"), /* 7 */
447 NT_("FromPool"), /* 10 */
448 NT_("AllFromPool"), /* 11 !!! see below !!! */
449 NT_("Enabled"), /* 12 */
450 NT_("RecyclePool"), /* 13 */
453 #define AllFromPool 11 /* keep this updated with above */
455 for (i=0; kw[i]; i++) {
458 if ((j=find_arg_with_value(ua, kw[i])) > 0) {
459 /* If all from pool don't select a media record */
460 if (i != AllFromPool && !select_media_dbr(ua, &mr)) {
465 update_volstatus(ua, ua->argv[j], &mr);
468 update_volretention(ua, ua->argv[j], &mr);
471 update_voluseduration(ua, ua->argv[j], &mr);
474 update_volmaxjobs(ua, ua->argv[j], &mr);
477 update_volmaxfiles(ua, ua->argv[j], &mr);
480 update_volmaxbytes(ua, ua->argv[j], &mr);
483 update_volrecycle(ua, ua->argv[j], &mr);
486 update_volinchanger(ua, ua->argv[j], &mr);
489 update_volslot(ua, ua->argv[j], &mr);
492 memset(&pr, 0, sizeof(POOL_DBR));
493 pr.PoolId = mr.PoolId;
494 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
495 ua->error_msg("%s", db_strerror(ua->db));
498 update_vol_pool(ua, ua->argv[j], &mr, &pr);
501 update_vol_from_pool(ua, &mr);
504 update_all_vols_from_pool(ua, ua->argv[j]);
507 update_volenabled(ua, ua->argv[j], &mr);
510 update_vol_recyclepool(ua, ua->argv[j], &mr);
518 start_prompt(ua, _("Parameters to modify:\n"));
519 add_prompt(ua, _("Volume Status")); /* 0 */
520 add_prompt(ua, _("Volume Retention Period")); /* 1 */
521 add_prompt(ua, _("Volume Use Duration")); /* 2 */
522 add_prompt(ua, _("Maximum Volume Jobs")); /* 3 */
523 add_prompt(ua, _("Maximum Volume Files")); /* 4 */
524 add_prompt(ua, _("Maximum Volume Bytes")); /* 5 */
525 add_prompt(ua, _("Recycle Flag")); /* 6 */
526 add_prompt(ua, _("Slot")); /* 7 */
527 add_prompt(ua, _("InChanger Flag")); /* 8 */
528 add_prompt(ua, _("Volume Files")); /* 9 */
529 add_prompt(ua, _("Pool")); /* 10 */
530 add_prompt(ua, _("Volume from Pool")); /* 11 */
531 add_prompt(ua, _("All Volumes from Pool")); /* 12 */
532 add_prompt(ua, _("Enabled")), /* 13 */
533 add_prompt(ua, _("RecyclePool")), /* 14 */
534 add_prompt(ua, _("Done")); /* 15 */
535 i = do_prompt(ua, "", _("Select parameter to modify"), NULL, 0);
537 /* For All Volumes from Pool and Done, we don't need a Volume record */
538 if (i != 12 && i != 15) {
539 if (!select_media_dbr(ua, &mr)) { /* Get Volume record */
542 ua->info_msg(_("Updating Volume \"%s\"\n"), mr.VolumeName);
545 case 0: /* Volume Status */
546 /* Modify Volume Status */
547 ua->info_msg(_("Current Volume status is: %s\n"), mr.VolStatus);
548 start_prompt(ua, _("Possible Values are:\n"));
549 add_prompt(ua, NT_("Append"));
550 add_prompt(ua, NT_("Archive"));
551 add_prompt(ua, NT_("Disabled"));
552 add_prompt(ua, NT_("Full"));
553 add_prompt(ua, NT_("Used"));
554 add_prompt(ua, NT_("Cleaning"));
555 if (strcmp(mr.VolStatus, NT_("Purged")) == 0) {
556 add_prompt(ua, NT_("Recycle"));
558 add_prompt(ua, NT_("Read-Only"));
559 if (do_prompt(ua, "", _("Choose new Volume Status"), ua->cmd, sizeof(mr.VolStatus)) < 0) {
562 update_volstatus(ua, ua->cmd, &mr);
564 case 1: /* Retention */
565 ua->info_msg(_("Current retention period is: %s\n"),
566 edit_utime(mr.VolRetention, ed1, sizeof(ed1)));
567 if (!get_cmd(ua, _("Enter Volume Retention period: "))) {
570 update_volretention(ua, ua->cmd, &mr);
573 case 2: /* Use Duration */
574 ua->info_msg(_("Current use duration is: %s\n"),
575 edit_utime(mr.VolUseDuration, ed1, sizeof(ed1)));
576 if (!get_cmd(ua, _("Enter Volume Use Duration: "))) {
579 update_voluseduration(ua, ua->cmd, &mr);
582 case 3: /* Max Jobs */
583 ua->info_msg(_("Current max jobs is: %u\n"), mr.MaxVolJobs);
584 if (!get_pint(ua, _("Enter new Maximum Jobs: "))) {
587 update_volmaxjobs(ua, ua->cmd, &mr);
590 case 4: /* Max Files */
591 ua->info_msg(_("Current max files is: %u\n"), mr.MaxVolFiles);
592 if (!get_pint(ua, _("Enter new Maximum Files: "))) {
595 update_volmaxfiles(ua, ua->cmd, &mr);
598 case 5: /* Max Bytes */
599 ua->info_msg(_("Current value is: %s\n"), edit_uint64(mr.MaxVolBytes, ed1));
600 if (!get_cmd(ua, _("Enter new Maximum Bytes: "))) {
603 update_volmaxbytes(ua, ua->cmd, &mr);
607 case 6: /* Recycle */
608 ua->info_msg(_("Current recycle flag is: %s\n"),
609 mr.Recycle==1?_("yes"):_("no"));
610 if (!get_yesno(ua, _("Enter new Recycle status: "))) {
613 update_volrecycle(ua, ua->cmd, &mr);
617 ua->info_msg(_("Current Slot is: %d\n"), mr.Slot);
618 if (!get_pint(ua, _("Enter new Slot: "))) {
621 update_volslot(ua, ua->cmd, &mr);
624 case 8: /* InChanger */
625 ua->info_msg(_("Current InChanger flag is: %d\n"), mr.InChanger);
626 bsnprintf(buf, sizeof(buf), _("Set InChanger flag for Volume \"%s\": yes/no: "),
628 if (!get_yesno(ua, buf)) {
631 mr.InChanger = ua->pint32_val;
633 * Make sure to use db_update... rather than doing this directly,
634 * so that any Slot is handled correctly.
636 if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
637 ua->error_msg(_("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
639 ua->info_msg(_("New InChanger flag is: %d\n"), mr.InChanger);
644 case 9: /* Volume Files */
646 ua->warning_msg(_("Warning changing Volume Files can result\n"
647 "in loss of data on your Volume\n\n"));
648 ua->info_msg(_("Current Volume Files is: %u\n"), mr.VolFiles);
649 if (!get_pint(ua, _("Enter new number of Files for Volume: "))) {
652 VolFiles = ua->pint32_val;
653 if (VolFiles != (int)(mr.VolFiles + 1)) {
654 ua->warning_msg(_("Normally, you should only increase Volume Files by one!\n"));
655 if (!get_yesno(ua, _("Increase Volume Files? (yes/no): ")) || ua->pint32_val == 0) {
659 query = get_pool_memory(PM_MESSAGE);
660 Mmsg(query, "UPDATE Media SET VolFiles=%u WHERE MediaId=%s",
661 VolFiles, edit_int64(mr.MediaId, ed1));
662 if (!db_sql_query(ua->db, query, NULL, NULL)) {
663 ua->error_msg("%s", db_strerror(ua->db));
665 ua->info_msg(_("New Volume Files is: %u\n"), VolFiles);
667 free_pool_memory(query);
670 case 10: /* Volume's Pool */
671 memset(&pr, 0, sizeof(POOL_DBR));
672 pr.PoolId = mr.PoolId;
673 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
674 ua->error_msg("%s", db_strerror(ua->db));
677 ua->info_msg(_("Current Pool is: %s\n"), pr.Name);
678 if (!get_cmd(ua, _("Enter new Pool name: "))) {
681 update_vol_pool(ua, ua->cmd, &mr, &pr);
685 update_vol_from_pool(ua, &mr);
688 pool = select_pool_resource(ua);
690 update_all_vols_from_pool(ua, pool->name());
695 ua->info_msg(_("Current Enabled is: %d\n"), mr.Enabled);
696 if (!get_cmd(ua, _("Enter new Enabled: "))) {
699 if (strcasecmp(ua->cmd, "yes") == 0 || strcasecmp(ua->cmd, "true") == 0) {
701 } else if (strcasecmp(ua->cmd, "no") == 0 || strcasecmp(ua->cmd, "false") == 0) {
703 } else if (strcasecmp(ua->cmd, "archived") == 0) {
706 mr.Enabled = atoi(ua->cmd);
708 update_volenabled(ua, ua->cmd, &mr);
712 memset(&pr, 0, sizeof(POOL_DBR));
713 pr.PoolId = mr.RecyclePoolId;
714 if (db_get_pool_record(ua->jcr, ua->db, &pr)) {
715 ua->info_msg(_("Current RecyclePool is: %s\n"), pr.Name);
717 ua->warning_msg(_("No current RecyclePool\n"));
719 if (!get_cmd(ua, _("Enter new RecyclePool name: "))) {
722 update_vol_recyclepool(ua, ua->cmd, &mr);
725 default: /* Done or error */
726 ua->info_msg(_("Selection terminated.\n"));
734 * Update pool record -- pull info from current POOL resource
736 static bool update_pool(UAContext *ua)
744 pool = get_pool_resource(ua);
749 memset(&pr, 0, sizeof(pr));
750 bstrncpy(pr.Name, pool->name(), sizeof(pr.Name));
751 if (!get_pool_dbr(ua, &pr)) {
755 set_pooldbr_from_poolres(&pr, pool, POOL_OP_UPDATE); /* update */
756 set_pooldbr_recyclepoolid(ua->jcr, ua->db, &pr, pool);
758 id = db_update_pool_record(ua->jcr, ua->db, &pr);
760 ua->error_msg(_("db_update_pool_record returned %d. ERR=%s\n"),
761 id, db_strerror(ua->db));
763 query = get_pool_memory(PM_MESSAGE);
764 Mmsg(query, list_pool, edit_int64(pr.PoolId, ed1));
765 db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST);
766 free_pool_memory(query);
767 ua->info_msg(_("Pool DB record updated from resource.\n"));
772 * Update a Job record -- allows you to change the
773 * date fields in a Job record. This helps when
774 * providing migration from other vendors.
776 static bool update_job(UAContext *ua)
779 char ed1[50], ed2[50];
780 POOL_MEM cmd(PM_MESSAGE);
784 char *client_name = NULL;
785 char *start_time = NULL;
787 NT_("starttime"), /* 0 */
788 NT_("client"), /* 1 */
791 Dmsg1(200, "cmd=%s\n", ua->cmd);
792 i = find_arg_with_value(ua, NT_("jobid"));
794 ua->error_msg(_("Expect JobId keyword, not found.\n"));
797 memset(&jr, 0, sizeof(jr));
798 memset(&cr, 0, sizeof(cr));
799 jr.JobId = str_to_int64(ua->argv[i]);
800 if (!db_get_job_record(ua->jcr, ua->db, &jr)) {
801 ua->error_msg("%s", db_strerror(ua->db));
805 for (i=0; kw[i]; i++) {
807 if ((j=find_arg_with_value(ua, kw[i])) >= 0) {
809 case 0: /* start time */
810 start_time = ua->argv[j];
812 case 1: /* Client name */
813 client_name = ua->argv[j];
818 if (!client_name && !start_time) {
819 ua->error_msg(_("Neither Client nor StartTime specified.\n"));
823 if (!get_client_dbr(ua, &cr)) {
826 jr.ClientId = cr.ClientId;
831 StartTime = str_to_utime(start_time);
832 if (StartTime == 0) {
833 ua->error_msg(_("Improper date format: %s\n"), ua->argv[i]);
836 delta_start = StartTime - jr.StartTime;
837 Dmsg3(200, "ST=%d jr.ST=%d delta=%d\n", (time_t)StartTime,
838 (time_t)jr.StartTime, (time_t)delta_start);
839 jr.StartTime = (time_t)StartTime;
840 jr.SchedTime += (time_t)delta_start;
841 jr.EndTime += (time_t)delta_start;
842 jr.JobTDate += delta_start;
843 /* Convert to DB times */
844 bstrutime(jr.cStartTime, sizeof(jr.cStartTime), jr.StartTime);
845 bstrutime(jr.cSchedTime, sizeof(jr.cSchedTime), jr.SchedTime);
846 bstrutime(jr.cEndTime, sizeof(jr.cEndTime), jr.EndTime);
848 Mmsg(cmd, "UPDATE Job SET ClientId=%s,StartTime='%s',SchedTime='%s',"
849 "EndTime='%s',JobTDate=%s WHERE JobId=%s",
850 edit_int64(jr.ClientId, ed1),
854 edit_uint64(jr.JobTDate, ed1),
855 edit_int64(jr.JobId, ed2));
856 if (!db_sql_query(ua->db, cmd.c_str(), NULL, NULL)) {
857 ua->error_msg("%s", db_strerror(ua->db));