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 + -
显示快捷键?