]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/cats/bdb.c
First cut AutoPrune
[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  *    Version $Id$
12  *
13  */
14
15
16 /*
17    Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
18
19    This program is free software; you can redistribute it and/or
20    modify it under the terms of the GNU General Public License as
21    published by the Free Software Foundation; either version 2 of
22    the License, or (at your option) any later version.
23
24    This program is distributed in the hope that it will be useful,
25    but WITHOUT ANY WARRANTY; without even the implied warranty of
26    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27    General Public License for more details.
28
29    You should have received a copy of the GNU General Public
30    License along with this program; if not, write to the Free
31    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
32    MA 02111-1307, USA.
33
34  */
35
36
37 /* The following is necessary so that we do not include
38  * the dummy external definition of DB.
39  */
40 #define __SQL_C                       /* indicate that this is sql.c */
41
42 #include "bacula.h"
43 #include "cats.h"
44
45 #ifdef HAVE_BACULA_DB
46
47 /* Forward referenced functions */
48
49 extern char *working_directory;
50
51 /* List of open databases */
52 static BQUEUE db_list = {&db_list, &db_list};
53 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
54
55 /* -----------------------------------------------------------------------
56  *
57  *   Bacula specific defines and subroutines
58  *
59  * -----------------------------------------------------------------------
60  */
61
62
63 #define DB_CONTROL_FILENAME  "control.db"
64 #define DB_JOBS_FILENAME     "jobs.db"
65 #define DB_POOLS_FILENAME    "pools.db"
66 #define DB_MEDIA_FILENAME    "media.db"
67 #define DB_JOBMEDIA_FILENAME "jobmedia.db"
68 #define DB_CLIENT_FILENAME   "client.db"
69 #define DB_FILESET_FILENAME  "fileset.db"
70
71 static char *make_filename(B_DB *mdb, char *name)
72 {
73    char *dbf, sep;
74
75    dbf = (char *) get_pool_memory(PM_FNAME);
76    if (working_directory[strlen(working_directory)-1] == '/') {
77       sep = 0;
78    } else {
79       sep = '/'; 
80    }
81    Mmsg(&dbf, "%s%c%s-%s", working_directory, sep, mdb->db_name, name);
82    return dbf;
83 }
84
85 int bdb_write_control_file(B_DB *mdb)
86 {
87    mdb->control.time = time(NULL);
88    lseek(mdb->cfd, 0, SEEK_SET);
89    if (write(mdb->cfd, &mdb->control, sizeof(mdb->control)) != sizeof(mdb->control)) {
90       Mmsg1(&mdb->errmsg, "Error writing control file. ERR=%s\n", strerror(errno));
91       Emsg0(M_FATAL, 0, mdb->errmsg);
92       return 0;
93    }
94    return 1;
95 }
96
97 /*
98  * Initialize database data structure. In principal this should
99  * never have errors, or it is really fatal.
100  */
101 B_DB *
102 db_init_database(char *db_name, char *db_user, char *db_password)
103 {
104    B_DB *mdb;
105    P(mutex);                          /* lock DB queue */
106    /* Look to see if DB already open */
107    for (mdb=NULL; (mdb=(B_DB *)qnext(&db_list, &mdb->bq)); ) {
108       if (strcmp(mdb->db_name, db_name) == 0) {
109          Dmsg2(200, "DB REopen %d %s\n", mdb->ref_count, db_name);
110          mdb->ref_count++;
111          V(mutex);
112          return mdb;                  /* already open */
113       }
114    }
115    Dmsg0(200, "db_open first time\n");
116    mdb = (B_DB *) malloc(sizeof(B_DB));
117    memset(mdb, 0, sizeof(B_DB));
118    Dmsg0(200, "DB struct init\n");
119    mdb->db_name = bstrdup(db_name);
120    mdb->errmsg = (char *) get_pool_memory(PM_EMSG);
121    *mdb->errmsg = 0;
122    mdb->cmd = (char *) get_pool_memory(PM_EMSG);  /* command buffer */
123    mdb->ref_count = 1;
124    qinsert(&db_list, &mdb->bq);       /* put db in list */
125    Dmsg0(200, "Done db_open_database()\n");
126    mdb->cfd = -1;
127    V(mutex);
128    return mdb;
129 }
130
131 /*
132  * Now actually open the database.  This can generate errors,
133  * which are returned in the errmsg
134  */
135 int
136 db_open_database(B_DB *mdb)
137 {
138    char *dbf;
139    int fd, badctl;
140    int errstat;
141    off_t filend;
142
143    Dmsg1(200, "db_open_database() %s\n", mdb->db_name);
144
145    P(mutex);
146    if ((errstat = pthread_mutex_init(&(mdb->mutex), NULL)) != 0) {
147       Mmsg1(&mdb->errmsg, "Unable to initialize DB mutex. ERR=%s\n", strerror(errstat));
148       V(mutex);
149       return 0;
150    }
151    P(mdb->mutex);                     /* test it once */
152    V(mdb->mutex);
153
154    Dmsg0(200, "make_filename\n");
155    dbf = make_filename(mdb, DB_CONTROL_FILENAME);
156    mdb->cfd = open(dbf, O_CREAT|O_RDWR, 0600); 
157    free_memory(dbf);
158    if (mdb->cfd < 0) {
159       Mmsg2(&mdb->errmsg, "Unable to open Catalog DB control file %s: ERR=%s\n", 
160          dbf, strerror(errno));
161       V(mutex);
162       return 0;
163    }
164    Dmsg0(200, "DB open\n");
165    /* See if the file was previously written */
166    filend = lseek(mdb->cfd, 0, SEEK_END);
167    if (filend == 0) {                 /* No, initialize everything */
168       Dmsg0(200, "Init DB files\n");
169       memset(&mdb->control, 0, sizeof(mdb->control));
170       mdb->control.bdb_version = BDB_VERSION;
171       bdb_write_control_file(mdb);
172
173       /* Create Jobs File */
174       dbf = make_filename(mdb, DB_JOBS_FILENAME);
175       fd = open(dbf, O_CREAT|O_RDWR, 0600);
176       free_memory(dbf);
177       close(fd);
178
179       /* Create Pools File */
180       dbf = make_filename(mdb, DB_POOLS_FILENAME);
181       fd = open(dbf, O_CREAT|O_RDWR, 0600);
182       free_memory(dbf);
183       close(fd);
184
185       /* Create Media File */
186       dbf = make_filename(mdb, DB_MEDIA_FILENAME);
187       fd = open(dbf, O_CREAT|O_RDWR, 0600);
188       free_memory(dbf);
189       close(fd);
190
191       /* Create JobMedia File */
192       dbf = make_filename(mdb, DB_JOBMEDIA_FILENAME);
193       fd = open(dbf, O_CREAT|O_RDWR, 0600);
194       free_memory(dbf);
195       close(fd);
196
197       /* Create Client File */
198       dbf = make_filename(mdb, DB_CLIENT_FILENAME);
199       fd = open(dbf, O_CREAT|O_RDWR, 0600);
200       free_memory(dbf);
201       close(fd);
202
203       /* Create FileSet File */
204       dbf = make_filename(mdb, DB_FILESET_FILENAME);
205       fd = open(dbf, O_CREAT|O_RDWR, 0600);
206       free_memory(dbf);
207       close(fd);
208    }
209
210    Dmsg0(200, "Read control file\n");
211    badctl = 0;
212    lseek(mdb->cfd, 0, SEEK_SET);      /* seek to begining of control file */
213    if (read(mdb->cfd, &mdb->control, sizeof(mdb->control)) != sizeof(mdb->control)) {
214       Mmsg1(&mdb->errmsg, "Error reading catalog DB control file. ERR=%s\n", strerror(errno));
215       badctl = 1;
216    } else if (mdb->control.bdb_version != BDB_VERSION) {
217       Mmsg2(&mdb->errmsg, "Error, catalog DB control file wrong version. \
218 Wanted %d, got %d\n\
219 Please reinitialize the working directory.\n", 
220          BDB_VERSION, mdb->control.bdb_version);
221       badctl = 1;
222    }
223    if (badctl) {
224       V(mutex);
225       return 0;
226    }
227    V(mutex);
228    return 1;
229 }
230
231 void db_close_database(B_DB *mdb)            
232 {
233    P(mutex);
234    mdb->ref_count--;
235    if (mdb->ref_count == 0) {
236       qdchain(&mdb->bq);
237       /*  close file descriptors */
238       if (mdb->cfd >= 0) {
239          close(mdb->cfd);
240       }
241       free(mdb->db_name);
242       if (mdb->jobfd) {
243          fclose(mdb->jobfd);
244       }
245       if (mdb->poolfd) {
246          fclose(mdb->poolfd);
247       }
248       if (mdb->mediafd) {
249          fclose(mdb->mediafd);
250       }
251       if (mdb->jobmediafd) {
252          fclose(mdb->jobmediafd);
253       }
254       if (mdb->clientfd) {
255          fclose(mdb->clientfd);
256       }
257       if (mdb->filesetfd) {
258          fclose(mdb->filesetfd);
259       }
260       pthread_mutex_destroy(&mdb->mutex);
261       free_pool_memory(mdb->errmsg);
262       free_pool_memory(mdb->cmd);
263       free(mdb);
264    }
265    V(mutex);
266 }
267
268
269 void db_escape_string(char *snew, char *old, int len)
270 {
271    strcpy(snew, old);
272 }
273
274 char *db_strerror(B_DB *mdb)
275 {
276    return mdb->errmsg;
277 }
278
279 int db_sql_query(B_DB *mdb, char *query, DB_RESULT_HANDLER *result_handler, void *ctx)
280 {
281    return 1;
282 }
283
284 /*
285  * Open the Jobs file for reading/writing
286  */
287 int bdb_open_jobs_file(B_DB *mdb)
288 {
289    char *dbf;
290
291    if (!mdb->jobfd) {  
292       dbf = make_filename(mdb, DB_JOBS_FILENAME);
293       mdb->jobfd = fopen(dbf, "r+");
294       if (!mdb->jobfd) {
295          Mmsg2(&mdb->errmsg, "Error opening DB Jobs file %s: ERR=%s\n", 
296             dbf, strerror(errno));
297          Emsg0(M_FATAL, 0, mdb->errmsg);
298          free_memory(dbf);
299          return 0;
300       }
301       free_memory(dbf);
302    }
303    return 1;
304 }
305
306 /*
307  * Open the JobMedia file for reading/writing
308  */
309 int bdb_open_jobmedia_file(B_DB *mdb)
310 {
311    char *dbf;
312
313    if (!mdb->jobmediafd) {  
314       dbf = make_filename(mdb, DB_JOBMEDIA_FILENAME);
315       mdb->jobmediafd = fopen(dbf, "r+");
316       if (!mdb->jobmediafd) {
317          Mmsg2(&mdb->errmsg, "Error opening DB JobMedia file %s: ERR=%s\n", 
318             dbf, strerror(errno));
319          Emsg0(M_FATAL, 0, mdb->errmsg);
320          free_memory(dbf);
321          return 0;
322       }
323       free_memory(dbf);
324    }
325    return 1;
326 }
327
328
329 /*
330  * Open the Pools file for reading/writing
331  */
332 int bdb_open_pools_file(B_DB *mdb)
333 {
334    char *dbf;
335
336    if (!mdb->poolfd) {  
337       dbf = make_filename(mdb, DB_POOLS_FILENAME);
338       mdb->poolfd = fopen(dbf, "r+");
339       if (!mdb->poolfd) {
340          Mmsg2(&mdb->errmsg, "Error opening DB Pools file %s: ERR=%s\n", 
341             dbf, strerror(errno));
342          Emsg0(M_FATAL, 0, mdb->errmsg);
343          free_memory(dbf);
344          return 0;
345       }
346       Dmsg1(200, "Opened pool file %s\n", dbf);
347       free_memory(dbf);
348    }
349    return 1;
350 }
351
352 /*
353  * Open the Client file for reading/writing
354  */
355 int bdb_open_client_file(B_DB *mdb)
356 {
357    char *dbf;
358
359    if (!mdb->clientfd) {  
360       dbf = make_filename(mdb, DB_CLIENT_FILENAME);
361       mdb->clientfd = fopen(dbf, "r+");
362       if (!mdb->clientfd) {
363          Mmsg2(&mdb->errmsg, "Error opening DB Clients file %s: ERR=%s\n", 
364             dbf, strerror(errno));
365          Emsg0(M_FATAL, 0, mdb->errmsg);
366          free_memory(dbf);
367          return 0;
368       }
369       free_memory(dbf);
370    }
371    return 1;
372 }
373
374 /*
375  * Open the FileSet file for reading/writing
376  */
377 int bdb_open_fileset_file(B_DB *mdb)
378 {
379    char *dbf;
380
381    if (!mdb->filesetfd) {  
382       dbf = make_filename(mdb, DB_CLIENT_FILENAME);
383       mdb->filesetfd = fopen(dbf, "r+");
384       if (!mdb->filesetfd) {
385          Mmsg2(&mdb->errmsg, "Error opening DB FileSet file %s: ERR=%s\n", 
386             dbf, strerror(errno));
387          Emsg0(M_FATAL, 0, mdb->errmsg);
388          free_memory(dbf);
389          return 0;
390       }
391       free_memory(dbf);
392    }
393    return 1;
394 }
395
396
397
398 /*
399  * Open the Media file for reading/writing
400  */
401 int bdb_open_media_file(B_DB *mdb)
402 {
403    char *dbf;
404
405    if (!mdb->mediafd) {  
406       dbf = make_filename(mdb, DB_MEDIA_FILENAME);
407       mdb->mediafd = fopen(dbf, "r+");
408       if (!mdb->mediafd) {
409          Mmsg2(&mdb->errmsg, "Error opening DB Media file %s: ERR=%s\n", 
410             dbf, strerror(errno));
411          free_memory(dbf);
412          return 0;
413       }
414       free_memory(dbf);
415    }
416    return 1;
417 }
418
419 #endif /* HAVE_BACULA_DB */