2 * Bacula Catalog Database Get record interface routines
3 * Note, these routines generally get a record by id or
4 * by name. If more logic is involved, the routine
7 * Bacula Catalog Database routines written specifically
8 * for Bacula. Note, these routines are VERY dumb and
9 * do not provide all the functionality of an SQL database.
10 * The purpose of these routines is to ensure that Bacula
11 * can limp along if no real database is loaded on the
14 * Kern Sibbald, January MMI
19 Bacula® - The Network Backup Solution
21 Copyright (C) 2001-2006 Free Software Foundation Europe e.V.
23 The main author of Bacula is Kern Sibbald, with contributions from
24 many others, a complete list can be found in the file AUTHORS.
25 This program is Free Software; you can redistribute it and/or
26 modify it under the terms of version two of the GNU General Public
27 License as published by the Free Software Foundation and included
30 This program is distributed in the hope that it will be useful, but
31 WITHOUT ANY WARRANTY; without even the implied warranty of
32 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
33 General Public License for more details.
35 You should have received a copy of the GNU General Public License
36 along with this program; if not, write to the Free Software
37 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
40 Bacula® is a registered trademark of John Walker.
41 The licensor of Bacula is the Free Software Foundation Europe
42 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
43 Switzerland, email:ftf@fsfeurope.org.
47 /* The following is necessary so that we do not include
48 * the dummy external definition of DB.
50 #define __SQL_C /* indicate that this is sql.c */
58 /* Forward referenced functions */
61 /* -----------------------------------------------------------------------
63 * Bacula specific defines and subroutines
65 * -----------------------------------------------------------------------
70 * Get Job record for given JobId
71 * Returns: 0 on failure
75 bool db_get_job_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr)
84 if (jr->JobId == 0 && jr->Name[0] == 0) { /* he wants # of Job records */
85 jr->JobId = mdb->control.JobId;
89 Dmsg0(200, "Open Jobs\n");
90 if (!bdb_open_jobs_file(mdb)) {
94 fseek(mdb->jobfd, 0L, SEEK_SET); /* rewind file */
96 /* Linear search through Job records
99 while (fread(&ojr, len, 1, mdb->jobfd) > 0) {
100 /* If id not zero, search by Id */
101 if (jr->JobId != 0) {
102 if (jr->JobId == ojr.JobId) {
106 } else if (strcmp(jr->Job, ojr.Job) == 0) {
108 Dmsg1(200, "Found Job: %s\n", ojr.Job);
111 rec_addr = ftell(mdb->jobfd); /* save start next record */
114 /* Found desired record, now return it */
115 memcpy(jr, &ojr, len);
116 jr->rec_addr = rec_addr;
118 Dmsg2(200, "Found job record: JobId=%d Job=%s",
123 strcpy(mdb->errmsg, "Job record not found.\n");
126 Dmsg1(200, "Return job stat=%d\n", stat);
132 * Get the number of pool records
134 * Returns: -1 on failure
137 int db_get_num_pool_records(JCR *jcr, B_DB *mdb)
142 stat = mdb->control.PoolId;
148 * This function returns a list of all the Pool record ids.
149 * The caller must free ids if non-NULL.
151 * Returns 0: on failure
154 int db_get_pool_ids(JCR *jcr, B_DB *mdb, int *num_ids, uint32_t *ids[])
163 if (!bdb_open_pools_file(mdb)) {
167 fseek(mdb->poolfd, 0L, SEEK_SET); /* rewind file */
168 /* Linear search through Pool records
171 *num_ids = mdb->control.PoolId;
172 id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
173 while (fread(&opr, len, 1, mdb->poolfd) > 0) {
174 id[i++] = opr.PoolId;
184 * If the PoolId is non-zero, we get its record,
185 * otherwise, we search on the PoolName
187 * Returns: false on failure
190 bool db_get_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr)
198 Dmsg0(200, "Open pools\n");
199 if (!bdb_open_pools_file(mdb)) {
203 fseek(mdb->poolfd, 0L, SEEK_SET); /* rewind file */
205 /* Linear search through Pool records
208 while (fread(&opr, len, 1, mdb->poolfd) > 0) {
209 /* If id not zero, search by Id */
210 if (pr->PoolId != 0) {
211 if (pr->PoolId == opr.PoolId) {
215 } else if (strcmp(pr->Name, opr.Name) == 0) {
217 Dmsg1(200, "Found pool: %s\n", opr.Name);
220 rec_addr = ftell(mdb->poolfd); /* save start next record */
223 /* Found desired record, now return it */
224 memcpy(pr, &opr, len);
225 pr->rec_addr = rec_addr;
226 Dmsg3(200, "Found pool record: PoolId=%d Name=%s PoolType=%s\n",
227 opr.PoolId, opr.Name, opr.PoolType);
231 strcpy(mdb->errmsg, "Pool record not found.\n");
238 * Get the number of Media records
240 * Returns: -1 on failure
243 int db_get_num_media_records(JCR *jcr, B_DB *mdb)
248 stat = mdb->control.MediaId;
254 * This function returns a list of all the Media record ids
255 * for a specified PoolId
256 * The caller must free ids if non-NULL.
258 * Returns false: on failure
261 bool db_get_media_ids(JCR *jcr, B_DB *mdb, uint32_t PoolId, int *num_ids, uint32_t *ids[])
270 if (!bdb_open_media_file(mdb)) {
274 fseek(mdb->mediafd, 0L, SEEK_SET); /* rewind file */
275 /* Linear search through Pool records
278 if (mdb->control.MediaId == 0) {
282 *num_ids = mdb->control.MediaId;
283 id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
284 while (fread(&omr, len, 1, mdb->mediafd) > 0) {
285 if (PoolId == omr.MediaId) {
286 id[i++] = omr.MediaId;
296 * If the MediaId is non-zero, we get its record,
297 * otherwise, we search on the MediaName
299 * Returns: false on failure
302 bool db_get_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
310 if (!bdb_open_media_file(mdb)) {
313 fseek(mdb->mediafd, 0L, SEEK_SET); /* rewind file */
315 /* Linear search through Media records
318 while (fread(&omr, len, 1, mdb->mediafd) > 0) {
319 if (omr.MediaId == 0) {
320 continue; /* deleted record */
322 Dmsg1(200, "VolName=%s\n", omr.VolumeName);
323 /* If id not zero, search by Id */
324 if (mr->MediaId != 0) {
325 Dmsg1(200, "MediaId=%d\n", mr->MediaId);
326 if (mr->MediaId == omr.MediaId) {
330 } else if (strcmp(mr->VolumeName, omr.VolumeName) == 0) {
334 rec_addr = ftell(mdb->mediafd); /* save start next record */
337 /* Found desired record, now return it */
338 memcpy(mr, &omr, len);
339 mr->rec_addr = rec_addr;
340 Dmsg3(200, "Found media record: MediaId=%d Name=%s MediaType=%s\n",
341 omr.MediaId, omr.VolumeName, mr->MediaType);
345 strcpy(mdb->errmsg, "Could not find requested Media record.\n");
353 * Find VolumeNames for a give JobId
354 * Returns: 0 on error or no Volumes found
355 * number of volumes on success
356 * Volumes are concatenated in VolumeNames
357 * separated by a vertical bar (|).
359 int db_get_job_volume_names(JCR *jcr, B_DB *mdb, uint32_t JobId, POOLMEM **VolumeNames)
367 if (!bdb_open_jobmedia_file(mdb)) {
371 if (!bdb_open_media_file(mdb)) {
378 fseek(mdb->jobmediafd, 0L, SEEK_SET); /* rewind the file */
379 while (fread(&jm, jmlen, 1, mdb->jobmediafd) > 0) {
380 if (jm.JobId == JobId) {
381 /* Now look up VolumeName in Media file given MediaId */
382 fseek(mdb->mediafd, 0L, SEEK_SET);
383 while (fread(&mr, mrlen, 1, mdb->mediafd) > 0) {
384 if (jm.MediaId == mr.MediaId) {
385 if (*VolumeNames[0] != 0) { /* if not first name, */
386 pm_strcat(VolumeNames, "|"); /* add separator */
388 pm_strcat(VolumeNames, mr.VolumeName); /* add Volume Name */
395 strcpy(mdb->errmsg, "No Volumes found.\n");
403 * If the ClientId is non-zero, we get its record,
404 * otherwise, we search on the Name
406 * Returns: 0 on failure
409 int db_get_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cr)
416 if (!bdb_open_client_file(mdb)) {
420 fseek(mdb->clientfd, 0L, SEEK_SET); /* rewind file */
422 * Linear search through Client records
425 while (fread(&lcr, len, 1, mdb->clientfd)) {
426 /* If id not zero, search by Id */
427 if (cr->ClientId != 0) {
428 if (cr->ClientId != lcr.ClientId) {
432 } else if (strcmp(cr->Name, lcr.Name) != 0) {
433 continue; /* not found */
435 memcpy(cr, &lcr, len);
437 Dmsg2(200, "Found Client record: ClientId=%d Name=%s\n",
438 lcr.ClientId, lcr.Name);
442 strcpy(mdb->errmsg, "Client record not found.\n");
449 * Get FileSet Record (We read the FILESET_DBR structure)
450 * If the FileSetId is non-zero, we get its record,
451 * otherwise, we search on the FileSet (its name).
453 * Returns: 0 on failure
456 int db_get_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr)
462 if (!bdb_open_fileset_file(mdb)) {
466 fseek(mdb->filesetfd, 0L, SEEK_SET); /* rewind file */
468 * Linear search through FileSet records
470 while (fread(&lfsr, sizeof(lfsr), 1, mdb->filesetfd) > 0) {
471 /* If id not zero, search by Id */
472 if (fsr->FileSetId != 0) {
473 if (fsr->FileSetId != lfsr.FileSetId) {
476 /* Search by Name & MD5 */
477 } else if (strcmp(fsr->FileSet, lfsr.FileSet) != 0 ||
478 strcmp(fsr->MD5, lfsr.MD5) != 0) {
479 continue; /* not found */
481 /* Found desired record, now return it */
482 memcpy(fsr, &lfsr, sizeof(lfsr));
483 stat = fsr->FileSetId;
484 Dmsg2(200, "Found FileSet record: FileSetId=%d FileSet=%s\n",
485 lfsr.FileSetId, lfsr.FileSet);
489 strcpy(mdb->errmsg, "FileSet record not found.\n");
495 bool db_get_query_dbids(JCR *jcr, B_DB *mdb, POOL_MEM &query, dbid_list &ids)
498 int db_get_file_attributes_record(JCR *jcr, B_DB *mdb, char *fname, JOB_DBR *jr, FILE_DBR *fdbr)
501 int db_get_job_volume_parameters(JCR *jcr, B_DB *mdb, uint32_t JobId, VOL_PARAMS **VolParams)
504 int db_get_client_ids(JCR *jcr, B_DB *mdb, int *num_ids, uint32_t *ids[])
507 int db_get_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr)
511 #endif /* HAVE_BACULA_DB */