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