LCOV - code coverage report
Current view: top level - src/tds - mem.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 663 982 67.5 %
Date: 2025-01-18 11:50:39 Functions: 59 60 98.3 %

          Line data    Source code
       1             : /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
       2             :  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005  Brian Bruns
       3             :  * Copyright (C) 2005-2015 Frediano Ziglio
       4             :  *
       5             :  * This library is free software; you can redistribute it and/or
       6             :  * modify it under the terms of the GNU Library General Public
       7             :  * License as published by the Free Software Foundation; either
       8             :  * version 2 of the License, or (at your option) any later version.
       9             :  *
      10             :  * This library is distributed in the hope that it will be useful,
      11             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13             :  * Library General Public License for more details.
      14             :  *
      15             :  * You should have received a copy of the GNU Library General Public
      16             :  * License along with this library; if not, write to the
      17             :  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      18             :  * Boston, MA 02111-1307, USA.
      19             :  */
      20             : 
      21             : #include <config.h>
      22             : 
      23             : #include <stdlib.h>
      24             : 
      25             : #if HAVE_UNISTD_H
      26             : #include <unistd.h>
      27             : #endif /* HAVE_UNISTD_H */
      28             : 
      29             : #include <assert.h>
      30             : 
      31             : #include <freetds/tds.h>
      32             : #include <freetds/iconv.h>
      33             : #include <freetds/tls.h>
      34             : #include <freetds/checks.h>
      35             : #include <freetds/utils/string.h>
      36             : #include <freetds/replacements.h>
      37             : #include <freetds/enum_cap.h>
      38             : #include <freetds/utils.h>
      39             : 
      40             : #if HAVE_SYS_SOCKET_H
      41             : #include <sys/socket.h>
      42             : #endif
      43             : 
      44             : #ifdef HAVE_STRING_H
      45             : #include <string.h>
      46             : #endif
      47             : 
      48             : #ifdef HAVE_LOCALE_H
      49             : #include <locale.h>
      50             : #endif /* HAVE_LOCALE_H */
      51             : 
      52             : #ifdef HAVE_LANGINFO_H
      53             : #include <langinfo.h>
      54             : #endif /* HAVE_LANGINFO_H */
      55             : 
      56             : static void tds_free_env(TDSCONNECTION * conn);
      57             : static void tds_free_compute_results(TDSSOCKET * tds);
      58             : static void tds_free_compute_result(TDSCOMPUTEINFO * comp_info);
      59             : 
      60             : #undef TEST_MALLOC
      61             : #define TEST_MALLOC(dest,type) \
      62             :         {if (!(dest = (type*)calloc(1, sizeof(type)))) goto Cleanup;}
      63             : 
      64             : #undef TEST_CALLOC
      65             : #define TEST_CALLOC(dest,type,n) \
      66             :         {if (!(dest = (type*)calloc((n), sizeof(type)))) goto Cleanup;}
      67             : 
      68             : /**
      69             :  * \ingroup libtds
      70             :  * \defgroup mem Memory allocation
      71             :  * Allocate or free resources. Allocation can fail only on out of memory. 
      72             :  * In such case they return NULL and leave the state as before call.
      73             :  * Mainly function names are in the form tds_alloc_XX or tds_free_XXX.
      74             :  * tds_alloc_XXX functions allocate structures and return pointer to allocated
      75             :  * data while tds_free_XXX take structure pointers and free them. Some functions
      76             :  * require additional parameters to initialize structure correctly.
      77             :  * The main exception are structures that use reference counting. These structures
      78             :  * have tds_alloc_XXX functions but instead of tds_free_XXX use tds_release_XXX.
      79             :  */
      80             : 
      81             : /**
      82             :  * \addtogroup mem
      83             :  * @{
      84             :  */
      85             : 
      86             : static volatile unsigned int inc_num = 1;
      87             : 
      88             : /**
      89             :  * Get an id for dynamic query based on TDS information
      90             :  * \param conn state information for the connection and the TDS protocol
      91             :  * \return TDS_FAIL or TDS_SUCCESS
      92             :  */
      93             : static char *
      94      526188 : tds_get_dynid(TDSCONNECTION * conn, char *id)
      95             : {
      96             :         unsigned long n;
      97             :         int i;
      98             :         char *p;
      99             :         char c;
     100             : 
     101             :         CHECK_CONN_EXTRA(conn);
     102             : 
     103      526188 :         inc_num = (inc_num + 1) & 0xffff;
     104             :         /* some version of Sybase require length <= 10, so we code id */
     105      526188 :         n = (unsigned long) (TDS_INTPTR) conn;
     106      526188 :         p = id;
     107      526188 :         *p++ = (char) ('a' + (n % 26u));
     108      526188 :         n /= 26u;
     109     5261880 :         for (i = 0; i < 9; ++i) {
     110     4735692 :                 c = (char) ('0' + (n % 36u));
     111     4735692 :                 *p++ = (c < ('0' + 10)) ? c : c + ('a' - '0' - 10);
     112             :                 /* tdsdump_log(TDS_DBG_INFO1, "%d -> %d(%c)\n", (int) (n%36u),p[-1],p[-1]); */
     113     4735692 :                 n /= 36u;
     114     4735692 :                 if (i == 4)
     115      526188 :                         n += 3u * inc_num;
     116             :         }
     117      526188 :         *p = 0;
     118      526188 :         return id;
     119             : }
     120             : 
     121             : #include <freetds/pushvis.h>
     122             : extern const TDSCOLUMNFUNCS tds_invalid_funcs;
     123             : #include <freetds/popvis.h>
     124             : 
     125             : static TDSCOLUMN *
     126       81880 : tds_alloc_column(void)
     127             : {
     128             :         TDSCOLUMN *col;
     129             : 
     130       81880 :         TEST_MALLOC(col, TDSCOLUMN);
     131      163760 :         tds_dstr_init(&col->table_name);
     132      163760 :         tds_dstr_init(&col->column_name);
     133      163760 :         tds_dstr_init(&col->table_column_name);
     134       81880 :         col->funcs = &tds_invalid_funcs;
     135             : 
     136       81880 :       Cleanup:
     137       81880 :         return col;
     138             : }
     139             : 
     140             : static void
     141       81820 : tds_free_column(TDSCOLUMN *col)
     142             : {
     143       81820 :         tds_dstr_free(&col->table_name);
     144       81820 :         tds_dstr_free(&col->column_name);
     145       81820 :         tds_dstr_free(&col->table_column_name);
     146       81820 :         free(col);
     147       81820 : }
     148             : 
     149             : 
     150             : /**
     151             :  * \fn TDSDYNAMIC *tds_alloc_dynamic(TDSCONNECTION *conn, const char *id)
     152             :  * \brief Allocate a dynamic statement.
     153             :  * \param conn the connection within which to allocate the statement.
     154             :  * \param id a character label identifying the statement.
     155             :  * \return a pointer to the allocated structure (NULL on failure).
     156             :  *
     157             :  * tds_alloc_dynamic is used to implement placeholder code under TDS 5.0
     158             :  */
     159             : TDSDYNAMIC *
     160      526196 : tds_alloc_dynamic(TDSCONNECTION * conn, const char *id)
     161             : {
     162             :         TDSDYNAMIC *dyn;
     163             :         char tmp_id[30];
     164             : 
     165      526196 :         if (id) {
     166             :                 /* check to see if id already exists (shouldn't) */
     167          16 :                 if (tds_lookup_dynamic(conn, id))
     168             :                         return NULL;
     169             :         } else {
     170             :                 unsigned int n;
     171             :                 id = tmp_id;
     172             : 
     173             :                 for (n = 0;;) {
     174      526188 :                         if (!tds_lookup_dynamic(conn, tds_get_dynid(conn, tmp_id)))
     175             :                                 break;
     176           8 :                         if (++n == 256)
     177             :                                 return NULL;
     178             :                 }
     179             :         }
     180             : 
     181      526196 :         TEST_MALLOC(dyn, TDSDYNAMIC);
     182             : 
     183             :         /* take into account pointer in list */
     184      526196 :         dyn->ref_count = 2;
     185             : 
     186             :         /* insert into list */
     187      526196 :         dyn->next = conn->dyns;
     188      526196 :         conn->dyns = dyn;
     189             : 
     190      526196 :         strlcpy(dyn->id, id, TDS_MAX_DYNID_LEN);
     191             : 
     192      526196 :         return dyn;
     193             : 
     194      526196 :       Cleanup:
     195             :         return NULL;
     196             : }
     197             : 
     198             : /**
     199             :  * \fn void tds_free_input_params(TDSDYNAMIC *dyn)
     200             :  * \brief Frees all allocated input parameters of a dynamic statement.
     201             :  * \param dyn the dynamic statement whose input parameter are to be freed
     202             :  *
     203             :  * tds_free_input_params frees all parameters for the give dynamic statement
     204             :  */
     205             : void
     206        1102 : tds_free_input_params(TDSDYNAMIC * dyn)
     207             : {
     208             :         TDSPARAMINFO *info;
     209             : 
     210      527298 :         info = dyn->params;
     211      527298 :         if (info) {
     212        1088 :                 tds_free_param_results(info);
     213         738 :                 dyn->params = NULL;
     214             :         }
     215        1102 : }
     216             : 
     217             : /*
     218             :  * Called when dynamic got deallocated from server
     219             :  */
     220             : void
     221      526356 : tds_dynamic_deallocated(TDSCONNECTION *conn, TDSDYNAMIC *dyn)
     222             : {
     223             :         TDSDYNAMIC **victim;
     224             : 
     225      526356 :         tdsdump_log(TDS_DBG_FUNC, "tds_dynamic_deallocated() : freeing dynamic_id %s\n", dyn->id);
     226             : 
     227      526356 :         victim = &conn->dyns;
     228     1052872 :         while (*victim != dyn) {
     229         320 :                 if (*victim == NULL) {
     230         160 :                         tdsdump_log(TDS_DBG_FUNC, "tds_dynamic_deallocated() : cannot find id %s\n", dyn->id);
     231             :                         return;
     232             :                 }
     233         160 :                 victim = &(*victim)->next;
     234             :         }
     235             : 
     236             :         /* remove from list */
     237      526196 :         *victim = dyn->next;
     238      526196 :         dyn->next = NULL;
     239             : 
     240             :         /* assure there is no id left */
     241      526196 :         dyn->num_id = 0;
     242             : 
     243      526196 :         tds_release_dynamic(&dyn);
     244             : }
     245             : 
     246             : 
     247             : /**
     248             :  * \fn void tds_release_dynamic(TDSDYNAMIC **pdyn)
     249             :  * \brief Frees dynamic statement
     250             :  * \param pdyn pointer to dynamic statement to be freed.
     251             :  */
     252             : void
     253     1127921 : tds_release_dynamic(TDSDYNAMIC ** pdyn)
     254             : {
     255             :         TDSDYNAMIC *dyn;
     256             : 
     257     1127921 :         dyn = *pdyn;
     258     1127921 :         *pdyn = NULL;
     259     1127921 :         if (!dyn || --dyn->ref_count > 0)
     260             :                 return;
     261             : 
     262     1052392 :         tds_detach_results(dyn->res_info);
     263             : 
     264      526196 :         tds_free_results(dyn->res_info);
     265      526196 :         tds_free_input_params(dyn);
     266      526196 :         free(dyn->query);
     267      526196 :         free(dyn);
     268             : }
     269             : 
     270             : /**
     271             :  * \fn TDSPARAMINFO *tds_alloc_param_result(TDSPARAMINFO *old_param)
     272             :  * \brief Adds a output parameter to TDSPARAMINFO.
     273             :  * \param old_param a pointer to the TDSPARAMINFO structure containing the 
     274             :  * current set of output parameter, or NULL if none exists.
     275             :  * \return a pointer to the new TDSPARAMINFO structure.
     276             :  *
     277             :  * tds_alloc_param_result() works a bit differently than the other alloc result
     278             :  * functions.  Output parameters come in individually with no total number 
     279             :  * given in advance, so we simply call this func every time with get a
     280             :  * TDS_PARAM_TOKEN and let it realloc the columns struct one bigger. 
     281             :  * tds_free_all_results() usually cleans up after us.
     282             :  */
     283             : TDSPARAMINFO *
     284       32358 : tds_alloc_param_result(TDSPARAMINFO * old_param)
     285             : {
     286             :         TDSPARAMINFO *param_info;
     287             :         TDSCOLUMN *colinfo;
     288             : 
     289             :         /* parameters cannot have row associated */
     290       32358 :         if (old_param && (old_param->current_row || old_param->row_free))
     291             :                 return NULL;
     292             : 
     293       32358 :         colinfo = tds_alloc_column();
     294       32358 :         if (!colinfo)
     295             :                 return NULL;
     296             : 
     297       32358 :         param_info = old_param;
     298       32358 :         if (!param_info) {
     299       23336 :                 TEST_MALLOC(param_info, TDSPARAMINFO);
     300       23336 :                 param_info->ref_count = 1;
     301             :         }
     302             : 
     303       32358 :         if (!TDS_RESIZE(param_info->columns, param_info->num_cols + 1u))
     304             :                 goto Cleanup;
     305             : 
     306       32358 :         param_info->columns[param_info->num_cols++] = colinfo;
     307       32358 :         return param_info;
     308             : 
     309           0 :       Cleanup:
     310           0 :         if (!old_param)
     311           0 :                 free(param_info);
     312           0 :         free(colinfo);
     313           0 :         return NULL;
     314             : }
     315             : 
     316             : /**
     317             :  * Delete latest parameter
     318             :  */
     319             : void
     320          18 : tds_free_param_result(TDSPARAMINFO * param_info)
     321             : {
     322             :         TDSCOLUMN *col;
     323             : 
     324          18 :         if (!param_info || param_info->num_cols <= 0)
     325             :                 return;
     326             : 
     327          18 :         col = param_info->columns[--param_info->num_cols];
     328          18 :         if (col->column_data && col->column_data_free)
     329          18 :                 col->column_data_free(col);
     330             : 
     331          18 :         if (param_info->num_cols == 0)
     332          18 :                 TDS_ZERO_FREE(param_info->columns);
     333             : 
     334             :         /*
     335             :          * NOTE some information should be freed too but when this function
     336             :          * is called are not used. I hope to remove the need for this
     337             :          * function ASAP
     338             :          * A better way is to support different way to allocate and get
     339             :          * parameters
     340             :          * -- freddy77
     341             :          */
     342          18 :         tds_free_column(col);
     343             : }
     344             : 
     345             : static void
     346             : tds_free_tvp_row(TDS_TVP_ROW *row)
     347             : {
     348          36 :         tds_free_param_results(row->params);
     349             : }
     350             : 
     351             : static void
     352       19696 : tds_param_free(TDSCOLUMN *col)
     353             : {
     354       19696 :         if (!col->column_data)
     355             :                 return;
     356             : 
     357       19696 :         if (col->column_type == SYBMSTABLE) {
     358           4 :                 tds_deinit_tvp((TDS_TVP *) col->column_data);
     359       19692 :         } else if (is_blob_col(col)) {
     360        1714 :                 TDSBLOB *blob = (TDSBLOB *) col->column_data;
     361        1714 :                 free(blob->textvalue);
     362             :         }
     363             : 
     364       19696 :         TDS_ZERO_FREE(col->column_data);
     365             : }
     366             : 
     367             : /**
     368             :  * Allocate data for a parameter.
     369             :  * @param curparam parameter to retrieve size information
     370             :  * @return NULL on failure or new data
     371             :  */
     372             : void *
     373       19696 : tds_alloc_param_data(TDSCOLUMN * curparam)
     374             : {
     375             :         TDS_INT data_size;
     376             :         void *data;
     377             : 
     378       19696 :         CHECK_COLUMN_EXTRA(curparam);
     379             : 
     380       19696 :         data_size = curparam->funcs->row_len(curparam);
     381             : 
     382             :         /* allocate data */
     383       19696 :         if (curparam->column_data && curparam->column_data_free)
     384           0 :                 curparam->column_data_free(curparam);
     385       19696 :         curparam->column_data_free = tds_param_free;
     386             : 
     387       19696 :         data = malloc(data_size);
     388       19696 :         curparam->column_data = (unsigned char*) data;
     389       19696 :         if (!data)
     390             :                 return NULL;
     391             :         /* if is a blob reset buffer */
     392       19696 :         if (is_blob_col(curparam) || curparam->column_type == SYBMSTABLE)
     393        1718 :                 memset(data, 0, data_size);
     394             : 
     395             :         return data;
     396             : }
     397             : 
     398             : /**
     399             :  * Allocate memory for storing compute info
     400             :  * return NULL on out of memory
     401             :  */
     402             : 
     403             : static TDSCOMPUTEINFO *
     404          72 : tds_alloc_compute_result(TDS_USMALLINT num_cols, TDS_USMALLINT by_cols)
     405             : {
     406             :         TDS_USMALLINT col;
     407             :         TDSCOMPUTEINFO *info;
     408             : 
     409          72 :         TEST_MALLOC(info, TDSCOMPUTEINFO);
     410          72 :         info->ref_count = 1;
     411             : 
     412          72 :         TEST_CALLOC(info->columns, TDSCOLUMN *, num_cols);
     413             : 
     414          72 :         info->num_cols = num_cols;
     415         144 :         for (col = 0; col < num_cols; col++)
     416          72 :                 if (!(info->columns[col] = tds_alloc_column()))
     417             :                         goto Cleanup;
     418             : 
     419          72 :         if (by_cols) {
     420          24 :                 TEST_CALLOC(info->bycolumns, TDS_SMALLINT, by_cols);
     421          24 :                 info->by_cols = by_cols;
     422             :         }
     423             : 
     424             :         return info;
     425           0 :       Cleanup:
     426           0 :         tds_free_compute_result(info);
     427           0 :         return NULL;
     428             : }
     429             : 
     430             : TDSCOMPUTEINFO **
     431          72 : tds_alloc_compute_results(TDSSOCKET * tds, TDS_USMALLINT num_cols, TDS_USMALLINT by_cols)
     432             : {
     433             :         TDS_UINT n;
     434             :         TDSCOMPUTEINFO **comp_info;
     435             :         TDSCOMPUTEINFO *cur_comp_info;
     436             : 
     437          72 :         tdsdump_log(TDS_DBG_FUNC, "alloc_compute_result. num_cols = %d bycols = %d\n", num_cols, by_cols);
     438          72 :         tdsdump_log(TDS_DBG_FUNC, "alloc_compute_result. num_comp_info = %d\n", tds->num_comp_info);
     439             : 
     440          72 :         cur_comp_info = tds_alloc_compute_result(num_cols, by_cols);
     441          72 :         if (!cur_comp_info)
     442             :                 return NULL;
     443             : 
     444          72 :         n = tds->num_comp_info;
     445          72 :         comp_info = (TDSCOMPUTEINFO **) TDS_RESIZE(tds->comp_info, n + 1u);
     446          72 :         if (!comp_info) {
     447           0 :                 tds_free_compute_result(cur_comp_info);
     448           0 :                 return NULL;
     449             :         }
     450             : 
     451          72 :         tds->comp_info = comp_info;
     452          72 :         comp_info[n] = cur_comp_info;
     453          72 :         tds->num_comp_info = n + 1u;
     454             : 
     455          72 :         tdsdump_log(TDS_DBG_FUNC, "alloc_compute_result. num_comp_info = %d\n", tds->num_comp_info);
     456             : 
     457             :         return comp_info;
     458             : }
     459             : 
     460             : TDSRESULTINFO *
     461       28040 : tds_alloc_results(TDS_USMALLINT num_cols)
     462             : {
     463             :         TDSRESULTINFO *res_info;
     464             :         TDS_USMALLINT col;
     465             : 
     466       28040 :         TEST_MALLOC(res_info, TDSRESULTINFO);
     467       28040 :         res_info->ref_count = 1;
     468       28040 :         if (num_cols)
     469       27890 :                 TEST_CALLOC(res_info->columns, TDSCOLUMN *, num_cols);
     470       49450 :         for (col = 0; col < num_cols; col++)
     471       49450 :                 if (!(res_info->columns[col] = tds_alloc_column()))
     472             :                         goto Cleanup;
     473       28040 :         res_info->num_cols = num_cols;
     474       28040 :         res_info->row_size = 0;
     475       28040 :         return res_info;
     476           0 :       Cleanup:
     477           0 :         tds_free_results(res_info);
     478           0 :         return NULL;
     479             : }
     480             : 
     481             : void
     482      337328 : tds_set_current_results(TDSSOCKET *tds, TDSRESULTINFO *info)
     483             : {
     484      337328 :         tds_detach_results(info);
     485      337328 :         if (tds->current_results)
     486         470 :                 tds->current_results->attached_to = NULL;
     487      337328 :         if (info)
     488      337322 :                 info->attached_to = tds;
     489      337328 :         tds->in_row = (info != NULL);
     490      337328 :         tds->current_results = info;
     491      337328 : }
     492             : 
     493             : /**
     494             :  * Detach result info from it current socket
     495             :  */
     496             : void
     497           0 : tds_detach_results(TDSRESULTINFO *info)
     498             : {
     499     1142615 :         if (info && info->attached_to) {
     500      336846 :                 info->attached_to->current_results = NULL;
     501      336846 :                 info->attached_to->in_row = false;
     502      336846 :                 info->attached_to = NULL;
     503             :         }
     504           0 : }
     505             : 
     506             : static void
     507       27650 : tds_row_free(TDSRESULTINFO *res_info, unsigned char *row)
     508             : {
     509             :         int i;
     510             :         const TDSCOLUMN *col;
     511             : 
     512       27650 :         if (!res_info || !row)
     513             :                 return;
     514             : 
     515       49268 :         for (i = 0; i < res_info->num_cols; ++i) {
     516       49268 :                 col = res_info->columns[i];
     517             :                 
     518       49268 :                 if (is_blob_col(col)) {
     519        2940 :                         TDSBLOB *blob = (TDSBLOB *) &row[col->column_data - res_info->current_row];
     520        2940 :                         if (blob->textvalue)
     521        2384 :                                 TDS_ZERO_FREE(blob->textvalue);
     522             :                 }
     523             :         }
     524             : 
     525       27650 :         free(row);
     526             : }
     527             : 
     528             : /**
     529             :  * Allocate space for row store
     530             :  * return NULL on out of memory
     531             :  */
     532             : TDSRET
     533       27674 : tds_alloc_row(TDSRESULTINFO * res_info)
     534             : {
     535       27674 :         int i, num_cols = res_info->num_cols;
     536             :         unsigned char *ptr;
     537             :         TDSCOLUMN *col;
     538             :         TDS_UINT row_size;
     539             : 
     540             :         /* compute row size */
     541       27674 :         row_size = 0;
     542       77002 :         for (i = 0; i < num_cols; ++i) {
     543       49328 :                 col = res_info->columns[i];
     544             : 
     545       49328 :                 col->column_data_free = NULL;
     546             : 
     547       49328 :                 row_size += col->funcs->row_len(col);
     548       49328 :                 row_size += (TDS_ALIGN_SIZE - 1);
     549       49328 :                 row_size -= row_size % TDS_ALIGN_SIZE;
     550             :         }
     551       27674 :         res_info->row_size = row_size;
     552             : 
     553       27674 :         ptr = tds_new0(unsigned char, row_size ? row_size : 1);
     554       27674 :         res_info->current_row = ptr;
     555       27674 :         if (!ptr)
     556             :                 return TDS_FAIL;
     557       27674 :         res_info->row_free = tds_row_free;
     558             : 
     559             :         /* fill column_data */
     560       27674 :         row_size = 0;
     561       77002 :         for (i = 0; i < num_cols; ++i) {
     562       49328 :                 col = res_info->columns[i];
     563             : 
     564       49328 :                 col->column_data = ptr + row_size;
     565             : 
     566       49328 :                 row_size += col->funcs->row_len(col);
     567       49328 :                 row_size += (TDS_ALIGN_SIZE - 1);
     568       49328 :                 row_size -= row_size % TDS_ALIGN_SIZE;
     569             :         }
     570             : 
     571             :         return TDS_SUCCESS;
     572             : }
     573             : 
     574             : TDSRET
     575          72 : tds_alloc_compute_row(TDSCOMPUTEINFO * res_info)
     576             : {
     577          72 :         return tds_alloc_row(res_info);
     578             : }
     579             : 
     580             : void
     581       81123 : tds_free_param_results(TDSPARAMINFO * param_info)
     582             : {
     583      190851 :         tds_free_results(param_info);
     584       81123 : }
     585             : 
     586             : static void
     587             : tds_free_compute_result(TDSCOMPUTEINFO * comp_info)
     588             : {
     589          72 :         tds_free_results(comp_info);
     590             : }
     591             : 
     592             : static void
     593      108614 : tds_free_compute_results(TDSSOCKET * tds)
     594             : {
     595      108614 :         TDSCOMPUTEINFO ** comp_info = tds->comp_info;
     596      108614 :         TDS_UINT i, num_comp = tds->num_comp_info;
     597             : 
     598      108614 :         tds->comp_info = NULL;
     599      108614 :         tds->num_comp_info = 0;
     600             : 
     601      108686 :         for (i = 0; i < num_comp; i++) {
     602          72 :                 if (comp_info && comp_info[i]) {
     603         144 :                         tds_detach_results(comp_info[i]);
     604          72 :                         tds_free_compute_result(comp_info[i]);
     605             :                 }
     606             :         }
     607      108614 :         if (num_comp)
     608          48 :                 free(comp_info);
     609      108614 : }
     610             : 
     611             : void
     612      156461 : tds_free_row(TDSRESULTINFO * res_info, unsigned char *row)
     613             : {
     614      156461 :         assert(res_info);
     615      156461 :         if (!row || !res_info->row_free)
     616             :                 return;
     617             : 
     618        2176 :         res_info->row_free(res_info, row);
     619             : }
     620             : 
     621             : void
     622     1079872 : tds_free_results(TDSRESULTINFO * res_info)
     623             : {
     624             :         int i;
     625             :         TDSCOLUMN *curcol;
     626             : 
     627     1079872 :         if (!res_info)
     628             :                 return;
     629             : 
     630      217451 :         if (--res_info->ref_count != 0)
     631             :                 return;
     632             : 
     633       51424 :         tds_detach_results(res_info);
     634             : 
     635       51424 :         if (res_info->num_cols && res_info->columns) {
     636       81802 :                 for (i = 0; i < res_info->num_cols; i++)
     637       81802 :                         if ((curcol = res_info->columns[i]) != NULL) {
     638       81802 :                                 if (curcol->bcp_terminator)
     639          42 :                                         TDS_ZERO_FREE(curcol->bcp_terminator);
     640       81802 :                                 tds_free_bcp_column_data(curcol->bcp_column_data);
     641       81802 :                                 curcol->bcp_column_data = NULL;
     642       81802 :                                 if (curcol->column_data && curcol->column_data_free)
     643       20102 :                                         curcol->column_data_free(curcol);
     644             :                         }
     645             :         }
     646             : 
     647       51424 :         if (res_info->current_row && res_info->row_free)
     648       25548 :                 res_info->row_free(res_info, res_info->current_row);
     649             : 
     650       51424 :         if (res_info->num_cols && res_info->columns) {
     651       81802 :                 for (i = 0; i < res_info->num_cols; i++)
     652       81802 :                         if ((curcol = res_info->columns[i]) != NULL)
     653       81802 :                                 tds_free_column(curcol);
     654       51406 :                 free(res_info->columns);
     655             :         }
     656             : 
     657       51424 :         free(res_info->bycolumns);
     658             : 
     659       51424 :         free(res_info);
     660             : }
     661             : 
     662             : void
     663      108614 : tds_free_all_results(TDSSOCKET * tds)
     664             : {
     665      108614 :         tdsdump_log(TDS_DBG_FUNC, "tds_free_all_results()\n");
     666      217228 :         tds_detach_results(tds->res_info);
     667      108614 :         tds_free_results(tds->res_info);
     668      108614 :         tds->res_info = NULL;
     669      217228 :         tds_detach_results(tds->param_info);
     670      217228 :         tds_free_param_results(tds->param_info);
     671      108614 :         tds->param_info = NULL;
     672      108614 :         tds_free_compute_results(tds);
     673      108614 :         tds->has_status = false;
     674      108614 :         tds->in_row = false;
     675      108614 :         tds->ret_status = 0;
     676      108614 :         if (tds->cur_dyn)
     677        4815 :                 tds_detach_results(tds->cur_dyn->res_info);
     678      108614 : }
     679             : 
     680             : /*
     681             :  * Return true if winsock is initialized, else false.
     682             :  */
     683             : static bool
     684             : winsock_initialized(void)
     685             : {
     686             : #ifdef _WIN32
     687             :         static bool initialized = false;
     688             :         static tds_mutex mtx = TDS_MUTEX_INITIALIZER;
     689             : 
     690             :         int erc;
     691             : 
     692             :         if (initialized)
     693             :                 return true;
     694             : 
     695             :         tds_mutex_lock(&mtx);
     696             :         /* same check inside the mutex */
     697             :         if (initialized) {
     698             :                 tds_mutex_unlock(&mtx);
     699             :                 return true;
     700             :         }
     701             : 
     702             :         /* initialize the socket layer */
     703             :         erc = tds_socket_init();
     704             :         initialized = (erc == 0);
     705             :         tds_mutex_unlock(&mtx);
     706             : 
     707             :         if (erc != 0) {
     708             :                 char *errstr = sock_strerror(erc);
     709             :                 tdsdump_log(TDS_DBG_ERROR, "tds_init_winsock: WSAStartup failed with %d (%s)\n", erc, errstr);
     710             :                 sock_strerror_free(errstr);
     711             :                 return false;
     712             :         }
     713             : #endif
     714             :         return true;
     715             : }
     716             : 
     717             : TDSCONTEXT *
     718        2883 : tds_alloc_context(void * parent)
     719             : {
     720             :         TDSCONTEXT *context;
     721             :         TDSLOCALE *locale;
     722             : 
     723             :         if (!winsock_initialized())
     724             :                 return NULL;
     725             : 
     726        2883 :         if ((locale = tds_get_locale()) == NULL)
     727             :                 return NULL;
     728             : 
     729        2883 :         if ((context = tds_new0(TDSCONTEXT, 1)) == NULL) {
     730           0 :                 tds_free_locale(locale);
     731           0 :                 return NULL;
     732             :         }
     733        2883 :         context->locale = locale;
     734        2883 :         context->parent = parent;
     735        2883 :         context->money_use_2_digits = false;
     736             : 
     737        2883 :         return context;
     738             : }
     739             : 
     740             : void
     741        2859 : tds_free_context(TDSCONTEXT * context)
     742             : {
     743        2859 :         if (!context)
     744             :                 return;
     745             : 
     746        2859 :         tds_free_locale(context->locale);
     747        2859 :         free(context);
     748             : }
     749             : 
     750             : TDSLOCALE *
     751        2947 : tds_alloc_locale(void)
     752             : {
     753             :         TDSLOCALE *locale;
     754             : 
     755        2947 :         TEST_MALLOC(locale, TDSLOCALE);
     756             : 
     757             :         return locale;
     758             : 
     759           0 :       Cleanup:
     760           0 :         tds_free_locale(locale);
     761           0 :         return NULL;
     762             : }
     763             : 
     764             : /*
     765             :  * Default capabilities.
     766             :  */
     767             : #undef REQ
     768             : #define SUPPORTED_REQ_CAP(i) \
     769             :         REQ(i,LANG) REQ(i,RPC) REQ(i,EVT) REQ(i,MSTMT) REQ(i,BCP) REQ(i,CURSOR) REQ(i,DYNF) \
     770             :         REQ(i,MSG) REQ(i,PARAM) REQ(i,DATA_INT1) REQ(i,DATA_INT2) REQ(i,DATA_INT4) REQ(i,DATA_BIT) \
     771             :         REQ(i,DATA_CHAR) REQ(i,DATA_VCHAR) REQ(i,DATA_BIN) REQ(i,DATA_VBIN) REQ(i,DATA_MNY8) \
     772             :         REQ(i,DATA_MNY4) REQ(i,DATA_DATE8) REQ(i,DATA_DATE4) REQ(i,DATA_FLT4) REQ(i,DATA_FLT8) \
     773             :         REQ(i,DATA_NUM) REQ(i,DATA_TEXT) REQ(i,DATA_IMAGE) REQ(i,DATA_DEC) REQ(i,DATA_LCHAR) \
     774             :         REQ(i,DATA_LBIN) REQ(i,DATA_INTN) REQ(i,DATA_DATETIMEN) REQ(i,DATA_MONEYN) \
     775             :         REQ(i,CSR_PREV) REQ(i,CSR_FIRST) REQ(i,CSR_LAST) REQ(i,CSR_ABS) REQ(i,CSR_REL) \
     776             :         REQ(i,CSR_MULTI) REQ(i,CON_INBAND) REQ(i,PROTO_TEXT) REQ(i,PROTO_BULK) \
     777             :         REQ(i,DATA_SENSITIVITY) REQ(i,DATA_BOUNDARY) REQ(i,PROTO_DYNPROC) REQ(i,DATA_FLTN) \
     778             :         REQ(i,DATA_BITN) REQ(i,DATA_INT8) REQ(i,WIDETABLE) \
     779             :         REQ(i,DATA_UINT2) REQ(i,DATA_UINT4) REQ(i,DATA_UINT8) REQ(i,DATA_UINTN) REQ(i,LARGEIDENT) \
     780             :         REQ(i,SRVPKTSIZE) REQ(i,DATA_DATE) REQ(i,DATA_TIME) REQ(i,DATA_BIGTIME) REQ(i,DATA_BIGDATETIME)
     781             : #define REQ(i,n) |(((TDS_REQ_ ## n / 8) == i)?(1<<(TDS_REQ_ ## n & 7)):0)
     782             : #define REQB(i) 0 SUPPORTED_REQ_CAP(i)
     783             : 
     784             : #undef RES
     785             : #define SUPPORTED_RES_CAP(i) \
     786             :         RES(i,CON_NOOOB) RES(i,PROTO_NOTEXT) RES(i,PROTO_NOBULK) RES(i,NOTDSDEBUG)
     787             : #define RES(i,n) |(((TDS_RES_ ## n / 8) == i)?(1<<(TDS_RES_ ## n & 7)):0)
     788             : #define RESB(i) 0 SUPPORTED_RES_CAP(i)
     789             : 
     790             : static const TDS_CAPABILITIES defaultcaps = { {
     791             :      /* type,  len, data, data, data, data, data, data, data, data, data, data, data, data, data, data (14 bytes) */
     792             :         { 1, 14, { REQB(13), REQB(12), REQB(11), REQB(10), REQB(9), REQB(8), REQB(7),
     793             :                    REQB(6),  REQB(5),  REQB(4),  REQB(3),  REQB(2), REQB(1), REQB(0) } },
     794             :         { 2, 14, { RESB(13), RESB(12), RESB(11), RESB(10), RESB(9), RESB(8), RESB(7),
     795             :                    RESB(6),  RESB(5),  RESB(4),  RESB(3),  RESB(2), RESB(1), RESB(0) } }
     796             : } };
     797             : /* check we match the values size */
     798             : TDS_COMPILE_CHECK(tds_values_len, sizeof(defaultcaps.types[0].values) == 14);
     799             : /* check we match the default size */
     800             : TDS_COMPILE_CHECK(tds_cap_len, sizeof(defaultcaps) == TDS_MAX_CAPABILITY);
     801             : 
     802             : /**
     803             :  * Initialize login structure with locale information and other stuff for connection
     804             :  * @param locale locale information (copied to configuration information)
     805             :  * @result login structure or NULL if initialization error
     806             :  */
     807             : TDSLOGIN*
     808        3041 : tds_init_login(TDSLOGIN *login, TDSLOCALE * locale)
     809             : {
     810             :         char hostname[128];
     811             : #if HAVE_NL_LANGINFO && defined(CODESET)
     812             :         const char *charset;
     813             : #elif !defined(_WIN32)
     814             :         char *lc_all, *tok = NULL;
     815             : #endif
     816             : #ifdef _WIN32
     817             :         char cp[128];
     818             : #endif
     819             : 
     820             :         /*
     821             :          * TDS 7.0:
     822             :          * ODBC driver settings.
     823             :          * Change to initial language must succeed.
     824             :          */
     825        3041 :         login->option_flag2 = TDS_INIT_LANG_REQUIRED|TDS_ODBC_ON;
     826        3041 :         login->tds_version = TDS_DEFAULT_VERSION;
     827        3041 :         login->block_size = 0;
     828             : 
     829             : #if HAVE_NL_LANGINFO && defined(CODESET)
     830        3041 :         charset = nl_langinfo(CODESET);
     831        3041 :         if (strcmp(tds_canonical_charset_name(charset), "US-ASCII") == 0)
     832        3029 :                 charset = "ISO-8859-1";
     833        3041 :         if (!tds_dstr_copy(&login->client_charset, charset))
     834             :                 return NULL;
     835             : #else
     836             :         if (!tds_dstr_copy(&login->client_charset, "ISO-8859-1"))
     837             :                 return NULL;
     838             : 
     839             : #ifdef _WIN32
     840             :         /* for Windows uses GetLocaleInfoA */
     841             :         strcpy(cp, "CP");
     842             :         if (GetLocaleInfoA(GetThreadLocale(), LOCALE_IDEFAULTANSICODEPAGE, cp + 2, sizeof(cp) - 2) > 0)
     843             :                 if (!tds_dstr_copy(&login->client_charset, cp))
     844             :                         return NULL;
     845             : #else
     846             :         if ((lc_all = strdup(setlocale(LC_ALL, NULL))) == NULL)
     847             :                 return NULL;
     848             : 
     849             :         if (strtok_r(lc_all, ".", &tok)) {
     850             :                 char *encoding = strtok_r(NULL, "@", &tok);
     851             :                 if (encoding) {
     852             :                         if (!tds_dstr_copy(&login->client_charset, encoding)) {
     853             :                                 free(lc_all);
     854             :                                 return NULL;
     855             :                         }
     856             :                 }
     857             :         }
     858             :         free(lc_all);
     859             : #endif
     860             : #endif
     861             : 
     862        3041 :         if (locale) {
     863        3041 :                 if (locale->language)
     864           0 :                         if (!tds_dstr_copy(&login->language, locale->language))
     865             :                                 return NULL;
     866        3041 :                 if (locale->server_charset)
     867           0 :                         if (!tds_dstr_copy(&login->server_charset, locale->server_charset))
     868             :                                 return NULL;
     869             :         }
     870        6082 :         if (tds_dstr_isempty(&login->language)) {
     871        2985 :                 if (!tds_dstr_copy(&login->language, TDS_DEF_LANG))
     872             :                         return NULL;
     873             :         }
     874        3041 :         memset(hostname, '\0', sizeof(hostname));
     875        3041 :         gethostname(hostname, sizeof(hostname));
     876        3041 :         hostname[sizeof(hostname) - 1] = '\0';  /* make sure it's terminated */
     877        3041 :         if (!tds_dstr_copy(&login->client_host_name, hostname))
     878             :                 return NULL;
     879             : 
     880        3041 :         login->valid_configuration = 1;
     881        3041 :         login->check_ssl_hostname = 1;
     882             : 
     883        3041 :         return login;
     884             : }
     885             : 
     886             : TDSCURSOR *
     887        1742 : tds_alloc_cursor(TDSSOCKET *tds, const char *name, TDS_INT namelen, const char *query, TDS_INT querylen)
     888             : {
     889             :         TDSCURSOR *cursor;
     890             :         TDSCURSOR *pcursor;
     891             : 
     892        1742 :         TEST_MALLOC(cursor, TDSCURSOR);
     893        1742 :         cursor->ref_count = 1;
     894             : 
     895        1742 :         cursor->type = TDS_CUR_TYPE_KEYSET;
     896        1742 :         cursor->concurrency = TDS_CUR_CONCUR_OPTIMISTIC;
     897             : 
     898        1742 :         TEST_CALLOC(cursor->cursor_name, char, namelen + 1);
     899        1742 :         memcpy(cursor->cursor_name, name, namelen);
     900             : 
     901        1742 :         TEST_CALLOC(cursor->query, char, querylen + 1);
     902        1742 :         memcpy(cursor->query, query, querylen);
     903             : 
     904        1742 :         if (tds->conn->cursors == NULL) {
     905        1716 :                 tds->conn->cursors = cursor;
     906             :         } else {
     907           0 :                 for (pcursor = tds->conn->cursors; pcursor->next; pcursor = pcursor->next)
     908           0 :                         continue;
     909          26 :                 pcursor->next = cursor;
     910             :         }
     911             :         /* take into account reference in connection list */
     912        1742 :         ++cursor->ref_count;
     913             : 
     914        1742 :         return cursor;
     915             : 
     916           0 :       Cleanup:
     917           0 :         tds_release_cursor(&cursor);
     918           0 :         return NULL;
     919             : }
     920             : 
     921             : /*
     922             :  * Called when cursor got deallocated from server
     923             :  */
     924             : void
     925        1742 : tds_cursor_deallocated(TDSCONNECTION *conn, TDSCURSOR *cursor)
     926             : {
     927             :         TDSCURSOR **victim;
     928             : 
     929        1742 :         tdsdump_log(TDS_DBG_FUNC, "tds_cursor_deallocated() : freeing cursor_id %d\n", cursor->cursor_id);
     930             : 
     931        1742 :         victim = &conn->cursors;
     932        3496 :         while (*victim != cursor) {
     933          12 :                 if (*victim == NULL) {
     934           0 :                         tdsdump_log(TDS_DBG_FUNC, "tds_cursor_deallocated() : cannot find cursor_id %d\n", cursor->cursor_id);
     935             :                         return;
     936             :                 }
     937          12 :                 victim = &(*victim)->next;
     938             :         }
     939             : 
     940             :         /* remove from list */
     941        1742 :         *victim = cursor->next;
     942        1742 :         cursor->next = NULL;
     943             : 
     944        1742 :         tds_release_cursor(&cursor);
     945             : }
     946             : 
     947             : /*
     948             :  * Decrement reference counter and free if necessary.
     949             :  * Called internally by libTDS and by upper library when you don't need 
     950             :  * cursor reference anymore
     951             :  */
     952             : void
     953       68658 : tds_release_cursor(TDSCURSOR **pcursor)
     954             : {
     955       68658 :         TDSCURSOR *cursor = *pcursor;
     956       68658 :         *pcursor = NULL;
     957       68658 :         if (!cursor || --cursor->ref_count > 0)
     958             :                 return;
     959             : 
     960        1742 :         tdsdump_log(TDS_DBG_FUNC, "tds_release_cursor() : freeing cursor_id %d\n", cursor->cursor_id);
     961             : 
     962        1742 :         tdsdump_log(TDS_DBG_FUNC, "tds_release_cursor() : freeing cursor results\n");
     963        3484 :         tds_detach_results(cursor->res_info);
     964        1742 :         tds_free_results(cursor->res_info);
     965             : 
     966        1742 :         if (cursor->cursor_name) {
     967        1742 :                 tdsdump_log(TDS_DBG_FUNC, "tds_release_cursor() : freeing cursor name\n");
     968        1742 :                 free(cursor->cursor_name);
     969             :         }
     970             : 
     971        1742 :         if (cursor->query) {
     972        1742 :                 tdsdump_log(TDS_DBG_FUNC, "tds_release_cursor() : freeing cursor query\n");
     973        1742 :                 free(cursor->query);
     974             :         }
     975             : 
     976        1742 :         tdsdump_log(TDS_DBG_FUNC, "tds_release_cursor() : cursor_id %d freed\n", cursor->cursor_id);
     977        1742 :         free(cursor);
     978             : }
     979             : 
     980             : TDSLOGIN *
     981        5858 : tds_alloc_login(bool use_environment)
     982             : {
     983        5858 :         TDSLOGIN *login = NULL;
     984        5858 :         const char *server_name = TDS_DEF_SERVER;
     985             : 
     986        5858 :         TEST_MALLOC(login, TDSLOGIN);
     987        5858 :         login->check_ssl_hostname = 1;
     988        5858 :         login->use_utf16 = 1;
     989        5858 :         login->bulk_copy = 1;
     990       11716 :         tds_dstr_init(&login->server_name);
     991       11716 :         tds_dstr_init(&login->language);
     992       11716 :         tds_dstr_init(&login->server_charset);
     993       11716 :         tds_dstr_init(&login->client_host_name);
     994       11716 :         tds_dstr_init(&login->server_host_name);
     995       11716 :         tds_dstr_init(&login->app_name);
     996       11716 :         tds_dstr_init(&login->user_name);
     997       11716 :         tds_dstr_init(&login->password);
     998       11716 :         tds_dstr_init(&login->library);
     999       11716 :         tds_dstr_init(&login->new_password);
    1000             : 
    1001        5858 :         login->ip_addrs = NULL;
    1002             : 
    1003       11716 :         tds_dstr_init(&login->database);
    1004        5858 :         login->dump_file = NULL;
    1005       11716 :         tds_dstr_init(&login->client_charset);
    1006       11716 :         tds_dstr_init(&login->instance_name);
    1007       11716 :         tds_dstr_init(&login->server_realm_name);
    1008       11716 :         tds_dstr_init(&login->server_spn);
    1009       11716 :         tds_dstr_init(&login->cafile);
    1010       11716 :         tds_dstr_init(&login->crlfile);
    1011       11716 :         tds_dstr_init(&login->certificate_host_name);
    1012       11716 :         tds_dstr_init(&login->db_filename);
    1013       11716 :         tds_dstr_init(&login->openssl_ciphers);
    1014       11716 :         tds_dstr_init(&login->routing_address);
    1015             : 
    1016        5858 :         if (use_environment) {
    1017             :                 const char *s;
    1018        2817 :                 if ((s=getenv("DSQUERY")) != NULL)
    1019           0 :                         server_name = s;
    1020             : 
    1021        2817 :                 if ((s=getenv("TDSQUERY")) != NULL)
    1022           0 :                         server_name = s;
    1023             :         }
    1024             : 
    1025        5858 :         if (!tds_dstr_copy(&login->server_name, server_name)) {
    1026           0 :                 free(login);
    1027           0 :                 return NULL;
    1028             :         }
    1029             : 
    1030        5858 :         login->capabilities = defaultcaps;
    1031        5858 :         login->use_ntlmv2_specified = 0;
    1032        5858 :         login->use_ntlmv2 = 1;
    1033             : 
    1034           0 : Cleanup:
    1035             :         return login;
    1036             : }
    1037             : 
    1038             : void
    1039        6550 : tds_free_login(TDSLOGIN * login)
    1040             : {
    1041        6550 :         if (!login)
    1042             :                 return;
    1043             : 
    1044             :         /* for security reason clear memory */
    1045        5832 :         tds_dstr_zero(&login->password);
    1046        5832 :         tds_dstr_free(&login->password);
    1047        5832 :         tds_dstr_zero(&login->new_password);
    1048        5832 :         tds_dstr_free(&login->new_password);
    1049        5832 :         tds_dstr_free(&login->server_name);
    1050        5832 :         tds_dstr_free(&login->language);
    1051        5832 :         tds_dstr_free(&login->server_charset);
    1052        5832 :         tds_dstr_free(&login->client_host_name);
    1053        5832 :         tds_dstr_free(&login->app_name);
    1054        5832 :         tds_dstr_free(&login->user_name);
    1055        5832 :         tds_dstr_free(&login->library);
    1056        5832 :         tds_dstr_free(&login->client_charset);
    1057        5832 :         tds_dstr_free(&login->server_host_name);
    1058             : 
    1059        5832 :         if (login->ip_addrs != NULL)
    1060        3039 :                 freeaddrinfo(login->ip_addrs);
    1061             : 
    1062        5832 :         tds_dstr_free(&login->database);
    1063        5832 :         free(login->dump_file);
    1064        5832 :         tds_dstr_free(&login->instance_name);
    1065        5832 :         tds_dstr_free(&login->server_realm_name);
    1066        5832 :         tds_dstr_free(&login->server_spn);
    1067        5832 :         tds_dstr_free(&login->cafile);
    1068        5832 :         tds_dstr_free(&login->crlfile);
    1069        5832 :         tds_dstr_free(&login->certificate_host_name);
    1070        5832 :         tds_dstr_free(&login->db_filename);
    1071        5832 :         tds_dstr_free(&login->openssl_ciphers);
    1072        5832 :         tds_dstr_free(&login->routing_address);
    1073        5832 :         free(login);
    1074             : }
    1075             : 
    1076             : TDSPACKET *
    1077       12647 : tds_alloc_packet(void *buf, unsigned len)
    1078             : {
    1079       12647 :         TDSPACKET *packet = (TDSPACKET *) malloc(len + TDS_OFFSET(TDSPACKET, buf));
    1080       12647 :         if (TDS_LIKELY(packet)) {
    1081        8768 :                 tds_packet_zero_data_start(packet);
    1082       12647 :                 packet->data_len = 0;
    1083       12647 :                 packet->capacity = len;
    1084       12647 :                 packet->sid = 0;
    1085       12647 :                 packet->next = NULL;
    1086       12647 :                 if (buf) {
    1087         113 :                         memcpy(packet->buf, buf, len);
    1088         113 :                         packet->data_len = len;
    1089             :                 }
    1090             :         }
    1091       12647 :         return packet;
    1092             : }
    1093             : 
    1094             : TDSPACKET *
    1095       39737 : tds_realloc_packet(TDSPACKET *packet, unsigned len)
    1096             : {
    1097       45722 :         if (packet->capacity < len) {
    1098        4991 :                 packet = (TDSPACKET *) realloc(packet, len + TDS_OFFSET(TDSPACKET, buf));
    1099        4991 :                 if (TDS_LIKELY(packet))
    1100        4991 :                         packet->capacity = len;
    1101             :         }
    1102       39737 :         return packet;
    1103             : }
    1104             : 
    1105             : void
    1106       41398 : tds_free_packets(TDSPACKET *packet)
    1107             : {
    1108             :         TDSPACKET *next;
    1109       53985 :         for (; packet; packet = next) {
    1110       12587 :                 next = packet->next;
    1111       12587 :                 free(packet);
    1112             :         }
    1113       41398 : }
    1114             : 
    1115             : static void
    1116        3805 : tds_deinit_connection(TDSCONNECTION *conn)
    1117             : {
    1118        3805 :         if (conn->authentication)
    1119           0 :                 conn->authentication->free(conn, conn->authentication);
    1120        3805 :         conn->authentication = NULL;
    1121        7650 :         while (conn->dyns)
    1122          40 :                 tds_dynamic_deallocated(conn, conn->dyns);
    1123        3817 :         while (conn->cursors)
    1124          12 :                 tds_cursor_deallocated(conn, conn->cursors);
    1125        3805 :         tds_ssl_deinit(conn);
    1126             :         /* close connection and free inactive sockets */
    1127        3805 :         tds_connection_close(conn);
    1128        3805 :         tds_wakeup_close(&conn->wakeup);
    1129        3805 :         tds_iconv_free(conn);
    1130        3805 :         free(conn->product_name);
    1131        3805 :         free(conn->server);
    1132        3805 :         tds_free_env(conn);
    1133        7610 :         tds_free_packets(conn->packet_cache);
    1134        3805 :         tds_mutex_free(&conn->list_mtx);
    1135             : #if ENABLE_ODBC_MARS
    1136        3842 :         tds_free_packets(conn->packets);
    1137        3842 :         tds_free_packets(conn->recv_packet);
    1138        3842 :         tds_free_packets(conn->send_packets);
    1139        1921 :         free(conn->sessions);
    1140             : #endif
    1141        3805 : }
    1142             : 
    1143             : static TDSCONNECTION *
    1144        3829 : tds_init_connection(TDSCONNECTION *conn, TDSCONTEXT *context, unsigned int bufsize)
    1145             : {
    1146        3829 :         conn->env.block_size = bufsize;
    1147        3829 :         conn->s = INVALID_SOCKET;
    1148        3829 :         conn->use_iconv = 1;
    1149        3829 :         conn->tds_ctx = context;
    1150        3829 :         conn->ncharsize = 1;
    1151        3829 :         conn->unicharsize = 1;
    1152             : 
    1153        3829 :         if (tds_wakeup_init(&conn->wakeup))
    1154             :                 goto Cleanup;
    1155             : 
    1156        3829 :         if (tds_iconv_alloc(conn))
    1157             :                 goto Cleanup;
    1158             : 
    1159        7658 :         if (tds_mutex_init(&conn->list_mtx))
    1160             :                 goto Cleanup;
    1161             : 
    1162             : #if ENABLE_ODBC_MARS
    1163        1933 :         TEST_CALLOC(conn->sessions, TDSSOCKET*, 64);
    1164        1933 :         conn->num_sessions = 64;
    1165             : #endif
    1166        1933 :         return conn;
    1167             : 
    1168           0 : Cleanup:
    1169           0 :         tds_wakeup_close(&conn->wakeup);
    1170           0 :         tds_iconv_free(conn);
    1171           0 :         return NULL;
    1172             : }
    1173             : 
    1174             : static TDSSOCKET *
    1175        3834 : tds_init_socket(TDSSOCKET * tds_socket, unsigned int bufsize)
    1176             : {
    1177             :         TDSPACKET *pkt;
    1178             : 
    1179        3834 :         tds_socket->parent = NULL;
    1180             : 
    1181        3834 :         tds_socket->recv_packet = tds_alloc_packet(NULL, bufsize);
    1182        3834 :         if (!tds_socket->recv_packet)
    1183             :                 goto Cleanup;
    1184        3834 :         tds_socket->in_buf = tds_socket->recv_packet->buf;
    1185             : 
    1186        3834 :         pkt = tds_alloc_packet(NULL, bufsize + TDS_ADDITIONAL_SPACE);
    1187        3834 :         if (!pkt)
    1188             :                 goto Cleanup;
    1189        3834 :         tds_set_current_send_packet(tds_socket, pkt);
    1190             : 
    1191        3834 :         tds_socket->out_buf_max = bufsize;
    1192             : 
    1193             :         /* Jeff's hack, init to no timeout */
    1194        3834 :         tds_socket->query_timeout = 0;
    1195        3834 :         tds_init_write_buf(tds_socket);
    1196        3834 :         tds_socket->state = TDS_DEAD;
    1197        3834 :         tds_socket->env_chg_func = NULL;
    1198        7668 :         if (tds_mutex_init(&tds_socket->wire_mtx))
    1199             :                 goto Cleanup;
    1200             : 
    1201             : #ifdef ENABLE_ODBC_MARS
    1202        1938 :         tds_socket->sid = 0;
    1203        1938 :         if (tds_cond_init(&tds_socket->packet_cond))
    1204             :                 goto Cleanup;
    1205             : 
    1206        1938 :         tds_socket->recv_seq = 0;
    1207        1938 :         tds_socket->send_seq = 0;
    1208        1938 :         tds_socket->recv_wnd = 4;
    1209        1938 :         tds_socket->send_wnd = 4;
    1210             : #endif
    1211        1938 :         return tds_socket;
    1212             : 
    1213           0 :       Cleanup:
    1214             :         return NULL;
    1215             : }
    1216             : 
    1217             : 
    1218             : #if ENABLE_ODBC_MARS
    1219             : static void
    1220        1921 : tds_free_connection(TDSCONNECTION *conn)
    1221             : {
    1222        1921 :         if (!conn) return;
    1223        1921 :         assert(conn->in_net_tds == NULL);
    1224        1921 :         tds_deinit_connection(conn);
    1225        1921 :         free(conn);
    1226             : }
    1227             : 
    1228             : static TDSCONNECTION *
    1229        1933 : tds_alloc_connection(TDSCONTEXT *context, unsigned int bufsize)
    1230             : {
    1231             :         TDSCONNECTION *conn;
    1232             : 
    1233        1933 :         TEST_MALLOC(conn, TDSCONNECTION);
    1234        1933 :         if (!tds_init_connection(conn, context, bufsize))
    1235             :                 goto Cleanup;
    1236             :         return conn;
    1237             : 
    1238           0 : Cleanup:
    1239           0 :         tds_free_connection(conn);
    1240           0 :         return NULL;
    1241             : }
    1242             : 
    1243             : static TDSSOCKET *
    1244        1938 : tds_alloc_socket_base(unsigned int bufsize)
    1245             : {
    1246             :         TDSSOCKET *tds_socket;
    1247             : 
    1248        1938 :         TEST_MALLOC(tds_socket, TDSSOCKET);
    1249        1938 :         if (!tds_init_socket(tds_socket, bufsize))
    1250             :                 goto Cleanup;
    1251             :         return tds_socket;
    1252             : 
    1253           0 :       Cleanup:
    1254           0 :         tds_free_socket(tds_socket);
    1255           0 :         return NULL;
    1256             : }
    1257             : 
    1258             : TDSSOCKET *
    1259        1933 : tds_alloc_socket(TDSCONTEXT * context, unsigned int bufsize)
    1260             : {
    1261        1933 :         TDSCONNECTION *conn = tds_alloc_connection(context, bufsize);
    1262             :         TDSSOCKET *tds;
    1263             : 
    1264        1933 :         if (!conn)
    1265             :                 return NULL;
    1266             : 
    1267        1933 :         tds = tds_alloc_socket_base(bufsize);
    1268        1933 :         if (tds) {
    1269        1933 :                 conn->sessions[0] = tds;
    1270        1933 :                 tds->conn = conn;
    1271        1933 :                 return tds;
    1272             :         }
    1273           0 :         tds_free_connection(conn);
    1274           0 :         return NULL;
    1275             : }
    1276             : 
    1277             : static bool
    1278           5 : tds_alloc_new_sid(TDSSOCKET *tds)
    1279             : {
    1280             :         uint16_t sid;
    1281           5 :         TDSCONNECTION *conn = tds->conn;
    1282             : 
    1283           5 :         tds_mutex_lock(&conn->list_mtx);
    1284           7 :         for (sid = 1; sid < conn->num_sessions; ++sid)
    1285           7 :                 if (!conn->sessions[sid])
    1286             :                         break;
    1287           5 :         if (sid == conn->num_sessions) {
    1288             :                 /* extend array */
    1289           0 :                 TDSSOCKET **s = (TDSSOCKET **) TDS_RESIZE(conn->sessions, sid+64);
    1290           0 :                 if (!s)
    1291             :                         goto error;
    1292           0 :                 memset(s + conn->num_sessions, 0, sizeof(*s) * 64);
    1293           0 :                 conn->num_sessions += 64;
    1294             :         }
    1295           5 :         conn->sessions[sid] = tds;
    1296           5 :         tds->sid = sid;
    1297           5 : error:
    1298           5 :         tds_mutex_unlock(&conn->list_mtx);
    1299           5 :         return tds->sid != 0;
    1300             : }
    1301             : 
    1302             : TDSSOCKET *
    1303          11 : tds_alloc_additional_socket(TDSCONNECTION *conn)
    1304             : {
    1305             :         TDSSOCKET *tds;
    1306          11 :         if (!IS_TDS72_PLUS(conn) || !conn->mars)
    1307             :                 return NULL;
    1308             : 
    1309           5 :         tds = tds_alloc_socket_base(sizeof(TDS72_SMP_HEADER) + conn->env.block_size);
    1310           5 :         if (!tds)
    1311             :                 return NULL;
    1312           5 :         tds->send_packet->data_start = sizeof(TDS72_SMP_HEADER);
    1313           5 :         tds->out_buf = tds->send_packet->buf + sizeof(TDS72_SMP_HEADER);
    1314           5 :         tds->out_buf_max -= sizeof(TDS72_SMP_HEADER);
    1315             : 
    1316           5 :         tds->conn = conn;
    1317           5 :         if (!tds_alloc_new_sid(tds))
    1318             :                 goto Cleanup;
    1319             : 
    1320           5 :         tds->state = TDS_IDLE;
    1321           5 :         if (TDS_FAILED(tds_append_syn(tds)))
    1322             :                 goto Cleanup;
    1323             : 
    1324             :         return tds;
    1325             : 
    1326           0 :       Cleanup:
    1327           0 :         tds_free_socket(tds);
    1328           0 :         return NULL;
    1329             : }
    1330             : #else /* !ENABLE_ODBC_MARS */
    1331             : TDSSOCKET *
    1332        1896 : tds_alloc_socket(TDSCONTEXT * context, unsigned int bufsize)
    1333             : {
    1334             :         TDSSOCKET *tds_socket;
    1335             : 
    1336        1896 :         TEST_MALLOC(tds_socket, TDSSOCKET);
    1337        1896 :         if (!tds_init_connection(tds_socket->conn, context, bufsize))
    1338             :                 goto Cleanup;
    1339        1896 :         if (!tds_init_socket(tds_socket, bufsize))
    1340             :                 goto Cleanup;
    1341             :         return tds_socket;
    1342             : 
    1343           0 :       Cleanup:
    1344           0 :         tds_free_socket(tds_socket);
    1345           0 :         return NULL;
    1346             : }
    1347             : #endif /* !ENABLE_ODBC_MARS */
    1348             : 
    1349             : TDSSOCKET *
    1350        5985 : tds_realloc_socket(TDSSOCKET * tds, size_t bufsize)
    1351             : {
    1352             :         TDSPACKET *packet;
    1353             : #if ENABLE_ODBC_MARS
    1354        3063 :         size_t smp_hdr_len = tds->conn->mars ? sizeof(TDS72_SMP_HEADER) : 0;
    1355             : #else
    1356             :         enum { smp_hdr_len = 0 };
    1357             : #endif
    1358             : 
    1359        5985 :         assert(tds && tds->out_buf && tds->send_packet);
    1360             : 
    1361        5985 :         if (bufsize < 512)
    1362           0 :                 bufsize = 512;
    1363             : 
    1364             :         /* prevent nasty memory conditions, server should send the request at
    1365             :          * the beginning only */
    1366        5985 :         if (tds->out_pos > bufsize || tds->frozen)
    1367             :                 return NULL;
    1368             : 
    1369        5985 :         tds->conn->env.block_size = bufsize;
    1370             : 
    1371       11970 :         packet = tds_realloc_packet(tds->send_packet, smp_hdr_len + bufsize + TDS_ADDITIONAL_SPACE);
    1372        5985 :         if (packet == NULL)
    1373             :                 return NULL;
    1374             : 
    1375             : #if ENABLE_ODBC_MARS
    1376        3063 :         packet->data_start = smp_hdr_len;
    1377             : #endif
    1378        5985 :         tds->out_buf_max = bufsize;
    1379        5985 :         tds_set_current_send_packet(tds, packet);
    1380        5985 :         return tds;
    1381             : }
    1382             : 
    1383             : #if ENABLE_ODBC_MARS
    1384             : static void
    1385        1926 : tds_connection_remove_socket(TDSCONNECTION *conn, TDSSOCKET *tds)
    1386             : {
    1387             :         unsigned n;
    1388        1926 :         bool must_free_connection = true;
    1389        1926 :         tds_mutex_lock(&conn->list_mtx);
    1390        1926 :         if (tds->sid < conn->num_sessions)
    1391        1926 :                 conn->sessions[tds->sid] = NULL;
    1392      124870 :         for (n = 0; n < conn->num_sessions; ++n)
    1393      122949 :                 if (TDSSOCKET_VALID(conn->sessions[n])) {
    1394             :                         must_free_connection = false;
    1395             :                         break;
    1396             :                 }
    1397        1926 :         if (!must_free_connection) {
    1398             :                 /* tds use connection member so must be valid */
    1399           5 :                 tds_append_fin(tds);
    1400             :         }
    1401        1926 :         tds_mutex_unlock(&conn->list_mtx);
    1402             : 
    1403             :         /* detach entirely */
    1404        1926 :         tds->conn = NULL;
    1405             : 
    1406        1926 :         if (must_free_connection)
    1407        1921 :                 tds_free_connection(conn);
    1408        1926 : }
    1409             : #else
    1410             : static void inline
    1411             : tds_connection_remove_socket(TDSCONNECTION *conn, TDSSOCKET *tds TDS_UNUSED)
    1412             : {
    1413        1884 :         tds_deinit_connection(conn);
    1414             : }
    1415             : #endif
    1416             : 
    1417             : void
    1418        5838 : tds_free_socket(TDSSOCKET * tds)
    1419             : {
    1420             : #if ENABLE_EXTRA_CHECKS
    1421             :         TDSDYNAMIC *dyn;
    1422             :         TDSCURSOR *cur;
    1423             : #endif
    1424             : 
    1425        5838 :         if (!tds)
    1426             :                 return;
    1427             : 
    1428             :         /* detach this socket */
    1429        3810 :         tds_release_cur_dyn(tds);
    1430        3810 :         tds_release_cursor(&tds->cur_cursor);
    1431        7620 :         tds_detach_results(tds->current_results);
    1432             : #if ENABLE_EXTRA_CHECKS
    1433        3852 :         for (dyn = tds->conn->dyns; dyn; dyn = dyn->next) {
    1434          42 :                 if (dyn->res_info && dyn->res_info->attached_to == tds) {
    1435           0 :                         assert(0);
    1436             :                 }
    1437             :         }
    1438        3822 :         for (cur = tds->conn->cursors; cur; cur = cur->next) {
    1439          12 :                 if (cur->res_info && cur->res_info->attached_to == tds) {
    1440           0 :                         assert(0);
    1441             :                 }
    1442             :         }
    1443             : #endif
    1444        3810 :         tds_free_all_results(tds);
    1445             : #if ENABLE_ODBC_MARS
    1446        3852 :         tds_cond_destroy(&tds->packet_cond);
    1447             : #endif
    1448             : 
    1449        5694 :         tds_connection_remove_socket(tds->conn, tds);
    1450        7620 :         tds_free_packets(tds->recv_packet);
    1451        3810 :         if (tds->frozen_packets)
    1452             :                 tds_free_packets(tds->frozen_packets);
    1453             :         else
    1454        3810 :                 tds_free_packets(tds->send_packet);
    1455        3810 :         free(tds);
    1456             : }
    1457             : 
    1458             : void
    1459        2923 : tds_free_locale(TDSLOCALE * locale)
    1460             : {
    1461        2923 :         if (!locale)
    1462             :                 return;
    1463             : 
    1464        2923 :         free(locale->language);
    1465        2923 :         free(locale->server_charset);
    1466        2923 :         free(locale->datetime_fmt);
    1467        2923 :         free(locale->date_fmt);
    1468        2923 :         free(locale->time_fmt);
    1469        2923 :         free(locale);
    1470             : }
    1471             : 
    1472             : static void
    1473        3805 : tds_free_env(TDSCONNECTION* conn)
    1474             : {
    1475        3805 :         if (conn->env.language)
    1476        2179 :                 TDS_ZERO_FREE(conn->env.language);
    1477        3805 :         if (conn->env.charset)
    1478         540 :                 TDS_ZERO_FREE(conn->env.charset);
    1479        3805 :         if (conn->env.database)
    1480        2887 :                 TDS_ZERO_FREE(conn->env.database);
    1481        3805 : }
    1482             : 
    1483             : void
    1484       12191 : tds_free_msg(TDSMESSAGE * message)
    1485             : {
    1486       12191 :         if (message) {
    1487       12191 :                 message->priv_msg_type = 0;
    1488       12191 :                 message->msgno = 0;
    1489       12191 :                 message->state = 0;
    1490       12191 :                 message->severity = 0;
    1491       12191 :                 message->line_number = 0;
    1492       12191 :                 TDS_ZERO_FREE(message->message);
    1493       12191 :                 TDS_ZERO_FREE(message->server);
    1494       12191 :                 TDS_ZERO_FREE(message->proc_name);
    1495       12191 :                 TDS_ZERO_FREE(message->sql_state);
    1496             :         }
    1497       12191 : }
    1498             : 
    1499             : #define SQLS_ENTRY(number,state) case number: p = state; break
    1500             : 
    1501             : char *
    1502       33056 : tds_alloc_client_sqlstate(int msgno)
    1503             : {
    1504       33056 :         const char *p = NULL;
    1505             : 
    1506       33056 :         switch (msgno) {
    1507             :                 SQLS_ENTRY(17000, "S1T00");   /* timeouts ??? */
    1508           1 :                 SQLS_ENTRY(20004, "08S01");   /* Communication link failure */
    1509          58 :                 SQLS_ENTRY(20006, "08S01");
    1510           0 :                 SQLS_ENTRY(20009, "08S01");
    1511           0 :                 SQLS_ENTRY(20020, "08S01");
    1512           0 :                 SQLS_ENTRY(20019, "24000");   /* Invalid cursor state */
    1513           0 :                 SQLS_ENTRY(20014, "28000");   /* Invalid authorization specification */
    1514       28824 :                 SQLS_ENTRY(2400, "42000");    /* Syntax error or access violation */
    1515         592 :                 SQLS_ENTRY(2401, "42000");
    1516        1544 :                 SQLS_ENTRY(2403, "42000");
    1517           0 :                 SQLS_ENTRY(2404, "42000");
    1518        1769 :                 SQLS_ENTRY(2402, "S1000");    /* General error */
    1519             :         }
    1520             : 
    1521             :         if (p != NULL)
    1522       32788 :                 return strdup(p);
    1523             :         else
    1524             :                 return NULL;
    1525             : }
    1526             : 
    1527             : char *
    1528       12082 : tds_alloc_lookup_sqlstate(TDSSOCKET * tds, int msgno)
    1529             : {
    1530       12082 :         const char *p = NULL;
    1531       12082 :         char *q = NULL;
    1532             : 
    1533       12082 :         if (TDS_IS_MSSQL(tds)) {
    1534        5330 :                 switch (msgno) {        /* MSSQL Server */
    1535             : 
    1536         468 :                         SQLS_ENTRY(3621,"01000");
    1537          20 :                         SQLS_ENTRY(8153,"01003");     /* Null in aggregate */
    1538           6 :                         SQLS_ENTRY(911, "08004");     /* Server rejected connection */
    1539           0 :                         SQLS_ENTRY(512, "21000");     /* Subquery returns more than one value */
    1540           0 :                         SQLS_ENTRY(213, "21S01");     /* Insert column list mismatch */
    1541           0 :                         SQLS_ENTRY(109, "21S01");
    1542           0 :                         SQLS_ENTRY(110, "21S01");
    1543           0 :                         SQLS_ENTRY(1774,"21S02");     /* Ref column mismatch */
    1544           0 :                         SQLS_ENTRY(8152,"22001");     /* String data would be truncated */
    1545           0 :                         SQLS_ENTRY(5146,"22003");     /* Numeric value out of range */
    1546           0 :                         SQLS_ENTRY(168, "22003");     /* Arithmetic overflow */
    1547         396 :                         SQLS_ENTRY(220, "22003");
    1548           0 :                         SQLS_ENTRY(232, "22003");
    1549           0 :                         SQLS_ENTRY(234, "22003");
    1550           0 :                         SQLS_ENTRY(236, "22003");
    1551           0 :                         SQLS_ENTRY(238, "22003");
    1552           0 :                         SQLS_ENTRY(244, "22003");
    1553           0 :                         SQLS_ENTRY(246, "22003");
    1554           0 :                         SQLS_ENTRY(248, "22003");
    1555           0 :                         SQLS_ENTRY(519, "22003");
    1556           0 :                         SQLS_ENTRY(520, "22003");
    1557           0 :                         SQLS_ENTRY(521, "22003");
    1558           0 :                         SQLS_ENTRY(522, "22003");
    1559           0 :                         SQLS_ENTRY(523, "22003");
    1560           0 :                         SQLS_ENTRY(524, "22003");
    1561           0 :                         SQLS_ENTRY(1007,"22003");
    1562           0 :                         SQLS_ENTRY(3606,"22003");
    1563           0 :                         SQLS_ENTRY(8115,"22003");
    1564           0 :                         SQLS_ENTRY(206, "22005");     /* Error in assignment */
    1565           0 :                         SQLS_ENTRY(235, "22005");
    1566           0 :                         SQLS_ENTRY(247, "22005");
    1567           0 :                         SQLS_ENTRY(249, "22005");
    1568           0 :                         SQLS_ENTRY(256, "22005");
    1569           0 :                         SQLS_ENTRY(257, "22005");
    1570           0 :                         SQLS_ENTRY(305, "22005");
    1571           0 :                         SQLS_ENTRY(409, "22005");
    1572           0 :                         SQLS_ENTRY(518, "22005");
    1573           0 :                         SQLS_ENTRY(529, "22005");
    1574           0 :                         SQLS_ENTRY(210, "22007");     /* Invalid datetime format */
    1575           0 :                         SQLS_ENTRY(241, "22007");
    1576           0 :                         SQLS_ENTRY(295, "22007");
    1577          12 :                         SQLS_ENTRY(242, "22008");     /* Datetime out of range */
    1578           0 :                         SQLS_ENTRY(296, "22008");
    1579           0 :                         SQLS_ENTRY(298, "22008");
    1580           0 :                         SQLS_ENTRY(535, "22008");
    1581           0 :                         SQLS_ENTRY(542, "22008");
    1582           6 :                         SQLS_ENTRY(517, "22008");
    1583           0 :                         SQLS_ENTRY(3607, "22012");    /* Div by zero */
    1584         130 :                         SQLS_ENTRY(8134, "22012");
    1585           0 :                         SQLS_ENTRY(245, "22018");     /* Syntax error? */
    1586           6 :                         SQLS_ENTRY(2627, "23000");    /* Constraint violation */
    1587           6 :                         SQLS_ENTRY(515, "23000");
    1588           0 :                         SQLS_ENTRY(233, "23000");
    1589           0 :                         SQLS_ENTRY(273, "23000");
    1590           0 :                         SQLS_ENTRY(530, "23000");
    1591           0 :                         SQLS_ENTRY(2601,"23000");
    1592           0 :                         SQLS_ENTRY(2615,"23000");
    1593           0 :                         SQLS_ENTRY(2626,"23000");
    1594           0 :                         SQLS_ENTRY(3604,"23000");
    1595           0 :                         SQLS_ENTRY(3605,"23000");
    1596           0 :                         SQLS_ENTRY(544, "23000");
    1597           0 :                         SQLS_ENTRY(547, "23000");
    1598           0 :                         SQLS_ENTRY(550, "23000");
    1599           0 :                         SQLS_ENTRY(4415, "23000");
    1600           0 :                         SQLS_ENTRY(1505, "23000");
    1601           0 :                         SQLS_ENTRY(1508, "23000");
    1602           0 :                         SQLS_ENTRY(3725, "23000");
    1603           0 :                         SQLS_ENTRY(3726, "23000");
    1604           0 :                         SQLS_ENTRY(4712, "23000");
    1605           0 :                         SQLS_ENTRY(10055, "23000");
    1606           0 :                         SQLS_ENTRY(10065, "23000");
    1607           0 :                         SQLS_ENTRY(11011, "23000");
    1608           0 :                         SQLS_ENTRY(11040, "23000");
    1609           0 :                         SQLS_ENTRY(16999, "24000");   /* Invalid cursor state */
    1610           0 :                         SQLS_ENTRY(16905, "24000");
    1611           0 :                         SQLS_ENTRY(16917, "24000");
    1612           0 :                         SQLS_ENTRY(16946, "24000");
    1613           0 :                         SQLS_ENTRY(16950, "24000");
    1614           0 :                         SQLS_ENTRY(266, "25000");     /* Invalid transaction state */
    1615           0 :                         SQLS_ENTRY(277,"25000");
    1616           0 :                         SQLS_ENTRY(611,"25000");
    1617           0 :                         SQLS_ENTRY(3906,"25000");
    1618           0 :                         SQLS_ENTRY(3908,"25000");
    1619           0 :                         SQLS_ENTRY(6401,"25000");
    1620           0 :                         SQLS_ENTRY(626, "25000");
    1621           0 :                         SQLS_ENTRY(627, "25000");
    1622           0 :                         SQLS_ENTRY(628, "25000");
    1623           0 :                         SQLS_ENTRY(3902, "25000");
    1624           0 :                         SQLS_ENTRY(3903, "25000");
    1625           0 :                         SQLS_ENTRY(3916, "25000");
    1626           0 :                         SQLS_ENTRY(3918, "25000");
    1627           0 :                         SQLS_ENTRY(3919, "25000");
    1628           0 :                         SQLS_ENTRY(3921, "25000");
    1629           0 :                         SQLS_ENTRY(3922, "25000");
    1630          16 :                         SQLS_ENTRY(3926, "25000");
    1631           0 :                         SQLS_ENTRY(7969, "25000");
    1632           0 :                         SQLS_ENTRY(8506, "25000");
    1633           0 :                         SQLS_ENTRY(15626, "25000");
    1634           0 :                         SQLS_ENTRY(18456, "28000");   /* Login failed? */
    1635           0 :                         SQLS_ENTRY(6104, "37000");    /* Syntax error or access violation */
    1636           0 :                         SQLS_ENTRY(8114, "37000");
    1637           0 :                         SQLS_ENTRY(131, "37000");
    1638           2 :                         SQLS_ENTRY(137, "37000");
    1639          24 :                         SQLS_ENTRY(170, "37000");
    1640           0 :                         SQLS_ENTRY(174, "37000");
    1641           0 :                         SQLS_ENTRY(201, "37000");
    1642           6 :                         SQLS_ENTRY(2812, "37000");
    1643           0 :                         SQLS_ENTRY(2526, "37000");
    1644           0 :                         SQLS_ENTRY(8144, "37000");
    1645           0 :                         SQLS_ENTRY(17308, "42000");   /* Syntax/Access violation */
    1646           0 :                         SQLS_ENTRY(17571, "42000");
    1647           0 :                         SQLS_ENTRY(18002, "42000");
    1648           0 :                         SQLS_ENTRY(229, "42000");
    1649           0 :                         SQLS_ENTRY(230, "42000");
    1650           0 :                         SQLS_ENTRY(262, "42000");
    1651           0 :                         SQLS_ENTRY(2557, "42000");
    1652           0 :                         SQLS_ENTRY(2571, "42000");
    1653           0 :                         SQLS_ENTRY(2760, "42000");
    1654           0 :                         SQLS_ENTRY(3110, "42000");
    1655           0 :                         SQLS_ENTRY(3704, "42000");
    1656           0 :                         SQLS_ENTRY(4613, "42000");
    1657           0 :                         SQLS_ENTRY(4618, "42000");
    1658           0 :                         SQLS_ENTRY(4834, "42000");
    1659           0 :                         SQLS_ENTRY(5011, "42000");
    1660           0 :                         SQLS_ENTRY(5116, "42000");
    1661           0 :                         SQLS_ENTRY(5812, "42000");
    1662           0 :                         SQLS_ENTRY(6004, "42000");
    1663           0 :                         SQLS_ENTRY(6102, "42000");
    1664           0 :                         SQLS_ENTRY(7956, "42000");
    1665           0 :                         SQLS_ENTRY(11010, "42000");
    1666           0 :                         SQLS_ENTRY(11045, "42000");
    1667           0 :                         SQLS_ENTRY(14126, "42000");
    1668           0 :                         SQLS_ENTRY(15247, "42000");
    1669           0 :                         SQLS_ENTRY(15622, "42000");
    1670           0 :                         SQLS_ENTRY(20604, "42000");
    1671           0 :                         SQLS_ENTRY(21049, "42000");
    1672           0 :                         SQLS_ENTRY(113, "42000");
    1673           0 :                         SQLS_ENTRY(2714, "42S01");    /* Table or view already exists */
    1674          18 :                         SQLS_ENTRY(208, "42S02");     /* Table or view not found */
    1675         144 :                         SQLS_ENTRY(3701, "42S02");
    1676           0 :                         SQLS_ENTRY(1913, "42S11");    /* Index already exists */
    1677           0 :                         SQLS_ENTRY(15605, "42S11");
    1678           0 :                         SQLS_ENTRY(307, "42S12");     /* Index not found */
    1679           0 :                         SQLS_ENTRY(308, "42S12");
    1680           0 :                         SQLS_ENTRY(10033, "42S12");
    1681           0 :                         SQLS_ENTRY(15323, "42S12");
    1682           0 :                         SQLS_ENTRY(18833, "42S12");
    1683           0 :                         SQLS_ENTRY(4925, "42S21");    /* Column already exists */
    1684           0 :                         SQLS_ENTRY(21255, "42S21");
    1685           0 :                         SQLS_ENTRY(1911, "42S22");    /* Column not found */
    1686          36 :                         SQLS_ENTRY(207, "42S22");
    1687           0 :                         SQLS_ENTRY(4924, "42S22");
    1688           0 :                         SQLS_ENTRY(4926, "42S22");
    1689           0 :                         SQLS_ENTRY(15645, "42S22");
    1690           0 :                         SQLS_ENTRY(21166, "42S22");
    1691             :                 }
    1692             :         } else {
    1693        6752 :                 switch (msgno) {        /* Sybase */
    1694           4 :                         SQLS_ENTRY(3621, "01000");
    1695           0 :                         SQLS_ENTRY(9501, "01003");    /* Null in aggregate */
    1696           1 :                         SQLS_ENTRY(911, "08004");     /* Server rejected connection */
    1697           0 :                         SQLS_ENTRY(512, "21000");     /* Subquery returns more than one value */
    1698           0 :                         SQLS_ENTRY(213, "21S01");     /* Insert column list mismatch */
    1699           0 :                         SQLS_ENTRY(109, "21S01");
    1700           0 :                         SQLS_ENTRY(110, "21S01");
    1701           0 :                         SQLS_ENTRY(1715, "21S02");    /* Ref column mismatch */
    1702           0 :                         SQLS_ENTRY(9502, "22001");    /* String data would be truncated */
    1703           0 :                         SQLS_ENTRY(220, "22003");     /* Arithmetic overflow */
    1704           0 :                         SQLS_ENTRY(168, "22003");
    1705           0 :                         SQLS_ENTRY(227, "22003");
    1706           0 :                         SQLS_ENTRY(232, "22003");
    1707           0 :                         SQLS_ENTRY(234, "22003");
    1708           0 :                         SQLS_ENTRY(236, "22003");
    1709           0 :                         SQLS_ENTRY(238, "22003");
    1710           0 :                         SQLS_ENTRY(244, "22003");
    1711           0 :                         SQLS_ENTRY(246, "22003");
    1712           0 :                         SQLS_ENTRY(247, "22003");
    1713           0 :                         SQLS_ENTRY(248, "22003");
    1714           0 :                         SQLS_ENTRY(519, "22003");
    1715           0 :                         SQLS_ENTRY(520, "22003");
    1716           0 :                         SQLS_ENTRY(521, "22003");
    1717           0 :                         SQLS_ENTRY(522, "22003");
    1718           0 :                         SQLS_ENTRY(523, "22003");
    1719           0 :                         SQLS_ENTRY(524, "22003");
    1720           0 :                         SQLS_ENTRY(3606, "22003");
    1721           0 :                         SQLS_ENTRY(206, "22005");     /* Error in assignment */
    1722           0 :                         SQLS_ENTRY(235, "22005");
    1723           4 :                         SQLS_ENTRY(249, "22005");
    1724           0 :                         SQLS_ENTRY(256, "22005");
    1725           0 :                         SQLS_ENTRY(305, "22005");
    1726           0 :                         SQLS_ENTRY(409, "22005");
    1727           0 :                         SQLS_ENTRY(518, "22005");
    1728           0 :                         SQLS_ENTRY(529, "22005");
    1729           0 :                         SQLS_ENTRY(535, "22008");     /* Datetime out of range */
    1730           0 :                         SQLS_ENTRY(542, "22008");
    1731           2 :                         SQLS_ENTRY(517, "22008");
    1732           0 :                         SQLS_ENTRY(3607, "22012");    /* Div by zero */
    1733           0 :                         SQLS_ENTRY(245, "22018");     /* Syntax error? */
    1734           0 :                         SQLS_ENTRY(544, "23000");     /* Constraint violation */
    1735           0 :                         SQLS_ENTRY(233, "23000");
    1736           0 :                         SQLS_ENTRY(273, "23000");
    1737           0 :                         SQLS_ENTRY(530, "23000");
    1738           0 :                         SQLS_ENTRY(2601,"23000");
    1739           0 :                         SQLS_ENTRY(2615,"23000");
    1740           0 :                         SQLS_ENTRY(2626,"23000");
    1741           0 :                         SQLS_ENTRY(3604,"23000");
    1742           0 :                         SQLS_ENTRY(3605,"23000");
    1743           0 :                         SQLS_ENTRY(545, "23000");
    1744           0 :                         SQLS_ENTRY(546, "23000");
    1745           0 :                         SQLS_ENTRY(547, "23000");
    1746           0 :                         SQLS_ENTRY(548, "23000");
    1747           0 :                         SQLS_ENTRY(549, "23000");
    1748           0 :                         SQLS_ENTRY(550, "23000");
    1749           0 :                         SQLS_ENTRY(1505, "23000");
    1750           0 :                         SQLS_ENTRY(1508, "23000");
    1751           0 :                         SQLS_ENTRY(565, "24000");     /* Invalid cursor state */
    1752           0 :                         SQLS_ENTRY(558, "24000");
    1753           0 :                         SQLS_ENTRY(559, "24000");
    1754           0 :                         SQLS_ENTRY(6235, "24000");
    1755           0 :                         SQLS_ENTRY(583, "24000");
    1756           0 :                         SQLS_ENTRY(6259, "24000");
    1757           0 :                         SQLS_ENTRY(6260, "24000");
    1758           0 :                         SQLS_ENTRY(562, "24000");
    1759           0 :                         SQLS_ENTRY(277, "25000");     /* Invalid transaction state */
    1760           0 :                         SQLS_ENTRY(611,"25000");
    1761           0 :                         SQLS_ENTRY(3906,"25000");
    1762           0 :                         SQLS_ENTRY(3908,"25000");
    1763           0 :                         SQLS_ENTRY(6401,"25000");
    1764           0 :                         SQLS_ENTRY(627, "25000");
    1765           0 :                         SQLS_ENTRY(628, "25000");
    1766           0 :                         SQLS_ENTRY(641, "25000");
    1767           0 :                         SQLS_ENTRY(642, "25000");
    1768           0 :                         SQLS_ENTRY(1276, "25000");
    1769           0 :                         SQLS_ENTRY(3902, "25000");
    1770           0 :                         SQLS_ENTRY(3903, "25000");
    1771           0 :                         SQLS_ENTRY(6104, "37000");    /* Syntax error or access violation */
    1772           0 :                         SQLS_ENTRY(102, "37000");
    1773          24 :                         SQLS_ENTRY(137, "37000");
    1774           0 :                         SQLS_ENTRY(7327, "37000");
    1775           0 :                         SQLS_ENTRY(201, "37000");
    1776           0 :                         SQLS_ENTRY(257, "37000");
    1777           2 :                         SQLS_ENTRY(2812, "37000");
    1778           0 :                         SQLS_ENTRY(2526, "37000");
    1779           0 :                         SQLS_ENTRY(11021, "37000");
    1780           0 :                         SQLS_ENTRY(229, "42000");     /* Syntax/Access violation */
    1781           0 :                         SQLS_ENTRY(230, "42000");
    1782           0 :                         SQLS_ENTRY(262, "42000");
    1783           0 :                         SQLS_ENTRY(4602, "42000");
    1784           0 :                         SQLS_ENTRY(4603, "42000");
    1785           0 :                         SQLS_ENTRY(4608, "42000");
    1786           0 :                         SQLS_ENTRY(10306, "42000");
    1787           0 :                         SQLS_ENTRY(10323, "42000");
    1788           0 :                         SQLS_ENTRY(10330, "42000");
    1789           0 :                         SQLS_ENTRY(10331, "42000");
    1790           0 :                         SQLS_ENTRY(10332, "42000");
    1791           0 :                         SQLS_ENTRY(11110, "42000");
    1792           0 :                         SQLS_ENTRY(11113, "42000");
    1793           0 :                         SQLS_ENTRY(11118, "42000");
    1794           0 :                         SQLS_ENTRY(11121, "42000");
    1795           0 :                         SQLS_ENTRY(17222, "42000");
    1796           0 :                         SQLS_ENTRY(17223, "42000");
    1797           0 :                         SQLS_ENTRY(18350, "42000");
    1798           0 :                         SQLS_ENTRY(18351, "42000");
    1799           0 :                         SQLS_ENTRY(113, "42000");
    1800           0 :                         SQLS_ENTRY(2714, "42S01");    /* Table or view already exists */
    1801           0 :                         SQLS_ENTRY(208, "42S02");     /* Table or view not found */
    1802          44 :                         SQLS_ENTRY(3701, "42S02");
    1803           0 :                         SQLS_ENTRY(1913, "42S11");    /* Index already exists */
    1804           0 :                         SQLS_ENTRY(307, "42S12");     /* Index not found */
    1805           0 :                         SQLS_ENTRY(7010, "42S12");
    1806           0 :                         SQLS_ENTRY(18091, "42S12");
    1807           0 :                         SQLS_ENTRY(1921, "42S21");    /* Column already exists */
    1808           0 :                         SQLS_ENTRY(1720, "42S22");    /* Column not found */
    1809           6 :                         SQLS_ENTRY(207, "42S22");
    1810           0 :                         SQLS_ENTRY(4934, "42S22");
    1811           0 :                         SQLS_ENTRY(18117, "42S22");
    1812             :                 }
    1813             :         }
    1814             : 
    1815       12082 :         if (p != NULL && (q = strdup(p)) != NULL) {
    1816             :                 /* FIXME correct here ?? */
    1817             :                 /* Convert known ODBC 3.x states listed above to 2.x */
    1818        1383 :                 if (memcmp(q, "42S", 3) == 0)
    1819         248 :                         memcpy(q, "S00", 3);
    1820             : 
    1821             :                 return q;
    1822             :         }
    1823             :         return NULL;
    1824             : }
    1825             : 
    1826             : BCPCOLDATA *
    1827        2434 : tds_alloc_bcp_column_data(unsigned int column_size)
    1828             : {
    1829             :         BCPCOLDATA *coldata;
    1830             : 
    1831        2434 :         TEST_MALLOC(coldata, BCPCOLDATA);
    1832             : 
    1833        2434 :         if (column_size > 4 * 1024)
    1834          80 :                 column_size = 4 * 1024;
    1835        2434 :         TEST_CALLOC(coldata->data, unsigned char, column_size);
    1836             : 
    1837             :         return coldata;
    1838           0 : Cleanup:
    1839           0 :         tds_free_bcp_column_data(coldata);
    1840           0 :         return NULL;
    1841             : }
    1842             : 
    1843             : void
    1844       81802 : tds_free_bcp_column_data(BCPCOLDATA * coldata)
    1845             : {
    1846       81802 :         if (!coldata)
    1847             :                 return;
    1848             : 
    1849        2434 :         free(coldata->data);
    1850        2434 :         free(coldata);
    1851             : }
    1852             : 
    1853             : TDSBCPINFO *
    1854         288 : tds_alloc_bcpinfo(void)
    1855             : {
    1856             :         TDSBCPINFO *bcpinfo;
    1857             : 
    1858         288 :         TEST_MALLOC(bcpinfo, TDSBCPINFO);
    1859             : 
    1860         576 :         tds_dstr_init(&bcpinfo->hint);
    1861         576 :         tds_dstr_init(&bcpinfo->tablename);
    1862             : 
    1863         288 :         return bcpinfo;
    1864         288 : Cleanup:
    1865             :         return NULL;
    1866             : }
    1867             : 
    1868             : void
    1869         472 : tds_deinit_bcpinfo(TDSBCPINFO *bcpinfo)
    1870             : {
    1871         472 :         tds_dstr_free(&bcpinfo->hint);
    1872         472 :         tds_dstr_free(&bcpinfo->tablename);
    1873         472 :         TDS_ZERO_FREE(bcpinfo->insert_stmt);
    1874         472 :         tds_free_results(bcpinfo->bindinfo);
    1875         472 :         bcpinfo->bindinfo = NULL;
    1876         472 :         TDS_ZERO_FREE(bcpinfo->sybase_colinfo);
    1877         472 :         bcpinfo->sybase_count = 0;
    1878         472 : }
    1879             : 
    1880             : void
    1881        2118 : tds_free_bcpinfo(TDSBCPINFO *bcpinfo)
    1882             : {
    1883        2118 :         if (bcpinfo) {
    1884         288 :                 tds_deinit_bcpinfo(bcpinfo);
    1885         288 :                 free(bcpinfo);
    1886             :         }
    1887        2118 : }
    1888             : 
    1889             : /**
    1890             :  * Reallocate a pointer and update it if success
    1891             :  * \param pp pointer to pointer to be reallocated
    1892             :  * \param new_size new size to be allocated
    1893             :  * \return new pointer allocated, NULL on failure
    1894             :  */
    1895             : void *
    1896      109222 : tds_realloc(void **pp, size_t new_size)
    1897             : {
    1898             :         void *p;
    1899             : 
    1900             :         /* some implementation of malloc/realloc does not like size==0 */
    1901      109222 :         if (!new_size)
    1902           0 :                 new_size = 1;
    1903             : 
    1904             :         /* use malloc if not allocated before, some implementation require it */
    1905      109222 :         if (*pp)
    1906       43182 :                 p = realloc(*pp, new_size);
    1907             :         else
    1908       66040 :                 p = malloc(new_size);
    1909             : 
    1910             :         /* update pointer only on success */
    1911      109222 :         if (p)
    1912      109222 :                 *pp = p;
    1913             : 
    1914      109222 :         return p;
    1915             : }
    1916             : 
    1917             : void
    1918           8 : tds_deinit_tvp(TDS_TVP *table)
    1919             : {
    1920             :         TDS_TVP_ROW *tvp_row, *next_row;
    1921             : 
    1922           8 :         free(table->schema);
    1923           8 :         table->schema = NULL;
    1924           8 :         free(table->name);
    1925           8 :         table->name = NULL;
    1926          16 :         tds_free_param_results(table->metadata);
    1927           8 :         table->metadata = NULL;
    1928          26 :         for (tvp_row = table->row; tvp_row != NULL; tvp_row = next_row) {
    1929          18 :                 next_row = tvp_row->next;
    1930          18 :                 tds_free_tvp_row(tvp_row);
    1931          18 :                 free(tvp_row);
    1932             :         }
    1933           8 :         table->row = NULL;
    1934           8 : }
    1935             : 
    1936             : /** @} */

Generated by: LCOV version 1.13