Annotation of embedaddon/php/ext/dba/dba.c, revision 1.1.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>