1 /*
2    BAREOS® - Backup Archiving REcovery Open Sourced
3 
4    Copyright (C) 2000-2012 Free Software Foundation Europe e.V.
5    Copyright (C) 2011-2016 Planets Communications B.V.
6    Copyright (C) 2013-2019 Bareos GmbH & Co. KG
7 
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version three of the GNU Affero General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12 
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    Affero General Public License for more details.
17 
18    You should have received a copy of the GNU Affero 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
21    02110-1301, USA.
22 */
23 /*
24  * Kern Sibbald, March 2000
25  */
26 /**
27  * @file
28  * BAREOS Catalog Database Update record interface routines
29  */
30 
31 #include "include/bareos.h"
32 
33 #if HAVE_SQLITE3 || HAVE_MYSQL || HAVE_POSTGRESQL || HAVE_INGRES || HAVE_DBI
34 
35 #  include "cats.h"
36 #  include "lib/edit.h"
37 
38 /* -----------------------------------------------------------------------
39  *
40  *   Generic Routines (or almost generic)
41  *
42  * -----------------------------------------------------------------------
43  */
44 
45 /* -----------------------------------------------------------------------
46  *
47  *   Generic Routines (or almost generic)
48  *
49  * -----------------------------------------------------------------------
50  */
51 /* Update the attributes record by adding the file digest */
AddDigestToFileRecord(JobControlRecord * jcr,FileId_t FileId,char * digest,int type)52 bool BareosDb::AddDigestToFileRecord(JobControlRecord* jcr,
53                                      FileId_t FileId,
54                                      char* digest,
55                                      int type)
56 {
57   bool retval;
58   char ed1[50];
59   int len = strlen(digest);
60 
61   DbLock(this);
62   esc_name = CheckPoolMemorySize(esc_name, len * 2 + 1);
63   EscapeString(jcr, esc_name, digest, len);
64   Mmsg(cmd, "UPDATE File SET MD5='%s' WHERE FileId=%s", esc_name,
65        edit_int64(FileId, ed1));
66   retval = UPDATE_DB(jcr, cmd);
67   DbUnlock(this);
68 
69   return retval;
70 }
71 
72 /* Mark the file record as being visited during database
73  * verify compare. Stuff JobId into the MarkId field
74  */
MarkFileRecord(JobControlRecord * jcr,FileId_t FileId,JobId_t JobId)75 bool BareosDb::MarkFileRecord(JobControlRecord* jcr,
76                               FileId_t FileId,
77                               JobId_t JobId)
78 {
79   bool retval;
80   char ed1[50], ed2[50];
81 
82   DbLock(this);
83   Mmsg(cmd, "UPDATE File SET MarkId=%s WHERE FileId=%s", edit_int64(JobId, ed1),
84        edit_int64(FileId, ed2));
85   retval = UPDATE_DB(jcr, cmd);
86   DbUnlock(this);
87 
88   return retval;
89 }
90 
91 /**
92  * Update the Job record at start of Job
93  *
94  * Returns: false on failure
95  *          true  on success
96  */
UpdateJobStartRecord(JobControlRecord * jcr,JobDbRecord * jr)97 bool BareosDb::UpdateJobStartRecord(JobControlRecord* jcr, JobDbRecord* jr)
98 {
99   char dt[MAX_TIME_LENGTH];
100   time_t stime;
101   btime_t JobTDate;
102   bool retval;
103   char ed1[50], ed2[50], ed3[50], ed4[50], ed5[50];
104 
105   stime = jr->StartTime;
106   bstrutime(dt, sizeof(dt), stime);
107   JobTDate = (btime_t)stime;
108 
109   DbLock(this);
110   Mmsg(cmd,
111        "UPDATE Job SET JobStatus='%c',Level='%c',StartTime='%s',"
112        "ClientId=%s,JobTDate=%s,PoolId=%s,FileSetId=%s WHERE JobId=%s",
113        (char)(jcr->JobStatus), (char)(jr->JobLevel), dt,
114        edit_int64(jr->ClientId, ed1), edit_uint64(JobTDate, ed2),
115        edit_int64(jr->PoolId, ed3), edit_int64(jr->FileSetId, ed4),
116        edit_int64(jr->JobId, ed5));
117 
118   retval = UPDATE_DB(jcr, cmd);
119   changes = 0;
120   DbUnlock(this);
121   return retval;
122 }
123 
124 /**
125  * Update Long term statistics with all jobs that were run before age seconds
126  */
UpdateStats(JobControlRecord * jcr,utime_t age)127 int BareosDb::UpdateStats(JobControlRecord* jcr, utime_t age)
128 {
129   char ed1[30];
130   int rows;
131   utime_t now = (utime_t)time(NULL);
132 
133   DbLock(this);
134 
135   edit_uint64(now - age, ed1);
136   FillQuery(SQL_QUERY::fill_jobhisto, ed1);
137   if (QUERY_DB(jcr, cmd)) {
138     rows = SqlAffectedRows();
139   } else {
140     rows = -1;
141   }
142 
143   DbUnlock(this);
144   return rows;
145 }
146 
147 /**
148  * Update the Job record at end of Job
149  *
150  * Returns: false on failure
151  *          true on success
152  */
UpdateJobEndRecord(JobControlRecord * jcr,JobDbRecord * jr)153 bool BareosDb::UpdateJobEndRecord(JobControlRecord* jcr, JobDbRecord* jr)
154 {
155   bool retval;
156   char dt[MAX_TIME_LENGTH];
157   char rdt[MAX_TIME_LENGTH];
158   time_t ttime;
159   char ed1[30], ed2[30], ed3[50], ed4[50];
160   btime_t JobTDate;
161   char PriorJobId[50];
162 
163   if (jr->PriorJobId) {
164     bstrncpy(PriorJobId, edit_int64(jr->PriorJobId, ed1), sizeof(PriorJobId));
165   } else {
166     bstrncpy(PriorJobId, "0", sizeof(PriorJobId));
167   }
168 
169   ttime = jr->EndTime;
170   bstrutime(dt, sizeof(dt), ttime);
171 
172   if (jr->RealEndTime < jr->EndTime) { jr->RealEndTime = jr->EndTime; }
173   ttime = jr->RealEndTime;
174   bstrutime(rdt, sizeof(rdt), ttime);
175 
176   JobTDate = ttime;
177 
178   DbLock(this);
179   Mmsg(
180       cmd,
181       "UPDATE Job SET JobStatus='%c',Level='%c',EndTime='%s',"
182       "ClientId=%u,JobBytes=%s,ReadBytes=%s,JobFiles=%u,JobErrors=%u,"
183       "VolSessionId=%u,"
184       "VolSessionTime=%u,PoolId=%u,FileSetId=%u,JobTDate=%s,"
185       "RealEndTime='%s',PriorJobId=%s,HasBase=%u,PurgedFiles=%u WHERE JobId=%s",
186       (char)(jr->JobStatus), (char)(jr->JobLevel), dt, jr->ClientId,
187       edit_uint64(jr->JobBytes, ed1), edit_uint64(jr->ReadBytes, ed4),
188       jr->JobFiles, jr->JobErrors, jr->VolSessionId, jr->VolSessionTime,
189       jr->PoolId, jr->FileSetId, edit_uint64(JobTDate, ed2), rdt, PriorJobId,
190       jr->HasBase, jr->PurgedFiles, edit_int64(jr->JobId, ed3));
191 
192   retval = UPDATE_DB(jcr, cmd);
193 
194   DbUnlock(this);
195   return retval;
196 }
197 
198 /**
199  * Update Client record
200  * Returns: false on failure
201  *          true on success
202  */
UpdateClientRecord(JobControlRecord * jcr,ClientDbRecord * cr)203 bool BareosDb::UpdateClientRecord(JobControlRecord* jcr, ClientDbRecord* cr)
204 {
205   bool retval = false;
206   char ed1[50], ed2[50];
207   char esc_clientname[MAX_ESCAPE_NAME_LENGTH];
208   char esc_uname[MAX_ESCAPE_NAME_LENGTH];
209   ClientDbRecord tcr;
210 
211   DbLock(this);
212   tcr = *cr;
213   if (!CreateClientRecord(jcr, &tcr)) { goto bail_out; }
214 
215   EscapeString(jcr, esc_clientname, cr->Name, strlen(cr->Name));
216   EscapeString(jcr, esc_uname, cr->Uname, strlen(cr->Uname));
217   Mmsg(cmd,
218        "UPDATE Client SET AutoPrune=%d,FileRetention=%s,JobRetention=%s,"
219        "Uname='%s' WHERE Name='%s'",
220        cr->AutoPrune, edit_uint64(cr->FileRetention, ed1),
221        edit_uint64(cr->JobRetention, ed2), esc_uname, esc_clientname);
222 
223   retval = UPDATE_DB(jcr, cmd);
224 
225 bail_out:
226   DbUnlock(this);
227   return retval;
228 }
229 
230 /**
231  * Update Counters record
232  * Returns: false on failure
233  *          true on success
234  */
UpdateCounterRecord(JobControlRecord * jcr,CounterDbRecord * cr)235 bool BareosDb::UpdateCounterRecord(JobControlRecord* jcr, CounterDbRecord* cr)
236 {
237   bool retval;
238   char esc[MAX_ESCAPE_NAME_LENGTH];
239 
240   DbLock(this);
241 
242   EscapeString(jcr, esc, cr->Counter, strlen(cr->Counter));
243   FillQuery(SQL_QUERY::update_counter_values, cr->MinValue, cr->MaxValue,
244             cr->CurrentValue, cr->WrapCounter, esc);
245   retval = UPDATE_DB(jcr, cmd);
246 
247   DbUnlock(this);
248   return retval;
249 }
250 
UpdatePoolRecord(JobControlRecord * jcr,PoolDbRecord * pr)251 bool BareosDb::UpdatePoolRecord(JobControlRecord* jcr, PoolDbRecord* pr)
252 {
253   bool retval;
254   char ed1[50], ed2[50], ed3[50], ed4[50], ed5[50], ed6[50];
255   char esc[MAX_ESCAPE_NAME_LENGTH];
256 
257   DbLock(this);
258   EscapeString(jcr, esc, pr->LabelFormat, strlen(pr->LabelFormat));
259 
260   Mmsg(cmd, "SELECT count(*) from Media WHERE PoolId=%s",
261        edit_int64(pr->PoolId, ed4));
262   pr->NumVols = GetSqlRecordMax(jcr);
263   Dmsg1(400, "NumVols=%d\n", pr->NumVols);
264 
265   Mmsg(cmd,
266        "UPDATE Pool SET NumVols=%u,MaxVols=%u,UseOnce=%d,UseCatalog=%d,"
267        "AcceptAnyVolume=%d,VolRetention='%s',VolUseDuration='%s',"
268        "MaxVolJobs=%u,MaxVolFiles=%u,MaxVolBytes=%s,Recycle=%d,"
269        "AutoPrune=%d,LabelType=%d,LabelFormat='%s',RecyclePoolId=%s,"
270        "ScratchPoolId=%s,ActionOnPurge=%d,MinBlockSize=%d,MaxBlockSize=%d "
271        "WHERE PoolId=%s",
272        pr->NumVols, pr->MaxVols, pr->UseOnce, pr->UseCatalog,
273        pr->AcceptAnyVolume, edit_uint64(pr->VolRetention, ed1),
274        edit_uint64(pr->VolUseDuration, ed2), pr->MaxVolJobs, pr->MaxVolFiles,
275        edit_uint64(pr->MaxVolBytes, ed3), pr->Recycle, pr->AutoPrune,
276        pr->LabelType, esc, edit_int64(pr->RecyclePoolId, ed5),
277        edit_int64(pr->ScratchPoolId, ed6), pr->ActionOnPurge, pr->MinBlocksize,
278        pr->MaxBlocksize, ed4);
279   retval = UPDATE_DB(jcr, cmd);
280   DbUnlock(this);
281   return retval;
282 }
283 
UpdateStorageRecord(JobControlRecord * jcr,StorageDbRecord * sr)284 bool BareosDb::UpdateStorageRecord(JobControlRecord* jcr, StorageDbRecord* sr)
285 {
286   bool retval;
287   char ed1[50];
288 
289   DbLock(this);
290   Mmsg(cmd, "UPDATE Storage SET AutoChanger=%d WHERE StorageId=%s",
291        sr->AutoChanger, edit_int64(sr->StorageId, ed1));
292 
293   retval = UPDATE_DB(jcr, cmd);
294   DbUnlock(this);
295   return retval;
296 }
297 
298 
299 /**
300  * Update the Media Record at end of Session
301  *
302  * Returns: false on failure
303  *          true on success
304  */
UpdateMediaRecord(JobControlRecord * jcr,MediaDbRecord * mr)305 bool BareosDb::UpdateMediaRecord(JobControlRecord* jcr, MediaDbRecord* mr)
306 {
307   bool retval;
308   char dt[MAX_TIME_LENGTH];
309   time_t ttime;
310   char ed1[50], ed2[50], ed3[50], ed4[50];
311   char ed5[50], ed6[50], ed7[50], ed8[50];
312   char ed9[50], ed10[50], ed11[50];
313   char esc_medianame[MAX_ESCAPE_NAME_LENGTH];
314   char esc_status[MAX_ESCAPE_NAME_LENGTH];
315 
316   Dmsg1(100, "update_media: FirstWritten=%d\n", mr->FirstWritten);
317   DbLock(this);
318   EscapeString(jcr, esc_medianame, mr->VolumeName, strlen(mr->VolumeName));
319   EscapeString(jcr, esc_status, mr->VolStatus, strlen(mr->VolStatus));
320 
321   if (mr->set_first_written) {
322     Dmsg1(400, "Set FirstWritten Vol=%s\n", mr->VolumeName);
323     ttime = mr->FirstWritten;
324     bstrutime(dt, sizeof(dt), ttime);
325     Mmsg(cmd,
326          "UPDATE Media SET FirstWritten='%s'"
327          " WHERE VolumeName='%s'",
328          dt, esc_medianame);
329     retval = UPDATE_DB(jcr, cmd);
330     Dmsg1(400, "Firstwritten=%d\n", mr->FirstWritten);
331   }
332 
333   /* Label just done? */
334   if (mr->set_label_date) {
335     ttime = mr->LabelDate;
336     if (ttime == 0) { ttime = time(NULL); }
337     bstrutime(dt, sizeof(dt), ttime);
338     Mmsg(cmd,
339          "UPDATE Media SET LabelDate='%s' "
340          "WHERE VolumeName='%s'",
341          dt, esc_medianame);
342     UPDATE_DB(jcr, cmd);
343   }
344 
345   if (mr->LastWritten != 0) {
346     ttime = mr->LastWritten;
347     bstrutime(dt, sizeof(dt), ttime);
348     Mmsg(cmd,
349          "UPDATE Media Set LastWritten='%s' "
350          "WHERE VolumeName='%s'",
351          dt, esc_medianame);
352     UPDATE_DB(jcr, cmd);
353   }
354 
355   Mmsg(cmd,
356        "UPDATE Media SET VolJobs=%u,"
357        "VolFiles=%u,VolBlocks=%u,VolBytes=%s,VolMounts=%u,VolErrors=%u,"
358        "VolWrites=%u,MaxVolBytes=%s,VolStatus='%s',"
359        "Slot=%d,InChanger=%d,VolReadTime=%s,VolWriteTime=%s,"
360        "LabelType=%d,StorageId=%s,PoolId=%s,VolRetention=%s,VolUseDuration=%s,"
361        "MaxVolJobs=%d,MaxVolFiles=%d,Enabled=%d,LocationId=%s,"
362        "ScratchPoolId=%s,RecyclePoolId=%s,RecycleCount=%d,Recycle=%d,"
363        "ActionOnPurge=%d,"
364        "MinBlocksize=%u,MaxBlocksize=%u"
365        " WHERE VolumeName='%s'",
366        mr->VolJobs, mr->VolFiles, mr->VolBlocks, edit_uint64(mr->VolBytes, ed1),
367        mr->VolMounts, mr->VolErrors, mr->VolWrites,
368        edit_uint64(mr->MaxVolBytes, ed2), esc_status, mr->Slot, mr->InChanger,
369        edit_int64(mr->VolReadTime, ed3), edit_int64(mr->VolWriteTime, ed4),
370        mr->LabelType, edit_int64(mr->StorageId, ed5),
371        edit_int64(mr->PoolId, ed6), edit_uint64(mr->VolRetention, ed7),
372        edit_uint64(mr->VolUseDuration, ed8), mr->MaxVolJobs, mr->MaxVolFiles,
373        mr->Enabled, edit_uint64(mr->LocationId, ed9),
374        edit_uint64(mr->ScratchPoolId, ed10),
375        edit_uint64(mr->RecyclePoolId, ed11), mr->RecycleCount, mr->Recycle,
376        mr->ActionOnPurge, mr->MinBlocksize, mr->MaxBlocksize, esc_medianame);
377 
378   Dmsg1(400, "%s\n", cmd);
379 
380   retval = UPDATE_DB(jcr, cmd);
381 
382   /*
383    * Make sure InChanger is 0 for any record having the same Slot
384    */
385   MakeInchangerUnique(jcr, mr);
386 
387   DbUnlock(this);
388 
389   return retval;
390 }
391 
392 /**
393  * Update the Media Record Default values from Pool
394  *
395  * Returns: false on failure
396  *          true on success
397  */
UpdateMediaDefaults(JobControlRecord * jcr,MediaDbRecord * mr)398 bool BareosDb::UpdateMediaDefaults(JobControlRecord* jcr, MediaDbRecord* mr)
399 {
400   bool retval;
401   char ed1[50], ed2[50], ed3[50], ed4[50], ed5[50];
402   char esc[MAX_ESCAPE_NAME_LENGTH];
403 
404   DbLock(this);
405   if (mr->VolumeName[0]) {
406     EscapeString(jcr, esc, mr->VolumeName, strlen(mr->VolumeName));
407     Mmsg(cmd,
408          "UPDATE Media SET "
409          "ActionOnPurge=%d,Recycle=%d,VolRetention=%s,VolUseDuration=%s,"
410          "MaxVolJobs=%u,MaxVolFiles=%u,MaxVolBytes=%s,RecyclePoolId=%s,"
411          "MinBlocksize=%d,MaxBlocksize=%d"
412          " WHERE VolumeName='%s'",
413          mr->ActionOnPurge, mr->Recycle, edit_uint64(mr->VolRetention, ed1),
414          edit_uint64(mr->VolUseDuration, ed2), mr->MaxVolJobs, mr->MaxVolFiles,
415          edit_uint64(mr->MaxVolBytes, ed3), edit_uint64(mr->RecyclePoolId, ed4),
416          mr->MinBlocksize, mr->MaxBlocksize, esc);
417   } else {
418     Mmsg(cmd,
419          "UPDATE Media SET "
420          "ActionOnPurge=%d,Recycle=%d,VolRetention=%s,VolUseDuration=%s,"
421          "MaxVolJobs=%u,MaxVolFiles=%u,MaxVolBytes=%s,RecyclePoolId=%s,"
422          "MinBlocksize=%d,MaxBlocksize=%d"
423          " WHERE PoolId=%s",
424          mr->ActionOnPurge, mr->Recycle, edit_uint64(mr->VolRetention, ed1),
425          edit_uint64(mr->VolUseDuration, ed2), mr->MaxVolJobs, mr->MaxVolFiles,
426          edit_uint64(mr->MaxVolBytes, ed3), edit_int64(mr->RecyclePoolId, ed4),
427          mr->MinBlocksize, mr->MaxBlocksize, edit_int64(mr->PoolId, ed5));
428   }
429 
430   Dmsg1(400, "%s\n", cmd);
431 
432   retval = UPDATE_DB(jcr, cmd);
433 
434   DbUnlock(this);
435   return retval;
436 }
437 
438 
439 /**
440  * If we have a non-zero InChanger, ensure that no other Media
441  *  record has InChanger set on the same Slot.
442  *
443  * This routine assumes the database is already locked.
444  */
MakeInchangerUnique(JobControlRecord * jcr,MediaDbRecord * mr)445 void BareosDb::MakeInchangerUnique(JobControlRecord* jcr, MediaDbRecord* mr)
446 {
447   char ed1[50], ed2[50];
448   char esc[MAX_ESCAPE_NAME_LENGTH];
449   if (mr->InChanger != 0 && mr->Slot != 0 && mr->StorageId != 0) {
450     if (mr->MediaId != 0) {
451       Mmsg(cmd,
452            "UPDATE Media SET InChanger=0, Slot=0 WHERE "
453            "Slot=%d AND StorageId=%s AND MediaId!=%s",
454            mr->Slot, edit_int64(mr->StorageId, ed1),
455            edit_int64(mr->MediaId, ed2));
456 
457     } else if (*mr->VolumeName) {
458       EscapeString(jcr, esc, mr->VolumeName, strlen(mr->VolumeName));
459       Mmsg(cmd,
460            "UPDATE Media SET InChanger=0, Slot=0 WHERE "
461            "Slot=%d AND StorageId=%s AND VolumeName!='%s'",
462            mr->Slot, edit_int64(mr->StorageId, ed1), esc);
463 
464     } else { /* used by ua_label to reset all volume with this slot */
465       Mmsg(cmd,
466            "UPDATE Media SET InChanger=0, Slot=0 WHERE "
467            "Slot=%d AND StorageId=%s",
468            mr->Slot, edit_int64(mr->StorageId, ed1), mr->VolumeName);
469     }
470     Dmsg1(100, "%s\n", cmd);
471     UPDATE_DB_NO_AFR(jcr, cmd);
472   }
473 }
474 
475 /**
476  * Update Quota record
477  *
478  * Returns: false on failure
479  *          true on success
480  */
UpdateQuotaGracetime(JobControlRecord * jcr,JobDbRecord * jr)481 bool BareosDb::UpdateQuotaGracetime(JobControlRecord* jcr, JobDbRecord* jr)
482 {
483   bool retval;
484   char ed1[50], ed2[50];
485   time_t now = time(NULL);
486 
487   DbLock(this);
488 
489   Mmsg(cmd, "UPDATE Quota SET GraceTime=%s WHERE ClientId='%s'",
490        edit_uint64(now, ed1), edit_uint64(jr->ClientId, ed2));
491 
492   retval = UPDATE_DB(jcr, cmd);
493 
494   DbUnlock(this);
495 
496   return retval;
497 }
498 
499 /**
500  * Update Quota Softlimit
501  *
502  * Returns: false on failure
503  *          true on success
504  */
UpdateQuotaSoftlimit(JobControlRecord * jcr,JobDbRecord * jr)505 bool BareosDb::UpdateQuotaSoftlimit(JobControlRecord* jcr, JobDbRecord* jr)
506 {
507   bool retval;
508   char ed1[50], ed2[50];
509 
510   DbLock(this);
511 
512   Mmsg(cmd, "UPDATE Quota SET QuotaLimit=%s WHERE ClientId='%s'",
513        edit_uint64((jr->JobSumTotalBytes + jr->JobBytes), ed1),
514        edit_uint64(jr->ClientId, ed2));
515 
516   retval = UPDATE_DB(jcr, cmd);
517 
518   DbUnlock(this);
519 
520   return retval;
521 }
522 
523 /**
524  * Reset Quota Gracetime
525  *
526  * Returns: false on failure
527  *          true on success
528  */
ResetQuotaRecord(JobControlRecord * jcr,ClientDbRecord * cr)529 bool BareosDb::ResetQuotaRecord(JobControlRecord* jcr, ClientDbRecord* cr)
530 {
531   bool retval;
532   char ed1[50];
533 
534   DbLock(this);
535 
536   Mmsg(cmd,
537        "UPDATE Quota SET GraceTime='0', QuotaLimit='0' WHERE ClientId='%s'",
538        edit_uint64(cr->ClientId, ed1));
539 
540   retval = UPDATE_DB(jcr, cmd);
541 
542   DbUnlock(this);
543 
544   return retval;
545 }
546 
547 /**
548  * Update NDMP level mapping
549  *
550  * Returns: false on failure
551  *          true on success
552  */
UpdateNdmpLevelMapping(JobControlRecord * jcr,JobDbRecord * jr,char * filesystem,int level)553 bool BareosDb::UpdateNdmpLevelMapping(JobControlRecord* jcr,
554                                       JobDbRecord* jr,
555                                       char* filesystem,
556                                       int level)
557 {
558   bool retval;
559   char ed1[50], ed2[50], ed3[50];
560 
561   DbLock(this);
562 
563   esc_name = CheckPoolMemorySize(esc_name, strlen(filesystem) * 2 + 1);
564   EscapeString(jcr, esc_name, filesystem, strlen(filesystem));
565 
566   Mmsg(cmd,
567        "UPDATE NDMPLevelMap SET DumpLevel='%s' WHERE "
568        "ClientId='%s' AND FileSetId='%s' AND FileSystem='%s'",
569        edit_uint64(level, ed1), edit_uint64(jr->ClientId, ed2),
570        edit_uint64(jr->FileSetId, ed3), esc_name);
571 
572   retval = UPDATE_DB(jcr, cmd);
573 
574   DbUnlock(this);
575 
576   return retval;
577 }
578 #endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_POSTGRESQL || HAVE_INGRES || \
579           HAVE_DBI */
580