Changed to sourceforge tdb code. This includes spinlocks (so we now have
[samba.git] / source / tdb / tdbutil.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 3.0
4    tdb utility functions
5    Copyright (C) Andrew Tridgell 1992-1998
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 /* these are little tdb utility functions that are meant to make
25    dealing with a tdb database a little less cumbersome in Samba */
26
27 /* lock a chain by string */
28 int tdb_lock_bystring(TDB_CONTEXT *tdb, char *keyval)
29 {
30         TDB_DATA key;
31
32         key.dptr = keyval;
33         key.dsize = strlen(keyval)+1;
34         
35         return tdb_chainlock(tdb, key);
36 }
37
38 /* unlock a chain by string */
39 int tdb_unlock_bystring(TDB_CONTEXT *tdb, char *keyval)
40 {
41         TDB_DATA key;
42
43         key.dptr = keyval;
44         key.dsize = strlen(keyval)+1;
45         
46         return tdb_chainunlock(tdb, key);
47 }
48
49 /* lock a chain by string key */
50
51
52 /* fetch a value by a arbitrary blob key, return -1 if not found */
53 int tdb_fetch_int_byblob(TDB_CONTEXT *tdb, char *keyval, size_t len)
54 {
55         TDB_DATA key, data;
56         int ret;
57
58         key.dptr = keyval;
59         key.dsize = len;
60         data = tdb_fetch(tdb, key);
61         if (!data.dptr || data.dsize != sizeof(int)) return -1;
62         
63         memcpy(&ret, data.dptr, sizeof(int));
64         free(data.dptr);
65         return ret;
66 }
67
68 /* fetch a value by string key, return -1 if not found */
69 int tdb_fetch_int(TDB_CONTEXT *tdb, char *keystr)
70 {
71         return tdb_fetch_int_byblob(tdb, keystr, strlen(keystr) + 1);
72 }
73
74 /* store a value by an arbitary blob key, return 0 on success, -1 on failure */
75 int tdb_store_int_byblob(TDB_CONTEXT *tdb, char *keystr, size_t len, int v)
76 {
77         TDB_DATA key, data;
78
79         key.dptr = keystr;
80         key.dsize = len;
81         data.dptr = (void *)&v;
82         data.dsize = sizeof(int);
83
84         return tdb_store(tdb, key, data, TDB_REPLACE);
85 }
86
87 /* store a value by string key, return 0 on success, -1 on failure */
88 int tdb_store_int(TDB_CONTEXT *tdb, char *keystr, int v)
89 {
90         return tdb_store_int_byblob(tdb, keystr, strlen(keystr) + 1, v);
91 }
92
93 /* Store a buffer by a null terminated string key.  Return 0 on success, -1
94    on failure */
95 int tdb_store_by_string(TDB_CONTEXT *tdb, char *keystr, void *buffer, int len)
96 {
97     TDB_DATA key, data;
98
99     key.dptr = keystr;
100     key.dsize = strlen(keystr) + 1;
101
102     data.dptr = buffer;
103     data.dsize = len;
104
105     return tdb_store(tdb, key, data, TDB_REPLACE);
106 }
107
108 /* Fetch a buffer using a null terminated string key.  Don't forget to call
109    free() on the result dptr. */
110 TDB_DATA tdb_fetch_by_string(TDB_CONTEXT *tdb, char *keystr)
111 {
112     TDB_DATA key;
113
114     key.dptr = keystr;
115     key.dsize = strlen(keystr) + 1;
116
117     return tdb_fetch(tdb, key);
118 }
119
120
121 /* useful pair of routines for packing/unpacking data consisting of
122    integers and strings */
123 size_t tdb_pack(char *buf, int bufsize, char *fmt, ...)
124 {
125         uint16 w;
126         uint32 d;
127         int i;
128         void *p;
129         int len;
130         char *s;
131         char *buf0 = buf;
132         char *fmt0 = fmt;
133         int bufsize0 = bufsize;
134         va_list ap;
135         char c;
136
137         va_start(ap, fmt);
138         
139         while (*fmt) {
140                 switch ((c = *fmt++)) {
141                 case 'w':
142                         len = 2;
143                         w = (uint16)va_arg(ap, int);
144                         if (bufsize >= len) {
145                                 SSVAL(buf, 0, w);
146                         }
147                         break;
148                 case 'd':
149                         len = 4;
150                         d = va_arg(ap, uint32);
151                         if (bufsize >= len) {
152                                 SIVAL(buf, 0, d);
153                         }
154                         break;
155                 case 'p':
156                         len = 4;
157                         p = va_arg(ap, void *);
158                         d = p?1:0;
159                         if (bufsize >= len) {
160                                 SIVAL(buf, 0, d);
161                         }
162                         break;
163                 case 'P':
164                         s = va_arg(ap,char *);
165                         w = strlen(s);
166                         len = w + 1;
167                         if (bufsize >= len) {
168                                 memcpy(buf, s, len);
169                         }
170                         break;
171                 case 'f':
172                         s = va_arg(ap,char *);
173                         w = strlen(s);
174                         len = w + 1;
175                         if (bufsize >= len) {
176                                 memcpy(buf, s, len);
177                         }
178                         break;
179                 case 'B':
180                         i = va_arg(ap, int);
181                         s = va_arg(ap, char *);
182                         len = 4+i;
183                         if (bufsize >= len) {
184                                 SIVAL(buf, 0, i);
185                                 memcpy(buf+4, s, i);
186                         }
187                         break;
188                 default:
189                         DEBUG(0,("Unknown tdb_pack format %c in %s\n", 
190                                  c, fmt));
191                         break;
192                 }
193
194                 buf += len;
195                 bufsize -= len;
196         }
197
198         va_end(ap);
199
200         DEBUG(8,("tdb_pack(%s, %d) -> %d\n", 
201                  fmt0, bufsize0, (int)PTR_DIFF(buf, buf0)));
202         
203         return PTR_DIFF(buf, buf0);
204 }
205
206
207
208 /* useful pair of routines for packing/unpacking data consisting of
209    integers and strings */
210 int tdb_unpack(char *buf, int bufsize, char *fmt, ...)
211 {
212         uint16 *w;
213         uint32 *d;
214         int len;
215         int *i;
216         void **p;
217         char *s, **b;
218         char *buf0 = buf;
219         char *fmt0 = fmt;
220         int bufsize0 = bufsize;
221         va_list ap;
222         char c;
223
224         va_start(ap, fmt);
225         
226         while (*fmt) {
227                 switch ((c=*fmt++)) {
228                 case 'w':
229                         len = 2;
230                         w = va_arg(ap, uint16 *);
231                         if (bufsize < len) goto no_space;
232                         *w = SVAL(buf, 0);
233                         break;
234                 case 'd':
235                         len = 4;
236                         d = va_arg(ap, uint32 *);
237                         if (bufsize < len) goto no_space;
238                         *d = IVAL(buf, 0);
239                         break;
240                 case 'p':
241                         len = 4;
242                         p = va_arg(ap, void **);
243                         if (bufsize < len) goto no_space;
244                         *p = (void *)IVAL(buf, 0);
245                         break;
246                 case 'P':
247                         s = va_arg(ap,char *);
248                         len = strlen(buf) + 1;
249                         if (bufsize < len || len > sizeof(pstring)) goto no_space;
250                         memcpy(s, buf, len);
251                         break;
252                 case 'f':
253                         s = va_arg(ap,char *);
254                         len = strlen(buf) + 1;
255                         if (bufsize < len || len > sizeof(fstring)) goto no_space;
256                         memcpy(s, buf, len);
257                         break;
258                 case 'B':
259                         i = va_arg(ap, int *);
260                         b = va_arg(ap, char **);
261                         len = 4;
262                         if (bufsize < len) goto no_space;
263                         *i = IVAL(buf, 0);
264                         if (! *i) break;
265                         len += *i;
266                         if (bufsize < len) goto no_space;
267                         *b = (char *)malloc(*i);
268                         if (! *b) goto no_space;
269                         memcpy(*b, buf+4, *i);
270                         break;
271                 default:
272                         DEBUG(0,("Unknown tdb_unpack format %c in %s\n", 
273                                  c, fmt));
274                         break;
275                 }
276
277                 buf += len;
278                 bufsize -= len;
279         }
280
281         va_end(ap);
282
283         DEBUG(8,("tdb_unpack(%s, %d) -> %d\n", 
284                  fmt0, bufsize0, (int)PTR_DIFF(buf, buf0)));
285
286         return PTR_DIFF(buf, buf0);
287
288  no_space:
289         return -1;
290 }