xref: /PHP-5.3/ext/interbase/ibase_service.c (revision a2045ff3)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 5                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1997-2013 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: Ard Biesheuvel <a.k.biesheuvel@its.tudelft.nl>              |
16    +----------------------------------------------------------------------+
17  */
18 
19 /* $Id$ */
20 
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 
25 #include "php.h"
26 
27 #if HAVE_IBASE
28 
29 #include "php_interbase.h"
30 #include "php_ibase_includes.h"
31 
32 typedef struct {
33 	isc_svc_handle handle;
34 	char *hostname;
35 	char *username;
36 	long res_id;
37 } ibase_service;
38 
39 static int le_service;
40 
_php_ibase_free_service(zend_rsrc_list_entry * rsrc TSRMLS_DC)41 static void _php_ibase_free_service(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
42 {
43 	ibase_service *sv = (ibase_service *) rsrc->ptr;
44 
45 	if (isc_service_detach(IB_STATUS, &sv->handle)) {
46 		_php_ibase_error(TSRMLS_C);
47 	}
48 
49 	if (sv->hostname) {
50 		efree(sv->hostname);
51 	}
52 	if (sv->username) {
53 		efree(sv->username);
54 	}
55 
56 	efree(sv);
57 }
58 /* }}} */
59 
60 /* the svc api seems to get confused after an error has occurred,
61    so invalidate the handle on errors */
62 #define IBASE_SVC_ERROR(svm) \
63 	do { zend_list_delete(svm->res_id); _php_ibase_error(TSRMLS_C); } while (0)
64 
65 
php_ibase_service_minit(INIT_FUNC_ARGS)66 void php_ibase_service_minit(INIT_FUNC_ARGS) /* {{{ */
67 {
68 	le_service = zend_register_list_destructors_ex(_php_ibase_free_service, NULL,
69 	    "interbase service manager handle", module_number);
70 
71 	/* backup options */
72 	REGISTER_LONG_CONSTANT("IBASE_BKP_IGNORE_CHECKSUMS", isc_spb_bkp_ignore_checksums, CONST_PERSISTENT);
73 	REGISTER_LONG_CONSTANT("IBASE_BKP_IGNORE_LIMBO", isc_spb_bkp_ignore_limbo, CONST_PERSISTENT);
74 	REGISTER_LONG_CONSTANT("IBASE_BKP_METADATA_ONLY", isc_spb_bkp_metadata_only, CONST_PERSISTENT);
75 	REGISTER_LONG_CONSTANT("IBASE_BKP_NO_GARBAGE_COLLECT", isc_spb_bkp_no_garbage_collect, CONST_PERSISTENT);
76 	REGISTER_LONG_CONSTANT("IBASE_BKP_OLD_DESCRIPTIONS", isc_spb_bkp_old_descriptions, CONST_PERSISTENT);
77 	REGISTER_LONG_CONSTANT("IBASE_BKP_NON_TRANSPORTABLE", isc_spb_bkp_non_transportable, CONST_PERSISTENT);
78 	REGISTER_LONG_CONSTANT("IBASE_BKP_CONVERT", isc_spb_bkp_convert, CONST_PERSISTENT);
79 
80 	/* restore options */
81 	REGISTER_LONG_CONSTANT("IBASE_RES_DEACTIVATE_IDX", isc_spb_res_deactivate_idx, CONST_PERSISTENT);
82 	REGISTER_LONG_CONSTANT("IBASE_RES_NO_SHADOW", isc_spb_res_no_shadow, CONST_PERSISTENT);
83 	REGISTER_LONG_CONSTANT("IBASE_RES_NO_VALIDITY", isc_spb_res_no_validity, CONST_PERSISTENT);
84 	REGISTER_LONG_CONSTANT("IBASE_RES_ONE_AT_A_TIME", isc_spb_res_one_at_a_time, CONST_PERSISTENT);
85 	REGISTER_LONG_CONSTANT("IBASE_RES_REPLACE", isc_spb_res_replace, CONST_PERSISTENT);
86 	REGISTER_LONG_CONSTANT("IBASE_RES_CREATE", isc_spb_res_create, CONST_PERSISTENT);
87 	REGISTER_LONG_CONSTANT("IBASE_RES_USE_ALL_SPACE", isc_spb_res_use_all_space, CONST_PERSISTENT);
88 
89 	/* manage options */
90 	REGISTER_LONG_CONSTANT("IBASE_PRP_PAGE_BUFFERS", isc_spb_prp_page_buffers, CONST_PERSISTENT);
91 	REGISTER_LONG_CONSTANT("IBASE_PRP_SWEEP_INTERVAL", isc_spb_prp_sweep_interval, CONST_PERSISTENT);
92 	REGISTER_LONG_CONSTANT("IBASE_PRP_SHUTDOWN_DB", isc_spb_prp_shutdown_db, CONST_PERSISTENT);
93 	REGISTER_LONG_CONSTANT("IBASE_PRP_DENY_NEW_TRANSACTIONS", isc_spb_prp_deny_new_transactions, CONST_PERSISTENT);
94 	REGISTER_LONG_CONSTANT("IBASE_PRP_DENY_NEW_ATTACHMENTS", isc_spb_prp_deny_new_attachments, CONST_PERSISTENT);
95 	REGISTER_LONG_CONSTANT("IBASE_PRP_RESERVE_SPACE", isc_spb_prp_reserve_space, CONST_PERSISTENT);
96 	  REGISTER_LONG_CONSTANT("IBASE_PRP_RES_USE_FULL", isc_spb_prp_res_use_full, CONST_PERSISTENT);
97 	  REGISTER_LONG_CONSTANT("IBASE_PRP_RES", isc_spb_prp_res, CONST_PERSISTENT);
98 	REGISTER_LONG_CONSTANT("IBASE_PRP_WRITE_MODE", isc_spb_prp_write_mode, CONST_PERSISTENT);
99 	  REGISTER_LONG_CONSTANT("IBASE_PRP_WM_ASYNC", isc_spb_prp_wm_async, CONST_PERSISTENT);
100 	  REGISTER_LONG_CONSTANT("IBASE_PRP_WM_SYNC", isc_spb_prp_wm_sync, CONST_PERSISTENT);
101 	REGISTER_LONG_CONSTANT("IBASE_PRP_ACCESS_MODE", isc_spb_prp_access_mode, CONST_PERSISTENT);
102 	  REGISTER_LONG_CONSTANT("IBASE_PRP_AM_READONLY", isc_spb_prp_am_readonly, CONST_PERSISTENT);
103 	  REGISTER_LONG_CONSTANT("IBASE_PRP_AM_READWRITE", isc_spb_prp_am_readwrite, CONST_PERSISTENT);
104 	REGISTER_LONG_CONSTANT("IBASE_PRP_SET_SQL_DIALECT", isc_spb_prp_set_sql_dialect, CONST_PERSISTENT);
105 	REGISTER_LONG_CONSTANT("IBASE_PRP_ACTIVATE", isc_spb_prp_activate, CONST_PERSISTENT);
106 	REGISTER_LONG_CONSTANT("IBASE_PRP_DB_ONLINE", isc_spb_prp_db_online, CONST_PERSISTENT);
107 
108 	/* repair options */
109 	REGISTER_LONG_CONSTANT("IBASE_RPR_CHECK_DB", isc_spb_rpr_check_db, CONST_PERSISTENT);
110 	REGISTER_LONG_CONSTANT("IBASE_RPR_IGNORE_CHECKSUM", isc_spb_rpr_ignore_checksum, CONST_PERSISTENT);
111 	REGISTER_LONG_CONSTANT("IBASE_RPR_KILL_SHADOWS", isc_spb_rpr_kill_shadows, CONST_PERSISTENT);
112 	REGISTER_LONG_CONSTANT("IBASE_RPR_MEND_DB", isc_spb_rpr_mend_db, CONST_PERSISTENT);
113 	REGISTER_LONG_CONSTANT("IBASE_RPR_VALIDATE_DB", isc_spb_rpr_validate_db, CONST_PERSISTENT);
114 	  REGISTER_LONG_CONSTANT("IBASE_RPR_FULL", isc_spb_rpr_full, CONST_PERSISTENT);
115 	REGISTER_LONG_CONSTANT("IBASE_RPR_SWEEP_DB", isc_spb_rpr_sweep_db, CONST_PERSISTENT);
116 
117 	/* db info arguments */
118 	REGISTER_LONG_CONSTANT("IBASE_STS_DATA_PAGES", isc_spb_sts_data_pages, CONST_PERSISTENT);
119 	REGISTER_LONG_CONSTANT("IBASE_STS_DB_LOG", isc_spb_sts_db_log, CONST_PERSISTENT);
120 	REGISTER_LONG_CONSTANT("IBASE_STS_HDR_PAGES", isc_spb_sts_hdr_pages, CONST_PERSISTENT);
121 	REGISTER_LONG_CONSTANT("IBASE_STS_IDX_PAGES", isc_spb_sts_idx_pages, CONST_PERSISTENT);
122 	REGISTER_LONG_CONSTANT("IBASE_STS_SYS_RELATIONS", isc_spb_sts_sys_relations, CONST_PERSISTENT);
123 
124 	/* server info arguments */
125 	REGISTER_LONG_CONSTANT("IBASE_SVC_SERVER_VERSION", isc_info_svc_server_version, CONST_PERSISTENT);
126 	REGISTER_LONG_CONSTANT("IBASE_SVC_IMPLEMENTATION", isc_info_svc_implementation, CONST_PERSISTENT);
127 	REGISTER_LONG_CONSTANT("IBASE_SVC_GET_ENV", isc_info_svc_get_env, CONST_PERSISTENT);
128 	REGISTER_LONG_CONSTANT("IBASE_SVC_GET_ENV_LOCK", isc_info_svc_get_env_lock, CONST_PERSISTENT);
129 	REGISTER_LONG_CONSTANT("IBASE_SVC_GET_ENV_MSG", isc_info_svc_get_env_msg, CONST_PERSISTENT);
130 	REGISTER_LONG_CONSTANT("IBASE_SVC_USER_DBPATH", isc_info_svc_user_dbpath, CONST_PERSISTENT);
131 	REGISTER_LONG_CONSTANT("IBASE_SVC_SVR_DB_INFO", isc_info_svc_svr_db_info, CONST_PERSISTENT);
132 	REGISTER_LONG_CONSTANT("IBASE_SVC_GET_USERS", isc_info_svc_get_users, CONST_PERSISTENT);
133 }
134 /* }}} */
135 
_php_ibase_user(INTERNAL_FUNCTION_PARAMETERS,char operation)136 static void _php_ibase_user(INTERNAL_FUNCTION_PARAMETERS, char operation) /* {{{ */
137 {
138 	/* user = 0, password = 1, first_name = 2, middle_name = 3, last_name = 4 */
139 	static char const user_flags[] = { isc_spb_sec_username, isc_spb_sec_password,
140 	    isc_spb_sec_firstname, isc_spb_sec_middlename, isc_spb_sec_lastname };
141 	char buf[128], *args[] = { NULL, NULL, NULL, NULL, NULL };
142 	int i, args_len[] = { 0, 0, 0, 0, 0 };
143 	unsigned short spb_len = 1;
144 	zval *res;
145 	ibase_service *svm;
146 
147 	RESET_ERRMSG;
148 
149 	if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
150 			(operation == isc_action_svc_delete_user) ? "rs" : "rss|sss",
151 			&res, &args[0], &args_len[0], &args[1], &args_len[1], &args[2], &args_len[2],
152 			&args[3], &args_len[3], &args[4], &args_len[4])) {
153 		RETURN_FALSE;
154 	}
155 
156 	ZEND_FETCH_RESOURCE(svm, ibase_service *, &res, -1, "Interbase service manager handle",
157 		le_service);
158 
159 	buf[0] = operation;
160 
161 	for (i = 0; i < sizeof(user_flags); ++i) {
162 		if (args[i] != NULL) {
163 			int chunk = slprintf(&buf[spb_len], sizeof(buf) - spb_len, "%c%c%c%s",
164 				user_flags[i], (char)args_len[i], (char)(args_len[i] >> 8), args[i]);
165 
166 			if ((spb_len + chunk) > sizeof(buf) || chunk <= 0) {
167 				_php_ibase_module_error("Internal error: insufficient buffer space for SPB (%d)"
168 					TSRMLS_CC, spb_len);
169 				RETURN_FALSE;
170 			}
171 			spb_len += chunk;
172 		}
173 	}
174 
175 	/* now start the job */
176 	if (isc_service_start(IB_STATUS, &svm->handle, NULL, spb_len, buf)) {
177 		IBASE_SVC_ERROR(svm);
178 		RETURN_FALSE;
179 	}
180 
181 	RETURN_TRUE;
182 }
183 /* }}} */
184 
185 /* {{{ proto bool ibase_add_user(resource service_handle, string user_name, string password [, string first_name [, string middle_name [, string last_name]]])
186    Add a user to security database */
PHP_FUNCTION(ibase_add_user)187 PHP_FUNCTION(ibase_add_user)
188 {
189 	_php_ibase_user(INTERNAL_FUNCTION_PARAM_PASSTHRU, isc_action_svc_add_user);
190 }
191 /* }}} */
192 
193 /* {{{ proto bool ibase_modify_user(resource service_handle, string user_name, string password [, string first_name [, string middle_name [, string last_name]]])
194    Modify a user in security database */
PHP_FUNCTION(ibase_modify_user)195 PHP_FUNCTION(ibase_modify_user)
196 {
197 	_php_ibase_user(INTERNAL_FUNCTION_PARAM_PASSTHRU, isc_action_svc_modify_user);
198 }
199 /* }}} */
200 
201 /* {{{ proto bool ibase_delete_user(resource service_handle, string user_name, string password [, string first_name [, string middle_name [, string last_name]]])
202    Delete a user from security database */
PHP_FUNCTION(ibase_delete_user)203 PHP_FUNCTION(ibase_delete_user)
204 {
205 	_php_ibase_user(INTERNAL_FUNCTION_PARAM_PASSTHRU, isc_action_svc_delete_user);
206 }
207 /* }}} */
208 
209 /* {{{ proto resource ibase_service_attach(string host, string dba_username, string dba_password)
210    Connect to the service manager */
PHP_FUNCTION(ibase_service_attach)211 PHP_FUNCTION(ibase_service_attach)
212 {
213 	int hlen, ulen, plen, spb_len;
214 	ibase_service *svm;
215 	char buf[128], *host, *user, *pass, *loc;
216 	isc_svc_handle handle = NULL;
217 
218 	RESET_ERRMSG;
219 
220 	if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss",
221 			&host, &hlen, &user, &ulen, &pass, &plen)) {
222 
223 		RETURN_FALSE;
224 	}
225 
226 	/* construct the spb, hack the service name into it as well */
227 	spb_len = slprintf(buf, sizeof(buf), "%c%c%c%c%s%c%c%s" "%s:service_mgr",
228 		isc_spb_version, isc_spb_current_version, isc_spb_user_name, (char)ulen,
229 		user, isc_spb_password, (char)plen, pass, host);
230 
231 	if (spb_len > sizeof(buf) || spb_len == -1) {
232 		_php_ibase_module_error("Internal error: insufficient buffer space for SPB (%d)" TSRMLS_CC, spb_len);
233 		RETURN_FALSE;
234 	}
235 
236 	spb_len -= hlen + 12;
237 	loc = buf + spb_len; /* points to %s:service_mgr part */
238 
239 	/* attach to the service manager */
240 	if (isc_service_attach(IB_STATUS, 0, loc, &handle, (unsigned short)spb_len, buf)) {
241 		_php_ibase_error(TSRMLS_C);
242 		RETURN_FALSE;
243 	}
244 
245 	svm = (ibase_service*)emalloc(sizeof(ibase_service));
246 	svm->handle = handle;
247 	svm->hostname = estrdup(host);
248 	svm->username = estrdup(user);
249 
250 	ZEND_REGISTER_RESOURCE(return_value, svm, le_service);
251 	svm->res_id = Z_LVAL_P(return_value);
252 }
253 /* }}} */
254 
255 /* {{{ proto bool ibase_service_detach(resource service_handle)
256    Disconnect from the service manager */
PHP_FUNCTION(ibase_service_detach)257 PHP_FUNCTION(ibase_service_detach)
258 {
259 	zval *res;
260 
261 	RESET_ERRMSG;
262 
263 	if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &res)) {
264 		RETURN_FALSE;
265 	}
266 
267 	zend_list_delete(Z_LVAL_P(res));
268 
269 	RETURN_TRUE;
270 }
271 /* }}} */
272 
_php_ibase_service_query(INTERNAL_FUNCTION_PARAMETERS,ibase_service * svm,char info_action)273 static void _php_ibase_service_query(INTERNAL_FUNCTION_PARAMETERS, /* {{{ */
274 	ibase_service *svm, char info_action)
275 {
276 	static char spb[] = { isc_info_svc_timeout, 10, 0, 0, 0 };
277 
278 	char res_buf[400], *result, *heap_buf = NULL, *heap_p;
279 	long heap_buf_size = 200, line_len;
280 
281 	/* info about users requires an action first */
282 	if (info_action == isc_info_svc_get_users) {
283 		static char action[] = { isc_action_svc_display_user };
284 
285 		if (isc_service_start(IB_STATUS, &svm->handle, NULL, sizeof(action), action)) {
286 			IBASE_SVC_ERROR(svm);
287 			RETURN_FALSE;
288 		}
289 	}
290 
291 query_loop:
292 	result = res_buf;
293 
294 	if (isc_service_query(IB_STATUS, &svm->handle, NULL, sizeof(spb), spb,
295 			1, &info_action, sizeof(res_buf), res_buf)) {
296 
297 		IBASE_SVC_ERROR(svm);
298 		RETURN_FALSE;
299 	}
300 	while (*result != isc_info_end) {
301 		switch (*result++) {
302 			default:
303 				RETURN_FALSE;
304 
305 			case isc_info_svc_line:
306 				if (! (line_len = isc_vax_integer(result, 2))) {
307 					/* done */
308 					if (heap_buf) {
309 						RETURN_STRING(heap_buf,0);
310 					} else {
311 						RETURN_TRUE;
312 					}
313 				}
314 				if (!heap_buf || (heap_p - heap_buf + line_len +2) > heap_buf_size) {
315 					long res_size = heap_buf ? heap_p - heap_buf : 0;
316 
317 					while (heap_buf_size < (res_size + line_len +2)) {
318 						heap_buf_size *= 2;
319 					}
320 					heap_buf = (char*) erealloc(heap_buf, heap_buf_size);
321 					heap_p = heap_buf + res_size;
322 				}
323 				result += 2;
324 				*(result+line_len) = 0;
325 				snprintf(heap_p, heap_buf_size - (heap_p - heap_buf), "%s\n", result);
326 				heap_p += line_len +1;
327 				goto query_loop; /* repeat until result is exhausted */
328 
329 			case isc_info_svc_server_version:
330 			case isc_info_svc_implementation:
331 			case isc_info_svc_get_env:
332 			case isc_info_svc_get_env_lock:
333 			case isc_info_svc_get_env_msg:
334 			case isc_info_svc_user_dbpath:
335 				RETURN_STRINGL(result + 2, isc_vax_integer(result, 2), 1);
336 
337 			case isc_info_svc_svr_db_info:
338 				array_init(return_value);
339 
340 				do {
341 					switch (*result++) {
342 						int len;
343 
344 						case isc_spb_num_att:
345 							add_assoc_long(return_value, "attachments", isc_vax_integer(result,4));
346 							result += 4;
347 							break;
348 
349 						case isc_spb_num_db:
350 							add_assoc_long(return_value, "databases", isc_vax_integer(result,4));
351 							result += 4;
352 							break;
353 
354 						case isc_spb_dbname:
355 							len = isc_vax_integer(result,2);
356 							add_next_index_stringl(return_value, result +2, len, 1);
357 							result += len+2;
358 					}
359 				} while (*result != isc_info_flag_end);
360 				return;
361 
362 			case isc_info_svc_get_users: {
363 				zval *user;
364 				array_init(return_value);
365 
366 				while (*result != isc_info_end) {
367 
368 					switch (*result++) {
369 						int len;
370 
371 						case isc_spb_sec_username:
372 							/* it appears that the username is always first */
373 							ALLOC_INIT_ZVAL(user);
374 							array_init(user);
375 							add_next_index_zval(return_value, user);
376 
377 							len = isc_vax_integer(result,2);
378 							add_assoc_stringl(user, "user_name", result +2, len, 1);
379 							result += len+2;
380 							break;
381 
382 						case isc_spb_sec_firstname:
383 							len = isc_vax_integer(result,2);
384 							add_assoc_stringl(user, "first_name", result +2, len, 1);
385 							result += len+2;
386 							break;
387 
388 						case isc_spb_sec_middlename:
389 							len = isc_vax_integer(result,2);
390 							add_assoc_stringl(user, "middle_name", result +2, len, 1);
391 							result += len+2;
392 							break;
393 
394 						case isc_spb_sec_lastname:
395 							len = isc_vax_integer(result,2);
396 							add_assoc_stringl(user, "last_name", result +2, len, 1);
397 							result += len+2;
398 							break;
399 
400 						case isc_spb_sec_userid:
401 							add_assoc_long(user, "user_id", isc_vax_integer(result, 4));
402 							result += 4;
403 							break;
404 
405 						case isc_spb_sec_groupid:
406 							add_assoc_long(user, "group_id", isc_vax_integer(result, 4));
407 							result += 4;
408 							break;
409 					}
410 				}
411 				return;
412 			}
413 		}
414 	}
415 }
416 /* }}} */
417 
_php_ibase_backup_restore(INTERNAL_FUNCTION_PARAMETERS,char operation)418 static void _php_ibase_backup_restore(INTERNAL_FUNCTION_PARAMETERS, char operation) /* {{{ */
419 {
420 	/**
421 	 * It appears that the service API is a little bit confused about which flag
422 	 * to use for the source and destination in the case of a restore operation.
423 	 * When passing the backup file as isc_spb_dbname and the destination db as
424 	 * bpk_file, things work well.
425 	 */
426 	zval *res;
427 	char *db, *bk, buf[200];
428 	int dblen, bklen, spb_len;
429 	long opts = 0;
430 	zend_bool verbose = 0;
431 	ibase_service *svm;
432 
433 	RESET_ERRMSG;
434 
435 	if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss|lb",
436 			&res, &db, &dblen, &bk, &bklen, &opts, &verbose)) {
437 		RETURN_FALSE;
438 	}
439 
440 	ZEND_FETCH_RESOURCE(svm, ibase_service *, &res, -1,
441 		"Interbase service manager handle", le_service);
442 
443 	/* fill the param buffer */
444 	spb_len = slprintf(buf, sizeof(buf), "%c%c%c%c%s%c%c%c%s%c%c%c%c%c",
445 		operation, isc_spb_dbname, (char)dblen, (char)(dblen >> 8), db,
446 		isc_spb_bkp_file, (char)bklen, (char)(bklen >> 8), bk, isc_spb_options,
447 		(char)opts,(char)(opts >> 8), (char)(opts >> 16), (char)(opts >> 24));
448 
449 	if (verbose) {
450 		buf[spb_len++] = isc_spb_verbose;
451 	}
452 
453 	if (spb_len > sizeof(buf) || spb_len <= 0) {
454 		_php_ibase_module_error("Internal error: insufficient buffer space for SPB (%d)" TSRMLS_CC, spb_len);
455 		RETURN_FALSE;
456 	}
457 
458 	/* now start the backup/restore job */
459 	if (isc_service_start(IB_STATUS, &svm->handle, NULL, (unsigned short)spb_len, buf)) {
460 		IBASE_SVC_ERROR(svm);
461 		RETURN_FALSE;
462 	}
463 
464 	if (!verbose) {
465 		RETURN_TRUE;
466 	} else {
467 		_php_ibase_service_query(INTERNAL_FUNCTION_PARAM_PASSTHRU, svm, isc_info_svc_line);
468 	}
469 }
470 /* }}} */
471 
472 /* {{{ proto mixed ibase_backup(resource service_handle, string source_db, string dest_file [, int options [, bool verbose]])
473    Initiates a backup task in the service manager and returns immediately */
PHP_FUNCTION(ibase_backup)474 PHP_FUNCTION(ibase_backup)
475 {
476 	_php_ibase_backup_restore(INTERNAL_FUNCTION_PARAM_PASSTHRU, isc_action_svc_backup);
477 }
478 /* }}} */
479 
480 /* {{{ proto mixed ibase_restore(resource service_handle, string source_file, string dest_db [, int options [, bool verbose]])
481    Initiates a restore task in the service manager and returns immediately */
PHP_FUNCTION(ibase_restore)482 PHP_FUNCTION(ibase_restore)
483 {
484 	_php_ibase_backup_restore(INTERNAL_FUNCTION_PARAM_PASSTHRU, isc_action_svc_restore);
485 }
486 /* }}} */
487 
_php_ibase_service_action(INTERNAL_FUNCTION_PARAMETERS,char svc_action)488 static void _php_ibase_service_action(INTERNAL_FUNCTION_PARAMETERS, char svc_action) /* {{{ */
489 {
490 	zval *res;
491 	char buf[128], *db;
492 	int dblen, spb_len;
493 	long action, argument = 0;
494 	ibase_service *svm;
495 
496 	RESET_ERRMSG;
497 
498 	if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsl|l",
499 			&res, &db, &dblen, &action, &argument)) {
500 		RETURN_FALSE;
501 	}
502 
503 	ZEND_FETCH_RESOURCE(svm, ibase_service *, &res, -1,
504 		"Interbase service manager handle", le_service);
505 
506 	if (svc_action == isc_action_svc_db_stats) {
507 		switch (action) {
508 			default:
509 				goto unknown_option;
510 
511 			case isc_spb_sts_data_pages:
512 			case isc_spb_sts_db_log:
513 			case isc_spb_sts_hdr_pages:
514 			case isc_spb_sts_idx_pages:
515 			case isc_spb_sts_sys_relations:
516 				goto options_argument;
517 		}
518 	} else {
519 		/* these actions all expect different types of arguments */
520 		switch (action) {
521 			default:
522 unknown_option:
523 				_php_ibase_module_error("Unrecognised option (%ld)" TSRMLS_CC, action);
524 				RETURN_FALSE;
525 
526 			case isc_spb_rpr_check_db:
527 			case isc_spb_rpr_ignore_checksum:
528 			case isc_spb_rpr_kill_shadows:
529 			case isc_spb_rpr_mend_db:
530 			case isc_spb_rpr_validate_db:
531 			case isc_spb_rpr_sweep_db:
532 				svc_action = isc_action_svc_repair;
533 
534 			case isc_spb_prp_activate:
535 			case isc_spb_prp_db_online:
536 options_argument:
537 				argument |= action;
538 				action = isc_spb_options;
539 
540 			case isc_spb_prp_page_buffers:
541 			case isc_spb_prp_sweep_interval:
542 			case isc_spb_prp_shutdown_db:
543 			case isc_spb_prp_deny_new_transactions:
544 			case isc_spb_prp_deny_new_attachments:
545 			case isc_spb_prp_set_sql_dialect:
546 				spb_len = slprintf(buf, sizeof(buf), "%c%c%c%c%s%c%c%c%c%c",
547 					svc_action, isc_spb_dbname, (char)dblen, (char)(dblen >> 8), db,
548 					(char)action, (char)argument, (char)(argument >> 8), (char)(argument >> 16),
549 					(char)(argument >> 24));
550 				break;
551 
552 			case isc_spb_prp_reserve_space:
553 			case isc_spb_prp_write_mode:
554 			case isc_spb_prp_access_mode:
555 				spb_len = slprintf(buf, sizeof(buf), "%c%c%c%c%s%c%c",
556 					isc_action_svc_properties, isc_spb_dbname, (char)dblen, (char)(dblen >> 8),
557 					db, (char)action, (char)argument);
558 		}
559 	}
560 
561 	if (spb_len > sizeof(buf) || spb_len == -1) {
562 		_php_ibase_module_error("Internal error: insufficient buffer space for SPB (%d)" TSRMLS_CC, spb_len);
563 		RETURN_FALSE;
564 	}
565 
566 	if (isc_service_start(IB_STATUS, &svm->handle, NULL, (unsigned short)spb_len, buf)) {
567 		IBASE_SVC_ERROR(svm);
568 		RETURN_FALSE;
569 	}
570 
571 	if (svc_action == isc_action_svc_db_stats) {
572 		_php_ibase_service_query(INTERNAL_FUNCTION_PARAM_PASSTHRU, svm, isc_info_svc_line);
573 	} else {
574 		RETURN_TRUE;
575 	}
576 }
577 /* }}} */
578 
579 /* {{{ proto bool ibase_maintain_db(resource service_handle, string db, int action [, int argument])
580    Execute a maintenance command on the database server */
PHP_FUNCTION(ibase_maintain_db)581 PHP_FUNCTION(ibase_maintain_db)
582 {
583 	_php_ibase_service_action(INTERNAL_FUNCTION_PARAM_PASSTHRU, isc_action_svc_properties);
584 }
585 /* }}} */
586 
587 /* {{{ proto string ibase_db_info(resource service_handle, string db, int action [, int argument])
588    Request statistics about a database */
PHP_FUNCTION(ibase_db_info)589 PHP_FUNCTION(ibase_db_info)
590 {
591 	_php_ibase_service_action(INTERNAL_FUNCTION_PARAM_PASSTHRU, isc_action_svc_db_stats);
592 }
593 /* }}} */
594 
595 /* {{{ proto string ibase_server_info(resource service_handle, int action)
596    Request information about a database server */
PHP_FUNCTION(ibase_server_info)597 PHP_FUNCTION(ibase_server_info)
598 {
599 	zval *res;
600 	long action;
601 	ibase_service *svm;
602 
603 	RESET_ERRMSG;
604 
605 	if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &res, &action)) {
606 		RETURN_FALSE;
607 	}
608 
609 	ZEND_FETCH_RESOURCE(svm, ibase_service *, &res, -1,
610 		"Interbase service manager handle", le_service);
611 
612 	_php_ibase_service_query(INTERNAL_FUNCTION_PARAM_PASSTHRU, svm, (char)action);
613 }
614 /* }}} */
615 
616 #else
617 
php_ibase_register_service_constants(INIT_FUNC_ARGS)618 void php_ibase_register_service_constants(INIT_FUNC_ARGS) { /* nop */ }
619 
620 #endif /* HAVE_IBASE */
621 
622 /*
623  * Local variables:
624  * tab-width: 4
625  * c-basic-offset: 4
626  * End:
627  * vim600: sw=4 ts=4 fdm=marker
628  * vim<600: sw=4 ts=4
629  */
630