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

Generated by: LCOV version 1.13