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 : }
|