Annotation of embedaddon/php/ext/dba/dba.c, revision 1.1
1.1 ! misho 1: /*
! 2: +----------------------------------------------------------------------+
! 3: | PHP Version 5 |
! 4: +----------------------------------------------------------------------+
! 5: | Copyright (c) 1997-2012 The PHP Group |
! 6: +----------------------------------------------------------------------+
! 7: | This source file is subject to version 3.01 of the PHP license, |
! 8: | that is bundled with this package in the file LICENSE, and is |
! 9: | available through the world-wide-web at the following url: |
! 10: | http://www.php.net/license/3_01.txt |
! 11: | If you did not receive a copy of the PHP license and are unable to |
! 12: | obtain it through the world-wide-web, please send a note to |
! 13: | license@php.net so we can mail you a copy immediately. |
! 14: +----------------------------------------------------------------------+
! 15: | Authors: Sascha Schumann <sascha@schumann.cx> |
! 16: | Marcus Boerger <helly@php.net> |
! 17: +----------------------------------------------------------------------+
! 18: */
! 19:
! 20: /* $Id: dba.c 321634 2012-01-01 13:15:04Z felipe $ */
! 21:
! 22: #ifdef HAVE_CONFIG_H
! 23: #include "config.h"
! 24: #endif
! 25:
! 26: #include "php.h"
! 27:
! 28: #if HAVE_DBA
! 29:
! 30: #include "php_ini.h"
! 31: #include <stdio.h>
! 32: #include <fcntl.h>
! 33: #ifdef HAVE_SYS_FILE_H
! 34: #include <sys/file.h>
! 35: #endif
! 36:
! 37: #include "php_dba.h"
! 38: #include "ext/standard/info.h"
! 39: #include "ext/standard/php_string.h"
! 40: #include "ext/standard/flock_compat.h"
! 41:
! 42: #include "php_gdbm.h"
! 43: #include "php_ndbm.h"
! 44: #include "php_dbm.h"
! 45: #include "php_cdb.h"
! 46: #include "php_db1.h"
! 47: #include "php_db2.h"
! 48: #include "php_db3.h"
! 49: #include "php_db4.h"
! 50: #include "php_flatfile.h"
! 51: #include "php_inifile.h"
! 52: #include "php_qdbm.h"
! 53:
! 54: /* {{{ arginfo */
! 55: ZEND_BEGIN_ARG_INFO_EX(arginfo_dba_popen, 0, 0, 2)
! 56: ZEND_ARG_INFO(0, path)
! 57: ZEND_ARG_INFO(0, mode)
! 58: ZEND_ARG_INFO(0, handlername)
! 59: ZEND_ARG_INFO(0, ...)
! 60: ZEND_END_ARG_INFO()
! 61:
! 62: ZEND_BEGIN_ARG_INFO_EX(arginfo_dba_open, 0, 0, 2)
! 63: ZEND_ARG_INFO(0, path)
! 64: ZEND_ARG_INFO(0, mode)
! 65: ZEND_ARG_INFO(0, handlername)
! 66: ZEND_ARG_INFO(0, ...)
! 67: ZEND_END_ARG_INFO()
! 68:
! 69: ZEND_BEGIN_ARG_INFO(arginfo_dba_close, 0)
! 70: ZEND_ARG_INFO(0, handle)
! 71: ZEND_END_ARG_INFO()
! 72:
! 73: ZEND_BEGIN_ARG_INFO(arginfo_dba_exists, 0)
! 74: ZEND_ARG_INFO(0, key)
! 75: ZEND_ARG_INFO(0, handle)
! 76: ZEND_END_ARG_INFO()
! 77:
! 78: ZEND_BEGIN_ARG_INFO_EX(arginfo_dba_fetch, 0, 0, 2)
! 79: ZEND_ARG_INFO(0, key)
! 80: ZEND_ARG_INFO(0, skip)
! 81: ZEND_ARG_INFO(0, handle)
! 82: ZEND_END_ARG_INFO()
! 83:
! 84: ZEND_BEGIN_ARG_INFO(arginfo_dba_key_split, 0)
! 85: ZEND_ARG_INFO(0, key)
! 86: ZEND_END_ARG_INFO()
! 87:
! 88: ZEND_BEGIN_ARG_INFO(arginfo_dba_firstkey, 0)
! 89: ZEND_ARG_INFO(0, handle)
! 90: ZEND_END_ARG_INFO()
! 91:
! 92: ZEND_BEGIN_ARG_INFO(arginfo_dba_nextkey, 0)
! 93: ZEND_ARG_INFO(0, handle)
! 94: ZEND_END_ARG_INFO()
! 95:
! 96: ZEND_BEGIN_ARG_INFO(arginfo_dba_delete, 0)
! 97: ZEND_ARG_INFO(0, key)
! 98: ZEND_ARG_INFO(0, handle)
! 99: ZEND_END_ARG_INFO()
! 100:
! 101: ZEND_BEGIN_ARG_INFO(arginfo_dba_insert, 0)
! 102: ZEND_ARG_INFO(0, key)
! 103: ZEND_ARG_INFO(0, value)
! 104: ZEND_ARG_INFO(0, handle)
! 105: ZEND_END_ARG_INFO()
! 106:
! 107: ZEND_BEGIN_ARG_INFO(arginfo_dba_replace, 0)
! 108: ZEND_ARG_INFO(0, key)
! 109: ZEND_ARG_INFO(0, value)
! 110: ZEND_ARG_INFO(0, handle)
! 111: ZEND_END_ARG_INFO()
! 112:
! 113: ZEND_BEGIN_ARG_INFO(arginfo_dba_optimize, 0)
! 114: ZEND_ARG_INFO(0, handle)
! 115: ZEND_END_ARG_INFO()
! 116:
! 117: ZEND_BEGIN_ARG_INFO(arginfo_dba_sync, 0)
! 118: ZEND_ARG_INFO(0, handle)
! 119: ZEND_END_ARG_INFO()
! 120:
! 121: ZEND_BEGIN_ARG_INFO_EX(arginfo_dba_handlers, 0, 0, 0)
! 122: ZEND_ARG_INFO(0, full_info)
! 123: ZEND_END_ARG_INFO()
! 124:
! 125: ZEND_BEGIN_ARG_INFO(arginfo_dba_list, 0)
! 126: ZEND_END_ARG_INFO()
! 127:
! 128: /* }}} */
! 129:
! 130: /* {{{ dba_functions[]
! 131: */
! 132: const zend_function_entry dba_functions[] = {
! 133: PHP_FE(dba_open, arginfo_dba_open)
! 134: PHP_FE(dba_popen, arginfo_dba_popen)
! 135: PHP_FE(dba_close, arginfo_dba_close)
! 136: PHP_FE(dba_delete, arginfo_dba_delete)
! 137: PHP_FE(dba_exists, arginfo_dba_exists)
! 138: PHP_FE(dba_fetch, arginfo_dba_fetch)
! 139: PHP_FE(dba_insert, arginfo_dba_insert)
! 140: PHP_FE(dba_replace, arginfo_dba_replace)
! 141: PHP_FE(dba_firstkey, arginfo_dba_firstkey)
! 142: PHP_FE(dba_nextkey, arginfo_dba_nextkey)
! 143: PHP_FE(dba_optimize, arginfo_dba_optimize)
! 144: PHP_FE(dba_sync, arginfo_dba_sync)
! 145: PHP_FE(dba_handlers, arginfo_dba_handlers)
! 146: PHP_FE(dba_list, arginfo_dba_list)
! 147: PHP_FE(dba_key_split, arginfo_dba_key_split)
! 148: PHP_FE_END
! 149: };
! 150: /* }}} */
! 151:
! 152: PHP_MINIT_FUNCTION(dba);
! 153: PHP_MSHUTDOWN_FUNCTION(dba);
! 154: PHP_MINFO_FUNCTION(dba);
! 155:
! 156: ZEND_BEGIN_MODULE_GLOBALS(dba)
! 157: char *default_handler;
! 158: dba_handler *default_hptr;
! 159: ZEND_END_MODULE_GLOBALS(dba)
! 160:
! 161: ZEND_DECLARE_MODULE_GLOBALS(dba)
! 162:
! 163: #ifdef ZTS
! 164: #define DBA_G(v) TSRMG(dba_globals_id, zend_dba_globals *, v)
! 165: #else
! 166: #define DBA_G(v) (dba_globals.v)
! 167: #endif
! 168:
! 169: static PHP_GINIT_FUNCTION(dba);
! 170:
! 171: zend_module_entry dba_module_entry = {
! 172: STANDARD_MODULE_HEADER,
! 173: "dba",
! 174: dba_functions,
! 175: PHP_MINIT(dba),
! 176: PHP_MSHUTDOWN(dba),
! 177: NULL,
! 178: NULL,
! 179: PHP_MINFO(dba),
! 180: NO_VERSION_YET,
! 181: PHP_MODULE_GLOBALS(dba),
! 182: PHP_GINIT(dba),
! 183: NULL,
! 184: NULL,
! 185: STANDARD_MODULE_PROPERTIES_EX
! 186: };
! 187:
! 188: #ifdef COMPILE_DL_DBA
! 189: ZEND_GET_MODULE(dba)
! 190: #endif
! 191:
! 192: /* {{{ macromania */
! 193:
! 194: #define DBA_ID_PARS \
! 195: zval *id; \
! 196: dba_info *info = NULL; \
! 197: int ac = ZEND_NUM_ARGS()
! 198:
! 199: /* these are used to get the standard arguments */
! 200:
! 201: /* {{{ php_dba_myke_key */
! 202: static size_t php_dba_make_key(zval *key, char **key_str, char **key_free TSRMLS_DC)
! 203: {
! 204: if (Z_TYPE_P(key) == IS_ARRAY) {
! 205: zval **group, **name;
! 206: HashPosition pos;
! 207: size_t len;
! 208:
! 209: if (zend_hash_num_elements(Z_ARRVAL_P(key)) != 2) {
! 210: php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "Key does not have exactly two elements: (key, name)");
! 211: return -1;
! 212: }
! 213: zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(key), &pos);
! 214: zend_hash_get_current_data_ex(Z_ARRVAL_P(key), (void **) &group, &pos);
! 215: zend_hash_move_forward_ex(Z_ARRVAL_P(key), &pos);
! 216: zend_hash_get_current_data_ex(Z_ARRVAL_P(key), (void **) &name, &pos);
! 217: convert_to_string_ex(group);
! 218: convert_to_string_ex(name);
! 219: if (Z_STRLEN_PP(group) == 0) {
! 220: *key_str = Z_STRVAL_PP(name);
! 221: *key_free = NULL;
! 222: return Z_STRLEN_PP(name);
! 223: }
! 224: len = spprintf(key_str, 0, "[%s]%s", Z_STRVAL_PP(group), Z_STRVAL_PP(name));
! 225: *key_free = *key_str;
! 226: return len;
! 227: } else {
! 228: *key_free = NULL;
! 229:
! 230: convert_to_string(key);
! 231: *key_str = Z_STRVAL_P(key);
! 232:
! 233: return Z_STRLEN_P(key);
! 234: }
! 235: }
! 236: /* }}} */
! 237:
! 238: #define DBA_GET2 \
! 239: zval *key; \
! 240: char *key_str, *key_free; \
! 241: size_t key_len; \
! 242: if (zend_parse_parameters(ac TSRMLS_CC, "zr", &key, &id) == FAILURE) { \
! 243: return; \
! 244: } \
! 245: if ((key_len = php_dba_make_key(key, &key_str, &key_free TSRMLS_CC)) == 0) {\
! 246: RETURN_FALSE; \
! 247: }
! 248:
! 249: #define DBA_GET2_3 \
! 250: zval *key; \
! 251: char *key_str, *key_free; \
! 252: size_t key_len; \
! 253: long skip = 0; \
! 254: switch(ac) { \
! 255: case 2: \
! 256: if (zend_parse_parameters(ac TSRMLS_CC, "zr", &key, &id) == FAILURE) { \
! 257: return; \
! 258: } \
! 259: break; \
! 260: case 3: \
! 261: if (zend_parse_parameters(ac TSRMLS_CC, "zlr", &key, &skip, &id) == FAILURE) { \
! 262: return; \
! 263: } \
! 264: break; \
! 265: default: \
! 266: WRONG_PARAM_COUNT; \
! 267: } \
! 268: if ((key_len = php_dba_make_key(key, &key_str, &key_free TSRMLS_CC)) == 0) {\
! 269: RETURN_FALSE; \
! 270: }
! 271:
! 272:
! 273: #define DBA_FETCH_RESOURCE(info, id) \
! 274: ZEND_FETCH_RESOURCE2(info, dba_info *, id, -1, "DBA identifier", le_db, le_pdb);
! 275:
! 276: #define DBA_ID_GET2 DBA_ID_PARS; DBA_GET2; DBA_FETCH_RESOURCE(info, &id)
! 277: #define DBA_ID_GET2_3 DBA_ID_PARS; DBA_GET2_3; DBA_FETCH_RESOURCE(info, &id)
! 278:
! 279: #define DBA_ID_DONE \
! 280: if (key_free) efree(key_free)
! 281: /* a DBA handler must have specific routines */
! 282:
! 283: #define DBA_NAMED_HND(alias, name, flags) \
! 284: {\
! 285: #alias, flags, dba_open_##name, dba_close_##name, dba_fetch_##name, dba_update_##name, \
! 286: dba_exists_##name, dba_delete_##name, dba_firstkey_##name, dba_nextkey_##name, \
! 287: dba_optimize_##name, dba_sync_##name, dba_info_##name \
! 288: },
! 289:
! 290: #define DBA_HND(name, flags) DBA_NAMED_HND(name, name, flags)
! 291:
! 292: /* check whether the user has write access */
! 293: #define DBA_WRITE_CHECK \
! 294: if(info->mode != DBA_WRITER && info->mode != DBA_TRUNC && info->mode != DBA_CREAT) { \
! 295: php_error_docref(NULL TSRMLS_CC, E_WARNING, "You cannot perform a modification to a database without proper access"); \
! 296: RETURN_FALSE; \
! 297: }
! 298:
! 299: /* }}} */
! 300:
! 301: /* {{{ globals */
! 302:
! 303: static dba_handler handler[] = {
! 304: #if DBA_GDBM
! 305: DBA_HND(gdbm, DBA_LOCK_EXT) /* Locking done in library if set */
! 306: #endif
! 307: #if DBA_DBM
! 308: DBA_HND(dbm, DBA_LOCK_ALL) /* No lock in lib */
! 309: #endif
! 310: #if DBA_NDBM
! 311: DBA_HND(ndbm, DBA_LOCK_ALL) /* Could be done in library: filemode = 0644 + S_ENFMT */
! 312: #endif
! 313: #if DBA_CDB
! 314: DBA_HND(cdb, DBA_STREAM_OPEN|DBA_LOCK_ALL) /* No lock in lib */
! 315: #endif
! 316: #if DBA_CDB_BUILTIN
! 317: DBA_NAMED_HND(cdb_make, cdb, DBA_STREAM_OPEN|DBA_LOCK_ALL) /* No lock in lib */
! 318: #endif
! 319: #if DBA_DB1
! 320: DBA_HND(db1, DBA_LOCK_ALL) /* No lock in lib */
! 321: #endif
! 322: #if DBA_DB2
! 323: DBA_HND(db2, DBA_LOCK_ALL) /* No lock in lib */
! 324: #endif
! 325: #if DBA_DB3
! 326: DBA_HND(db3, DBA_LOCK_ALL) /* No lock in lib */
! 327: #endif
! 328: #if DBA_DB4
! 329: DBA_HND(db4, DBA_LOCK_ALL) /* No lock in lib */
! 330: #endif
! 331: #if DBA_INIFILE
! 332: DBA_HND(inifile, DBA_STREAM_OPEN|DBA_LOCK_ALL|DBA_CAST_AS_FD) /* No lock in lib */
! 333: #endif
! 334: #if DBA_FLATFILE
! 335: DBA_HND(flatfile, DBA_STREAM_OPEN|DBA_LOCK_ALL|DBA_NO_APPEND) /* No lock in lib */
! 336: #endif
! 337: #if DBA_QDBM
! 338: DBA_HND(qdbm, DBA_LOCK_EXT)
! 339: #endif
! 340: { NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
! 341: };
! 342:
! 343: #if DBA_FLATFILE
! 344: #define DBA_DEFAULT "flatfile"
! 345: #elif DBA_DB4
! 346: #define DBA_DEFAULT "db4"
! 347: #elif DBA_DB3
! 348: #define DBA_DEFAULT "db3"
! 349: #elif DBA_DB2
! 350: #define DBA_DEFAULT "db2"
! 351: #elif DBA_DB1
! 352: #define DBA_DEFAULT "db1"
! 353: #elif DBA_GDBM
! 354: #define DBA_DEFAULT "gdbm"
! 355: #elif DBA_NBBM
! 356: #define DBA_DEFAULT "ndbm"
! 357: #elif DBA_DBM
! 358: #define DBA_DEFAULT "dbm"
! 359: #elif DBA_QDBM
! 360: #define DBA_DEFAULT "qdbm"
! 361: #else
! 362: #define DBA_DEFAULT ""
! 363: #endif
! 364: /* cdb/cdb_make and ini are no option here */
! 365:
! 366: static int le_db;
! 367: static int le_pdb;
! 368: /* }}} */
! 369:
! 370: /* {{{ dba_fetch_resource
! 371: PHPAPI void dba_fetch_resource(dba_info **pinfo, zval **id TSRMLS_DC)
! 372: {
! 373: dba_info *info;
! 374: DBA_ID_FETCH
! 375: *pinfo = info;
! 376: }
! 377: */
! 378: /* }}} */
! 379:
! 380: /* {{{ dba_get_handler
! 381: PHPAPI dba_handler *dba_get_handler(const char* handler_name)
! 382: {
! 383: dba_handler *hptr;
! 384: for (hptr = handler; hptr->name && strcasecmp(hptr->name, handler_name); hptr++);
! 385: return hptr;
! 386: }
! 387: */
! 388: /* }}} */
! 389:
! 390: /* {{{ dba_close
! 391: */
! 392: static void dba_close(dba_info *info TSRMLS_DC)
! 393: {
! 394: if (info->hnd) {
! 395: info->hnd->close(info TSRMLS_CC);
! 396: }
! 397: if (info->path) {
! 398: pefree(info->path, info->flags&DBA_PERSISTENT);
! 399: }
! 400: if (info->fp && info->fp!=info->lock.fp) {
! 401: if(info->flags&DBA_PERSISTENT) {
! 402: php_stream_pclose(info->fp);
! 403: } else {
! 404: php_stream_close(info->fp);
! 405: }
! 406: }
! 407: if (info->lock.fp) {
! 408: if(info->flags&DBA_PERSISTENT) {
! 409: php_stream_pclose(info->lock.fp);
! 410: } else {
! 411: php_stream_close(info->lock.fp);
! 412: }
! 413: }
! 414: if (info->lock.name) {
! 415: pefree(info->lock.name, info->flags&DBA_PERSISTENT);
! 416: }
! 417: pefree(info, info->flags&DBA_PERSISTENT);
! 418: }
! 419: /* }}} */
! 420:
! 421: /* {{{ dba_close_rsrc
! 422: */
! 423: static void dba_close_rsrc(zend_rsrc_list_entry *rsrc TSRMLS_DC)
! 424: {
! 425: dba_info *info = (dba_info *)rsrc->ptr;
! 426:
! 427: dba_close(info TSRMLS_CC);
! 428: }
! 429: /* }}} */
! 430:
! 431: /* {{{ dba_close_pe_rsrc_deleter */
! 432: int dba_close_pe_rsrc_deleter(zend_rsrc_list_entry *le, void *pDba TSRMLS_DC)
! 433: {
! 434: return le->ptr == pDba;
! 435: }
! 436: /* }}} */
! 437:
! 438: /* {{{ dba_close_pe_rsrc */
! 439: static void dba_close_pe_rsrc(zend_rsrc_list_entry *rsrc TSRMLS_DC)
! 440: {
! 441: dba_info *info = (dba_info *)rsrc->ptr;
! 442:
! 443: /* closes the resource by calling dba_close_rsrc() */
! 444: zend_hash_apply_with_argument(&EG(persistent_list), (apply_func_arg_t) dba_close_pe_rsrc_deleter, info TSRMLS_CC);
! 445: }
! 446: /* }}} */
! 447:
! 448: /* {{{ PHP_INI
! 449: */
! 450: ZEND_INI_MH(OnUpdateDefaultHandler)
! 451: {
! 452: dba_handler *hptr;
! 453:
! 454: if (!strlen(new_value)) {
! 455: DBA_G(default_hptr) = NULL;
! 456: return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
! 457: }
! 458:
! 459: for (hptr = handler; hptr->name && strcasecmp(hptr->name, new_value); hptr++);
! 460:
! 461: if (!hptr->name) {
! 462: php_error_docref(NULL TSRMLS_CC, E_WARNING, "No such handler: %s", new_value);
! 463: return FAILURE;
! 464: }
! 465: DBA_G(default_hptr) = hptr;
! 466: return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
! 467: }
! 468:
! 469: PHP_INI_BEGIN()
! 470: STD_PHP_INI_ENTRY("dba.default_handler", DBA_DEFAULT, PHP_INI_ALL, OnUpdateDefaultHandler, default_handler, zend_dba_globals, dba_globals)
! 471: PHP_INI_END()
! 472: /* }}} */
! 473:
! 474: /* {{{ PHP_GINIT_FUNCTION
! 475: */
! 476: static PHP_GINIT_FUNCTION(dba)
! 477: {
! 478: dba_globals->default_handler = "";
! 479: dba_globals->default_hptr = NULL;
! 480: }
! 481: /* }}} */
! 482:
! 483: /* {{{ PHP_MINIT_FUNCTION
! 484: */
! 485: PHP_MINIT_FUNCTION(dba)
! 486: {
! 487: REGISTER_INI_ENTRIES();
! 488: le_db = zend_register_list_destructors_ex(dba_close_rsrc, NULL, "dba", module_number);
! 489: le_pdb = zend_register_list_destructors_ex(dba_close_pe_rsrc, dba_close_rsrc, "dba persistent", module_number);
! 490: return SUCCESS;
! 491: }
! 492: /* }}} */
! 493:
! 494: /* {{{ PHP_MSHUTDOWN_FUNCTION
! 495: */
! 496: PHP_MSHUTDOWN_FUNCTION(dba)
! 497: {
! 498: UNREGISTER_INI_ENTRIES();
! 499: return SUCCESS;
! 500: }
! 501: /* }}} */
! 502:
! 503: #include "ext/standard/php_smart_str.h"
! 504:
! 505: /* {{{ PHP_MINFO_FUNCTION
! 506: */
! 507: PHP_MINFO_FUNCTION(dba)
! 508: {
! 509: dba_handler *hptr;
! 510: smart_str handlers = {0};
! 511:
! 512: for(hptr = handler; hptr->name; hptr++) {
! 513: smart_str_appends(&handlers, hptr->name);
! 514: smart_str_appendc(&handlers, ' ');
! 515: }
! 516:
! 517: php_info_print_table_start();
! 518: php_info_print_table_row(2, "DBA support", "enabled");
! 519: if (handlers.c) {
! 520: smart_str_0(&handlers);
! 521: php_info_print_table_row(2, "Supported handlers", handlers.c);
! 522: smart_str_free(&handlers);
! 523: } else {
! 524: php_info_print_table_row(2, "Supported handlers", "none");
! 525: }
! 526: php_info_print_table_end();
! 527: DISPLAY_INI_ENTRIES();
! 528: }
! 529: /* }}} */
! 530:
! 531: /* {{{ php_dba_update
! 532: */
! 533: static void php_dba_update(INTERNAL_FUNCTION_PARAMETERS, int mode)
! 534: {
! 535: char *v;
! 536: int val_len;
! 537: zval *id;
! 538: dba_info *info = NULL;
! 539: int ac = ZEND_NUM_ARGS();
! 540: zval *key;
! 541: char *val;
! 542: char *key_str, *key_free;
! 543: size_t key_len;
! 544:
! 545: if (zend_parse_parameters(ac TSRMLS_CC, "zsr", &key, &val, &val_len, &id) == FAILURE) {
! 546: return;
! 547: }
! 548:
! 549: if ((key_len = php_dba_make_key(key, &key_str, &key_free TSRMLS_CC)) == 0) {
! 550: RETURN_FALSE;
! 551: }
! 552:
! 553: DBA_FETCH_RESOURCE(info, &id);
! 554:
! 555: DBA_WRITE_CHECK;
! 556:
! 557: if (PG(magic_quotes_runtime)) {
! 558: v = estrndup(val, val_len);
! 559: php_stripslashes(v, &val_len TSRMLS_CC);
! 560: if (info->hnd->update(info, key_str, key_len, v, val_len, mode TSRMLS_CC) == SUCCESS) {
! 561: efree(v);
! 562: DBA_ID_DONE;
! 563: RETURN_TRUE;
! 564: }
! 565: efree(v);
! 566: } else {
! 567: if (info->hnd->update(info, key_str, key_len, val, val_len, mode TSRMLS_CC) == SUCCESS) {
! 568: DBA_ID_DONE;
! 569: RETURN_TRUE;
! 570: }
! 571: }
! 572:
! 573: DBA_ID_DONE;
! 574: RETURN_FALSE;
! 575: }
! 576: /* }}} */
! 577:
! 578: #define FREENOW if(args) efree(args); if(key) efree(key)
! 579:
! 580: /* {{{ php_find_dbm
! 581: */
! 582: dba_info *php_dba_find(const char* path TSRMLS_DC)
! 583: {
! 584: zend_rsrc_list_entry *le;
! 585: dba_info *info;
! 586: int numitems, i;
! 587:
! 588: numitems = zend_hash_next_free_element(&EG(regular_list));
! 589: for (i=1; i<numitems; i++) {
! 590: if (zend_hash_index_find(&EG(regular_list), i, (void **) &le)==FAILURE) {
! 591: continue;
! 592: }
! 593: if (Z_TYPE_P(le) == le_db || Z_TYPE_P(le) == le_pdb) {
! 594: info = (dba_info *)(le->ptr);
! 595: if (!strcmp(info->path, path)) {
! 596: return (dba_info *)(le->ptr);
! 597: }
! 598: }
! 599: }
! 600:
! 601: return NULL;
! 602: }
! 603: /* }}} */
! 604:
! 605: /* {{{ php_dba_open
! 606: */
! 607: static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
! 608: {
! 609: zval ***args = (zval ***) NULL;
! 610: int ac = ZEND_NUM_ARGS();
! 611: dba_mode_t modenr;
! 612: dba_info *info, *other;
! 613: dba_handler *hptr;
! 614: char *key = NULL, *error = NULL;
! 615: int keylen = 0;
! 616: int i;
! 617: int lock_mode, lock_flag, lock_dbf = 0;
! 618: char *file_mode;
! 619: char mode[4], *pmode, *lock_file_mode = NULL;
! 620: int persistent_flag = persistent ? STREAM_OPEN_PERSISTENT : 0;
! 621: char *opened_path, *lock_name;
! 622:
! 623: if(ac < 2) {
! 624: WRONG_PARAM_COUNT;
! 625: }
! 626:
! 627: /* we pass additional args to the respective handler */
! 628: args = safe_emalloc(ac, sizeof(zval *), 0);
! 629: if (zend_get_parameters_array_ex(ac, args) != SUCCESS) {
! 630: FREENOW;
! 631: WRONG_PARAM_COUNT;
! 632: }
! 633:
! 634: /* we only take string arguments */
! 635: for (i = 0; i < ac; i++) {
! 636: convert_to_string_ex(args[i]);
! 637: keylen += Z_STRLEN_PP(args[i]);
! 638: }
! 639:
! 640: if (persistent) {
! 641: zend_rsrc_list_entry *le;
! 642:
! 643: /* calculate hash */
! 644: key = safe_emalloc(keylen, 1, 1);
! 645: key[keylen] = '\0';
! 646: keylen = 0;
! 647:
! 648: for(i = 0; i < ac; i++) {
! 649: memcpy(key+keylen, Z_STRVAL_PP(args[i]), Z_STRLEN_PP(args[i]));
! 650: keylen += Z_STRLEN_PP(args[i]);
! 651: }
! 652:
! 653: /* try to find if we already have this link in our persistent list */
! 654: if (zend_hash_find(&EG(persistent_list), key, keylen+1, (void **) &le) == SUCCESS) {
! 655: FREENOW;
! 656:
! 657: if (Z_TYPE_P(le) != le_pdb) {
! 658: RETURN_FALSE;
! 659: }
! 660:
! 661: info = (dba_info *)le->ptr;
! 662:
! 663: ZEND_REGISTER_RESOURCE(return_value, info, le_pdb);
! 664: return;
! 665: }
! 666: }
! 667:
! 668: if (ac==2) {
! 669: hptr = DBA_G(default_hptr);
! 670: if (!hptr) {
! 671: php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "No default handler selected");
! 672: FREENOW;
! 673: RETURN_FALSE;
! 674: }
! 675: } else {
! 676: for (hptr = handler; hptr->name && strcasecmp(hptr->name, Z_STRVAL_PP(args[2])); hptr++);
! 677: }
! 678:
! 679: if (!hptr->name) {
! 680: php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "No such handler: %s", Z_STRVAL_PP(args[2]));
! 681: FREENOW;
! 682: RETURN_FALSE;
! 683: }
! 684:
! 685: /* Check mode: [rwnc][fl]?t?
! 686: * r: Read
! 687: * w: Write
! 688: * n: Create/Truncate
! 689: * c: Create
! 690: *
! 691: * d: force lock on database file
! 692: * l: force lock on lck file
! 693: * -: ignore locking
! 694: *
! 695: * t: test open database, warning if locked
! 696: */
! 697: strlcpy(mode, Z_STRVAL_PP(args[1]), sizeof(mode));
! 698: pmode = &mode[0];
! 699: if (pmode[0] && (pmode[1]=='d' || pmode[1]=='l' || pmode[1]=='-')) { /* force lock on db file or lck file or disable locking */
! 700: switch (pmode[1]) {
! 701: case 'd':
! 702: lock_dbf = 1;
! 703: if ((hptr->flags & DBA_LOCK_ALL) == 0) {
! 704: lock_flag = (hptr->flags & DBA_LOCK_ALL);
! 705: break;
! 706: }
! 707: /* no break */
! 708: case 'l':
! 709: lock_flag = DBA_LOCK_ALL;
! 710: if ((hptr->flags & DBA_LOCK_ALL) == 0) {
! 711: php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_NOTICE, "Handler %s does locking internally", hptr->name);
! 712: }
! 713: break;
! 714: default:
! 715: case '-':
! 716: if ((hptr->flags & DBA_LOCK_ALL) == 0) {
! 717: php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Locking cannot be disabled for handler %s", hptr->name);
! 718: FREENOW;
! 719: RETURN_FALSE;
! 720: }
! 721: lock_flag = 0;
! 722: break;
! 723: }
! 724: } else {
! 725: lock_flag = (hptr->flags&DBA_LOCK_ALL);
! 726: lock_dbf = 1;
! 727: }
! 728: switch (*pmode++) {
! 729: case 'r':
! 730: modenr = DBA_READER;
! 731: lock_mode = (lock_flag & DBA_LOCK_READER) ? LOCK_SH : 0;
! 732: file_mode = "r";
! 733: break;
! 734: case 'w':
! 735: modenr = DBA_WRITER;
! 736: lock_mode = (lock_flag & DBA_LOCK_WRITER) ? LOCK_EX : 0;
! 737: file_mode = "r+b";
! 738: break;
! 739: case 'c':
! 740: modenr = DBA_CREAT;
! 741: lock_mode = (lock_flag & DBA_LOCK_CREAT) ? LOCK_EX : 0;
! 742: if (lock_mode) {
! 743: if (lock_dbf) {
! 744: /* the create/append check will be done on the lock
! 745: * when the lib opens the file it is already created
! 746: */
! 747: file_mode = "r+b"; /* read & write, seek 0 */
! 748: lock_file_mode = "a+b"; /* append */
! 749: } else {
! 750: file_mode = "a+b"; /* append */
! 751: lock_file_mode = "w+b"; /* create/truncate */
! 752: }
! 753: } else {
! 754: file_mode = "a+b";
! 755: }
! 756: /* In case of the 'a+b' append mode, the handler is responsible
! 757: * to handle any rewind problems (see flatfile handler).
! 758: */
! 759: break;
! 760: case 'n':
! 761: modenr = DBA_TRUNC;
! 762: lock_mode = (lock_flag & DBA_LOCK_TRUNC) ? LOCK_EX : 0;
! 763: file_mode = "w+b";
! 764: break;
! 765: default:
! 766: php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Illegal DBA mode");
! 767: FREENOW;
! 768: RETURN_FALSE;
! 769: }
! 770: if (!lock_file_mode) {
! 771: lock_file_mode = file_mode;
! 772: }
! 773: if (*pmode=='d' || *pmode=='l' || *pmode=='-') {
! 774: pmode++; /* done already - skip here */
! 775: }
! 776: if (*pmode=='t') {
! 777: pmode++;
! 778: if (!lock_flag) {
! 779: php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "You cannot combine modifiers - (no lock) and t (test lock)");
! 780: FREENOW;
! 781: RETURN_FALSE;
! 782: }
! 783: if (!lock_mode) {
! 784: if ((hptr->flags & DBA_LOCK_ALL) == 0) {
! 785: php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Handler %s uses its own locking which doesn't support mode modifier t (test lock)", hptr->name);
! 786: FREENOW;
! 787: RETURN_FALSE;
! 788: } else {
! 789: php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Handler %s doesn't uses locking for this mode which makes modifier t (test lock) obsolete", hptr->name);
! 790: FREENOW;
! 791: RETURN_FALSE;
! 792: }
! 793: } else {
! 794: lock_mode |= LOCK_NB; /* test =: non blocking */
! 795: }
! 796: }
! 797: if (*pmode) {
! 798: php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Illegal DBA mode");
! 799: FREENOW;
! 800: RETURN_FALSE;
! 801: }
! 802:
! 803: info = pemalloc(sizeof(dba_info), persistent);
! 804: memset(info, 0, sizeof(dba_info));
! 805: info->path = pestrdup(Z_STRVAL_PP(args[0]), persistent);
! 806: info->mode = modenr;
! 807: info->argc = ac - 3;
! 808: info->argv = args + 3;
! 809: info->flags = (hptr->flags & ~DBA_LOCK_ALL) | (lock_flag & DBA_LOCK_ALL) | (persistent ? DBA_PERSISTENT : 0);
! 810: info->lock.mode = lock_mode;
! 811:
! 812: /* if any open call is a locking call:
! 813: * check if we already habe a locking call open that should block this call
! 814: * the problem is some systems would allow read during write
! 815: */
! 816: if (hptr->flags & DBA_LOCK_ALL) {
! 817: if ((other = php_dba_find(info->path TSRMLS_CC)) != NULL) {
! 818: if ( ( (lock_mode&LOCK_EX) && (other->lock.mode&(LOCK_EX|LOCK_SH)) )
! 819: || ( (other->lock.mode&LOCK_EX) && (lock_mode&(LOCK_EX|LOCK_SH)) )
! 820: ) {
! 821: error = "Unable to establish lock (database file already open)"; /* force failure exit */
! 822: }
! 823: }
! 824: }
! 825:
! 826: if (!error && lock_mode) {
! 827: if (lock_dbf) {
! 828: lock_name = Z_STRVAL_PP(args[0]);
! 829: } else {
! 830: spprintf(&lock_name, 0, "%s.lck", info->path);
! 831: if (!strcmp(file_mode, "r")) {
! 832: /* when in read only mode try to use existing .lck file first */
! 833: /* do not log errors for .lck file while in read ony mode on .lck file */
! 834: lock_file_mode = "rb";
! 835: info->lock.fp = php_stream_open_wrapper(lock_name, lock_file_mode, STREAM_MUST_SEEK|IGNORE_PATH|ENFORCE_SAFE_MODE|persistent_flag, &opened_path);
! 836: }
! 837: if (!info->lock.fp) {
! 838: /* when not in read mode or failed to open .lck file read only. now try again in create(write) mode and log errors */
! 839: lock_file_mode = "a+b";
! 840: } else {
! 841: if (!persistent) {
! 842: info->lock.name = opened_path;
! 843: } else {
! 844: info->lock.name = pestrdup(opened_path, persistent);
! 845: efree(opened_path);
! 846: }
! 847: }
! 848: }
! 849: if (!info->lock.fp) {
! 850: info->lock.fp = php_stream_open_wrapper(lock_name, lock_file_mode, STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH|ENFORCE_SAFE_MODE|persistent_flag, &opened_path);
! 851: if (info->lock.fp) {
! 852: if (lock_dbf) {
! 853: /* replace the path info with the real path of the opened file */
! 854: pefree(info->path, persistent);
! 855: info->path = pestrdup(opened_path, persistent);
! 856: }
! 857: /* now store the name of the lock */
! 858: if (!persistent) {
! 859: info->lock.name = opened_path;
! 860: } else {
! 861: info->lock.name = pestrdup(opened_path, persistent);
! 862: efree(opened_path);
! 863: }
! 864: }
! 865: }
! 866: if (!lock_dbf) {
! 867: efree(lock_name);
! 868: }
! 869: if (!info->lock.fp) {
! 870: dba_close(info TSRMLS_CC);
! 871: /* stream operation already wrote an error message */
! 872: FREENOW;
! 873: RETURN_FALSE;
! 874: }
! 875: if (!php_stream_supports_lock(info->lock.fp)) {
! 876: error = "Stream does not support locking";
! 877: }
! 878: if (php_stream_lock(info->lock.fp, lock_mode)) {
! 879: error = "Unable to establish lock"; /* force failure exit */
! 880: }
! 881: }
! 882:
! 883: /* centralised open stream for builtin */
! 884: if (!error && (hptr->flags&DBA_STREAM_OPEN)==DBA_STREAM_OPEN) {
! 885: if (info->lock.fp && lock_dbf) {
! 886: info->fp = info->lock.fp; /* use the same stream for locking and database access */
! 887: } else {
! 888: info->fp = php_stream_open_wrapper(info->path, file_mode, STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH|ENFORCE_SAFE_MODE|persistent_flag, NULL);
! 889: }
! 890: if (!info->fp) {
! 891: dba_close(info TSRMLS_CC);
! 892: /* stream operation already wrote an error message */
! 893: FREENOW;
! 894: RETURN_FALSE;
! 895: }
! 896: if (hptr->flags & (DBA_NO_APPEND|DBA_CAST_AS_FD)) {
! 897: /* Needed becasue some systems do not allow to write to the original
! 898: * file contents with O_APPEND being set.
! 899: */
! 900: if (SUCCESS != php_stream_cast(info->fp, PHP_STREAM_AS_FD, (void*)&info->fd, 1)) {
! 901: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not cast stream");
! 902: dba_close(info TSRMLS_CC);
! 903: FREENOW;
! 904: RETURN_FALSE;
! 905: #ifdef F_SETFL
! 906: } else if (modenr == DBA_CREAT) {
! 907: int flags = fcntl(info->fd, F_SETFL);
! 908: fcntl(info->fd, F_SETFL, flags & ~O_APPEND);
! 909: #endif
! 910: }
! 911:
! 912: }
! 913: }
! 914:
! 915: if (error || hptr->open(info, &error TSRMLS_CC) != SUCCESS) {
! 916: dba_close(info TSRMLS_CC);
! 917: php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Driver initialization failed for handler: %s%s%s", hptr->name, error?": ":"", error?error:"");
! 918: FREENOW;
! 919: RETURN_FALSE;
! 920: }
! 921:
! 922: info->hnd = hptr;
! 923: info->argc = 0;
! 924: info->argv = NULL;
! 925:
! 926: if (persistent) {
! 927: zend_rsrc_list_entry new_le;
! 928:
! 929: Z_TYPE(new_le) = le_pdb;
! 930: new_le.ptr = info;
! 931: if (zend_hash_update(&EG(persistent_list), key, keylen+1, &new_le, sizeof(zend_rsrc_list_entry), NULL) == FAILURE) {
! 932: dba_close(info TSRMLS_CC);
! 933: php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Could not register persistent resource");
! 934: FREENOW;
! 935: RETURN_FALSE;
! 936: }
! 937: }
! 938:
! 939: ZEND_REGISTER_RESOURCE(return_value, info, (persistent ? le_pdb : le_db));
! 940: FREENOW;
! 941: }
! 942: /* }}} */
! 943: #undef FREENOW
! 944:
! 945: /* {{{ proto resource dba_popen(string path, string mode [, string handlername, string ...])
! 946: Opens path using the specified handler in mode persistently */
! 947: PHP_FUNCTION(dba_popen)
! 948: {
! 949: php_dba_open(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
! 950: }
! 951: /* }}} */
! 952:
! 953: /* {{{ proto resource dba_open(string path, string mode [, string handlername, string ...])
! 954: Opens path using the specified handler in mode*/
! 955: PHP_FUNCTION(dba_open)
! 956: {
! 957: php_dba_open(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
! 958: }
! 959: /* }}} */
! 960:
! 961: /* {{{ proto void dba_close(resource handle)
! 962: Closes database */
! 963: PHP_FUNCTION(dba_close)
! 964: {
! 965: zval *id;
! 966: dba_info *info = NULL;
! 967:
! 968: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &id) == FAILURE) {
! 969: return;
! 970: }
! 971:
! 972: DBA_FETCH_RESOURCE(info, &id);
! 973:
! 974: zend_list_delete(Z_RESVAL_P(id));
! 975: }
! 976: /* }}} */
! 977:
! 978: /* {{{ proto bool dba_exists(string key, resource handle)
! 979: Checks, if the specified key exists */
! 980: PHP_FUNCTION(dba_exists)
! 981: {
! 982: DBA_ID_GET2;
! 983:
! 984: if(info->hnd->exists(info, key_str, key_len TSRMLS_CC) == SUCCESS) {
! 985: DBA_ID_DONE;
! 986: RETURN_TRUE;
! 987: }
! 988: DBA_ID_DONE;
! 989: RETURN_FALSE;
! 990: }
! 991: /* }}} */
! 992:
! 993: /* {{{ proto string dba_fetch(string key, [int skip ,] resource handle)
! 994: Fetches the data associated with key */
! 995: PHP_FUNCTION(dba_fetch)
! 996: {
! 997: char *val;
! 998: int len = 0;
! 999: DBA_ID_GET2_3;
! 1000:
! 1001: if (ac==3) {
! 1002: if (!strcmp(info->hnd->name, "cdb")) {
! 1003: if (skip < 0) {
! 1004: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Handler %s accepts only skip values greater than or equal to zero, using skip=0", info->hnd->name);
! 1005: skip = 0;
! 1006: }
! 1007: } else if (!strcmp(info->hnd->name, "inifile")) {
! 1008: /* "-1" is compareable to 0 but allows a non restrictive
! 1009: * access which is fater. For example 'inifile' uses this
! 1010: * to allow faster access when the key was already found
! 1011: * using firstkey/nextkey. However explicitly setting the
! 1012: * value to 0 ensures the first value.
! 1013: */
! 1014: if (skip < -1) {
! 1015: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Handler %s accepts only skip value -1 and greater, using skip=0", info->hnd->name);
! 1016: skip = 0;
! 1017: }
! 1018: } else {
! 1019: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Handler %s does not support optional skip parameter, the value will be ignored", info->hnd->name);
! 1020: skip = 0;
! 1021: }
! 1022: } else {
! 1023: skip = 0;
! 1024: }
! 1025: if((val = info->hnd->fetch(info, key_str, key_len, skip, &len TSRMLS_CC)) != NULL) {
! 1026: if (val && PG(magic_quotes_runtime)) {
! 1027: val = php_addslashes(val, len, &len, 1 TSRMLS_CC);
! 1028: }
! 1029: DBA_ID_DONE;
! 1030: RETURN_STRINGL(val, len, 0);
! 1031: }
! 1032: DBA_ID_DONE;
! 1033: RETURN_FALSE;
! 1034: }
! 1035: /* }}} */
! 1036:
! 1037: /* {{{ proto array|false dba_key_split(string key)
! 1038: Splits an inifile key into an array of the form array(0=>group,1=>value_name) but returns false if input is false or null */
! 1039: PHP_FUNCTION(dba_key_split)
! 1040: {
! 1041: zval *zkey;
! 1042: char *key, *name;
! 1043: int key_len;
! 1044:
! 1045: if (ZEND_NUM_ARGS() != 1) {
! 1046: WRONG_PARAM_COUNT;
! 1047: }
! 1048: if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "z", &zkey) == SUCCESS) {
! 1049: if (Z_TYPE_P(zkey) == IS_NULL || (Z_TYPE_P(zkey) == IS_BOOL && !Z_LVAL_P(zkey))) {
! 1050: RETURN_BOOL(0);
! 1051: }
! 1052: }
! 1053: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &key_len) == FAILURE) {
! 1054: RETURN_BOOL(0);
! 1055: }
! 1056: array_init(return_value);
! 1057: if (key[0] == '[' && (name = strchr(key, ']')) != NULL) {
! 1058: add_next_index_stringl(return_value, key+1, name - (key + 1), 1);
! 1059: add_next_index_stringl(return_value, name+1, key_len - (name - key + 1), 1);
! 1060: } else {
! 1061: add_next_index_stringl(return_value, "", 0, 1);
! 1062: add_next_index_stringl(return_value, key, key_len, 1);
! 1063: }
! 1064: }
! 1065: /* }}} */
! 1066:
! 1067: /* {{{ proto string dba_firstkey(resource handle)
! 1068: Resets the internal key pointer and returns the first key */
! 1069: PHP_FUNCTION(dba_firstkey)
! 1070: {
! 1071: char *fkey;
! 1072: int len;
! 1073: zval *id;
! 1074: dba_info *info = NULL;
! 1075:
! 1076: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &id) == FAILURE) {
! 1077: return;
! 1078: }
! 1079:
! 1080: DBA_FETCH_RESOURCE(info, &id);
! 1081:
! 1082: fkey = info->hnd->firstkey(info, &len TSRMLS_CC);
! 1083:
! 1084: if (fkey)
! 1085: RETURN_STRINGL(fkey, len, 0);
! 1086:
! 1087: RETURN_FALSE;
! 1088: }
! 1089: /* }}} */
! 1090:
! 1091: /* {{{ proto string dba_nextkey(resource handle)
! 1092: Returns the next key */
! 1093: PHP_FUNCTION(dba_nextkey)
! 1094: {
! 1095: char *nkey;
! 1096: int len;
! 1097: zval *id;
! 1098: dba_info *info = NULL;
! 1099:
! 1100: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &id) == FAILURE) {
! 1101: return;
! 1102: }
! 1103:
! 1104: DBA_FETCH_RESOURCE(info, &id);
! 1105:
! 1106: nkey = info->hnd->nextkey(info, &len TSRMLS_CC);
! 1107:
! 1108: if (nkey)
! 1109: RETURN_STRINGL(nkey, len, 0);
! 1110:
! 1111: RETURN_FALSE;
! 1112: }
! 1113: /* }}} */
! 1114:
! 1115: /* {{{ proto bool dba_delete(string key, resource handle)
! 1116: Deletes the entry associated with key
! 1117: If inifile: remove all other key lines */
! 1118: PHP_FUNCTION(dba_delete)
! 1119: {
! 1120: DBA_ID_GET2;
! 1121:
! 1122: DBA_WRITE_CHECK;
! 1123:
! 1124: if(info->hnd->delete(info, key_str, key_len TSRMLS_CC) == SUCCESS)
! 1125: {
! 1126: DBA_ID_DONE;
! 1127: RETURN_TRUE;
! 1128: }
! 1129: DBA_ID_DONE;
! 1130: RETURN_FALSE;
! 1131: }
! 1132: /* }}} */
! 1133:
! 1134: /* {{{ proto bool dba_insert(string key, string value, resource handle)
! 1135: If not inifile: Insert value as key, return false, if key exists already
! 1136: If inifile: Add vakue as key (next instance of key) */
! 1137: PHP_FUNCTION(dba_insert)
! 1138: {
! 1139: php_dba_update(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
! 1140: }
! 1141: /* }}} */
! 1142:
! 1143: /* {{{ proto bool dba_replace(string key, string value, resource handle)
! 1144: Inserts value as key, replaces key, if key exists already
! 1145: If inifile: remove all other key lines */
! 1146: PHP_FUNCTION(dba_replace)
! 1147: {
! 1148: php_dba_update(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
! 1149: }
! 1150: /* }}} */
! 1151:
! 1152: /* {{{ proto bool dba_optimize(resource handle)
! 1153: Optimizes (e.g. clean up, vacuum) database */
! 1154: PHP_FUNCTION(dba_optimize)
! 1155: {
! 1156: zval *id;
! 1157: dba_info *info = NULL;
! 1158:
! 1159: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &id) == FAILURE) {
! 1160: return;
! 1161: }
! 1162:
! 1163: DBA_FETCH_RESOURCE(info, &id);
! 1164:
! 1165: DBA_WRITE_CHECK;
! 1166:
! 1167: if (info->hnd->optimize(info TSRMLS_CC) == SUCCESS) {
! 1168: RETURN_TRUE;
! 1169: }
! 1170:
! 1171: RETURN_FALSE;
! 1172: }
! 1173: /* }}} */
! 1174:
! 1175: /* {{{ proto bool dba_sync(resource handle)
! 1176: Synchronizes database */
! 1177: PHP_FUNCTION(dba_sync)
! 1178: {
! 1179: zval *id;
! 1180: dba_info *info = NULL;
! 1181:
! 1182: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &id) == FAILURE) {
! 1183: return;
! 1184: }
! 1185:
! 1186: DBA_FETCH_RESOURCE(info, &id);
! 1187:
! 1188: if (info->hnd->sync(info TSRMLS_CC) == SUCCESS) {
! 1189: RETURN_TRUE;
! 1190: }
! 1191:
! 1192: RETURN_FALSE;
! 1193: }
! 1194: /* }}} */
! 1195:
! 1196: /* {{{ proto array dba_handlers([bool full_info])
! 1197: List configured database handlers */
! 1198: PHP_FUNCTION(dba_handlers)
! 1199: {
! 1200: dba_handler *hptr;
! 1201: zend_bool full_info = 0;
! 1202:
! 1203: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &full_info) == FAILURE) {
! 1204: RETURN_FALSE;
! 1205: }
! 1206:
! 1207: array_init(return_value);
! 1208:
! 1209: for(hptr = handler; hptr->name; hptr++) {
! 1210: if (full_info) {
! 1211: add_assoc_string(return_value, hptr->name, hptr->info(hptr, NULL TSRMLS_CC), 0);
! 1212: } else {
! 1213: add_next_index_string(return_value, hptr->name, 1);
! 1214: }
! 1215: }
! 1216: }
! 1217: /* }}} */
! 1218:
! 1219: /* {{{ proto array dba_list()
! 1220: List opened databases */
! 1221: PHP_FUNCTION(dba_list)
! 1222: {
! 1223: ulong numitems, i;
! 1224: zend_rsrc_list_entry *le;
! 1225: dba_info *info;
! 1226:
! 1227: if (zend_parse_parameters_none() == FAILURE) {
! 1228: RETURN_FALSE;
! 1229: }
! 1230:
! 1231: array_init(return_value);
! 1232:
! 1233: numitems = zend_hash_next_free_element(&EG(regular_list));
! 1234: for (i=1; i<numitems; i++) {
! 1235: if (zend_hash_index_find(&EG(regular_list), i, (void **) &le)==FAILURE) {
! 1236: continue;
! 1237: }
! 1238: if (Z_TYPE_P(le) == le_db || Z_TYPE_P(le) == le_pdb) {
! 1239: info = (dba_info *)(le->ptr);
! 1240: add_index_string(return_value, i, info->path, 1);
! 1241: }
! 1242: }
! 1243: }
! 1244: /* }}} */
! 1245:
! 1246: #endif /* HAVE_DBA */
! 1247:
! 1248: /*
! 1249: * Local variables:
! 1250: * tab-width: 4
! 1251: * c-basic-offset: 4
! 1252: * End:
! 1253: * vim600: sw=4 ts=4 fdm=marker
! 1254: * vim<600: sw=4 ts=4
! 1255: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>