/* * pool_process_members * check the fd_set for members returning data to the client, lookup the * client holding this member and forward the results. */ int pool_process_members(TDS_POOL * pool, fd_set * fds) { TDS_POOL_MEMBER *pmbr; TDS_POOL_USER *puser; TDSSOCKET *tds; int i, age, ret; int cnt = 0; time_t time_now; for (i = 0; i < pool->num_members; i++) { pmbr = &pool->members[i]; tds = pmbr->tds; if (!tds) { assert(pmbr->state == TDS_IDLE); continue; /* dead connection */ } time_now = time(NULL); if (FD_ISSET(tds_get_s(tds), fds)) { pmbr->last_used_tm = time_now; cnt++; if (pool_packet_read(tds)) continue; if (tds->in_len == 0) { fprintf(stderr, "Uh oh! member %d disconnected\n", i); /* mark as dead */ pool_free_member(pmbr); } else if (tds->in_len < 0) { fprintf(stderr, "Uh oh! member %d disconnected\n", i); perror("read"); pool_free_member(pmbr); } else { tdsdump_dump_buf(TDS_DBG_NETWORK, "Got packet from server:", tds->in_buf, tds->in_len); /* fprintf(stderr, "read %d bytes from member %d\n", tds->in_len, i); */ puser = pmbr->current_user; if (puser) { tdsdump_log(TDS_DBG_INFO1, "writing it sock %d\n", tds_get_s(puser->tds)); /* cf. net.c for better technique. */ /* FIXME handle partial write, stop read on member */ ret = pool_write_all(tds_get_s(puser->tds), tds->in_buf, tds->in_len); if (ret < 0) { /* couldn't write, ditch the user */ fprintf(stdout, "member %d received error while writing\n",i); pool_free_member(pmbr); } } } } age = time_now - pmbr->last_used_tm; if (age > pool->max_member_age && i >= pool->min_open_conn && !pmbr->current_user) { fprintf(stderr, "member %d is %d seconds old...closing\n", i, age); pool_free_member(pmbr); } } return cnt; }
CS_RETCODE cs_diag(CS_CONTEXT * ctx, CS_INT operation, CS_INT type, CS_INT idx, CS_VOID * buffer) { tdsdump_log(TDS_DBG_FUNC, "cs_diag(%p, %d, %d, %d, %p)\n", ctx, operation, type, idx, buffer); switch (operation) { case CS_INIT: if ( ctx->cs_errhandletype == _CS_ERRHAND_CB) { /* contrary to the manual page you don't seem to */ /* be able to turn on inline message handling */ /* using cs_diag, once a callback is installed! */ return CS_FAIL; } ctx->cs_errhandletype = _CS_ERRHAND_INLINE; ctx->cs_diag_msglimit = CS_NO_LIMIT; ctx->_cslibmsg_cb = (CS_CSLIBMSG_FUNC) cs_diag_storemsg; break; case CS_MSGLIMIT: if ( ctx->cs_errhandletype != _CS_ERRHAND_INLINE) { return CS_FAIL; } ctx->cs_diag_msglimit = *(CS_INT *)buffer; break; case CS_CLEAR: if ( ctx->cs_errhandletype != _CS_ERRHAND_INLINE) { return CS_FAIL; } return (cs_diag_clearmsg(ctx, type)); break; case CS_GET: if ( ctx->cs_errhandletype != _CS_ERRHAND_INLINE) { return CS_FAIL; } if (buffer == NULL) return CS_FAIL; if (idx == 0 || (ctx->cs_diag_msglimit != CS_NO_LIMIT && idx > ctx->cs_diag_msglimit) ) return CS_FAIL; return (cs_diag_getmsg(ctx, idx, (CS_CLIENTMSG *)buffer)); break; case CS_STATUS: if ( ctx->cs_errhandletype != _CS_ERRHAND_INLINE) { return CS_FAIL; } if (buffer == NULL) return CS_FAIL; return (cs_diag_countmsg(ctx, (CS_INT *)buffer)); break; } return CS_SUCCEED; }
CS_RETCODE cs_will_convert(CS_CONTEXT * ctx, CS_INT srctype, CS_INT desttype, CS_BOOL * result) { tdsdump_log(TDS_DBG_FUNC, "cs_will_convert(%p, %d, %d, %p)\n", ctx, srctype, desttype, result); *result = (tds_willconvert(srctype, desttype) ? CS_TRUE : CS_FALSE); return CS_SUCCEED; }
/* * pool_user_read * checks the packet type of data coming from the client and allocates a * pool member if necessary. */ static bool pool_user_read(TDS_POOL * pool, TDS_POOL_USER * puser) { TDSSOCKET *tds = puser->sock.tds; TDS_POOL_MEMBER *pmbr = NULL; for (;;) { if (pool_packet_read(tds)) break; if (tds->in_len == 0) { tdsdump_log(TDS_DBG_INFO1, "user disconnected\n"); pool_free_user(pool, puser); return false; } else { TDS_UCHAR in_flag = tds->in_buf[0]; tdsdump_dump_buf(TDS_DBG_NETWORK, "Got packet from client:", tds->in_buf, tds->in_len); switch (in_flag) { case TDS_QUERY: case TDS_NORMAL: case TDS_RPC: case TDS_BULK: case TDS_CANCEL: case TDS7_TRANS: if (!pool_write_data(&puser->sock, &puser->assigned_member->sock)) { pool_reset_member(pool, puser->assigned_member); return false; } pmbr = puser->assigned_member; break; default: tdsdump_log(TDS_DBG_ERROR, "Unrecognized packet type, closing user\n"); pool_free_user(pool, puser); return false; } } } if (pmbr && !pmbr->sock.poll_send) tds_socket_flush(tds_get_s(pmbr->sock.tds)); return true; }
void odbc_bcp_free_storage(TDS_DBC *dbc) { tdsdump_log(TDS_DBG_FUNC, "_bcp_free_storage(%p)\n", dbc); assert(dbc); tds_free_bcpinfo(dbc->bcpinfo); dbc->bcpinfo = NULL; TDS_ZERO_FREE(dbc->bcphint); }
void dbpivot_max (struct col_t *tgt, const struct col_t *src) { assert( tgt && src); assert (src->type); tgt->type = src->type; if (col_null(src)) return; switch (src->type) { case SYBINT1: tgt->ti = tgt->ti > src->ti? tgt->ti : src->ti; break; case SYBINT2: tgt->si = tgt->si > src->si? tgt->si : src->si; break; case SYBINT4: tgt->i = tgt->i > src->i? tgt->i : src->i; break; case SYBFLT8: tgt->f = tgt->f > src->f? tgt->f : src->f; break; case SYBREAL: tgt->r = tgt->r > src->r? tgt->r : src->r; break; case SYBCHAR: case SYBVARCHAR: case SYBINTN: case SYBDATETIME: case SYBBIT: case SYBTEXT: case SYBNTEXT: case SYBIMAGE: case SYBMONEY4: case SYBMONEY: case SYBDATETIME4: case SYBBINARY: case SYBVOID: case SYBVARBINARY: case SYBBITN: case SYBNUMERIC: case SYBDECIMAL: case SYBFLTN: case SYBMONEYN: case SYBDATETIMN: default: tdsdump_log(TDS_DBG_INFO1, "dbpivot_sum(): invalid operand %d\n", src->type); tgt->type = SYBINT4; tgt->i = 0; break; } }
static void tds_config_env_tdsport(TDSCONNECTINFO * connect_info) { char *s; if ((s = getenv("TDSPORT"))) { connect_info->port = atoi(s); tdsdump_log(TDS_DBG_INFO1, "%L Setting 'port' to %s from $TDSPORT.\n", s); } return; }
static int tds_try_conf_file(const char *path, const char *how, const char *server, TDSCONNECTINFO * connect_info) { int found = 0; FILE *in; if ((in = fopen(path, "r")) != NULL) { tdsdump_log(TDS_DBG_INFO1, "%L Found conf file '%s' %s. Reading section '%s'.\n", path, how, server); found = tds_read_conf_sections(in, server, connect_info); if (found) { tdsdump_log(TDS_DBG_INFO1, "%L ...Success.\n"); } else { tdsdump_log(TDS_DBG_INFO2, "%L ...'%s' not found.\n", server); } fclose(in); } return found; }
CS_RETCODE cs_loc_drop(CS_CONTEXT * ctx, CS_LOCALE * locale) { tdsdump_log(TDS_DBG_FUNC, "cs_loc_drop(%p, %p)\n", ctx, locale); if (!locale) return CS_FAIL; _cs_locale_free(locale); return CS_SUCCEED; }
static SSL_RET tds_push_func_login(SSL_PUSH_ARGS) { TDSSOCKET *tds = (TDSSOCKET *) SSL_PTR; tdsdump_log(TDS_DBG_INFO1, "in tds_push_func_login\n"); /* initializing SSL, write crypted data inside normal TDS packets */ tds_put_n(tds, data, len); return len; }
void _cs_locale_free(CS_LOCALE *locale) { tdsdump_log(TDS_DBG_FUNC, "_cs_locale_free(%p)\n", locale); /* free contents */ _cs_locale_free_contents(locale); /* free the data structure */ free(locale); }
/** * Help to build query to be sent to server. * Append column declaration to the query. * Only for TDS 7.0+. * \tds * \param[out] clause output string * \param bcpcol column to append * \param first true if column is the first * \return TDS_SUCCESS or TDS_FAIL. */ static TDSRET tds7_build_bulk_insert_stmt(TDSSOCKET * tds, TDSPBCB * clause, TDSCOLUMN * bcpcol, int first) { char column_type[40]; tdsdump_log(TDS_DBG_FUNC, "tds7_build_bulk_insert_stmt(%p, %p, %p, %d)\n", tds, clause, bcpcol, first); if (TDS_FAILED(tds_get_column_declaration(tds, bcpcol, column_type))) { tdserror(tds_get_ctx(tds), tds, TDSEBPROBADTYP, errno); tdsdump_log(TDS_DBG_FUNC, "error: cannot build bulk insert statement. unrecognized server datatype %d\n", bcpcol->on_server.column_type); return TDS_FAIL; } if (clause->cb < strlen(clause->pb) + tds_quote_id(tds, NULL, tds_dstr_cstr(&bcpcol->column_name), tds_dstr_len(&bcpcol->column_name)) + strlen(column_type) + ((first) ? 2u : 4u)) { char *temp = (char*) malloc(2 * clause->cb); if (!temp) { tdserror(tds_get_ctx(tds), tds, TDSEMEM, errno); return TDS_FAIL; } strcpy(temp, clause->pb); if (clause->from_malloc) free(clause->pb); clause->from_malloc = 1; clause->pb = temp; clause->cb *= 2; } if (!first) strcat(clause->pb, ", "); tds_quote_id(tds, strchr(clause->pb, 0), tds_dstr_cstr(&bcpcol->column_name), tds_dstr_len(&bcpcol->column_name)); strcat(clause->pb, " "); strcat(clause->pb, column_type); return TDS_SUCCESS; }
int tds_config_boolean(const char *value) { int p; for (p = 0; p < TDS_VECTOR_SIZE(boolean_values); ++p) { if (!strcasecmp(value, boolean_values[p].value)) return boolean_values[p].to_return; } tdsdump_log(TDS_DBG_INFO1, "UNRECOGNIZED boolean value: '%s'. Treating as 'no'.\n", value); return 0; }
static void tds_config_env_tdsver(TDSLOGIN * login) { char *tdsver; if ((tdsver = getenv("TDSVER"))) { TDS_USMALLINT *pver = tds_config_verstr(tdsver, login); tdsdump_log(TDS_DBG_INFO1, "TDS version %sset to %s from $TDSVER.\n", (pver? "":"not "), tdsver); } return; }
/* TDSHOST env var, [email protected] 01/21/02 */ static void tds_config_env_tdshost(TDSLOGIN * login) { const char *tdshost; char tmp[128]; struct tds_addrinfo *addrs; if (!(tdshost = getenv("TDSHOST"))) return; if (TDS_FAILED(tds_lookup_host_set(tdshost, &login->ip_addrs))) { tdsdump_log(TDS_DBG_WARN, "Name resolution failed for '%s' from $TDSHOST.\n", tdshost); return; } tds_dstr_copy(&login->server_host_name, tdshost); for (addrs = login->ip_addrs; addrs != NULL; addrs = addrs->ai_next) { tdsdump_log(TDS_DBG_INFO1, "Setting IP Address to %s (%s) from $TDSHOST.\n", tds_addrinfo2str(addrs, tmp, sizeof(tmp)), tdshost); } }
static void tds_config_env_tdsver(TDSCONNECTINFO * connect_info) { char *tdsver; if ((tdsver = getenv("TDSVER"))) { tds_config_verstr(tdsver, connect_info); tdsdump_log(TDS_DBG_INFO1, "%L Setting 'tdsver' to %s from $TDSVER.\n", tdsver); } return; }
static void tds_config_env_tdsport(TDSLOGIN * login) { char *s; if ((s = getenv("TDSPORT"))) { login->port = tds_lookup_port(s); tds_dstr_empty(&login->instance_name); tdsdump_log(TDS_DBG_INFO1, "Setting 'port' to %s from $TDSPORT.\n", s); } return; }
int tds_config_boolean(const char *option, const char *value, TDSLOGIN *login) { int ret = tds_parse_boolean(value, -1); if (ret >= 0) return ret; tdsdump_log(TDS_DBG_ERROR, "UNRECOGNIZED option value '%s' for boolean setting '%s'!\n", value, option); login->valid_configuration = 0; return 0; }
int parse_prepared_query(struct _hstmt *stmt, int compute_row) { /* try setting this parameter */ TDSPARAMINFO *temp_params; int nparam = stmt->params ? stmt->params->num_cols : 0; if (stmt->prepared_pos) return prepared_rpc(stmt, compute_row); tdsdump_log(TDS_DBG_FUNC, "parsing %d parameters\n", nparam); for (; stmt->param_num <= stmt->param_count; ++nparam, ++stmt->param_num) { /* find bound parameter */ if (stmt->param_num > stmt->apd->header.sql_desc_count || stmt->param_num > stmt->ipd->header.sql_desc_count) { tdsdump_log(TDS_DBG_FUNC, "parse_prepared_query: logic_error: parameter out of bounds: " "%d > %d || %d > %d\n", stmt->param_num, stmt->apd->header.sql_desc_count, stmt->param_num, stmt->ipd->header.sql_desc_count); return SQL_ERROR; } /* add a column to parameters */ if (!(temp_params = tds_alloc_param_result(stmt->params))) { odbc_errs_add(&stmt->errs, "HY001", NULL); return SQL_ERROR; } stmt->params = temp_params; switch (odbc_sql2tds (stmt, &stmt->ipd->records[stmt->param_num - 1], &stmt->apd->records[stmt->param_num - 1], stmt->params->columns[nparam], compute_row, stmt->apd, stmt->curr_param_row)) { case SQL_ERROR: return SQL_ERROR; case SQL_NEED_DATA: return SQL_NEED_DATA; } } return SQL_SUCCESS; }
void tds_env_change(TDSSOCKET * tds, int type, const char *oldvalue, const char *newvalue) { TDS_SMALLINT totsize; /* If oldvalue is NULL, treat it like "" */ if (oldvalue == NULL) oldvalue = ""; /* * NOTE: I don't know why each type of environment value has a different * format. According to the TDS5 specifications, they should all use * the same format. The code for the TDS_ENV_CHARSET case *should* * work for all environment values. -- Steve Kirkendall */ switch (type) { case TDS_ENV_DATABASE: case TDS_ENV_LANG: case TDS_ENV_PACKSIZE: case TDS_ENV_CHARSET: tds_put_byte(tds, TDS_ENVCHANGE_TOKEN); /* totsize = type + newlen + newvalue + oldlen + oldvalue */ /* FIXME ucs2 */ totsize = (IS_TDS7_PLUS(tds->conn) ? 2 : 1) * (strlen(oldvalue) + strlen(newvalue)) + 3; tds_put_smallint(tds, totsize); tds_put_byte(tds, type); tds_put_byte(tds, strlen(newvalue)); /* FIXME this assume singlebyte -> ucs2 for mssql */ tds_put_string(tds, newvalue, strlen(newvalue)); tds_put_byte(tds, strlen(oldvalue)); /* FIXME this assume singlebyte -> ucs2 for mssql */ tds_put_string(tds, oldvalue, strlen(oldvalue)); break; case TDS_ENV_LCID: case TDS_ENV_SQLCOLLATION: #if 1 tds_put_byte(tds, TDS_ENVCHANGE_TOKEN); /* totsize = type + len + oldvalue + len + newvalue */ totsize = 3 + strlen(newvalue) + strlen(oldvalue); tds_put_smallint(tds, totsize); tds_put_byte(tds, type); tds_put_byte(tds, strlen(newvalue)); tds_put_n(tds, newvalue, strlen(newvalue)); tds_put_byte(tds, strlen(oldvalue)); tds_put_n(tds, oldvalue, strlen(oldvalue)); break; #endif default: tdsdump_log(TDS_DBG_WARN, "tds_env_change() ignoring unsupported environment code #%d", type); } }
/** * Inputs are FreeTDS canonical names, no other. No alias list is consulted. */ iconv_t tds_sys_iconv_open (const char* tocode, const char* fromcode) { int i; unsigned int fromto; const char *enc_name; unsigned char encodings[2]; static char first_time = 1; if (first_time) { first_time = 0; tdsdump_log(TDS_DBG_INFO1, "Using trivial iconv\n"); } /* match both inputs to our canonical names */ enc_name = fromcode; for (i=0; i < 2; ++i) { unsigned char encoding; if (strcmp(enc_name, "ISO-8859-1") == 0) encoding = 0; else if (strcmp(enc_name, "US-ASCII") == 0) encoding = 1; else if (strcmp(enc_name, "UCS-2LE") == 0 || strcmp(enc_name, "UTF-16LE") == 0) encoding = 2; else if (strcmp(enc_name, "UCS-2BE") == 0 || strcmp(enc_name, "UTF-16BE") == 0) encoding = 3; else if (strcmp(enc_name, "UCS-4LE") == 0) encoding = 4; else if (strcmp(enc_name, "UCS-4BE") == 0) encoding = 5; else if (strcmp(enc_name, "UTF-8") == 0) encoding = 6; else { errno = EINVAL; return (iconv_t)(-1); } encodings[i] = encoding; enc_name = tocode; } fromto = (encodings[0] << 4) | (encodings[1] & 0x0F); /* like to like */ if (encodings[0] == encodings[1]) { fromto = Like_to_Like; } return (iconv_t) (TDS_INTPTR) fromto; }
static void tds_config_encryption(const char * value, TDSLOGIN * login) { TDS_ENCRYPTION_LEVEL lvl = TDS_ENCRYPTION_OFF; if (!strcasecmp(value, TDS_STR_ENCRYPTION_OFF)) ; else if (!strcasecmp(value, TDS_STR_ENCRYPTION_REQUEST)) lvl = TDS_ENCRYPTION_REQUEST; else if (!strcasecmp(value, TDS_STR_ENCRYPTION_REQUIRE)) lvl = TDS_ENCRYPTION_REQUIRE; else { tdsdump_log(TDS_DBG_ERROR, "UNRECOGNIZED option value '%s' for '%s' setting!\n", value, TDS_STR_ENCRYPTION); tdsdump_log(TDS_DBG_ERROR, "Valid settings are: ('%s', '%s', '%s')\n", TDS_STR_ENCRYPTION_OFF, TDS_STR_ENCRYPTION_REQUEST, TDS_STR_ENCRYPTION_REQUIRE); lvl = TDS_ENCRYPTION_REQUIRE; /* Assuming "require" is safer than "no" */ login->valid_configuration = 0; } login->encryption_level = lvl; }
/** * Set TDS version from given string * @param tdsver tds string version * @param login where to store information * @return as encoded hex value: high nybble major, low nybble minor. */ TDS_USMALLINT * tds_config_verstr(const char *tdsver, TDSLOGIN * login) { static const struct tdsvername_t tds_versions[] = { { "0", 0x000 } , {"auto", 0x000 } , { "4.2", 0x402 } , { "4.2", 0x402 } , { "46", 0x406 } , { "4.6", 0x406 } , { "50", 0x500 } , { "5.0", 0x500 } , { "70", 0x700 } , { "7.0", 0x700 } , { "80", 0x701 } , { "8.0", 0x701 } , { "7.1", 0x701 } , { "7.2", 0x702 } , { "7.3", 0x703 } , { "7.4", 0x704 } }; const struct tdsvername_t *pver; if (!login) { assert(login); return NULL; } if ((pver = (const struct tdsvername_t *) TDS_FIND(tdsver, tds_versions, tds_vernanme_cmp)) == NULL) { tdsdump_log(TDS_DBG_INFO1, "error: no such version: %s\n", tdsver); return NULL; } login->tds_version = pver->version; tdsdump_log(TDS_DBG_INFO1, "Setting tds version to %s (0x%0x).\n", tdsver, pver->version); return &login->tds_version; }
CS_RETCODE cs_loc_alloc(CS_CONTEXT * ctx, CS_LOCALE ** locptr) { CS_LOCALE *tds_csloc; tdsdump_log(TDS_DBG_FUNC, "cs_loc_alloc(%p, %p)\n", ctx, locptr); tds_csloc = _cs_locale_alloc(); if (!tds_csloc) return CS_FAIL; *locptr = tds_csloc; return CS_SUCCEED; }
CS_RETCODE cs_ctx_drop(CS_CONTEXT * ctx) { tdsdump_log(TDS_DBG_FUNC, "cs_ctx_drop(%p)\n", ctx); if (ctx) { _ct_diag_clearmsg(ctx, CS_ALLMSG_TYPE); free(ctx->userdata); if (ctx->tds_ctx) tds_free_context(ctx->tds_ctx); free(ctx); } return CS_SUCCEED; }
int tds_config_boolean(const char *option, const char *value, TDSLOGIN *login) { int p; for (p = 0; p < TDS_VECTOR_SIZE(boolean_values); ++p) { if (!strcasecmp(value, boolean_values[p].value)) return boolean_values[p].to_return; } tdsdump_log(TDS_DBG_ERROR, "UNRECOGNIZED option value '%s' for boolean setting '%s'!\n", value, option); login->valid_configuration = 0; return 0; }
static char * _cs_get_msgstr(const char *funcname, int layer, int origin, int severity, int number) { char *m; tdsdump_log(TDS_DBG_FUNC, "_cs_get_msgstr(%s, %d, %d, %d, %d)\n", funcname, layer, origin, severity, number); if (asprintf(&m, "%s: %s: %s: %s", funcname, _cs_get_layer(layer), _cs_get_origin(origin), (layer == 2) ? _cs_get_user_api_layer_error(number) : "unrecognized error") < 0) { return NULL; } return m; }
/* TDSHOST env var, [email protected] 01/21/02 */ static void tds_config_env_tdshost(TDSCONNECTINFO * connect_info) { char *tdshost; char tmp[256]; if ((tdshost = getenv("TDSHOST"))) { tds_lookup_host(tdshost, tmp); tds_dstr_copy(&connect_info->ip_addr, tmp); tdsdump_log(TDS_DBG_INFO1, "%L Setting 'ip_addr' to %s (%s) from $TDSHOST.\n", tmp, tdshost); } return; }
static const char * _cs_get_layer(int layer) { tdsdump_log(TDS_DBG_FUNC, "_cs_get_layer(%d)\n", layer); switch (layer) { case 2: return "cslib user api layer"; break; default: break; } return "unrecognized layer"; }
/** * \ingroup odbc_bcp * \brief Prepare for bulk copy operation on a table * * \param dbc ODBC database connection object * \param tblname the name of the table receiving or providing the data. * \param hfile the data file opposite the table, if any. NB: The current * implementation does not support file I/O so this must be NULL * \param errfile the "error file" captures messages and, if errors are * encountered. NB: The current implementation does not support * file I/O so this must be NULL * \param direction one of * - \b DB_IN writing to the table * - \b DB_OUT writing to the host file (Not currently supported) * . * \remarks bcp_init() sets the host file data format and acquires the table metadata. * It is called before the other bulk copy functions. * * The ODBC BCP functionality should be accessed via the inline functions in * odbcss.h. * * After calling this function, call bcp_bind() to associate your data with * the appropriate table column. * * \sa SQL_COPT_SS_BCP, odbc_bcp_bind(), odbc_bcp_done(), odbc_bcp_exec() */ void odbc_bcp_init(TDS_DBC *dbc, const ODBC_CHAR *tblname, const ODBC_CHAR *hfile, const ODBC_CHAR *errfile, int direction _WIDE) { /* TODO convert unicode for printing */ tdsdump_log(TDS_DBG_FUNC, "bcp_init(%p, %s, %s, %s, %d)\n", dbc, tblname, hfile, errfile, direction); if (!tblname) ODBCBCP_ERROR_RETURN("HY009"); /* Free previously allocated storage in dbproc & initialise flags, etc. */ odbc_bcp_free_storage(dbc); /* * Validate other parameters */ if (dbc->tds_socket->conn->tds_version < 0x500) ODBCBCP_ERROR_RETURN("HYC00"); if (direction != BCP_DIRECTION_IN || hfile || errfile) ODBCBCP_ERROR_RETURN("HYC00"); /* Allocate storage */ dbc->bcpinfo = tds_alloc_bcpinfo(); if (dbc->bcpinfo == NULL) ODBCBCP_ERROR_RETURN("HY001"); if (!odbc_dstr_copy(dbc, &dbc->bcpinfo->tablename, SQL_NTS, tblname)) { odbc_bcp_free_storage(dbc); ODBCBCP_ERROR_RETURN("HY001"); } if (tds_dstr_len(&dbc->bcpinfo->tablename) > 92 && !IS_TDS7_PLUS(dbc->tds_socket->conn)) { /* 30.30.30 */ odbc_bcp_free_storage(dbc); ODBCBCP_ERROR_RETURN("HYC00"); } dbc->bcpinfo->direction = direction; dbc->bcpinfo->xfer_init = 0; dbc->bcpinfo->bind_count = 0; if (TDS_FAILED(tds_bcp_init(dbc->tds_socket, dbc->bcpinfo))) { /* TODO return proper error */ /* Attempt to use Bulk Copy with a non-existent Server table (might be why ...) */ ODBCBCP_ERROR_RETURN("HY000"); } }