LCOV - code coverage report
Current view: top level - src/ctlib - cs.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 308 657 46.9 %
Date: 2025-01-18 12:13:41 Functions: 17 40 42.5 %

          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) 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 <stdarg.h>
      24             : 
      25             : #include <freetds/time.h>
      26             : 
      27             : #include <stdio.h>
      28             : #include <assert.h>
      29             : 
      30             : #if HAVE_STDLIB_H
      31             : #include <stdlib.h>
      32             : #endif /* HAVE_STDLIB_H */
      33             : 
      34             : #if HAVE_STRING_H
      35             : #include <string.h>
      36             : #endif /* HAVE_STRING_H */
      37             : 
      38             : #include <freetds/replacements.h>
      39             : 
      40             : #include "cspublic.h"
      41             : #include "ctlib.h"
      42             : 
      43             : #undef cs_dt_crack
      44             : 
      45             : static CS_INT cs_diag_storemsg(CS_CONTEXT *context, CS_CLIENTMSG *message);
      46             : static CS_INT cs_diag_clearmsg(CS_CONTEXT *context, CS_INT type);
      47             : static CS_INT cs_diag_getmsg(CS_CONTEXT *context, CS_INT idx, CS_CLIENTMSG *message);
      48             : static CS_INT cs_diag_countmsg(CS_CONTEXT *context, CS_INT *count);
      49             : 
      50             : const char *
      51           0 : cs_prretcode(int retcode)
      52             : {
      53             :         static char unknown[24];
      54             :         
      55           0 :         tdsdump_log(TDS_DBG_FUNC, "cs_prretcode(%d)\n", retcode);
      56             : 
      57           0 :         switch(retcode) {
      58             :         case CS_SUCCEED:        return "CS_SUCCEED";
      59           0 :         case CS_FAIL:           return "CS_FAIL";
      60           0 :         case CS_MEM_ERROR:      return "CS_MEM_ERROR";
      61           0 :         case CS_PENDING:        return "CS_PENDING";
      62           0 :         case CS_QUIET:          return "CS_QUIET";
      63           0 :         case CS_BUSY:           return "CS_BUSY";
      64           0 :         case CS_INTERRUPT:      return "CS_INTERRUPT";
      65           0 :         case CS_BLK_HAS_TEXT:   return "CS_BLK_HAS_TEXT";
      66           0 :         case CS_CONTINUE:       return "CS_CONTINUE";
      67           0 :         case CS_FATAL:          return "CS_FATAL";
      68           0 :         case CS_RET_HAFAILOVER: return "CS_RET_HAFAILOVER";
      69           0 :         case CS_UNSUPPORTED:    return "CS_UNSUPPORTED";
      70             : 
      71           0 :         case CS_CANCELED:       return "CS_CANCELED";
      72           0 :         case CS_ROW_FAIL:       return "CS_ROW_FAIL";
      73           0 :         case CS_END_DATA:       return "CS_END_DATA";
      74           0 :         case CS_END_RESULTS:    return "CS_END_RESULTS";
      75           0 :         case CS_END_ITEM:       return "CS_END_ITEM";
      76           0 :         case CS_NOMSG:          return "CS_NOMSG";
      77           0 :         case CS_TIMED_OUT:      return "CS_TIMED_OUT";
      78             : 
      79           0 :         default:
      80           0 :                 sprintf(unknown, "oops: %u ??", retcode);
      81             :         }
      82           0 :         return unknown;
      83             : }
      84             : 
      85             : static const char *
      86          24 : _cs_get_layer(int layer)
      87             : {
      88          24 :         tdsdump_log(TDS_DBG_FUNC, "_cs_get_layer(%d)\n", layer);
      89             : 
      90          24 :         switch (layer) {
      91             :         case 2:
      92             :                 return "cslib user api layer";
      93             :                 break;
      94             :         default:
      95             :                 break;
      96             :         }
      97           0 :         return "unrecognized layer";
      98             : }
      99             : 
     100             : static const char *
     101          24 : _cs_get_origin(int origin)
     102             : {
     103          24 :         tdsdump_log(TDS_DBG_FUNC, "_cs_get_origin(%d)\n", origin);
     104             : 
     105          24 :         switch (origin) {
     106             :         case 1:
     107             :                 return "external error";
     108             :                 break;
     109           0 :         case 2:
     110           0 :                 return "internal CS-Library error";
     111             :                 break;
     112           8 :         case 4:
     113           8 :                 return "common library error";
     114             :                 break;
     115           0 :         case 5:
     116           0 :                 return "intl library error";
     117             :                 break;
     118             :         default:
     119             :                 break;
     120             :         }
     121           0 :         return "unrecognized origin";
     122             : }
     123             : 
     124             : static const char *
     125          24 : _cs_get_user_api_layer_error(int error)
     126             : {
     127          24 :         tdsdump_log(TDS_DBG_FUNC, "_cs_get_user_api_layer_error(%d)\n", error);
     128             : 
     129          24 :         switch (error) {
     130             :         case 3:
     131             :                 return "Memory allocation failure.";
     132             :                 break;
     133          16 :         case 16:
     134          16 :                 return "Conversion between %1! and %2! datatypes is not supported.";
     135             :                 break;
     136           8 :         case 20:
     137           8 :                 return "The conversion/operation resulted in overflow.";
     138             :                 break;
     139           0 :         case 24:
     140           0 :                 return "The conversion/operation was stopped due to a syntax error in the source field.";
     141             :                 break;
     142             :         default:
     143             :                 break;
     144             :         }
     145           0 :         return "unrecognized error";
     146             : }
     147             : 
     148             : static char *
     149          24 : _cs_get_msgstr(const char *funcname, int layer, int origin, int severity, int number)
     150             : {
     151             :         char *m;
     152             : 
     153          24 :         tdsdump_log(TDS_DBG_FUNC, "_cs_get_msgstr(%s, %d, %d, %d, %d)\n", funcname, layer, origin, severity, number);
     154             : 
     155          24 :         if (asprintf(&m, "%s: %s: %s: %s", funcname, _cs_get_layer(layer), _cs_get_origin(origin), (layer == 2)
     156             :                      ? _cs_get_user_api_layer_error(number)
     157             :                      : "unrecognized error") < 0) {
     158             :                 return NULL;
     159             :         }
     160          24 :         return m;
     161             : }
     162             : 
     163             : static void
     164         104 : _csclient_msg(CS_CONTEXT * ctx, const char *funcname, int layer, int origin, int severity, int number, const char *fmt, ...)
     165             : {
     166             :         va_list ap;
     167             :         CS_CLIENTMSG cm;
     168             :         char *msgstr;
     169             : 
     170         104 :         tdsdump_log(TDS_DBG_FUNC, "_csclient_msg(%p, %s, %d, %d, %d, %d, %s)\n", ctx, funcname, layer, origin, severity, number, fmt);
     171             : 
     172         104 :         va_start(ap, fmt);
     173             : 
     174         104 :         if (ctx->_cslibmsg_cb) {
     175          24 :                 cm.severity = severity;
     176          48 :                 cm.msgnumber = (((layer << 24) & 0xFF000000)
     177          24 :                                 | ((origin << 16) & 0x00FF0000)
     178          24 :                                 | ((severity << 8) & 0x0000FF00)
     179          24 :                                 | ((number) & 0x000000FF));
     180          24 :                 msgstr = _cs_get_msgstr(funcname, layer, origin, severity, number);
     181          24 :                 tds_vstrbuild(cm.msgstring, CS_MAX_MSG, &(cm.msgstringlen), msgstr, CS_NULLTERM, fmt, CS_NULLTERM, ap);
     182          24 :                 cm.msgstring[cm.msgstringlen] = '\0';
     183          24 :                 free(msgstr);
     184          24 :                 cm.osnumber = 0;
     185          24 :                 cm.osstring[0] = '\0';
     186          24 :                 cm.osstringlen = 0;
     187          24 :                 cm.status = 0;
     188             :                 /* cm.sqlstate */
     189          24 :                 cm.sqlstatelen = 0;
     190          24 :                 ctx->_cslibmsg_cb(ctx, &cm);
     191             :         }
     192             : 
     193         104 :         va_end(ap);
     194         104 : }
     195             : 
     196             : /**
     197             :  * Allocate new CS_LOCALE and initialize it
     198             :  * returns NULL on out of memory errors 
     199             :  */
     200             : static CS_LOCALE *
     201           0 : _cs_locale_alloc(void)
     202             : {
     203           0 :         tdsdump_log(TDS_DBG_FUNC, "_cs_locale_alloc()\n");
     204             : 
     205           0 :         return tds_new0(CS_LOCALE, 1);
     206             : }
     207             : 
     208             : static void
     209           0 : _cs_locale_free_contents(CS_LOCALE *locale)
     210             : {
     211           0 :         tdsdump_log(TDS_DBG_FUNC, "_cs_locale_free_contents(%p)\n", locale);
     212             : 
     213             :         /* free strings */
     214           0 :         free(locale->language);
     215           0 :         locale->language = NULL;
     216           0 :         free(locale->charset);
     217           0 :         locale->charset = NULL;
     218           0 :         free(locale->time);
     219           0 :         locale->time = NULL;
     220           0 :         free(locale->collate);
     221           0 :         locale->collate = NULL;
     222           0 : }
     223             : 
     224             : void 
     225           0 : _cs_locale_free(CS_LOCALE *locale)
     226             : {
     227           0 :         tdsdump_log(TDS_DBG_FUNC, "_cs_locale_free(%p)\n", locale);
     228             : 
     229             :         /* free contents */
     230           0 :         _cs_locale_free_contents(locale);
     231             : 
     232             :         /* free the data structure */
     233           0 :         free(locale);
     234           0 : }
     235             : 
     236             : /* returns 0 on out of memory errors, 1 for OK */
     237             : int
     238           0 : _cs_locale_copy_inplace(CS_LOCALE *new_locale, CS_LOCALE *orig)
     239             : {
     240           0 :         tdsdump_log(TDS_DBG_FUNC, "_cs_locale_copy_inplace(%p, %p)\n", new_locale, orig);
     241             : 
     242           0 :         _cs_locale_free_contents(new_locale);
     243           0 :         if (orig->language) {
     244           0 :                 new_locale->language = strdup(orig->language);
     245           0 :                 if (!new_locale->language)
     246             :                         goto Cleanup;
     247             :         }
     248             : 
     249           0 :         if (orig->charset) {
     250           0 :                 new_locale->charset = strdup(orig->charset);
     251           0 :                 if (!new_locale->charset)
     252             :                         goto Cleanup;
     253             :         }
     254             : 
     255           0 :         if (orig->time) {
     256           0 :                 new_locale->time = strdup(orig->time);
     257           0 :                 if (!new_locale->time)
     258             :                         goto Cleanup;
     259             :         }
     260             : 
     261           0 :         if (orig->collate) {
     262           0 :                 new_locale->collate = strdup(orig->collate);
     263           0 :                 if (!new_locale->collate)
     264             :                         goto Cleanup;
     265             :         }
     266             : 
     267             :         return 1;
     268             : 
     269           0 : Cleanup:
     270           0 :         _cs_locale_free_contents(new_locale);
     271           0 :         return 0;
     272             : }
     273             : 
     274             : /* returns NULL on out of memory errors */
     275             : CS_LOCALE *
     276           0 : _cs_locale_copy(CS_LOCALE *orig)
     277             : {
     278             :         CS_LOCALE *new_locale;
     279             : 
     280           0 :         tdsdump_log(TDS_DBG_FUNC, "_cs_locale_copy(%p)\n", orig);
     281             : 
     282           0 :         new_locale = _cs_locale_alloc();
     283           0 :         if (!new_locale)
     284             :                 return NULL;
     285             : 
     286           0 :         if (orig->language) {
     287           0 :                 new_locale->language = strdup(orig->language);
     288           0 :                 if (!new_locale->language)
     289             :                         goto Cleanup;
     290             :         }
     291             : 
     292           0 :         if (orig->charset) {
     293           0 :                 new_locale->charset = strdup(orig->charset);
     294           0 :                 if (!new_locale->charset)
     295             :                         goto Cleanup;
     296             :         }
     297             : 
     298           0 :         if (orig->time) {
     299           0 :                 new_locale->time = strdup(orig->time);
     300           0 :                 if (!new_locale->time)
     301             :                         goto Cleanup;
     302             :         }
     303             : 
     304           0 :         if (orig->collate) {
     305           0 :                 new_locale->collate = strdup(orig->collate);
     306           0 :                 if (!new_locale->collate)
     307             :                         goto Cleanup;
     308             :         }
     309             : 
     310             :         return new_locale;
     311             : 
     312           0 : Cleanup:
     313           0 :         _cs_locale_free(new_locale);
     314           0 :         return NULL;
     315             : }
     316             : 
     317             : CS_RETCODE
     318        1088 : cs_ctx_alloc(CS_INT version, CS_CONTEXT ** out_ctx)
     319             : {
     320             :         TDSCONTEXT *tds_ctx;
     321             :         CS_CONTEXT *ctx;
     322             : 
     323        1088 :         tdsdump_log(TDS_DBG_FUNC, "cs_ctx_alloc(%d, %p)\n", version, out_ctx);
     324             : 
     325        1088 :         ctx = tds_new0(CS_CONTEXT, 1);
     326        1088 :         if (!ctx)
     327             :                 return CS_FAIL;
     328        1088 :         ctx->use_large_identifiers = _ct_is_large_identifiers_version(version);
     329        1088 :         tds_ctx = tds_alloc_context(ctx);
     330        1088 :         if (!tds_ctx) {
     331           0 :                 free(ctx);
     332           0 :                 return CS_FAIL;
     333             :         }
     334        1088 :         ctx->tds_ctx = tds_ctx;
     335        1088 :         if (tds_ctx->locale && !tds_ctx->locale->datetime_fmt) {
     336             :                 /* set default in case there's no locale file */
     337           0 :                 tds_ctx->locale->datetime_fmt = strdup(STD_DATETIME_FMT);
     338             :         }
     339             : 
     340        1088 :         ctx->login_timeout = -1;
     341        1088 :         ctx->query_timeout = -1;
     342             : 
     343        1088 :         *out_ctx = ctx;
     344        1088 :         return CS_SUCCEED;
     345             : }
     346             : 
     347             : CS_RETCODE
     348           0 : cs_ctx_global(CS_INT version, CS_CONTEXT ** ctx)
     349             : {
     350             :         static CS_CONTEXT *global_cs_ctx = NULL;
     351             : 
     352           0 :         tdsdump_log(TDS_DBG_FUNC, "cs_ctx_global(%d, %p)\n", version, ctx);
     353             : 
     354           0 :         if (global_cs_ctx != NULL) {
     355           0 :                 *ctx = global_cs_ctx;
     356           0 :                 return CS_SUCCEED;
     357             :         }
     358           0 :         if (cs_ctx_alloc(version, ctx) != CS_SUCCEED) {
     359             :                 return CS_FAIL;
     360             :         }
     361           0 :         global_cs_ctx = *ctx;
     362           0 :         return CS_SUCCEED;
     363             : }
     364             : 
     365             : CS_RETCODE
     366        1088 : cs_ctx_drop(CS_CONTEXT * ctx)
     367             : {
     368        1088 :         tdsdump_log(TDS_DBG_FUNC, "cs_ctx_drop(%p)\n", ctx);
     369             : 
     370        1088 :         if (ctx) {
     371        1088 :                 _ct_diag_clearmsg(ctx, CS_ALLMSG_TYPE);
     372        1088 :                 free(ctx->userdata);
     373        1088 :                 if (ctx->tds_ctx)
     374        1088 :                         tds_free_context(ctx->tds_ctx);
     375        1088 :                 free(ctx);
     376             :         }
     377        1088 :         return CS_SUCCEED;
     378             : }
     379             : 
     380             : CS_RETCODE
     381          64 : cs_config(CS_CONTEXT * ctx, CS_INT action, CS_INT property, CS_VOID * buffer, CS_INT buflen, CS_INT * outlen)
     382             : {
     383             :         CS_INT maxcp;   /* declared  for - CS_USERDATA changes - swapna*/
     384             : 
     385          64 :         tdsdump_log(TDS_DBG_FUNC, "cs_config(%p, %d, %d, %p, %d, %p)\n", ctx, action, property, buffer, buflen, outlen);
     386             : 
     387          64 :         if (action == CS_GET) {
     388          24 :                 if (buffer == NULL) {
     389             :                         return CS_SUCCEED;
     390             :                 }
     391          24 :                 switch (property) {
     392           0 :                 case CS_MESSAGE_CB:
     393           0 :                         *(void **) buffer = (void*) ctx->_cslibmsg_cb;
     394           0 :                         return CS_SUCCEED;
     395          24 :                 case CS_USERDATA:
     396          24 :                         maxcp = ctx->userdata_len;
     397          24 :                         if (outlen)
     398          24 :                                 *outlen = maxcp;
     399          24 :                         if (maxcp > buflen)
     400           8 :                                 maxcp = buflen;
     401             : 
     402          24 :                         memcpy(buffer, ctx->userdata, maxcp); 
     403             :                         
     404          24 :                         return CS_SUCCEED;
     405             :                 case CS_EXTRA_INF:
     406             :                 case CS_LOC_PROP:
     407             :                 case CS_VERSION:
     408             :                         return CS_FAIL;
     409             :                         break;
     410             :                 }
     411             :         }
     412          40 :         if (action == CS_SET) {
     413          40 :                 switch (property) {
     414          16 :                 case CS_MESSAGE_CB:
     415          16 :                         if ( ctx->cs_errhandletype == _CS_ERRHAND_INLINE) {
     416           0 :                                 cs_diag_clearmsg(ctx, CS_UNUSED);
     417             :                         }
     418          16 :                         ctx->_cslibmsg_cb = (CS_CSLIBMSG_FUNC) buffer;
     419          16 :                         ctx->cs_errhandletype = _CS_ERRHAND_CB;
     420          16 :                         return CS_SUCCEED;
     421          24 :                 case CS_USERDATA:
     422          24 :                         free(ctx->userdata);
     423             :         
     424          24 :                         if (buflen == CS_NULLTERM) {
     425          16 :                                 maxcp = strlen((char*) buffer) + 1;
     426             :                         } else {
     427             :                                 maxcp = buflen;
     428             :                         }
     429          24 :                         ctx->userdata = (void *) malloc(maxcp);
     430          24 :                         if ( ctx->userdata == NULL) {
     431             :                                 return CS_FAIL;
     432             :                         }
     433          24 :                         ctx->userdata_len = maxcp;
     434             :         
     435          24 :                         if (buffer) {
     436          24 :                                 memcpy(ctx->userdata, buffer, maxcp);
     437             :                         } else {
     438             :                                 return CS_FAIL;
     439             :                         }
     440          24 :                         return CS_SUCCEED;
     441             :         
     442             :                 case CS_EXTRA_INF:
     443             :                 case CS_LOC_PROP:
     444             :                 case CS_VERSION:
     445             :                         return CS_FAIL;
     446             :                         break;
     447             :                 }
     448             :         }
     449           0 :         if (action == CS_CLEAR) {
     450           0 :                 switch (property) {
     451           0 :                 case CS_MESSAGE_CB:
     452           0 :                         if ( ctx->cs_errhandletype == _CS_ERRHAND_INLINE) {
     453           0 :                                 cs_diag_clearmsg(ctx, CS_UNUSED);
     454             :                         }
     455           0 :                         ctx->_cslibmsg_cb = NULL;
     456           0 :                         ctx->cs_errhandletype = 0;
     457           0 :                         return CS_SUCCEED;
     458           0 :                 case CS_USERDATA:
     459           0 :                         free(ctx->userdata);
     460           0 :                         ctx->userdata = NULL;
     461             :         
     462           0 :                         return CS_SUCCEED;
     463             :         
     464             :                 case CS_EXTRA_INF:
     465             :                 case CS_LOC_PROP:
     466             :                 case CS_VERSION:
     467             :                         return CS_FAIL;
     468             :                         break;
     469             :                 }
     470             :         }
     471             :         return CS_FAIL;
     472             : }
     473             : 
     474             : CS_RETCODE
     475        4779 : _cs_convert(CS_CONTEXT * ctx, const CS_DATAFMT_COMMON * srcfmt, CS_VOID * srcdata,
     476             :             const CS_DATAFMT_COMMON * destfmt, CS_VOID * destdata, CS_INT * resultlen)
     477             : {
     478             :         TDS_SERVER_TYPE src_type, desttype;
     479             :         int src_len, destlen, len;
     480             :         CONV_RESULT cres;
     481             :         unsigned char *dest;
     482             :         CS_RETCODE ret;
     483             :         CS_INT dummy, datatype;
     484        4779 :         CS_VARCHAR *destvc = NULL;
     485             : 
     486        4779 :         tdsdump_log(TDS_DBG_FUNC, "cs_convert(%p, %p, %p, %p, %p, %p)\n", ctx, srcfmt, srcdata, destfmt, destdata, resultlen);
     487             : 
     488             :         /* If destination is NULL we have a problem */
     489        4779 :         if (destdata == NULL) {
     490             :                 /* TODO: add error message */
     491           0 :                 tdsdump_log(TDS_DBG_FUNC, "error: destdata is null\n");
     492             :                 return CS_FAIL;
     493             : 
     494             :         }
     495             : 
     496             :         /* If destfmt is NULL we have a problem */
     497        4779 :         if (destfmt == NULL) {
     498             :                 /* TODO: add error message */
     499           0 :                 tdsdump_log(TDS_DBG_FUNC, "error: destfmt is null\n");
     500             :                 return CS_FAIL;
     501             : 
     502             :         }
     503             :         
     504        4779 :         if (resultlen == NULL) 
     505          32 :                 resultlen = &dummy;
     506             : 
     507             :         /* If source is indicated to be NULL, set dest to low values */
     508        4779 :         if (srcdata == NULL) {
     509             :                 /* TODO: implement cs_setnull */
     510           0 :                 tdsdump_log(TDS_DBG_FUNC, "srcdata is null\n");
     511           0 :                 memset(destdata, '\0', destfmt->maxlength);
     512           0 :                 *resultlen = 0;
     513           0 :                 return CS_SUCCEED;
     514             : 
     515             :         }
     516             : 
     517        4779 :         datatype = srcfmt->datatype;
     518        4779 :         src_type = _ct_get_server_type(NULL, datatype);
     519        4779 :         if (src_type == TDS_INVALID_TYPE)
     520             :                 return CS_FAIL;
     521        4779 :         src_len = srcfmt->maxlength;
     522        4779 :         if (datatype == CS_VARCHAR_TYPE || datatype == CS_VARBINARY_TYPE) {
     523           0 :                 CS_VARCHAR *vc = (CS_VARCHAR *) srcdata;
     524           0 :                 src_len = vc->len;
     525           0 :                 srcdata = vc->str;
     526             :         }
     527             : 
     528        4779 :         datatype = destfmt->datatype;
     529        4779 :         desttype = _ct_get_server_type(NULL, datatype);
     530        4779 :         if (desttype == TDS_INVALID_TYPE)
     531             :                 return CS_FAIL;
     532        4779 :         destlen = destfmt->maxlength;
     533        4779 :         if (datatype == CS_VARCHAR_TYPE || datatype == CS_VARBINARY_TYPE) {
     534           8 :                 destvc = (CS_VARCHAR *) destdata;
     535           8 :                 destlen  = sizeof(destvc->str);
     536           8 :                 destdata = destvc->str;
     537        4771 :         } else if (is_numeric_type(desttype)) {
     538         168 :                 destlen = sizeof(TDS_NUMERIC);
     539             :         }
     540             : 
     541        4779 :         tdsdump_log(TDS_DBG_FUNC, "converting type %d (%d bytes) to type = %d (%d bytes)\n",
     542             :                     src_type, src_len, desttype, destlen);
     543             : 
     544        4779 :         if (!is_fixed_type(desttype) && (destlen <= 0)) {
     545             :                 return CS_FAIL;
     546             :         }
     547             : 
     548        4779 :         dest = (unsigned char *) destdata;
     549             : 
     550             :         /* many times we are asked to convert a data type to itself */
     551             : 
     552        4779 :         if (src_type == desttype) {
     553        1846 :                 int minlen = src_len < destlen? src_len : destlen;
     554             : 
     555        1846 :                 tdsdump_log(TDS_DBG_FUNC, "cs_convert() srctype == desttype\n");
     556        1846 :                 switch (desttype) {
     557             : 
     558           8 :                 case SYBLONGBINARY:
     559             :                 case SYBBINARY:
     560             :                 case SYBVARBINARY:
     561             :                 case SYBIMAGE:
     562           8 :                         memcpy(dest, srcdata, minlen);
     563           8 :                         *resultlen = minlen;
     564             : 
     565           8 :                         if (src_len > destlen) {
     566           0 :                                 tdsdump_log(TDS_DBG_FUNC, "error: src_len > destlen\n");
     567             :                                 ret = CS_FAIL;
     568             :                         } else {
     569           8 :                                 switch (destfmt->format) {
     570           0 :                                 case CS_FMT_PADNULL:
     571           0 :                                         memset(dest + src_len, '\0', destlen - src_len);
     572           0 :                                         *resultlen = destlen;
     573             :                                         /* fall through */
     574             :                                 case CS_FMT_UNUSED:
     575             :                                         ret = CS_SUCCEED;
     576             :                                         break;
     577             :                                 default:
     578             :                                         ret = CS_FAIL;
     579             :                                         break;
     580             :                                 }
     581             :                         }
     582           8 :                         if (destvc) {
     583           0 :                                 destvc->len = minlen;
     584           0 :                                 *resultlen = sizeof(*destvc);
     585             :                         }
     586             :                         break;
     587             : 
     588        1560 :                 case SYBCHAR:
     589             :                 case SYBVARCHAR:
     590             :                 case SYBTEXT:
     591        1560 :                         tdsdump_log(TDS_DBG_FUNC, "cs_convert() desttype = character\n");
     592             : 
     593        1560 :                         memcpy(dest, srcdata, minlen);
     594        1560 :                         *resultlen = minlen;
     595             : 
     596        1560 :                         if (src_len > destlen) {
     597           8 :                                 tdsdump_log(TDS_DBG_FUNC, "error: src_len > destlen\n");
     598             :                                 ret = CS_FAIL;
     599             :                         } else {
     600        1552 :                                 switch (destfmt->format) {
     601        1306 :                                 case CS_FMT_NULLTERM:
     602        1306 :                                         if (src_len == destlen) {
     603           0 :                                                 *resultlen = src_len;
     604           0 :                                                 tdsdump_log(TDS_DBG_FUNC, "error: no room for null terminator\n");
     605             :                                                 ret = CS_FAIL;
     606             :                                         } else {
     607        1306 :                                                 dest[src_len] = '\0';
     608        1306 :                                                 *resultlen = src_len + 1;
     609        1306 :                                                 ret = CS_SUCCEED;
     610             :                                         }
     611             :                                         break;
     612             : 
     613           0 :                                 case CS_FMT_PADBLANK:
     614           0 :                                         memset(dest + src_len, ' ', destlen - src_len);
     615           0 :                                         *resultlen = destlen;
     616           0 :                                         ret = CS_SUCCEED;
     617           0 :                                         break;
     618           0 :                                 case CS_FMT_PADNULL:
     619           0 :                                         memset(dest + src_len, '\0', destlen - src_len);
     620           0 :                                         *resultlen = destlen;
     621           0 :                                         ret = CS_SUCCEED;
     622           0 :                                         break;
     623             :                                 case CS_FMT_UNUSED:
     624             :                                         ret = CS_SUCCEED;
     625             :                                         break;
     626           0 :                                 default:
     627           0 :                                         tdsdump_log(TDS_DBG_FUNC, "no destination format specified!\n");
     628             :                                         ret = CS_FAIL;
     629             :                                         break;
     630             :                                 }
     631             :                         }
     632        1560 :                         if (destvc) {
     633           0 :                                 destvc->len = minlen;
     634           0 :                                 *resultlen = sizeof(*destvc);
     635             :                         }
     636             :                         break;
     637         270 :                 case SYBINT1:
     638             :                 case SYBUINT1:
     639             :                 case SYBINT2:
     640             :                 case SYBUINT2:
     641             :                 case SYBINT4:
     642             :                 case SYBUINT4:
     643             :                 case SYBINT8:
     644             :                 case SYBUINT8:
     645             :                 case SYBFLT8:
     646             :                 case SYBREAL:
     647             :                 case SYBBIT:
     648             :                 case SYBMONEY:
     649             :                 case SYBMONEY4:
     650             :                 case SYBDATETIME:
     651             :                 case SYBDATETIME4:
     652             :                 case SYBTIME:
     653             :                 case SYBDATE:
     654             :                 case SYB5BIGDATETIME:
     655             :                 case SYB5BIGTIME:
     656         270 :                         *resultlen = tds_get_size_by_type(src_type);
     657         270 :                         if (*resultlen > 0)
     658         270 :                                 memcpy(dest, srcdata, *resultlen);
     659             :                         ret = CS_SUCCEED;
     660             :                         break;
     661             : 
     662           8 :                 case SYBNUMERIC:
     663             :                 case SYBDECIMAL:
     664           8 :                         src_len = tds_numeric_bytes_per_prec[((TDS_NUMERIC *) srcdata)->precision] + 2;
     665           8 :                 case SYBBITN:
     666             :                 case SYBUNIQUE:
     667           8 :                         memcpy(dest, srcdata, minlen);
     668           8 :                         *resultlen = minlen;
     669             : 
     670           8 :                         if (src_len > destlen) {
     671           0 :                                 tdsdump_log(TDS_DBG_FUNC, "error: src_len > destlen\n");
     672             :                                 ret = CS_FAIL;
     673             :                         } else {
     674             :                                 ret = CS_SUCCEED;
     675             :                         }
     676             :                         break;
     677             : 
     678           0 :                 default:
     679           0 :                         tdsdump_log(TDS_DBG_FUNC, "error: unrecognized type\n");
     680             :                         ret = CS_FAIL;
     681             :                         break;
     682             :                 }
     683             : 
     684        1846 :                 tdsdump_log(TDS_DBG_FUNC, "cs_convert() returning  %s\n", cs_prretcode(ret));
     685             :                 return ret;
     686             : 
     687             :         }
     688             : 
     689             :         assert(src_type != desttype);
     690             :         
     691             :         /* set the output precision/scale for conversions to numeric type */
     692        2933 :         if (is_numeric_type(desttype)) {
     693         160 :                 cres.n.precision = destfmt->precision;
     694         160 :                 cres.n.scale = destfmt->scale;
     695         160 :                 if (destfmt->precision == CS_SRC_VALUE)
     696           0 :                         cres.n.precision = srcfmt->precision;
     697         160 :                 if (destfmt->scale == CS_SRC_VALUE)
     698           0 :                         cres.n.scale = srcfmt->scale;
     699             :         }
     700             : 
     701        2933 :         tdsdump_log(TDS_DBG_FUNC, "cs_convert() calling tds_convert\n");
     702        2933 :         len = tds_convert(ctx->tds_ctx, src_type, srcdata, src_len, desttype, &cres);
     703             : 
     704        2933 :         tdsdump_log(TDS_DBG_FUNC, "cs_convert() tds_convert returned %d\n", len);
     705             : 
     706        2933 :         switch (len) {
     707          24 :         case TDS_CONVERT_NOAVAIL:
     708          24 :                 _csclient_msg(ctx, "cs_convert", 2, 1, 1, 16, "%d, %d", src_type, desttype);
     709          24 :                 return CS_FAIL;
     710             :                 break;
     711          32 :         case TDS_CONVERT_SYNTAX:
     712          32 :                 _csclient_msg(ctx, "cs_convert", 2, 4, 1, 24, "");
     713          32 :                 return CS_FAIL;
     714             :                 break;
     715           0 :         case TDS_CONVERT_NOMEM:
     716           0 :                 _csclient_msg(ctx, "cs_convert", 2, 4, 1, 3, "");
     717           0 :                 return CS_FAIL;
     718             :                 break;
     719          48 :         case TDS_CONVERT_OVERFLOW:
     720          48 :                 _csclient_msg(ctx, "cs_convert", 2, 4, 1, 20, "");
     721          48 :                 return CS_FAIL;
     722             :                 break;
     723             :         case TDS_CONVERT_FAIL:
     724             :                 return CS_FAIL;
     725             :                 break;
     726        2829 :         default:
     727        2829 :                 if (len < 0) {
     728             :                         return CS_FAIL;
     729             :                 }
     730             :                 break;
     731             :         }
     732             : 
     733        2829 :         switch (desttype) {
     734          16 :         case SYBBINARY:
     735             :         case SYBVARBINARY:
     736             :         case SYBIMAGE:
     737          16 :                 ret = CS_SUCCEED;
     738          16 :                 if (len > destlen) {
     739           8 :                         tdsdump_log(TDS_DBG_FUNC, "error_handler: Data-conversion resulted in overflow\n");
     740             :                         ret = CS_FAIL;
     741             :                         len = destlen;
     742             :                 }
     743          16 :                 memcpy(dest, cres.ib, len);
     744          16 :                 free(cres.ib);
     745          16 :                 *resultlen = destlen;
     746          16 :                 if (destvc) {
     747           0 :                         destvc->len = len;
     748           0 :                         *resultlen = sizeof(*destvc);
     749             :                 }
     750          16 :                 memset(dest + len, '\0', destlen - len);
     751          16 :                 break;
     752         972 :         case SYBBIT:
     753             :         case SYBBITN:
     754             :                 /* fall trough, act same way of TINYINT */
     755             :         case SYBINT1:
     756             :         case SYBUINT1:
     757             :         case SYBINT2:
     758             :         case SYBUINT2:
     759             :         case SYBINT4:
     760             :         case SYBUINT4:
     761             :         case SYBINT8:
     762             :         case SYBUINT8:
     763             :         case SYBFLT8:
     764             :         case SYBREAL:
     765             :         case SYBMONEY:
     766             :         case SYBMONEY4:
     767             :         case SYBDATETIME:
     768             :         case SYBDATETIME4:
     769             :         case SYBTIME:
     770             :         case SYBDATE:
     771             :         case SYBUNIQUE:
     772             :         case SYB5BIGDATETIME:
     773             :         case SYB5BIGTIME:
     774         972 :                 *resultlen = tds_get_size_by_type(desttype);
     775         972 :                 memcpy(dest, &(cres.ti), *resultlen);
     776         972 :                 ret = CS_SUCCEED;
     777         972 :                 break;
     778         160 :         case SYBNUMERIC:
     779             :         case SYBDECIMAL:
     780         160 :                 src_len = tds_numeric_bytes_per_prec[cres.n.precision] + 2;
     781         160 :                 memcpy(dest, &(cres.n), src_len);
     782         160 :                 *resultlen = src_len;
     783         160 :                 ret = CS_SUCCEED;
     784         160 :                 break;
     785        1681 :         case SYBCHAR:
     786             :         case SYBVARCHAR:
     787             :         case SYBTEXT:
     788        1681 :                 ret = CS_SUCCEED;
     789        1681 :                 if (len > destlen) {
     790           8 :                         tdsdump_log(TDS_DBG_FUNC, "Data-conversion resulted in overflow\n");
     791             :                         len = destlen;
     792             :                         ret = CS_FAIL;
     793             :                 }
     794        1681 :                 switch (destfmt->format) {
     795             : 
     796        1629 :                 case CS_FMT_NULLTERM:
     797        1629 :                         tdsdump_log(TDS_DBG_FUNC, "cs_convert() FMT_NULLTERM\n");
     798        1629 :                         if (len == destlen) {
     799           0 :                                 tdsdump_log(TDS_DBG_FUNC, "not enough room for data + a null terminator - error\n");
     800             :                                 ret = CS_FAIL;  /* not enough room for data + a null terminator - error */
     801             :                         } else {
     802        1629 :                                 memcpy(dest, cres.c, len);
     803        1629 :                                 dest[len] = 0;
     804        1629 :                                 *resultlen = len + 1;
     805             :                         }
     806             :                         break;
     807             : 
     808           0 :                 case CS_FMT_PADBLANK:
     809           0 :                         tdsdump_log(TDS_DBG_FUNC, "cs_convert() FMT_PADBLANK\n");
     810             :                         /* strcpy here can lead to a small buffer overflow */
     811           0 :                         memcpy(dest, cres.c, len);
     812           0 :                         memset(dest + len, ' ', destlen - len);
     813           0 :                         *resultlen = destlen;
     814           0 :                         break;
     815             : 
     816           0 :                 case CS_FMT_PADNULL:
     817           0 :                         tdsdump_log(TDS_DBG_FUNC, "cs_convert() FMT_PADNULL\n");
     818             :                         /* strcpy here can lead to a small buffer overflow */
     819           0 :                         memcpy(dest, cres.c, len);
     820           0 :                         memset(dest + len, '\0', destlen - len);
     821           0 :                         *resultlen = destlen;
     822           0 :                         break;
     823          52 :                 case CS_FMT_UNUSED:
     824          52 :                         tdsdump_log(TDS_DBG_FUNC, "cs_convert() FMT_UNUSED\n");
     825          52 :                         memcpy(dest, cres.c, len);
     826          52 :                         *resultlen = len;
     827          52 :                         break;
     828             :                 default:
     829             :                         ret = CS_FAIL;
     830             :                         break;
     831             :                 }
     832        1681 :                 if (destvc) {
     833           8 :                         destvc->len = len;
     834           8 :                         *resultlen = sizeof(*destvc);
     835             :                 }
     836        1681 :                 free(cres.c);
     837        1681 :                 break;
     838             :         default:
     839             :                 ret = CS_FAIL;
     840             :                 break;
     841             :         }
     842        2829 :         tdsdump_log(TDS_DBG_FUNC, "cs_convert() returning  %s\n", cs_prretcode(ret));
     843             :         return (ret);
     844             : }
     845             : 
     846             : CS_RETCODE
     847         448 : cs_convert(CS_CONTEXT * ctx, CS_DATAFMT * srcfmt, CS_VOID * srcdata, CS_DATAFMT * destfmt, CS_VOID * destdata, CS_INT * resultlen)
     848             : {
     849         448 :         return _cs_convert(ctx, _ct_datafmt_common(ctx, srcfmt), srcdata,
     850             :                            _ct_datafmt_common(ctx, destfmt), destdata, resultlen);
     851             : }
     852             : 
     853             : CS_RETCODE
     854           0 : cs_dt_crack_v2(CS_CONTEXT * ctx, CS_INT datetype, CS_VOID * dateval, CS_DATEREC * daterec)
     855             : {
     856             :         TDSDATEREC dr;
     857             :         TDS_INT tds_type;
     858           0 :         bool extended = false;
     859             : 
     860           0 :         tdsdump_log(TDS_DBG_FUNC, "cs_dt_crack_v2(%p, %d, %p, %p)\n", ctx, datetype, dateval, daterec);
     861             : 
     862           0 :         switch (datetype) {
     863             :         case CS_DATETIME_TYPE:
     864             :                 tds_type = SYBDATETIME;
     865             :                 break;
     866           0 :         case CS_DATETIME4_TYPE:
     867           0 :                 tds_type = SYBDATETIME4;
     868           0 :                 break;
     869           0 :         case CS_DATE_TYPE:
     870           0 :                 tds_type = SYBDATE;
     871           0 :                 break;
     872           0 :         case CS_TIME_TYPE:
     873           0 :                 tds_type = SYBTIME;
     874           0 :                 break;
     875           0 :         case CS_BIGDATETIME_TYPE:
     876           0 :                 tds_type = SYB5BIGDATETIME;
     877           0 :                 extended = true;
     878           0 :                 break;
     879           0 :         case CS_BIGTIME_TYPE:
     880           0 :                 tds_type = SYB5BIGTIME;
     881           0 :                 extended = true;
     882           0 :                 break;
     883             :         default:
     884             :                 return CS_FAIL;
     885             :         }
     886           0 :         tds_datecrack(tds_type, dateval, &dr);
     887             : 
     888             :         /* Sybase CT-Library does not set these fields for CS_BIGTIME_TYPE */
     889           0 :         if (tds_type != SYB5BIGTIME) {
     890           0 :                 daterec->dateyear = dr.year;
     891           0 :                 daterec->datemonth = dr.month;
     892           0 :                 daterec->datedmonth = dr.day;
     893           0 :                 daterec->datedyear = dr.dayofyear;
     894           0 :                 daterec->datedweek = dr.weekday;
     895             :         }
     896           0 :         daterec->datehour = dr.hour;
     897           0 :         daterec->dateminute = dr.minute;
     898           0 :         daterec->datesecond = dr.second;
     899           0 :         daterec->datemsecond = dr.decimicrosecond / 10000u;
     900           0 :         daterec->datetzone = 0;
     901           0 :         if (extended) {
     902           0 :                 daterec->datesecfrac = dr.decimicrosecond / 10u;
     903           0 :                 daterec->datesecprec = 1000000;
     904             :         }
     905             : 
     906             :         return CS_SUCCEED;
     907             : }
     908             : 
     909             : CS_RETCODE
     910           0 : cs_dt_crack(CS_CONTEXT * ctx, CS_INT datetype, CS_VOID * dateval, CS_DATEREC * daterec)
     911             : {
     912           0 :         tdsdump_log(TDS_DBG_FUNC, "cs_dt_crack(%p, %d, %p, %p)\n", ctx, datetype, dateval, daterec);
     913             : 
     914           0 :         if (datetype != CS_BIGDATETIME_TYPE && datetype != CS_BIGTIME_TYPE)
     915           0 :                 return cs_dt_crack_v2(ctx, datetype, dateval, daterec);
     916             :         return CS_FAIL;
     917             : }
     918             : 
     919             : CS_RETCODE
     920           0 : cs_loc_alloc(CS_CONTEXT * ctx, CS_LOCALE ** locptr)
     921             : {
     922             :         CS_LOCALE *tds_csloc;
     923             : 
     924           0 :         tdsdump_log(TDS_DBG_FUNC, "cs_loc_alloc(%p, %p)\n", ctx, locptr);
     925             : 
     926           0 :         tds_csloc = _cs_locale_alloc();
     927           0 :         if (!tds_csloc)
     928             :                 return CS_FAIL;
     929             : 
     930           0 :         *locptr = tds_csloc;
     931           0 :         return CS_SUCCEED;
     932             : }
     933             : 
     934             : CS_RETCODE
     935           0 : cs_loc_drop(CS_CONTEXT * ctx, CS_LOCALE * locale)
     936             : {
     937           0 :         tdsdump_log(TDS_DBG_FUNC, "cs_loc_drop(%p, %p)\n", ctx, locale);
     938             : 
     939           0 :         if (!locale)
     940             :                 return CS_FAIL;
     941             : 
     942           0 :         _cs_locale_free(locale);
     943           0 :         return CS_SUCCEED;
     944             : }
     945             : 
     946             : CS_RETCODE
     947           0 : cs_locale(CS_CONTEXT * ctx, CS_INT action, CS_LOCALE * locale, CS_INT type, CS_VOID * buffer, CS_INT buflen, CS_INT * outlen)
     948             : {
     949           0 :         CS_RETCODE code = CS_FAIL;
     950             : 
     951           0 :         tdsdump_log(TDS_DBG_FUNC, "cs_locale(%p, %d, %p, %d, %p, %d, %p)\n", ctx, action, locale, type, buffer, buflen, outlen);
     952             : 
     953           0 :         if (action == CS_SET) {
     954           0 :                 switch (type) {
     955           0 :                 case CS_LC_ALL:
     956             :                         /* what to do here if there is locale data? */
     957           0 :                         if (!buffer) {
     958           0 :                                 code = CS_SUCCEED;
     959             :                         }
     960             :                         break;
     961             : 
     962           0 :                 case CS_SYB_CHARSET:
     963           0 :                         if (buflen == CS_NULLTERM) {
     964           0 :                                 buflen = strlen((char *)buffer);
     965             :                         }
     966             :                         
     967           0 :                         free(locale->charset);
     968           0 :                         locale->charset = tds_strndup(buffer, buflen);
     969           0 :                         if (!locale->charset)
     970             :                                 break;
     971             : 
     972           0 :                         code = CS_SUCCEED;
     973           0 :                         break;
     974             : 
     975           0 :                 case CS_SYB_LANG:
     976           0 :                         if (buflen == CS_NULLTERM) {
     977           0 :                                 buflen = strlen((char *)buffer);
     978             :                         }
     979             :                         
     980           0 :                         free(locale->language);
     981           0 :                         locale->language = tds_strndup(buffer, buflen);
     982           0 :                         if (!locale->language)
     983             :                                 break;
     984             : 
     985           0 :                         code = CS_SUCCEED;
     986           0 :                         break;
     987             : 
     988           0 :                 case CS_SYB_LANG_CHARSET:
     989             :                 {
     990             :                         int i;
     991           0 :                         char *b = (char *)buffer;
     992             : 
     993           0 :                         if (buflen == CS_NULLTERM) {
     994           0 :                                 buflen = strlen(b);
     995             :                         }
     996             : 
     997             :                         /* find '.' character */
     998           0 :                         for (i = 0; i < buflen; ++i) {
     999           0 :                                 if (b[i] == '.') {
    1000             :                                         break;
    1001             :                                 }                                       
    1002             :                         }
    1003             :                         /* not found */
    1004           0 :                         if (i == buflen) {
    1005             :                                 break;
    1006             :                         }
    1007           0 :                         if (i) {
    1008           0 :                                 free(locale->language);
    1009           0 :                                 locale->language = tds_strndup(b, i);
    1010           0 :                                 if (!locale->language)
    1011             :                                         break;
    1012             :                         }
    1013           0 :                         if (i != (buflen - 1)) {
    1014           0 :                                 free(locale->charset);
    1015           0 :                                 locale->charset = tds_strndup(b + i + 1, buflen - i - 1);
    1016           0 :                                 if (!locale->charset)
    1017             :                                         break;
    1018             :                         }
    1019             :                         code = CS_SUCCEED;
    1020             :                         break;
    1021             :                 }
    1022             : 
    1023             :                 /* TODO commented out until the code works end-to-end
    1024             :                 case CS_SYB_SORTORDER:
    1025             :                         if (buflen == CS_NULLTERM) {
    1026             :                                 buflen = strlen((char *)buffer);
    1027             :                         }
    1028             :                         
    1029             :                         free(locale->collate);
    1030             :                         locale->collate = tds_strndup(buffer, buflen);
    1031             :                         if (!locale->collate)
    1032             :                                 break;
    1033             : 
    1034             :                         code = CS_SUCCEED;
    1035             :                         break;
    1036             :                 */
    1037             :                 }
    1038             :         }
    1039           0 :         else if (action == CS_GET)
    1040             :         {
    1041             :                 int tlen;
    1042             : 
    1043           0 :                 switch (type) {
    1044           0 :                 case CS_SYB_CHARSET:
    1045           0 :                         tlen = (locale->charset ? strlen(locale->charset) : 0) + 1;
    1046           0 :                         if (buflen < tlen)
    1047             :                         {
    1048           0 :                                 if (outlen)
    1049           0 :                                         *outlen = tlen;
    1050             :                                 break;
    1051             :                         }
    1052           0 :                         if (locale->charset)
    1053           0 :                                 strcpy((char *)buffer, locale->charset);
    1054             :                         else
    1055           0 :                                 ((char *)buffer)[0] = '\0';
    1056             :                         code = CS_SUCCEED;
    1057             :                         break;
    1058             : 
    1059           0 :                 case CS_SYB_LANG:
    1060           0 :                         tlen = (locale->language ? strlen(locale->language) : 0) + 1;
    1061           0 :                         if (buflen < tlen)
    1062             :                         {
    1063           0 :                                 if (outlen)
    1064           0 :                                         *outlen = tlen;
    1065             :                                 break;
    1066             :                         }
    1067           0 :                         if (locale->language)
    1068           0 :                                 strcpy((char *)buffer, locale->language);
    1069             :                         else
    1070           0 :                                 ((char *)buffer)[0] = '\0';
    1071             :                         code = CS_SUCCEED;
    1072             :                         break;
    1073             : 
    1074           0 :                 case CS_SYB_LANG_CHARSET:
    1075             :                 {
    1076             :                         int clen;
    1077             : 
    1078           0 :                         tlen = (locale->language ? strlen(locale->language) : 0) + 1;
    1079           0 :                         clen = (locale->charset ? strlen(locale->charset) : 0) + 1;
    1080             :                         
    1081           0 :                         if (buflen < (tlen + clen))
    1082             :                         {
    1083           0 :                                 if (outlen)
    1084           0 :                                         *outlen = tlen + clen;
    1085             :                                 break;
    1086             :                         }
    1087           0 :                         if (locale->language)
    1088           0 :                                 strcpy((char *)buffer, locale->language);
    1089             :                         else
    1090           0 :                                 ((char *)buffer)[0] = '\0';
    1091           0 :                         strcat((char *)buffer, ".");
    1092           0 :                         if (locale->charset) {
    1093           0 :                                 tlen = strlen((char *)buffer);
    1094           0 :                                 strcpy((char *)buffer + tlen, locale->charset);
    1095             :                         }
    1096             :                         code = CS_SUCCEED;
    1097             :                         break;
    1098             :                 }
    1099             : 
    1100           0 :                 case CS_SYB_SORTORDER:
    1101           0 :                         tlen = (locale->collate ? strlen(locale->collate) : 0) + 1;
    1102           0 :                         if (buflen < tlen)
    1103             :                         {
    1104           0 :                                 if (outlen)
    1105           0 :                                         *outlen = tlen;
    1106             :                                 break;
    1107             :                         }
    1108           0 :                         if (locale->collate)
    1109           0 :                                 strcpy((char *)buffer, locale->collate);
    1110             :                         else
    1111           0 :                                 ((char *)buffer)[0] = '\0';
    1112             :                         code = CS_SUCCEED;
    1113             :                         break;
    1114             :                 }
    1115             :         }
    1116           0 :         return code;
    1117             : }
    1118             : 
    1119             : CS_RETCODE
    1120           0 : cs_dt_info(CS_CONTEXT * ctx, CS_INT action, CS_LOCALE * locale, CS_INT type, CS_INT item, CS_VOID * buffer, CS_INT buflen,
    1121             :            CS_INT * outlen)
    1122             : {
    1123           0 :         tdsdump_log(TDS_DBG_FUNC, "cs_dt_info(%p, %d, %p, %d, %d, %p, %d, %p)\n", 
    1124             :                                 ctx, action, locale, type, item, buffer, buflen, outlen);
    1125             : 
    1126             :         if (action == CS_SET) {
    1127             :                 switch (type) {
    1128             :                 case CS_DT_CONVFMT:
    1129             :                         break;
    1130             :                 }
    1131             :         }
    1132           0 :         return CS_SUCCEED;
    1133             : }
    1134             : 
    1135             : CS_RETCODE
    1136           0 : cs_strbuild(CS_CONTEXT * ctx, CS_CHAR * buffer, CS_INT buflen, CS_INT * resultlen, CS_CHAR * text, CS_INT textlen,
    1137             :             CS_CHAR * formats, CS_INT formatlen, ...)
    1138             : {
    1139             :         va_list ap;
    1140             :         TDSRET rc;
    1141             : 
    1142           0 :         tdsdump_log(TDS_DBG_FUNC, "cs_strbuild(%p, %p, %d, %p, %p, %d, %p, %d)\n", 
    1143             :                                 ctx, buffer, buflen, resultlen, text, textlen, formats, formatlen);
    1144             : 
    1145           0 :         va_start(ap, formatlen);
    1146           0 :         rc = tds_vstrbuild(buffer, buflen, resultlen, text, textlen, formats, formatlen, ap);
    1147           0 :         va_end(ap);
    1148             : 
    1149           0 :         return TDS_SUCCEED(rc) ? CS_SUCCEED : CS_FAIL;
    1150             : }
    1151             : 
    1152             : CS_RETCODE
    1153           0 : cs_calc(CS_CONTEXT * ctx, CS_INT op, CS_INT datatype, CS_VOID * var1, CS_VOID * var2, CS_VOID * dest)
    1154             : {
    1155             : 
    1156           0 :         tdsdump_log(TDS_DBG_FUNC, "cs_calc(%p, %d, %d, %p, %p, %p)\n", ctx, op, datatype, var1, var2, dest);
    1157             : 
    1158           0 :         tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED cs_calc()\n");
    1159           0 :         return CS_FAIL;
    1160             : }
    1161             : 
    1162             : CS_RETCODE
    1163           0 : cs_cmp(CS_CONTEXT * ctx, CS_INT datatype, CS_VOID * var1, CS_VOID * var2, CS_INT * result)
    1164             : {
    1165             : 
    1166           0 :         tdsdump_log(TDS_DBG_FUNC, "cs_cmp(%p, %d, %p, %p, %p)\n", ctx, datatype, var1, var2, result);
    1167             : 
    1168           0 :         tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED cs_cmp()\n");
    1169           0 :         return CS_FAIL;
    1170             : }
    1171             : 
    1172             : CS_RETCODE
    1173           0 : cs_conv_mult(CS_CONTEXT * ctx, CS_LOCALE * srcloc, CS_LOCALE * destloc, CS_INT * conv_multiplier)
    1174             : {
    1175             : 
    1176           0 :         tdsdump_log(TDS_DBG_FUNC, "cs_conv_mult(%p, %p, %p, %p)\n", ctx, srcloc, destloc, conv_multiplier);
    1177             : 
    1178           0 :         tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED cs_conv_mult()\n");
    1179           0 :         return CS_FAIL;
    1180             : }
    1181             : 
    1182             : CS_RETCODE
    1183          56 : cs_diag(CS_CONTEXT * ctx, CS_INT operation, CS_INT type, CS_INT idx, CS_VOID * buffer)
    1184             : {
    1185          56 :         tdsdump_log(TDS_DBG_FUNC, "cs_diag(%p, %d, %d, %d, %p)\n", ctx, operation, type, idx, buffer);
    1186             : 
    1187          56 :         switch (operation) {
    1188             : 
    1189           8 :                 case CS_INIT:
    1190           8 :                         if ( ctx->cs_errhandletype == _CS_ERRHAND_CB) {
    1191             :                                 /* contrary to the manual page you don't seem to */
    1192             :                                 /* be able to turn on inline message handling    */
    1193             :                                 /* using cs_diag, once a callback is installed!  */
    1194             :                                 return CS_FAIL;
    1195             :                         }
    1196           8 :                         ctx->cs_errhandletype = _CS_ERRHAND_INLINE;
    1197           8 :                         ctx->cs_diag_msglimit = CS_NO_LIMIT;
    1198           8 :                         ctx->_cslibmsg_cb = (CS_CSLIBMSG_FUNC) cs_diag_storemsg; 
    1199           8 :                         break;
    1200           0 :                 case CS_MSGLIMIT:
    1201           0 :                         if ( ctx->cs_errhandletype != _CS_ERRHAND_INLINE) {
    1202             :                                 return CS_FAIL;
    1203             :                         }
    1204           0 :                         ctx->cs_diag_msglimit = *(CS_INT *)buffer;
    1205           0 :                         break;
    1206           8 :                 case CS_CLEAR:
    1207           8 :                         if ( ctx->cs_errhandletype != _CS_ERRHAND_INLINE) {
    1208             :                                 return CS_FAIL;
    1209             :                         }
    1210           8 :                         return (cs_diag_clearmsg(ctx, type));
    1211             : 
    1212             :                         break;
    1213          24 :                 case CS_GET:
    1214          24 :                         if ( ctx->cs_errhandletype != _CS_ERRHAND_INLINE) {
    1215             :                                 return CS_FAIL;
    1216             :                         }
    1217          24 :                         if (buffer == NULL)
    1218             :                                 return CS_FAIL;
    1219             : 
    1220          24 :                         if (idx == 0 || (ctx->cs_diag_msglimit != CS_NO_LIMIT && idx > ctx->cs_diag_msglimit) )
    1221             :                                 return CS_FAIL;
    1222             : 
    1223          24 :                         return (cs_diag_getmsg(ctx, idx, (CS_CLIENTMSG *)buffer)); 
    1224             :                         
    1225             :                         break;
    1226          16 :                 case CS_STATUS:
    1227          16 :                         if ( ctx->cs_errhandletype != _CS_ERRHAND_INLINE) {
    1228             :                                 return CS_FAIL;
    1229             :                         }
    1230          16 :                         if (buffer == NULL) 
    1231             :                                 return CS_FAIL;
    1232             : 
    1233          16 :                         return (cs_diag_countmsg(ctx, (CS_INT *)buffer));
    1234             :                         break;
    1235             :         }
    1236             :         return CS_SUCCEED;
    1237             :                 
    1238             : }
    1239             : 
    1240             : CS_RETCODE
    1241           0 : cs_manage_convert(CS_CONTEXT * ctx, CS_INT action, CS_INT srctype, CS_CHAR * srcname, CS_INT srcnamelen, CS_INT desttype,
    1242             :                   CS_CHAR * destname, CS_INT destnamelen, CS_INT * conv_multiplier, CS_CONV_FUNC * func)
    1243             : {
    1244             : 
    1245           0 :         tdsdump_log(TDS_DBG_FUNC, "cs_manage_convert(%p, %d, %d, %p, %d, %d, %p, %d, %p, %p)\n", 
    1246             :                                 ctx, action, srctype, srcname, srcnamelen, desttype, destname, destnamelen, conv_multiplier, func);
    1247             : 
    1248           0 :         tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED cs_manage_convert()\n");
    1249           0 :         return CS_FAIL;
    1250             : }
    1251             : 
    1252             : CS_RETCODE
    1253           0 : cs_objects(CS_CONTEXT * ctx, CS_INT action, CS_OBJNAME * objname, CS_OBJDATA * objdata)
    1254             : {
    1255             : 
    1256           0 :         tdsdump_log(TDS_DBG_FUNC, "cs_objects(%p, %d, %p, %p)\n", ctx, action, objname, objdata);
    1257             : 
    1258           0 :         tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED cs_objects()\n");
    1259           0 :         return CS_FAIL;
    1260             : }
    1261             : 
    1262             : CS_RETCODE
    1263           0 : cs_set_convert(CS_CONTEXT * ctx, CS_INT action, CS_INT srctype, CS_INT desttype, CS_CONV_FUNC * func)
    1264             : {
    1265             : 
    1266           0 :         tdsdump_log(TDS_DBG_FUNC, "cs_set_convert(%p, %d, %d, %d, %p)\n", ctx, action, srctype, desttype, func);
    1267             : 
    1268           0 :         tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED cs_set_convert()\n");
    1269           0 :         return CS_FAIL;
    1270             : }
    1271             : 
    1272             : CS_RETCODE
    1273           0 : cs_setnull(CS_CONTEXT * ctx, CS_DATAFMT * datafmt, CS_VOID * buffer, CS_INT buflen)
    1274             : {
    1275             : 
    1276           0 :         tdsdump_log(TDS_DBG_FUNC, "cs_setnull(%p, %p, %p, %d)\n", ctx, datafmt, buffer, buflen);
    1277             : 
    1278           0 :         tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED cs_setnull()\n");
    1279           0 :         return CS_FAIL;
    1280             : }
    1281             : 
    1282             : CS_RETCODE
    1283           0 : cs_strcmp(CS_CONTEXT * ctx, CS_LOCALE * locale, CS_INT type, CS_CHAR * str1, CS_INT len1, CS_CHAR * str2, CS_INT len2,
    1284             :           CS_INT * result)
    1285             : {
    1286             : 
    1287           0 :         tdsdump_log(TDS_DBG_FUNC, "cs_strcmp(%p, %p, %d, %p, %d, %p, %d, %p)\n", 
    1288             :                                         ctx, locale, type, str1, len1, str2, len2, result);
    1289             : 
    1290           0 :         tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED cs_strcmp()\n");
    1291           0 :         return CS_FAIL;
    1292             : }
    1293             : 
    1294             : CS_RETCODE
    1295           0 : cs_time(CS_CONTEXT * ctx, CS_LOCALE * locale, CS_VOID * buffer, CS_INT buflen, CS_INT * outlen, CS_DATEREC * daterec)
    1296             : {
    1297             : 
    1298           0 :         tdsdump_log(TDS_DBG_FUNC, "cs_time(%p, %p, %p, %d, %p, %p)\n", ctx, locale, buffer, buflen, outlen, daterec);
    1299             : 
    1300           0 :         tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED cs_time()\n");
    1301           0 :         return CS_FAIL;
    1302             : }
    1303             : 
    1304             : CS_RETCODE
    1305      748240 : cs_will_convert(CS_CONTEXT * ctx, CS_INT srctype, CS_INT desttype, CS_BOOL * result)
    1306             : {
    1307             : 
    1308      748240 :         tdsdump_log(TDS_DBG_FUNC, "cs_will_convert(%p, %d, %d, %p)\n", ctx, srctype, desttype, result);
    1309             : 
    1310      748240 :         srctype = _ct_get_server_type(NULL, srctype);
    1311      748240 :         desttype = _ct_get_server_type(NULL, desttype);
    1312      748240 :         *result = (tds_willconvert(srctype, desttype) ? CS_TRUE : CS_FALSE);
    1313      748240 :         return CS_SUCCEED;
    1314             : }
    1315             : 
    1316             : static CS_INT 
    1317          16 : cs_diag_storemsg(CS_CONTEXT *context, CS_CLIENTMSG *message)
    1318             : {
    1319             :         struct cs_diag_msg **curptr;
    1320          16 :         CS_INT msg_count = 0;
    1321             : 
    1322          16 :         tdsdump_log(TDS_DBG_FUNC, "cs_diag_storemsg(%p, %p)\n", context, message);
    1323             : 
    1324          16 :         curptr = &(context->msgstore);
    1325             : 
    1326             :         /* if we already have a list of messages, */
    1327             :         /* go to the end of the list...           */
    1328             : 
    1329          40 :         while (*curptr != NULL) {
    1330           8 :                 msg_count++;
    1331           8 :                 curptr = &((*curptr)->next);
    1332             :         }
    1333             : 
    1334             :         /* messages over and above the agreed limit */
    1335             :         /* are simply discarded...                  */
    1336             : 
    1337          16 :         if (context->cs_diag_msglimit != CS_NO_LIMIT &&
    1338             :                 msg_count >= context->cs_diag_msglimit) {
    1339             :                 return CS_FAIL;
    1340             :         }
    1341             : 
    1342          16 :         *curptr = tds_new(struct cs_diag_msg, 1);
    1343          16 :         if (*curptr == NULL) { 
    1344             :                 return CS_FAIL;
    1345             :         } else {
    1346          16 :                 (*curptr)->next = NULL;
    1347          16 :                 (*curptr)->msg  = tds_new(CS_CLIENTMSG, 1);
    1348          16 :                 if ((*curptr)->msg == NULL) {
    1349             :                         return CS_FAIL;
    1350             :                 } else {
    1351          16 :                         memcpy((*curptr)->msg, message, sizeof(CS_CLIENTMSG));
    1352             :                 }
    1353             :         }
    1354             : 
    1355          16 :         return CS_SUCCEED;
    1356             : }
    1357             : 
    1358             : static CS_INT 
    1359          24 : cs_diag_getmsg(CS_CONTEXT *context, CS_INT idx, CS_CLIENTMSG *message)
    1360             : {
    1361             :         struct cs_diag_msg *curptr;
    1362          24 :         CS_INT msg_count = 0, msg_found = 0;
    1363             : 
    1364          24 :         tdsdump_log(TDS_DBG_FUNC, "cs_diag_getmsg(%p, %d, %p)\n", context, idx, message);
    1365             : 
    1366          24 :         curptr = context->msgstore;
    1367             : 
    1368             :         /* if we already have a list of messages, */
    1369             :         /* go to the end of the list...           */
    1370             : 
    1371          72 :         while (curptr != NULL) {
    1372          40 :                 msg_count++;
    1373          40 :                 if (msg_count == idx) {
    1374             :                         msg_found++;
    1375             :                         break;
    1376             :                 }
    1377          24 :                 curptr = curptr->next;
    1378             :         }
    1379          24 :         if (msg_found) {
    1380          16 :                 memcpy(message, curptr->msg, sizeof(CS_CLIENTMSG));
    1381          16 :                 return CS_SUCCEED;
    1382             :         } else {
    1383             :                 return CS_NOMSG;
    1384             :         }
    1385             : }
    1386             : 
    1387             : static CS_INT 
    1388           8 : cs_diag_clearmsg(CS_CONTEXT *context, CS_INT type)
    1389             : {
    1390             :         struct cs_diag_msg *curptr, *freeptr;
    1391             : 
    1392           8 :         tdsdump_log(TDS_DBG_FUNC, "cs_diag_clearmsg(%p, %d)\n", context, type);
    1393             : 
    1394           8 :         curptr = context->msgstore;
    1395           8 :         context->msgstore = NULL;
    1396             : 
    1397          32 :         while (curptr != NULL ) {
    1398          16 :                 freeptr = curptr;
    1399          16 :                 curptr = freeptr->next;
    1400          16 :                 free(freeptr->msg);
    1401          16 :                 free(freeptr);
    1402             :         }
    1403           8 :         return CS_SUCCEED;
    1404             : }
    1405             : 
    1406             : static CS_INT 
    1407          16 : cs_diag_countmsg(CS_CONTEXT *context, CS_INT *count)
    1408             : {
    1409             :         struct cs_diag_msg *curptr;
    1410          16 :         CS_INT msg_count = 0;
    1411             : 
    1412          16 :         tdsdump_log(TDS_DBG_FUNC, "cs_diag_countmsg(%p, %p)\n", context, count);
    1413             : 
    1414          16 :         curptr = context->msgstore;
    1415             : 
    1416          48 :         while (curptr != NULL) {
    1417          16 :                 msg_count++;
    1418          16 :                 curptr = curptr->next;
    1419             :         }
    1420          16 :         *count = msg_count;
    1421          16 :         return CS_SUCCEED;
    1422             : }
    1423             : 
    1424             : /**
    1425             :  * Try to convert to a type we can handle
    1426             :  */
    1427             : int
    1428        4395 : _cs_convert_not_client(CS_CONTEXT *ctx, const TDSCOLUMN *curcol, CONV_RESULT *convert_buffer, unsigned char **p_src)
    1429             : {
    1430             :         int ct_type;
    1431        4395 :         TDS_SERVER_TYPE desttype, type = curcol->column_type;
    1432             : 
    1433        4395 :         if (type == SYBVARIANT)
    1434         442 :                 type = ((const TDSVARIANT *) curcol->column_data)->type;
    1435             : 
    1436        4395 :         switch (type) {
    1437             :         case SYBMSDATE:
    1438             :                 desttype = SYBDATE;
    1439             :                 ct_type = CS_DATE_TYPE;
    1440             :                 break;
    1441          32 :         case SYBMSTIME:
    1442          32 :                 desttype = SYB5BIGTIME;
    1443          32 :                 ct_type = CS_BIGTIME_TYPE;
    1444          32 :                 break;
    1445          64 :         case SYBMSDATETIME2:
    1446             :         case SYBMSDATETIMEOFFSET:
    1447          64 :                 desttype = SYB5BIGDATETIME;
    1448          64 :                 ct_type = CS_BIGDATETIME_TYPE;
    1449          64 :                 break;
    1450             :         default:
    1451             :                 return CS_ILLEGAL_TYPE;
    1452             :         }
    1453             : 
    1454         128 :         if (convert_buffer) {
    1455         128 :                 int len = tds_convert(ctx->tds_ctx, type, *p_src,
    1456          64 :                                       curcol->column_cur_size, desttype, convert_buffer);
    1457          64 :                 if (len < 0)
    1458             :                         return CS_ILLEGAL_TYPE; /* TODO _csclient_msg ?? */
    1459          64 :                 *p_src = (unsigned char *) convert_buffer;
    1460             :         }
    1461             :         return ct_type;
    1462             : }

Generated by: LCOV version 1.13