92b443ce99a38d8b515d9a09d5a8174bad3aa592
[p5sagit/p5-mst-13.2.git] / ext / ODBM_File / ODBM_File.xs
1 #include "EXTERN.h"
2 #include "perl.h"
3 #include "XSUB.h"
4
5 #ifdef NULL
6 #undef NULL
7 #endif
8 #ifdef I_DBM
9 #  include <dbm.h>
10 #else
11 #  ifdef I_RPCSVC_DBM
12 #    include <rpcsvc/dbm.h>
13 #  endif
14 #endif
15
16 #ifdef DBM_BUG_DUPLICATE_FREE 
17 /*
18  * DBM on at least Ultrix and HPUX call dbmclose() from dbminit(),
19  * resulting in duplicate free() because dbmclose() does *not*
20  * check if it has already been called for this DBM.
21  * If some malloc/free calls have been done between dbmclose() and
22  * the next dbminit(), the memory might be used for something else when
23  * it is freed.
24  * Verified to work on ultrix4.3.  Probably will work on HP/UX.
25  * Set DBM_BUG_DUPLICATE_FREE in the extension hint file.
26  */
27 /* Close the previous dbm, and fail to open a new dbm */
28 #define dbmclose()      ((void) dbminit("/tmp/x/y/z/z/y"))
29 #endif
30
31 #include <fcntl.h>
32
33 typedef void* ODBM_File;
34
35 #define odbm_FETCH(db,key)                      fetch(key)
36 #define odbm_STORE(db,key,value,flags)          store(key,value)
37 #define odbm_DELETE(db,key)                     delete(key)
38 #define odbm_FIRSTKEY(db)                       firstkey()
39 #define odbm_NEXTKEY(db,key)                    nextkey(key)
40
41 static int dbmrefcnt;
42
43 #ifndef DBM_REPLACE
44 #define DBM_REPLACE 0
45 #endif
46
47 MODULE = ODBM_File      PACKAGE = ODBM_File     PREFIX = odbm_
48
49 ODBM_File
50 odbm_TIEHASH(dbtype, filename, flags, mode)
51         char *          dbtype
52         char *          filename
53         int             flags
54         int             mode
55         CODE:
56         {
57             char tmpbuf[1025];
58             if (dbmrefcnt++)
59                 croak("Old dbm can only open one database");
60             sprintf(tmpbuf,"%s.dir",filename);
61             if (stat(tmpbuf, &statbuf) < 0) {
62                 if (flags & O_CREAT) {
63                     if (mode < 0 || close(creat(tmpbuf,mode)) < 0)
64                         croak("ODBM_File: Can't create %s", filename);
65                     sprintf(tmpbuf,"%s.pag",filename);
66                     if (close(creat(tmpbuf,mode)) < 0)
67                         croak("ODBM_File: Can't create %s", filename);
68                 }
69                 else
70                     croak("ODBM_FILE: Can't open %s", filename);
71             }
72             RETVAL = (void*)(dbminit(filename) >= 0 ? &dbmrefcnt : 0);
73             ST(0) = sv_mortalcopy(&sv_undef);
74             sv_setptrobj(ST(0), RETVAL, "ODBM_File");
75         }
76
77 void
78 DESTROY(db)
79         ODBM_File       db
80         CODE:
81         dbmrefcnt--;
82         dbmclose();
83
84 datum
85 odbm_FETCH(db, key)
86         ODBM_File       db
87         datum           key
88
89 int
90 odbm_STORE(db, key, value, flags = DBM_REPLACE)
91         ODBM_File       db
92         datum           key
93         datum           value
94         int             flags
95     CLEANUP:
96         if (RETVAL) {
97             if (RETVAL < 0 && errno == EPERM)
98                 croak("No write permission to odbm file");
99             croak("odbm store returned %d, errno %d, key \"%s\"",
100                         RETVAL,errno,key.dptr);
101         }
102
103 int
104 odbm_DELETE(db, key)
105         ODBM_File       db
106         datum           key
107
108 datum
109 odbm_FIRSTKEY(db)
110         ODBM_File       db
111
112 datum
113 odbm_NEXTKEY(db, key)
114         ODBM_File       db
115         datum           key
116