Update.
[glibc.git] / db2 / common / db_err.c
blobf3e7b404486cff14abdba8b762c4e6da9ff607d7
1 /*-
2 * See the file LICENSE for redistribution information.
4 * Copyright (c) 1996, 1997
5 * Sleepycat Software. All rights reserved.
6 */
8 #include "config.h"
10 #ifndef lint
11 static const char sccsid[] = "@(#)db_err.c 10.18 (Sleepycat) 8/27/97";
12 #endif /* not lint */
14 #ifndef NO_SYSTEM_INCLUDES
15 #include <sys/types.h>
17 #include <errno.h>
19 #ifdef __STDC__
20 #include <stdarg.h>
21 #else
22 #include <varargs.h>
23 #endif
24 #endif
26 #include "db_int.h"
27 #include "common_ext.h"
29 static int __db_rdonly __P((const DB_ENV *, const char *));
32 * __db_err --
33 * Standard DB error routine.
35 * PUBLIC: #ifdef __STDC__
36 * PUBLIC: void __db_err __P((const DB_ENV *dbenv, const char *fmt, ...));
37 * PUBLIC: #else
38 * PUBLIC: void __db_err();
39 * PUBLIC: #endif
41 void
42 #ifdef __STDC__
43 __db_err(const DB_ENV *dbenv, const char *fmt, ...)
44 #else
45 __db_err(dbenv, fmt, va_alist)
46 const DB_ENV *dbenv;
47 const char *fmt;
48 va_dcl
49 #endif
51 va_list ap;
52 char errbuf[2048]; /* XXX: END OF THE STACK DON'T TRUST SPRINTF. */
54 if (dbenv == NULL)
55 return;
57 #ifdef __STDC__
58 va_start(ap, fmt);
59 #else
60 va_start(ap);
61 #endif
62 if (dbenv->db_errcall != NULL) {
63 (void)vsnprintf(errbuf, sizeof(errbuf), fmt, ap);
64 dbenv->db_errcall(dbenv->db_errpfx, errbuf);
66 if (dbenv->db_errfile != NULL) {
67 if (dbenv->db_errpfx != NULL)
68 (void)fprintf(dbenv->db_errfile, "%s: ",
69 dbenv->db_errpfx);
70 (void)vfprintf(dbenv->db_errfile, fmt, ap);
71 (void)fprintf(dbenv->db_errfile, "\n");
72 (void)fflush(dbenv->db_errfile);
74 va_end(ap);
78 * XXX
79 * Provide ANSI C prototypes for the panic functions. Some compilers, (e.g.,
80 * MS VC 4.2) get upset if they aren't here, even though the K&R declaration
81 * appears before the assignment in the __db__panic() call.
83 static int __db_ecursor __P((DB *, DB_TXN *, DBC **));
84 static int __db_edel __P((DB *, DB_TXN *, DBT *, int));
85 static int __db_efd __P((DB *, int *));
86 static int __db_egp __P((DB *, DB_TXN *, DBT *, DBT *, int));
87 static int __db_estat __P((DB *, void *, void *(*)(size_t), int));
88 static int __db_esync __P((DB *, int));
91 * __db_ecursor --
92 * After-panic cursor routine.
94 static int
95 __db_ecursor(a, b, c)
96 DB *a;
97 DB_TXN *b;
98 DBC **c;
100 a = a; b = b; c = c; /* XXX: Shut the compiler up. */
102 return (EPERM);
106 * __db_edel --
107 * After-panic delete routine.
109 static int
110 __db_edel(a, b, c, d)
111 DB *a;
112 DB_TXN *b;
113 DBT *c;
114 int d;
116 a = a; b = b; c = c; d = d; /* XXX: Shut the compiler up. */
118 return (EPERM);
122 * __db_efd --
123 * After-panic fd routine.
125 static int
126 __db_efd(a, b)
127 DB *a;
128 int *b;
130 a = a; b = b; /* XXX: Shut the compiler up. */
132 return (EPERM);
136 * __db_egp --
137 * After-panic get/put routine.
139 static int
140 __db_egp(a, b, c, d, e)
141 DB *a;
142 DB_TXN *b;
143 DBT *c, *d;
144 int e;
146 a = a; b = b; c = c; d = d; e = e; /* XXX: Shut the compiler up. */
148 return (EPERM);
152 * __db_estat --
153 * After-panic stat routine.
155 static int
156 __db_estat(a, b, c, d)
157 DB *a;
158 void *b;
159 void *(*c) __P((size_t));
160 int d;
162 a = a; b = b; c = c; d = d; /* XXX: Shut the compiler up. */
164 return (EPERM);
168 * __db_esync --
169 * After-panic sync routine.
171 static int
172 __db_esync(a, b)
173 DB *a;
174 int b;
176 a = a; b = b; /* XXX: Shut the compiler up. */
178 return (EPERM);
182 * __db_panic --
183 * Lock out the tree due to unrecoverable error.
185 * PUBLIC: int __db_panic __P((DB *));
188 __db_panic(dbp)
189 DB *dbp;
192 * XXX
193 * We should shut down all of the process's cursors, too.
195 * We should call mpool and have it shut down the file, so we get
196 * other processes sharing this file as well.
198 dbp->cursor = __db_ecursor;
199 dbp->del = __db_edel;
200 dbp->fd = __db_efd;
201 dbp->get = __db_egp;
202 dbp->put = __db_egp;
203 dbp->stat = __db_estat;
204 dbp->sync = __db_esync;
206 return (EPERM);
209 /* Check for invalid flags. */
210 #undef DB_CHECK_FLAGS
211 #define DB_CHECK_FLAGS(dbenv, name, flags, ok_flags) \
212 if ((flags) & ~(ok_flags)) \
213 return (__db_ferr(dbenv, name, 0));
214 /* Check for invalid flag combinations. */
215 #undef DB_CHECK_FCOMBO
216 #define DB_CHECK_FCOMBO(dbenv, name, flags, flag1, flag2) \
217 if ((flags) & (flag1) && (flags) & (flag2)) \
218 return (__db_ferr(dbenv, name, 1));
221 * __db_fchk --
222 * General flags checking routine.
224 * PUBLIC: int __db_fchk __P((DB_ENV *, const char *, int, int));
227 __db_fchk(dbenv, name, flags, ok_flags)
228 DB_ENV *dbenv;
229 const char *name;
230 int flags, ok_flags;
232 DB_CHECK_FLAGS(dbenv, name, flags, ok_flags);
233 return (0);
237 * __db_fcchk --
238 * General combination flags checking routine.
240 * PUBLIC: int __db_fcchk __P((DB_ENV *, const char *, int, int, int));
243 __db_fcchk(dbenv, name, flags, flag1, flag2)
244 DB_ENV *dbenv;
245 const char *name;
246 int flags, flag1, flag2;
248 DB_CHECK_FCOMBO(dbenv, name, flags, flag1, flag2);
249 return (0);
253 * __db_cdelchk --
254 * Common cursor delete argument checking routine.
256 * PUBLIC: int __db_cdelchk __P((const DB *, int, int, int));
259 __db_cdelchk(dbp, flags, isrdonly, isvalid)
260 const DB *dbp;
261 int flags, isrdonly, isvalid;
263 /* Check for changes to a read-only tree. */
264 if (isrdonly)
265 return (__db_rdonly(dbp->dbenv, "c_del"));
267 /* Check for invalid dbc->c_del() function flags. */
268 DB_CHECK_FLAGS(dbp->dbenv, "c_del", flags, 0);
271 * The cursor must be initialized, return -1 for an invalid cursor,
272 * otherwise 0.
274 return (isvalid ? 0 : EINVAL);
278 * __db_cgetchk --
279 * Common cursor get argument checking routine.
281 * PUBLIC: int __db_cgetchk __P((const DB *, DBT *, DBT *, int, int));
284 __db_cgetchk(dbp, key, data, flags, isvalid)
285 const DB *dbp;
286 DBT *key, *data;
287 int flags, isvalid;
289 int check_key;
291 check_key = 0;
293 /* Check for invalid dbc->c_get() function flags. */
294 switch (flags) {
295 case DB_CURRENT:
296 case DB_FIRST:
297 case DB_LAST:
298 case DB_NEXT:
299 case DB_PREV:
300 case DB_SET_RANGE:
301 check_key = 1;
302 break;
303 case DB_SET:
304 break;
305 case DB_SET_RECNO:
306 case DB_GET_RECNO:
307 if (!F_ISSET(dbp, DB_BT_RECNUM))
308 goto err;
309 check_key = 1;
310 break;
311 default:
312 err: return (__db_ferr(dbp->dbenv, "c_get", 0));
315 /* Check for invalid key/data flags. */
316 DB_CHECK_FLAGS(dbp->dbenv, "key", key->flags,
317 DB_DBT_MALLOC | DB_DBT_USERMEM | DB_DBT_PARTIAL);
318 DB_CHECK_FLAGS(dbp->dbenv, "data", data->flags,
319 DB_DBT_MALLOC | DB_DBT_USERMEM | DB_DBT_PARTIAL);
321 /* Check dbt's for valid flags when multi-threaded. */
322 if (F_ISSET(dbp, DB_AM_THREAD)) {
323 if (!F_ISSET(data, DB_DBT_USERMEM | DB_DBT_MALLOC))
324 return (__db_ferr(dbp->dbenv, "threaded data", 1));
325 if (check_key &&
326 !F_ISSET(key, DB_DBT_USERMEM | DB_DBT_MALLOC))
327 return (__db_ferr(dbp->dbenv, "threaded key", 1));
331 * The cursor must be initialized for DB_CURRENT, return -1 for an
332 * invalid cursor, otherwise 0.
334 return (isvalid || flags != DB_CURRENT ? 0 : EINVAL);
338 * __db_cputchk --
339 * Common cursor put argument checking routine.
341 * PUBLIC: int __db_cputchk __P((const DB *,
342 * PUBLIC: const DBT *, DBT *, int, int, int));
345 __db_cputchk(dbp, key, data, flags, isrdonly, isvalid)
346 const DB *dbp;
347 const DBT *key;
348 DBT *data;
349 int flags, isrdonly, isvalid;
351 int check_key;
353 /* Check for changes to a read-only tree. */
354 if (isrdonly)
355 return (__db_rdonly(dbp->dbenv, "c_put"));
357 /* Check for invalid dbc->c_put() function flags. */
358 check_key = 0;
359 switch (flags) {
360 case DB_AFTER:
361 case DB_BEFORE:
362 if (dbp->type == DB_RECNO && !F_ISSET(dbp, DB_RE_RENUMBER))
363 goto err;
364 if (dbp->type != DB_RECNO && !F_ISSET(dbp, DB_AM_DUP))
365 goto err;
366 break;
367 case DB_CURRENT:
368 break;
369 case DB_KEYFIRST:
370 case DB_KEYLAST:
371 if (dbp->type == DB_RECNO)
372 goto err;
373 check_key = 1;
374 break;
375 default:
376 err: return (__db_ferr(dbp->dbenv, "c_put", 0));
379 /* Check for invalid key/data flags. */
380 if (check_key)
381 DB_CHECK_FLAGS(dbp->dbenv, "key", key->flags,
382 DB_DBT_MALLOC | DB_DBT_USERMEM | DB_DBT_PARTIAL);
383 DB_CHECK_FLAGS(dbp->dbenv, "data", data->flags,
384 DB_DBT_MALLOC | DB_DBT_USERMEM | DB_DBT_PARTIAL);
387 * The cursor must be initialized for anything other than DB_KEYFIRST
388 * and DB_KEYLAST, return -1 for an invalid cursor, otherwise 0.
390 return (isvalid ||
391 (flags != DB_KEYFIRST && flags != DB_KEYLAST) ? 0 : EINVAL);
395 * __db_delchk --
396 * Common delete argument checking routine.
398 * PUBLIC: int __db_delchk __P((const DB *, int, int));
401 __db_delchk(dbp, flags, isrdonly)
402 const DB *dbp;
403 int flags, isrdonly;
405 /* Check for changes to a read-only tree. */
406 if (isrdonly)
407 return (__db_rdonly(dbp->dbenv, "delete"));
409 /* Check for invalid db->del() function flags. */
410 DB_CHECK_FLAGS(dbp->dbenv, "delete", flags, 0);
412 return (0);
416 * __db_getchk --
417 * Common get argument checking routine.
419 * PUBLIC: int __db_getchk __P((const DB *, const DBT *, DBT *, int));
422 __db_getchk(dbp, key, data, flags)
423 const DB *dbp;
424 const DBT *key;
425 DBT *data;
426 int flags;
428 /* Check for invalid db->get() function flags. */
429 DB_CHECK_FLAGS(dbp->dbenv,
430 "get", flags, F_ISSET(dbp, DB_BT_RECNUM) ? DB_SET_RECNO : 0);
432 /* Check for invalid key/data flags. */
433 DB_CHECK_FLAGS(dbp->dbenv, "key", key->flags, 0);
434 DB_CHECK_FLAGS(dbp->dbenv, "data", data->flags,
435 DB_DBT_MALLOC | DB_DBT_USERMEM | DB_DBT_PARTIAL);
436 DB_CHECK_FCOMBO(dbp->dbenv,
437 "data", data->flags, DB_DBT_MALLOC, DB_DBT_USERMEM);
438 if (F_ISSET(dbp, DB_AM_THREAD) &&
439 !F_ISSET(data, DB_DBT_MALLOC | DB_DBT_USERMEM))
440 return (__db_ferr(dbp->dbenv, "threaded data", 1));
442 return (0);
446 * __db_putchk --
447 * Common put argument checking routine.
449 * PUBLIC: int __db_putchk __P((const DB *, DBT *, const DBT *, int, int, int));
452 __db_putchk(dbp, key, data, flags, isrdonly, isdup)
453 const DB *dbp;
454 DBT *key;
455 const DBT *data;
456 int flags, isrdonly, isdup;
458 /* Check for changes to a read-only tree. */
459 if (isrdonly)
460 return (__db_rdonly(dbp->dbenv, "put"));
462 /* Check for invalid db->put() function flags. */
463 DB_CHECK_FLAGS(dbp->dbenv, "put", flags,
464 DB_NOOVERWRITE | (dbp->type == DB_RECNO ? DB_APPEND : 0));
466 /* Check for invalid key/data flags. */
467 DB_CHECK_FLAGS(dbp->dbenv, "key", key->flags, 0);
468 DB_CHECK_FLAGS(dbp->dbenv, "data", data->flags,
469 DB_DBT_MALLOC | DB_DBT_USERMEM | DB_DBT_PARTIAL);
470 DB_CHECK_FCOMBO(dbp->dbenv,
471 "data", data->flags, DB_DBT_MALLOC, DB_DBT_USERMEM);
473 /* Check for partial puts in the presence of duplicates. */
474 if (isdup && F_ISSET(data, DB_DBT_PARTIAL)) {
475 __db_err(dbp->dbenv,
476 "a partial put in the presence of duplicates requires a cursor operation");
477 return (EINVAL);
479 return (0);
483 * __db_statchk --
484 * Common stat argument checking routine.
486 * PUBLIC: int __db_statchk __P((const DB *, int));
489 __db_statchk(dbp, flags)
490 const DB *dbp;
491 int flags;
493 /* Check for invalid db->stat() function flags. */
494 DB_CHECK_FLAGS(dbp->dbenv, "stat", flags, DB_RECORDCOUNT);
496 if (LF_ISSET(DB_RECORDCOUNT) &&
497 dbp->type == DB_BTREE && !F_ISSET(dbp, DB_BT_RECNUM))
498 return (__db_ferr(dbp->dbenv, "stat", 0));
500 return (0);
504 * __db_syncchk --
505 * Common sync argument checking routine.
507 * PUBLIC: int __db_syncchk __P((const DB *, int));
510 __db_syncchk(dbp, flags)
511 const DB *dbp;
512 int flags;
514 /* Check for invalid db->sync() function flags. */
515 DB_CHECK_FLAGS(dbp->dbenv, "sync", flags, 0);
517 return (0);
521 * __db_ferr --
522 * Common flag errors.
524 * PUBLIC: int __db_ferr __P((const DB_ENV *, const char *, int));
527 __db_ferr(dbenv, name, combo)
528 const DB_ENV *dbenv;
529 const char *name;
530 int combo;
532 __db_err(dbenv, "illegal flag %sspecified to %s",
533 combo ? "combination " : "", name);
534 return (EINVAL);
538 * __db_rdonly --
539 * Common readonly message.
541 static int
542 __db_rdonly(dbenv, name)
543 const DB_ENV *dbenv;
544 const char *name;
546 __db_err(dbenv, "%s: attempt to modify a read-only tree", name);
547 return (EACCES);