]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/cats/bdb.c
Convert to pure GPL v2 license.
[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    Bacula® - The Network Backup Solution
16
17    Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
18
19    The main author of Bacula is Kern Sibbald, with contributions from
20    many others, a complete list can be found in the file AUTHORS.
21    This program is Free Software; you can redistribute it and/or
22    modify it under the terms of version two of the GNU General Public
23    License as published by the Free Software Foundation and included
24    in the file LICENSE.
25
26    This program is distributed in the hope that it will be useful, but
27    WITHOUT ANY WARRANTY; without even the implied warranty of
28    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
29    General Public License for more details.
30
31    You should have received a copy of the GNU General Public License
32    along with this program; if not, write to the Free Software
33    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
34    02110-1301, USA.
35
36    Bacula® is a registered trademark of John Walker.
37    The licensor of Bacula is the Free Software Foundation Europe
38    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
39    Switzerland, email:ftf@fsfeurope.org.
40 */
41
42
43 /* The following is necessary so that we do not include
44  * the dummy external definition of DB.
45  */
46 #define __SQL_C                       /* indicate that this is sql.c */
47
48 #include "bacula.h"
49 #include "cats.h"
50
51 #ifdef HAVE_BACULA_DB
52
53 uint32_t bacula_db_version = 0;
54
55 /* List of open databases */
56 static BQUEUE db_list = {&db_list, &db_list};
57 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
58
59 /* -----------------------------------------------------------------------
60  *
61  *   Bacula specific defines and subroutines
62  *
63  * -----------------------------------------------------------------------
64  */
65
66
67 #define DB_CONTROL_FILENAME  "control.db"
68 #define DB_JOBS_FILENAME     "jobs.db"
69 #define DB_POOLS_FILENAME    "pools.db"
70 #define DB_MEDIA_FILENAME    "media.db"
71 #define DB_JOBMEDIA_FILENAME "jobmedia.db"
72 #define DB_CLIENT_FILENAME   "client.db"
73 #define DB_FILESET_FILENAME  "fileset.db"
74
75 static POOLMEM *make_filename(B_DB *mdb, char *name)
76 {
77    char sep;
78    POOLMEM *dbf;
79
80    dbf = get_pool_memory(PM_FNAME);
81    if (IsPathSeparator(working_directory[strlen(working_directory)-1])) {
82       sep = 0;
83    } else {
84       sep = '/';
85    }
86    Mmsg(dbf, "%s%c%s-%s", working_directory, sep, mdb->db_name, name);
87    return dbf;
88 }
89
90 int bdb_write_control_file(B_DB *mdb)
91 {
92    mdb->control.time = time(NULL);
93    lseek(mdb->cfd, 0, SEEK_SET);
94    if (write(mdb->cfd, &mdb->control, sizeof(mdb->control)) != sizeof(mdb->control)) {
95       Mmsg1(&mdb->errmsg, "Error writing control file. ERR=%s\n", strerror(errno));
96       Emsg0(M_FATAL, 0, mdb->errmsg);
97       return 0;
98    }
99    return 1;
100 }
101
102 /*
103  * Retrieve database type
104  */
105 const char *
106 db_get_type(void)
107 {
108    return "Internal";
109 }
110
111 /*
112  * Initialize database data structure. In principal this should
113  * never have errors, or it is really fatal.
114  */
115 B_DB *
116 db_init_database(JCR *jcr, char const *db_name, char const *db_user, char const *db_password,
117                  char const *db_address, int db_port, char const *db_socket,
118                  int mult_db_connections)
119 {
120    B_DB *mdb;
121    P(mutex);                          /* lock DB queue */
122    /* Look to see if DB already open */
123    for (mdb=NULL; (mdb=(B_DB *)qnext(&db_list, &mdb->bq)); ) {
124       if (strcmp(mdb->db_name, db_name) == 0) {
125          Dmsg2(200, "DB REopen %d %s\n", mdb->ref_count, db_name);
126          mdb->ref_count++;
127          V(mutex);
128          return mdb;                  /* already open */
129       }
130    }
131
132    Dmsg0(200, "db_open first time\n");
133    mdb = (B_DB *)malloc(sizeof(B_DB));
134    memset(mdb, 0, sizeof(B_DB));
135    Dmsg0(200, "DB struct init\n");
136    mdb->db_name = bstrdup(db_name);
137    mdb->errmsg = get_pool_memory(PM_EMSG);
138    *mdb->errmsg = 0;
139    mdb->cmd = get_pool_memory(PM_EMSG);  /* command buffer */
140    mdb->ref_count = 1;
141    mdb->cached_path = get_pool_memory(PM_FNAME);
142    mdb->cached_path_id = 0;
143    qinsert(&db_list, &mdb->bq);       /* put db in list */
144    Dmsg0(200, "Done db_open_database()\n");
145    mdb->cfd = -1;
146    V(mutex);
147    Jmsg(jcr, M_WARNING, 0, _("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"));
148    Jmsg(jcr, M_WARNING, 0, _("WARNING!!!! The Internal Database is NOT OPERATIONAL!\n"));
149    Jmsg(jcr, M_WARNING, 0, _("You should use SQLite, PostgreSQL, or MySQL\n"));
150
151    return mdb;
152 }
153
154 /*
155  * Now actually open the database.  This can generate errors,
156  * which are returned in the errmsg
157  */
158 int
159 db_open_database(JCR *jcr, B_DB *mdb)
160 {
161    char *dbf;
162    int fd, badctl;
163    off_t filend;
164    int errstat;
165
166    Dmsg1(200, "db_open_database() %s\n", mdb->db_name);
167
168    P(mutex);
169
170    if ((errstat=rwl_init(&mdb->lock)) != 0) {
171       Mmsg1(&mdb->errmsg, _("Unable to initialize DB lock. ERR=%s\n"), strerror(errstat));
172       V(mutex);
173       return 0;
174    }
175
176    Dmsg0(200, "make_filename\n");
177    dbf = make_filename(mdb, DB_CONTROL_FILENAME);
178    mdb->cfd = open(dbf, O_CREAT|O_RDWR, 0600);
179    free_memory(dbf);
180    if (mdb->cfd < 0) {
181       Mmsg2(&mdb->errmsg, _("Unable to open Catalog DB control file %s: ERR=%s\n"),
182          dbf, strerror(errno));
183       V(mutex);
184       return 0;
185    }
186    Dmsg0(200, "DB open\n");
187    /* See if the file was previously written */
188    filend = lseek(mdb->cfd, 0, SEEK_END);
189    if (filend == 0) {                 /* No, initialize everything */
190       Dmsg0(200, "Init DB files\n");
191       memset(&mdb->control, 0, sizeof(mdb->control));
192       mdb->control.bdb_version = BDB_VERSION;
193       bdb_write_control_file(mdb);
194
195       /* Create Jobs File */
196       dbf = make_filename(mdb, DB_JOBS_FILENAME);
197       fd = open(dbf, O_CREAT|O_RDWR, 0600);
198       free_memory(dbf);
199       close(fd);
200
201       /* Create Pools File */
202       dbf = make_filename(mdb, DB_POOLS_FILENAME);
203       fd = open(dbf, O_CREAT|O_RDWR, 0600);
204       free_memory(dbf);
205       close(fd);
206
207       /* Create Media File */
208       dbf = make_filename(mdb, DB_MEDIA_FILENAME);
209       fd = open(dbf, O_CREAT|O_RDWR, 0600);
210       free_memory(dbf);
211       close(fd);
212
213       /* Create JobMedia File */
214       dbf = make_filename(mdb, DB_JOBMEDIA_FILENAME);
215       fd = open(dbf, O_CREAT|O_RDWR, 0600);
216       free_memory(dbf);
217       close(fd);
218
219       /* Create Client File */
220       dbf = make_filename(mdb, DB_CLIENT_FILENAME);
221       fd = open(dbf, O_CREAT|O_RDWR, 0600);
222       free_memory(dbf);
223       close(fd);
224
225       /* Create FileSet File */
226       dbf = make_filename(mdb, DB_FILESET_FILENAME);
227       fd = open(dbf, O_CREAT|O_RDWR, 0600);
228       free_memory(dbf);
229       close(fd);
230    }
231
232    Dmsg0(200, "Read control file\n");
233    badctl = 0;
234    lseek(mdb->cfd, 0, SEEK_SET);      /* seek to begining of control file */
235    if (read(mdb->cfd, &mdb->control, sizeof(mdb->control)) != sizeof(mdb->control)) {
236       Mmsg1(&mdb->errmsg, _("Error reading catalog DB control file. ERR=%s\n"), strerror(errno));
237       badctl = 1;
238    } else if (mdb->control.bdb_version != BDB_VERSION) {
239       Mmsg2(&mdb->errmsg, _("Error, catalog DB control file wrong version. "
240 "Wanted %d, got %d\n"
241 "Please reinitialize the working directory.\n"),
242          BDB_VERSION, mdb->control.bdb_version);
243       badctl = 1;
244    }
245    bacula_db_version = mdb->control.bdb_version;
246    if (badctl) {
247       V(mutex);
248       return 0;
249    }
250    V(mutex);
251    return 1;
252 }
253
254 void db_close_database(JCR *jcr, B_DB *mdb)
255 {
256    P(mutex);
257    mdb->ref_count--;
258    if (mdb->ref_count == 0) {
259       qdchain(&mdb->bq);
260       /*  close file descriptors */
261       if (mdb->cfd >= 0) {
262          close(mdb->cfd);
263       }
264       free(mdb->db_name);
265       if (mdb->jobfd) {
266          fclose(mdb->jobfd);
267       }
268       if (mdb->poolfd) {
269          fclose(mdb->poolfd);
270       }
271       if (mdb->mediafd) {
272          fclose(mdb->mediafd);
273       }
274       if (mdb->jobmediafd) {
275          fclose(mdb->jobmediafd);
276       }
277       if (mdb->clientfd) {
278          fclose(mdb->clientfd);
279       }
280       if (mdb->filesetfd) {
281          fclose(mdb->filesetfd);
282       }
283       rwl_destroy(&mdb->lock);
284       free_pool_memory(mdb->errmsg);
285       free_pool_memory(mdb->cmd);
286       free_pool_memory(mdb->cached_path);
287       free(mdb);
288    }
289    V(mutex);
290 }
291
292 void db_thread_cleanup()
293 { }
294
295
296 void db_escape_string(char *snew, char *old, int len)
297 {
298    memset(snew, 0, len);
299    bstrncpy(snew, old, len);
300 }
301
302 char *db_strerror(B_DB *mdb)
303 {
304    return mdb->errmsg;
305 }
306
307 int db_sql_query(B_DB *mdb, char const *query, DB_RESULT_HANDLER *result_handler, void *ctx)
308 {
309    return 1;
310 }
311
312 /*
313  * Open the Jobs file for reading/writing
314  */
315 int bdb_open_jobs_file(B_DB *mdb)
316 {
317    char *dbf;
318
319    if (!mdb->jobfd) {
320       dbf = make_filename(mdb, DB_JOBS_FILENAME);
321       mdb->jobfd = fopen(dbf, "r+b");
322       if (!mdb->jobfd) {
323          Mmsg2(&mdb->errmsg, "Error opening DB Jobs file %s: ERR=%s\n",
324             dbf, strerror(errno));
325          Emsg0(M_FATAL, 0, mdb->errmsg);
326          free_memory(dbf);
327          return 0;
328       }
329       free_memory(dbf);
330    }
331    return 1;
332 }
333
334 /*
335  * Open the JobMedia file for reading/writing
336  */
337 int bdb_open_jobmedia_file(B_DB *mdb)
338 {
339    char *dbf;
340
341    if (!mdb->jobmediafd) {
342       dbf = make_filename(mdb, DB_JOBMEDIA_FILENAME);
343       mdb->jobmediafd = fopen(dbf, "r+b");
344       if (!mdb->jobmediafd) {
345          Mmsg2(&mdb->errmsg, "Error opening DB JobMedia file %s: ERR=%s\n",
346             dbf, strerror(errno));
347          Emsg0(M_FATAL, 0, mdb->errmsg);
348          free_memory(dbf);
349          return 0;
350       }
351       free_memory(dbf);
352    }
353    return 1;
354 }
355
356
357 /*
358  * Open the Pools file for reading/writing
359  */
360 int bdb_open_pools_file(B_DB *mdb)
361 {
362    char *dbf;
363
364    if (!mdb->poolfd) {
365       dbf = make_filename(mdb, DB_POOLS_FILENAME);
366       mdb->poolfd = fopen(dbf, "r+b");
367       if (!mdb->poolfd) {
368          Mmsg2(&mdb->errmsg, "Error opening DB Pools file %s: ERR=%s\n",
369             dbf, strerror(errno));
370          Emsg0(M_FATAL, 0, mdb->errmsg);
371          free_memory(dbf);
372          return 0;
373       }
374       Dmsg1(200, "Opened pool file %s\n", dbf);
375       free_memory(dbf);
376    }
377    return 1;
378 }
379
380 /*
381  * Open the Client file for reading/writing
382  */
383 int bdb_open_client_file(B_DB *mdb)
384 {
385    char *dbf;
386
387    if (!mdb->clientfd) {
388       dbf = make_filename(mdb, DB_CLIENT_FILENAME);
389       mdb->clientfd = fopen(dbf, "r+b");
390       if (!mdb->clientfd) {
391          Mmsg2(&mdb->errmsg, "Error opening DB Clients file %s: ERR=%s\n",
392             dbf, strerror(errno));
393          Emsg0(M_FATAL, 0, mdb->errmsg);
394          free_memory(dbf);
395          return 0;
396       }
397       free_memory(dbf);
398    }
399    return 1;
400 }
401
402 /*
403  * Open the FileSet file for reading/writing
404  */
405 int bdb_open_fileset_file(B_DB *mdb)
406 {
407    char *dbf;
408
409    if (!mdb->filesetfd) {
410       dbf = make_filename(mdb, DB_CLIENT_FILENAME);
411       mdb->filesetfd = fopen(dbf, "r+b");
412       if (!mdb->filesetfd) {
413          Mmsg2(&mdb->errmsg, "Error opening DB FileSet file %s: ERR=%s\n",
414             dbf, strerror(errno));
415          Emsg0(M_FATAL, 0, mdb->errmsg);
416          free_memory(dbf);
417          return 0;
418       }
419       free_memory(dbf);
420    }
421    return 1;
422 }
423
424
425
426 /*
427  * Open the Media file for reading/writing
428  */
429 int bdb_open_media_file(B_DB *mdb)
430 {
431    char *dbf;
432
433    if (!mdb->mediafd) {
434       dbf = make_filename(mdb, DB_MEDIA_FILENAME);
435       mdb->mediafd = fopen(dbf, "r+b");
436       if (!mdb->mediafd) {
437          Mmsg2(&mdb->errmsg, "Error opening DB Media file %s: ERR=%s\n",
438             dbf, strerror(errno));
439          free_memory(dbf);
440          return 0;
441       }
442       free_memory(dbf);
443    }
444    return 1;
445 }
446
447
448 void _db_lock(const char *file, int line, B_DB *mdb)
449 {
450    int errstat;
451    if ((errstat=rwl_writelock(&mdb->lock)) != 0) {
452       e_msg(file, line, M_ABORT, 0, "rwl_writelock failure. ERR=%s\n",
453            strerror(errstat));
454    }
455 }
456
457 void _db_unlock(const char *file, int line, B_DB *mdb)
458 {
459    int errstat;
460    if ((errstat=rwl_writeunlock(&mdb->lock)) != 0) {
461       e_msg(file, line, M_ABORT, 0, "rwl_writeunlock failure. ERR=%s\n",
462            strerror(errstat));
463    }
464 }
465
466 /*
467  * Start a transaction. This groups inserts and makes things
468  *  much more efficient. Usually started when inserting
469  *  file attributes.
470  */
471 void db_start_transaction(JCR *jcr, B_DB *mdb)
472 {
473 }
474
475 void db_end_transaction(JCR *jcr, B_DB *mdb)
476 {
477 }
478
479 bool db_update_storage_record(JCR *jcr, B_DB *mdb, STORAGE_DBR *sr)
480 { return true; }
481
482 void
483 db_list_pool_records(JCR *jcr, B_DB *mdb, POOL_DBR *pdbr, 
484                      DB_LIST_HANDLER *sendit, void *ctx, e_list_type type)
485 { }
486
487 int db_int64_handler(void *ctx, int num_fields, char **row)
488 { return 0; }
489
490
491 #endif /* HAVE_BACULA_DB */