mem.c

来自「在Linux/Unix下面访问WINDOWS SQLSERVER 的ODBC驱动」· C语言 代码 · 共 1,446 行 · 第 1/3 页

C
1,446
字号
tds_free_compute_result(TDSCOMPUTEINFO * comp_info){	tds_free_results(comp_info);}static voidtds_free_compute_results(TDSSOCKET * tds){	int i;	TDSCOMPUTEINFO ** comp_info = tds->comp_info;	TDS_INT num_comp = tds->num_comp_info;	tds->comp_info = NULL;	tds->num_comp_info = 0;	for (i = 0; i < num_comp; i++) {		if (comp_info && comp_info[i]) {			if (tds->current_results == comp_info[i])				tds->current_results = NULL;			tds_free_compute_result(comp_info[i]);		}	}	if (num_comp)		free(comp_info);}voidtds_free_row(TDSRESULTINFO * res_info, unsigned char *row){	assert(res_info);	if (!row || !res_info->row_free)		return;	res_info->row_free(res_info, row);}voidtds_free_results(TDSRESULTINFO * res_info){	int i;	TDSCOLUMN *curcol;	if (!res_info)		return;	if (--res_info->ref_count != 0)		return;	if (res_info->num_cols && res_info->columns) {		for (i = 0; i < res_info->num_cols; i++)			if ((curcol = res_info->columns[i]) != NULL) {				if (curcol->bcp_terminator)					TDS_ZERO_FREE(curcol->bcp_terminator);				tds_free_bcp_column_data(curcol->bcp_column_data);				curcol->bcp_column_data = NULL;				if (curcol->column_data && curcol->column_data_free)					curcol->column_data_free(curcol);			}	}	if (res_info->current_row && res_info->row_free)		res_info->row_free(res_info, res_info->current_row);	if (res_info->num_cols && res_info->columns) {		for (i = 0; i < res_info->num_cols; i++)			if ((curcol = res_info->columns[i]) != NULL) {				free(curcol->table_column_name);				free(curcol);			}		free(res_info->columns);	}	free(res_info->bycolumns);	free(res_info);}voidtds_free_all_results(TDSSOCKET * tds){	tdsdump_log(TDS_DBG_FUNC, "tds_free_all_results()\n");	if (tds->current_results == tds->res_info)		tds->current_results = NULL;	tds_free_results(tds->res_info);	tds->res_info = NULL;	if (tds->current_results == tds->param_info)		tds->current_results = NULL;	tds_free_param_results(tds->param_info);	tds->param_info = NULL;	tds_free_compute_results(tds);	tds->has_status = 0;	tds->ret_status = 0;}TDSCONTEXT *tds_alloc_context(void * parent){	TDSCONTEXT *context;	TDSLOCALE *locale;	locale = tds_get_locale();	if (!locale)		return NULL;	context = (TDSCONTEXT *) calloc(1, sizeof(TDSCONTEXT));	if (!context) {		tds_free_locale(locale);		return NULL;	}	context->locale = locale;	context->parent = parent;	return context;}voidtds_free_context(TDSCONTEXT * context){	if (!context)		return;	tds_free_locale(context->locale);	free(context);}TDSLOCALE *tds_alloc_locale(void){	TDSLOCALE *locale;	TEST_MALLOC(locale, TDSLOCALE);	return locale;      Cleanup:	return NULL;}static const unsigned char defaultcaps[] = {      /* type,  len, data, data, data, data, data, data, data, data, data (9 bytes) */	0x01, 0x09, 0x00, 0x08, 0x0E, 0x6D, 0x7F, 0xFF, 0xFF, 0xFF, 0xFE,	0x02, 0x09, 0x00, 0x00, 0x00, 0x00, 0x02, 0x68, 0x00, 0x00, 0x00};#if ENABLE_EXTRA_CHECKS/* * Default capabilities as of December 2006.   */static const TDS_TINYINT request_capabilities[] = 	{  /* no zero */ TDS_REQ_LANG, TDS_REQ_RPC, TDS_REQ_EVT,	  TDS_REQ_MSTMT, TDS_REQ_BCP, TDS_REQ_CURSOR, TDS_REQ_DYNF				/* capability.data[8] */	, TDS_REQ_MSG, TDS_REQ_PARAM, TDS_REQ_DATA_INT1, TDS_REQ_DATA_INT2, 	  TDS_REQ_DATA_INT4, TDS_REQ_DATA_BIT, TDS_REQ_DATA_CHAR, TDS_REQ_DATA_VCHAR 		/* capability.data[7] */	, TDS_REQ_DATA_BIN, TDS_REQ_DATA_VBIN, TDS_REQ_DATA_MNY8, TDS_REQ_DATA_MNY4, 	  TDS_REQ_DATA_DATE8, TDS_REQ_DATA_DATE4, TDS_REQ_DATA_FLT4, TDS_REQ_DATA_FLT8		/* capability.data[6] */	, TDS_REQ_DATA_NUM, TDS_REQ_DATA_TEXT, TDS_REQ_DATA_IMAGE, TDS_REQ_DATA_DEC, 	  TDS_REQ_DATA_LCHAR, TDS_REQ_DATA_LBIN, TDS_REQ_DATA_INTN, TDS_REQ_DATA_DATETIMEN	/* capability.data[5] */	, TDS_REQ_DATA_MONEYN, TDS_REQ_CSR_PREV, TDS_REQ_CSR_FIRST, TDS_REQ_CSR_LAST, 	  TDS_REQ_CSR_ABS, TDS_REQ_CSR_REL, TDS_REQ_CSR_MULTI					/* capability.data[4] */	, TDS_REQ_CON_INBAND,                   TDS_REQ_PROTO_TEXT, TDS_REQ_PROTO_BULK, 	  TDS_REQ_DATA_SENSITIVITY, TDS_REQ_DATA_BOUNDARY					/* capability.data[3] */	,                           TDS_REQ_DATA_FLTN, TDS_REQ_DATA_BITN, TDS_REQ_DATA_INT8	/* capability.data[2] */	, TDS_REQ_WIDETABLE									/* capability.data[1] */	};static const TDS_TINYINT response_capabilities[] = 	{ TDS_RES_CON_NOOOB	, TDS_RES_PROTO_NOTEXT	, TDS_RES_PROTO_NOBULK	, TDS_RES_NOTDSDEBUG	};/* * The TDSLOGIN::capabilities member is a little wrong because it includes the type and typelen members. * The 22 bytes are structured as: *	offset	name	value	meaning *	------	----	-----	-------------------------- *	  0	type	  1	request *	  1	len	  9	9 capability bytes follow *	 2-10	data	   *	 11	type	  2	response *	 12	len	  9	9 capability bytes follow *	13-21	data	   * * This function manipulates the data portion without altering the length. *  * \param capabilities 	address of the data portion in the TDSLOGIN member to be affected. * \param capability 	capability to set or reset.  Pass as negative to reset.   */static unsigned char *tds_capability_set(unsigned char capabilities[], unsigned int cap, size_t len){	int index = (len - cap/8u) - 1;	unsigned char mask = 1 << ((8u+cap) % 8u);	assert(0 < index && (unsigned) index < len);	capabilities[index] |= mask;	return capabilities;}static voidtds_capability_test(void){	unsigned char buf_capabilities[TDS_MAX_CAPABILITY];	unsigned char *capabilities[2];	int i, c, ncap;	const TDS_TINYINT* pcap;	/*	 * Set the capabilities using the enumerated types, one at a time.  	 */	memset(buf_capabilities, 0, TDS_MAX_CAPABILITY);	capabilities[0] = buf_capabilities;	capabilities[1] = buf_capabilities + TDS_MAX_CAPABILITY / 2;	pcap = request_capabilities;	ncap = TDS_VECTOR_SIZE(request_capabilities);	for (c=0; c < 2; c++) {		const int bufsize = TDS_MAX_CAPABILITY / 2 - 2;		capabilities[c][0] = 1 + c; /* request/response */		capabilities[c][1] = bufsize;		for (i=0; i < ncap; i++) {			tds_capability_set(capabilities[c]+2, pcap[i], bufsize);		}		pcap = response_capabilities;		ncap = TDS_VECTOR_SIZE(response_capabilities);	}	/* 	 * For now, we test to make sure the enumerated set yields the same bit pattern 	 * that we used to create with magic numbers.  Eventually we can delete defaultcaps and the below assertion.	 */	assert(0 == memcmp(buf_capabilities, defaultcaps, TDS_MAX_CAPABILITY));}#endif/** * Allocate space for configure structure and initialize with default values * @param locale locale information (copied to configuration information) * @result allocated structure or NULL if out of memory */TDSCONNECTION *tds_alloc_connection(TDSLOCALE * locale){	TDSCONNECTION *connection;	char hostname[128];	TEST_MALLOC(connection, TDSCONNECTION);	tds_dstr_init(&connection->server_name);	tds_dstr_init(&connection->language);	tds_dstr_init(&connection->server_charset);	tds_dstr_init(&connection->client_host_name);	tds_dstr_init(&connection->server_host_name);	tds_dstr_init(&connection->app_name);	tds_dstr_init(&connection->user_name);	tds_dstr_init(&connection->password);	tds_dstr_init(&connection->library);	tds_dstr_init(&connection->ip_addr);	tds_dstr_init(&connection->database);	tds_dstr_init(&connection->dump_file);	tds_dstr_init(&connection->client_charset);	tds_dstr_init(&connection->instance_name);	/* fill in all hardcoded defaults */	if (!tds_dstr_copy(&connection->server_name, TDS_DEF_SERVER))		goto Cleanup;	connection->major_version = TDS_DEF_MAJOR;	connection->minor_version = TDS_DEF_MINOR;	connection->port = TDS_DEF_PORT;	connection->block_size = 0;	/* TODO use system default ?? */	if (!tds_dstr_copy(&connection->client_charset, "ISO-8859-1"))		goto Cleanup;	if (locale) {		if (locale->language)			if (!tds_dstr_copy(&connection->language, locale->language))				goto Cleanup;		if (locale->server_charset)			if (!tds_dstr_copy(&connection->server_charset, locale->server_charset))				goto Cleanup;	}	if (tds_dstr_isempty(&connection->language)) {		if (!tds_dstr_copy(&connection->language, TDS_DEF_LANG))			goto Cleanup;	}	memset(hostname, '\0', sizeof(hostname));	gethostname(hostname, sizeof(hostname));	hostname[sizeof(hostname) - 1] = '\0';	/* make sure it's truncated */	if (!tds_dstr_copy(&connection->client_host_name, hostname))		goto Cleanup;#if ENABLE_EXTRA_CHECKS	tds_capability_test();#endif	memcpy(connection->capabilities, defaultcaps, TDS_MAX_CAPABILITY);	return connection;      Cleanup:	tds_free_connection(connection);	return NULL;}TDSCURSOR *tds_alloc_cursor(TDSSOCKET *tds, const char *name, TDS_INT namelen, const char *query, TDS_INT querylen){	TDSCURSOR *cursor;	TDSCURSOR *pcursor;	TEST_MALLOC(cursor, TDSCURSOR);	cursor->ref_count = 1;	if ( tds->cursors == NULL ) {		tds->cursors = cursor;	} else {		pcursor = tds->cursors;		for (;;) {			tdsdump_log(TDS_DBG_FUNC, "tds_alloc_cursor() : stepping thru existing cursors\n");			if (pcursor->next == NULL)				break;			pcursor = pcursor->next;		}		pcursor->next = cursor;	}	/* take into account reference in tds list */	++cursor->ref_count;	TEST_CALLOC(cursor->cursor_name, char, namelen + 1);	strcpy(cursor->cursor_name, name);	cursor->cursor_name_len = namelen;	TEST_CALLOC(cursor->query, char, querylen + 1);	strcpy(cursor->query, query);	cursor->query_len = querylen;	return cursor;      Cleanup:	if (cursor)		tds_cursor_deallocated(tds, cursor);	tds_release_cursor(tds, cursor);	return NULL;}/* * Called when cursor got deallocated from server */voidtds_cursor_deallocated(TDSSOCKET *tds, TDSCURSOR *cursor){	TDSCURSOR *victim = NULL;	TDSCURSOR *prev = NULL;	TDSCURSOR *next = NULL;	tdsdump_log(TDS_DBG_FUNC, "tds_cursor_deallocated() : freeing cursor_id %d\n", cursor->cursor_id);	if (tds->cur_cursor == cursor) {		tds_release_cursor(tds, cursor);		tds->cur_cursor = NULL;	}	victim = tds->cursors;	if (victim == NULL) {		tdsdump_log(TDS_DBG_FUNC, "tds_cursor_deallocated() : no allocated cursors %d\n", cursor->cursor_id);		return;	}	for (;;) {		if (victim == cursor)			break;		prev = victim;		victim = victim->next;		if (victim == NULL) {			tdsdump_log(TDS_DBG_FUNC, "tds_cursor_deallocated() : cannot find cursor_id %d\n", cursor->cursor_id);			return;		}	}	tdsdump_log(TDS_DBG_FUNC, "tds_cursor_deallocated() : cursor_id %d found\n", cursor->cursor_id);	next = victim->next;	tdsdump_log(TDS_DBG_FUNC, "tds_cursor_deallocated() : relinking list\n");	if (prev)		prev->next = next;	else		tds->cursors = next;	tdsdump_log(TDS_DBG_FUNC, "tds_cursor_deallocated() : relinked list\n");	tds_release_cursor(tds, cursor);}/* * Decrement reference counter and free if necessary. * Called internally by libTDS and by upper library when you don't need  * cursor reference anymore */voidtds_release_cursor(TDSSOCKET *tds, TDSCURSOR *cursor){	if (!cursor || --cursor->ref_count > 0)		return;	tdsdump_log(TDS_DBG_FUNC, "tds_release_cursor() : freeing cursor_id %d\n", cursor->cursor_id);	tdsdump_log(TDS_DBG_FUNC, "tds_release_cursor() : freeing cursor results\n");	if (tds->current_results == cursor->res_info)		tds->current_results = NULL;	tds_free_results(cursor->res_info);	if (cursor->cursor_name) {		tdsdump_log(TDS_DBG_FUNC, "tds_release_cursor() : freeing cursor name\n");		free(cursor->cursor_name);	}	if (cursor->query) {		tdsdump_log(TDS_DBG_FUNC, "tds_release_cursor() : freeing cursor query\n");		free(cursor->query);	}	tdsdump_log(TDS_DBG_FUNC, "tds_release_cursor() : cursor_id %d freed\n", cursor->cursor_id);	free(cursor);}TDSLOGIN *tds_alloc_login(void){	TDSLOGIN *tds_login;	TEST_MALLOC(tds_login, TDSLOGIN);	tds_dstr_init(&tds_login->server_name);	tds_dstr_init(&tds_login->server_addr);	tds_dstr_init(&tds_login->language);	tds_dstr_init(&tds_login->server_charset);	tds_dstr_init(&tds_login->client_host_name);	tds_dstr_init(&tds_login->app_name);	tds_dstr_init(&tds_login->user_name);	tds_dstr_init(&tds_login->password);	tds_dstr_init(&tds_login->library);	tds_dstr_init(&tds_login->client_charset);	memcpy(tds_login->capabilities, defaultcaps, TDS_MAX_CAPABILITY);	return tds_login;      Cleanup:	return NULL;}voidtds_free_login(TDSLOGIN * login){	if (login) {		/* for security reason clear memory */		tds_dstr_zero(&login->password);		tds_dstr_free(&login->password);		tds_dstr_free(&login->server_name);		tds_dstr_free(&login->server_addr);		tds_dstr_free(&login->language);		tds_dstr_free(&login->server_charset);		tds_dstr_free(&login->client_host_name);		tds_dstr_free(&login->app_name);		tds_dstr_free(&login->user_name);		tds_dstr_free(&login->library);		tds_dstr_free(&login->client_charset);		free(login);	}}TDSSOCKET *tds_alloc_socket(TDSCONTEXT * context, int bufsize){	TDSSOCKET *tds_socket;	TEST_MALLOC(tds_socket, TDSSOCKET);	tds_socket->tds_ctx = context;	tds_socket->in_buf_max = 0;	TEST_CALLOC(tds_socket->out_buf, unsigned char, bufsize + TDS_ADDITIONAL_SPACE);	tds_socket->parent = NULL;	/*	 * TDS 7.0: 	 * 0x02 indicates ODBC driver	 * 0x01 means change to initial language must succeed

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?