]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/cats/bdb.c
95ebf715fed3e410bb649a541b3cc47539468577
[bacula/bacula] / bacula / src / cats / bdb.c
1 /*
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
7  *  system.
8  *   
9  *    Kern Sibbald, January MMI 
10  */
11
12 /*
13    Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
14
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.
19
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.
24
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,
28    MA 02111-1307, USA.
29
30  */
31
32
33 /* The following is necessary so that we do not include
34  * the dummy external definition of DB.
35  */
36 #define __SQL_C                       /* indicate that this is sql.c */
37
38 #include "bacula.h"
39 #include "cats.h"
40
41 #ifdef HAVE_BACULA_DB
42
43 /* Forward referenced functions */
44
45 extern char *working_directory;
46
47 /* List of open databases */
48 static BQUEUE db_list = {&db_list, &db_list};
49 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
50
51 /* -----------------------------------------------------------------------
52  *
53  *   Bacula specific defines and subroutines
54  *
55  * -----------------------------------------------------------------------
56  */
57
58
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"
66
67 static char *make_filename(B_DB *mdb, char *name)
68 {
69    char *dbf, sep;
70
71    dbf = (char *) get_pool_memory(PM_FNAME);
72    if (working_directory[strlen(working_directory)-1] == '/') {
73       sep = 0;
74    } else {
75       sep = '/'; 
76    }
77    Mmsg(&dbf, "%s%c%s-%s", working_directory, sep, mdb->db_name, name);
78    return dbf;
79 }
80
81 int bdb_write_control_file(B_DB *mdb)
82 {
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);
88       return 0;
89    }
90    return 1;
91 }
92
93 /*
94  * Initialize database data structure. In principal this should
95  * never have errors, or it is really fatal.
96  */
97 B_DB *
98 db_init_database(char *db_name, char *db_user, char *db_password)
99 {
100    B_DB *mdb;
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);
106          mdb->ref_count++;
107          V(mutex);
108          return mdb;                  /* already open */
109       }
110    }
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);
117    *mdb->errmsg = 0;
118    mdb->cmd = (char *) get_pool_memory(PM_EMSG);  /* command buffer */
119    mdb->ref_count = 1;
120    qinsert(&db_list, &mdb->bq);       /* put db in list */
121    Dmsg0(200, "Done db_open_database()\n");
122    mdb->cfd = -1;
123    V(mutex);
124    return mdb;
125 }
126
127 /*
128  * Now actually open the database.  This can generate errors,
129  * which are returned in the errmsg
130  */
131 int
132 db_open_database(B_DB *mdb)
133 {
134    char *dbf;
135    int fd, badctl;
136    int errstat;
137    off_t filend;
138
139    Dmsg1(200, "db_open_database() %s\n", mdb->db_name);
140
141    P(mutex);
142    if ((errstat = pthread_mutex_init(&(mdb->mutex), NULL)) != 0) {
143       Mmsg1(&mdb->errmsg, "Unable to initialize DB mutex. ERR=%s\n", strerror(errstat));
144       V(mutex);
145       return 0;
146    }
147    P(mdb->mutex);                     /* test it once */
148    V(mdb->mutex);
149
150    Dmsg0(200, "make_filename\n");
151    dbf = make_filename(mdb, DB_CONTROL_FILENAME);
152    mdb->cfd = open(dbf, O_CREAT|O_RDWR, 0600); 
153    free_memory(dbf);
154    if (mdb->cfd < 0) {
155       Mmsg2(&mdb->errmsg, "Unable to open Catalog DB control file %s: ERR=%s\n", 
156          dbf, strerror(errno));
157       V(mutex);
158       return 0;
159    }
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);
168
169       /* Create Jobs File */
170       dbf = make_filename(mdb, DB_JOBS_FILENAME);
171       fd = open(dbf, O_CREAT|O_RDWR, 0600);
172       free_memory(dbf);
173       close(fd);
174
175       /* Create Pools File */
176       dbf = make_filename(mdb, DB_POOLS_FILENAME);
177       fd = open(dbf, O_CREAT|O_RDWR, 0600);
178       free_memory(dbf);
179       close(fd);
180
181       /* Create Media File */
182       dbf = make_filename(mdb, DB_MEDIA_FILENAME);
183       fd = open(dbf, O_CREAT|O_RDWR, 0600);
184       free_memory(dbf);
185       close(fd);
186
187       /* Create JobMedia File */
188       dbf = make_filename(mdb, DB_JOBMEDIA_FILENAME);
189       fd = open(dbf, O_CREAT|O_RDWR, 0600);
190       free_memory(dbf);
191       close(fd);
192
193       /* Create Client File */
194       dbf = make_filename(mdb, DB_CLIENT_FILENAME);
195       fd = open(dbf, O_CREAT|O_RDWR, 0600);
196       free_memory(dbf);
197       close(fd);
198
199       /* Create FileSet File */
200       dbf = make_filename(mdb, DB_FILESET_FILENAME);
201       fd = open(dbf, O_CREAT|O_RDWR, 0600);
202       free_memory(dbf);
203       close(fd);
204    }
205
206    Dmsg0(200, "Read control file\n");
207    badctl = 0;
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));
211       badctl = 1;
212    } else if (mdb->control.bdb_version != BDB_VERSION) {
213       Mmsg2(&mdb->errmsg, "Error, catalog DB control file wrong version. \
214 Wanted %d, got %d\n\
215 Please reinitialize the working directory.\n", 
216          BDB_VERSION, mdb->control.bdb_version);
217       badctl = 1;
218    }
219    if (badctl) {
220       V(mutex);
221       return 0;
222    }
223    V(mutex);
224    return 1;
225 }
226
227 void db_close_database(B_DB *mdb)            
228 {
229    P(mutex);
230    mdb->ref_count--;
231    if (mdb->ref_count == 0) {
232       qdchain(&mdb->bq);
233       /*  close file descriptors */
234       if (mdb->cfd >= 0) {
235          close(mdb->cfd);
236       }
237       free(mdb->db_name);
238       if (mdb->jobfd) {
239          fclose(mdb->jobfd);
240       }
241       if (mdb->poolfd) {
242          fclose(mdb->poolfd);
243       }
244       if (mdb->mediafd) {
245          fclose(mdb->mediafd);
246       }
247       if (mdb->jobmediafd) {
248          fclose(mdb->jobmediafd);
249       }
250       if (mdb->clientfd) {
251          fclose(mdb->clientfd);
252       }
253       if (mdb->filesetfd) {
254          fclose(mdb->filesetfd);
255       }
256       pthread_mutex_destroy(&mdb->mutex);
257       free_pool_memory(mdb->errmsg);
258       free_pool_memory(mdb->cmd);
259       free(mdb);
260    }
261    V(mutex);
262 }
263
264
265 void db_escape_string(char *snew, char *old, int len)
266 {
267    strcpy(snew, old);
268 }
269
270 char *db_strerror(B_DB *mdb)
271 {
272    return mdb->errmsg;
273 }
274
275 int db_sql_query(B_DB *mdb, char *query, DB_RESULT_HANDLER *result_handler, void *ctx)
276 {
277    return 1;
278 }
279
280 /*
281  * Open the Jobs file for reading/writing
282  */
283 int bdb_open_jobs_file(B_DB *mdb)
284 {
285    char *dbf;
286
287    if (!mdb->jobfd) {  
288       dbf = make_filename(mdb, DB_JOBS_FILENAME);
289       mdb->jobfd = fopen(dbf, "r+");
290       if (!mdb->jobfd) {
291          Mmsg2(&mdb->errmsg, "Error opening DB Jobs file %s: ERR=%s\n", 
292             dbf, strerror(errno));
293          Emsg0(M_FATAL, 0, mdb->errmsg);
294          free_memory(dbf);
295          return 0;
296       }
297       free_memory(dbf);
298    }
299    return 1;
300 }
301
302 /*
303  * Open the JobMedia file for reading/writing
304  */
305 int bdb_open_jobmedia_file(B_DB *mdb)
306 {
307    char *dbf;
308
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);
316          free_memory(dbf);
317          return 0;
318       }
319       free_memory(dbf);
320    }
321    return 1;
322 }
323
324
325 /*
326  * Open the Pools file for reading/writing
327  */
328 int bdb_open_pools_file(B_DB *mdb)
329 {
330    char *dbf;
331
332    if (!mdb->poolfd) {  
333       dbf = make_filename(mdb, DB_POOLS_FILENAME);
334       mdb->poolfd = fopen(dbf, "r+");
335       if (!mdb->poolfd) {
336          Mmsg2(&mdb->errmsg, "Error opening DB Pools file %s: ERR=%s\n", 
337             dbf, strerror(errno));
338          Emsg0(M_FATAL, 0, mdb->errmsg);
339          free_memory(dbf);
340          return 0;
341       }
342       Dmsg1(200, "Opened pool file %s\n", dbf);
343       free_memory(dbf);
344    }
345    return 1;
346 }
347
348 /*
349  * Open the Client file for reading/writing
350  */
351 int bdb_open_client_file(B_DB *mdb)
352 {
353    char *dbf;
354
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);
362          free_memory(dbf);
363          return 0;
364       }
365       free_memory(dbf);
366    }
367    return 1;
368 }
369
370 /*
371  * Open the FileSet file for reading/writing
372  */
373 int bdb_open_fileset_file(B_DB *mdb)
374 {
375    char *dbf;
376
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);
384          free_memory(dbf);
385          return 0;
386       }
387       free_memory(dbf);
388    }
389    return 1;
390 }
391
392
393
394 /*
395  * Open the Media file for reading/writing
396  */
397 int bdb_open_media_file(B_DB *mdb)
398 {
399    char *dbf;
400
401    if (!mdb->mediafd) {  
402       dbf = make_filename(mdb, DB_MEDIA_FILENAME);
403       mdb->mediafd = fopen(dbf, "r+");
404       if (!mdb->mediafd) {
405          Mmsg2(&mdb->errmsg, "Error opening DB Media file %s: ERR=%s\n", 
406             dbf, strerror(errno));
407          free_memory(dbf);
408          return 0;
409       }
410       free_memory(dbf);
411    }
412    return 1;
413 }
414
415 #endif /* HAVE_BACULA_DB */