00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "db_config.h"
00011
00012 #ifndef NO_SYSTEM_INCLUDES
00013 #include <sys/types.h>
00014
00015 #include <stdlib.h>
00016 #include <string.h>
00017 #include <tcl.h>
00018 #endif
00019
00020 #include "db_int.h"
00021 #include "dbinc/tcl_db.h"
00022 #include "dbinc/db_page.h"
00023 #include "dbinc/db_am.h"
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #define GLOB_CHAR(c) ((c) == '*' || (c) == '?')
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 DBTCL_INFO *
00055 _NewInfo(interp, anyp, name, type)
00056 Tcl_Interp *interp;
00057 void *anyp;
00058 char *name;
00059 enum INFOTYPE type;
00060 {
00061 DBTCL_INFO *p;
00062 int ret;
00063
00064 if ((ret = __os_calloc(NULL, sizeof(DBTCL_INFO), 1, &p)) != 0) {
00065 Tcl_SetResult(interp, db_strerror(ret), TCL_STATIC);
00066 return (NULL);
00067 }
00068
00069 if ((ret = __os_strdup(NULL, name, &p->i_name)) != 0) {
00070 Tcl_SetResult(interp, db_strerror(ret), TCL_STATIC);
00071 __os_free(NULL, p);
00072 return (NULL);
00073 }
00074 p->i_interp = interp;
00075 p->i_anyp = anyp;
00076 p->i_type = type;
00077
00078 LIST_INSERT_HEAD(&__db_infohead, p, entries);
00079 return (p);
00080 }
00081
00082
00083
00084
00085 void *
00086 _NameToPtr(name)
00087 CONST char *name;
00088 {
00089 DBTCL_INFO *p;
00090
00091 for (p = LIST_FIRST(&__db_infohead); p != NULL;
00092 p = LIST_NEXT(p, entries))
00093 if (strcmp(name, p->i_name) == 0)
00094 return (p->i_anyp);
00095 return (NULL);
00096 }
00097
00098
00099
00100
00101 DBTCL_INFO *
00102 _PtrToInfo(ptr)
00103 CONST void *ptr;
00104 {
00105 DBTCL_INFO *p;
00106
00107 for (p = LIST_FIRST(&__db_infohead); p != NULL;
00108 p = LIST_NEXT(p, entries))
00109 if (p->i_anyp == ptr)
00110 return (p);
00111 return (NULL);
00112 }
00113
00114
00115
00116
00117 DBTCL_INFO *
00118 _NameToInfo(name)
00119 CONST char *name;
00120 {
00121 DBTCL_INFO *p;
00122
00123 for (p = LIST_FIRST(&__db_infohead); p != NULL;
00124 p = LIST_NEXT(p, entries))
00125 if (strcmp(name, p->i_name) == 0)
00126 return (p);
00127 return (NULL);
00128 }
00129
00130
00131
00132
00133 void
00134 _SetInfoData(p, data)
00135 DBTCL_INFO *p;
00136 void *data;
00137 {
00138 if (p == NULL)
00139 return;
00140 p->i_anyp = data;
00141 return;
00142 }
00143
00144
00145
00146
00147 void
00148 _DeleteInfo(p)
00149 DBTCL_INFO *p;
00150 {
00151 if (p == NULL)
00152 return;
00153 LIST_REMOVE(p, entries);
00154 if (p->i_lockobj.data != NULL)
00155 __os_free(NULL, p->i_lockobj.data);
00156 if (p->i_err != NULL && p->i_err != stderr) {
00157 (void)fclose(p->i_err);
00158 p->i_err = NULL;
00159 }
00160 if (p->i_errpfx != NULL)
00161 __os_free(NULL, p->i_errpfx);
00162 if (p->i_btcompare != NULL)
00163 Tcl_DecrRefCount(p->i_btcompare);
00164 if (p->i_dupcompare != NULL)
00165 Tcl_DecrRefCount(p->i_dupcompare);
00166 if (p->i_hashproc != NULL)
00167 Tcl_DecrRefCount(p->i_hashproc);
00168 if (p->i_second_call != NULL)
00169 Tcl_DecrRefCount(p->i_second_call);
00170 if (p->i_rep_eid != NULL)
00171 Tcl_DecrRefCount(p->i_rep_eid);
00172 if (p->i_rep_send != NULL)
00173 Tcl_DecrRefCount(p->i_rep_send);
00174 __os_free(NULL, p->i_name);
00175 __os_free(NULL, p);
00176
00177 return;
00178 }
00179
00180
00181
00182
00183
00184 int
00185 _SetListElem(interp, list, elem1, e1cnt, elem2, e2cnt)
00186 Tcl_Interp *interp;
00187 Tcl_Obj *list;
00188 void *elem1, *elem2;
00189 u_int32_t e1cnt, e2cnt;
00190 {
00191 Tcl_Obj *myobjv[2], *thislist;
00192 int myobjc;
00193
00194 myobjc = 2;
00195 myobjv[0] = Tcl_NewByteArrayObj((u_char *)elem1, (int)e1cnt);
00196 myobjv[1] = Tcl_NewByteArrayObj((u_char *)elem2, (int)e2cnt);
00197 thislist = Tcl_NewListObj(myobjc, myobjv);
00198 if (thislist == NULL)
00199 return (TCL_ERROR);
00200 return (Tcl_ListObjAppendElement(interp, list, thislist));
00201
00202 }
00203
00204
00205
00206
00207 int
00208 _SetListElemInt(interp, list, elem1, elem2)
00209 Tcl_Interp *interp;
00210 Tcl_Obj *list;
00211 void *elem1;
00212 long elem2;
00213 {
00214 Tcl_Obj *myobjv[2], *thislist;
00215 int myobjc;
00216
00217 myobjc = 2;
00218 myobjv[0] =
00219 Tcl_NewByteArrayObj((u_char *)elem1, (int)strlen((char *)elem1));
00220 myobjv[1] = Tcl_NewLongObj(elem2);
00221 thislist = Tcl_NewListObj(myobjc, myobjv);
00222 if (thislist == NULL)
00223 return (TCL_ERROR);
00224 return (Tcl_ListObjAppendElement(interp, list, thislist));
00225 }
00226
00227
00228
00229
00230
00231
00232 #ifdef HAVE_SEQUENCE
00233
00234
00235
00236
00237 int
00238 _SetListElemWideInt(interp, list, elem1, elem2)
00239 Tcl_Interp *interp;
00240 Tcl_Obj *list;
00241 void *elem1;
00242 int64_t elem2;
00243 {
00244 Tcl_Obj *myobjv[2], *thislist;
00245 int myobjc;
00246
00247 myobjc = 2;
00248 myobjv[0] =
00249 Tcl_NewByteArrayObj((u_char *)elem1, (int)strlen((char *)elem1));
00250 myobjv[1] = Tcl_NewWideIntObj(elem2);
00251 thislist = Tcl_NewListObj(myobjc, myobjv);
00252 if (thislist == NULL)
00253 return (TCL_ERROR);
00254 return (Tcl_ListObjAppendElement(interp, list, thislist));
00255 }
00256 #endif
00257
00258
00259
00260
00261
00262 int
00263 _SetListRecnoElem(interp, list, elem1, elem2, e2size)
00264 Tcl_Interp *interp;
00265 Tcl_Obj *list;
00266 db_recno_t elem1;
00267 u_char *elem2;
00268 u_int32_t e2size;
00269 {
00270 Tcl_Obj *myobjv[2], *thislist;
00271 int myobjc;
00272
00273 myobjc = 2;
00274 myobjv[0] = Tcl_NewWideIntObj((Tcl_WideInt)elem1);
00275 myobjv[1] = Tcl_NewByteArrayObj(elem2, (int)e2size);
00276 thislist = Tcl_NewListObj(myobjc, myobjv);
00277 if (thislist == NULL)
00278 return (TCL_ERROR);
00279 return (Tcl_ListObjAppendElement(interp, list, thislist));
00280
00281 }
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299 int
00300 _Set3DBTList(interp, list, elem1, is1recno, elem2, is2recno, elem3)
00301 Tcl_Interp *interp;
00302 Tcl_Obj *list;
00303 DBT *elem1, *elem2, *elem3;
00304 int is1recno, is2recno;
00305 {
00306
00307 Tcl_Obj *myobjv[3], *thislist;
00308
00309 if (is1recno)
00310 myobjv[0] = Tcl_NewWideIntObj(
00311 (Tcl_WideInt)*(db_recno_t *)elem1->data);
00312 else
00313 myobjv[0] = Tcl_NewByteArrayObj(
00314 (u_char *)elem1->data, (int)elem1->size);
00315
00316 if (is2recno)
00317 myobjv[1] = Tcl_NewWideIntObj(
00318 (Tcl_WideInt)*(db_recno_t *)elem2->data);
00319 else
00320 myobjv[1] = Tcl_NewByteArrayObj(
00321 (u_char *)elem2->data, (int)elem2->size);
00322
00323 myobjv[2] = Tcl_NewByteArrayObj(
00324 (u_char *)elem3->data, (int)elem3->size);
00325
00326 thislist = Tcl_NewListObj(3, myobjv);
00327
00328 if (thislist == NULL)
00329 return (TCL_ERROR);
00330 return (Tcl_ListObjAppendElement(interp, list, thislist));
00331 }
00332
00333
00334
00335
00336
00337
00338
00339 int
00340 _SetMultiList(interp, list, key, data, type, flag)
00341 Tcl_Interp *interp;
00342 Tcl_Obj *list;
00343 DBT *key, *data;
00344 DBTYPE type;
00345 u_int32_t flag;
00346 {
00347 db_recno_t recno;
00348 u_int32_t dlen, klen;
00349 int result;
00350 void *pointer, *dp, *kp;
00351
00352 recno = 0;
00353 dlen = 0;
00354 kp = NULL;
00355
00356 DB_MULTIPLE_INIT(pointer, data);
00357 result = TCL_OK;
00358
00359 if (type == DB_RECNO || type == DB_QUEUE)
00360 recno = *(db_recno_t *) key->data;
00361 else
00362 kp = key->data;
00363 klen = key->size;
00364 do {
00365 if (flag & DB_MULTIPLE_KEY) {
00366 if (type == DB_RECNO || type == DB_QUEUE)
00367 DB_MULTIPLE_RECNO_NEXT(pointer,
00368 data, recno, dp, dlen);
00369 else
00370 DB_MULTIPLE_KEY_NEXT(pointer,
00371 data, kp, klen, dp, dlen);
00372 } else
00373 DB_MULTIPLE_NEXT(pointer, data, dp, dlen);
00374
00375 if (pointer == NULL)
00376 break;
00377
00378 if (type == DB_RECNO || type == DB_QUEUE) {
00379 result =
00380 _SetListRecnoElem(interp, list, recno, dp, dlen);
00381 recno++;
00382
00383 if (recno == 0)
00384 recno++;
00385 } else
00386 result = _SetListElem(interp, list, kp, klen, dp, dlen);
00387 } while (result == TCL_OK);
00388
00389 return (result);
00390 }
00391
00392
00393
00394 int
00395 _GetGlobPrefix(pattern, prefix)
00396 char *pattern;
00397 char **prefix;
00398 {
00399 int i, j;
00400 char *p;
00401
00402
00403
00404
00405 if (__os_strdup(NULL, pattern, prefix) != 0)
00406 return (1);
00407
00408 p = *prefix;
00409 for (i = 0, j = 0; p[i] && !GLOB_CHAR(p[i]); i++, j++)
00410
00411
00412
00413 if (p[i] == '\\' && p[i+1]) {
00414 p[j] = p[i+1];
00415 i++;
00416 } else
00417 p[j] = p[i];
00418 p[j] = 0;
00419 return (0);
00420 }
00421
00422
00423
00424
00425 int
00426 _ReturnSetup(interp, ret, ok, errmsg)
00427 Tcl_Interp *interp;
00428 int ret, ok;
00429 char *errmsg;
00430 {
00431 char *msg;
00432
00433 if (ret > 0)
00434 return (_ErrorSetup(interp, ret, errmsg));
00435
00436
00437
00438
00439
00440
00441
00442
00443 if (ret == 0) {
00444 Tcl_SetResult(interp, "0", TCL_STATIC);
00445 return (TCL_OK);
00446 }
00447
00448 msg = db_strerror(ret);
00449 Tcl_AppendResult(interp, msg, NULL);
00450
00451 if (ok)
00452 return (TCL_OK);
00453 else {
00454 Tcl_SetErrorCode(interp, "BerkeleyDB", msg, NULL);
00455 return (TCL_ERROR);
00456 }
00457 }
00458
00459
00460
00461
00462 int
00463 _ErrorSetup(interp, ret, errmsg)
00464 Tcl_Interp *interp;
00465 int ret;
00466 char *errmsg;
00467 {
00468 Tcl_SetErrno(ret);
00469 Tcl_AppendResult(interp, errmsg, ":", Tcl_PosixError(interp), NULL);
00470 return (TCL_ERROR);
00471 }
00472
00473
00474
00475
00476 void
00477 _ErrorFunc(dbenv, pfx, msg)
00478 const DB_ENV *dbenv;
00479 CONST char *pfx;
00480 const char *msg;
00481 {
00482 DBTCL_INFO *p;
00483 Tcl_Interp *interp;
00484 size_t size;
00485 char *err;
00486
00487 COMPQUIET(dbenv, NULL);
00488
00489 p = _NameToInfo(pfx);
00490 if (p == NULL)
00491 return;
00492 interp = p->i_interp;
00493
00494 size = strlen(pfx) + strlen(msg) + 4;
00495
00496
00497
00498
00499 if (__os_malloc(NULL, size, &err) != 0) {
00500 Tcl_AddErrorInfo(interp, msg);
00501 Tcl_AppendResult(interp, msg, "\n", NULL);
00502 return;
00503 }
00504 snprintf(err, size, "%s: %s", pfx, msg);
00505 Tcl_AddErrorInfo(interp, err);
00506 Tcl_AppendResult(interp, err, "\n", NULL);
00507 __os_free(NULL, err);
00508 return;
00509 }
00510
00511 #define INVALID_LSNMSG "Invalid LSN with %d parts. Should have 2.\n"
00512
00513
00514
00515
00516 int
00517 _GetLsn(interp, obj, lsn)
00518 Tcl_Interp *interp;
00519 Tcl_Obj *obj;
00520 DB_LSN *lsn;
00521 {
00522 Tcl_Obj **myobjv;
00523 char msg[MSG_SIZE];
00524 int myobjc, result;
00525 u_int32_t tmp;
00526
00527 result = Tcl_ListObjGetElements(interp, obj, &myobjc, &myobjv);
00528 if (result == TCL_ERROR)
00529 return (result);
00530 if (myobjc != 2) {
00531 result = TCL_ERROR;
00532 snprintf(msg, MSG_SIZE, INVALID_LSNMSG, myobjc);
00533 Tcl_SetResult(interp, msg, TCL_VOLATILE);
00534 return (result);
00535 }
00536 result = _GetUInt32(interp, myobjv[0], &tmp);
00537 if (result == TCL_ERROR)
00538 return (result);
00539 lsn->file = tmp;
00540 result = _GetUInt32(interp, myobjv[1], &tmp);
00541 lsn->offset = tmp;
00542 return (result);
00543 }
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560 int
00561 _GetUInt32(interp, obj, resp)
00562 Tcl_Interp *interp;
00563 Tcl_Obj *obj;
00564 u_int32_t *resp;
00565 {
00566 int result;
00567 long ltmp;
00568
00569 result = Tcl_GetLongFromObj(interp, obj, <mp);
00570 if (result != TCL_OK)
00571 return (result);
00572
00573 if ((unsigned long)ltmp != (u_int32_t)ltmp) {
00574 if (interp != NULL) {
00575 Tcl_ResetResult(interp);
00576 Tcl_AppendToObj(Tcl_GetObjResult(interp),
00577 "integer value too large for u_int32_t", -1);
00578 }
00579 return (TCL_ERROR);
00580 }
00581
00582 *resp = (u_int32_t)ltmp;
00583 return (TCL_OK);
00584 }
00585
00586
00587
00588
00589
00590
00591
00592
00593 Tcl_Obj *
00594 _GetFlagsList(interp, flags, fnp)
00595 Tcl_Interp *interp;
00596 u_int32_t flags;
00597 const FN *fnp;
00598 {
00599 Tcl_Obj *newlist, *newobj;
00600 int result;
00601
00602 newlist = Tcl_NewObj();
00603
00604
00605
00606
00607
00608 for (; fnp->mask != 0; ++fnp)
00609 if (LF_ISSET(fnp->mask)) {
00610 newobj = NewStringObj(fnp->name, strlen(fnp->name));
00611 result =
00612 Tcl_ListObjAppendElement(interp, newlist, newobj);
00613
00614
00615
00616
00617
00618
00619
00620 DB_ASSERT(result == TCL_OK);
00621 }
00622
00623 return (newlist);
00624 }
00625
00626 int __debug_stop, __debug_on, __debug_print, __debug_test;
00627
00628
00629
00630
00631 void
00632 _debug_check()
00633 {
00634 if (__debug_on == 0)
00635 return;
00636
00637 if (__debug_print != 0) {
00638 printf("\r%7d:", __debug_on);
00639 (void)fflush(stdout);
00640 }
00641 if (__debug_on++ == __debug_test || __debug_stop)
00642 __db_loadme();
00643 }
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662 int
00663 _CopyObjBytes(interp, obj, newp, sizep, freep)
00664 Tcl_Interp *interp;
00665 Tcl_Obj *obj;
00666 void *newp;
00667 u_int32_t *sizep;
00668 int *freep;
00669 {
00670 void *tmp, *new;
00671 int i, len, ret;
00672
00673
00674
00675
00676
00677
00678 *freep = 0;
00679 ret = Tcl_GetIntFromObj(interp, obj, &i);
00680 tmp = Tcl_GetByteArrayFromObj(obj, &len);
00681 *sizep = (u_int32_t)len;
00682 if (ret == TCL_ERROR) {
00683 Tcl_ResetResult(interp);
00684 *(void **)newp = tmp;
00685 return (0);
00686 }
00687
00688
00689
00690
00691
00692
00693 if ((ret = __os_malloc(NULL, (size_t)len, &new)) != 0)
00694 return (ret);
00695 memcpy(new, tmp, (size_t)len);
00696 *(void **)newp = new;
00697 *freep = 1;
00698 return (0);
00699 }