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
20 Copyright (C) 2001-2003 Kern Sibbald and John Walker
22 This program is free software; you can redistribute it and/or
23 modify it under the terms of the GNU General Public License as
24 published by the Free Software Foundation; either version 2 of
25 the License, or (at your option) any later version.
27 This program is distributed in the hope that it will be useful,
28 but WITHOUT ANY WARRANTY; without even the implied warranty of
29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
30 General Public License for more details.
32 You should have received a copy of the GNU General Public
33 License along with this program; if not, write to the Free
34 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
40 /* The following is necessary so that we do not include
41 * the dummy external definition of DB.
43 #define __SQL_C /* indicate that this is sql.c */
51 /* Forward referenced functions */
54 /* -----------------------------------------------------------------------
56 * Bacula specific defines and subroutines
58 * -----------------------------------------------------------------------
63 * Get Job record for given JobId
64 * Returns: 0 on failure
68 int db_get_job_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr)
77 if (jr->JobId == 0 && jr->Name[0] == 0) { /* he wants # of Job records */
78 jr->JobId = mdb->control.JobId;
82 Dmsg0(200, "Open Jobs\n");
83 if (!bdb_open_jobs_file(mdb)) {
87 fseek(mdb->jobfd, 0L, SEEK_SET); /* rewind file */
89 /* Linear search through Job records
92 while (fread(&ojr, len, 1, mdb->jobfd) > 0) {
93 /* If id not zero, search by Id */
95 if (jr->JobId == ojr.JobId) {
99 } else if (strcmp(jr->Job, ojr.Job) == 0) {
101 Dmsg1(200, "Found Job: %s\n", ojr.Job);
104 rec_addr = ftell(mdb->jobfd); /* save start next record */
107 /* Found desired record, now return it */
108 memcpy(jr, &ojr, len);
109 jr->rec_addr = rec_addr;
111 Dmsg2(200, "Found job record: JobId=%d Job=%s",
116 strcpy(mdb->errmsg, "Job record not found.\n");
119 Dmsg1(200, "Return job stat=%d\n", stat);
125 * Get the number of pool records
127 * Returns: -1 on failure
130 int db_get_num_pool_records(JCR *jcr, B_DB *mdb)
135 stat = mdb->control.PoolId;
141 * This function returns a list of all the Pool record ids.
142 * The caller must free ids if non-NULL.
144 * Returns 0: on failure
147 int db_get_pool_ids(JCR *jcr, B_DB *mdb, int *num_ids, uint32_t *ids[])
156 if (!bdb_open_pools_file(mdb)) {
160 fseek(mdb->poolfd, 0L, SEEK_SET); /* rewind file */
161 /* Linear search through Pool records
164 *num_ids = mdb->control.PoolId;
165 id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
166 while (fread(&opr, len, 1, mdb->poolfd) > 0) {
167 id[i++] = opr.PoolId;
177 * If the PoolId is non-zero, we get its record,
178 * otherwise, we search on the PoolName
180 * Returns: 0 on failure
183 int db_get_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr)
192 Dmsg0(200, "Open pools\n");
193 if (!bdb_open_pools_file(mdb)) {
197 fseek(mdb->poolfd, 0L, SEEK_SET); /* rewind file */
199 /* Linear search through Pool records
202 while (fread(&opr, len, 1, mdb->poolfd) > 0) {
203 /* If id not zero, search by Id */
204 if (pr->PoolId != 0) {
205 if (pr->PoolId == opr.PoolId) {
209 } else if (strcmp(pr->Name, opr.Name) == 0) {
211 Dmsg1(200, "Found pool: %s\n", opr.Name);
214 rec_addr = ftell(mdb->poolfd); /* save start next record */
217 /* Found desired record, now return it */
218 memcpy(pr, &opr, len);
219 pr->rec_addr = rec_addr;
221 Dmsg3(200, "Found pool record: PoolId=%d Name=%s PoolType=%s\n",
222 opr.PoolId, opr.Name, opr.PoolType);
226 strcpy(mdb->errmsg, "Pool record not found.\n");
229 Dmsg1(200, "Return pool stat=%d\n", stat);
234 * Get the number of Media records
236 * Returns: -1 on failure
239 int db_get_num_media_records(JCR *jcr, B_DB *mdb)
244 stat = mdb->control.MediaId;
250 * This function returns a list of all the Media record ids
251 * for a specified PoolId
252 * The caller must free ids if non-NULL.
254 * Returns 0: on failure
257 int db_get_media_ids(JCR *jcr, B_DB *mdb, uint32_t PoolId, int *num_ids, uint32_t *ids[])
266 if (!bdb_open_media_file(mdb)) {
270 fseek(mdb->mediafd, 0L, SEEK_SET); /* rewind file */
271 /* Linear search through Pool records
274 if (mdb->control.MediaId == 0) {
278 *num_ids = mdb->control.MediaId;
279 id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
280 while (fread(&omr, len, 1, mdb->mediafd) > 0) {
281 if (PoolId == omr.MediaId) {
282 id[i++] = omr.MediaId;
292 * If the MediaId is non-zero, we get its record,
293 * otherwise, we search on the MediaName
295 * Returns: 0 on failure
298 int db_get_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
307 if (!bdb_open_media_file(mdb)) {
311 fseek(mdb->mediafd, 0L, SEEK_SET); /* rewind file */
313 /* Linear search through Media records
316 while (fread(&omr, len, 1, mdb->mediafd) > 0) {
317 if (omr.MediaId == 0) {
318 continue; /* deleted record */
320 Dmsg1(200, "VolName=%s\n", omr.VolumeName);
321 /* If id not zero, search by Id */
322 if (mr->MediaId != 0) {
323 Dmsg1(200, "MediaId=%d\n", mr->MediaId);
324 if (mr->MediaId == omr.MediaId) {
328 } else if (strcmp(mr->VolumeName, omr.VolumeName) == 0) {
332 rec_addr = ftell(mdb->mediafd); /* save start next record */
335 /* Found desired record, now return it */
336 memcpy(mr, &omr, len);
337 mr->rec_addr = rec_addr;
339 Dmsg3(200, "Found media record: MediaId=%d Name=%s MediaType=%s\n",
340 omr.MediaId, omr.VolumeName, mr->MediaType);
344 strcpy(mdb->errmsg, "Could not find requested Media record.\n");
351 * Find VolumeNames for a give JobId
352 * Returns: 0 on error or no Volumes found
353 * number of volumes on success
354 * Volumes are concatenated in VolumeNames
355 * separated by a vertical bar (|).
357 int db_get_job_volume_names(JCR *jcr, B_DB *mdb, uint32_t JobId, POOLMEM **VolumeNames)
365 if (!bdb_open_jobmedia_file(mdb)) {
369 if (!bdb_open_media_file(mdb)) {
376 fseek(mdb->jobmediafd, 0L, SEEK_SET); /* rewind the file */
377 while (fread(&jm, jmlen, 1, mdb->jobmediafd) > 0) {
378 if (jm.JobId == JobId) {
379 /* Now look up VolumeName in Media file given MediaId */
380 fseek(mdb->mediafd, 0L, SEEK_SET);
381 while (fread(&mr, mrlen, 1, mdb->mediafd) > 0) {
382 if (jm.MediaId == mr.MediaId) {
383 if (*VolumeNames[0] != 0) { /* if not first name, */
384 pm_strcat(VolumeNames, "|"); /* add separator */
386 pm_strcat(VolumeNames, mr.VolumeName); /* add Volume Name */
393 strcpy(mdb->errmsg, "No Volumes found.\n");
401 * If the ClientId is non-zero, we get its record,
402 * otherwise, we search on the Name
404 * Returns: 0 on failure
407 int db_get_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cr)
414 if (!bdb_open_client_file(mdb)) {
418 fseek(mdb->clientfd, 0L, SEEK_SET); /* rewind file */
420 * Linear search through Client records
423 while (fread(&lcr, len, 1, mdb->clientfd)) {
424 /* If id not zero, search by Id */
425 if (cr->ClientId != 0) {
426 if (cr->ClientId != lcr.ClientId) {
430 } else if (strcmp(cr->Name, lcr.Name) != 0) {
431 continue; /* not found */
433 memcpy(cr, &lcr, len);
435 Dmsg2(200, "Found Client record: ClientId=%d Name=%s\n",
436 lcr.ClientId, lcr.Name);
440 strcpy(mdb->errmsg, "Client record not found.\n");
447 * Get FileSet Record (We read the FILESET_DBR structure)
448 * If the FileSetId is non-zero, we get its record,
449 * otherwise, we search on the FileSet (its name).
451 * Returns: 0 on failure
454 int db_get_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr)
460 if (!bdb_open_fileset_file(mdb)) {
464 fseek(mdb->filesetfd, 0L, SEEK_SET); /* rewind file */
466 * Linear search through FileSet records
468 while (fread(&lfsr, sizeof(lfsr), 1, mdb->filesetfd) > 0) {
469 /* If id not zero, search by Id */
470 if (fsr->FileSetId != 0) {
471 if (fsr->FileSetId != lfsr.FileSetId) {
474 /* Search by Name & MD5 */
475 } else if (strcmp(fsr->FileSet, lfsr.FileSet) != 0 ||
476 strcmp(fsr->MD5, lfsr.MD5) != 0) {
477 continue; /* not found */
479 /* Found desired record, now return it */
480 memcpy(fsr, &lfsr, sizeof(lfsr));
481 stat = fsr->FileSetId;
482 Dmsg2(200, "Found FileSet record: FileSetId=%d FileSet=%s\n",
483 lfsr.FileSetId, lfsr.FileSet);
487 strcpy(mdb->errmsg, "FileSet record not found.\n");
495 int db_get_file_attributes_record(JCR *jcr, B_DB *mdb, char *fname, JOB_DBR *jr, FILE_DBR *fdbr)
498 int db_get_job_volume_parameters(JCR *jcr, B_DB *mdb, uint32_t JobId, VOL_PARAMS **VolParams)
501 int db_get_client_ids(JCR *jcr, B_DB *mdb, int *num_ids, uint32_t *ids[])
504 int db_get_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr)
508 #endif /* HAVE_BACULA_DB */