1 /* Database access routines
2 Copyright (C) 1996, William M. Perry
4 This file is part of XEmacs.
6 XEmacs is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 You should have received a copy of the GNU General Public License
17 along with XEmacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 /* Synched up with: Not in FSF. */
23 /* Written by Bill Perry */
24 /* Substantially rewritten by Martin Buchholz */
25 /* db 2.x support added by Andreas Jaeger */
34 #error HAVE_DATABASE not defined!!
37 #include "database.h" /* Our include file */
39 #ifdef HAVE_BERKELEY_DB
40 /* Work around Berkeley DB's use of int types which are defined
41 slightly differently in the not quite yet standard <inttypes.h>.
42 See db.h for details of why we're resorting to this... */
43 /* glibc 2.1 doesn't have this problem with DB 2.x */
44 #if !(defined __GLIBC__ && __GLIBC_MINOR__ >= 1)
45 #ifdef HAVE_INTTYPES_H
46 #define __BIT_TYPES_DEFINED__
49 typedef uint8_t u_int8_t;
50 typedef uint16_t u_int16_t;
51 typedef uint32_t u_int32_t;
52 #ifdef WE_DONT_NEED_QUADS
53 typedef uint64_t u_int64_t;
55 #endif /* WE_DONT_NEED_QUADS */
56 #endif /* HAVE_INTTYPES_H */
57 #endif /* !(defined __GLIBC__ && __GLIBC_MINOR__ >= 1) */
58 /* Berkeley DB wants __STDC__ to be defined; else if does `#define const' */
59 #if ! defined (__STDC__) && ! defined(__cplusplus)
62 #include DB_H_FILE /* Berkeley db's header file */
63 #ifndef DB_VERSION_MAJOR
64 # define DB_VERSION_MAJOR 1
65 #endif /* DB_VERSION_MAJOR */
66 #ifndef DB_VERSION_MINOR
67 # define DB_VERSION_MINOR 0
68 #endif /* DB_VERSION_MINOR */
69 Lisp_Object Qberkeley_db;
70 Lisp_Object Qhash, Qbtree, Qrecno, Qunknown;
71 #if DB_VERSION_MAJOR > 2
74 #endif /* HAVE_BERKELEY_DB */
82 /* #### The following should be settable on a per-database level.
83 But the whole coding-system infrastructure should be rewritten someday.
84 We really need coding-system aliases. -- martin */
85 Lisp_Object Vdatabase_coding_system;
88 Lisp_Object Qdatabasep;
92 Lisp_Object (*get_subtype) (Lisp_Database *);
93 Lisp_Object (*get_type) (Lisp_Database *);
94 Lisp_Object (*get) (Lisp_Database *, Lisp_Object);
95 int (*put) (Lisp_Database *, Lisp_Object, Lisp_Object, Lisp_Object);
96 int (*rem) (Lisp_Database *, Lisp_Object);
97 void (*map) (Lisp_Database *, Lisp_Object);
98 void (*close) (Lisp_Database *);
99 Lisp_Object (*last_error) (Lisp_Database *);
104 struct lcrecord_header header;
113 #ifdef HAVE_BERKELEY_DB
118 Lisp_Object coding_system;
122 #define XDATABASE(x) XRECORD (x, database, Lisp_Database)
123 #define XSETDATABASE(x, p) XSETRECORD (x, p, database)
124 #define DATABASEP(x) RECORDP (x, database)
125 #define CHECK_DATABASE(x) CHECK_RECORD (x, database)
126 #define CONCHECK_DATABASE(x) CONCHECK_RECORD (x, database)
127 #define DATABASE_LIVE_P(x) (x->live_p)
129 #define CHECK_LIVE_DATABASE(db) do { \
130 CHECK_DATABASE (db); \
131 if (!DATABASE_LIVE_P (XDATABASE(db))) \
132 signal_simple_error ("Attempting to access closed database", db); \
136 static Lisp_Database *
137 allocate_database (void)
139 Lisp_Database *db = alloc_lcrecord_type (Lisp_Database, &lrecord_database);
143 #ifdef HAVE_BERKELEY_DB
144 db->db_handle = NULL;
147 db->dbm_handle = NULL;
153 db->coding_system = Fget_coding_system (Qbinary);
159 mark_database (Lisp_Object object)
161 Lisp_Database *db = XDATABASE (object);
166 print_database (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
169 Lisp_Database *db = XDATABASE (obj);
172 error ("printing unreadable object #<database 0x%x>", db->header.uid);
174 write_c_string ("#<database \"", printcharfun);
175 print_internal (db->fname, printcharfun, 0);
176 sprintf (buf, "\" (%s/%s/%s) 0x%x>",
177 (char *) string_data (XSYMBOL (db->funcs->get_type (db))->name),
178 (char *) string_data (XSYMBOL (db->funcs->get_subtype (db))->name),
179 (!DATABASE_LIVE_P (db) ? "closed" :
180 (db->access_ & O_WRONLY) ? "writeonly" :
181 (db->access_ & O_RDWR) ? "readwrite" : "readonly"),
183 write_c_string (buf, printcharfun);
187 finalize_database (void *header, int for_disksave)
189 Lisp_Database *db = (Lisp_Database *) header;
194 XSETDATABASE (object, db);
197 ("Can't dump an emacs containing database objects", object);
199 db->funcs->close (db);
202 DEFINE_LRECORD_IMPLEMENTATION ("database", database,
203 mark_database, print_database,
204 finalize_database, 0, 0, 0,
207 DEFUN ("close-database", Fclose_database, 1, 1, 0, /*
208 Close database DATABASE.
213 CHECK_LIVE_DATABASE (database);
214 db = XDATABASE (database);
215 db->funcs->close (db);
220 DEFUN ("database-type", Fdatabase_type, 1, 1, 0, /*
221 Return the type of database DATABASE.
225 CHECK_DATABASE (database);
227 return XDATABASE (database)->funcs->get_type (XDATABASE (database));
230 DEFUN ("database-subtype", Fdatabase_subtype, 1, 1, 0, /*
231 Return the subtype of database DATABASE, if any.
235 CHECK_DATABASE (database);
237 return XDATABASE (database)->funcs->get_subtype (XDATABASE (database));
240 DEFUN ("database-live-p", Fdatabase_live_p, 1, 1, 0, /*
241 Return t if OBJECT is an active database.
245 return DATABASEP (object) && DATABASE_LIVE_P (XDATABASE (object)) ?
249 DEFUN ("database-file-name", Fdatabase_file_name, 1, 1, 0, /*
250 Return the filename associated with the database DATABASE.
254 CHECK_DATABASE (database);
256 return XDATABASE (database)->fname;
259 DEFUN ("databasep", Fdatabasep, 1, 1, 0, /*
260 Return t if OBJECT is a database.
264 return DATABASEP (object) ? Qt : Qnil;
269 dbm_map (Lisp_Database *db, Lisp_Object func)
271 datum keydatum, valdatum;
272 Lisp_Object key, val;
274 for (keydatum = dbm_firstkey (db->dbm_handle);
275 keydatum.dptr != NULL;
276 keydatum = dbm_nextkey (db->dbm_handle))
278 valdatum = dbm_fetch (db->dbm_handle, keydatum);
279 key = make_string ((unsigned char *) keydatum.dptr, keydatum.dsize);
280 val = make_string ((unsigned char *) valdatum.dptr, valdatum.dsize);
281 call2 (func, key, val);
286 dbm_get (Lisp_Database *db, Lisp_Object key)
288 datum keydatum, valdatum;
290 keydatum.dptr = (char *) XSTRING_DATA (key);
291 keydatum.dsize = XSTRING_LENGTH (key);
292 valdatum = dbm_fetch (db->dbm_handle, keydatum);
294 return (valdatum.dptr
295 ? make_string ((unsigned char *) valdatum.dptr, valdatum.dsize)
300 dbm_put (Lisp_Database *db,
301 Lisp_Object key, Lisp_Object val, Lisp_Object replace)
303 datum keydatum, valdatum;
305 valdatum.dptr = (char *) XSTRING_DATA (val);
306 valdatum.dsize = XSTRING_LENGTH (val);
307 keydatum.dptr = (char *) XSTRING_DATA (key);
308 keydatum.dsize = XSTRING_LENGTH (key);
310 return !dbm_store (db->dbm_handle, keydatum, valdatum,
311 NILP (replace) ? DBM_INSERT : DBM_REPLACE);
315 dbm_remove (Lisp_Database *db, Lisp_Object key)
319 keydatum.dptr = (char *) XSTRING_DATA (key);
320 keydatum.dsize = XSTRING_LENGTH (key);
322 return dbm_delete (db->dbm_handle, keydatum);
326 dbm_type (Lisp_Database *db)
332 dbm_subtype (Lisp_Database *db)
338 dbm_lasterr (Lisp_Database *db)
340 return lisp_strerror (db->dberrno);
344 dbm_closeit (Lisp_Database *db)
348 dbm_close (db->dbm_handle);
349 db->dbm_handle = NULL;
353 static DB_FUNCS ndbm_func_block =
364 #endif /* HAVE_DBM */
366 #ifdef HAVE_BERKELEY_DB
368 berkdb_type (Lisp_Database *db)
374 berkdb_subtype (Lisp_Database *db)
379 switch (db->db_handle->type)
381 case DB_BTREE: return Qbtree;
382 case DB_HASH: return Qhash;
383 case DB_RECNO: return Qrecno;
384 #if DB_VERSION_MAJOR > 2
385 case DB_QUEUE: return Qqueue;
387 default: return Qunknown;
392 berkdb_lasterr (Lisp_Database *db)
394 return lisp_strerror (db->dberrno);
398 berkdb_get (Lisp_Database *db, Lisp_Object key)
400 DBT keydatum, valdatum;
403 /* DB Version 2 requires DBT's to be zeroed before use. */
407 keydatum.data = XSTRING_DATA (key);
408 keydatum.size = XSTRING_LENGTH (key);
410 #if DB_VERSION_MAJOR == 1
411 status = db->db_handle->get (db->db_handle, &keydatum, &valdatum, 0);
413 status = db->db_handle->get (db->db_handle, NULL, &keydatum, &valdatum, 0);
414 #endif /* DB_VERSION_MAJOR */
417 /* #### Not mule-ized! will crash! */
418 return make_string ((Bufbyte *) valdatum.data, valdatum.size);
420 #if DB_VERSION_MAJOR == 1
421 db->dberrno = (status == 1) ? -1 : errno;
423 db->dberrno = (status < 0) ? -1 : errno;
424 #endif /* DB_VERSION_MAJOR */
430 berkdb_put (Lisp_Database *db,
435 DBT keydatum, valdatum;
438 /* DB Version 2 requires DBT's to be zeroed before use. */
442 keydatum.data = XSTRING_DATA (key);
443 keydatum.size = XSTRING_LENGTH (key);
444 valdatum.data = XSTRING_DATA (val);
445 valdatum.size = XSTRING_LENGTH (val);
446 #if DB_VERSION_MAJOR == 1
447 status = db->db_handle->put (db->db_handle, &keydatum, &valdatum,
448 NILP (replace) ? R_NOOVERWRITE : 0);
449 db->dberrno = (status == 1) ? -1 : errno;
451 status = db->db_handle->put (db->db_handle, NULL, &keydatum, &valdatum,
452 NILP (replace) ? DB_NOOVERWRITE : 0);
453 db->dberrno = (status < 0) ? -1 : errno;
454 #endif/* DV_VERSION_MAJOR = 2 */
460 berkdb_remove (Lisp_Database *db, Lisp_Object key)
465 /* DB Version 2 requires DBT's to be zeroed before use. */
468 keydatum.data = XSTRING_DATA (key);
469 keydatum.size = XSTRING_LENGTH (key);
471 #if DB_VERSION_MAJOR == 1
472 status = db->db_handle->del (db->db_handle, &keydatum, 0);
474 status = db->db_handle->del (db->db_handle, NULL, &keydatum, 0);
475 #endif /* DB_VERSION_MAJOR */
480 #if DB_VERSION_MAJOR == 1
481 db->dberrno = (status == 1) ? -1 : errno;
483 db->dberrno = (status < 0) ? -1 : errno;
484 #endif /* DB_VERSION_MAJOR */
490 berkdb_map (Lisp_Database *db, Lisp_Object func)
492 DBT keydatum, valdatum;
493 Lisp_Object key, val;
494 DB *dbp = db->db_handle;
500 #if DB_VERSION_MAJOR == 1
501 for (status = dbp->seq (dbp, &keydatum, &valdatum, R_FIRST);
503 status = dbp->seq (dbp, &keydatum, &valdatum, R_NEXT))
505 /* #### Needs mule-izing */
506 key = make_string ((Bufbyte *) keydatum.data, keydatum.size);
507 val = make_string ((Bufbyte *) valdatum.data, valdatum.size);
508 call2 (func, key, val);
514 #if DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >=6
515 status = dbp->cursor (dbp, NULL, &dbcp, 0);
517 status = dbp->cursor (dbp, NULL, &dbcp);
519 for (status = dbcp->c_get (dbcp, &keydatum, &valdatum, DB_FIRST);
521 status = dbcp->c_get (dbcp, &keydatum, &valdatum, DB_NEXT))
523 /* #### Needs mule-izing */
524 key = make_string ((Bufbyte *) keydatum.data, keydatum.size);
525 val = make_string ((Bufbyte *) valdatum.data, valdatum.size);
526 call2 (func, key, val);
528 dbcp->c_close (dbcp);
530 #endif /* DB_VERSION_MAJOR */
534 berkdb_close (Lisp_Database *db)
538 #if DB_VERSION_MAJOR == 1
539 db->db_handle->sync (db->db_handle, 0);
540 db->db_handle->close (db->db_handle);
542 db->db_handle->sync (db->db_handle, 0);
543 db->db_handle->close (db->db_handle, 0);
544 #endif /* DB_VERSION_MAJOR */
545 db->db_handle = NULL;
549 static DB_FUNCS berk_func_block =
560 #endif /* HAVE_BERKELEY_DB */
562 DEFUN ("database-last-error", Fdatabase_last_error, 0, 1, 0, /*
563 Return the last error associated with DATABASE.
568 return lisp_strerror (errno);
570 CHECK_DATABASE (database);
572 return XDATABASE (database)->funcs->last_error (XDATABASE (database));
575 DEFUN ("open-database", Fopen_database, 1, 5, 0, /*
576 Return a new database object opened on FILE.
577 Optional arguments TYPE and SUBTYPE specify the database type.
578 Optional argument ACCESS specifies the access rights, which may be any
579 combination of 'r' 'w' and '+', for read, write, and creation flags.
580 Optional argument MODE gives the permissions to use when opening FILE,
581 and defaults to 0755.
583 (file, type, subtype, access_, mode))
585 /* This function can GC */
588 Lisp_Database *db = NULL;
590 struct gcpro gcpro1, gcpro2;
593 GCPRO2 (file, access_);
594 file = Fexpand_file_name (file, Qnil);
597 TO_EXTERNAL_FORMAT (LISP_STRING, file,
598 C_STRING_ALLOCA, filename,
603 accessmask = O_RDWR | O_CREAT;
608 CHECK_STRING (access_);
609 acc = (char *) XSTRING_DATA (access_);
611 if (strchr (acc, '+'))
612 accessmask |= O_CREAT;
615 char *rp = strchr (acc, 'r');
616 char *wp = strchr (acc, 'w');
617 if (rp && wp) accessmask |= O_RDWR;
618 else if (wp) accessmask |= O_WRONLY;
619 else accessmask |= O_RDONLY;
625 modemask = 0755; /* rwxr-xr-x */
630 modemask = XINT (mode);
634 if (NILP (type) || EQ (type, Qdbm))
636 DBM *dbase = dbm_open (filename, accessmask, modemask);
640 db = allocate_database ();
641 db->dbm_handle = dbase;
642 db->funcs = &ndbm_func_block;
645 #endif /* HAVE_DBM */
647 #ifdef HAVE_BERKELEY_DB
648 if (NILP (type) || EQ (type, Qberkeley_db))
652 #if DB_VERSION_MAJOR != 1
656 if (EQ (subtype, Qhash) || NILP (subtype))
657 real_subtype = DB_HASH;
658 else if (EQ (subtype, Qbtree))
659 real_subtype = DB_BTREE;
660 else if (EQ (subtype, Qrecno))
661 real_subtype = DB_RECNO;
662 #if DB_VERSION_MAJOR > 2
663 else if (EQ (subtype, Qqueue))
664 real_subtype = DB_QUEUE;
667 signal_simple_error ("Unsupported subtype", subtype);
669 #if DB_VERSION_MAJOR == 1
670 dbase = dbopen (filename, accessmask, modemask, real_subtype, NULL);
674 /* Berkeley DB Version 2 has only the accessmask DB_CREATE and DB_RDONLY,
675 other flags shouldn't be set */
677 accessmask = DB_CREATE;
681 CHECK_STRING (access_);
682 acc = (char *) XSTRING_DATA (access_);
685 if (strchr (acc, '+'))
686 accessmask |= DB_CREATE;
688 if (strchr (acc, 'r') && !strchr (acc, 'w'))
689 accessmask |= DB_RDONLY;
691 #if DB_VERSION_MAJOR == 2
692 status = db_open (filename, real_subtype, accessmask,
693 modemask, NULL , NULL, &dbase);
697 status = db_create (&dbase, NULL, 0);
700 #if DB_VERSION_MAJOR < 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR < 1)
701 status = dbase->open (dbase, filename, NULL,
702 real_subtype, accessmask, modemask);
703 #else /* DB_VERSION >= 4.1 */
704 /* DB_AUTO_COMMIT requires transaction support, don't try it */
705 status = dbase->open (dbase, NULL, filename, NULL, real_subtype,
706 accessmask, modemask);
707 #endif /* DB_VERSION < 4.1 */
710 dbase->close (dbase, 0);
713 #endif /* DB_VERSION_MAJOR > 2 */
714 /* Normalize into system specific file modes. Only for printing */
715 accessmask = accessmask & DB_RDONLY ? O_RDONLY : O_RDWR;
716 #endif /* DB_VERSION_MAJOR */
718 db = allocate_database ();
719 db->db_handle = dbase;
720 db->funcs = &berk_func_block;
723 #endif /* HAVE_BERKELEY_DB */
725 signal_simple_error ("Unsupported database type", type);
732 db->access_ = accessmask;
736 XSETDATABASE (retval, db);
741 DEFUN ("put-database", Fput_database, 3, 4, 0, /*
742 Store KEY and VALUE in DATABASE.
743 If optional fourth arg REPLACE is non-nil,
744 replace any existing entry in the database.
746 (key, value, database, replace))
748 CHECK_LIVE_DATABASE (database);
750 CHECK_STRING (value);
752 Lisp_Database *db = XDATABASE (database);
753 int status = db->funcs->put (db, key, value, replace);
754 return status ? Qt : Qnil;
758 DEFUN ("remove-database", Fremove_database, 2, 2, 0, /*
759 Remove KEY from DATABASE.
763 CHECK_LIVE_DATABASE (database);
766 Lisp_Database *db = XDATABASE (database);
767 int status = db->funcs->rem (db, key);
768 return status ? Qt : Qnil;
772 DEFUN ("get-database", Fget_database, 2, 3, 0, /*
773 Return value for KEY in DATABASE.
774 If there is no corresponding value, return DEFAULT (defaults to nil).
776 (key, database, default_))
778 CHECK_LIVE_DATABASE (database);
781 Lisp_Database *db = XDATABASE (database);
782 Lisp_Object retval = db->funcs->get (db, key);
783 return NILP (retval) ? default_ : retval;
787 DEFUN ("map-database", Fmap_database, 2, 2, 0, /*
788 Map FUNCTION over entries in DATABASE, calling it with two args,
789 each key and value in the database.
791 (function, database))
793 CHECK_LIVE_DATABASE (database);
795 XDATABASE (database)->funcs->map (XDATABASE (database), function);
801 syms_of_database (void)
803 INIT_LRECORD_IMPLEMENTATION (database);
805 defsymbol (&Qdatabasep, "databasep");
807 defsymbol (&Qdbm, "dbm");
809 #ifdef HAVE_BERKELEY_DB
810 defsymbol (&Qberkeley_db, "berkeley-db");
811 defsymbol (&Qhash, "hash");
812 defsymbol (&Qbtree, "btree");
813 defsymbol (&Qrecno, "recno");
814 #if DB_VERSION_MAJOR > 2
815 defsymbol (&Qqueue, "queue");
817 defsymbol (&Qunknown, "unknown");
820 DEFSUBR (Fopen_database);
821 DEFSUBR (Fdatabasep);
822 DEFSUBR (Fmap_database);
823 DEFSUBR (Fput_database);
824 DEFSUBR (Fget_database);
825 DEFSUBR (Fremove_database);
826 DEFSUBR (Fdatabase_type);
827 DEFSUBR (Fdatabase_subtype);
828 DEFSUBR (Fdatabase_last_error);
829 DEFSUBR (Fdatabase_live_p);
830 DEFSUBR (Fdatabase_file_name);
831 DEFSUBR (Fclose_database);
835 vars_of_database (void)
840 #ifdef HAVE_BERKELEY_DB
841 Fprovide (Qberkeley_db);
844 #if 0 /* #### implement me! */
846 DEFVAR_LISP ("database-coding-system", &Vdatabase_coding_system /*
847 Coding system used to convert data in database files.
849 Vdatabase_coding_system = Qnil;