]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/ua_update.c
ebl add update volume=xxx recyclepool=yyyy
[bacula/bacula] / bacula / src / dird / ua_update.c
1 /*
2  *
3  *   Bacula Director -- Update command processing
4  *     Split from ua_cmds.c March 2005
5  *
6  *     Kern Sibbald, September MM
7  *
8  *   Version $Id$
9  */
10 /*
11    Bacula® - The Network Backup Solution
12
13    Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
14
15    The main author of Bacula is Kern Sibbald, with contributions from
16    many others, a complete list can be found in the file AUTHORS.
17    This program is Free Software; you can redistribute it and/or
18    modify it under the terms of version two of the GNU General Public
19    License as published by the Free Software Foundation plus additions
20    that are listed in the file LICENSE.
21
22    This program is distributed in the hope that it will be useful, but
23    WITHOUT ANY WARRANTY; without even the implied warranty of
24    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25    General Public License for more details.
26
27    You should have received a copy of the GNU General Public License
28    along with this program; if not, write to the Free Software
29    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
30    02110-1301, USA.
31
32    Bacula® is a registered trademark of John Walker.
33    The licensor of Bacula is the Free Software Foundation Europe
34    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
35    Switzerland, email:ftf@fsfeurope.org.
36 */
37
38 #include "bacula.h"
39 #include "dird.h"
40
41 /* Forward referenced functions */
42 static int update_volume(UAContext *ua);
43 static bool update_pool(UAContext *ua);
44
45 /*
46  * Update a Pool Record in the database.
47  *  It is always updated from the Resource record.
48  *
49  *    update pool=<pool-name>
50  *         updates pool from Pool resource
51  *    update media pool=<pool-name> volume=<volume-name>
52  *         changes pool info for volume
53  *    update slots [scan=...]
54  *         updates autochanger slots
55  */
56 int update_cmd(UAContext *ua, const char *cmd)
57 {
58    static const char *kw[] = {
59       NT_("media"),  /* 0 */
60       NT_("volume"), /* 1 */
61       NT_("pool"),   /* 2 */
62       NT_("slots"),  /* 3 */
63       NULL};
64
65    if (!open_client_db(ua)) {
66       return 1;
67    }
68
69    switch (find_arg_keyword(ua, kw)) {
70    case 0:
71    case 1:
72       update_volume(ua);
73       return 1;
74    case 2:
75       update_pool(ua);
76       return 1;
77    case 3:
78       update_slots(ua);
79       return 1;
80    default:
81       break;
82    }
83
84    start_prompt(ua, _("Update choice:\n"));
85    add_prompt(ua, _("Volume parameters"));
86    add_prompt(ua, _("Pool from resource"));
87    add_prompt(ua, _("Slots from autochanger"));
88    switch (do_prompt(ua, _("item"), _("Choose catalog item to update"), NULL, 0)) {
89    case 0:
90       update_volume(ua);
91       break;
92    case 1:
93       update_pool(ua);
94       break;
95    case 2:
96       update_slots(ua);
97       break;
98    default:
99       break;
100    }
101    return 1;
102 }
103
104 static void update_volstatus(UAContext *ua, const char *val, MEDIA_DBR *mr)
105 {
106    POOL_MEM query(PM_MESSAGE);
107    const char *kw[] = {
108       NT_("Append"),
109       NT_("Archive"),
110       NT_("Disabled"),
111       NT_("Full"),
112       NT_("Used"),
113       NT_("Cleaning"),
114       NT_("Recycle"),
115       NT_("Read-Only"),
116       NT_("Error"),
117       NULL};
118    bool found = false;
119    int i;
120
121    for (i=0; kw[i]; i++) {
122       if (strcasecmp(val, kw[i]) == 0) {
123          found = true;
124          break;
125       }
126    }
127    if (!found) {
128       bsendmsg(ua, _("Invalid VolStatus specified: %s\n"), val);
129    } else {
130       char ed1[50];
131       bstrncpy(mr->VolStatus, kw[i], sizeof(mr->VolStatus));
132       Mmsg(query, "UPDATE Media SET VolStatus='%s' WHERE MediaId=%s",
133          mr->VolStatus, edit_int64(mr->MediaId,ed1));
134       if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
135          bsendmsg(ua, "%s", db_strerror(ua->db));
136       } else {
137          bsendmsg(ua, _("New Volume status is: %s\n"), mr->VolStatus);
138       }
139    }
140 }
141
142 static void update_volretention(UAContext *ua, char *val, MEDIA_DBR *mr)
143 {
144    char ed1[150], ed2[50];
145    POOL_MEM query(PM_MESSAGE);
146    if (!duration_to_utime(val, &mr->VolRetention)) {
147       bsendmsg(ua, _("Invalid retention period specified: %s\n"), val);
148       return;
149    }
150    Mmsg(query, "UPDATE Media SET VolRetention=%s WHERE MediaId=%s",
151       edit_uint64(mr->VolRetention, ed1), edit_int64(mr->MediaId,ed2));
152    if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
153       bsendmsg(ua, "%s", db_strerror(ua->db));
154    } else {
155       bsendmsg(ua, _("New retention period is: %s\n"),
156          edit_utime(mr->VolRetention, ed1, sizeof(ed1)));
157    }
158 }
159
160 static void update_voluseduration(UAContext *ua, char *val, MEDIA_DBR *mr)
161 {
162    char ed1[150], ed2[50];
163    POOL_MEM query(PM_MESSAGE);
164
165    if (!duration_to_utime(val, &mr->VolUseDuration)) {
166       bsendmsg(ua, _("Invalid use duration specified: %s\n"), val);
167       return;
168    }
169    Mmsg(query, "UPDATE Media SET VolUseDuration=%s WHERE MediaId=%s",
170       edit_uint64(mr->VolUseDuration, ed1), edit_int64(mr->MediaId,ed2));
171    if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
172       bsendmsg(ua, "%s", db_strerror(ua->db));
173    } else {
174       bsendmsg(ua, _("New use duration is: %s\n"),
175          edit_utime(mr->VolUseDuration, ed1, sizeof(ed1)));
176    }
177 }
178
179 static void update_volmaxjobs(UAContext *ua, char *val, MEDIA_DBR *mr)
180 {
181    POOL_MEM query(PM_MESSAGE);
182    char ed1[50];
183    Mmsg(query, "UPDATE Media SET MaxVolJobs=%s WHERE MediaId=%s",
184       val, edit_int64(mr->MediaId,ed1));
185    if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
186       bsendmsg(ua, "%s", db_strerror(ua->db));
187    } else {
188       bsendmsg(ua, _("New max jobs is: %s\n"), val);
189    }
190 }
191
192 static void update_volmaxfiles(UAContext *ua, char *val, MEDIA_DBR *mr)
193 {
194    POOL_MEM query(PM_MESSAGE);
195    char ed1[50];
196    Mmsg(query, "UPDATE Media SET MaxVolFiles=%s WHERE MediaId=%s",
197       val, edit_int64(mr->MediaId, ed1));
198    if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
199       bsendmsg(ua, "%s", db_strerror(ua->db));
200    } else {
201       bsendmsg(ua, _("New max files is: %s\n"), val);
202    }
203 }
204
205 static void update_volmaxbytes(UAContext *ua, char *val, MEDIA_DBR *mr)
206 {
207    uint64_t maxbytes;
208    char ed1[50], ed2[50];
209    POOL_MEM query(PM_MESSAGE);
210
211    if (!size_to_uint64(val, strlen(val), &maxbytes)) {
212       bsendmsg(ua, _("Invalid max. bytes specification: %s\n"), val);
213       return;
214    }
215    Mmsg(query, "UPDATE Media SET MaxVolBytes=%s WHERE MediaId=%s",
216       edit_uint64(maxbytes, ed1), edit_int64(mr->MediaId, ed2));
217    if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
218       bsendmsg(ua, "%s", db_strerror(ua->db));
219    } else {
220       bsendmsg(ua, _("New Max bytes is: %s\n"), edit_uint64(maxbytes, ed1));
221    }
222 }
223
224 static void update_volrecycle(UAContext *ua, char *val, MEDIA_DBR *mr)
225 {
226    int recycle;
227    char ed1[50];
228
229    POOL_MEM query(PM_MESSAGE);
230    if (!is_yesno(val, &recycle)) {
231       bsendmsg(ua, _("Invalid value. It must be yes or no.\n"));
232       return;
233    }
234    Mmsg(query, "UPDATE Media SET Recycle=%d WHERE MediaId=%s",
235       recycle, edit_int64(mr->MediaId, ed1));
236    if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
237       bsendmsg(ua, "%s", db_strerror(ua->db));
238    } else {
239       bsendmsg(ua, _("New Recycle flag is: %s\n"),
240          mr->Recycle==1?_("yes"):_("no"));
241    }
242 }
243
244 static void update_volinchanger(UAContext *ua, char *val, MEDIA_DBR *mr)
245 {
246    int InChanger;
247    char ed1[50];
248
249    POOL_MEM query(PM_MESSAGE);
250    if (!is_yesno(val, &InChanger)) {
251       bsendmsg(ua, _("Invalid value. It must be yes or no.\n"));
252       return;
253    }
254    Mmsg(query, "UPDATE Media SET InChanger=%d WHERE MediaId=%s",
255       InChanger, edit_int64(mr->MediaId, ed1));
256    if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
257       bsendmsg(ua, "%s", db_strerror(ua->db));
258    } else {
259       bsendmsg(ua, _("New InChanger flag is: %s\n"),
260          mr->InChanger==1?_("yes"):_("no"));
261    }
262 }
263
264
265 static void update_volslot(UAContext *ua, char *val, MEDIA_DBR *mr)
266 {
267    POOL_DBR pr;
268
269    memset(&pr, 0, sizeof(POOL_DBR));
270    pr.PoolId = mr->PoolId;
271    if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
272       bsendmsg(ua, "%s", db_strerror(ua->db));
273       return;
274    }
275    mr->Slot = atoi(val);
276    if (pr.MaxVols > 0 && mr->Slot > (int)pr.MaxVols) {
277       bsendmsg(ua, _("Invalid slot, it must be between 0 and MaxVols=%d\n"),
278          pr.MaxVols);
279       return;
280    }
281    /*
282     * Make sure to use db_update... rather than doing this directly,
283     *   so that any Slot is handled correctly.
284     */
285    if (!db_update_media_record(ua->jcr, ua->db, mr)) {
286       bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
287    } else {
288       bsendmsg(ua, _("New Slot is: %d\n"), mr->Slot);
289    }
290 }
291
292 /* Modify the Pool in which this Volume is located */
293 void update_vol_pool(UAContext *ua, char *val, MEDIA_DBR *mr, POOL_DBR *opr)
294 {
295    POOL_DBR pr;
296    POOLMEM *query;
297    char ed1[50], ed2[50];
298
299    memset(&pr, 0, sizeof(pr));
300    bstrncpy(pr.Name, val, sizeof(pr.Name));
301    if (!get_pool_dbr(ua, &pr)) {
302       return;
303    }
304    mr->PoolId = pr.PoolId;            /* set new PoolId */
305    /*
306     */
307    query = get_pool_memory(PM_MESSAGE);
308    db_lock(ua->db);
309    Mmsg(query, "UPDATE Media SET PoolId=%s WHERE MediaId=%s",
310       edit_int64(mr->PoolId, ed1),
311       edit_int64(mr->MediaId, ed2));
312    if (!db_sql_query(ua->db, query, NULL, NULL)) {
313       bsendmsg(ua, "%s", db_strerror(ua->db));
314    } else {
315       bsendmsg(ua, _("New Pool is: %s\n"), pr.Name);
316       opr->NumVols--;
317       if (!db_update_pool_record(ua->jcr, ua->db, opr)) {
318          bsendmsg(ua, "%s", db_strerror(ua->db));
319       }
320       pr.NumVols++;
321       if (!db_update_pool_record(ua->jcr, ua->db, &pr)) {
322          bsendmsg(ua, "%s", db_strerror(ua->db));
323       }
324    }
325    db_unlock(ua->db);
326    free_pool_memory(query);
327 }
328
329 /* Modify the RecyclePool of a Volume */
330 void update_vol_recyclepool(UAContext *ua, char *val, MEDIA_DBR *mr)
331 {
332    POOL_DBR pr;
333    POOLMEM *query;
334    char ed1[50], ed2[50];
335
336    memset(&pr, 0, sizeof(pr));
337    bstrncpy(pr.Name, val, sizeof(pr.Name));
338    if (!get_pool_dbr(ua, &pr, NT_("recyclepool"))) {
339       return;
340    }
341    /* pool = select_pool_resource(ua);  */
342    mr->RecyclePoolId = pr.PoolId;            /* get the PoolId */
343
344    query = get_pool_memory(PM_MESSAGE);
345    db_lock(ua->db);
346    Mmsg(query, "UPDATE Media SET RecyclePoolId=%s WHERE MediaId=%s",
347       edit_int64(mr->RecyclePoolId, ed1),
348       edit_int64(mr->MediaId, ed2));
349    if (!db_sql_query(ua->db, query, NULL, NULL)) {
350       bsendmsg(ua, "%s", db_strerror(ua->db));
351    } else {
352       bsendmsg(ua, _("New RecyclePool is: %s\n"), pr.Name);
353    }
354    db_unlock(ua->db);
355    free_pool_memory(query);
356 }
357
358 /*
359  * Refresh the Volume information from the Pool record
360  */
361 static void update_vol_from_pool(UAContext *ua, MEDIA_DBR *mr)
362 {
363    POOL_DBR pr;
364
365    memset(&pr, 0, sizeof(pr));
366    pr.PoolId = mr->PoolId;
367    if (!db_get_pool_record(ua->jcr, ua->db, &pr) ||
368        !acl_access_ok(ua, Pool_ACL, pr.Name)) {
369       return;
370    }
371    set_pool_dbr_defaults_in_media_dbr(mr, &pr);
372    if (!db_update_media_defaults(ua->jcr, ua->db, mr)) {
373       bsendmsg(ua, _("Error updating Volume record: ERR=%s"), db_strerror(ua->db));
374    } else {
375       bsendmsg(ua, _("Volume defaults updated from \"%s\" Pool record.\n"),
376          pr.Name);
377    }
378 }
379
380 /*
381  * Refresh the Volume information from the Pool record
382  *   for all Volumes
383  */
384 static void update_all_vols_from_pool(UAContext *ua)
385 {
386    POOL_DBR pr;
387    MEDIA_DBR mr;
388
389    memset(&pr, 0, sizeof(pr));
390    memset(&mr, 0, sizeof(mr));
391    if (!get_pool_dbr(ua, &pr)) {
392       return;
393    }
394    set_pool_dbr_defaults_in_media_dbr(&mr, &pr);
395    mr.PoolId = pr.PoolId;
396    if (!db_update_media_defaults(ua->jcr, ua->db, &mr)) {
397       bsendmsg(ua, _("Error updating Volume records: ERR=%s"), db_strerror(ua->db));
398    } else {
399       bsendmsg(ua, _("All Volume defaults updated from Pool record.\n"));
400    }
401 }
402
403 static void update_volenabled(UAContext *ua, char *val, MEDIA_DBR *mr)
404 {
405    mr->Enabled = get_enabled(ua, val);
406    if (mr->Enabled < 0) {
407       return;
408    }
409    if (!db_update_media_record(ua->jcr, ua->db, mr)) {
410       bsendmsg(ua, _("Error updating media record Enabled: ERR=%s"), db_strerror(ua->db));
411    } else {
412       bsendmsg(ua, _("New Enabled is: %d\n"), mr->Enabled);
413    }
414 }
415
416
417
418 /*
419  * Update a media record -- allows you to change the
420  *  Volume status. E.g. if you want Bacula to stop
421  *  writing on the volume, set it to anything other
422  *  than Append.
423  */
424 static int update_volume(UAContext *ua)
425 {
426    MEDIA_DBR mr;
427    POOL_DBR pr;
428    POOLMEM *query;
429    char ed1[130];
430    bool done = false;
431    int i;
432    const char *kw[] = {
433       _("VolStatus"),                /* 0 */
434       _("VolRetention"),             /* 1 */
435       _("VolUse"),                   /* 2 */
436       _("MaxVolJobs"),               /* 3 */
437       _("MaxVolFiles"),              /* 4 */
438       _("MaxVolBytes"),              /* 5 */
439       _("Recycle"),                  /* 6 */
440       _("InChanger"),                /* 7 */
441       _("Slot"),                     /* 8 */
442       _("Pool"),                     /* 9 */
443       _("FromPool"),                 /* 10 */
444       _("AllFromPool"),              /* 11 !!! see below !!! */
445       _("Enabled"),                  /* 12 */
446       _("RecyclePool"),              /* 13 */
447       NULL };
448
449 #define AllFromPool 11               /* keep this updated with above */
450
451    for (i=0; kw[i]; i++) {
452       int j;
453       POOL_DBR pr;
454       if ((j=find_arg_with_value(ua, kw[i])) > 0) {
455          /* If all from pool don't select a media record */
456          if (i != AllFromPool && !select_media_dbr(ua, &mr)) {
457             return 0;
458          }
459          switch (i) {
460          case 0:
461             update_volstatus(ua, ua->argv[j], &mr);
462             break;
463          case 1:
464             update_volretention(ua, ua->argv[j], &mr);
465             break;
466          case 2:
467             update_voluseduration(ua, ua->argv[j], &mr);
468             break;
469          case 3:
470             update_volmaxjobs(ua, ua->argv[j], &mr);
471             break;
472          case 4:
473             update_volmaxfiles(ua, ua->argv[j], &mr);
474             break;
475          case 5:
476             update_volmaxbytes(ua, ua->argv[j], &mr);
477             break;
478          case 6:
479             update_volrecycle(ua, ua->argv[j], &mr);
480             break;
481          case 7:
482             update_volinchanger(ua, ua->argv[j], &mr);
483             break;
484          case 8:
485             update_volslot(ua, ua->argv[j], &mr);
486             break;
487          case 9:
488             memset(&pr, 0, sizeof(POOL_DBR));
489             pr.PoolId = mr.PoolId;
490             if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
491                bsendmsg(ua, "%s", db_strerror(ua->db));
492                break;
493             }
494             update_vol_pool(ua, ua->argv[j], &mr, &pr);
495             break;
496          case 10:
497             update_vol_from_pool(ua, &mr);
498             return 1;
499          case 11:
500             update_all_vols_from_pool(ua);
501             return 1;
502          case 12:
503             update_volenabled(ua, ua->argv[j], &mr);
504             break;
505          case 13:
506             update_vol_recyclepool(ua, ua->argv[j], &mr);
507             break;
508          }
509          done = true;
510       }
511    }
512
513    for ( ; !done; ) {
514       start_prompt(ua, _("Parameters to modify:\n"));
515       add_prompt(ua, _("Volume Status"));              /* 0 */
516       add_prompt(ua, _("Volume Retention Period"));    /* 1 */
517       add_prompt(ua, _("Volume Use Duration"));        /* 2 */
518       add_prompt(ua, _("Maximum Volume Jobs"));        /* 3 */
519       add_prompt(ua, _("Maximum Volume Files"));       /* 4 */
520       add_prompt(ua, _("Maximum Volume Bytes"));       /* 5 */
521       add_prompt(ua, _("Recycle Flag"));               /* 6 */
522       add_prompt(ua, _("Slot"));                       /* 7 */
523       add_prompt(ua, _("InChanger Flag"));             /* 8 */
524       add_prompt(ua, _("Volume Files"));               /* 9 */
525       add_prompt(ua, _("Pool"));                       /* 10 */
526       add_prompt(ua, _("Volume from Pool"));           /* 11 */
527       add_prompt(ua, _("All Volumes from Pool"));      /* 12 */
528       add_prompt(ua, _("Enabled")),                    /* 13 */
529       add_prompt(ua, _("RecyclePool")),                /* 14 */
530       add_prompt(ua, _("Done"));                       /* 15 */
531       i = do_prompt(ua, "", _("Select parameter to modify"), NULL, 0);  
532
533       /* For All Volumes from Pool and Done, we don't need a Volume record */
534       if (i != 12 && i != 15) {
535          if (!select_media_dbr(ua, &mr)) {  /* Get Volume record */
536             return 0;
537          }
538          bsendmsg(ua, _("Updating Volume \"%s\"\n"), mr.VolumeName);
539       }
540       switch (i) {
541       case 0:                         /* Volume Status */
542          /* Modify Volume Status */
543          bsendmsg(ua, _("Current Volume status is: %s\n"), mr.VolStatus);
544          start_prompt(ua, _("Possible Values are:\n"));
545          add_prompt(ua, NT_("Append")); 
546          add_prompt(ua, NT_("Archive"));
547          add_prompt(ua, NT_("Disabled"));
548          add_prompt(ua, NT_("Full"));
549          add_prompt(ua, NT_("Used"));
550          add_prompt(ua, NT_("Cleaning"));
551          if (strcmp(mr.VolStatus, NT_("Purged")) == 0) {
552             add_prompt(ua, NT_("Recycle"));
553          }
554          add_prompt(ua, NT_("Read-Only"));
555          if (do_prompt(ua, "", _("Choose new Volume Status"), ua->cmd, sizeof(mr.VolStatus)) < 0) {
556             return 1;
557          }
558          update_volstatus(ua, ua->cmd, &mr);
559          break;
560       case 1:                         /* Retention */
561          bsendmsg(ua, _("Current retention period is: %s\n"),
562             edit_utime(mr.VolRetention, ed1, sizeof(ed1)));
563          if (!get_cmd(ua, _("Enter Volume Retention period: "))) {
564             return 0;
565          }
566          update_volretention(ua, ua->cmd, &mr);
567          break;
568
569       case 2:                         /* Use Duration */
570          bsendmsg(ua, _("Current use duration is: %s\n"),
571             edit_utime(mr.VolUseDuration, ed1, sizeof(ed1)));
572          if (!get_cmd(ua, _("Enter Volume Use Duration: "))) {
573             return 0;
574          }
575          update_voluseduration(ua, ua->cmd, &mr);
576          break;
577
578       case 3:                         /* Max Jobs */
579          bsendmsg(ua, _("Current max jobs is: %u\n"), mr.MaxVolJobs);
580          if (!get_pint(ua, _("Enter new Maximum Jobs: "))) {
581             return 0;
582          }
583          update_volmaxjobs(ua, ua->cmd, &mr);
584          break;
585
586       case 4:                         /* Max Files */
587          bsendmsg(ua, _("Current max files is: %u\n"), mr.MaxVolFiles);
588          if (!get_pint(ua, _("Enter new Maximum Files: "))) {
589             return 0;
590          }
591          update_volmaxfiles(ua, ua->cmd, &mr);
592          break;
593
594       case 5:                         /* Max Bytes */
595          bsendmsg(ua, _("Current value is: %s\n"), edit_uint64(mr.MaxVolBytes, ed1));
596          if (!get_cmd(ua, _("Enter new Maximum Bytes: "))) {
597             return 0;
598          }
599          update_volmaxbytes(ua, ua->cmd, &mr);
600          break;
601
602
603       case 6:                         /* Recycle */
604          bsendmsg(ua, _("Current recycle flag is: %s\n"),
605             mr.Recycle==1?_("yes"):_("no"));
606          if (!get_yesno(ua, _("Enter new Recycle status: "))) {
607             return 0;
608          }
609          update_volrecycle(ua, ua->cmd, &mr);
610          break;
611
612       case 7:                         /* Slot */
613          bsendmsg(ua, _("Current Slot is: %d\n"), mr.Slot);
614          if (!get_pint(ua, _("Enter new Slot: "))) {
615             return 0;
616          }
617          update_volslot(ua, ua->cmd, &mr);
618          break;
619          
620       case 8:                         /* InChanger */
621          bsendmsg(ua, _("Current InChanger flag is: %d\n"), mr.InChanger);
622          if (!get_yesno(ua, _("Set InChanger flag? yes/no: "))) {
623             return 0;
624          }
625          mr.InChanger = ua->pint32_val;
626          /*
627           * Make sure to use db_update... rather than doing this directly,
628           *   so that any Slot is handled correctly.
629           */
630          if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
631             bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
632          } else {
633             bsendmsg(ua, _("New InChanger flag is: %d\n"), mr.InChanger);
634          }
635          break;
636
637
638       case 9:                         /* Volume Files */
639          int32_t VolFiles;
640          bsendmsg(ua, _("Warning changing Volume Files can result\n"
641                         "in loss of data on your Volume\n\n"));
642          bsendmsg(ua, _("Current Volume Files is: %u\n"), mr.VolFiles);
643          if (!get_pint(ua, _("Enter new number of Files for Volume: "))) {
644             return 0;
645          }
646          VolFiles = ua->pint32_val;
647          if (VolFiles != (int)(mr.VolFiles + 1)) {
648             bsendmsg(ua, _("Normally, you should only increase Volume Files by one!\n"));
649             if (!get_yesno(ua, _("Continue? (yes/no): ")) || ua->pint32_val == 0) {
650                break;
651             }
652          }
653          query = get_pool_memory(PM_MESSAGE);
654          Mmsg(query, "UPDATE Media SET VolFiles=%u WHERE MediaId=%s",
655             VolFiles, edit_int64(mr.MediaId, ed1));
656          if (!db_sql_query(ua->db, query, NULL, NULL)) {
657             bsendmsg(ua, "%s", db_strerror(ua->db));
658          } else {
659             bsendmsg(ua, _("New Volume Files is: %u\n"), VolFiles);
660          }
661          free_pool_memory(query);
662          break;
663
664       case 10:                        /* Volume's Pool */
665          memset(&pr, 0, sizeof(POOL_DBR));
666          pr.PoolId = mr.PoolId;
667          if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
668             bsendmsg(ua, "%s", db_strerror(ua->db));
669             return 0;
670          }
671          bsendmsg(ua, _("Current Pool is: %s\n"), pr.Name);
672          if (!get_cmd(ua, _("Enter new Pool name: "))) {
673             return 0;
674          }
675          update_vol_pool(ua, ua->cmd, &mr, &pr);
676          return 1;
677
678       case 11:
679          update_vol_from_pool(ua, &mr);
680          return 1;
681       case 12:
682          update_all_vols_from_pool(ua);
683          return 1;
684
685       case 13:
686          bsendmsg(ua, _("Current Enabled is: %d\n"), mr.Enabled);
687          if (!get_cmd(ua, _("Enter new Enabled: "))) {
688             return 0;
689          }
690          if (strcasecmp(ua->cmd, "yes") == 0 || strcasecmp(ua->cmd, "true") == 0) {
691             mr.Enabled = 1;
692          } else if (strcasecmp(ua->cmd, "no") == 0 || strcasecmp(ua->cmd, "false") == 0) {
693             mr.Enabled = 0;
694          } else if (strcasecmp(ua->cmd, "archived") == 0) { 
695             mr.Enabled = 2;
696          } else {
697             mr.Enabled = atoi(ua->cmd);
698          }
699          update_volenabled(ua, ua->cmd, &mr);
700          break;
701
702       case 14:
703          memset(&pr, 0, sizeof(POOL_DBR));
704          pr.PoolId = mr.RecyclePoolId;
705          if (db_get_pool_record(ua->jcr, ua->db, &pr)) {
706             bsendmsg(ua, _("Current RecyclePool is: %s\n"), pr.Name);
707          } else {
708             bsendmsg(ua, _("No current RecyclePool\n"));
709          }
710          if (!get_cmd(ua, _("Enter new RecyclePool name: "))) {
711             return 0;
712          }
713          update_vol_recyclepool(ua, ua->cmd, &mr);
714          return 1;
715
716       default:                        /* Done or error */
717          bsendmsg(ua, _("Selection terminated.\n"));
718          return 1;
719       }
720    }
721    return 1;
722 }
723
724 /*
725  * Update pool record -- pull info from current POOL resource
726  */
727 static bool update_pool(UAContext *ua)
728 {
729    POOL_DBR  pr;
730    int id;
731    POOL *pool;
732    POOLMEM *query;
733    char ed1[50];
734
735    pool = get_pool_resource(ua);
736    if (!pool) {
737       return false;
738    }
739
740    memset(&pr, 0, sizeof(pr));
741    bstrncpy(pr.Name, pool->hdr.name, sizeof(pr.Name));
742    if (!get_pool_dbr(ua, &pr)) {
743       return false;
744    }
745
746    set_pooldbr_from_poolres(&pr, pool, POOL_OP_UPDATE); /* update */
747
748    id = db_update_pool_record(ua->jcr, ua->db, &pr);
749    if (id <= 0) {
750       bsendmsg(ua, _("db_update_pool_record returned %d. ERR=%s\n"),
751          id, db_strerror(ua->db));
752    }
753    query = get_pool_memory(PM_MESSAGE);
754    Mmsg(query, list_pool, edit_int64(pr.PoolId, ed1));
755    db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST);
756    free_pool_memory(query);
757    bsendmsg(ua, _("Pool DB record updated from resource.\n"));
758    return true;
759 }