LCOV - code coverage report
Current view: top level - src/tds - mem.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 661 980 67.4 %
Date: 2025-01-18 12:13:41 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             :                 /* printf("%d -> %d(%c)\n",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       81362 : tds_alloc_column(void)
     127             : {
     128             :         TDSCOLUMN *col;
     129             : 
     130       81362 :         TEST_MALLOC(col, TDSCOLUMN);
     131      162724 :         tds_dstr_init(&col->table_name);
     132      162724 :         tds_dstr_init(&col->column_name);
     133      162724 :         tds_dstr_init(&col->table_column_name);
     134       81362 :         col->funcs = &tds_invalid_funcs;
     135             : 
     136       81362 :       Cleanup:
     137       81362 :         return col;
     138             : }
     139             : 
     140             : static void
     141       81302 : tds_free_column(TDSCOLUMN *col)
     142             : {
     143       81302 :         tds_dstr_free(&col->table_name);
     144       81302 :         tds_dstr_free(&col->column_name);
     145       81302 :         tds_dstr_free(&col->table_column_name);
     146       81302 :         free(col);
     147       81302 : }
     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     1127341 : tds_release_dynamic(TDSDYNAMIC ** pdyn)
     254             : {
     255             :         TDSDYNAMIC *dyn;
     256             : 
     257     1127341 :         dyn = *pdyn;
     258     1127341 :         *pdyn = NULL;
     259     1127341 :         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 informations 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       27602 : tds_alloc_results(TDS_USMALLINT num_cols)
     462             : {
     463             :         TDSRESULTINFO *res_info;
     464             :         TDS_USMALLINT col;
     465             : 
     466       27602 :         TEST_MALLOC(res_info, TDSRESULTINFO);
     467       27602 :         res_info->ref_count = 1;
     468       27602 :         if (num_cols)
     469       27452 :                 TEST_CALLOC(res_info->columns, TDSCOLUMN *, num_cols);
     470       48932 :         for (col = 0; col < num_cols; col++)
     471       48932 :                 if (!(res_info->columns[col] = tds_alloc_column()))
     472             :                         goto Cleanup;
     473       27602 :         res_info->num_cols = num_cols;
     474       27602 :         res_info->row_size = 0;
     475       27602 :         return res_info;
     476           0 :       Cleanup:
     477           0 :         tds_free_results(res_info);
     478           0 :         return NULL;
     479             : }
     480             : 
     481             : void
     482      295060 : tds_set_current_results(TDSSOCKET *tds, TDSRESULTINFO *info)
     483             : {
     484      295060 :         tds_detach_results(info);
     485      295060 :         if (tds->current_results)
     486         470 :                 tds->current_results->attached_to = NULL;
     487      295060 :         if (info)
     488      295054 :                 info->attached_to = tds;
     489      295060 :         tds->in_row = (info != NULL);
     490      295060 :         tds->current_results = info;
     491      295060 : }
     492             : 
     493             : /**
     494             :  * Detach result info from it current socket
     495             :  */
     496             : void
     497           0 : tds_detach_results(TDSRESULTINFO *info)
     498             : {
     499     1161206 :         if (info && info->attached_to) {
     500      294578 :                 info->attached_to->current_results = NULL;
     501      294578 :                 info->attached_to->in_row = false;
     502      294578 :                 info->attached_to = NULL;
     503             :         }
     504           0 : }
     505             : 
     506             : static void
     507       27396 : tds_row_free(TDSRESULTINFO *res_info, unsigned char *row)
     508             : {
     509             :         int i;
     510             :         const TDSCOLUMN *col;
     511             : 
     512       27396 :         if (!res_info || !row)
     513             :                 return;
     514             : 
     515       48950 :         for (i = 0; i < res_info->num_cols; ++i) {
     516       48950 :                 col = res_info->columns[i];
     517             :                 
     518       48950 :                 if (is_blob_col(col)) {
     519        2912 :                         TDSBLOB *blob = (TDSBLOB *) &row[col->column_data - res_info->current_row];
     520        2912 :                         if (blob->textvalue)
     521        2372 :                                 TDS_ZERO_FREE(blob->textvalue);
     522             :                 }
     523             :         }
     524             : 
     525       27396 :         free(row);
     526             : }
     527             : 
     528             : /**
     529             :  * Allocate space for row store
     530             :  * return NULL on out of memory
     531             :  */
     532             : TDSRET
     533       27420 : tds_alloc_row(TDSRESULTINFO * res_info)
     534             : {
     535       27420 :         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       27420 :         row_size = 0;
     542       76430 :         for (i = 0; i < num_cols; ++i) {
     543       49010 :                 col = res_info->columns[i];
     544             : 
     545       49010 :                 col->column_data_free = NULL;
     546             : 
     547       49010 :                 row_size += col->funcs->row_len(col);
     548       49010 :                 row_size += (TDS_ALIGN_SIZE - 1);
     549       49010 :                 row_size -= row_size % TDS_ALIGN_SIZE;
     550             :         }
     551       27420 :         res_info->row_size = row_size;
     552             : 
     553       27420 :         ptr = tds_new0(unsigned char, res_info->row_size);
     554       27420 :         res_info->current_row = ptr;
     555       27420 :         if (!ptr)
     556             :                 return TDS_FAIL;
     557       27420 :         res_info->row_free = tds_row_free;
     558             : 
     559             :         /* fill column_data */
     560       27420 :         row_size = 0;
     561       76430 :         for (i = 0; i < num_cols; ++i) {
     562       49010 :                 col = res_info->columns[i];
     563             : 
     564       49010 :                 col->column_data = ptr + row_size;
     565             : 
     566       49010 :                 row_size += col->funcs->row_len(col);
     567       49010 :                 row_size += (TDS_ALIGN_SIZE - 1);
     568       49010 :                 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       80355 : tds_free_param_results(TDSPARAMINFO * param_info)
     582             : {
     583      220771 :         tds_free_results(param_info);
     584       80355 : }
     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      139302 : tds_free_compute_results(TDSSOCKET * tds)
     594             : {
     595      139302 :         TDSCOMPUTEINFO ** comp_info = tds->comp_info;
     596      139302 :         TDS_UINT i, num_comp = tds->num_comp_info;
     597             : 
     598      139302 :         tds->comp_info = NULL;
     599      139302 :         tds->num_comp_info = 0;
     600             : 
     601      139374 :         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      139302 :         if (num_comp)
     608          48 :                 free(comp_info);
     609      139302 : }
     610             : 
     611             : void
     612      156477 : tds_free_row(TDSRESULTINFO * res_info, unsigned char *row)
     613             : {
     614      156477 :         assert(res_info);
     615      156477 :         if (!row || !res_info->row_free)
     616             :                 return;
     617             : 
     618        2176 :         res_info->row_free(res_info, row);
     619             : }
     620             : 
     621             : void
     622     1140296 : tds_free_results(TDSRESULTINFO * res_info)
     623             : {
     624             :         int i;
     625             :         TDSCOLUMN *curcol;
     626             : 
     627     1140296 :         if (!res_info)
     628             :                 return;
     629             : 
     630      217029 :         if (--res_info->ref_count != 0)
     631             :                 return;
     632             : 
     633       50986 :         tds_detach_results(res_info);
     634             : 
     635       50986 :         if (res_info->num_cols && res_info->columns) {
     636       81284 :                 for (i = 0; i < res_info->num_cols; i++)
     637       81284 :                         if ((curcol = res_info->columns[i]) != NULL) {
     638       81284 :                                 if (curcol->bcp_terminator)
     639          42 :                                         TDS_ZERO_FREE(curcol->bcp_terminator);
     640       81284 :                                 tds_free_bcp_column_data(curcol->bcp_column_data);
     641       81284 :                                 curcol->bcp_column_data = NULL;
     642       81284 :                                 if (curcol->column_data && curcol->column_data_free)
     643       20102 :                                         curcol->column_data_free(curcol);
     644             :                         }
     645             :         }
     646             : 
     647       50986 :         if (res_info->current_row && res_info->row_free)
     648       25294 :                 res_info->row_free(res_info, res_info->current_row);
     649             : 
     650       50986 :         if (res_info->num_cols && res_info->columns) {
     651       81284 :                 for (i = 0; i < res_info->num_cols; i++)
     652       81284 :                         if ((curcol = res_info->columns[i]) != NULL)
     653       81284 :                                 tds_free_column(curcol);
     654       50968 :                 free(res_info->columns);
     655             :         }
     656             : 
     657       50986 :         free(res_info->bycolumns);
     658             : 
     659       50986 :         free(res_info);
     660             : }
     661             : 
     662             : void
     663      139302 : tds_free_all_results(TDSSOCKET * tds)
     664             : {
     665      139302 :         tdsdump_log(TDS_DBG_FUNC, "tds_free_all_results()\n");
     666      278604 :         tds_detach_results(tds->res_info);
     667      139302 :         tds_free_results(tds->res_info);
     668      139302 :         tds->res_info = NULL;
     669      278604 :         tds_detach_results(tds->param_info);
     670      278604 :         tds_free_param_results(tds->param_info);
     671      139302 :         tds->param_info = NULL;
     672      139302 :         tds_free_compute_results(tds);
     673      139302 :         tds->has_status = false;
     674      139302 :         tds->in_row = false;
     675      139302 :         tds->ret_status = 0;
     676      139302 :         if (tds->cur_dyn)
     677        4815 :                 tds_detach_results(tds->cur_dyn->res_info);
     678      139302 : }
     679             : 
     680             : /*
     681             :  * Return 1 if winsock is initialized, else 0.
     682             :  */
     683             : static int
     684             : winsock_initialized(void)
     685             : {
     686             : #if defined(_WIN32) || defined(_WIN64)
     687             :         static bool initialized = false;
     688             :         static tds_mutex mtx = TDS_MUTEX_INITIALIZER;
     689             : 
     690             :         WSADATA wsa_data;
     691             :         int erc;
     692             : 
     693             :         if (initialized)
     694             :                 return 1;
     695             : 
     696             :         tds_mutex_lock(&mtx);
     697             :         /* same check inside the mutex */
     698             :         if (initialized) {
     699             :                 tds_mutex_unlock(&mtx);
     700             :                 return 1;
     701             :         }
     702             : 
     703             :         /* initialize the socket layer */
     704             :         erc = WSAStartup(MAKEWORD(2, 2), &wsa_data);
     705             :         initialized = (erc == 0);
     706             :         tds_mutex_unlock(&mtx);
     707             : 
     708             :         if (erc != 0) {
     709             :                 char *errstr = sock_strerror(erc);
     710             :                 tdsdump_log(TDS_DBG_ERROR, "tds_init_winsock: WSAStartup failed with %d (%s)\n", erc, errstr);
     711             :                 sock_strerror_free(errstr);
     712             :                 return 0;
     713             :         }
     714             : #endif
     715             :         return 1;
     716             : }
     717             : 
     718             : TDSCONTEXT *
     719        2818 : tds_alloc_context(void * parent)
     720             : {
     721             :         TDSCONTEXT *context;
     722             :         TDSLOCALE *locale;
     723             : 
     724             :         if (!winsock_initialized())
     725             :                 return NULL;
     726             : 
     727        2818 :         if ((locale = tds_get_locale()) == NULL)
     728             :                 return NULL;
     729             : 
     730        2818 :         if ((context = tds_new0(TDSCONTEXT, 1)) == NULL) {
     731           0 :                 tds_free_locale(locale);
     732           0 :                 return NULL;
     733             :         }
     734        2818 :         context->locale = locale;
     735        2818 :         context->parent = parent;
     736        2818 :         context->money_use_2_digits = false;
     737             : 
     738        2818 :         return context;
     739             : }
     740             : 
     741             : void
     742        2794 : tds_free_context(TDSCONTEXT * context)
     743             : {
     744        2794 :         if (!context)
     745             :                 return;
     746             : 
     747        2794 :         tds_free_locale(context->locale);
     748        2794 :         free(context);
     749             : }
     750             : 
     751             : TDSLOCALE *
     752        2882 : tds_alloc_locale(void)
     753             : {
     754             :         TDSLOCALE *locale;
     755             : 
     756        2882 :         TEST_MALLOC(locale, TDSLOCALE);
     757             : 
     758             :         return locale;
     759             : 
     760           0 :       Cleanup:
     761           0 :         tds_free_locale(locale);
     762           0 :         return NULL;
     763             : }
     764             : 
     765             : /*
     766             :  * Default capabilities.
     767             :  */
     768             : #undef REQ
     769             : #define SUPPORTED_REQ_CAP(i) \
     770             :         REQ(i,LANG) REQ(i,RPC) REQ(i,EVT) REQ(i,MSTMT) REQ(i,BCP) REQ(i,CURSOR) REQ(i,DYNF) \
     771             :         REQ(i,MSG) REQ(i,PARAM) REQ(i,DATA_INT1) REQ(i,DATA_INT2) REQ(i,DATA_INT4) REQ(i,DATA_BIT) \
     772             :         REQ(i,DATA_CHAR) REQ(i,DATA_VCHAR) REQ(i,DATA_BIN) REQ(i,DATA_VBIN) REQ(i,DATA_MNY8) \
     773             :         REQ(i,DATA_MNY4) REQ(i,DATA_DATE8) REQ(i,DATA_DATE4) REQ(i,DATA_FLT4) REQ(i,DATA_FLT8) \
     774             :         REQ(i,DATA_NUM) REQ(i,DATA_TEXT) REQ(i,DATA_IMAGE) REQ(i,DATA_DEC) REQ(i,DATA_LCHAR) \
     775             :         REQ(i,DATA_LBIN) REQ(i,DATA_INTN) REQ(i,DATA_DATETIMEN) REQ(i,DATA_MONEYN) \
     776             :         REQ(i,CSR_PREV) REQ(i,CSR_FIRST) REQ(i,CSR_LAST) REQ(i,CSR_ABS) REQ(i,CSR_REL) \
     777             :         REQ(i,CSR_MULTI) REQ(i,CON_INBAND) REQ(i,PROTO_TEXT) REQ(i,PROTO_BULK) \
     778             :         REQ(i,DATA_SENSITIVITY) REQ(i,DATA_BOUNDARY) REQ(i,PROTO_DYNPROC) REQ(i,DATA_FLTN) \
     779             :         REQ(i,DATA_BITN) REQ(i,DATA_INT8) REQ(i,WIDETABLE) \
     780             :         REQ(i,DATA_UINT2) REQ(i,DATA_UINT4) REQ(i,DATA_UINT8) REQ(i,DATA_UINTN) REQ(i,LARGEIDENT) \
     781             :         REQ(i,SRVPKTSIZE) REQ(i,DATA_DATE) REQ(i,DATA_TIME) REQ(i,DATA_BIGTIME) REQ(i,DATA_BIGDATETIME)
     782             : #define REQ(i,n) |(((TDS_REQ_ ## n / 8) == i)?(1<<(TDS_REQ_ ## n & 7)):0)
     783             : #define REQB(i) 0 SUPPORTED_REQ_CAP(i)
     784             : 
     785             : #undef RES
     786             : #define SUPPORTED_RES_CAP(i) \
     787             :         RES(i,CON_NOOOB) RES(i,PROTO_NOTEXT) RES(i,PROTO_NOBULK) RES(i,NOTDSDEBUG)
     788             : #define RES(i,n) |(((TDS_RES_ ## n / 8) == i)?(1<<(TDS_RES_ ## n & 7)):0)
     789             : #define RESB(i) 0 SUPPORTED_RES_CAP(i)
     790             : 
     791             : static const TDS_CAPABILITIES defaultcaps = { {
     792             :      /* type,  len, data, data, data, data, data, data, data, data, data, data, data, data, data, data (14 bytes) */
     793             :         { 1, 14, { REQB(13), REQB(12), REQB(11), REQB(10), REQB(9), REQB(8), REQB(7),
     794             :                    REQB(6),  REQB(5),  REQB(4),  REQB(3),  REQB(2), REQB(1), REQB(0) } },
     795             :         { 2, 14, { RESB(13), RESB(12), RESB(11), RESB(10), RESB(9), RESB(8), RESB(7),
     796             :                    RESB(6),  RESB(5),  RESB(4),  RESB(3),  RESB(2), RESB(1), RESB(0) } }
     797             : } };
     798             : /* check we match the values size */
     799             : TDS_COMPILE_CHECK(tds_values_len, sizeof(defaultcaps.types[0].values) == 14);
     800             : /* check we match the default size */
     801             : TDS_COMPILE_CHECK(tds_cap_len, sizeof(defaultcaps) == TDS_MAX_CAPABILITY);
     802             : 
     803             : /**
     804             :  * Initialize login structure with locale information and other stuff for connection
     805             :  * @param locale locale information (copied to configuration information)
     806             :  * @result login structure or NULL if initialization error
     807             :  */
     808             : TDSLOGIN*
     809        2992 : tds_init_login(TDSLOGIN *login, TDSLOCALE * locale)
     810             : {
     811             :         char hostname[128];
     812             : #if HAVE_NL_LANGINFO && defined(CODESET)
     813             :         const char *charset;
     814             : #elif !defined(_WIN32)
     815             :         char *lc_all, *tok = NULL;
     816             : #endif
     817             : #ifdef _WIN32
     818             :         char cp[128];
     819             : #endif
     820             : 
     821             :         /*
     822             :          * TDS 7.0:
     823             :          * ODBC driver settings.
     824             :          * Change to initial language must succeed.
     825             :          */
     826        2992 :         login->option_flag2 = TDS_INIT_LANG_REQUIRED|TDS_ODBC_ON;
     827        2992 :         login->tds_version = TDS_DEFAULT_VERSION;
     828        2992 :         login->block_size = 0;
     829             : 
     830             : #if HAVE_NL_LANGINFO && defined(CODESET)
     831        2992 :         charset = nl_langinfo(CODESET);
     832        2992 :         if (strcmp(tds_canonical_charset_name(charset), "US-ASCII") == 0)
     833        2980 :                 charset = "ISO-8859-1";
     834        2992 :         if (!tds_dstr_copy(&login->client_charset, charset))
     835             :                 return NULL;
     836             : #else
     837             :         if (!tds_dstr_copy(&login->client_charset, "ISO-8859-1"))
     838             :                 return NULL;
     839             : 
     840             : #ifdef _WIN32
     841             :         /* for Windows uses GetLocaleInfoA */
     842             :         strcpy(cp, "CP");
     843             :         if (GetLocaleInfoA(GetThreadLocale(), LOCALE_IDEFAULTANSICODEPAGE, cp + 2, sizeof(cp) - 2) > 0)
     844             :                 if (!tds_dstr_copy(&login->client_charset, cp))
     845             :                         return NULL;
     846             : #else
     847             :         if ((lc_all = strdup(setlocale(LC_ALL, NULL))) == NULL)
     848             :                 return NULL;
     849             : 
     850             :         if (strtok_r(lc_all, ".", &tok)) {
     851             :                 char *encoding = strtok_r(NULL, "@", &tok);
     852             :                 if (encoding) {
     853             :                         if (!tds_dstr_copy(&login->client_charset, encoding))
     854             :                                 return NULL;
     855             :                 }
     856             :         }
     857             :         free(lc_all);
     858             : #endif
     859             : #endif
     860             : 
     861        2992 :         if (locale) {
     862        2992 :                 if (locale->language)
     863           0 :                         if (!tds_dstr_copy(&login->language, locale->language))
     864             :                                 return NULL;
     865        2992 :                 if (locale->server_charset)
     866           0 :                         if (!tds_dstr_copy(&login->server_charset, locale->server_charset))
     867             :                                 return NULL;
     868             :         }
     869        5984 :         if (tds_dstr_isempty(&login->language)) {
     870        2936 :                 if (!tds_dstr_copy(&login->language, TDS_DEF_LANG))
     871             :                         return NULL;
     872             :         }
     873        2992 :         memset(hostname, '\0', sizeof(hostname));
     874        2992 :         gethostname(hostname, sizeof(hostname));
     875        2992 :         hostname[sizeof(hostname) - 1] = '\0';  /* make sure it's terminated */
     876        2992 :         if (!tds_dstr_copy(&login->client_host_name, hostname))
     877             :                 return NULL;
     878             : 
     879        2992 :         login->valid_configuration = 1;
     880        2992 :         login->check_ssl_hostname = 1;
     881             : 
     882        2992 :         return login;
     883             : }
     884             : 
     885             : TDSCURSOR *
     886        1742 : tds_alloc_cursor(TDSSOCKET *tds, const char *name, TDS_INT namelen, const char *query, TDS_INT querylen)
     887             : {
     888             :         TDSCURSOR *cursor;
     889             :         TDSCURSOR *pcursor;
     890             : 
     891        1742 :         TEST_MALLOC(cursor, TDSCURSOR);
     892        1742 :         cursor->ref_count = 1;
     893             : 
     894        1742 :         cursor->type = TDS_CUR_TYPE_KEYSET;
     895        1742 :         cursor->concurrency = TDS_CUR_CONCUR_OPTIMISTIC;
     896             : 
     897        1742 :         TEST_CALLOC(cursor->cursor_name, char, namelen + 1);
     898        1742 :         memcpy(cursor->cursor_name, name, namelen);
     899             : 
     900        1742 :         TEST_CALLOC(cursor->query, char, querylen + 1);
     901        1742 :         memcpy(cursor->query, query, querylen);
     902             : 
     903        1742 :         if (tds->conn->cursors == NULL) {
     904        1716 :                 tds->conn->cursors = cursor;
     905             :         } else {
     906           0 :                 for (pcursor = tds->conn->cursors; pcursor->next; pcursor = pcursor->next)
     907           0 :                         continue;
     908          26 :                 pcursor->next = cursor;
     909             :         }
     910             :         /* take into account reference in connection list */
     911        1742 :         ++cursor->ref_count;
     912             : 
     913        1742 :         return cursor;
     914             : 
     915           0 :       Cleanup:
     916           0 :         tds_release_cursor(&cursor);
     917           0 :         return NULL;
     918             : }
     919             : 
     920             : /*
     921             :  * Called when cursor got deallocated from server
     922             :  */
     923             : void
     924        1742 : tds_cursor_deallocated(TDSCONNECTION *conn, TDSCURSOR *cursor)
     925             : {
     926             :         TDSCURSOR **victim;
     927             : 
     928        1742 :         tdsdump_log(TDS_DBG_FUNC, "tds_cursor_deallocated() : freeing cursor_id %d\n", cursor->cursor_id);
     929             : 
     930        1742 :         victim = &conn->cursors;
     931        3496 :         while (*victim != cursor) {
     932          12 :                 if (*victim == NULL) {
     933           0 :                         tdsdump_log(TDS_DBG_FUNC, "tds_cursor_deallocated() : cannot find cursor_id %d\n", cursor->cursor_id);
     934             :                         return;
     935             :                 }
     936          12 :                 victim = &(*victim)->next;
     937             :         }
     938             : 
     939             :         /* remove from list */
     940        1742 :         *victim = cursor->next;
     941        1742 :         cursor->next = NULL;
     942             : 
     943        1742 :         tds_release_cursor(&cursor);
     944             : }
     945             : 
     946             : /*
     947             :  * Decrement reference counter and free if necessary.
     948             :  * Called internally by libTDS and by upper library when you don't need 
     949             :  * cursor reference anymore
     950             :  */
     951             : void
     952       68086 : tds_release_cursor(TDSCURSOR **pcursor)
     953             : {
     954       68086 :         TDSCURSOR *cursor = *pcursor;
     955       68086 :         *pcursor = NULL;
     956       68086 :         if (!cursor || --cursor->ref_count > 0)
     957             :                 return;
     958             : 
     959        1742 :         tdsdump_log(TDS_DBG_FUNC, "tds_release_cursor() : freeing cursor_id %d\n", cursor->cursor_id);
     960             : 
     961        1742 :         tdsdump_log(TDS_DBG_FUNC, "tds_release_cursor() : freeing cursor results\n");
     962        3484 :         tds_detach_results(cursor->res_info);
     963        1742 :         tds_free_results(cursor->res_info);
     964             : 
     965        1742 :         if (cursor->cursor_name) {
     966        1742 :                 tdsdump_log(TDS_DBG_FUNC, "tds_release_cursor() : freeing cursor name\n");
     967        1742 :                 free(cursor->cursor_name);
     968             :         }
     969             : 
     970        1742 :         if (cursor->query) {
     971        1742 :                 tdsdump_log(TDS_DBG_FUNC, "tds_release_cursor() : freeing cursor query\n");
     972        1742 :                 free(cursor->query);
     973             :         }
     974             : 
     975        1742 :         tdsdump_log(TDS_DBG_FUNC, "tds_release_cursor() : cursor_id %d freed\n", cursor->cursor_id);
     976        1742 :         free(cursor);
     977             : }
     978             : 
     979             : TDSLOGIN *
     980        5738 : tds_alloc_login(int use_environment)
     981             : {
     982        5738 :         TDSLOGIN *login = NULL;
     983        5738 :         const char *server_name = TDS_DEF_SERVER;
     984             : 
     985        5738 :         TEST_MALLOC(login, TDSLOGIN);
     986        5738 :         login->check_ssl_hostname = 1;
     987        5738 :         login->use_utf16 = 1;
     988        5738 :         login->bulk_copy = 1;
     989       11476 :         tds_dstr_init(&login->server_name);
     990       11476 :         tds_dstr_init(&login->language);
     991       11476 :         tds_dstr_init(&login->server_charset);
     992       11476 :         tds_dstr_init(&login->client_host_name);
     993       11476 :         tds_dstr_init(&login->server_host_name);
     994       11476 :         tds_dstr_init(&login->app_name);
     995       11476 :         tds_dstr_init(&login->user_name);
     996       11476 :         tds_dstr_init(&login->password);
     997       11476 :         tds_dstr_init(&login->library);
     998       11476 :         tds_dstr_init(&login->new_password);
     999             : 
    1000        5738 :         login->ip_addrs = NULL;
    1001             : 
    1002       11476 :         tds_dstr_init(&login->database);
    1003       11476 :         tds_dstr_init(&login->dump_file);
    1004       11476 :         tds_dstr_init(&login->client_charset);
    1005       11476 :         tds_dstr_init(&login->instance_name);
    1006       11476 :         tds_dstr_init(&login->server_realm_name);
    1007       11476 :         tds_dstr_init(&login->server_spn);
    1008       11476 :         tds_dstr_init(&login->cafile);
    1009       11476 :         tds_dstr_init(&login->crlfile);
    1010       11476 :         tds_dstr_init(&login->db_filename);
    1011       11476 :         tds_dstr_init(&login->openssl_ciphers);
    1012       11476 :         tds_dstr_init(&login->routing_address);
    1013             : 
    1014        5738 :         if (use_environment) {
    1015             :                 const char *s;
    1016        2746 :                 if ((s=getenv("DSQUERY")) != NULL)
    1017           0 :                         server_name = s;
    1018             : 
    1019        2746 :                 if ((s=getenv("TDSQUERY")) != NULL)
    1020           0 :                         server_name = s;
    1021             :         }
    1022             : 
    1023        5738 :         if (!tds_dstr_copy(&login->server_name, server_name)) {
    1024           0 :                 free(login);
    1025           0 :                 return NULL;
    1026             :         }
    1027             : 
    1028        5738 :         login->capabilities = defaultcaps;
    1029        5738 :         login->use_ntlmv2_specified = 0;
    1030        5738 :         login->use_ntlmv2 = 1;
    1031             : 
    1032           0 : Cleanup:
    1033             :         return login;
    1034             : }
    1035             : 
    1036             : void
    1037        6424 : tds_free_login(TDSLOGIN * login)
    1038             : {
    1039        6424 :         if (!login)
    1040             :                 return;
    1041             : 
    1042             :         /* for security reason clear memory */
    1043        5712 :         tds_dstr_zero(&login->password);
    1044        5712 :         tds_dstr_free(&login->password);
    1045        5712 :         tds_dstr_zero(&login->new_password);
    1046        5712 :         tds_dstr_free(&login->new_password);
    1047        5712 :         tds_dstr_free(&login->server_name);
    1048        5712 :         tds_dstr_free(&login->language);
    1049        5712 :         tds_dstr_free(&login->server_charset);
    1050        5712 :         tds_dstr_free(&login->client_host_name);
    1051        5712 :         tds_dstr_free(&login->app_name);
    1052        5712 :         tds_dstr_free(&login->user_name);
    1053        5712 :         tds_dstr_free(&login->library);
    1054        5712 :         tds_dstr_free(&login->client_charset);
    1055        5712 :         tds_dstr_free(&login->server_host_name);
    1056             : 
    1057        5712 :         if (login->ip_addrs != NULL)
    1058        2990 :                 freeaddrinfo(login->ip_addrs);
    1059             : 
    1060        5712 :         tds_dstr_free(&login->database);
    1061        5712 :         tds_dstr_free(&login->dump_file);
    1062        5712 :         tds_dstr_free(&login->instance_name);
    1063        5712 :         tds_dstr_free(&login->server_realm_name);
    1064        5712 :         tds_dstr_free(&login->server_spn);
    1065        5712 :         tds_dstr_free(&login->cafile);
    1066        5712 :         tds_dstr_free(&login->crlfile);
    1067        5712 :         tds_dstr_free(&login->db_filename);
    1068        5712 :         tds_dstr_free(&login->openssl_ciphers);
    1069        5712 :         tds_dstr_free(&login->routing_address);
    1070        5712 :         free(login);
    1071             : }
    1072             : 
    1073             : TDSPACKET *
    1074       12409 : tds_alloc_packet(void *buf, unsigned len)
    1075             : {
    1076       12409 :         TDSPACKET *packet = (TDSPACKET *) malloc(len + TDS_OFFSET(TDSPACKET, buf));
    1077       12409 :         if (TDS_LIKELY(packet)) {
    1078        8608 :                 tds_packet_zero_data_start(packet);
    1079       12409 :                 packet->data_len = 0;
    1080       12409 :                 packet->capacity = len;
    1081       12409 :                 packet->sid = 0;
    1082       12409 :                 packet->next = NULL;
    1083       12409 :                 if (buf) {
    1084         113 :                         memcpy(packet->buf, buf, len);
    1085         113 :                         packet->data_len = len;
    1086             :                 }
    1087             :         }
    1088       12409 :         return packet;
    1089             : }
    1090             : 
    1091             : TDSPACKET *
    1092       38928 : tds_realloc_packet(TDSPACKET *packet, unsigned len)
    1093             : {
    1094       44817 :         if (packet->capacity < len) {
    1095        4925 :                 packet = (TDSPACKET *) realloc(packet, len + TDS_OFFSET(TDSPACKET, buf));
    1096        4925 :                 if (TDS_LIKELY(packet))
    1097        4925 :                         packet->capacity = len;
    1098             :         }
    1099       38928 :         return packet;
    1100             : }
    1101             : 
    1102             : void
    1103       40549 : tds_free_packets(TDSPACKET *packet)
    1104             : {
    1105             :         TDSPACKET *next;
    1106       52898 :         for (; packet; packet = next) {
    1107       12349 :                 next = packet->next;
    1108       12349 :                 free(packet);
    1109             :         }
    1110       40549 : }
    1111             : 
    1112             : static void
    1113        3726 : tds_deinit_connection(TDSCONNECTION *conn)
    1114             : {
    1115        3726 :         if (conn->authentication)
    1116           0 :                 conn->authentication->free(conn, conn->authentication);
    1117        3726 :         conn->authentication = NULL;
    1118        7492 :         while (conn->dyns)
    1119          40 :                 tds_dynamic_deallocated(conn, conn->dyns);
    1120        3738 :         while (conn->cursors)
    1121          12 :                 tds_cursor_deallocated(conn, conn->cursors);
    1122        3726 :         tds_ssl_deinit(conn);
    1123             :         /* close connection and free inactive sockets */
    1124        3726 :         tds_connection_close(conn);
    1125        3726 :         tds_wakeup_close(&conn->wakeup);
    1126        3726 :         tds_iconv_free(conn);
    1127        3726 :         free(conn->product_name);
    1128        3726 :         free(conn->server);
    1129        3726 :         tds_free_env(conn);
    1130        7452 :         tds_free_packets(conn->packet_cache);
    1131        3726 :         tds_mutex_free(&conn->list_mtx);
    1132             : #if ENABLE_ODBC_MARS
    1133        3762 :         tds_free_packets(conn->packets);
    1134        3762 :         tds_free_packets(conn->recv_packet);
    1135        3762 :         tds_free_packets(conn->send_packets);
    1136        1881 :         free(conn->sessions);
    1137             : #endif
    1138        3726 : }
    1139             : 
    1140             : static TDSCONNECTION *
    1141        3750 : tds_init_connection(TDSCONNECTION *conn, TDSCONTEXT *context, unsigned int bufsize)
    1142             : {
    1143        3750 :         conn->env.block_size = bufsize;
    1144        3750 :         conn->s = INVALID_SOCKET;
    1145        3750 :         conn->use_iconv = 1;
    1146        3750 :         conn->tds_ctx = context;
    1147        3750 :         conn->ncharsize = 1;
    1148        3750 :         conn->unicharsize = 1;
    1149             : 
    1150        3750 :         if (tds_wakeup_init(&conn->wakeup))
    1151             :                 goto Cleanup;
    1152             : 
    1153        3750 :         if (tds_iconv_alloc(conn))
    1154             :                 goto Cleanup;
    1155             : 
    1156        7500 :         if (tds_mutex_init(&conn->list_mtx))
    1157             :                 goto Cleanup;
    1158             : 
    1159             : #if ENABLE_ODBC_MARS
    1160        1893 :         TEST_CALLOC(conn->sessions, TDSSOCKET*, 64);
    1161        1893 :         conn->num_sessions = 64;
    1162             : #endif
    1163        1893 :         return conn;
    1164             : 
    1165           0 : Cleanup:
    1166           0 :         tds_wakeup_close(&conn->wakeup);
    1167           0 :         tds_iconv_free(conn);
    1168           0 :         return NULL;
    1169             : }
    1170             : 
    1171             : static TDSSOCKET *
    1172        3755 : tds_init_socket(TDSSOCKET * tds_socket, unsigned int bufsize)
    1173             : {
    1174             :         TDSPACKET *pkt;
    1175             : 
    1176        3755 :         tds_socket->parent = NULL;
    1177             : 
    1178        3755 :         tds_socket->recv_packet = tds_alloc_packet(NULL, bufsize);
    1179        3755 :         if (!tds_socket->recv_packet)
    1180             :                 goto Cleanup;
    1181        3755 :         tds_socket->in_buf = tds_socket->recv_packet->buf;
    1182             : 
    1183        3755 :         pkt = tds_alloc_packet(NULL, bufsize + TDS_ADDITIONAL_SPACE);
    1184        3755 :         if (!pkt)
    1185             :                 goto Cleanup;
    1186        3755 :         tds_set_current_send_packet(tds_socket, pkt);
    1187             : 
    1188        3755 :         tds_socket->out_buf_max = bufsize;
    1189             : 
    1190             :         /* Jeff's hack, init to no timeout */
    1191        3755 :         tds_socket->query_timeout = 0;
    1192        3755 :         tds_init_write_buf(tds_socket);
    1193        3755 :         tds_socket->state = TDS_DEAD;
    1194        3755 :         tds_socket->env_chg_func = NULL;
    1195        7510 :         if (tds_mutex_init(&tds_socket->wire_mtx))
    1196             :                 goto Cleanup;
    1197             : 
    1198             : #ifdef ENABLE_ODBC_MARS
    1199        1898 :         tds_socket->sid = 0;
    1200        1898 :         if (tds_cond_init(&tds_socket->packet_cond))
    1201             :                 goto Cleanup;
    1202             : 
    1203        1898 :         tds_socket->recv_seq = 0;
    1204        1898 :         tds_socket->send_seq = 0;
    1205        1898 :         tds_socket->recv_wnd = 4;
    1206        1898 :         tds_socket->send_wnd = 4;
    1207             : #endif
    1208        1898 :         return tds_socket;
    1209             : 
    1210           0 :       Cleanup:
    1211             :         return NULL;
    1212             : }
    1213             : 
    1214             : 
    1215             : #if ENABLE_ODBC_MARS
    1216             : static void
    1217        1881 : tds_free_connection(TDSCONNECTION *conn)
    1218             : {
    1219        1881 :         if (!conn) return;
    1220        1881 :         assert(conn->in_net_tds == NULL);
    1221        1881 :         tds_deinit_connection(conn);
    1222        1881 :         free(conn);
    1223             : }
    1224             : 
    1225             : static TDSCONNECTION *
    1226        1893 : tds_alloc_connection(TDSCONTEXT *context, unsigned int bufsize)
    1227             : {
    1228             :         TDSCONNECTION *conn;
    1229             : 
    1230        1893 :         TEST_MALLOC(conn, TDSCONNECTION);
    1231        1893 :         if (!tds_init_connection(conn, context, bufsize))
    1232             :                 goto Cleanup;
    1233             :         return conn;
    1234             : 
    1235           0 : Cleanup:
    1236           0 :         tds_free_connection(conn);
    1237           0 :         return NULL;
    1238             : }
    1239             : 
    1240             : static TDSSOCKET *
    1241        1898 : tds_alloc_socket_base(unsigned int bufsize)
    1242             : {
    1243             :         TDSSOCKET *tds_socket;
    1244             : 
    1245        1898 :         TEST_MALLOC(tds_socket, TDSSOCKET);
    1246        1898 :         if (!tds_init_socket(tds_socket, bufsize))
    1247             :                 goto Cleanup;
    1248             :         return tds_socket;
    1249             : 
    1250           0 :       Cleanup:
    1251           0 :         tds_free_socket(tds_socket);
    1252           0 :         return NULL;
    1253             : }
    1254             : 
    1255             : TDSSOCKET *
    1256        1893 : tds_alloc_socket(TDSCONTEXT * context, unsigned int bufsize)
    1257             : {
    1258        1893 :         TDSCONNECTION *conn = tds_alloc_connection(context, bufsize);
    1259             :         TDSSOCKET *tds;
    1260             : 
    1261        1893 :         if (!conn)
    1262             :                 return NULL;
    1263             : 
    1264        1893 :         tds = tds_alloc_socket_base(bufsize);
    1265        1893 :         if (tds) {
    1266        1893 :                 conn->sessions[0] = tds;
    1267        1893 :                 tds->conn = conn;
    1268        1893 :                 return tds;
    1269             :         }
    1270           0 :         tds_free_connection(conn);
    1271           0 :         return NULL;
    1272             : }
    1273             : 
    1274             : static bool
    1275           5 : tds_alloc_new_sid(TDSSOCKET *tds)
    1276             : {
    1277             :         uint16_t sid;
    1278           5 :         TDSCONNECTION *conn = tds->conn;
    1279             : 
    1280           5 :         tds_mutex_lock(&conn->list_mtx);
    1281           7 :         for (sid = 1; sid < conn->num_sessions; ++sid)
    1282           7 :                 if (!conn->sessions[sid])
    1283             :                         break;
    1284           5 :         if (sid == conn->num_sessions) {
    1285             :                 /* extend array */
    1286           0 :                 TDSSOCKET **s = (TDSSOCKET **) TDS_RESIZE(conn->sessions, sid+64);
    1287           0 :                 if (!s)
    1288             :                         goto error;
    1289           0 :                 memset(s + conn->num_sessions, 0, sizeof(*s) * 64);
    1290           0 :                 conn->num_sessions += 64;
    1291             :         }
    1292           5 :         conn->sessions[sid] = tds;
    1293           5 :         tds->sid = sid;
    1294           5 : error:
    1295           5 :         tds_mutex_unlock(&conn->list_mtx);
    1296           5 :         return tds->sid != 0;
    1297             : }
    1298             : 
    1299             : TDSSOCKET *
    1300          11 : tds_alloc_additional_socket(TDSCONNECTION *conn)
    1301             : {
    1302             :         TDSSOCKET *tds;
    1303          11 :         if (!IS_TDS72_PLUS(conn) || !conn->mars)
    1304             :                 return NULL;
    1305             : 
    1306           5 :         tds = tds_alloc_socket_base(sizeof(TDS72_SMP_HEADER) + conn->env.block_size);
    1307           5 :         if (!tds)
    1308             :                 return NULL;
    1309           5 :         tds->send_packet->data_start = sizeof(TDS72_SMP_HEADER);
    1310           5 :         tds->out_buf = tds->send_packet->buf + sizeof(TDS72_SMP_HEADER);
    1311           5 :         tds->out_buf_max -= sizeof(TDS72_SMP_HEADER);
    1312             : 
    1313           5 :         tds->conn = conn;
    1314           5 :         if (!tds_alloc_new_sid(tds))
    1315             :                 goto Cleanup;
    1316             : 
    1317           5 :         tds->state = TDS_IDLE;
    1318           5 :         if (TDS_FAILED(tds_append_syn(tds)))
    1319             :                 goto Cleanup;
    1320             : 
    1321             :         return tds;
    1322             : 
    1323           0 :       Cleanup:
    1324           0 :         tds_free_socket(tds);
    1325           0 :         return NULL;
    1326             : }
    1327             : #else /* !ENABLE_ODBC_MARS */
    1328             : TDSSOCKET *
    1329        1857 : tds_alloc_socket(TDSCONTEXT * context, unsigned int bufsize)
    1330             : {
    1331             :         TDSSOCKET *tds_socket;
    1332             : 
    1333        1857 :         TEST_MALLOC(tds_socket, TDSSOCKET);
    1334        1857 :         if (!tds_init_connection(tds_socket->conn, context, bufsize))
    1335             :                 goto Cleanup;
    1336        1857 :         if (!tds_init_socket(tds_socket, bufsize))
    1337             :                 goto Cleanup;
    1338             :         return tds_socket;
    1339             : 
    1340           0 :       Cleanup:
    1341           0 :         tds_free_socket(tds_socket);
    1342           0 :         return NULL;
    1343             : }
    1344             : #endif /* !ENABLE_ODBC_MARS */
    1345             : 
    1346             : TDSSOCKET *
    1347        5889 : tds_realloc_socket(TDSSOCKET * tds, size_t bufsize)
    1348             : {
    1349             :         TDSPACKET *packet;
    1350             : #if ENABLE_ODBC_MARS
    1351        3014 :         size_t smp_hdr_len = tds->conn->mars ? sizeof(TDS72_SMP_HEADER) : 0;
    1352             : #else
    1353             :         enum { smp_hdr_len = 0 };
    1354             : #endif
    1355             : 
    1356        5889 :         assert(tds && tds->out_buf && tds->send_packet);
    1357             : 
    1358        5889 :         if (bufsize < 512)
    1359           0 :                 bufsize = 512;
    1360             : 
    1361             :         /* prevent nasty memory conditions, server should send the request at
    1362             :          * the beginning only */
    1363        5889 :         if (tds->out_pos > bufsize || tds->frozen)
    1364             :                 return NULL;
    1365             : 
    1366        5889 :         tds->conn->env.block_size = bufsize;
    1367             : 
    1368       11778 :         packet = tds_realloc_packet(tds->send_packet, smp_hdr_len + bufsize + TDS_ADDITIONAL_SPACE);
    1369        5889 :         if (packet == NULL)
    1370             :                 return NULL;
    1371             : 
    1372             : #if ENABLE_ODBC_MARS
    1373        3014 :         packet->data_start = smp_hdr_len;
    1374             : #endif
    1375        5889 :         tds->out_buf_max = bufsize;
    1376        5889 :         tds_set_current_send_packet(tds, packet);
    1377        5889 :         return tds;
    1378             : }
    1379             : 
    1380             : #if ENABLE_ODBC_MARS
    1381             : static void
    1382        1886 : tds_connection_remove_socket(TDSCONNECTION *conn, TDSSOCKET *tds)
    1383             : {
    1384             :         unsigned n;
    1385        1886 :         bool must_free_connection = true;
    1386        1886 :         tds_mutex_lock(&conn->list_mtx);
    1387        1886 :         if (tds->sid < conn->num_sessions)
    1388        1886 :                 conn->sessions[tds->sid] = NULL;
    1389      122270 :         for (n = 0; n < conn->num_sessions; ++n)
    1390      120389 :                 if (TDSSOCKET_VALID(conn->sessions[n])) {
    1391             :                         must_free_connection = false;
    1392             :                         break;
    1393             :                 }
    1394        1886 :         if (!must_free_connection) {
    1395             :                 /* tds use connection member so must be valid */
    1396           5 :                 tds_append_fin(tds);
    1397             :         }
    1398        1886 :         tds_mutex_unlock(&conn->list_mtx);
    1399             : 
    1400             :         /* detach entirely */
    1401        1886 :         tds->conn = NULL;
    1402             : 
    1403        1886 :         if (must_free_connection)
    1404        1881 :                 tds_free_connection(conn);
    1405        1886 : }
    1406             : #else
    1407             : static void inline
    1408             : tds_connection_remove_socket(TDSCONNECTION *conn, TDSSOCKET *tds)
    1409             : {
    1410        1845 :         tds_deinit_connection(conn);
    1411             : }
    1412             : #endif
    1413             : 
    1414             : void
    1415        5703 : tds_free_socket(TDSSOCKET * tds)
    1416             : {
    1417             : #if ENABLE_EXTRA_CHECKS
    1418             :         TDSDYNAMIC *dyn;
    1419             :         TDSCURSOR *cur;
    1420             : #endif
    1421             : 
    1422        5703 :         if (!tds)
    1423             :                 return;
    1424             : 
    1425             :         /* detach this socket */
    1426        3731 :         tds_release_cur_dyn(tds);
    1427        3731 :         tds_release_cursor(&tds->cur_cursor);
    1428        7462 :         tds_detach_results(tds->current_results);
    1429             : #if ENABLE_EXTRA_CHECKS
    1430        3773 :         for (dyn = tds->conn->dyns; dyn; dyn = dyn->next) {
    1431          42 :                 if (dyn->res_info && dyn->res_info->attached_to == tds) {
    1432           0 :                         assert(0);
    1433             :                 }
    1434             :         }
    1435        3743 :         for (cur = tds->conn->cursors; cur; cur = cur->next) {
    1436          12 :                 if (cur->res_info && cur->res_info->attached_to == tds) {
    1437           0 :                         assert(0);
    1438             :                 }
    1439             :         }
    1440             : #endif
    1441        3731 :         tds_free_all_results(tds);
    1442             : #if ENABLE_ODBC_MARS
    1443        3772 :         tds_cond_destroy(&tds->packet_cond);
    1444             : #endif
    1445             : 
    1446        5576 :         tds_connection_remove_socket(tds->conn, tds);
    1447        7462 :         tds_free_packets(tds->recv_packet);
    1448        3731 :         if (tds->frozen_packets)
    1449             :                 tds_free_packets(tds->frozen_packets);
    1450             :         else
    1451        3731 :                 tds_free_packets(tds->send_packet);
    1452        3731 :         free(tds);
    1453             : }
    1454             : 
    1455             : void
    1456        2858 : tds_free_locale(TDSLOCALE * locale)
    1457             : {
    1458        2858 :         if (!locale)
    1459             :                 return;
    1460             : 
    1461        2858 :         free(locale->language);
    1462        2858 :         free(locale->server_charset);
    1463        2858 :         free(locale->datetime_fmt);
    1464        2858 :         free(locale->date_fmt);
    1465        2858 :         free(locale->time_fmt);
    1466        2858 :         free(locale);
    1467             : }
    1468             : 
    1469             : static void
    1470        3726 : tds_free_env(TDSCONNECTION* conn)
    1471             : {
    1472        3726 :         if (conn->env.language)
    1473        2138 :                 TDS_ZERO_FREE(conn->env.language);
    1474        3726 :         if (conn->env.charset)
    1475         534 :                 TDS_ZERO_FREE(conn->env.charset);
    1476        3726 :         if (conn->env.database)
    1477        2838 :                 TDS_ZERO_FREE(conn->env.database);
    1478        3726 : }
    1479             : 
    1480             : void
    1481       11859 : tds_free_msg(TDSMESSAGE * message)
    1482             : {
    1483       11859 :         if (message) {
    1484       11859 :                 message->priv_msg_type = 0;
    1485       11859 :                 message->msgno = 0;
    1486       11859 :                 message->state = 0;
    1487       11859 :                 message->severity = 0;
    1488       11859 :                 message->line_number = 0;
    1489       11859 :                 TDS_ZERO_FREE(message->message);
    1490       11859 :                 TDS_ZERO_FREE(message->server);
    1491       11859 :                 TDS_ZERO_FREE(message->proc_name);
    1492       11859 :                 TDS_ZERO_FREE(message->sql_state);
    1493             :         }
    1494       11859 : }
    1495             : 
    1496             : #define SQLS_ENTRY(number,state) case number: p = state; break
    1497             : 
    1498             : char *
    1499       33028 : tds_alloc_client_sqlstate(int msgno)
    1500             : {
    1501       33028 :         const char *p = NULL;
    1502             : 
    1503       33028 :         switch (msgno) {
    1504             :                 SQLS_ENTRY(17000, "S1T00");   /* timeouts ??? */
    1505           1 :                 SQLS_ENTRY(20004, "08S01");   /* Communication link failure */
    1506          54 :                 SQLS_ENTRY(20006, "08S01");
    1507           0 :                 SQLS_ENTRY(20009, "08S01");
    1508           0 :                 SQLS_ENTRY(20020, "08S01");
    1509           0 :                 SQLS_ENTRY(20019, "24000");   /* Invalid cursor state */
    1510           0 :                 SQLS_ENTRY(20014, "28000");   /* Invalid authorization specification */
    1511       28824 :                 SQLS_ENTRY(2400, "42000");    /* Syntax error or access violation */
    1512         592 :                 SQLS_ENTRY(2401, "42000");
    1513        1544 :                 SQLS_ENTRY(2403, "42000");
    1514           0 :                 SQLS_ENTRY(2404, "42000");
    1515        1769 :                 SQLS_ENTRY(2402, "S1000");    /* General error */
    1516             :         }
    1517             : 
    1518             :         if (p != NULL)
    1519       32784 :                 return strdup(p);
    1520             :         else
    1521             :                 return NULL;
    1522             : }
    1523             : 
    1524             : char *
    1525       11750 : tds_alloc_lookup_sqlstate(TDSSOCKET * tds, int msgno)
    1526             : {
    1527       11750 :         const char *p = NULL;
    1528       11750 :         char *q = NULL;
    1529             : 
    1530       11750 :         if (TDS_IS_MSSQL(tds)) {
    1531        5106 :                 switch (msgno) {        /* MSSQL Server */
    1532             : 
    1533         468 :                         SQLS_ENTRY(3621,"01000");
    1534          20 :                         SQLS_ENTRY(8153,"01003");     /* Null in aggregate */
    1535           6 :                         SQLS_ENTRY(911, "08004");     /* Server rejected connection */
    1536           0 :                         SQLS_ENTRY(512, "21000");     /* Subquery returns more than one value */
    1537           0 :                         SQLS_ENTRY(213, "21S01");     /* Insert column list mismatch */
    1538           0 :                         SQLS_ENTRY(109, "21S01");
    1539           0 :                         SQLS_ENTRY(110, "21S01");
    1540           0 :                         SQLS_ENTRY(1774,"21S02");     /* Ref column mismatch */
    1541           0 :                         SQLS_ENTRY(8152,"22001");     /* String data would be truncated */
    1542           0 :                         SQLS_ENTRY(5146,"22003");     /* Numeric value out of range */
    1543           0 :                         SQLS_ENTRY(168, "22003");     /* Arithmetic overflow */
    1544         396 :                         SQLS_ENTRY(220, "22003");
    1545           0 :                         SQLS_ENTRY(232, "22003");
    1546           0 :                         SQLS_ENTRY(234, "22003");
    1547           0 :                         SQLS_ENTRY(236, "22003");
    1548           0 :                         SQLS_ENTRY(238, "22003");
    1549           0 :                         SQLS_ENTRY(244, "22003");
    1550           0 :                         SQLS_ENTRY(246, "22003");
    1551           0 :                         SQLS_ENTRY(248, "22003");
    1552           0 :                         SQLS_ENTRY(519, "22003");
    1553           0 :                         SQLS_ENTRY(520, "22003");
    1554           0 :                         SQLS_ENTRY(521, "22003");
    1555           0 :                         SQLS_ENTRY(522, "22003");
    1556           0 :                         SQLS_ENTRY(523, "22003");
    1557           0 :                         SQLS_ENTRY(524, "22003");
    1558           0 :                         SQLS_ENTRY(1007,"22003");
    1559           0 :                         SQLS_ENTRY(3606,"22003");
    1560           0 :                         SQLS_ENTRY(8115,"22003");
    1561           0 :                         SQLS_ENTRY(206, "22005");     /* Error in assignment */
    1562           0 :                         SQLS_ENTRY(235, "22005");
    1563           0 :                         SQLS_ENTRY(247, "22005");
    1564           0 :                         SQLS_ENTRY(249, "22005");
    1565           0 :                         SQLS_ENTRY(256, "22005");
    1566           0 :                         SQLS_ENTRY(257, "22005");
    1567           0 :                         SQLS_ENTRY(305, "22005");
    1568           0 :                         SQLS_ENTRY(409, "22005");
    1569           0 :                         SQLS_ENTRY(518, "22005");
    1570           0 :                         SQLS_ENTRY(529, "22005");
    1571           0 :                         SQLS_ENTRY(210, "22007");     /* Invalid datetime format */
    1572           0 :                         SQLS_ENTRY(241, "22007");
    1573           0 :                         SQLS_ENTRY(295, "22007");
    1574          12 :                         SQLS_ENTRY(242, "22008");     /* Datetime out of range */
    1575           0 :                         SQLS_ENTRY(296, "22008");
    1576           0 :                         SQLS_ENTRY(298, "22008");
    1577           0 :                         SQLS_ENTRY(535, "22008");
    1578           0 :                         SQLS_ENTRY(542, "22008");
    1579           6 :                         SQLS_ENTRY(517, "22008");
    1580           0 :                         SQLS_ENTRY(3607, "22012");    /* Div by zero */
    1581          18 :                         SQLS_ENTRY(8134, "22012");
    1582           0 :                         SQLS_ENTRY(245, "22018");     /* Syntax error? */
    1583           6 :                         SQLS_ENTRY(2627, "23000");    /* Constraint violation */
    1584           6 :                         SQLS_ENTRY(515, "23000");
    1585           0 :                         SQLS_ENTRY(233, "23000");
    1586           0 :                         SQLS_ENTRY(273, "23000");
    1587           0 :                         SQLS_ENTRY(530, "23000");
    1588           0 :                         SQLS_ENTRY(2601,"23000");
    1589           0 :                         SQLS_ENTRY(2615,"23000");
    1590           0 :                         SQLS_ENTRY(2626,"23000");
    1591           0 :                         SQLS_ENTRY(3604,"23000");
    1592           0 :                         SQLS_ENTRY(3605,"23000");
    1593           0 :                         SQLS_ENTRY(544, "23000");
    1594           0 :                         SQLS_ENTRY(547, "23000");
    1595           0 :                         SQLS_ENTRY(550, "23000");
    1596           0 :                         SQLS_ENTRY(4415, "23000");
    1597           0 :                         SQLS_ENTRY(1505, "23000");
    1598           0 :                         SQLS_ENTRY(1508, "23000");
    1599           0 :                         SQLS_ENTRY(3725, "23000");
    1600           0 :                         SQLS_ENTRY(3726, "23000");
    1601           0 :                         SQLS_ENTRY(4712, "23000");
    1602           0 :                         SQLS_ENTRY(10055, "23000");
    1603           0 :                         SQLS_ENTRY(10065, "23000");
    1604           0 :                         SQLS_ENTRY(11011, "23000");
    1605           0 :                         SQLS_ENTRY(11040, "23000");
    1606           0 :                         SQLS_ENTRY(16999, "24000");   /* Invalid cursor state */
    1607           0 :                         SQLS_ENTRY(16905, "24000");
    1608           0 :                         SQLS_ENTRY(16917, "24000");
    1609           0 :                         SQLS_ENTRY(16946, "24000");
    1610           0 :                         SQLS_ENTRY(16950, "24000");
    1611           0 :                         SQLS_ENTRY(266, "25000");     /* Invalid transaction state */
    1612           0 :                         SQLS_ENTRY(277,"25000");
    1613           0 :                         SQLS_ENTRY(611,"25000");
    1614           0 :                         SQLS_ENTRY(3906,"25000");
    1615           0 :                         SQLS_ENTRY(3908,"25000");
    1616           0 :                         SQLS_ENTRY(6401,"25000");
    1617           0 :                         SQLS_ENTRY(626, "25000");
    1618           0 :                         SQLS_ENTRY(627, "25000");
    1619           0 :                         SQLS_ENTRY(628, "25000");
    1620           0 :                         SQLS_ENTRY(3902, "25000");
    1621           0 :                         SQLS_ENTRY(3903, "25000");
    1622           0 :                         SQLS_ENTRY(3916, "25000");
    1623           0 :                         SQLS_ENTRY(3918, "25000");
    1624           0 :                         SQLS_ENTRY(3919, "25000");
    1625           0 :                         SQLS_ENTRY(3921, "25000");
    1626           0 :                         SQLS_ENTRY(3922, "25000");
    1627          16 :                         SQLS_ENTRY(3926, "25000");
    1628           0 :                         SQLS_ENTRY(7969, "25000");
    1629           0 :                         SQLS_ENTRY(8506, "25000");
    1630           0 :                         SQLS_ENTRY(15626, "25000");
    1631           0 :                         SQLS_ENTRY(18456, "28000");   /* Login failed? */
    1632           0 :                         SQLS_ENTRY(6104, "37000");    /* Syntax error or access violation */
    1633           0 :                         SQLS_ENTRY(8114, "37000");
    1634           0 :                         SQLS_ENTRY(131, "37000");
    1635           2 :                         SQLS_ENTRY(137, "37000");
    1636          22 :                         SQLS_ENTRY(170, "37000");
    1637           0 :                         SQLS_ENTRY(174, "37000");
    1638           0 :                         SQLS_ENTRY(201, "37000");
    1639           6 :                         SQLS_ENTRY(2812, "37000");
    1640           0 :                         SQLS_ENTRY(2526, "37000");
    1641           0 :                         SQLS_ENTRY(8144, "37000");
    1642           0 :                         SQLS_ENTRY(17308, "42000");   /* Syntax/Access violation */
    1643           0 :                         SQLS_ENTRY(17571, "42000");
    1644           0 :                         SQLS_ENTRY(18002, "42000");
    1645           0 :                         SQLS_ENTRY(229, "42000");
    1646           0 :                         SQLS_ENTRY(230, "42000");
    1647           0 :                         SQLS_ENTRY(262, "42000");
    1648           0 :                         SQLS_ENTRY(2557, "42000");
    1649           0 :                         SQLS_ENTRY(2571, "42000");
    1650           0 :                         SQLS_ENTRY(2760, "42000");
    1651           0 :                         SQLS_ENTRY(3110, "42000");
    1652           0 :                         SQLS_ENTRY(3704, "42000");
    1653           0 :                         SQLS_ENTRY(4613, "42000");
    1654           0 :                         SQLS_ENTRY(4618, "42000");
    1655           0 :                         SQLS_ENTRY(4834, "42000");
    1656           0 :                         SQLS_ENTRY(5011, "42000");
    1657           0 :                         SQLS_ENTRY(5116, "42000");
    1658           0 :                         SQLS_ENTRY(5812, "42000");
    1659           0 :                         SQLS_ENTRY(6004, "42000");
    1660           0 :                         SQLS_ENTRY(6102, "42000");
    1661           0 :                         SQLS_ENTRY(7956, "42000");
    1662           0 :                         SQLS_ENTRY(11010, "42000");
    1663           0 :                         SQLS_ENTRY(11045, "42000");
    1664           0 :                         SQLS_ENTRY(14126, "42000");
    1665           0 :                         SQLS_ENTRY(15247, "42000");
    1666           0 :                         SQLS_ENTRY(15622, "42000");
    1667           0 :                         SQLS_ENTRY(20604, "42000");
    1668           0 :                         SQLS_ENTRY(21049, "42000");
    1669           0 :                         SQLS_ENTRY(113, "42000");
    1670           0 :                         SQLS_ENTRY(2714, "42S01");    /* Table or view already exists */
    1671          18 :                         SQLS_ENTRY(208, "42S02");     /* Table or view not found */
    1672         144 :                         SQLS_ENTRY(3701, "42S02");
    1673           0 :                         SQLS_ENTRY(1913, "42S11");    /* Index already exists */
    1674           0 :                         SQLS_ENTRY(15605, "42S11");
    1675           0 :                         SQLS_ENTRY(307, "42S12");     /* Index not found */
    1676           0 :                         SQLS_ENTRY(308, "42S12");
    1677           0 :                         SQLS_ENTRY(10033, "42S12");
    1678           0 :                         SQLS_ENTRY(15323, "42S12");
    1679           0 :                         SQLS_ENTRY(18833, "42S12");
    1680           0 :                         SQLS_ENTRY(4925, "42S21");    /* Column already exists */
    1681           0 :                         SQLS_ENTRY(21255, "42S21");
    1682           0 :                         SQLS_ENTRY(1911, "42S22");    /* Column not found */
    1683          36 :                         SQLS_ENTRY(207, "42S22");
    1684           0 :                         SQLS_ENTRY(4924, "42S22");
    1685           0 :                         SQLS_ENTRY(4926, "42S22");
    1686           0 :                         SQLS_ENTRY(15645, "42S22");
    1687           0 :                         SQLS_ENTRY(21166, "42S22");
    1688             :                 }
    1689             :         } else {
    1690        6644 :                 switch (msgno) {        /* Sybase */
    1691           4 :                         SQLS_ENTRY(3621, "01000");
    1692           0 :                         SQLS_ENTRY(9501, "01003");    /* Null in aggregate */
    1693           1 :                         SQLS_ENTRY(911, "08004");     /* Server rejected connection */
    1694           0 :                         SQLS_ENTRY(512, "21000");     /* Subquery returns more than one value */
    1695           0 :                         SQLS_ENTRY(213, "21S01");     /* Insert column list mismatch */
    1696           0 :                         SQLS_ENTRY(109, "21S01");
    1697           0 :                         SQLS_ENTRY(110, "21S01");
    1698           0 :                         SQLS_ENTRY(1715, "21S02");    /* Ref column mismatch */
    1699           0 :                         SQLS_ENTRY(9502, "22001");    /* String data would be truncated */
    1700           0 :                         SQLS_ENTRY(220, "22003");     /* Arithmetic overflow */
    1701           0 :                         SQLS_ENTRY(168, "22003");
    1702           0 :                         SQLS_ENTRY(227, "22003");
    1703           0 :                         SQLS_ENTRY(232, "22003");
    1704           0 :                         SQLS_ENTRY(234, "22003");
    1705           0 :                         SQLS_ENTRY(236, "22003");
    1706           0 :                         SQLS_ENTRY(238, "22003");
    1707           0 :                         SQLS_ENTRY(244, "22003");
    1708           0 :                         SQLS_ENTRY(246, "22003");
    1709           0 :                         SQLS_ENTRY(247, "22003");
    1710           0 :                         SQLS_ENTRY(248, "22003");
    1711           0 :                         SQLS_ENTRY(519, "22003");
    1712           0 :                         SQLS_ENTRY(520, "22003");
    1713           0 :                         SQLS_ENTRY(521, "22003");
    1714           0 :                         SQLS_ENTRY(522, "22003");
    1715           0 :                         SQLS_ENTRY(523, "22003");
    1716           0 :                         SQLS_ENTRY(524, "22003");
    1717           0 :                         SQLS_ENTRY(3606, "22003");
    1718           0 :                         SQLS_ENTRY(206, "22005");     /* Error in assignment */
    1719           0 :                         SQLS_ENTRY(235, "22005");
    1720           4 :                         SQLS_ENTRY(249, "22005");
    1721           0 :                         SQLS_ENTRY(256, "22005");
    1722           0 :                         SQLS_ENTRY(305, "22005");
    1723           0 :                         SQLS_ENTRY(409, "22005");
    1724           0 :                         SQLS_ENTRY(518, "22005");
    1725           0 :                         SQLS_ENTRY(529, "22005");
    1726           0 :                         SQLS_ENTRY(535, "22008");     /* Datetime out of range */
    1727           0 :                         SQLS_ENTRY(542, "22008");
    1728           2 :                         SQLS_ENTRY(517, "22008");
    1729           0 :                         SQLS_ENTRY(3607, "22012");    /* Div by zero */
    1730           0 :                         SQLS_ENTRY(245, "22018");     /* Syntax error? */
    1731           0 :                         SQLS_ENTRY(544, "23000");     /* Constraint violation */
    1732           0 :                         SQLS_ENTRY(233, "23000");
    1733           0 :                         SQLS_ENTRY(273, "23000");
    1734           0 :                         SQLS_ENTRY(530, "23000");
    1735           0 :                         SQLS_ENTRY(2601,"23000");
    1736           0 :                         SQLS_ENTRY(2615,"23000");
    1737           0 :                         SQLS_ENTRY(2626,"23000");
    1738           0 :                         SQLS_ENTRY(3604,"23000");
    1739           0 :                         SQLS_ENTRY(3605,"23000");
    1740           0 :                         SQLS_ENTRY(545, "23000");
    1741           0 :                         SQLS_ENTRY(546, "23000");
    1742           0 :                         SQLS_ENTRY(547, "23000");
    1743           0 :                         SQLS_ENTRY(548, "23000");
    1744           0 :                         SQLS_ENTRY(549, "23000");
    1745           0 :                         SQLS_ENTRY(550, "23000");
    1746           0 :                         SQLS_ENTRY(1505, "23000");
    1747           0 :                         SQLS_ENTRY(1508, "23000");
    1748           0 :                         SQLS_ENTRY(565, "24000");     /* Invalid cursor state */
    1749           0 :                         SQLS_ENTRY(558, "24000");
    1750           0 :                         SQLS_ENTRY(559, "24000");
    1751           0 :                         SQLS_ENTRY(6235, "24000");
    1752           0 :                         SQLS_ENTRY(583, "24000");
    1753           0 :                         SQLS_ENTRY(6259, "24000");
    1754           0 :                         SQLS_ENTRY(6260, "24000");
    1755           0 :                         SQLS_ENTRY(562, "24000");
    1756           0 :                         SQLS_ENTRY(277, "25000");     /* Invalid transaction state */
    1757           0 :                         SQLS_ENTRY(611,"25000");
    1758           0 :                         SQLS_ENTRY(3906,"25000");
    1759           0 :                         SQLS_ENTRY(3908,"25000");
    1760           0 :                         SQLS_ENTRY(6401,"25000");
    1761           0 :                         SQLS_ENTRY(627, "25000");
    1762           0 :                         SQLS_ENTRY(628, "25000");
    1763           0 :                         SQLS_ENTRY(641, "25000");
    1764           0 :                         SQLS_ENTRY(642, "25000");
    1765           0 :                         SQLS_ENTRY(1276, "25000");
    1766           0 :                         SQLS_ENTRY(3902, "25000");
    1767           0 :                         SQLS_ENTRY(3903, "25000");
    1768           0 :                         SQLS_ENTRY(6104, "37000");    /* Syntax error or access violation */
    1769           0 :                         SQLS_ENTRY(102, "37000");
    1770          24 :                         SQLS_ENTRY(137, "37000");
    1771           0 :                         SQLS_ENTRY(7327, "37000");
    1772           0 :                         SQLS_ENTRY(201, "37000");
    1773           0 :                         SQLS_ENTRY(257, "37000");
    1774           2 :                         SQLS_ENTRY(2812, "37000");
    1775           0 :                         SQLS_ENTRY(2526, "37000");
    1776           0 :                         SQLS_ENTRY(11021, "37000");
    1777           0 :                         SQLS_ENTRY(229, "42000");     /* Syntax/Access violation */
    1778           0 :                         SQLS_ENTRY(230, "42000");
    1779           0 :                         SQLS_ENTRY(262, "42000");
    1780           0 :                         SQLS_ENTRY(4602, "42000");
    1781           0 :                         SQLS_ENTRY(4603, "42000");
    1782           0 :                         SQLS_ENTRY(4608, "42000");
    1783           0 :                         SQLS_ENTRY(10306, "42000");
    1784           0 :                         SQLS_ENTRY(10323, "42000");
    1785           0 :                         SQLS_ENTRY(10330, "42000");
    1786           0 :                         SQLS_ENTRY(10331, "42000");
    1787           0 :                         SQLS_ENTRY(10332, "42000");
    1788           0 :                         SQLS_ENTRY(11110, "42000");
    1789           0 :                         SQLS_ENTRY(11113, "42000");
    1790           0 :                         SQLS_ENTRY(11118, "42000");
    1791           0 :                         SQLS_ENTRY(11121, "42000");
    1792           0 :                         SQLS_ENTRY(17222, "42000");
    1793           0 :                         SQLS_ENTRY(17223, "42000");
    1794           0 :                         SQLS_ENTRY(18350, "42000");
    1795           0 :                         SQLS_ENTRY(18351, "42000");
    1796           0 :                         SQLS_ENTRY(113, "42000");
    1797           0 :                         SQLS_ENTRY(2714, "42S01");    /* Table or view already exists */
    1798           0 :                         SQLS_ENTRY(208, "42S02");     /* Table or view not found */
    1799          44 :                         SQLS_ENTRY(3701, "42S02");
    1800           0 :                         SQLS_ENTRY(1913, "42S11");    /* Index already exists */
    1801           0 :                         SQLS_ENTRY(307, "42S12");     /* Index not found */
    1802           0 :                         SQLS_ENTRY(7010, "42S12");
    1803           0 :                         SQLS_ENTRY(18091, "42S12");
    1804           0 :                         SQLS_ENTRY(1921, "42S21");    /* Column already exists */
    1805           0 :                         SQLS_ENTRY(1720, "42S22");    /* Column not found */
    1806           6 :                         SQLS_ENTRY(207, "42S22");
    1807           0 :                         SQLS_ENTRY(4934, "42S22");
    1808           0 :                         SQLS_ENTRY(18117, "42S22");
    1809             :                 }
    1810             :         }
    1811             : 
    1812       11750 :         if (p != NULL && (q = strdup(p)) != NULL) {
    1813             :                 /* FIXME correct here ?? */
    1814             :                 /* Convert known ODBC 3.x states listed above to 2.x */
    1815        1269 :                 if (memcmp(q, "42S", 3) == 0)
    1816         248 :                         memcpy(q, "S00", 3);
    1817             : 
    1818             :                 return q;
    1819             :         }
    1820             :         return NULL;
    1821             : }
    1822             : 
    1823             : BCPCOLDATA *
    1824        2410 : tds_alloc_bcp_column_data(unsigned int column_size)
    1825             : {
    1826             :         BCPCOLDATA *coldata;
    1827             : 
    1828        2410 :         TEST_MALLOC(coldata, BCPCOLDATA);
    1829             : 
    1830        2410 :         if (column_size > 4 * 1024)
    1831          72 :                 column_size = 4 * 1024;
    1832        2410 :         TEST_CALLOC(coldata->data, unsigned char, column_size);
    1833             : 
    1834             :         return coldata;
    1835           0 : Cleanup:
    1836           0 :         tds_free_bcp_column_data(coldata);
    1837           0 :         return NULL;
    1838             : }
    1839             : 
    1840             : void
    1841       81284 : tds_free_bcp_column_data(BCPCOLDATA * coldata)
    1842             : {
    1843       81284 :         if (!coldata)
    1844             :                 return;
    1845             : 
    1846        2410 :         free(coldata->data);
    1847        2410 :         free(coldata);
    1848             : }
    1849             : 
    1850             : TDSBCPINFO *
    1851         272 : tds_alloc_bcpinfo(void)
    1852             : {
    1853             :         TDSBCPINFO *bcpinfo;
    1854             : 
    1855         272 :         TEST_MALLOC(bcpinfo, TDSBCPINFO);
    1856             : 
    1857         544 :         tds_dstr_init(&bcpinfo->hint);
    1858         544 :         tds_dstr_init(&bcpinfo->tablename);
    1859             : 
    1860         272 :         return bcpinfo;
    1861         272 : Cleanup:
    1862             :         return NULL;
    1863             : }
    1864             : 
    1865             : void
    1866         456 : tds_deinit_bcpinfo(TDSBCPINFO *bcpinfo)
    1867             : {
    1868         456 :         tds_dstr_free(&bcpinfo->hint);
    1869         456 :         tds_dstr_free(&bcpinfo->tablename);
    1870         456 :         TDS_ZERO_FREE(bcpinfo->insert_stmt);
    1871         456 :         tds_free_results(bcpinfo->bindinfo);
    1872         456 :         bcpinfo->bindinfo = NULL;
    1873         456 :         TDS_ZERO_FREE(bcpinfo->sybase_colinfo);
    1874         456 :         bcpinfo->sybase_count = 0;
    1875         456 : }
    1876             : 
    1877             : void
    1878        2062 : tds_free_bcpinfo(TDSBCPINFO *bcpinfo)
    1879             : {
    1880        2062 :         if (bcpinfo) {
    1881         272 :                 tds_deinit_bcpinfo(bcpinfo);
    1882         272 :                 free(bcpinfo);
    1883             :         }
    1884        2062 : }
    1885             : 
    1886             : /**
    1887             :  * Reallocate a pointer and update it if success
    1888             :  * \param pp pointer to pointer to be reallocated
    1889             :  * \param new_size new size to be allocated
    1890             :  * \return new pointer allocated, NULL on failure
    1891             :  */
    1892             : void *
    1893      108662 : tds_realloc(void **pp, size_t new_size)
    1894             : {
    1895             :         void *p;
    1896             : 
    1897             :         /* some implementation of malloc/realloc does not like size==0 */
    1898      108662 :         if (!new_size)
    1899           0 :                 new_size = 1;
    1900             : 
    1901             :         /* use malloc if not allocated before, some implementation require it */
    1902      108662 :         if (*pp)
    1903       43154 :                 p = realloc(*pp, new_size);
    1904             :         else
    1905       65508 :                 p = malloc(new_size);
    1906             : 
    1907             :         /* update pointer only on success */
    1908      108662 :         if (p)
    1909      108662 :                 *pp = p;
    1910             : 
    1911      108662 :         return p;
    1912             : }
    1913             : 
    1914             : void
    1915           8 : tds_deinit_tvp(TDS_TVP *table)
    1916             : {
    1917             :         TDS_TVP_ROW *tvp_row, *next_row;
    1918             : 
    1919           8 :         free(table->schema);
    1920           8 :         table->schema = NULL;
    1921           8 :         free(table->name);
    1922           8 :         table->name = NULL;
    1923          16 :         tds_free_param_results(table->metadata);
    1924           8 :         table->metadata = NULL;
    1925          26 :         for (tvp_row = table->row; tvp_row != NULL; tvp_row = next_row) {
    1926          18 :                 next_row = tvp_row->next;
    1927          18 :                 tds_free_tvp_row(tvp_row);
    1928          18 :                 free(tvp_row);
    1929             :         }
    1930           8 :         table->row = NULL;
    1931           8 : }
    1932             : 
    1933             : /** @} */

Generated by: LCOV version 1.13