2 * Bacula Catalog Database routines written specifically
3 * for Bacula. Note, these routines are VERY dumb and
4 * do not provide all the functionality of an SQL database.
5 * The purpose of these routines is to ensure that Bacula
6 * can limp along if no real database is loaded on the
9 * Kern Sibbald, January MMI
13 Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
15 This program is free software; you can redistribute it and/or
16 modify it under the terms of the GNU General Public License as
17 published by the Free Software Foundation; either version 2 of
18 the License, or (at your option) any later version.
20 This program is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
25 You should have received a copy of the GNU General Public
26 License along with this program; if not, write to the Free
27 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
33 /* The following is necessary so that we do not include
34 * the dummy external definition of DB.
36 #define __SQL_C /* indicate that this is sql.c */
43 /* Forward referenced functions */
45 extern char *working_directory;
47 /* List of open databases */
48 static BQUEUE db_list = {&db_list, &db_list};
49 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
51 /* -----------------------------------------------------------------------
53 * Bacula specific defines and subroutines
55 * -----------------------------------------------------------------------
59 #define DB_CONTROL_FILENAME "control.db"
60 #define DB_JOBS_FILENAME "jobs.db"
61 #define DB_POOLS_FILENAME "pools.db"
62 #define DB_MEDIA_FILENAME "media.db"
63 #define DB_JOBMEDIA_FILENAME "jobmedia.db"
64 #define DB_CLIENT_FILENAME "client.db"
65 #define DB_FILESET_FILENAME "fileset.db"
67 static char *make_filename(B_DB *mdb, char *name)
71 dbf = (char *) get_pool_memory(PM_FNAME);
72 if (working_directory[strlen(working_directory)-1] == '/') {
77 Mmsg(&dbf, "%s%c%s-%s", working_directory, sep, mdb->db_name, name);
81 int bdb_write_control_file(B_DB *mdb)
83 mdb->control.time = time(NULL);
84 lseek(mdb->cfd, 0, SEEK_SET);
85 if (write(mdb->cfd, &mdb->control, sizeof(mdb->control)) != sizeof(mdb->control)) {
86 Mmsg1(&mdb->errmsg, "Error writing control file. ERR=%s\n", strerror(errno));
87 Emsg0(M_FATAL, 0, mdb->errmsg);
94 * Initialize database data structure. In principal this should
95 * never have errors, or it is really fatal.
98 db_init_database(char *db_name, char *db_user, char *db_password)
101 P(mutex); /* lock DB queue */
102 /* Look to see if DB already open */
103 for (mdb=NULL; (mdb=(B_DB *)qnext(&db_list, &mdb->bq)); ) {
104 if (strcmp(mdb->db_name, db_name) == 0) {
105 Dmsg2(200, "DB REopen %d %s\n", mdb->ref_count, db_name);
108 return mdb; /* already open */
111 Dmsg0(200, "db_open first time\n");
112 mdb = (B_DB *) malloc(sizeof(B_DB));
113 memset(mdb, 0, sizeof(B_DB));
114 Dmsg0(200, "DB struct init\n");
115 mdb->db_name = bstrdup(db_name);
116 mdb->errmsg = (char *) get_pool_memory(PM_EMSG);
118 mdb->cmd = (char *) get_pool_memory(PM_EMSG); /* command buffer */
120 qinsert(&db_list, &mdb->bq); /* put db in list */
121 Dmsg0(200, "Done db_open_database()\n");
128 * Now actually open the database. This can generate errors,
129 * which are returned in the errmsg
132 db_open_database(B_DB *mdb)
139 Dmsg1(200, "db_open_database() %s\n", mdb->db_name);
142 if ((errstat = pthread_mutex_init(&(mdb->mutex), NULL)) != 0) {
143 Mmsg1(&mdb->errmsg, "Unable to initialize DB mutex. ERR=%s\n", strerror(errstat));
147 P(mdb->mutex); /* test it once */
150 Dmsg0(200, "make_filename\n");
151 dbf = make_filename(mdb, DB_CONTROL_FILENAME);
152 mdb->cfd = open(dbf, O_CREAT|O_RDWR, 0600);
155 Mmsg2(&mdb->errmsg, "Unable to open Catalog DB control file %s: ERR=%s\n",
156 dbf, strerror(errno));
160 Dmsg0(200, "DB open\n");
161 /* See if the file was previously written */
162 filend = lseek(mdb->cfd, 0, SEEK_END);
163 if (filend == 0) { /* No, initialize everything */
164 Dmsg0(200, "Init DB files\n");
165 memset(&mdb->control, 0, sizeof(mdb->control));
166 mdb->control.bdb_version = BDB_VERSION;
167 bdb_write_control_file(mdb);
169 /* Create Jobs File */
170 dbf = make_filename(mdb, DB_JOBS_FILENAME);
171 fd = open(dbf, O_CREAT|O_RDWR, 0600);
175 /* Create Pools File */
176 dbf = make_filename(mdb, DB_POOLS_FILENAME);
177 fd = open(dbf, O_CREAT|O_RDWR, 0600);
181 /* Create Media File */
182 dbf = make_filename(mdb, DB_MEDIA_FILENAME);
183 fd = open(dbf, O_CREAT|O_RDWR, 0600);
187 /* Create JobMedia File */
188 dbf = make_filename(mdb, DB_JOBMEDIA_FILENAME);
189 fd = open(dbf, O_CREAT|O_RDWR, 0600);
193 /* Create Client File */
194 dbf = make_filename(mdb, DB_CLIENT_FILENAME);
195 fd = open(dbf, O_CREAT|O_RDWR, 0600);
199 /* Create FileSet File */
200 dbf = make_filename(mdb, DB_FILESET_FILENAME);
201 fd = open(dbf, O_CREAT|O_RDWR, 0600);
206 Dmsg0(200, "Read control file\n");
208 lseek(mdb->cfd, 0, SEEK_SET); /* seek to begining of control file */
209 if (read(mdb->cfd, &mdb->control, sizeof(mdb->control)) != sizeof(mdb->control)) {
210 Mmsg1(&mdb->errmsg, "Error reading catalog DB control file. ERR=%s\n", strerror(errno));
212 } else if (mdb->control.bdb_version != BDB_VERSION) {
213 Mmsg2(&mdb->errmsg, "Error, catalog DB control file wrong version. \
215 Please reinitialize the working directory.\n",
216 BDB_VERSION, mdb->control.bdb_version);
227 void db_close_database(B_DB *mdb)
231 if (mdb->ref_count == 0) {
233 /* close file descriptors */
245 fclose(mdb->mediafd);
247 if (mdb->jobmediafd) {
248 fclose(mdb->jobmediafd);
251 fclose(mdb->clientfd);
253 if (mdb->filesetfd) {
254 fclose(mdb->filesetfd);
256 pthread_mutex_destroy(&mdb->mutex);
257 free_pool_memory(mdb->errmsg);
258 free_pool_memory(mdb->cmd);
265 void db_escape_string(char *snew, char *old, int len)
270 char *db_strerror(B_DB *mdb)
275 int db_sql_query(B_DB *mdb, char *query, DB_RESULT_HANDLER *result_handler, void *ctx)
281 * Open the Jobs file for reading/writing
283 int bdb_open_jobs_file(B_DB *mdb)
288 dbf = make_filename(mdb, DB_JOBS_FILENAME);
289 mdb->jobfd = fopen(dbf, "r+");
291 Mmsg2(&mdb->errmsg, "Error opening DB Jobs file %s: ERR=%s\n",
292 dbf, strerror(errno));
293 Emsg0(M_FATAL, 0, mdb->errmsg);
303 * Open the JobMedia file for reading/writing
305 int bdb_open_jobmedia_file(B_DB *mdb)
309 if (!mdb->jobmediafd) {
310 dbf = make_filename(mdb, DB_JOBMEDIA_FILENAME);
311 mdb->jobmediafd = fopen(dbf, "r+");
312 if (!mdb->jobmediafd) {
313 Mmsg2(&mdb->errmsg, "Error opening DB JobMedia file %s: ERR=%s\n",
314 dbf, strerror(errno));
315 Emsg0(M_FATAL, 0, mdb->errmsg);
326 * Open the Pools file for reading/writing
328 int bdb_open_pools_file(B_DB *mdb)
333 dbf = make_filename(mdb, DB_POOLS_FILENAME);
334 mdb->poolfd = fopen(dbf, "r+");
336 Mmsg2(&mdb->errmsg, "Error opening DB Pools file %s: ERR=%s\n",
337 dbf, strerror(errno));
338 Emsg0(M_FATAL, 0, mdb->errmsg);
342 Dmsg1(200, "Opened pool file %s\n", dbf);
349 * Open the Client file for reading/writing
351 int bdb_open_client_file(B_DB *mdb)
355 if (!mdb->clientfd) {
356 dbf = make_filename(mdb, DB_CLIENT_FILENAME);
357 mdb->clientfd = fopen(dbf, "r+");
358 if (!mdb->clientfd) {
359 Mmsg2(&mdb->errmsg, "Error opening DB Clients file %s: ERR=%s\n",
360 dbf, strerror(errno));
361 Emsg0(M_FATAL, 0, mdb->errmsg);
371 * Open the FileSet file for reading/writing
373 int bdb_open_fileset_file(B_DB *mdb)
377 if (!mdb->filesetfd) {
378 dbf = make_filename(mdb, DB_CLIENT_FILENAME);
379 mdb->filesetfd = fopen(dbf, "r+");
380 if (!mdb->filesetfd) {
381 Mmsg2(&mdb->errmsg, "Error opening DB FileSet file %s: ERR=%s\n",
382 dbf, strerror(errno));
383 Emsg0(M_FATAL, 0, mdb->errmsg);
395 * Open the Media file for reading/writing
397 int bdb_open_media_file(B_DB *mdb)
402 dbf = make_filename(mdb, DB_MEDIA_FILENAME);
403 mdb->mediafd = fopen(dbf, "r+");
405 Mmsg2(&mdb->errmsg, "Error opening DB Media file %s: ERR=%s\n",
406 dbf, strerror(errno));
415 #endif /* HAVE_BACULA_DB */