Return to dba.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / dba |
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: */