LCOV - code coverage report
Current view: top level - src/tds - mem.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 666 985 67.6 %
Date: 2026-01-01 15:30:10 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      657816 : 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      657816 :         inc_num = (inc_num + 1) & 0xffff;
     104             :         /* some version of Sybase require length <= 10, so we code id */
     105      657816 :         n = (unsigned long) (TDS_INTPTR) conn;
     106      657816 :         p = id;
     107      657816 :         *p++ = (char) ('a' + (n % 26u));
     108      657816 :         n /= 26u;
     109     6578160 :         for (i = 0; i < 9; ++i) {
     110     5920344 :                 c = (char) ('0' + (n % 36u));
     111     5920344 :                 *p++ = (c < ('0' + 10)) ? c : c + ('a' - '0' - 10);
     112             :                 /* tdsdump_log(TDS_DBG_INFO1, "%d -> %d(%c)\n", (int) (n%36u),p[-1],p[-1]); */
     113     5920344 :                 n /= 36u;
     114     5920344 :                 if (i == 4)
     115      657816 :                         n += 3u * inc_num;
     116             :         }
     117      657816 :         *p = 0;
     118      657816 :         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      104943 : tds_alloc_column(void)
     127             : {
     128             :         TDSCOLUMN *col;
     129             : 
     130      104943 :         TEST_MALLOC(col, TDSCOLUMN);
     131      209886 :         tds_dstr_init(&col->table_name);
     132      209886 :         tds_dstr_init(&col->column_name);
     133      209886 :         tds_dstr_init(&col->table_column_name);
     134      104943 :         col->funcs = &tds_invalid_funcs;
     135      104943 :         col->use_iconv_out = 1;
     136             : 
     137      104943 :       Cleanup:
     138      104943 :         return col;
     139             : }
     140             : 
     141             : static void
     142      104869 : tds_free_column(TDSCOLUMN *col)
     143             : {
     144      104869 :         tds_dstr_free(&col->table_name);
     145      104869 :         tds_dstr_free(&col->column_name);
     146      104869 :         tds_dstr_free(&col->table_column_name);
     147      104869 :         free(col);
     148      104869 : }
     149             : 
     150             : 
     151             : /**
     152             :  * \fn TDSDYNAMIC *tds_alloc_dynamic(TDSCONNECTION *conn, const char *id)
     153             :  * \brief Allocate a dynamic statement.
     154             :  * \param conn the connection within which to allocate the statement.
     155             :  * \param id a character label identifying the statement.
     156             :  * \return a pointer to the allocated structure (NULL on failure).
     157             :  *
     158             :  * tds_alloc_dynamic is used to implement placeholder code under TDS 5.0
     159             :  */
     160             : TDSDYNAMIC *
     161      657826 : tds_alloc_dynamic(TDSCONNECTION * conn, const char *id)
     162             : {
     163             :         TDSDYNAMIC *dyn;
     164             :         char tmp_id[30];
     165             : 
     166      657826 :         if (id) {
     167             :                 /* check to see if id already exists (shouldn't) */
     168          20 :                 if (tds_lookup_dynamic(conn, id))
     169             :                         return NULL;
     170             :         } else {
     171             :                 unsigned int n;
     172             :                 id = tmp_id;
     173             : 
     174             :                 for (n = 0;;) {
     175      657816 :                         if (!tds_lookup_dynamic(conn, tds_get_dynid(conn, tmp_id)))
     176             :                                 break;
     177          10 :                         if (++n == 256)
     178             :                                 return NULL;
     179             :                 }
     180             :         }
     181             : 
     182      657826 :         TEST_MALLOC(dyn, TDSDYNAMIC);
     183             : 
     184             :         /* take into account pointer in list */
     185      657826 :         dyn->ref_count = 2;
     186             : 
     187             :         /* insert into list */
     188      657826 :         dyn->next = conn->dyns;
     189      657826 :         conn->dyns = dyn;
     190             : 
     191      657826 :         strlcpy(dyn->id, id, TDS_MAX_DYNID_LEN);
     192             : 
     193      657826 :         return dyn;
     194             : 
     195      657826 :       Cleanup:
     196             :         return NULL;
     197             : }
     198             : 
     199             : /**
     200             :  * \fn void tds_free_input_params(TDSDYNAMIC *dyn)
     201             :  * \brief Frees all allocated input parameters of a dynamic statement.
     202             :  * \param dyn the dynamic statement whose input parameter are to be freed
     203             :  *
     204             :  * tds_free_input_params frees all parameters for the give dynamic statement
     205             :  */
     206             : void
     207        1502 : tds_free_input_params(TDSDYNAMIC * dyn)
     208             : {
     209             :         TDSPARAMINFO *info;
     210             : 
     211      659328 :         info = dyn->params;
     212      659328 :         if (info) {
     213        1482 :                 tds_free_param_results(info);
     214        1084 :                 dyn->params = NULL;
     215             :         }
     216        1502 : }
     217             : 
     218             : /*
     219             :  * Called when dynamic got deallocated from server
     220             :  */
     221             : void
     222      658026 : tds_dynamic_deallocated(TDSCONNECTION *conn, TDSDYNAMIC *dyn)
     223             : {
     224             :         TDSDYNAMIC **victim;
     225             : 
     226      658026 :         tdsdump_log(TDS_DBG_FUNC, "tds_dynamic_deallocated() : freeing dynamic_id %s\n", dyn->id);
     227             : 
     228      658026 :         victim = &conn->dyns;
     229     1316252 :         while (*victim != dyn) {
     230         400 :                 if (*victim == NULL) {
     231         200 :                         tdsdump_log(TDS_DBG_FUNC, "tds_dynamic_deallocated() : cannot find id %s\n", dyn->id);
     232             :                         return;
     233             :                 }
     234         200 :                 victim = &(*victim)->next;
     235             :         }
     236             : 
     237             :         /* remove from list */
     238      657826 :         *victim = dyn->next;
     239      657826 :         dyn->next = NULL;
     240             : 
     241             :         /* assure there is no id left */
     242      657826 :         dyn->num_id = 0;
     243             : 
     244      657826 :         tds_release_dynamic(&dyn);
     245             : }
     246             : 
     247             : 
     248             : /**
     249             :  * \fn void tds_release_dynamic(TDSDYNAMIC **pdyn)
     250             :  * \brief Frees dynamic statement
     251             :  * \param pdyn pointer to dynamic statement to be freed.
     252             :  */
     253             : void
     254     1411745 : tds_release_dynamic(TDSDYNAMIC ** pdyn)
     255             : {
     256             :         TDSDYNAMIC *dyn;
     257             : 
     258     1411745 :         dyn = *pdyn;
     259     1411745 :         *pdyn = NULL;
     260     1411745 :         if (!dyn || --dyn->ref_count > 0)
     261             :                 return;
     262             : 
     263     1315652 :         tds_detach_results(dyn->res_info);
     264             : 
     265      657826 :         tds_free_results(dyn->res_info);
     266      657826 :         tds_free_input_params(dyn);
     267      657826 :         free(dyn->query);
     268      657826 :         free(dyn);
     269             : }
     270             : 
     271             : /**
     272             :  * \fn TDSPARAMINFO *tds_alloc_param_result(TDSPARAMINFO *old_param)
     273             :  * \brief Adds a output parameter to TDSPARAMINFO.
     274             :  * \param old_param a pointer to the TDSPARAMINFO structure containing the 
     275             :  * current set of output parameter, or NULL if none exists.
     276             :  * \return a pointer to the new TDSPARAMINFO structure.
     277             :  *
     278             :  * tds_alloc_param_result() works a bit differently than the other alloc result
     279             :  * functions.  Output parameters come in individually with no total number 
     280             :  * given in advance, so we simply call this func every time with get a
     281             :  * TDS_PARAM_TOKEN and let it realloc the columns struct one bigger. 
     282             :  * tds_free_all_results() usually cleans up after us.
     283             :  */
     284             : TDSPARAMINFO *
     285       42234 : tds_alloc_param_result(TDSPARAMINFO * old_param)
     286             : {
     287             :         TDSPARAMINFO *param_info;
     288             :         TDSCOLUMN *colinfo;
     289             : 
     290             :         /* parameters cannot have row associated */
     291       42234 :         if (old_param && (old_param->current_row || old_param->row_free))
     292             :                 return NULL;
     293             : 
     294       42234 :         colinfo = tds_alloc_column();
     295       42234 :         if (!colinfo)
     296             :                 return NULL;
     297             : 
     298       42234 :         param_info = old_param;
     299       42234 :         if (!param_info) {
     300       29986 :                 TEST_MALLOC(param_info, TDSPARAMINFO);
     301       29986 :                 param_info->ref_count = 1;
     302             :         }
     303             : 
     304       42234 :         if (!TDS_RESIZE(param_info->columns, param_info->num_cols + 1u))
     305             :                 goto Cleanup;
     306             : 
     307       42234 :         param_info->columns[param_info->num_cols++] = colinfo;
     308       42234 :         return param_info;
     309             : 
     310           0 :       Cleanup:
     311           0 :         if (!old_param)
     312           0 :                 free(param_info);
     313           0 :         free(colinfo);
     314           0 :         return NULL;
     315             : }
     316             : 
     317             : /**
     318             :  * Delete latest parameter
     319             :  */
     320             : void
     321          14 : tds_free_param_result(TDSPARAMINFO * param_info)
     322             : {
     323             :         TDSCOLUMN *col;
     324             : 
     325          14 :         if (!param_info || param_info->num_cols <= 0)
     326             :                 return;
     327             : 
     328          14 :         col = param_info->columns[--param_info->num_cols];
     329          14 :         if (col->column_data && col->column_data_free)
     330          14 :                 col->column_data_free(col);
     331             : 
     332          14 :         if (param_info->num_cols == 0)
     333          14 :                 TDS_ZERO_FREE(param_info->columns);
     334             : 
     335             :         /*
     336             :          * NOTE some information should be freed too but when this function
     337             :          * is called are not used. I hope to remove the need for this
     338             :          * function ASAP
     339             :          * A better way is to support different way to allocate and get
     340             :          * parameters
     341             :          * -- freddy77
     342             :          */
     343          14 :         tds_free_column(col);
     344             : }
     345             : 
     346             : static void
     347             : tds_free_tvp_row(TDS_TVP_ROW *row)
     348             : {
     349          72 :         tds_free_param_results(row->params);
     350             : }
     351             : 
     352             : static void
     353       26140 : tds_param_free(TDSCOLUMN *col)
     354             : {
     355       26140 :         if (!col->column_data)
     356             :                 return;
     357             : 
     358       26140 :         if (col->column_type == SYBMSTABLE) {
     359           8 :                 tds_deinit_tvp((TDS_TVP *) col->column_data);
     360       26132 :         } else if (is_blob_col(col)) {
     361        2166 :                 TDSBLOB *blob = (TDSBLOB *) col->column_data;
     362        2166 :                 free(blob->textvalue);
     363             :         }
     364             : 
     365       26140 :         TDS_ZERO_FREE(col->column_data);
     366             : }
     367             : 
     368             : /**
     369             :  * Allocate data for a parameter.
     370             :  * @param curparam parameter to retrieve size information
     371             :  * @return NULL on failure or new data
     372             :  */
     373             : void *
     374       26140 : tds_alloc_param_data(TDSCOLUMN * curparam)
     375             : {
     376             :         TDS_INT data_size;
     377             :         void *data;
     378             : 
     379       26140 :         CHECK_COLUMN_EXTRA(curparam);
     380             : 
     381       26140 :         data_size = curparam->funcs->row_len(curparam);
     382             : 
     383             :         /* allocate data */
     384       26140 :         if (curparam->column_data && curparam->column_data_free)
     385           0 :                 curparam->column_data_free(curparam);
     386       26140 :         curparam->column_data_free = tds_param_free;
     387             : 
     388       26140 :         data = malloc(data_size);
     389       26140 :         curparam->column_data = (unsigned char*) data;
     390       26140 :         if (!data)
     391             :                 return NULL;
     392             :         /* if is a blob reset buffer */
     393       26140 :         if (is_blob_col(curparam) || curparam->column_type == SYBMSTABLE)
     394        2174 :                 memset(data, 0, data_size);
     395             : 
     396             :         return data;
     397             : }
     398             : 
     399             : /**
     400             :  * Allocate memory for storing compute info
     401             :  * return NULL on out of memory
     402             :  */
     403             : 
     404             : static TDSCOMPUTEINFO *
     405          72 : tds_alloc_compute_result(TDS_USMALLINT num_cols, TDS_USMALLINT by_cols)
     406             : {
     407             :         TDS_USMALLINT col;
     408             :         TDSCOMPUTEINFO *info;
     409             : 
     410          72 :         TEST_MALLOC(info, TDSCOMPUTEINFO);
     411          72 :         info->ref_count = 1;
     412             : 
     413          72 :         TEST_CALLOC(info->columns, TDSCOLUMN *, num_cols);
     414             : 
     415          72 :         info->num_cols = num_cols;
     416         144 :         for (col = 0; col < num_cols; col++)
     417          72 :                 if (!(info->columns[col] = tds_alloc_column()))
     418             :                         goto Cleanup;
     419             : 
     420          72 :         if (by_cols) {
     421          24 :                 TEST_CALLOC(info->bycolumns, TDS_SMALLINT, by_cols);
     422          24 :                 info->by_cols = by_cols;
     423             :         }
     424             : 
     425             :         return info;
     426           0 :       Cleanup:
     427           0 :         tds_free_compute_result(info);
     428           0 :         return NULL;
     429             : }
     430             : 
     431             : TDSCOMPUTEINFO **
     432          72 : tds_alloc_compute_results(TDSSOCKET * tds, TDS_USMALLINT num_cols, TDS_USMALLINT by_cols)
     433             : {
     434             :         TDS_UINT n;
     435             :         TDSCOMPUTEINFO **comp_info;
     436             :         TDSCOMPUTEINFO *cur_comp_info;
     437             : 
     438          72 :         tdsdump_log(TDS_DBG_FUNC, "alloc_compute_result. num_cols = %d bycols = %d\n", num_cols, by_cols);
     439          72 :         tdsdump_log(TDS_DBG_FUNC, "alloc_compute_result. num_comp_info = %d\n", tds->num_comp_info);
     440             : 
     441          72 :         cur_comp_info = tds_alloc_compute_result(num_cols, by_cols);
     442          72 :         if (!cur_comp_info)
     443             :                 return NULL;
     444             : 
     445          72 :         n = tds->num_comp_info;
     446          72 :         comp_info = (TDSCOMPUTEINFO **) TDS_RESIZE(tds->comp_info, n + 1u);
     447          72 :         if (!comp_info) {
     448           0 :                 tds_free_compute_result(cur_comp_info);
     449           0 :                 return NULL;
     450             :         }
     451             : 
     452          72 :         tds->comp_info = comp_info;
     453          72 :         comp_info[n] = cur_comp_info;
     454          72 :         tds->num_comp_info = n + 1u;
     455             : 
     456          72 :         tdsdump_log(TDS_DBG_FUNC, "alloc_compute_result. num_comp_info = %d\n", tds->num_comp_info);
     457             : 
     458             :         return comp_info;
     459             : }
     460             : 
     461             : TDSRESULTINFO *
     462       35137 : tds_alloc_results(TDS_USMALLINT num_cols)
     463             : {
     464             :         TDSRESULTINFO *res_info;
     465             :         TDS_USMALLINT col;
     466             : 
     467       35137 :         TEST_MALLOC(res_info, TDSRESULTINFO);
     468       35137 :         res_info->ref_count = 1;
     469       35137 :         if (num_cols)
     470       34949 :                 TEST_CALLOC(res_info->columns, TDSCOLUMN *, num_cols);
     471       62637 :         for (col = 0; col < num_cols; col++)
     472       62637 :                 if (!(res_info->columns[col] = tds_alloc_column()))
     473             :                         goto Cleanup;
     474       35137 :         res_info->num_cols = num_cols;
     475       35137 :         res_info->row_size = 0;
     476       35137 :         return res_info;
     477           0 :       Cleanup:
     478           0 :         tds_free_results(res_info);
     479           0 :         return NULL;
     480             : }
     481             : 
     482             : void
     483      467585 : tds_set_current_results(TDSSOCKET *tds, TDSRESULTINFO *info)
     484             : {
     485      467585 :         tds_detach_results(info);
     486      467585 :         if (tds->current_results)
     487         530 :                 tds->current_results->attached_to = NULL;
     488      467585 :         if (info)
     489      467577 :                 info->attached_to = tds;
     490      467585 :         tds->in_row = (info != NULL);
     491      467585 :         tds->current_results = info;
     492      467585 : }
     493             : 
     494             : /**
     495             :  * Detach result info from it current socket
     496             :  */
     497             : void
     498           0 : tds_detach_results(TDSRESULTINFO *info)
     499             : {
     500     1480305 :         if (info && info->attached_to) {
     501      467041 :                 info->attached_to->current_results = NULL;
     502      467041 :                 info->attached_to->in_row = false;
     503      467041 :                 info->attached_to = NULL;
     504             :         }
     505           0 : }
     506             : 
     507             : static void
     508       34597 : tds_row_free(TDSRESULTINFO *res_info, unsigned char *row)
     509             : {
     510             :         int i;
     511             :         const TDSCOLUMN *col;
     512             : 
     513       34597 :         if (!res_info || !row)
     514             :                 return;
     515             : 
     516       62249 :         for (i = 0; i < res_info->num_cols; ++i) {
     517       62249 :                 col = res_info->columns[i];
     518             :                 
     519       62249 :                 if (is_blob_col(col)) {
     520        3614 :                         TDSBLOB *blob = (TDSBLOB *) &row[col->column_data - res_info->current_row];
     521        3614 :                         if (blob->textvalue)
     522        2872 :                                 TDS_ZERO_FREE(blob->textvalue);
     523             :                 }
     524             :         }
     525             : 
     526       34597 :         free(row);
     527             : }
     528             : 
     529             : /**
     530             :  * Allocate space for row store
     531             :  * return NULL on out of memory
     532             :  */
     533             : TDSRET
     534       34627 : tds_alloc_row(TDSRESULTINFO * res_info)
     535             : {
     536       34627 :         int i, num_cols = res_info->num_cols;
     537             :         unsigned char *ptr;
     538             :         TDSCOLUMN *col;
     539             :         TDS_UINT row_size;
     540             : 
     541             :         /* compute row size */
     542       34627 :         row_size = 0;
     543       96950 :         for (i = 0; i < num_cols; ++i) {
     544       62323 :                 col = res_info->columns[i];
     545             : 
     546       62323 :                 col->column_data_free = NULL;
     547             : 
     548       62323 :                 row_size += col->funcs->row_len(col);
     549       62323 :                 row_size += (TDS_ALIGN_SIZE - 1);
     550       62323 :                 row_size -= row_size % TDS_ALIGN_SIZE;
     551             :         }
     552       34627 :         res_info->row_size = row_size;
     553             : 
     554       34627 :         ptr = tds_new0(unsigned char, row_size ? row_size : 1);
     555       34627 :         res_info->current_row = ptr;
     556       34627 :         if (!ptr)
     557             :                 return TDS_FAIL;
     558       34627 :         res_info->row_free = tds_row_free;
     559             : 
     560             :         /* fill column_data */
     561       34627 :         row_size = 0;
     562       96950 :         for (i = 0; i < num_cols; ++i) {
     563       62323 :                 col = res_info->columns[i];
     564             : 
     565       62323 :                 col->column_data = ptr + row_size;
     566             : 
     567       62323 :                 row_size += col->funcs->row_len(col);
     568       62323 :                 row_size += (TDS_ALIGN_SIZE - 1);
     569       62323 :                 row_size -= row_size % TDS_ALIGN_SIZE;
     570             :         }
     571             : 
     572             :         return TDS_SUCCESS;
     573             : }
     574             : 
     575             : TDSRET
     576          72 : tds_alloc_compute_row(TDSCOMPUTEINFO * res_info)
     577             : {
     578          72 :         return tds_alloc_row(res_info);
     579             : }
     580             : 
     581             : void
     582      106265 : tds_free_param_results(TDSPARAMINFO * param_info)
     583             : {
     584      246053 :         tds_free_results(param_info);
     585      106265 : }
     586             : 
     587             : static void
     588             : tds_free_compute_result(TDSCOMPUTEINFO * comp_info)
     589             : {
     590          72 :         tds_free_results(comp_info);
     591             : }
     592             : 
     593             : static void
     594      138254 : tds_free_compute_results(TDSSOCKET * tds)
     595             : {
     596      138254 :         TDSCOMPUTEINFO ** comp_info = tds->comp_info;
     597      138254 :         TDS_UINT i, num_comp = tds->num_comp_info;
     598             : 
     599      138254 :         tds->comp_info = NULL;
     600      138254 :         tds->num_comp_info = 0;
     601             : 
     602      138326 :         for (i = 0; i < num_comp; i++) {
     603          72 :                 if (comp_info && comp_info[i]) {
     604         144 :                         tds_detach_results(comp_info[i]);
     605          72 :                         tds_free_compute_result(comp_info[i]);
     606             :                 }
     607             :         }
     608      138254 :         if (num_comp)
     609          48 :                 free(comp_info);
     610      138254 : }
     611             : 
     612             : void
     613      195717 : tds_free_row(TDSRESULTINFO * res_info, unsigned char *row)
     614             : {
     615      195717 :         assert(res_info);
     616      195717 :         if (!row || !res_info->row_free)
     617             :                 return;
     618             : 
     619        2720 :         res_info->row_free(res_info, row);
     620             : }
     621             : 
     622             : void
     623     1360298 : tds_free_results(TDSRESULTINFO * res_info)
     624             : {
     625             :         int i;
     626             :         TDSCOLUMN *curcol;
     627             : 
     628     1360298 :         if (!res_info)
     629             :                 return;
     630             : 
     631      272848 :         if (--res_info->ref_count != 0)
     632             :                 return;
     633             : 
     634       65165 :         tds_detach_results(res_info);
     635             : 
     636       65165 :         if (res_info->num_cols && res_info->columns) {
     637      104855 :                 for (i = 0; i < res_info->num_cols; i++)
     638      104855 :                         if ((curcol = res_info->columns[i]) != NULL) {
     639      104855 :                                 if (curcol->bcp_terminator)
     640          54 :                                         TDS_ZERO_FREE(curcol->bcp_terminator);
     641      104855 :                                 tds_free_bcp_column_data(curcol->bcp_column_data);
     642      104855 :                                 curcol->bcp_column_data = NULL;
     643      104855 :                                 if (curcol->column_data && curcol->column_data_free)
     644       26688 :                                         curcol->column_data_free(curcol);
     645             :                         }
     646             :         }
     647             : 
     648       65165 :         if (res_info->current_row && res_info->row_free)
     649       31955 :                 res_info->row_free(res_info, res_info->current_row);
     650             : 
     651       65165 :         if (res_info->num_cols && res_info->columns) {
     652      104855 :                 for (i = 0; i < res_info->num_cols; i++)
     653      104855 :                         if ((curcol = res_info->columns[i]) != NULL)
     654      104855 :                                 tds_free_column(curcol);
     655       65151 :                 free(res_info->columns);
     656             :         }
     657             : 
     658       65165 :         free(res_info->bycolumns);
     659             : 
     660       65165 :         free(res_info);
     661             : }
     662             : 
     663             : void
     664      138254 : tds_free_all_results(TDSSOCKET * tds)
     665             : {
     666      138254 :         tdsdump_log(TDS_DBG_FUNC, "tds_free_all_results()\n");
     667      276508 :         tds_detach_results(tds->res_info);
     668      138254 :         tds_free_results(tds->res_info);
     669      138254 :         tds->res_info = NULL;
     670      276508 :         tds_detach_results(tds->param_info);
     671      276508 :         tds_free_param_results(tds->param_info);
     672      138254 :         tds->param_info = NULL;
     673      138254 :         tds_free_compute_results(tds);
     674      138254 :         tds->has_status = false;
     675      138254 :         tds->in_row = false;
     676      138254 :         tds->ret_status = 0;
     677      138254 :         if (tds->cur_dyn)
     678        6168 :                 tds_detach_results(tds->cur_dyn->res_info);
     679      138254 : }
     680             : 
     681             : /*
     682             :  * Return true if winsock is initialized, else false.
     683             :  */
     684             : static bool
     685             : winsock_initialized(void)
     686             : {
     687             : #ifdef _WIN32
     688             :         static bool initialized = false;
     689             :         static tds_mutex mtx = TDS_MUTEX_INITIALIZER;
     690             : 
     691             :         int erc;
     692             : 
     693             :         if (initialized)
     694             :                 return true;
     695             : 
     696             :         tds_mutex_lock(&mtx);
     697             :         /* same check inside the mutex */
     698             :         if (initialized) {
     699             :                 tds_mutex_unlock(&mtx);
     700             :                 return true;
     701             :         }
     702             : 
     703             :         /* initialize the socket layer */
     704             :         erc = tds_socket_init();
     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 false;
     713             :         }
     714             : #endif
     715             :         return true;
     716             : }
     717             : 
     718             : TDSCONTEXT *
     719        3651 : tds_alloc_context(void * parent)
     720             : {
     721             :         TDSCONTEXT *context;
     722             :         TDSLOCALE *locale;
     723             : 
     724             :         if (!winsock_initialized())
     725             :                 return NULL;
     726             : 
     727        3651 :         if ((locale = tds_get_locale()) == NULL)
     728             :                 return NULL;
     729             : 
     730        3651 :         if ((context = tds_new0(TDSCONTEXT, 1)) == NULL) {
     731           0 :                 tds_free_locale(locale);
     732           0 :                 return NULL;
     733             :         }
     734        3651 :         context->locale = locale;
     735        3651 :         context->parent = parent;
     736        3651 :         context->money_use_2_digits = false;
     737             : 
     738        3651 :         return context;
     739             : }
     740             : 
     741             : void
     742        3621 : tds_free_context(TDSCONTEXT * context)
     743             : {
     744        3621 :         if (!context)
     745             :                 return;
     746             : 
     747        3621 :         tds_free_locale(context->locale);
     748        3621 :         free(context);
     749             : }
     750             : 
     751             : TDSLOCALE *
     752        3731 : tds_alloc_locale(void)
     753             : {
     754             :         TDSLOCALE *locale;
     755             : 
     756        3731 :         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,DOL_BULK) 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        3826 : 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        3826 :         login->option_flag2 = TDS_INIT_LANG_REQUIRED|TDS_ODBC_ON;
     827        3826 :         login->tds_version = TDS_DEFAULT_VERSION;
     828        3826 :         login->block_size = 0;
     829             : 
     830             : #if HAVE_NL_LANGINFO && defined(CODESET)
     831        3826 :         charset = nl_langinfo(CODESET);
     832        3826 :         if (strcmp(tds_canonical_charset_name(charset), "US-ASCII") == 0)
     833        3814 :                 charset = "ISO-8859-1";
     834        3826 :         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             :                                 free(lc_all);
     855             :                                 return NULL;
     856             :                         }
     857             :                 }
     858             :         }
     859             :         free(lc_all);
     860             : #endif
     861             : #endif
     862             : 
     863        3826 :         if (locale) {
     864        3826 :                 if (locale->language)
     865           0 :                         if (!tds_dstr_copy(&login->language, locale->language))
     866             :                                 return NULL;
     867        3826 :                 if (locale->server_charset)
     868           0 :                         if (!tds_dstr_copy(&login->server_charset, locale->server_charset))
     869             :                                 return NULL;
     870             :         }
     871        7652 :         if (tds_dstr_isempty(&login->language)) {
     872        3756 :                 if (!tds_dstr_copy(&login->language, TDS_DEF_LANG))
     873             :                         return NULL;
     874             :         }
     875        3826 :         memset(hostname, '\0', sizeof(hostname));
     876        3826 :         gethostname(hostname, sizeof(hostname));
     877        3826 :         hostname[sizeof(hostname) - 1] = '\0';  /* make sure it's terminated */
     878        3826 :         if (!tds_dstr_copy(&login->client_host_name, hostname))
     879             :                 return NULL;
     880             : 
     881        3826 :         login->valid_configuration = 1;
     882        3826 :         login->check_ssl_hostname = 1;
     883             : 
     884        3826 :         return login;
     885             : }
     886             : 
     887             : TDSCURSOR *
     888        2364 : tds_alloc_cursor(TDSSOCKET *tds, const char *name, size_t namelen, const char *query, size_t querylen)
     889             : {
     890             :         TDSCURSOR *cursor;
     891             :         TDSCURSOR *pcursor;
     892             : 
     893        2364 :         TEST_MALLOC(cursor, TDSCURSOR);
     894        2364 :         cursor->ref_count = 1;
     895             : 
     896        2364 :         cursor->type = TDS_CUR_TYPE_KEYSET;
     897        2364 :         cursor->concurrency = TDS_CUR_CONCUR_OPTIMISTIC;
     898             : 
     899        2364 :         TEST_CALLOC(cursor->cursor_name, char, namelen + 1);
     900        2364 :         memcpy(cursor->cursor_name, name, namelen);
     901             : 
     902        2364 :         TEST_CALLOC(cursor->query, char, querylen + 1);
     903        2364 :         memcpy(cursor->query, query, querylen);
     904             : 
     905        2364 :         if (tds->conn->cursors == NULL) {
     906        2330 :                 tds->conn->cursors = cursor;
     907             :         } else {
     908           0 :                 for (pcursor = tds->conn->cursors; pcursor->next; pcursor = pcursor->next)
     909           0 :                         continue;
     910          34 :                 pcursor->next = cursor;
     911             :         }
     912             :         /* take into account reference in connection list */
     913        2364 :         ++cursor->ref_count;
     914             : 
     915        2364 :         return cursor;
     916             : 
     917           0 :       Cleanup:
     918           0 :         tds_release_cursor(&cursor);
     919           0 :         return NULL;
     920             : }
     921             : 
     922             : /*
     923             :  * Called when cursor got deallocated from server
     924             :  */
     925             : void
     926        2364 : tds_cursor_deallocated(TDSCONNECTION *conn, TDSCURSOR *cursor)
     927             : {
     928             :         TDSCURSOR **victim;
     929             : 
     930        2364 :         tdsdump_log(TDS_DBG_FUNC, "tds_cursor_deallocated() : freeing cursor_id %d\n", cursor->cursor_id);
     931             : 
     932        2364 :         victim = &conn->cursors;
     933        4744 :         while (*victim != cursor) {
     934          16 :                 if (*victim == NULL) {
     935           0 :                         tdsdump_log(TDS_DBG_FUNC, "tds_cursor_deallocated() : cannot find cursor_id %d\n", cursor->cursor_id);
     936             :                         return;
     937             :                 }
     938          16 :                 victim = &(*victim)->next;
     939             :         }
     940             : 
     941             :         /* remove from list */
     942        2364 :         *victim = cursor->next;
     943        2364 :         cursor->next = NULL;
     944             : 
     945        2364 :         tds_release_cursor(&cursor);
     946             : }
     947             : 
     948             : /*
     949             :  * Decrement reference counter and free if necessary.
     950             :  * Called internally by libTDS and by upper library when you don't need 
     951             :  * cursor reference anymore
     952             :  */
     953             : void
     954       89160 : tds_release_cursor(TDSCURSOR **pcursor)
     955             : {
     956       89160 :         TDSCURSOR *cursor = *pcursor;
     957       89160 :         *pcursor = NULL;
     958       89160 :         if (!cursor || --cursor->ref_count > 0)
     959             :                 return;
     960             : 
     961        2364 :         tdsdump_log(TDS_DBG_FUNC, "tds_release_cursor() : freeing cursor_id %d\n", cursor->cursor_id);
     962             : 
     963        2364 :         tdsdump_log(TDS_DBG_FUNC, "tds_release_cursor() : freeing cursor results\n");
     964        4728 :         tds_detach_results(cursor->res_info);
     965        2364 :         tds_free_results(cursor->res_info);
     966             : 
     967        2364 :         if (cursor->cursor_name) {
     968        2364 :                 tdsdump_log(TDS_DBG_FUNC, "tds_release_cursor() : freeing cursor name\n");
     969        2364 :                 free(cursor->cursor_name);
     970             :         }
     971             : 
     972        2364 :         if (cursor->query) {
     973        2364 :                 tdsdump_log(TDS_DBG_FUNC, "tds_release_cursor() : freeing cursor query\n");
     974        2364 :                 free(cursor->query);
     975             :         }
     976             : 
     977        2364 :         tdsdump_log(TDS_DBG_FUNC, "tds_release_cursor() : cursor_id %d freed\n", cursor->cursor_id);
     978        2364 :         free(cursor);
     979             : }
     980             : 
     981             : TDSLOGIN *
     982        7160 : tds_alloc_login(bool use_environment)
     983             : {
     984        7160 :         TDSLOGIN *login = NULL;
     985        7160 :         const char *server_name = TDS_DEF_SERVER;
     986             : 
     987        7160 :         TEST_MALLOC(login, TDSLOGIN);
     988        7160 :         login->check_ssl_hostname = 1;
     989        7160 :         login->use_utf16 = 1;
     990        7160 :         login->bulk_copy = 1;
     991       14320 :         tds_dstr_init(&login->server_name);
     992       14320 :         tds_dstr_init(&login->language);
     993       14320 :         tds_dstr_init(&login->server_charset);
     994       14320 :         tds_dstr_init(&login->client_host_name);
     995       14320 :         tds_dstr_init(&login->server_host_name);
     996       14320 :         tds_dstr_init(&login->app_name);
     997       14320 :         tds_dstr_init(&login->user_name);
     998       14320 :         tds_dstr_init(&login->password);
     999       14320 :         tds_dstr_init(&login->library);
    1000       14320 :         tds_dstr_init(&login->new_password);
    1001             : 
    1002        7160 :         login->ip_addrs = NULL;
    1003             : 
    1004       14320 :         tds_dstr_init(&login->database);
    1005        7160 :         login->dump_file = NULL;
    1006       14320 :         tds_dstr_init(&login->client_charset);
    1007       14320 :         tds_dstr_init(&login->instance_name);
    1008       14320 :         tds_dstr_init(&login->server_realm_name);
    1009       14320 :         tds_dstr_init(&login->server_spn);
    1010       14320 :         tds_dstr_init(&login->cafile);
    1011       14320 :         tds_dstr_init(&login->crlfile);
    1012       14320 :         tds_dstr_init(&login->certificate_host_name);
    1013       14320 :         tds_dstr_init(&login->db_filename);
    1014       14320 :         tds_dstr_init(&login->openssl_ciphers);
    1015       14320 :         tds_dstr_init(&login->gnutls_ciphers);
    1016       14320 :         tds_dstr_init(&login->routing_address);
    1017             : 
    1018        7160 :         if (use_environment) {
    1019             :                 const char *s;
    1020        3334 :                 if ((s=getenv("DSQUERY")) != NULL)
    1021           0 :                         server_name = s;
    1022             : 
    1023        3334 :                 if ((s=getenv("TDSQUERY")) != NULL)
    1024           0 :                         server_name = s;
    1025             :         }
    1026             : 
    1027        7160 :         if (!tds_dstr_copy(&login->server_name, server_name)) {
    1028           0 :                 free(login);
    1029           0 :                 return NULL;
    1030             :         }
    1031             : 
    1032        7160 :         login->capabilities = defaultcaps;
    1033        7160 :         login->use_ntlmv2_specified = 0;
    1034        7160 :         login->use_ntlmv2 = 1;
    1035             : 
    1036           0 : Cleanup:
    1037             :         return login;
    1038             : }
    1039             : 
    1040             : void
    1041        7852 : tds_free_login(TDSLOGIN * login)
    1042             : {
    1043        7852 :         if (!login)
    1044             :                 return;
    1045             : 
    1046             :         /* for security reason clear memory */
    1047        7128 :         tds_dstr_zero(&login->password);
    1048        7128 :         tds_dstr_free(&login->password);
    1049        7128 :         tds_dstr_zero(&login->new_password);
    1050        7128 :         tds_dstr_free(&login->new_password);
    1051        7128 :         tds_dstr_free(&login->server_name);
    1052        7128 :         tds_dstr_free(&login->language);
    1053        7128 :         tds_dstr_free(&login->server_charset);
    1054        7128 :         tds_dstr_free(&login->client_host_name);
    1055        7128 :         tds_dstr_free(&login->app_name);
    1056        7128 :         tds_dstr_free(&login->user_name);
    1057        7128 :         tds_dstr_free(&login->library);
    1058        7128 :         tds_dstr_free(&login->client_charset);
    1059        7128 :         tds_dstr_free(&login->server_host_name);
    1060             : 
    1061        7128 :         if (login->ip_addrs != NULL)
    1062        3824 :                 freeaddrinfo(login->ip_addrs);
    1063             : 
    1064        7128 :         tds_dstr_free(&login->database);
    1065        7128 :         free(login->dump_file);
    1066        7128 :         tds_dstr_free(&login->instance_name);
    1067        7128 :         tds_dstr_free(&login->server_realm_name);
    1068        7128 :         tds_dstr_free(&login->server_spn);
    1069        7128 :         tds_dstr_free(&login->cafile);
    1070        7128 :         tds_dstr_free(&login->crlfile);
    1071        7128 :         tds_dstr_free(&login->certificate_host_name);
    1072        7128 :         tds_dstr_free(&login->db_filename);
    1073        7128 :         tds_dstr_free(&login->openssl_ciphers);
    1074        7128 :         tds_dstr_free(&login->gnutls_ciphers);
    1075        7128 :         tds_dstr_free(&login->routing_address);
    1076        7128 :         free(login);
    1077             : }
    1078             : 
    1079             : TDSPACKET *
    1080       15480 : tds_alloc_packet(void *buf, unsigned len)
    1081             : {
    1082       15480 :         TDSPACKET *packet = (TDSPACKET *) malloc(len + TDS_OFFSET(TDSPACKET, buf));
    1083       15480 :         if (TDS_LIKELY(packet)) {
    1084       10781 :                 tds_packet_zero_data_start(packet);
    1085       15480 :                 packet->data_len = 0;
    1086       15480 :                 packet->capacity = len;
    1087       15480 :                 packet->sid = 0;
    1088       15480 :                 packet->next = NULL;
    1089       15480 :                 if (buf) {
    1090         235 :                         memcpy(packet->buf, buf, len);
    1091         235 :                         packet->data_len = len;
    1092             :                 }
    1093             :         }
    1094       15480 :         return packet;
    1095             : }
    1096             : 
    1097             : TDSPACKET *
    1098       50495 : tds_realloc_packet(TDSPACKET *packet, unsigned len)
    1099             : {
    1100       58109 :         if (packet->capacity < len) {
    1101        6276 :                 packet = (TDSPACKET *) realloc(packet, len + TDS_OFFSET(TDSPACKET, buf));
    1102        6276 :                 if (TDS_LIKELY(packet))
    1103        6276 :                         packet->capacity = len;
    1104             :         }
    1105       50495 :         return packet;
    1106             : }
    1107             : 
    1108             : void
    1109       52463 : tds_free_packets(TDSPACKET *packet)
    1110             : {
    1111             :         TDSPACKET *next;
    1112       67868 :         for (; packet; packet = next) {
    1113       15405 :                 next = packet->next;
    1114       15405 :                 free(packet);
    1115             :         }
    1116       52463 : }
    1117             : 
    1118             : static void
    1119        4607 : tds_deinit_connection(TDSCONNECTION *conn)
    1120             : {
    1121        4607 :         if (conn->authentication)
    1122           0 :                 conn->authentication->free(conn, conn->authentication);
    1123        4607 :         conn->authentication = NULL;
    1124        9278 :         while (conn->dyns)
    1125          64 :                 tds_dynamic_deallocated(conn, conn->dyns);
    1126        4633 :         while (conn->cursors)
    1127          26 :                 tds_cursor_deallocated(conn, conn->cursors);
    1128        4607 :         tds_ssl_deinit(conn);
    1129             :         /* close connection and free inactive sockets */
    1130        4607 :         tds_connection_close(conn);
    1131        4607 :         tds_wakeup_close(&conn->wakeup);
    1132        4607 :         tds_iconv_free(conn);
    1133        4607 :         free(conn->product_name);
    1134        4607 :         free(conn->server);
    1135        4607 :         tds_free_env(conn);
    1136        9214 :         tds_free_packets(conn->packet_cache);
    1137        4607 :         tds_mutex_free(&conn->list_mtx);
    1138             : #if ENABLE_ODBC_MARS
    1139        4652 :         tds_free_packets(conn->packets);
    1140        4652 :         tds_free_packets(conn->recv_packet);
    1141        4652 :         tds_free_packets(conn->send_packets);
    1142        2326 :         free(conn->sessions);
    1143             : #endif
    1144        4607 : }
    1145             : 
    1146             : static TDSCONNECTION *
    1147        4637 : tds_init_connection(TDSCONNECTION *conn, TDSCONTEXT *context, unsigned int bufsize)
    1148             : {
    1149        4637 :         conn->env.block_size = bufsize;
    1150        4637 :         conn->s = INVALID_SOCKET;
    1151        4637 :         conn->use_iconv_in = 1;
    1152        4637 :         conn->tds_ctx = context;
    1153        4637 :         conn->ncharsize = 1;
    1154        4637 :         conn->unicharsize = 1;
    1155             : 
    1156        4637 :         if (tds_wakeup_init(&conn->wakeup))
    1157             :                 goto Cleanup;
    1158             : 
    1159        4637 :         if (tds_iconv_alloc(conn))
    1160             :                 goto Cleanup;
    1161             : 
    1162        9274 :         if (tds_mutex_init(&conn->list_mtx))
    1163             :                 goto Cleanup;
    1164             : 
    1165             : #if ENABLE_ODBC_MARS
    1166        2341 :         TEST_CALLOC(conn->sessions, TDSSOCKET*, 64);
    1167        2341 :         conn->num_sessions = 64;
    1168             : #endif
    1169        2341 :         return conn;
    1170             : 
    1171           0 : Cleanup:
    1172           0 :         tds_wakeup_close(&conn->wakeup);
    1173           0 :         tds_iconv_free(conn);
    1174           0 :         return NULL;
    1175             : }
    1176             : 
    1177             : static TDSSOCKET *
    1178        4647 : tds_init_socket(TDSSOCKET * tds_socket, unsigned int bufsize)
    1179             : {
    1180             :         TDSPACKET *pkt;
    1181             : 
    1182        4647 :         tds_socket->parent = NULL;
    1183             : 
    1184        4647 :         tds_socket->recv_packet = tds_alloc_packet(NULL, bufsize);
    1185        4647 :         if (!tds_socket->recv_packet)
    1186             :                 goto Cleanup;
    1187        4647 :         tds_socket->in_buf = tds_socket->recv_packet->buf;
    1188             : 
    1189        4647 :         pkt = tds_alloc_packet(NULL, bufsize + TDS_ADDITIONAL_SPACE);
    1190        4647 :         if (!pkt)
    1191             :                 goto Cleanup;
    1192        4647 :         tds_set_current_send_packet(tds_socket, pkt);
    1193             : 
    1194        4647 :         tds_socket->out_buf_max = bufsize;
    1195             : 
    1196             :         /* Jeff's hack, init to no timeout */
    1197        4647 :         tds_socket->query_timeout = 0;
    1198        4647 :         tds_init_write_buf(tds_socket);
    1199        4647 :         tds_socket->state = TDS_DEAD;
    1200        4647 :         tds_socket->env_chg_func = NULL;
    1201        9294 :         if (tds_mutex_init(&tds_socket->wire_mtx))
    1202             :                 goto Cleanup;
    1203             : 
    1204             : #ifdef ENABLE_ODBC_MARS
    1205        2351 :         tds_socket->sid = 0;
    1206        2351 :         if (tds_cond_init(&tds_socket->packet_cond))
    1207             :                 goto Cleanup;
    1208             : 
    1209        2351 :         tds_socket->recv_seq = 0;
    1210        2351 :         tds_socket->send_seq = 0;
    1211        2351 :         tds_socket->recv_wnd = 4;
    1212        2351 :         tds_socket->send_wnd = 4;
    1213             : #endif
    1214        2351 :         return tds_socket;
    1215             : 
    1216           0 :       Cleanup:
    1217             :         return NULL;
    1218             : }
    1219             : 
    1220             : 
    1221             : #if ENABLE_ODBC_MARS
    1222             : static void
    1223        2326 : tds_free_connection(TDSCONNECTION *conn)
    1224             : {
    1225        2326 :         if (!conn) return;
    1226        2326 :         assert(conn->in_net_tds == NULL);
    1227        2326 :         tds_deinit_connection(conn);
    1228        2326 :         free(conn);
    1229             : }
    1230             : 
    1231             : static TDSCONNECTION *
    1232        2341 : tds_alloc_connection(TDSCONTEXT *context, unsigned int bufsize)
    1233             : {
    1234             :         TDSCONNECTION *conn;
    1235             : 
    1236        2341 :         TEST_MALLOC(conn, TDSCONNECTION);
    1237        2341 :         if (!tds_init_connection(conn, context, bufsize))
    1238             :                 goto Cleanup;
    1239             :         return conn;
    1240             : 
    1241           0 : Cleanup:
    1242           0 :         tds_free_connection(conn);
    1243           0 :         return NULL;
    1244             : }
    1245             : 
    1246             : static TDSSOCKET *
    1247        2351 : tds_alloc_socket_base(unsigned int bufsize)
    1248             : {
    1249             :         TDSSOCKET *tds_socket;
    1250             : 
    1251        2351 :         TEST_MALLOC(tds_socket, TDSSOCKET);
    1252        2351 :         if (!tds_init_socket(tds_socket, bufsize))
    1253             :                 goto Cleanup;
    1254             :         return tds_socket;
    1255             : 
    1256           0 :       Cleanup:
    1257           0 :         tds_free_socket(tds_socket);
    1258           0 :         return NULL;
    1259             : }
    1260             : 
    1261             : TDSSOCKET *
    1262        2341 : tds_alloc_socket(TDSCONTEXT * context, unsigned int bufsize)
    1263             : {
    1264        2341 :         TDSCONNECTION *conn = tds_alloc_connection(context, bufsize);
    1265             :         TDSSOCKET *tds;
    1266             : 
    1267        2341 :         if (!conn)
    1268             :                 return NULL;
    1269             : 
    1270        2341 :         tds = tds_alloc_socket_base(bufsize);
    1271        2341 :         if (tds) {
    1272        2341 :                 conn->sessions[0] = tds;
    1273        2341 :                 tds->conn = conn;
    1274        2341 :                 return tds;
    1275             :         }
    1276           0 :         tds_free_connection(conn);
    1277           0 :         return NULL;
    1278             : }
    1279             : 
    1280             : static bool
    1281          10 : tds_alloc_new_sid(TDSSOCKET *tds)
    1282             : {
    1283             :         uint16_t sid;
    1284          10 :         TDSCONNECTION *conn = tds->conn;
    1285             : 
    1286          10 :         tds_mutex_lock(&conn->list_mtx);
    1287          13 :         for (sid = 1; sid < conn->num_sessions; ++sid)
    1288          13 :                 if (!conn->sessions[sid])
    1289             :                         break;
    1290          10 :         if (sid == conn->num_sessions) {
    1291             :                 /* extend array */
    1292           0 :                 TDSSOCKET **s = (TDSSOCKET **) TDS_RESIZE(conn->sessions, sid+64);
    1293           0 :                 if (!s)
    1294             :                         goto error;
    1295           0 :                 memset(s + conn->num_sessions, 0, sizeof(*s) * 64);
    1296           0 :                 conn->num_sessions += 64;
    1297             :         }
    1298          10 :         conn->sessions[sid] = tds;
    1299          10 :         tds->sid = sid;
    1300          10 : error:
    1301          10 :         tds_mutex_unlock(&conn->list_mtx);
    1302          10 :         return tds->sid != 0;
    1303             : }
    1304             : 
    1305             : TDSSOCKET *
    1306          16 : tds_alloc_additional_socket(TDSCONNECTION *conn)
    1307             : {
    1308             :         TDSSOCKET *tds;
    1309          16 :         if (!IS_TDS72_PLUS(conn) || !conn->mars)
    1310             :                 return NULL;
    1311             : 
    1312          10 :         tds = tds_alloc_socket_base(sizeof(TDS72_SMP_HEADER) + conn->env.block_size);
    1313          10 :         if (!tds)
    1314             :                 return NULL;
    1315          10 :         tds->send_packet->data_start = sizeof(TDS72_SMP_HEADER);
    1316          10 :         tds->out_buf = tds->send_packet->buf + sizeof(TDS72_SMP_HEADER);
    1317          10 :         tds->out_buf_max -= sizeof(TDS72_SMP_HEADER);
    1318             : 
    1319          10 :         tds->conn = conn;
    1320          10 :         if (!tds_alloc_new_sid(tds))
    1321             :                 goto Cleanup;
    1322             : 
    1323          10 :         tds->state = TDS_IDLE;
    1324          10 :         if (TDS_FAILED(tds_append_syn(tds)))
    1325             :                 goto Cleanup;
    1326             : 
    1327             :         return tds;
    1328             : 
    1329           0 :       Cleanup:
    1330           0 :         tds_free_socket(tds);
    1331           0 :         return NULL;
    1332             : }
    1333             : #else /* !ENABLE_ODBC_MARS */
    1334             : TDSSOCKET *
    1335        2296 : tds_alloc_socket(TDSCONTEXT * context, unsigned int bufsize)
    1336             : {
    1337             :         TDSSOCKET *tds_socket;
    1338             : 
    1339        2296 :         TEST_MALLOC(tds_socket, TDSSOCKET);
    1340        2296 :         if (!tds_init_connection(tds_socket->conn, context, bufsize))
    1341             :                 goto Cleanup;
    1342        2296 :         if (!tds_init_socket(tds_socket, bufsize))
    1343             :                 goto Cleanup;
    1344             :         return tds_socket;
    1345             : 
    1346           0 :       Cleanup:
    1347           0 :         tds_free_socket(tds_socket);
    1348           0 :         return NULL;
    1349             : }
    1350             : #endif /* !ENABLE_ODBC_MARS */
    1351             : 
    1352             : TDSSOCKET *
    1353        7614 : tds_realloc_socket(TDSSOCKET * tds, unsigned int bufsize)
    1354             : {
    1355             :         TDSPACKET *packet;
    1356             : #if ENABLE_ODBC_MARS
    1357        3937 :         size_t smp_hdr_len = tds->conn->mars ? sizeof(TDS72_SMP_HEADER) : 0;
    1358             : #else
    1359             :         enum { smp_hdr_len = 0 };
    1360             : #endif
    1361             : 
    1362        7614 :         assert(tds && tds->out_buf && tds->send_packet);
    1363             : 
    1364        7614 :         if (bufsize < 512)
    1365           0 :                 bufsize = 512;
    1366             : 
    1367             :         /* prevent nasty memory conditions, server should send the request at
    1368             :          * the beginning only */
    1369        7614 :         if (tds->out_pos > bufsize || tds->frozen)
    1370             :                 return NULL;
    1371             : 
    1372        7614 :         tds->conn->env.block_size = bufsize;
    1373             : 
    1374       15228 :         packet = tds_realloc_packet(tds->send_packet, smp_hdr_len + bufsize + TDS_ADDITIONAL_SPACE);
    1375        7614 :         if (packet == NULL)
    1376             :                 return NULL;
    1377             : 
    1378             : #if ENABLE_ODBC_MARS
    1379        3937 :         packet->data_start = smp_hdr_len;
    1380             : #endif
    1381        7614 :         tds->out_buf_max = bufsize;
    1382        7614 :         tds_set_current_send_packet(tds, packet);
    1383        7614 :         return tds;
    1384             : }
    1385             : 
    1386             : #if ENABLE_ODBC_MARS
    1387             : static void
    1388        2336 : tds_connection_remove_socket(TDSCONNECTION *conn, TDSSOCKET *tds)
    1389             : {
    1390             :         unsigned n;
    1391        2336 :         bool must_free_connection = true;
    1392        2336 :         tds_mutex_lock(&conn->list_mtx);
    1393        2336 :         if (tds->sid < conn->num_sessions)
    1394        2336 :                 conn->sessions[tds->sid] = NULL;
    1395      151200 :         for (n = 0; n < conn->num_sessions; ++n)
    1396      148874 :                 if (TDSSOCKET_VALID(conn->sessions[n])) {
    1397             :                         must_free_connection = false;
    1398             :                         break;
    1399             :                 }
    1400        2336 :         if (!must_free_connection) {
    1401             :                 /* tds use connection member so must be valid */
    1402          10 :                 tds_append_fin(tds);
    1403             :         }
    1404        2336 :         tds_mutex_unlock(&conn->list_mtx);
    1405             : 
    1406             :         /* detach entirely */
    1407        2336 :         tds->conn = NULL;
    1408             : 
    1409        2336 :         if (must_free_connection)
    1410        2326 :                 tds_free_connection(conn);
    1411        2336 : }
    1412             : #else
    1413             : static void inline
    1414             : tds_connection_remove_socket(TDSCONNECTION *conn, TDSSOCKET *tds TDS_UNUSED)
    1415             : {
    1416        2281 :         tds_deinit_connection(conn);
    1417             : }
    1418             : #endif
    1419             : 
    1420             : void
    1421        7195 : tds_free_socket(TDSSOCKET * tds)
    1422             : {
    1423             : #if ENABLE_EXTRA_CHECKS
    1424             :         TDSDYNAMIC *dyn;
    1425             :         TDSCURSOR *cur;
    1426             : #endif
    1427             : 
    1428        7195 :         if (!tds)
    1429             :                 return;
    1430             : 
    1431             :         /* detach this socket */
    1432        4617 :         tds_release_cur_dyn(tds);
    1433        4617 :         tds_release_cursor(&tds->cur_cursor);
    1434        9234 :         tds_detach_results(tds->current_results);
    1435             : #if ENABLE_EXTRA_CHECKS
    1436        4685 :         for (dyn = tds->conn->dyns; dyn; dyn = dyn->next) {
    1437          68 :                 if (dyn->res_info && dyn->res_info->attached_to == tds) {
    1438           0 :                         assert(0);
    1439             :                 }
    1440             :         }
    1441        4643 :         for (cur = tds->conn->cursors; cur; cur = cur->next) {
    1442          26 :                 if (cur->res_info && cur->res_info->attached_to == tds) {
    1443           0 :                         assert(0);
    1444             :                 }
    1445             :         }
    1446             : #endif
    1447        4617 :         tds_free_all_results(tds);
    1448             : #if ENABLE_ODBC_MARS
    1449        4672 :         tds_cond_destroy(&tds->packet_cond);
    1450             : #endif
    1451             : 
    1452        6898 :         tds_connection_remove_socket(tds->conn, tds);
    1453        9234 :         tds_free_packets(tds->recv_packet);
    1454        4617 :         if (tds->frozen_packets)
    1455             :                 tds_free_packets(tds->frozen_packets);
    1456             :         else
    1457        4617 :                 tds_free_packets(tds->send_packet);
    1458        4617 :         free(tds);
    1459             : }
    1460             : 
    1461             : void
    1462        3701 : tds_free_locale(TDSLOCALE * locale)
    1463             : {
    1464        3701 :         if (!locale)
    1465             :                 return;
    1466             : 
    1467        3701 :         free(locale->language);
    1468        3701 :         free(locale->server_charset);
    1469        3701 :         free(locale->datetime_fmt);
    1470        3701 :         free(locale->date_fmt);
    1471        3701 :         free(locale->time_fmt);
    1472        3701 :         free(locale);
    1473             : }
    1474             : 
    1475             : static void
    1476        4607 : tds_free_env(TDSCONNECTION* conn)
    1477             : {
    1478        4607 :         if (conn->env.language)
    1479        2918 :                 TDS_ZERO_FREE(conn->env.language);
    1480        4607 :         if (conn->env.charset)
    1481         546 :                 TDS_ZERO_FREE(conn->env.charset);
    1482        4607 :         if (conn->env.database)
    1483        3632 :                 TDS_ZERO_FREE(conn->env.database);
    1484        4607 : }
    1485             : 
    1486             : void
    1487       15803 : tds_free_msg(TDSMESSAGE * message)
    1488             : {
    1489       15803 :         if (message) {
    1490       15803 :                 message->priv_msg_type = 0;
    1491       15803 :                 message->msgno = 0;
    1492       15803 :                 message->state = 0;
    1493       15803 :                 message->severity = 0;
    1494       15803 :                 message->line_number = 0;
    1495       15803 :                 TDS_ZERO_FREE(message->message);
    1496       15803 :                 TDS_ZERO_FREE(message->server);
    1497       15803 :                 TDS_ZERO_FREE(message->proc_name);
    1498       15803 :                 TDS_ZERO_FREE(message->sql_state);
    1499             :         }
    1500       15803 : }
    1501             : 
    1502             : #define SQLS_ENTRY(number,state) case number: p = state; break
    1503             : 
    1504             : char *
    1505       41316 : tds_alloc_client_sqlstate(int msgno)
    1506             : {
    1507       41316 :         const char *p = NULL;
    1508             : 
    1509       41316 :         switch (msgno) {
    1510             :                 SQLS_ENTRY(17000, "S1T00");   /* timeouts ??? */
    1511           1 :                 SQLS_ENTRY(20004, "08S01");   /* Communication link failure */
    1512          72 :                 SQLS_ENTRY(20006, "08S01");
    1513           0 :                 SQLS_ENTRY(20009, "08S01");
    1514           0 :                 SQLS_ENTRY(20020, "08S01");
    1515           0 :                 SQLS_ENTRY(20019, "24000");   /* Invalid cursor state */
    1516           0 :                 SQLS_ENTRY(20014, "28000");   /* Invalid authorization specification */
    1517       36030 :                 SQLS_ENTRY(2400, "42000");    /* Syntax error or access violation */
    1518         740 :                 SQLS_ENTRY(2401, "42000");
    1519        1930 :                 SQLS_ENTRY(2403, "42000");
    1520           0 :                 SQLS_ENTRY(2404, "42000");
    1521        2211 :                 SQLS_ENTRY(2402, "S1000");    /* General error */
    1522             :         }
    1523             : 
    1524             :         if (p != NULL)
    1525       40984 :                 return strdup(p);
    1526             :         else
    1527             :                 return NULL;
    1528             : }
    1529             : 
    1530             : char *
    1531       15694 : tds_alloc_lookup_sqlstate(TDSSOCKET * tds, int msgno)
    1532             : {
    1533       15694 :         const char *p = NULL;
    1534       15694 :         char *q = NULL;
    1535             : 
    1536       15694 :         if (TDS_IS_MSSQL(tds)) {
    1537        7420 :                 switch (msgno) {        /* MSSQL Server */
    1538             : 
    1539         752 :                         SQLS_ENTRY(3621,"01000");
    1540          26 :                         SQLS_ENTRY(8153,"01003");     /* Null in aggregate */
    1541           8 :                         SQLS_ENTRY(911, "08004");     /* Server rejected connection */
    1542           0 :                         SQLS_ENTRY(512, "21000");     /* Subquery returns more than one value */
    1543           0 :                         SQLS_ENTRY(213, "21S01");     /* Insert column list mismatch */
    1544           0 :                         SQLS_ENTRY(109, "21S01");
    1545           0 :                         SQLS_ENTRY(110, "21S01");
    1546           0 :                         SQLS_ENTRY(1774,"21S02");     /* Ref column mismatch */
    1547           0 :                         SQLS_ENTRY(8152,"22001");     /* String data would be truncated */
    1548           0 :                         SQLS_ENTRY(5146,"22003");     /* Numeric value out of range */
    1549           0 :                         SQLS_ENTRY(168, "22003");     /* Arithmetic overflow */
    1550         656 :                         SQLS_ENTRY(220, "22003");
    1551           0 :                         SQLS_ENTRY(232, "22003");
    1552           0 :                         SQLS_ENTRY(234, "22003");
    1553           0 :                         SQLS_ENTRY(236, "22003");
    1554           0 :                         SQLS_ENTRY(238, "22003");
    1555           0 :                         SQLS_ENTRY(244, "22003");
    1556           0 :                         SQLS_ENTRY(246, "22003");
    1557           0 :                         SQLS_ENTRY(248, "22003");
    1558           0 :                         SQLS_ENTRY(519, "22003");
    1559           0 :                         SQLS_ENTRY(520, "22003");
    1560           0 :                         SQLS_ENTRY(521, "22003");
    1561           0 :                         SQLS_ENTRY(522, "22003");
    1562           0 :                         SQLS_ENTRY(523, "22003");
    1563           0 :                         SQLS_ENTRY(524, "22003");
    1564           0 :                         SQLS_ENTRY(1007,"22003");
    1565           0 :                         SQLS_ENTRY(3606,"22003");
    1566           0 :                         SQLS_ENTRY(8115,"22003");
    1567           0 :                         SQLS_ENTRY(206, "22005");     /* Error in assignment */
    1568           0 :                         SQLS_ENTRY(235, "22005");
    1569           0 :                         SQLS_ENTRY(247, "22005");
    1570           0 :                         SQLS_ENTRY(249, "22005");
    1571           0 :                         SQLS_ENTRY(256, "22005");
    1572           0 :                         SQLS_ENTRY(257, "22005");
    1573           0 :                         SQLS_ENTRY(305, "22005");
    1574           0 :                         SQLS_ENTRY(409, "22005");
    1575           0 :                         SQLS_ENTRY(518, "22005");
    1576           0 :                         SQLS_ENTRY(529, "22005");
    1577           0 :                         SQLS_ENTRY(210, "22007");     /* Invalid datetime format */
    1578           0 :                         SQLS_ENTRY(241, "22007");
    1579           0 :                         SQLS_ENTRY(295, "22007");
    1580          16 :                         SQLS_ENTRY(242, "22008");     /* Datetime out of range */
    1581           0 :                         SQLS_ENTRY(296, "22008");
    1582           0 :                         SQLS_ENTRY(298, "22008");
    1583           0 :                         SQLS_ENTRY(535, "22008");
    1584           0 :                         SQLS_ENTRY(542, "22008");
    1585           8 :                         SQLS_ENTRY(517, "22008");
    1586           0 :                         SQLS_ENTRY(3607, "22012");    /* Div by zero */
    1587         164 :                         SQLS_ENTRY(8134, "22012");
    1588           0 :                         SQLS_ENTRY(245, "22018");     /* Syntax error? */
    1589           8 :                         SQLS_ENTRY(2627, "23000");    /* Constraint violation */
    1590           8 :                         SQLS_ENTRY(515, "23000");
    1591           0 :                         SQLS_ENTRY(233, "23000");
    1592           0 :                         SQLS_ENTRY(273, "23000");
    1593           0 :                         SQLS_ENTRY(530, "23000");
    1594           0 :                         SQLS_ENTRY(2601,"23000");
    1595           0 :                         SQLS_ENTRY(2615,"23000");
    1596           0 :                         SQLS_ENTRY(2626,"23000");
    1597           0 :                         SQLS_ENTRY(3604,"23000");
    1598           0 :                         SQLS_ENTRY(3605,"23000");
    1599           0 :                         SQLS_ENTRY(544, "23000");
    1600           0 :                         SQLS_ENTRY(547, "23000");
    1601           0 :                         SQLS_ENTRY(550, "23000");
    1602           0 :                         SQLS_ENTRY(4415, "23000");
    1603           0 :                         SQLS_ENTRY(1505, "23000");
    1604           0 :                         SQLS_ENTRY(1508, "23000");
    1605           0 :                         SQLS_ENTRY(3725, "23000");
    1606           0 :                         SQLS_ENTRY(3726, "23000");
    1607           0 :                         SQLS_ENTRY(4712, "23000");
    1608           0 :                         SQLS_ENTRY(10055, "23000");
    1609           0 :                         SQLS_ENTRY(10065, "23000");
    1610           0 :                         SQLS_ENTRY(11011, "23000");
    1611           0 :                         SQLS_ENTRY(11040, "23000");
    1612           0 :                         SQLS_ENTRY(16999, "24000");   /* Invalid cursor state */
    1613           0 :                         SQLS_ENTRY(16905, "24000");
    1614           0 :                         SQLS_ENTRY(16917, "24000");
    1615           0 :                         SQLS_ENTRY(16946, "24000");
    1616           0 :                         SQLS_ENTRY(16950, "24000");
    1617           0 :                         SQLS_ENTRY(266, "25000");     /* Invalid transaction state */
    1618           0 :                         SQLS_ENTRY(277,"25000");
    1619           0 :                         SQLS_ENTRY(611,"25000");
    1620           0 :                         SQLS_ENTRY(3906,"25000");
    1621           0 :                         SQLS_ENTRY(3908,"25000");
    1622           0 :                         SQLS_ENTRY(6401,"25000");
    1623           0 :                         SQLS_ENTRY(626, "25000");
    1624           0 :                         SQLS_ENTRY(627, "25000");
    1625           0 :                         SQLS_ENTRY(628, "25000");
    1626           0 :                         SQLS_ENTRY(3902, "25000");
    1627           0 :                         SQLS_ENTRY(3903, "25000");
    1628           0 :                         SQLS_ENTRY(3916, "25000");
    1629           0 :                         SQLS_ENTRY(3918, "25000");
    1630           0 :                         SQLS_ENTRY(3919, "25000");
    1631           0 :                         SQLS_ENTRY(3921, "25000");
    1632           0 :                         SQLS_ENTRY(3922, "25000");
    1633          16 :                         SQLS_ENTRY(3926, "25000");
    1634           0 :                         SQLS_ENTRY(7969, "25000");
    1635           0 :                         SQLS_ENTRY(8506, "25000");
    1636           0 :                         SQLS_ENTRY(15626, "25000");
    1637           0 :                         SQLS_ENTRY(18456, "28000");   /* Login failed? */
    1638           0 :                         SQLS_ENTRY(6104, "37000");    /* Syntax error or access violation */
    1639           0 :                         SQLS_ENTRY(8114, "37000");
    1640           0 :                         SQLS_ENTRY(131, "37000");
    1641           2 :                         SQLS_ENTRY(137, "37000");
    1642          24 :                         SQLS_ENTRY(170, "37000");
    1643           0 :                         SQLS_ENTRY(174, "37000");
    1644           0 :                         SQLS_ENTRY(201, "37000");
    1645           8 :                         SQLS_ENTRY(2812, "37000");
    1646           0 :                         SQLS_ENTRY(2526, "37000");
    1647           0 :                         SQLS_ENTRY(8144, "37000");
    1648           0 :                         SQLS_ENTRY(17308, "42000");   /* Syntax/Access violation */
    1649           0 :                         SQLS_ENTRY(17571, "42000");
    1650           0 :                         SQLS_ENTRY(18002, "42000");
    1651           0 :                         SQLS_ENTRY(229, "42000");
    1652           0 :                         SQLS_ENTRY(230, "42000");
    1653           0 :                         SQLS_ENTRY(262, "42000");
    1654           0 :                         SQLS_ENTRY(2557, "42000");
    1655           0 :                         SQLS_ENTRY(2571, "42000");
    1656           0 :                         SQLS_ENTRY(2760, "42000");
    1657           0 :                         SQLS_ENTRY(3110, "42000");
    1658           0 :                         SQLS_ENTRY(3704, "42000");
    1659           0 :                         SQLS_ENTRY(4613, "42000");
    1660           0 :                         SQLS_ENTRY(4618, "42000");
    1661           0 :                         SQLS_ENTRY(4834, "42000");
    1662           0 :                         SQLS_ENTRY(5011, "42000");
    1663           0 :                         SQLS_ENTRY(5116, "42000");
    1664           0 :                         SQLS_ENTRY(5812, "42000");
    1665           0 :                         SQLS_ENTRY(6004, "42000");
    1666           0 :                         SQLS_ENTRY(6102, "42000");
    1667           0 :                         SQLS_ENTRY(7956, "42000");
    1668           0 :                         SQLS_ENTRY(11010, "42000");
    1669           0 :                         SQLS_ENTRY(11045, "42000");
    1670           0 :                         SQLS_ENTRY(14126, "42000");
    1671           0 :                         SQLS_ENTRY(15247, "42000");
    1672           0 :                         SQLS_ENTRY(15622, "42000");
    1673           0 :                         SQLS_ENTRY(20604, "42000");
    1674           0 :                         SQLS_ENTRY(21049, "42000");
    1675           0 :                         SQLS_ENTRY(113, "42000");
    1676           0 :                         SQLS_ENTRY(2714, "42S01");    /* Table or view already exists */
    1677          24 :                         SQLS_ENTRY(208, "42S02");     /* Table or view not found */
    1678         196 :                         SQLS_ENTRY(3701, "42S02");
    1679           0 :                         SQLS_ENTRY(1913, "42S11");    /* Index already exists */
    1680           0 :                         SQLS_ENTRY(15605, "42S11");
    1681           0 :                         SQLS_ENTRY(307, "42S12");     /* Index not found */
    1682           0 :                         SQLS_ENTRY(308, "42S12");
    1683           0 :                         SQLS_ENTRY(10033, "42S12");
    1684           0 :                         SQLS_ENTRY(15323, "42S12");
    1685           0 :                         SQLS_ENTRY(18833, "42S12");
    1686           0 :                         SQLS_ENTRY(4925, "42S21");    /* Column already exists */
    1687           0 :                         SQLS_ENTRY(21255, "42S21");
    1688           0 :                         SQLS_ENTRY(1911, "42S22");    /* Column not found */
    1689          48 :                         SQLS_ENTRY(207, "42S22");
    1690           0 :                         SQLS_ENTRY(4924, "42S22");
    1691           0 :                         SQLS_ENTRY(4926, "42S22");
    1692           0 :                         SQLS_ENTRY(15645, "42S22");
    1693           0 :                         SQLS_ENTRY(21166, "42S22");
    1694             :                 }
    1695             :         } else {
    1696        8274 :                 switch (msgno) {        /* Sybase */
    1697           4 :                         SQLS_ENTRY(3621, "01000");
    1698           0 :                         SQLS_ENTRY(9501, "01003");    /* Null in aggregate */
    1699           1 :                         SQLS_ENTRY(911, "08004");     /* Server rejected connection */
    1700           0 :                         SQLS_ENTRY(512, "21000");     /* Subquery returns more than one value */
    1701           0 :                         SQLS_ENTRY(213, "21S01");     /* Insert column list mismatch */
    1702           0 :                         SQLS_ENTRY(109, "21S01");
    1703           0 :                         SQLS_ENTRY(110, "21S01");
    1704           0 :                         SQLS_ENTRY(1715, "21S02");    /* Ref column mismatch */
    1705           0 :                         SQLS_ENTRY(9502, "22001");    /* String data would be truncated */
    1706           0 :                         SQLS_ENTRY(220, "22003");     /* Arithmetic overflow */
    1707           0 :                         SQLS_ENTRY(168, "22003");
    1708           0 :                         SQLS_ENTRY(227, "22003");
    1709           0 :                         SQLS_ENTRY(232, "22003");
    1710           0 :                         SQLS_ENTRY(234, "22003");
    1711           0 :                         SQLS_ENTRY(236, "22003");
    1712           0 :                         SQLS_ENTRY(238, "22003");
    1713           0 :                         SQLS_ENTRY(244, "22003");
    1714           0 :                         SQLS_ENTRY(246, "22003");
    1715           0 :                         SQLS_ENTRY(247, "22003");
    1716           0 :                         SQLS_ENTRY(248, "22003");
    1717           0 :                         SQLS_ENTRY(519, "22003");
    1718           0 :                         SQLS_ENTRY(520, "22003");
    1719           0 :                         SQLS_ENTRY(521, "22003");
    1720           0 :                         SQLS_ENTRY(522, "22003");
    1721           0 :                         SQLS_ENTRY(523, "22003");
    1722           0 :                         SQLS_ENTRY(524, "22003");
    1723           0 :                         SQLS_ENTRY(3606, "22003");
    1724           0 :                         SQLS_ENTRY(206, "22005");     /* Error in assignment */
    1725           0 :                         SQLS_ENTRY(235, "22005");
    1726           4 :                         SQLS_ENTRY(249, "22005");
    1727           0 :                         SQLS_ENTRY(256, "22005");
    1728           0 :                         SQLS_ENTRY(305, "22005");
    1729           0 :                         SQLS_ENTRY(409, "22005");
    1730           0 :                         SQLS_ENTRY(518, "22005");
    1731           0 :                         SQLS_ENTRY(529, "22005");
    1732           0 :                         SQLS_ENTRY(535, "22008");     /* Datetime out of range */
    1733           0 :                         SQLS_ENTRY(542, "22008");
    1734           2 :                         SQLS_ENTRY(517, "22008");
    1735           0 :                         SQLS_ENTRY(3607, "22012");    /* Div by zero */
    1736           0 :                         SQLS_ENTRY(245, "22018");     /* Syntax error? */
    1737           0 :                         SQLS_ENTRY(544, "23000");     /* Constraint violation */
    1738           0 :                         SQLS_ENTRY(233, "23000");
    1739           0 :                         SQLS_ENTRY(273, "23000");
    1740           0 :                         SQLS_ENTRY(530, "23000");
    1741           0 :                         SQLS_ENTRY(2601,"23000");
    1742           0 :                         SQLS_ENTRY(2615,"23000");
    1743           0 :                         SQLS_ENTRY(2626,"23000");
    1744           0 :                         SQLS_ENTRY(3604,"23000");
    1745           0 :                         SQLS_ENTRY(3605,"23000");
    1746           0 :                         SQLS_ENTRY(545, "23000");
    1747           0 :                         SQLS_ENTRY(546, "23000");
    1748           0 :                         SQLS_ENTRY(547, "23000");
    1749           0 :                         SQLS_ENTRY(548, "23000");
    1750           0 :                         SQLS_ENTRY(549, "23000");
    1751           0 :                         SQLS_ENTRY(550, "23000");
    1752           0 :                         SQLS_ENTRY(1505, "23000");
    1753           0 :                         SQLS_ENTRY(1508, "23000");
    1754           0 :                         SQLS_ENTRY(565, "24000");     /* Invalid cursor state */
    1755           0 :                         SQLS_ENTRY(558, "24000");
    1756           0 :                         SQLS_ENTRY(559, "24000");
    1757           0 :                         SQLS_ENTRY(6235, "24000");
    1758           0 :                         SQLS_ENTRY(583, "24000");
    1759           0 :                         SQLS_ENTRY(6259, "24000");
    1760           0 :                         SQLS_ENTRY(6260, "24000");
    1761           0 :                         SQLS_ENTRY(562, "24000");
    1762           0 :                         SQLS_ENTRY(277, "25000");     /* Invalid transaction state */
    1763           0 :                         SQLS_ENTRY(611,"25000");
    1764           0 :                         SQLS_ENTRY(3906,"25000");
    1765           0 :                         SQLS_ENTRY(3908,"25000");
    1766           0 :                         SQLS_ENTRY(6401,"25000");
    1767           0 :                         SQLS_ENTRY(627, "25000");
    1768           0 :                         SQLS_ENTRY(628, "25000");
    1769           0 :                         SQLS_ENTRY(641, "25000");
    1770           0 :                         SQLS_ENTRY(642, "25000");
    1771           0 :                         SQLS_ENTRY(1276, "25000");
    1772           0 :                         SQLS_ENTRY(3902, "25000");
    1773           0 :                         SQLS_ENTRY(3903, "25000");
    1774           0 :                         SQLS_ENTRY(6104, "37000");    /* Syntax error or access violation */
    1775           0 :                         SQLS_ENTRY(102, "37000");
    1776          24 :                         SQLS_ENTRY(137, "37000");
    1777           0 :                         SQLS_ENTRY(7327, "37000");
    1778           0 :                         SQLS_ENTRY(201, "37000");
    1779           0 :                         SQLS_ENTRY(257, "37000");
    1780           2 :                         SQLS_ENTRY(2812, "37000");
    1781           0 :                         SQLS_ENTRY(2526, "37000");
    1782           0 :                         SQLS_ENTRY(11021, "37000");
    1783           0 :                         SQLS_ENTRY(229, "42000");     /* Syntax/Access violation */
    1784           0 :                         SQLS_ENTRY(230, "42000");
    1785           0 :                         SQLS_ENTRY(262, "42000");
    1786           0 :                         SQLS_ENTRY(4602, "42000");
    1787           0 :                         SQLS_ENTRY(4603, "42000");
    1788           0 :                         SQLS_ENTRY(4608, "42000");
    1789           0 :                         SQLS_ENTRY(10306, "42000");
    1790           0 :                         SQLS_ENTRY(10323, "42000");
    1791           0 :                         SQLS_ENTRY(10330, "42000");
    1792           0 :                         SQLS_ENTRY(10331, "42000");
    1793           0 :                         SQLS_ENTRY(10332, "42000");
    1794           0 :                         SQLS_ENTRY(11110, "42000");
    1795           0 :                         SQLS_ENTRY(11113, "42000");
    1796           0 :                         SQLS_ENTRY(11118, "42000");
    1797           0 :                         SQLS_ENTRY(11121, "42000");
    1798           0 :                         SQLS_ENTRY(17222, "42000");
    1799           0 :                         SQLS_ENTRY(17223, "42000");
    1800           0 :                         SQLS_ENTRY(18350, "42000");
    1801           0 :                         SQLS_ENTRY(18351, "42000");
    1802           0 :                         SQLS_ENTRY(113, "42000");
    1803           0 :                         SQLS_ENTRY(2714, "42S01");    /* Table or view already exists */
    1804           0 :                         SQLS_ENTRY(208, "42S02");     /* Table or view not found */
    1805          44 :                         SQLS_ENTRY(3701, "42S02");
    1806           0 :                         SQLS_ENTRY(1913, "42S11");    /* Index already exists */
    1807           0 :                         SQLS_ENTRY(307, "42S12");     /* Index not found */
    1808           0 :                         SQLS_ENTRY(7010, "42S12");
    1809           0 :                         SQLS_ENTRY(18091, "42S12");
    1810           0 :                         SQLS_ENTRY(1921, "42S21");    /* Column already exists */
    1811           0 :                         SQLS_ENTRY(1720, "42S22");    /* Column not found */
    1812           6 :                         SQLS_ENTRY(207, "42S22");
    1813           0 :                         SQLS_ENTRY(4934, "42S22");
    1814           0 :                         SQLS_ENTRY(18117, "42S22");
    1815             :                 }
    1816             :         }
    1817             : 
    1818       15694 :         if (p != NULL && (q = strdup(p)) != NULL) {
    1819             :                 /* FIXME correct here ?? */
    1820             :                 /* Convert known ODBC 3.x states listed above to 2.x */
    1821        2051 :                 if (memcmp(q, "42S", 3) == 0)
    1822         318 :                         memcpy(q, "S00", 3);
    1823             : 
    1824             :                 return q;
    1825             :         }
    1826             :         return NULL;
    1827             : }
    1828             : 
    1829             : BCPCOLDATA *
    1830        3186 : tds_alloc_bcp_column_data(unsigned int column_size)
    1831             : {
    1832             :         BCPCOLDATA *coldata;
    1833             : 
    1834        3186 :         TEST_MALLOC(coldata, BCPCOLDATA);
    1835             : 
    1836        3186 :         if (column_size > 4 * 1024)
    1837         116 :                 column_size = 4 * 1024;
    1838        3186 :         TEST_CALLOC(coldata->data, unsigned char, column_size);
    1839             : 
    1840             :         return coldata;
    1841           0 : Cleanup:
    1842           0 :         tds_free_bcp_column_data(coldata);
    1843           0 :         return NULL;
    1844             : }
    1845             : 
    1846             : void
    1847      104855 : tds_free_bcp_column_data(BCPCOLDATA * coldata)
    1848             : {
    1849      104855 :         if (!coldata)
    1850             :                 return;
    1851             : 
    1852        3186 :         free(coldata->data);
    1853        3186 :         free(coldata);
    1854             : }
    1855             : 
    1856             : TDSBCPINFO *
    1857         394 : tds_alloc_bcpinfo(void)
    1858             : {
    1859             :         TDSBCPINFO *bcpinfo;
    1860             : 
    1861         394 :         TEST_MALLOC(bcpinfo, TDSBCPINFO);
    1862             : 
    1863         788 :         tds_dstr_init(&bcpinfo->hint);
    1864         788 :         tds_dstr_init(&bcpinfo->tablename);
    1865             : 
    1866         394 :         return bcpinfo;
    1867         394 : Cleanup:
    1868             :         return NULL;
    1869             : }
    1870             : 
    1871             : void
    1872         648 : tds_deinit_bcpinfo(TDSBCPINFO *bcpinfo)
    1873             : {
    1874         648 :         tds_dstr_free(&bcpinfo->hint);
    1875         648 :         tds_dstr_free(&bcpinfo->tablename);
    1876         648 :         TDS_ZERO_FREE(bcpinfo->insert_stmt);
    1877         648 :         tds_free_results(bcpinfo->bindinfo);
    1878         648 :         bcpinfo->bindinfo = NULL;
    1879         648 :         TDS_ZERO_FREE(bcpinfo->sybase_colinfo);
    1880         648 :         bcpinfo->sybase_count = 0;
    1881         648 : }
    1882             : 
    1883             : void
    1884        2738 : tds_free_bcpinfo(TDSBCPINFO *bcpinfo)
    1885             : {
    1886        2738 :         if (bcpinfo) {
    1887         394 :                 tds_deinit_bcpinfo(bcpinfo);
    1888         394 :                 free(bcpinfo);
    1889             :         }
    1890        2738 : }
    1891             : 
    1892             : /**
    1893             :  * Reallocate a pointer and update it if success
    1894             :  * \param pp pointer to pointer to be reallocated
    1895             :  * \param new_size new size to be allocated
    1896             :  * \return new pointer allocated, NULL on failure
    1897             :  */
    1898             : void *
    1899      140271 : tds_realloc(void **pp, size_t new_size)
    1900             : {
    1901             :         void *p;
    1902             : 
    1903             :         /* some implementation of malloc/realloc does not like size==0 */
    1904      140271 :         if (!new_size)
    1905           0 :                 new_size = 1;
    1906             : 
    1907             :         /* use malloc if not allocated before, some implementations require it */
    1908      140271 :         if (*pp)
    1909       55336 :                 p = realloc(*pp, new_size);
    1910             :         else
    1911       84935 :                 p = malloc(new_size);
    1912             : 
    1913             :         /* update pointer only on success */
    1914      140271 :         if (p)
    1915      140271 :                 *pp = p;
    1916             : 
    1917      140271 :         return p;
    1918             : }
    1919             : 
    1920             : void
    1921          16 : tds_deinit_tvp(TDS_TVP *table)
    1922             : {
    1923             :         TDS_TVP_ROW *tvp_row, *next_row;
    1924             : 
    1925          16 :         free(table->schema);
    1926          16 :         table->schema = NULL;
    1927          16 :         free(table->name);
    1928          16 :         table->name = NULL;
    1929          32 :         tds_free_param_results(table->metadata);
    1930          16 :         table->metadata = NULL;
    1931          52 :         for (tvp_row = table->row; tvp_row != NULL; tvp_row = next_row) {
    1932          36 :                 next_row = tvp_row->next;
    1933          36 :                 tds_free_tvp_row(tvp_row);
    1934          36 :                 free(tvp_row);
    1935             :         }
    1936          16 :         table->row = NULL;
    1937          16 : }
    1938             : 
    1939             : /** @} */

Generated by: LCOV version 1.13