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