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-2018 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  * Catalog header file
25  *
26  * by Kern E. Sibbald
27  */
28 /**
29  * @file
30  * Catalog header file
31  * Anyone who accesses the database will need to include
32  * this file.
33  */
34 
35 #ifndef BAREOS_CATS_CATS_H_
36 #define BAREOS_CATS_CATS_H_ 1
37 
38 /* import automatically generated SQL_QUERY_ENUM */
39 #include "bdb_query_enum_class.h"
40 
41 /* ==============================================================
42  *
43  *  What follows are definitions that are used "globally" for all
44  *   the different SQL engines and both inside and external to the
45  *   cats directory.
46  */
47 
48 #define faddr_t long
49 
50 struct VolumeSessionInfo;
51 
52 /**
53  * Generic definitions of list types, list handlers and result handlers.
54  */
55 enum e_list_type
56 {
57   NF_LIST,
58   RAW_LIST,
59   HORZ_LIST,
60   VERT_LIST
61 };
62 
63 /**
64  * Structure used when calling db_get_query_ids()
65  *  allows the subroutine to return a list of ids.
66  */
67 class dbid_list : public SmartAlloc {
68  public:
69   DBId_t* DBId;      /**< array of DBIds */
70   char* PurgedFiles; /**< Array of PurgedFile flags */
71   int num_ids;       /**< num of ids actually stored */
72   int max_ids;       /**< size of id array */
73   int num_seen;      /**< number of ids processed */
74   int tot_ids;       /**< total to process */
75 
76   dbid_list();  /**< in sql.c */
77   ~dbid_list(); /**< in sql.c */
78 
size()79   int size() const { return num_ids; }
80   DBId_t get(int i) const;
81 };
82 
83 /**
84  * Job information passed to create job record and update
85  * job record at end of job. Note, although this record
86  * contains all the fields found in the Job database record,
87  * it also contains fields found in the JobMedia record.
88  */
89 
90 /**
91  * Job record
92  */
93 struct JobDbRecord {
94   JobId_t JobId;
95   char Job[MAX_NAME_LENGTH];  /**< Job unique name */
96   char Name[MAX_NAME_LENGTH]; /**< Job base name */
97   int JobType;                /**< actually char(1) */
98   int JobLevel;               /**< actually char(1) */
99   int JobStatus;              /**< actually char(1) */
100   DBId_t ClientId;            /**< Id of client */
101   DBId_t PoolId;              /**< Id of pool */
102   DBId_t FileSetId;           /**< Id of FileSet */
103   DBId_t PriorJobId;          /**< Id of migrated (prior) job */
104   time_t SchedTime;           /**< Time job scheduled */
105   time_t StartTime;           /**< Job start time */
106   time_t EndTime;             /**< Job termination time of orig job */
107   time_t RealEndTime;         /**< Job termination time of this job */
108   utime_t JobTDate;           /**< Backup time/date in seconds */
109   uint32_t VolSessionId;
110   uint32_t VolSessionTime;
111   uint32_t JobFiles;
112   uint32_t JobErrors;
113   uint32_t JobMissingFiles;
114   uint64_t JobBytes;
115   uint64_t ReadBytes;
116   uint64_t JobSumTotalBytes; /**< Total sum in bytes of all jobs but this one */
117   int PurgedFiles;
118   int HasBase;
119 
120   /* Note, FirstIndex, LastIndex, Start/End File and Block
121    * are only used in the JobMedia record.
122    */
123   uint32_t FirstIndex; /**< First index this Volume */
124   uint32_t LastIndex;  /**< Last index this Volume */
125   uint32_t StartFile;
126   uint32_t EndFile;
127   uint32_t StartBlock;
128   uint32_t EndBlock;
129 
130   char cSchedTime[MAX_TIME_LENGTH];
131   char cStartTime[MAX_TIME_LENGTH];
132   char cEndTime[MAX_TIME_LENGTH];
133   char cRealEndTime[MAX_TIME_LENGTH];
134 
135   /*
136    * Extra stuff not in DB
137    */
138   int limit;  /**< limit records to display */
139   int offset; /**< offset records to display */
140   faddr_t rec_addr;
141   uint32_t FileIndex; /**< added during Verify */
142 };
143 
144 /* Job Media information used to create the media records
145  * for each Volume used for the job.
146  */
147 /**
148  * JobMedia record
149  */
150 struct JobMediaDbRecord {
151   DBId_t JobMediaId;   /**< record id */
152   JobId_t JobId;       /**< JobId */
153   DBId_t MediaId;      /**< MediaId */
154   uint32_t FirstIndex; /**< First index this Volume */
155   uint32_t LastIndex;  /**< Last index this Volume */
156   uint32_t StartFile;  /**< File for start of data */
157   uint32_t EndFile;    /**< End file on Volume */
158   uint32_t StartBlock; /**< start block on tape */
159   uint32_t EndBlock;   /**< last block */
160   uint64_t JobBytes;   /**< job bytes */
161 };
162 
163 
164 /**
165  * Volume Parameter structure
166  */
167 struct VolumeParameters {
168   char VolumeName[MAX_NAME_LENGTH]; /**< Volume name */
169   char MediaType[MAX_NAME_LENGTH];  /**< Media Type */
170   char Storage[MAX_NAME_LENGTH];    /**< Storage name */
171   uint32_t VolIndex;                /**< Volume seqence no. */
172   uint32_t FirstIndex;              /**< First index this Volume */
173   uint32_t LastIndex;               /**< Last index this Volume */
174   int32_t Slot;                     /**< Slot */
175   uint64_t StartAddr;               /**< Start address */
176   uint64_t EndAddr;                 /**< End address */
177   int32_t InChanger;                /**< InChanger flag */
178   uint64_t JobBytes;                /**< job bytes */
179   // uint32_t Copy;                     /**< identical copy */
180   // uint32_t Stripe;                   /**< RAIT strip number */
181 };
182 
183 /**
184  * Attributes record -- NOT same as in database because
185  * in general, this "record" creates multiple database
186  * records (e.g. pathname, filename, fileattributes).
187  */
188 struct AttributesDbRecord {
189   char* fname; /**< full path & filename */
190   char* link;  /**< link if any */
191   char* attr;  /**< attributes statp */
192   uint32_t FileIndex;
193   uint32_t Stream;
194   uint32_t FileType;
195   uint32_t DeltaSeq;
196   JobId_t JobId;
197   DBId_t ClientId;
198   DBId_t PathId;
199   FileId_t FileId;
200   char* Digest;
201   int DigestType;
202   uint64_t Fhinfo; /**< NDMP fh_info for DAR*/
203   uint64_t Fhnode; /**< NDMP fh_node for DAR*/
204 };
205 
206 /**
207  * Restore object database record
208  */
209 struct RestoreObjectDbRecord {
210   char* object_name;
211   char* object;
212   char* plugin_name;
213   uint32_t object_len;
214   uint32_t object_full_len;
215   uint32_t object_index;
216   int32_t object_compression;
217   uint32_t FileIndex;
218   uint32_t Stream;
219   uint32_t FileType;
220   JobId_t JobId;
221   DBId_t RestoreObjectId;
222 };
223 
224 /**
225  * File record -- same format as database
226  */
227 struct FileDbRecord {
228   FileId_t FileId;
229   uint32_t FileIndex;
230   JobId_t JobId;
231   DBId_t PathId;
232   JobId_t MarkId;
233   uint32_t DeltaSeq;
234   char LStat[256];
235   char Digest[BASE64_SIZE(CRYPTO_DIGEST_MAX_SIZE)];
236   int DigestType; /**< NO_SIG/MD5_SIG/SHA1_SIG */
237 };
238 
239 /**
240  * Pool record -- same format as database
241  */
242 struct PoolDbRecord {
243   DBId_t PoolId;
244   char Name[MAX_NAME_LENGTH]; /**< Pool name */
245   uint32_t NumVols;           /**< total number of volumes */
246   uint32_t MaxVols;           /**< max allowed volumes */
247   int32_t LabelType;          /**< BAREOS/ANSI/IBM */
248   int32_t UseOnce;            /**< set to use once only */
249   int32_t UseCatalog;         /**< set to use catalog */
250   int32_t AcceptAnyVolume;    /**< set to accept any volume sequence */
251   int32_t AutoPrune;          /**< set to prune automatically */
252   int32_t Recycle;            /**< default Vol recycle flag */
253   uint32_t ActionOnPurge; /**< action on purge, e.g. truncate the disk volume */
254   utime_t VolRetention;   /**< retention period in seconds */
255   utime_t VolUseDuration; /**< time in secs volume can be used */
256   uint32_t MaxVolJobs;    /**< Max Jobs on Volume */
257   uint32_t MaxVolFiles;   /**< Max files on Volume */
258   uint64_t MaxVolBytes;   /**< Max bytes on Volume */
259   DBId_t RecyclePoolId;   /**< RecyclePool destination when media is purged */
260   DBId_t ScratchPoolId;   /**< ScratchPool source when media is needed */
261   char PoolType[MAX_NAME_LENGTH];
262   char LabelFormat[MAX_NAME_LENGTH];
263   uint32_t MinBlocksize; /**< Minimum Block Size */
264   uint32_t MaxBlocksize; /**< Maximum Block Size */
265 
266   /*
267    * Extra stuff not in DB
268    */
269   faddr_t rec_addr;
270 };
271 
272 /**
273  * Device record
274  */
275 struct DeviceDbRecord {
276   DBId_t DeviceId;
277   char Name[MAX_NAME_LENGTH];        /**< Device name */
278   DBId_t MediaTypeId;                /**< MediaType */
279   DBId_t StorageId;                  /**< Storage id if autochanger */
280   uint32_t DevMounts;                /**< Number of times mounted */
281   uint32_t DevErrors;                /**< Number of read/write errors */
282   uint64_t DevReadBytes;             /**< Number of bytes read */
283   uint64_t DevWriteBytes;            /**< Number of bytes written */
284   uint64_t DevReadTime;              /**< time spent reading volume */
285   uint64_t DevWriteTime;             /**< time spent writing volume */
286   uint64_t DevReadTimeSincCleaning;  /**< read time since cleaning */
287   uint64_t DevWriteTimeSincCleaning; /**< write time since cleaning */
288   time_t CleaningDate;               /**< time last cleaned */
289   utime_t CleaningPeriod;            /**< time between cleanings */
290 };
291 
292 /**
293  * Storage database record
294  */
295 struct StorageDbRecord {
296   DBId_t StorageId;
297   char Name[MAX_NAME_LENGTH]; /**< Device name */
298   int AutoChanger;            /**< Set if autochanger */
299 
300   /*
301    * Extra stuff not in DB
302    */
303   bool created; /**< set if created by db_create ... */
304 };
305 
306 /**
307  * mediatype database record
308  */
309 struct MediaTypeDbRecord {
310   DBId_t MediaTypeId;
311   char MediaType[MAX_NAME_LENGTH]; /**< MediaType string */
312   int ReadOnly;                    /**< Set if read-only */
313 };
314 
315 /**
316  * Media record -- same as the database
317  */
318 struct MediaDbRecord {
319   DBId_t MediaId;                   /**< Unique volume id */
320   char VolumeName[MAX_NAME_LENGTH]; /**< Volume name */
321   char MediaType[MAX_NAME_LENGTH];  /**< Media type */
322   char EncrKey[MAX_NAME_LENGTH];    /**< Encryption Key */
323   DBId_t PoolId;                    /**< Pool id */
324   time_t FirstWritten;              /**< Time Volume first written this usage */
325   time_t LastWritten;               /**< Time Volume last written */
326   time_t LabelDate;                 /**< Date/Time Volume labeled */
327   time_t InitialWrite;              /**< Date/Time Volume first written */
328   int32_t LabelType;                /**< Label (BAREOS/ANSI/IBM) */
329   uint32_t VolJobs;                 /**< number of jobs on this medium */
330   uint32_t VolFiles;                /**< Number of files */
331   uint32_t VolBlocks;               /**< Number of blocks */
332   uint32_t VolMounts;               /**< Number of times mounted */
333   uint32_t VolErrors;               /**< Number of read/write errors */
334   uint32_t VolWrites;               /**< Number of writes */
335   uint32_t VolReads;                /**< Number of reads */
336   uint64_t VolBytes;                /**< Number of bytes written */
337   uint64_t MaxVolBytes;             /**< Max bytes to write to Volume */
338   uint64_t VolCapacityBytes;        /**< capacity estimate */
339   uint64_t VolReadTime;             /**< time spent reading volume */
340   uint64_t VolWriteTime;            /**< time spent writing volume */
341   utime_t VolRetention;             /**< Volume retention in seconds */
342   utime_t VolUseDuration;           /**< time in secs volume can be used */
343   uint32_t ActionOnPurge; /**< action on purge, e.g. truncate the disk volume */
344   uint32_t MaxVolJobs;    /**< Max Jobs on Volume */
345   uint32_t MaxVolFiles;   /**< Max files on Volume */
346   int32_t Recycle;        /**< recycle yes/no */
347   int32_t Slot;           /**< slot in changer */
348   int32_t Enabled;        /**< 0=disabled, 1=enabled, 2=archived */
349   int32_t InChanger;      /**< Volume currently in changer */
350   DBId_t StorageId;       /**< Storage record Id */
351   uint32_t EndFile;       /**< Last file on volume */
352   uint32_t EndBlock;      /**< Last block on volume */
353   uint32_t RecycleCount;  /**< Number of times recycled */
354   uint32_t MinBlocksize;  /**< Minimum Block Size */
355   uint32_t MaxBlocksize;  /**< Maximum Block Size */
356   char VolStatus[20];     /**< Volume status */
357   DBId_t DeviceId;        /**< Device where Vol last written */
358   DBId_t LocationId;      /**< Where Volume is -- user defined */
359   DBId_t ScratchPoolId;   /**< Where to move if scratch */
360   DBId_t RecyclePoolId;   /**< Where to move when recycled */
361 
362   /*
363    * Extra stuff not in DB
364    */
365   faddr_t rec_addr; /**< found record address */
366 
367   /*
368    * Since the database returns times as strings, this is how we pass them back.
369    */
370   char cFirstWritten[MAX_TIME_LENGTH]; /**< FirstWritten returned from DB */
371   char cLastWritten[MAX_TIME_LENGTH];  /**< LastWritten returned from DB */
372   char cLabelDate[MAX_TIME_LENGTH];    /**< LabelData returned from DB */
373   char cInitialWrite[MAX_TIME_LENGTH]; /**< InitialWrite returned from DB */
374   bool set_first_written;
375   bool set_label_date;
376 };
377 
378 /**
379  * Client record -- same as the database
380  */
381 struct ClientDbRecord {
382   DBId_t ClientId; /**< Unique Client id */
383   int AutoPrune;
384   utime_t GraceTime;   /**< Time remaining on gracetime */
385   uint32_t QuotaLimit; /**< The total softquota supplied if over grace */
386   utime_t FileRetention;
387   utime_t JobRetention;
388   char Name[MAX_NAME_LENGTH]; /**< Client name */
389   char Uname[256];            /**< Uname for client */
390 };
391 
392 /**
393  * Counter record -- same as in database
394  */
395 struct CounterDbRecord {
396   char Counter[MAX_NAME_LENGTH];
397   int32_t MinValue;
398   int32_t MaxValue;
399   int32_t CurrentValue;
400   char WrapCounter[MAX_NAME_LENGTH];
401 };
402 
403 /**
404  * FileSet record -- same as the database
405  */
406 struct FileSetDbRecord {
407   DBId_t FileSetId;              /**< Unique FileSet id */
408   char FileSet[MAX_NAME_LENGTH]; /**< FileSet name */
409   char* FileSetText;             /**< FileSet as Text */
410   char MD5[50];                  /**< MD5 signature of include/exclude */
411   time_t CreateTime;             /**< Date created */
412   /*
413    * This is where we return CreateTime
414    */
415   char cCreateTime[MAX_TIME_LENGTH]; /**< CreateTime as returned from DB */
416   /*
417    * Not in DB but returned by db_create_fileset()
418    */
419   bool created; /**< set when record newly created */
420 };
421 
422 /**
423  * Device Statistics record -- same as in database
424  */
425 struct DeviceStatisticsDbRecord {
426   DBId_t DeviceId;       /**< Device record id */
427   time_t SampleTime;     /**< Timestamp statistic was captured */
428   uint64_t ReadTime;     /**< Time spent reading volume */
429   uint64_t WriteTime;    /**< Time spent writing volume */
430   uint64_t ReadBytes;    /**< Number of bytes read */
431   uint64_t WriteBytes;   /**< Number of bytes written */
432   uint64_t SpoolSize;    /**< Number of bytes spooled */
433   uint32_t NumWaiting;   /**< Number of Jobs waiting for device */
434   uint32_t NumWriters;   /**< Number of writers to device */
435   DBId_t MediaId;        /**< MediaId used */
436   uint64_t VolCatBytes;  /**< Volume Bytes */
437   uint64_t VolCatFiles;  /**< Volume Files */
438   uint64_t VolCatBlocks; /**< Volume Blocks */
439 };
440 
441 /**
442  * TapeAlert record -- same as in database
443  */
444 struct TapealertStatsDbRecord {
445   DBId_t DeviceId;     /**< Device record id */
446   time_t SampleTime;   /**< Timestamp statistic was captured */
447   uint64_t AlertFlags; /**< Tape Alerts raised */
448 };
449 
450 /**
451  * Job Statistics record -- same as in database
452  */
453 struct JobStatisticsDbRecord {
454   DBId_t DeviceId;   /**< Device record id */
455   time_t SampleTime; /**< Timestamp statistic was captured */
456   JobId_t JobId;     /**< Job record id */
457   uint32_t JobFiles; /**< Number of Files in Job */
458   uint64_t JobBytes; /**< Number of Bytes in Job */
459 };
460 
461 /**
462  * Call back context for getting a 32/64 bit value from the database
463  */
464 class db_int64_ctx {
465  public:
466   int64_t value; /**< value returned */
467   int count;     /**< number of values seen */
468 
db_int64_ctx()469   db_int64_ctx() : value(0), count(0) {}
~db_int64_ctx()470   ~db_int64_ctx() {}
471 
472  private:
473   db_int64_ctx(const db_int64_ctx&); /**< prohibit pass by value */
474   db_int64_ctx& operator=(
475       const db_int64_ctx&); /**< prohibit class assignment */
476 };
477 
478 /**
479  * Call back context for getting a list of comma separated strings from the
480  * database
481  */
482 class db_list_ctx {
483  public:
484   POOLMEM* list; /* list */
485   int count;     /* number of values seen */
486 
db_list_ctx()487   db_list_ctx()
488   {
489     list = GetPoolMemory(PM_FNAME);
490     reset();
491   }
~db_list_ctx()492   ~db_list_ctx()
493   {
494     FreePoolMemory(list);
495     list = NULL;
496   }
reset()497   void reset()
498   {
499     *list = 0;
500     count = 0;
501   }
add(const db_list_ctx & str)502   void add(const db_list_ctx& str)
503   {
504     if (str.count > 0) {
505       if (*list) { PmStrcat(list, ","); }
506       PmStrcat(list, str.list);
507       count += str.count;
508     }
509   }
add(const char * str)510   void add(const char* str)
511   {
512     if (count > 0) { PmStrcat(list, ","); }
513     PmStrcat(list, str);
514     count++;
515   }
516 
517  private:
518   db_list_ctx(const db_list_ctx&);            /**< prohibit pass by value */
519   db_list_ctx& operator=(const db_list_ctx&); /**< prohibit class assignment */
520 };
521 
522 typedef enum
523 {
524   SQL_INTERFACE_TYPE_MYSQL = 0,
525   SQL_INTERFACE_TYPE_POSTGRESQL = 1,
526   SQL_INTERFACE_TYPE_SQLITE3 = 2,
527   SQL_INTERFACE_TYPE_INGRES = 3,
528   SQL_INTERFACE_TYPE_DBI = 4
529 } SQL_INTERFACETYPE;
530 
531 typedef enum
532 {
533   SQL_TYPE_MYSQL = 0,
534   SQL_TYPE_POSTGRESQL = 1,
535   SQL_TYPE_SQLITE3 = 2,
536   SQL_TYPE_INGRES = 3,
537   SQL_TYPE_UNKNOWN = 99
538 } SQL_DBTYPE;
539 
540 typedef void(DB_LIST_HANDLER)(void*, const char*);
541 typedef int(DB_RESULT_HANDLER)(void*, int, char**);
542 
543 #define DbLock(mdb) mdb->LockDb(__FILE__, __LINE__)
544 #define DbUnlock(mdb) mdb->UnlockDb(__FILE__, __LINE__)
545 
546 class pathid_cache;
547 
548 /*
549  * Initial size of query hash table and hint for number of pages.
550  */
551 #define QUERY_INITIAL_HASH_SIZE 1024
552 #define QUERY_HTABLE_PAGES 128
553 
554 /**
555  * Current database version number for all drivers
556  */
557 #define BDB_VERSION 2171
558 
559 #ifdef _BDB_PRIV_INTERFACE_
560 /*
561  * Generic definition of a sql_row.
562  */
563 typedef char** SQL_ROW;
564 
565 /*
566  * Generic definition of a a sql_field.
567  */
568 typedef struct sql_field {
569   char* name;     /* name of column */
570   int max_length; /* max length */
571   uint32_t type;  /* type */
572   uint32_t flags; /* flags */
573 } SQL_FIELD;
574 #endif
575 
576 class BareosDb
577     : public SmartAlloc
578     , public BareosDbQueryEnum {
579  protected:
580   /*
581    * Members
582    */
583   brwlock_t lock_;                      /**< Transaction lock */
584   dlink link_;                          /**< Queue control */
585   SQL_INTERFACETYPE db_interface_type_; /**< Type of backend used */
586   SQL_DBTYPE db_type_;                  /**< Database type */
587   uint32_t ref_count_;                  /**< Reference count */
588   bool connected_;                      /**< Connection made to db */
589   bool have_batch_insert_;              /**< Have batch insert support ? */
590   bool try_reconnect_;                  /**< Try reconnecting DB connection ? */
591   bool exit_on_fatal_;                  /**< Exit on FATAL DB errors ? */
592   char* db_driver_;                     /**< Database driver */
593   char* db_driverdir_;                  /**< Database driver dir */
594   char* db_name_;                       /**< Database name */
595   char* db_user_;                       /**< Database user */
596   char* db_address_;                    /**< Host name address */
597   char* db_socket_;                     /**< Socket for local access */
598   char* db_password_;                   /**< Database password */
599   char* last_query_text_;      /**< Last query text obtained from query table */
600   int db_port_;                /**< Port for host name address */
601   int cached_path_len;         /**< Length of cached path */
602   int changes;                 /**< Changes during transaction */
603   int fnl;                     /**< File name length */
604   int pnl;                     /**< Path name length */
605   bool disabled_batch_insert_; /**< Explicitly disabled batch insert mode ? */
606   bool is_private_;            /**< Private connection ? */
607   uint32_t cached_path_id;     /**< Cached path id */
608   uint32_t last_hash_key_;     /**< Last hash key lookup on query table */
609   POOLMEM* fname;              /**< Filename only */
610   POOLMEM* path;               /**< Path only */
611   POOLMEM* cached_path;        /**< Cached path name */
612   POOLMEM* esc_name;           /**< Escaped file name */
613   POOLMEM* esc_path;           /**< Escaped path name */
614   POOLMEM* esc_obj;            /**< Escaped restore object */
615   POOLMEM* cmd;                /**< SQL command string */
616   POOLMEM* errmsg;             /**< Nicely edited error message */
617   const char** queries;        /**< table of query texts */
618   static const char* query_names[]; /**< table of query names */
619 
620  private:
621   /*
622    * Methods
623    */
624   int GetFilenameRecord(JobControlRecord* jcr);
625   bool GetFileRecord(JobControlRecord* jcr,
626                      JobDbRecord* jr,
627                      FileDbRecord* fdbr);
628   bool CreateBatchFileAttributesRecord(JobControlRecord* jcr,
629                                        AttributesDbRecord* ar);
630   bool CreateFilenameRecord(JobControlRecord* jcr, AttributesDbRecord* ar);
631   bool CreateFileRecord(JobControlRecord* jcr, AttributesDbRecord* ar);
632   void CleanupBaseFile(JobControlRecord* jcr);
633   void BuildPathHierarchy(JobControlRecord* jcr,
634                           pathid_cache& ppathid_cache,
635                           char* org_pathid,
636                           char* path);
637   bool UpdatePathHierarchyCache(JobControlRecord* jcr,
638                                 pathid_cache& ppathid_cache,
639                                 JobId_t JobId);
640   void FillQueryVaList(POOLMEM*& query,
641                        BareosDb::SQL_QUERY_ENUM predefined_query,
642                        va_list arg_ptr);
643   void FillQueryVaList(PoolMem& query,
644                        BareosDb::SQL_QUERY_ENUM predefined_query,
645                        va_list arg_ptr);
646 
647  public:
648   /*
649    * Methods
650    */
BareosDb()651   BareosDb() {}
~BareosDb()652   virtual ~BareosDb() {}
get_db_name(void)653   const char* get_db_name(void) { return db_name_; }
get_db_user(void)654   const char* get_db_user(void) { return db_user_; }
IsConnected(void)655   bool IsConnected(void) { return connected_; }
BatchInsertAvailable(void)656   bool BatchInsertAvailable(void) { return have_batch_insert_; }
IsPrivate(void)657   bool IsPrivate(void) { return is_private_; }
SetPrivate(bool IsPrivate)658   void SetPrivate(bool IsPrivate) { is_private_ = IsPrivate; }
IncrementRefcount(void)659   void IncrementRefcount(void) { ref_count_++; }
660 
661   /* bvfs.c */
662   bool BvfsUpdatePathHierarchyCache(JobControlRecord* jcr, char* jobids);
663   void BvfsUpdateCache(JobControlRecord* jcr);
664   int BvfsLsDirs(PoolMem& query, void* ctx);
665   int BvfsBuildLsFileQuery(PoolMem& query,
666                            DB_RESULT_HANDLER* ResultHandler,
667                            void* ctx);
668 
669   /* sql.c */
670   char* strerror();
671   bool CheckMaxConnections(JobControlRecord* jcr, uint32_t max_concurrent_jobs);
672   bool CheckTablesVersion(JobControlRecord* jcr);
673   bool QueryDB(const char* file,
674                int line,
675                JobControlRecord* jcr,
676                const char* select_cmd);
677   bool InsertDB(const char* file,
678                 int line,
679                 JobControlRecord* jcr,
680                 const char* select_cmd);
681   int DeleteDB(const char* file,
682                int line,
683                JobControlRecord* jcr,
684                const char* DeleteCmd);
685   bool UpdateDB(const char* file,
686                 int line,
687                 JobControlRecord* jcr,
688                 const char* UpdateCmd,
689                 int nr_afr);
690   int GetSqlRecordMax(JobControlRecord* jcr);
691   void SplitPathAndFile(JobControlRecord* jcr, const char* fname);
692   void ListDashes(OutputFormatter* send);
693   int ListResult(void* vctx, int nb_col, char** row);
694   int ListResult(JobControlRecord* jcr,
695                  OutputFormatter* send,
696                  e_list_type type);
697   bool OpenBatchConnection(JobControlRecord* jcr);
698   void DbDebugPrint(FILE* fp);
699 
700   /* sql_create.c */
701   bool CreatePathRecord(JobControlRecord* jcr, AttributesDbRecord* ar);
702   bool CreateFileAttributesRecord(JobControlRecord* jcr,
703                                   AttributesDbRecord* ar);
704   bool CreateJobRecord(JobControlRecord* jcr, JobDbRecord* jr);
705   bool CreateMediaRecord(JobControlRecord* jcr, MediaDbRecord* media_dbr);
706   bool CreateClientRecord(JobControlRecord* jcr, ClientDbRecord* cr);
707   bool CreateFilesetRecord(JobControlRecord* jcr, FileSetDbRecord* fsr);
708   bool CreatePoolRecord(JobControlRecord* jcr, PoolDbRecord* pool_dbr);
709   bool CreateJobmediaRecord(JobControlRecord* jcr, JobMediaDbRecord* jr);
710   bool CreateCounterRecord(JobControlRecord* jcr, CounterDbRecord* cr);
711   bool CreateDeviceRecord(JobControlRecord* jcr, DeviceDbRecord* dr);
712   bool CreateStorageRecord(JobControlRecord* jcr, StorageDbRecord* sr);
713   bool CreateMediatypeRecord(JobControlRecord* jcr, MediaTypeDbRecord* mr);
714   bool WriteBatchFileRecords(JobControlRecord* jcr);
715   bool CreateAttributesRecord(JobControlRecord* jcr, AttributesDbRecord* ar);
716   bool CreateRestoreObjectRecord(JobControlRecord* jcr,
717                                  RestoreObjectDbRecord* ar);
718   bool CreateBaseFileAttributesRecord(JobControlRecord* jcr,
719                                       AttributesDbRecord* ar);
720   bool CommitBaseFileAttributesRecord(JobControlRecord* jcr);
721   bool CreateBaseFileList(JobControlRecord* jcr, char* jobids);
722   bool CreateQuotaRecord(JobControlRecord* jcr, ClientDbRecord* cr);
723   bool CreateNdmpLevelMapping(JobControlRecord* jcr,
724                               JobDbRecord* jr,
725                               char* filesystem);
726   bool CreateNdmpEnvironmentString(JobControlRecord* jcr,
727                                    JobDbRecord* jr,
728                                    char* name,
729                                    char* value);
730   bool CreateJobStatistics(JobControlRecord* jcr, JobStatisticsDbRecord* jsr);
731   bool CreateDeviceStatistics(JobControlRecord* jcr,
732                               DeviceStatisticsDbRecord* dsr);
733   bool CreateTapealertStatistics(JobControlRecord* jcr,
734                                  TapealertStatsDbRecord* tsr);
735 
736   /* sql_delete.c */
737   bool DeletePoolRecord(JobControlRecord* jcr, PoolDbRecord* pool_dbr);
738   bool DeleteMediaRecord(JobControlRecord* jcr, MediaDbRecord* mr);
739   bool PurgeMediaRecord(JobControlRecord* jcr, MediaDbRecord* mr);
740 
741   /* sql_find.c */
742   bool FindLastJobStartTime(JobControlRecord* jcr,
743                             JobDbRecord* jr,
744                             POOLMEM*& stime,
745                             char* job,
746                             int JobLevel);
747   bool FindJobStartTime(JobControlRecord* jcr,
748                         JobDbRecord* jr,
749                         POOLMEM*& stime,
750                         char* job);
751   bool FindLastJobid(JobControlRecord* jcr, const char* Name, JobDbRecord* jr);
752   int FindNextVolume(JobControlRecord* jcr,
753                      int index,
754                      bool InChanger,
755                      MediaDbRecord* mr,
756                      const char* unwanted_volumes);
757   bool FindFailedJobSince(JobControlRecord* jcr,
758                           JobDbRecord* jr,
759                           POOLMEM* stime,
760                           int& JobLevel);
761 
762   /* sql_get.c */
763   bool GetVolumeJobids(JobControlRecord* jcr,
764                        MediaDbRecord* mr,
765                        db_list_ctx* lst);
766   bool GetBaseFileList(JobControlRecord* jcr,
767                        bool use_md5,
768                        DB_RESULT_HANDLER* ResultHandler,
769                        void* ctx);
770   int GetPathRecord(JobControlRecord* jcr);
771   int GetPathRecord(JobControlRecord* jcr, const char* new_path);
772   bool GetPoolRecord(JobControlRecord* jcr, PoolDbRecord* pdbr);
773   bool GetStorageRecord(JobControlRecord* jcr, StorageDbRecord* sdbr);
774   bool GetJobRecord(JobControlRecord* jcr, JobDbRecord* jr);
775   int GetJobVolumeNames(JobControlRecord* jcr,
776                         JobId_t JobId,
777                         POOLMEM*& VolumeNames);
778   bool GetFileAttributesRecord(JobControlRecord* jcr,
779                                char* filename,
780                                JobDbRecord* jr,
781                                FileDbRecord* fdbr);
782   int GetFilesetRecord(JobControlRecord* jcr, FileSetDbRecord* fsr);
783   bool GetMediaRecord(JobControlRecord* jcr, MediaDbRecord* mr);
784   int GetNumMediaRecords(JobControlRecord* jcr);
785   int GetNumPoolRecords(JobControlRecord* jcr);
786   int GetPoolIds(JobControlRecord* jcr, int* num_ids, DBId_t** ids);
787   bool GetClientIds(JobControlRecord* jcr, int* num_ids, DBId_t** ids);
788   int GetStorageIds(JobControlRecord* jcr, int* num_ids, DBId_t** ids);
789   bool PrepareMediaSqlQuery(JobControlRecord* jcr,
790                             MediaDbRecord* mr,
791                             PoolMem& volumes);
792   bool GetMediaIds(JobControlRecord* jcr,
793                    MediaDbRecord* mr,
794                    PoolMem& volumes,
795                    int* num_ids,
796                    DBId_t** ids);
797   int GetJobVolumeParameters(JobControlRecord* jcr,
798                              JobId_t JobId,
799                              VolumeParameters** VolParams);
800   bool GetClientRecord(JobControlRecord* jcr, ClientDbRecord* cdbr);
801   bool GetCounterRecord(JobControlRecord* jcr, CounterDbRecord* cr);
802   bool GetQueryDbids(JobControlRecord* jcr, PoolMem& query, dbid_list& ids);
803   bool GetFileList(JobControlRecord* jcr,
804                    char* jobids,
805                    bool use_md5,
806                    bool use_delta,
807                    DB_RESULT_HANDLER* ResultHandler,
808                    void* ctx);
809   bool GetBaseJobid(JobControlRecord* jcr, JobDbRecord* jr, JobId_t* jobid);
810   bool AccurateGetJobids(JobControlRecord* jcr,
811                          JobDbRecord* jr,
812                          db_list_ctx* jobids);
813   bool GetUsedBaseJobids(JobControlRecord* jcr,
814                          POOLMEM* jobids,
815                          db_list_ctx* result);
816   bool GetQuotaRecord(JobControlRecord* jcr, ClientDbRecord* cr);
817   bool get_quota_jobbytes(JobControlRecord* jcr,
818                           JobDbRecord* jr,
819                           utime_t JobRetention);
820   bool get_quota_jobbytes_nofailed(JobControlRecord* jcr,
821                                    JobDbRecord* jr,
822                                    utime_t JobRetention);
823   int GetNdmpLevelMapping(JobControlRecord* jcr,
824                           JobDbRecord* jr,
825                           char* filesystem);
826   bool GetNdmpEnvironmentString(const std::string& query,
827                                 DB_RESULT_HANDLER* ResultHandler,
828                                 void* ctx);
829   bool GetNdmpEnvironmentString(const VolumeSessionInfo& vsi,
830                                 int32_t FileIndex,
831                                 DB_RESULT_HANDLER* ResultHandler,
832                                 void* ctx);
833   bool GetNdmpEnvironmentString(JobId_t JobId,
834                                 DB_RESULT_HANDLER* ResultHandler,
835                                 void* ctx);
836   bool GetNdmpEnvironmentString(JobId_t JobId,
837                                 int32_t FileIndex,
838                                 DB_RESULT_HANDLER* ResultHandler,
839                                 void* ctx);
840   bool PrepareMediaSqlQuery(JobControlRecord* jcr,
841                             MediaDbRecord* mr,
842                             PoolMem* querystring,
843                             PoolMem& volumes);
844   bool VerifyMediaIdsFromSingleStorage(JobControlRecord* jcr,
845                                        dbid_list& mediaIds);
846 
847   /* sql_list.c */
848   void ListPoolRecords(JobControlRecord* jcr,
849                        PoolDbRecord* pr,
850                        OutputFormatter* sendit,
851                        e_list_type type);
852   void ListJobRecords(JobControlRecord* jcr,
853                       JobDbRecord* jr,
854                       const char* range,
855                       const char* clientname,
856                       int jobstatus,
857                       int joblevel,
858                       const char* volumename,
859                       const char* poolname,
860                       utime_t since_time,
861                       bool last,
862                       bool count,
863                       OutputFormatter* sendit,
864                       e_list_type type);
865   void ListJobTotals(JobControlRecord* jcr,
866                      JobDbRecord* jr,
867                      OutputFormatter* sendit);
868   void ListFilesForJob(JobControlRecord* jcr,
869                        uint32_t jobid,
870                        OutputFormatter* sendit);
871   void ListFilesets(JobControlRecord* jcr,
872                     JobDbRecord* jr,
873                     const char* range,
874                     OutputFormatter* sendit,
875                     e_list_type type);
876   void ListStorageRecords(JobControlRecord* jcr,
877                           OutputFormatter* sendit,
878                           e_list_type type);
879   void ListMediaRecords(JobControlRecord* jcr,
880                         MediaDbRecord* mdbr,
881                         const char* range,
882                         bool count,
883                         OutputFormatter* sendit,
884                         e_list_type type);
885   void ListJobmediaRecords(JobControlRecord* jcr,
886                            JobId_t JobId,
887                            OutputFormatter* sendit,
888                            e_list_type type);
889   void ListVolumesOfJobid(JobControlRecord* jcr,
890                           JobId_t JobId,
891                           OutputFormatter* sendit,
892                           e_list_type type);
893   void ListJoblogRecords(JobControlRecord* jcr,
894                          JobId_t JobId,
895                          const char* range,
896                          bool count,
897                          OutputFormatter* sendit,
898                          e_list_type type);
899   void ListLogRecords(JobControlRecord* jcr,
900                       const char* clientname,
901                       const char* range,
902                       bool reverse,
903                       OutputFormatter* sendit,
904                       e_list_type type);
905   void ListJobstatisticsRecords(JobControlRecord* jcr,
906                                 uint32_t JobId,
907                                 OutputFormatter* sendit,
908                                 e_list_type type);
909   bool ListSqlQuery(JobControlRecord* jcr,
910                     const char* query,
911                     OutputFormatter* sendit,
912                     e_list_type type,
913                     bool verbose);
914   bool ListSqlQuery(JobControlRecord* jcr,
915                     SQL_QUERY_ENUM query,
916                     OutputFormatter* sendit,
917                     e_list_type type,
918                     bool verbose);
919   bool ListSqlQuery(JobControlRecord* jcr,
920                     const char* query,
921                     OutputFormatter* sendit,
922                     e_list_type type,
923                     const char* description,
924                     bool verbose = false);
925   bool ListSqlQuery(JobControlRecord* jcr,
926                     SQL_QUERY_ENUM query,
927                     OutputFormatter* sendit,
928                     e_list_type type,
929                     const char* description,
930                     bool verbose);
931   void ListClientRecords(JobControlRecord* jcr,
932                          char* clientname,
933                          OutputFormatter* sendit,
934                          e_list_type type);
935   void ListCopiesRecords(JobControlRecord* jcr,
936                          const char* range,
937                          const char* jobids,
938                          OutputFormatter* sendit,
939                          e_list_type type);
940   void ListBaseFilesForJob(JobControlRecord* jcr,
941                            JobId_t jobid,
942                            OutputFormatter* sendit);
943 
944   /* SqlQuery.c */
945   const char* get_predefined_query_name(SQL_QUERY_ENUM query);
946   const char* get_predefined_query(SQL_QUERY_ENUM query);
947 
948   void FillQuery(SQL_QUERY_ENUM predefined_query, ...);
949   void FillQuery(POOLMEM*& query, SQL_QUERY_ENUM predefined_query, ...);
950   void FillQuery(PoolMem& query, SQL_QUERY_ENUM predefined_query, ...);
951 
952   bool SqlQuery(SQL_QUERY_ENUM query, ...);
953   bool SqlQuery(const char* query, int flags = 0);
954   bool SqlQuery(const char* query, DB_RESULT_HANDLER* ResultHandler, void* ctx);
955 
956   /* sql_update.c */
957   bool UpdateJobStartRecord(JobControlRecord* jcr, JobDbRecord* jr);
958   bool UpdateJobEndRecord(JobControlRecord* jcr, JobDbRecord* jr);
959   bool UpdateClientRecord(JobControlRecord* jcr, ClientDbRecord* cr);
960   bool UpdatePoolRecord(JobControlRecord* jcr, PoolDbRecord* pr);
961   bool UpdateStorageRecord(JobControlRecord* jcr, StorageDbRecord* sr);
962   bool UpdateMediaRecord(JobControlRecord* jcr, MediaDbRecord* mr);
963   bool UpdateMediaDefaults(JobControlRecord* jcr, MediaDbRecord* mr);
964   bool UpdateCounterRecord(JobControlRecord* jcr, CounterDbRecord* cr);
965   bool UpdateQuotaGracetime(JobControlRecord* jcr, JobDbRecord* jr);
966   bool UpdateQuotaSoftlimit(JobControlRecord* jcr, JobDbRecord* jr);
967   bool ResetQuotaRecord(JobControlRecord* jcr, ClientDbRecord* jr);
968   bool UpdateNdmpLevelMapping(JobControlRecord* jcr,
969                               JobDbRecord* jr,
970                               char* filesystem,
971                               int level);
972   bool AddDigestToFileRecord(JobControlRecord* jcr,
973                              FileId_t FileId,
974                              char* digest,
975                              int type);
976   bool MarkFileRecord(JobControlRecord* jcr, FileId_t FileId, JobId_t JobId);
977   void MakeInchangerUnique(JobControlRecord* jcr, MediaDbRecord* mr);
978   int UpdateStats(JobControlRecord* jcr, utime_t age);
979 
980   /* Low level methods */
981   bool MatchDatabase(const char* db_driver,
982                      const char* db_name,
983                      const char* db_address,
984                      int db_port);
985   BareosDb* CloneDatabaseConnection(JobControlRecord* jcr,
986                                     bool mult_db_connections,
987                                     bool get_pooled_connection = true,
988                                     bool need_private = false);
GetTypeIndex(void)989   int GetTypeIndex(void) { return db_type_; }
990   const char* GetType(void);
991   void LockDb(const char* file, int line);
992   void UnlockDb(const char* file, int line);
993   void PrintLockInfo(FILE* fp);
994 
995   /* Virtual low level methods */
ThreadCleanup(void)996   virtual void ThreadCleanup(void) {}
997   virtual void EscapeString(JobControlRecord* jcr,
998                             char* snew,
999                             char* old,
1000                             int len);
1001   virtual char* EscapeObject(JobControlRecord* jcr, char* old, int len);
1002   virtual void UnescapeObject(JobControlRecord* jcr,
1003                               char* from,
1004                               int32_t expected_len,
1005                               POOLMEM*& dest,
1006                               int32_t* len);
1007 
1008   /* Pure virtual low level methods */
1009   virtual bool OpenDatabase(JobControlRecord* jcr) = 0;
1010   virtual void CloseDatabase(JobControlRecord* jcr) = 0;
1011   virtual bool ValidateConnection(void) = 0;
1012   virtual void StartTransaction(JobControlRecord* jcr) = 0;
1013   virtual void EndTransaction(JobControlRecord* jcr) = 0;
1014 
1015   /* By default, we use db_sql_query */
BigSqlQuery(const char * query,DB_RESULT_HANDLER * ResultHandler,void * ctx)1016   virtual bool BigSqlQuery(const char* query,
1017                            DB_RESULT_HANDLER* ResultHandler,
1018                            void* ctx)
1019   {
1020     return SqlQuery(query, ResultHandler, ctx);
1021   }
1022 
1023 #ifdef _BDB_PRIV_INTERFACE_
1024   /*
1025    * Backend methods
1026    */
1027  private:
1028   virtual int SqlNumRows(void) = 0;
1029   virtual void SqlFieldSeek(int field) = 0;
1030   virtual int SqlNumFields(void) = 0;
1031   virtual void SqlFreeResult(void) = 0;
1032   virtual SQL_ROW SqlFetchRow(void) = 0;
1033   virtual bool SqlQueryWithoutHandler(const char* query, int flags = 0) = 0;
1034   virtual bool SqlQueryWithHandler(const char* query,
1035                                    DB_RESULT_HANDLER* ResultHandler,
1036                                    void* ctx) = 0;
1037   virtual const char* sql_strerror(void) = 0;
1038   virtual void SqlDataSeek(int row) = 0;
1039   virtual int SqlAffectedRows(void) = 0;
1040   virtual uint64_t SqlInsertAutokeyRecord(const char* query,
1041                                           const char* table_name) = 0;
1042   virtual SQL_FIELD* SqlFetchField(void) = 0;
1043   virtual bool SqlFieldIsNotNull(int field_type) = 0;
1044   virtual bool SqlFieldIsNumeric(int field_type) = 0;
1045   virtual bool SqlBatchStart(JobControlRecord* jcr) = 0;
1046   virtual bool SqlBatchEnd(JobControlRecord* jcr, const char* error) = 0;
1047   virtual bool SqlBatchInsert(JobControlRecord* jcr,
1048                               AttributesDbRecord* ar) = 0;
1049 #endif
1050 };
1051 
1052 #ifdef _BDB_PRIV_INTERFACE_
1053 #include "bdb_priv.h"
1054 #endif
1055 
1056 /* SqlQuery Query Flags */
1057 #define QF_STORE_RESULT 0x01
1058 
1059 /* flush the batch insert connection every x changes */
1060 #define BATCH_FLUSH 800000
1061 
1062 /* Use for better error location printing */
1063 #define UPDATE_DB(jcr, cmd) UpdateDB(__FILE__, __LINE__, jcr, cmd, 1)
1064 #define UPDATE_DB_NO_AFR(jcr, cmd) UpdateDB(__FILE__, __LINE__, jcr, cmd, 0)
1065 #define INSERT_DB(jcr, cmd) InsertDB(__FILE__, __LINE__, jcr, cmd)
1066 #define QUERY_DB(jcr, cmd) QueryDB(__FILE__, __LINE__, jcr, cmd)
1067 #define DELETE_DB(jcr, cmd) DeleteDB(__FILE__, __LINE__, jcr, cmd)
1068 
1069 /**
1070  * Pooled backend connection.
1071  */
1072 struct SqlPoolEntry {
1073   int id; /**< Unique ID, connection numbering can have holes and the pool is
1074              not sorted on it */
1075   int reference_count; /**< Reference count for this entry */
1076   time_t last_update;  /**< When was this connection last updated either used or
1077                           put back on the pool */
1078   BareosDb* db_handle; /**< Connection handle to the database */
1079   dlink link;          /**< list management */
1080 };
1081 
1082 /**
1083  * Pooled backend list descriptor (one defined per backend defined in config)
1084  */
1085 struct SqlPoolDescriptor {
1086   dlist* pool_entries; /**< Linked list of all pool entries */
1087   bool active; /**< Is this an active pool, after a config reload an pool is
1088                   made inactive */
1089   time_t last_update;  /**< When was this pool last updated */
1090   int min_connections; /**< Minimum number of connections in the connection pool
1091                         */
1092   int max_connections; /**< Maximum number of connections in the connection pool
1093                         */
1094   int increment_connections; /**< Increase/Decrease the number of connection in
1095                                 the pool with this value */
1096   int idle_timeout;     /**< Number of seconds to wait before tearing down a
1097                            connection */
1098   int validate_timeout; /**< Number of seconds after which an idle connection
1099                            should be validated */
1100   int nr_connections;   /**< Number of active connections in the pool */
1101   dlink link;           /**< list management */
1102 };
1103 
1104 #include "include/jcr.h"
1105 
1106 /**
1107  * Object used in db_list_xxx function
1108  */
1109 class ListContext {
1110  public:
1111   char line[256]; /**< Used to print last dash line */
1112   int32_t num_rows;
1113 
1114   e_list_type type;      /**< Vertical/Horizontal */
1115   OutputFormatter* send; /**< send data back */
1116   bool once;             /**< Used to print header one time */
1117   BareosDb* mdb;
1118   JobControlRecord* jcr;
1119 
empty()1120   void empty()
1121   {
1122     once = false;
1123     line[0] = '\0';
1124   }
1125 
send_dashes()1126   void send_dashes()
1127   {
1128     if (*line) { send->Decoration(line); }
1129   }
1130 
ListContext(JobControlRecord * j,BareosDb * m,OutputFormatter * h,e_list_type t)1131   ListContext(JobControlRecord* j,
1132               BareosDb* m,
1133               OutputFormatter* h,
1134               e_list_type t)
1135   {
1136     line[0] = '\0';
1137     once = false;
1138     num_rows = 0;
1139     type = t;
1140     send = h;
1141     jcr = j;
1142     mdb = m;
1143   }
1144 };
1145 
1146 /**
1147  * Some functions exported by sql.c for use within the cats directory.
1148  */
1149 int ListResult(void* vctx, int cols, char** row);
1150 int ListResult(JobControlRecord* jcr,
1151                BareosDb* mdb,
1152                OutputFormatter* send,
1153                e_list_type type);
1154 #endif /* BAREOS_CATS_CATS_H_ */
1155