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) 2010, 2011  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 #include <stdio.h>
25 #include <assert.h>
26 
27 #if HAVE_STRING_H
28 #include <string.h>
29 #endif /* HAVE_STRING_H */
30 
31 #if HAVE_STDLIB_H
32 #include <stdlib.h>
33 #endif /* HAVE_STDLIB_H */
34 
35 #if HAVE_UNISTD_H
36 #include <unistd.h>
37 #endif /* HAVE_UNISTD_H */
38 
39 #ifdef _WIN32
40 #include <io.h>
41 #endif
42 
43 #include <freetds/tds.h>
44 #include <freetds/iconv.h>
45 #include <freetds/convert.h>
46 #include <freetds/bytes.h>
47 #include <freetds/utils/string.h>
48 #include <freetds/encodings.h>
49 #include <freetds/replacements.h>
50 #include <sybfront.h>
51 #include <sybdb.h>
52 #include <syberror.h>
53 #include <dblib.h>
54 
55 #define HOST_COL_CONV_ERROR 1
56 #define HOST_COL_NULL_ERROR 2
57 
58 #ifndef MAX
59 #define MAX(a,b) ( (a) > (b) ? (a) : (b) )
60 #endif
61 
62 #ifdef HAVE_FSEEKO
63 typedef off_t offset_type;
64 #elif defined(_WIN32) || defined(_WIN64)
65 /* win32 version */
66 typedef __int64 offset_type;
67 # if defined(HAVE__FSEEKI64) && defined(HAVE__FTELLI64)
68 #  define fseeko(f,o,w) _fseeki64((f),o,w)
69 #  define ftello(f) _ftelli64((f))
70 # else
71 #  define fseeko(f,o,w) (_lseeki64(fileno(f),o,w) == -1 ? -1 : 0)
72 #  define ftello(f) _telli64(fileno(f))
73 # endif
74 #else
75 /* use old version */
76 #define fseeko(f,o,w) fseek(f,o,w)
77 #define ftello(f) ftell(f)
78 typedef long offset_type;
79 #endif
80 
81 static void _bcp_free_storage(DBPROCESS * dbproc);
82 static void _bcp_free_columns(DBPROCESS * dbproc);
83 static void _bcp_null_error(TDSBCPINFO *bcpinfo, int index, int offset);
84 static TDSRET _bcp_get_col_data(TDSBCPINFO *bcpinfo, TDSCOLUMN *bindcol, int offset);
85 static TDSRET _bcp_no_get_col_data(TDSBCPINFO *bcpinfo, TDSCOLUMN *bindcol, int offset);
86 
87 static int rtrim(char *, int);
88 static int rtrim_u16(uint16_t *str, int len, uint16_t space);
89 static STATUS _bcp_read_hostfile(DBPROCESS * dbproc, FILE * hostfile, int *row_error, bool skip);
90 static int _bcp_readfmt_colinfo(DBPROCESS * dbproc, char *buf, BCP_HOSTCOLINFO * ci);
91 static int _bcp_get_term_var(const BYTE * pdata, const BYTE * term, int term_len);
92 
93 /*
94  * "If a host file is being used ... the default data formats are as follows:
95  *
96  *  > The order, type, length and number of the columns in the host file are
97  *    assumed to be identical to the order, type and number of the columns in the database table.
98  *  > If a given database column's data is fixed-length,
99  *    then the host file's  data column will also be fixed-length.
100  *  > If a given database column's data is variable-length or may contain null values,
101  *    the host file's data column will be prefixed by
102  *	a 4-byte length value for SYBTEXT and SYBIMAGE data types, and
103  *	a 1-byte length value for all other types.
104  *  > There are no terminators of any kind between host file columns."
105  */
106 
107 static void
init_hostfile_columns(DBPROCESS * dbproc)108 init_hostfile_columns(DBPROCESS *dbproc)
109 {
110 	const int ncols = dbproc->bcpinfo->bindinfo->num_cols;
111 	RETCODE erc;
112 	int icol;
113 
114 	if (ncols == 0)
115 		return;
116 
117 	if ((erc = bcp_columns(dbproc, ncols)) != SUCCEED) {
118 		assert(erc == SUCCEED);
119 		return;
120 	}
121 
122 	for (icol = 0; icol < ncols; icol++) {
123 		const TDSCOLUMN *pcol = dbproc->bcpinfo->bindinfo->columns[icol];
124 		int prefixlen = 0, termlen = 0;
125 
126 		switch (pcol->column_type) {
127 		case SYBTEXT:
128 		case SYBIMAGE:
129 			prefixlen = 4;
130 			break;
131 		default:
132 			prefixlen = dbvarylen(dbproc, icol+1)? 1 : 0;
133 		}
134 
135 		erc = bcp_colfmt(dbproc, icol+1, pcol->column_type, prefixlen, pcol->column_size, NULL, termlen, icol+1);
136 
137 		assert(erc == SUCCEED);
138 		if (erc != SUCCEED)
139 			return;
140 	}
141 }
142 
143 
144 /**
145  * \ingroup dblib_bcp
146  * \brief Prepare for bulk copy operation on a table
147  *
148  * \param dbproc contains all information needed by db-lib to manage communications with the server.
149  * \param tblname the name of the table receiving or providing the data.
150  * \param hfile the data file opposite the table, if any.
151  * \param errfile the "error file" captures messages and, if errors are encountered,
152  * 	copies of any rows that could not be written to the table.
153  * \param direction one of
154  *		- \b DB_IN writing to the table
155  *		- \b DB_OUT writing to the host file
156  * 		.
157  * \remarks bcp_init() sets the host file data format and acquires the table metadata.
158  *	It is called before the other bulk copy functions.
159  *
160  * 	When writing to a table, bcp can use as its data source a data file (\a hfile),
161  * 	or program data in an application's variables.  In the latter case, call bcp_bind()
162  *	to associate your data with the appropriate table column.
163  * \return SUCCEED or FAIL.
164  * \sa 	BCP_SETL(), bcp_bind(), bcp_done(), bcp_exec()
165  */
166 RETCODE
bcp_init(DBPROCESS * dbproc,const char * tblname,const char * hfile,const char * errfile,int direction)167 bcp_init(DBPROCESS * dbproc, const char *tblname, const char *hfile, const char *errfile, int direction)
168 {
169 	tdsdump_log(TDS_DBG_FUNC, "bcp_init(%p, %s, %s, %s, %d)\n",
170 			dbproc, tblname? tblname:"NULL", hfile? hfile:"NULL", errfile? errfile:"NULL", direction);
171 	CHECK_CONN(FAIL);
172 
173 	/*
174 	 * Validate other parameters
175 	 */
176 	if (dbproc->tds_socket->conn->tds_version < 0x500) {
177 		dbperror(dbproc, SYBETDSVER, 0);
178 		return FAIL;
179 	}
180 
181 	if (tblname == NULL) {
182 		dbperror(dbproc, SYBEBCITBNM, 0);
183 		return FAIL;
184 	}
185 
186 	if (direction != DB_QUERYOUT && !IS_TDS7_PLUS(dbproc->tds_socket->conn) &&
187 	    strlen(tblname) > 92) {	/* 30.30.30 for Sybase */
188 		dbperror(dbproc, SYBEBCITBLEN, 0);
189 		return FAIL;
190 	}
191 
192 	if (direction != DB_IN && direction != DB_OUT && direction != DB_QUERYOUT) {
193 		dbperror(dbproc, SYBEBDIO, 0);
194 		return FAIL;
195 	}
196 
197 	/* Free previously allocated storage in dbproc & initialise flags, etc. */
198 	_bcp_free_storage(dbproc);
199 
200 	/* Allocate storage */
201 	dbproc->bcpinfo = tds_alloc_bcpinfo();
202 	if (dbproc->bcpinfo == NULL)
203 		goto memory_error;
204 
205 	if (!tds_dstr_copy(&dbproc->bcpinfo->tablename, tblname))
206 		goto memory_error;
207 
208 	dbproc->bcpinfo->direction = direction;
209 
210 	dbproc->bcpinfo->xfer_init  = 0;
211 	dbproc->bcpinfo->bind_count = 0;
212 
213 	if (TDS_FAILED(tds_bcp_init(dbproc->tds_socket, dbproc->bcpinfo))) {
214 		/* TODO return proper error */
215 		/* Attempt to use Bulk Copy with a non-existent Server table (might be why ...) */
216 		dbperror(dbproc, SYBEBCNT, 0);
217 		return FAIL;
218 	}
219 
220 	/* Prepare default hostfile columns */
221 
222 	if (hfile == NULL) {
223 		dbproc->hostfileinfo = NULL;
224 		return SUCCEED;
225 	}
226 
227 	dbproc->hostfileinfo = tds_new0(BCP_HOSTFILEINFO, 1);
228 
229 	if (dbproc->hostfileinfo == NULL)
230 		goto memory_error;
231 	dbproc->hostfileinfo->maxerrs = 10;
232 	dbproc->hostfileinfo->firstrow = 1;
233 	if ((dbproc->hostfileinfo->hostfile = strdup(hfile)) == NULL)
234 		goto memory_error;
235 
236 	if (errfile != NULL)
237 		if ((dbproc->hostfileinfo->errorfile = strdup(errfile)) == NULL)
238 			goto memory_error;
239 
240 	init_hostfile_columns(dbproc);
241 
242 	return SUCCEED;
243 
244 memory_error:
245 	_bcp_free_storage(dbproc);
246 	dbperror(dbproc, SYBEMEM, ENOMEM);
247 	return FAIL;
248 }
249 
250 
251 /**
252  * \ingroup dblib_bcp
253  * \brief Set the length of a host variable to be written to a table.
254  *
255  * \param dbproc contains all information needed by db-lib to manage communications with the server.
256  * \param varlen size of the variable, in bytes, or
257  * 	- \b 0 indicating NULL
258  *	- \b -1 indicating size is determined by the prefix or terminator.
259  *		(If both a prefix and a terminator are present, bcp is supposed to use the smaller of the
260  *		 two.  This feature might or might not actually work.)
261  * \param table_column the number of the column in the table (starting with 1, not zero).
262  *
263  * \return SUCCEED or FAIL.
264  * \sa 	bcp_bind(), bcp_colptr(), bcp_sendrow()
265  */
266 RETCODE
bcp_collen(DBPROCESS * dbproc,DBINT varlen,int table_column)267 bcp_collen(DBPROCESS * dbproc, DBINT varlen, int table_column)
268 {
269 	TDSCOLUMN *bcpcol;
270 
271 	tdsdump_log(TDS_DBG_FUNC, "bcp_collen(%p, %d, %d)\n", dbproc, varlen, table_column);
272 
273 	CHECK_CONN(FAIL);
274 	CHECK_PARAMETER(dbproc->bcpinfo, SYBEBCPI, FAIL);		/* not initialized */
275 	DBPERROR_RETURN(dbproc->bcpinfo->direction != DB_IN, SYBEBCPN)	/* not inbound */
276 	DBPERROR_RETURN(dbproc->hostfileinfo != NULL, SYBEBCPI)		/* cannot have data file */
277 	CHECK_PARAMETER(0 < table_column &&
278 			    table_column <= dbproc->bcpinfo->bindinfo->num_cols, SYBECNOR, FAIL);
279 
280 	bcpcol = dbproc->bcpinfo->bindinfo->columns[table_column - 1];
281 
282 	/* Sybase library does not check for NULL here, only sending, so don't
283 	 * check and send SYBEBCNN */
284 	bcpcol->column_bindlen = varlen;
285 
286 	return SUCCEED;
287 }
288 
289 /**
290  * \ingroup dblib_bcp
291  * \brief Indicate how many columns are to be found in the datafile.
292  *
293  * \param dbproc contains all information needed by db-lib to manage communications with the server.
294  * \param host_colcount count of columns in the datafile, irrespective of how many you intend to use.
295  * \remarks This function describes the file as it is, not how it will be used.
296  *
297  * \return SUCCEED or FAIL.  It's hard to see how it could fail.
298  * \sa 	bcp_colfmt()
299  */
300 RETCODE
bcp_columns(DBPROCESS * dbproc,int host_colcount)301 bcp_columns(DBPROCESS * dbproc, int host_colcount)
302 {
303 	int i;
304 
305 	tdsdump_log(TDS_DBG_FUNC, "bcp_columns(%p, %d)\n", dbproc, host_colcount);
306 	CHECK_CONN(FAIL);
307 	CHECK_PARAMETER(dbproc->bcpinfo, SYBEBCPI, FAIL);
308 	CHECK_PARAMETER(dbproc->hostfileinfo, SYBEBIVI, FAIL);
309 
310 	if (host_colcount < 1) {
311 		dbperror(dbproc, SYBEBCFO, 0);
312 		return FAIL;
313 	}
314 
315 	_bcp_free_columns(dbproc);
316 
317 	dbproc->hostfileinfo->host_columns = tds_new0(BCP_HOSTCOLINFO *, host_colcount);
318 	if (dbproc->hostfileinfo->host_columns == NULL) {
319 		dbperror(dbproc, SYBEMEM, ENOMEM);
320 		return FAIL;
321 	}
322 
323 	dbproc->hostfileinfo->host_colcount = host_colcount;
324 
325 	for (i = 0; i < host_colcount; i++) {
326 		dbproc->hostfileinfo->host_columns[i] = tds_new0(BCP_HOSTCOLINFO, 1);
327 		if (dbproc->hostfileinfo->host_columns[i] == NULL) {
328 			dbproc->hostfileinfo->host_colcount = i;
329 			_bcp_free_columns(dbproc);
330 			dbperror(dbproc, SYBEMEM, ENOMEM);
331 			return FAIL;
332 		}
333 	}
334 
335 	return SUCCEED;
336 }
337 
338 /**
339  * \ingroup dblib_bcp
340  * \brief Specify the format of a datafile prior to writing to a table.
341  *
342  * \param dbproc contains all information needed by db-lib to manage communications with the server.
343  * \param host_colnum datafile column number (starting with 1, not zero).
344  * \param host_type dataype token describing the data type in \a host_colnum.  E.g. SYBCHAR for character data.
345  * \param host_prefixlen size of the prefix in the datafile column, if any.  For delimited files: zero.
346  *			May be 0, 1, 2, or 4 bytes.  The prefix will be read as an integer (not a character string) from the
347  * 			data file, and will be interpreted the data size of that column, in bytes.
348  * \param host_collen maximum size of datafile column, exclusive of any prefix/terminator.  Just the data, ma'am.
349  *		Special values:
350  *			- \b 0 indicates NULL.
351  *			- \b -1 for fixed-length non-null datatypes
352  *			- \b -1 for variable-length datatypes (e.g. SYBCHAR) where the length is established
353  *				by a prefix/terminator.
354  * \param host_term the sequence of characters that will serve as a column terminator (delimiter) in the datafile.
355  * 			Often a tab character, but can be any string of any length.  Zero indicates no terminator.
356  * 			Special characters:
357  *				- \b '\\0' terminator is an ASCII NUL.
358  *				- \b '\\t' terminator is an ASCII TAB.
359  *				- \b '\\n' terminator is an ASCII NL.
360  * \param host_termlen the length of \a host_term, in bytes.
361  * \param table_colnum Nth column, starting at 1, in the table that maps to \a host_colnum.
362  * 	If there is a column in the datafile that does not map to a table column, set \a table_colnum to zero.
363  *
364  *\remarks  bcp_colfmt() is called once for each column in the datafile, as specified with bcp_columns().
365  * In so doing, you describe to FreeTDS how to parse each line of your datafile, and where to send each field.
366  *
367  * When a prefix or terminator is used with variable-length data, \a host_collen may have one of three values:
368  *		- \b positive indicating the maximum number of bytes to be used
369  * 		- \b 0 indicating NULL
370  *		- \b -1 indicating no maximum; all data, as described by the prefix/terminator will be used.
371  *		.
372  * \return SUCCEED or FAIL.
373  * \sa 	bcp_batch(), bcp_bind(), bcp_colfmt_ps(), bcp_collen(), bcp_colptr(), bcp_columns(),
374  *	bcp_control(), bcp_done(), bcp_exec(), bcp_init(), bcp_sendrow
375  */
376 RETCODE
bcp_colfmt(DBPROCESS * dbproc,int host_colnum,int host_type,int host_prefixlen,DBINT host_collen,const BYTE * host_term,int host_termlen,int table_colnum)377 bcp_colfmt(DBPROCESS * dbproc, int host_colnum, int host_type, int host_prefixlen, DBINT host_collen, const BYTE * host_term,
378 	   int host_termlen, int table_colnum)
379 {
380 	BCP_HOSTCOLINFO *hostcol;
381 	BYTE *terminator = NULL;
382 
383 	tdsdump_log(TDS_DBG_FUNC, "bcp_colfmt(%p, %d, %d, %d, %d, %p, %d, %d)\n",
384 		    dbproc, host_colnum, host_type, host_prefixlen, (int) host_collen, host_term, host_termlen, table_colnum);
385 	CHECK_CONN(FAIL);
386 	CHECK_PARAMETER(dbproc->bcpinfo, SYBEBCPI, FAIL);
387 	CHECK_PARAMETER(dbproc->hostfileinfo, SYBEBIVI, FAIL);
388 
389 	/* Microsoft specifies a "file_termlen" of zero if there's no terminator */
390 	if (dbproc->msdblib && host_termlen == 0)
391 		host_termlen = -1;
392 
393 	if (host_termlen < 0)
394 		host_termlen = -1;
395 
396 	if (dbproc->hostfileinfo->host_colcount == 0) {
397 		dbperror(dbproc, SYBEBCBC, 0);
398 		return FAIL;
399 	}
400 
401 	if (host_colnum < 1) {
402 		dbperror(dbproc, SYBEBCFO, 0);
403 		return FAIL;
404 	}
405 
406 	if (host_colnum > dbproc->hostfileinfo->host_colcount) {
407 		dbperror(dbproc, SYBECNOR, 0);
408 		return FAIL;
409 	}
410 
411 	if (host_prefixlen != 0 && host_prefixlen != 1 && host_prefixlen != 2 && host_prefixlen != 4 && host_prefixlen != -1) {
412 		dbperror(dbproc, SYBEBCPREF, 0);
413 		return FAIL;
414 	}
415 
416 	/* if column is not copied you cannot specify destination type */
417 	if (table_colnum <= 0 && host_type == 0) {
418 		dbperror(dbproc, SYBEBCPCTYP, 0);
419 		return FAIL;
420 	}
421 
422 	if (table_colnum > 0 && !is_tds_type_valid(host_type)) {
423 		dbperror(dbproc, SYBEUDTY, 0);
424 		return FAIL;
425 	}
426 
427 	if (host_type && host_prefixlen == 0 && host_collen == -1 && host_termlen == -1 && !is_fixed_type(host_type)) {
428 		dbperror(dbproc, SYBEVDPT, 0);
429 		return FAIL;
430 	}
431 
432 	if (host_collen < -1) {
433 		dbperror(dbproc, SYBEBCHLEN, 0);
434 		return FAIL;
435 	}
436 
437 	/* No official error message.  Fix and warn. */
438 	if (is_fixed_type(host_type) && (host_collen != -1 && host_collen != 0)) {
439 		tdsdump_log(TDS_DBG_FUNC,
440 			    "bcp_colfmt: changing host_collen to -1 from %d for fixed type %d.\n",
441 			    host_collen, host_type);
442 		host_collen = -1;
443 	}
444 
445 	/*
446 	 * If there's a positive terminator length, we need a valid terminator pointer.
447 	 * If the terminator length is 0 or -1, then there's no terminator.
448 	 */
449 	if (host_term == NULL && host_termlen > 0) {
450 		dbperror(dbproc, SYBEVDPT, 0);	/* "all variable-length data must have either a length-prefix ..." */
451 		return FAIL;
452 	}
453 
454 	hostcol = dbproc->hostfileinfo->host_columns[host_colnum - 1];
455 
456 	/* TODO add precision scale and join with bcp_colfmt_ps */
457 	if (host_term && host_termlen > 0) {
458 		if ((terminator = tds_new(BYTE, host_termlen)) == NULL) {
459 			dbperror(dbproc, SYBEMEM, errno);
460 			return FAIL;
461 		}
462 		memcpy(terminator, host_term, host_termlen);
463 	}
464 	hostcol->host_column = host_colnum;
465 	hostcol->datatype = host_type ? (TDS_SERVER_TYPE) host_type : TDS_INVALID_TYPE;
466 	hostcol->prefix_len = host_prefixlen;
467 	hostcol->column_len = host_collen;
468 	free(hostcol->terminator);
469 	hostcol->terminator = terminator;
470 	hostcol->term_len = host_termlen;
471 	hostcol->tab_colnum = table_colnum;
472 
473 	return SUCCEED;
474 }
475 
476 /**
477  * \ingroup dblib_bcp
478  * \brief Specify the format of a host file for bulk copy purposes,
479  * 	with precision and scale support for numeric and decimal columns.
480  *
481  * \param dbproc contains all information needed by db-lib to manage communications with the server.
482  * \param host_colnum datafile column number (starting with 1, not zero).
483  * \param host_type dataype token describing the data type in \a host_colnum.  E.g. SYBCHAR for character data.
484  * \param host_prefixlen size of the prefix in the datafile column, if any.  For delimited files: zero.
485  *			May be 0, 1, 2, or 4 bytes.  The prefix will be read as an integer (not a character string) from the
486  * 			data file, and will be interpreted the data size of that column, in bytes.
487  * \param host_collen maximum size of datafile column, exclusive of any prefix/terminator.  Just the data, ma'am.
488  *		Special values:
489  *			- \b 0 indicates NULL.
490  *			- \b -1 for fixed-length non-null datatypes
491  *			- \b -1 for variable-length datatypes (e.g. SYBCHAR) where the length is established
492  *				by a prefix/terminator.
493  * \param host_term the sequence of characters that will serve as a column terminator (delimiter) in the datafile.
494  * 			Often a tab character, but can be any string of any length.  Zero indicates no terminator.
495  * 			Special characters:
496  *				- \b '\\0' terminator is an ASCII NUL.
497  *				- \b '\\t' terminator is an ASCII TAB.
498  *				- \b '\\n' terminator is an ASCII NL.
499  * \param host_termlen the length of \a host_term, in bytes.
500  * \param table_colnum Nth column, starting at 1, in the table that maps to \a host_colnum.
501  * 	If there is a column in the datafile that does not map to a table column, set \a table_colnum to zero.
502  * \param typeinfo something
503  * \todo Not implemented.
504  * \return SUCCEED or FAIL.
505  * \sa 	bcp_batch(), bcp_bind(), bcp_colfmt(), bcp_collen(), bcp_colptr(), bcp_columns(),
506  *	bcp_control(), bcp_done(), bcp_exec(), bcp_init(), bcp_sendrow
507  */
508 RETCODE
bcp_colfmt_ps(DBPROCESS * dbproc,int host_colnum,int host_type,int host_prefixlen,DBINT host_collen,BYTE * host_term,int host_termlen,int table_colnum,DBTYPEINFO * typeinfo)509 bcp_colfmt_ps(DBPROCESS * dbproc, int host_colnum, int host_type,
510 	      int host_prefixlen, DBINT host_collen, BYTE * host_term, int host_termlen, int table_colnum, DBTYPEINFO * typeinfo)
511 {
512 	tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED: bcp_colfmt_ps(%p, %d, %d)\n", dbproc, host_colnum, host_type);
513 	CHECK_CONN(FAIL);
514 	CHECK_PARAMETER(dbproc->bcpinfo, SYBEBCPI, FAIL);
515 
516 	/* dbperror(dbproc, , 0);	 Illegal precision specified */
517 
518 	/* TODO see bcp_colfmt */
519 	return FAIL;
520 }
521 
522 
523 /**
524  * \ingroup dblib_bcp
525  * \brief Set BCP options for uploading a datafile
526  *
527  * \param dbproc contains all information needed by db-lib to manage communications with the server.
528  * \param field symbolic constant indicating the option to be set, one of:
529  *  		- \b BCPMAXERRS Maximum errors tolerated before quitting. The default is 10.
530  *  		- \b BCPFIRST The first row to read in the datafile. The default is 1.
531  *  		- \b BCPLAST The last row to read in the datafile. The default is to copy all rows. A value of
532  *                  	-1 resets this field to its default?
533  *  		- \b BCPBATCH The number of rows per batch.  Default is 0, meaning a single batch.
534  * \param value The value for \a field.
535  *
536  * \remarks These options control the behavior of bcp_exec().
537  * When writing to a table from application host memory variables,
538  * program logic controls error tolerance and batch size.
539  *
540  * \return SUCCEED or FAIL.
541  * \sa 	bcp_batch(), bcp_bind(), bcp_colfmt(), bcp_collen(), bcp_colptr(), bcp_columns(), bcp_done(), bcp_exec(), bcp_options()
542  */
543 RETCODE
bcp_control(DBPROCESS * dbproc,int field,DBINT value)544 bcp_control(DBPROCESS * dbproc, int field, DBINT value)
545 {
546 	tdsdump_log(TDS_DBG_FUNC, "bcp_control(%p, %d, %d)\n", dbproc, field, value);
547 	CHECK_CONN(FAIL);
548 	CHECK_PARAMETER(dbproc->bcpinfo, SYBEBCPI, FAIL);
549 
550 	if (field == BCPKEEPIDENTITY) {
551 		dbproc->bcpinfo->identity_insert_on = (value != 0);
552 		return SUCCEED;
553 	}
554 
555 	CHECK_PARAMETER(dbproc->hostfileinfo, SYBEBIVI, FAIL);
556 
557 	switch (field) {
558 
559 	case BCPMAXERRS:
560 		if (value < 1)
561 			value = 10;
562 		dbproc->hostfileinfo->maxerrs = value;
563 		break;
564 	case BCPFIRST:
565 		if (value < 1)
566 			value = 1;
567 		dbproc->hostfileinfo->firstrow = value;
568 		break;
569 	case BCPLAST:
570 		dbproc->hostfileinfo->lastrow = value;
571 		break;
572 	case BCPBATCH:
573 		dbproc->hostfileinfo->batch = value;
574 		break;
575 
576 	default:
577 		dbperror(dbproc, SYBEIFNB, 0);
578 		return FAIL;
579 	}
580 	return SUCCEED;
581 }
582 
583 /*
584  * \ingroup dblib_bcp
585  * \brief Get BCP batch option
586  *
587  * \param dbproc contains all information needed by db-lib to manage communications with the server.
588  * \remarks This function is specific to FreeTDS.
589  *
590  * \return the value that was set by bcp_control.
591  * \sa 	bcp_batch(), bcp_control()
592  */
593 int
bcp_getbatchsize(DBPROCESS * dbproc)594 bcp_getbatchsize(DBPROCESS * dbproc)
595 {
596 	return dbproc->hostfileinfo->batch;
597 }
598 
599 /**
600  * \ingroup dblib_bcp
601  * \brief Set "hints" for uploading a file.  A FreeTDS-only function.
602  *
603  * \param dbproc contains all information needed by db-lib to manage communications with the server.
604  * \param option symbolic constant indicating the option to be set, one of:
605  * 		- \b BCPLABELED Not implemented.
606  * 		- \b BCPHINTS The hint to be passed when the bulk-copy begins.
607  * \param value The string constant for \a option a/k/a the hint.  One of:
608  * 		- \b ORDER The data are ordered in accordance with the table's clustered index.
609  * 		- \b ROWS_PER_BATCH The batch size
610  * 		- \b KILOBYTES_PER_BATCH The approximate number of kilobytes to use for a batch size
611  * 		- \b TABLOCK Lock the table
612  * 		- \b CHECK_CONSTRAINTS Apply constraints
613  * 		- \b FIRE_TRIGGERS Fire any INSERT triggers on the target table
614  * \param valuelen The strlen of \a value.
615  *
616  * \return SUCCEED or FAIL.
617  * \sa 	bcp_control(),
618  * 	bcp_exec(),
619  * \todo Simplify.  Remove \a valuelen, and dbproc->bcpinfo->hint = strdup(hints[i])
620  */
621 RETCODE
bcp_options(DBPROCESS * dbproc,int option,BYTE * value,int valuelen)622 bcp_options(DBPROCESS * dbproc, int option, BYTE * value, int valuelen)
623 {
624 	int i;
625 	static const char *const hints[] = {
626 		"ORDER", "ROWS_PER_BATCH", "KILOBYTES_PER_BATCH", "TABLOCK", "CHECK_CONSTRAINTS",
627 		"FIRE_TRIGGERS", "KEEP_NULLS", NULL
628 	};
629 
630 	tdsdump_log(TDS_DBG_FUNC, "bcp_options(%p, %d, %p, %d)\n", dbproc, option, value, valuelen);
631 	CHECK_CONN(FAIL);
632 	CHECK_PARAMETER(dbproc->bcpinfo, SYBEBCPI, FAIL);
633 	CHECK_NULP(value, "bcp_options", 3, FAIL);
634 
635 	switch (option) {
636 	case BCPLABELED:
637 		tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED bcp option: BCPLABELED\n");
638 		break;
639 	case BCPHINTS:
640 		if (!value || valuelen <= 0)
641 			break;
642 
643 		for (i = 0; hints[i]; i++) {	/* look up hint */
644 			if (strncasecmp((char *) value, hints[i], strlen(hints[i])) == 0) {
645 				dbproc->bcpinfo->hint = hints[i];	/* safe: hints[i] is static constant, above */
646 				return SUCCEED;
647 			}
648 		}
649 		tdsdump_log(TDS_DBG_FUNC, "failed, no such hint\n");
650 		break;
651 	default:
652 		tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED bcp option: %u\n", option);
653 		break;
654 	}
655 	return FAIL;
656 }
657 
658 /**
659  * \ingroup dblib_bcp
660  * \brief Override bcp_bind() by pointing to a different host variable.
661  *
662  * \param dbproc contains all information needed by db-lib to manage communications with the server.
663  * \param colptr The pointer, the address of your variable.
664  * \param table_column The 1-based column ordinal in the table.
665  * \remarks Use between calls to bcp_sendrow().  After calling bcp_colptr(),
666  * 		subsequent calls to bcp_sendrow() will bind to the new address.
667  * \return SUCCEED or FAIL.
668  * \sa 	bcp_bind(), bcp_collen(), bcp_sendrow()
669  */
670 RETCODE
bcp_colptr(DBPROCESS * dbproc,BYTE * colptr,int table_column)671 bcp_colptr(DBPROCESS * dbproc, BYTE * colptr, int table_column)
672 {
673 	TDSCOLUMN *curcol;
674 
675 	tdsdump_log(TDS_DBG_FUNC, "bcp_colptr(%p, %p, %d)\n", dbproc, colptr, table_column);
676 	CHECK_CONN(FAIL);
677 	CHECK_PARAMETER(dbproc->bcpinfo, SYBEBCPI, FAIL);
678 	CHECK_PARAMETER(dbproc->bcpinfo->bindinfo, SYBEBCPI, FAIL);
679 	/* colptr can be NULL */
680 
681 	if (dbproc->bcpinfo->direction != DB_IN) {
682 		dbperror(dbproc, SYBEBCPN, 0);
683 		return FAIL;
684 	}
685 	if (table_column <= 0 || table_column > dbproc->bcpinfo->bindinfo->num_cols) {
686 		dbperror(dbproc, SYBEBCPN, 0);
687 		return FAIL;
688 	}
689 
690 	curcol = dbproc->bcpinfo->bindinfo->columns[table_column - 1];
691 	curcol->column_varaddr = (TDS_CHAR *)colptr;
692 
693 	return SUCCEED;
694 }
695 
696 
697 /**
698  * \ingroup dblib_bcp
699  * \brief See if BCP_SETL() was used to set the LOGINREC for BCP work.
700  *
701  * \param login Address of the LOGINREC variable to be passed to dbopen().
702  *
703  * \return TRUE or FALSE.
704  * \sa 	BCP_SETL(), bcp_init(), dblogin(), dbopen()
705  */
706 DBBOOL
bcp_getl(LOGINREC * login)707 bcp_getl(LOGINREC * login)
708 {
709 	TDSLOGIN *tdsl = login->tds_login;
710 
711 	tdsdump_log(TDS_DBG_FUNC, "bcp_getl(%p)\n", login);
712 
713 	return (tdsl->bulk_copy);
714 }
715 
716 /**
717  * Convert column for output (usually to a file)
718  * Conversion is slightly different from input as:
719  * - date is formatted differently;
720  * - you have to set properly numeric while on input the column metadata are
721  *   used;
722  * - we need to make sure buffer is always at least a minimum bytes.
723  */
724 static int
_bcp_convert_out(DBPROCESS * dbproc,TDSCOLUMN * curcol,BCP_HOSTCOLINFO * hostcol,TDS_UCHAR ** p_data,const char * bcpdatefmt)725 _bcp_convert_out(DBPROCESS * dbproc, TDSCOLUMN *curcol, BCP_HOSTCOLINFO *hostcol, TDS_UCHAR **p_data, const char *bcpdatefmt)
726 {
727 	BYTE *src;
728 	int srclen;
729 	int buflen;
730 	int srctype = tds_get_conversion_type(curcol->column_type, curcol->column_size);
731 
732 	src = curcol->column_data;
733 	if (is_blob_col(curcol))
734 		src = (BYTE *) ((TDSBLOB *) src)->textvalue;
735 
736 	srclen = curcol->column_cur_size;
737 
738 	/*
739 	 * if we are converting datetime to string, need to override any
740 	 * date time formats already established
741 	 */
742 	if (is_datetime_type(srctype) && is_ascii_type(hostcol->datatype)) {
743 		TDSDATEREC when;
744 
745 		tds_datecrack(srctype, src, &when);
746 		buflen = (int)tds_strftime((TDS_CHAR *)(*p_data), 256,
747 					 bcpdatefmt, &when, 3);
748 	} else if (srclen == 0 && is_variable_type(curcol->column_type)
749 		   && is_ascii_type(hostcol->datatype)) {
750 		/*
751 		 * An empty string is denoted in the output file by a single ASCII NUL
752 		 * byte that we request by specifying a destination length of -1.  (Not
753 		 * to be confused with a database NULL, which is denoted in the output
754 		 * file with an empty string!)
755 		 */
756 		(*p_data)[0] = 0;
757 		buflen = 1;
758 	} else if (is_numeric_type(hostcol->datatype)) {
759 		TDS_NUMERIC *num = (TDS_NUMERIC *) (*p_data);
760 		if (is_numeric_type(srctype)) {
761 			TDS_NUMERIC *nsrc = (TDS_NUMERIC *) src;
762 			num->precision = nsrc->precision;
763 			num->scale = nsrc->scale;
764 		} else {
765 			num->precision = 18;
766 			num->scale = 0;
767 		}
768 		buflen = tds_convert(dbproc->tds_socket->conn->tds_ctx, srctype, src, srclen, hostcol->datatype, (CONV_RESULT *) num);
769 		if (buflen > 0)
770 			buflen = tds_numeric_bytes_per_prec[num->precision] + 2;
771 	} else if (!is_variable_type(hostcol->datatype)) {
772 		buflen = tds_convert(dbproc->tds_socket->conn->tds_ctx, srctype, src, srclen, hostcol->datatype, (CONV_RESULT *) (*p_data));
773 	} else {
774 		CONV_RESULT cr;
775 
776 		/*
777 		 * For null columns, the above work to determine the output buffer size is moot,
778 		 * because bcpcol->data_size is zero, so dbconvert() won't write anything,
779 		 * and returns zero.
780 		 */
781 		buflen = tds_convert(dbproc->tds_socket->conn->tds_ctx, srctype, src, srclen, hostcol->datatype, (CONV_RESULT *) &cr);
782 		if (buflen < 0)
783 			return buflen;
784 
785 		if (buflen >= 256) {
786 			free(*p_data);
787 			*p_data = (TDS_UCHAR *) cr.c;
788 		} else {
789 			memcpy(*p_data, cr.c, buflen);
790 			free(cr.c);
791 		}
792 
793 		/*
794 		 * Special case:  When outputting database varchar data
795 		 * (either varchar or nullable char) conversion may have
796 		 * trimmed trailing blanks such that nothing is left.
797 		 * In this case we need to put a single blank to the output file.
798 		 */
799 		if (is_char_type(curcol->column_type) && srclen > 0 && buflen == 0) {
800 			strcpy ((char *) (*p_data), " ");
801 			buflen = 1;
802 		}
803 	}
804 	return buflen;
805 }
806 
807 static int
bcp_cache_prefix_len(BCP_HOSTCOLINFO * hostcol,const TDSCOLUMN * curcol)808 bcp_cache_prefix_len(BCP_HOSTCOLINFO *hostcol, const TDSCOLUMN *curcol)
809 {
810 	int plen;
811 
812 	if (is_blob_type(hostcol->datatype))
813 		plen = 4;
814 	else if (is_numeric_type(hostcol->datatype))
815 		plen = 1;
816 	else if (!is_fixed_type(hostcol->datatype))
817 		plen = 2;
818 	else if (curcol->column_nullable)
819 		plen = 1;
820 	else
821 		plen = 0;
822 	/* cache */
823 	return hostcol->prefix_len = plen;
824 }
825 
826 static RETCODE
bcp_write_prefix(FILE * hostfile,BCP_HOSTCOLINFO * hostcol,TDSCOLUMN * curcol,int buflen)827 bcp_write_prefix(FILE *hostfile, BCP_HOSTCOLINFO *hostcol, TDSCOLUMN *curcol, int buflen)
828 {
829 	union {
830 		TDS_TINYINT ti;
831 		TDS_SMALLINT si;
832 		TDS_INT li;
833 	} u;
834 	int plen;
835 
836 	/* compute prefix len if needed */
837 	if ((plen = hostcol->prefix_len) == -1)
838 		plen = bcp_cache_prefix_len(hostcol, curcol);
839 
840 	/* output prefix to file */
841 	switch (plen) {
842 	default:
843 		return SUCCEED;
844 	case 1:
845 		u.ti = buflen;
846 		break;
847 	case 2:
848 		u.si = buflen;
849 		break;
850 	case 4:
851 		u.li = buflen;
852 		break;
853 	}
854 	if (fwrite(&u, plen, 1, hostfile) == 1)
855 		return SUCCEED;
856 
857 	return FAIL;
858 }
859 
860 /**
861  * \ingroup dblib_bcp_internal
862  * \brief
863  *
864  *
865  * \param dbproc contains all information needed by db-lib to manage communications with the server.
866  * \param rows_copied
867  *
868  * \return SUCCEED or FAIL.
869  * \sa 	BCP_SETL(), bcp_batch(), bcp_bind(), bcp_colfmt(), bcp_colfmt_ps(), bcp_collen(), bcp_colptr(), bcp_columns(), bcp_control(), bcp_done(), bcp_exec(), bcp_getl(), bcp_init(), bcp_moretext(), bcp_options(), bcp_readfmt(), bcp_sendrow()
870  */
871 static RETCODE
_bcp_exec_out(DBPROCESS * dbproc,DBINT * rows_copied)872 _bcp_exec_out(DBPROCESS * dbproc, DBINT * rows_copied)
873 {
874 	FILE *hostfile = NULL;
875 	TDS_UCHAR *data = NULL;
876 	int i;
877 
878 	TDSSOCKET *tds;
879 	TDSRESULTINFO *resinfo;
880 	TDSCOLUMN *curcol = NULL;
881 	BCP_HOSTCOLINFO *hostcol;
882 	int buflen;
883 
884 	TDS_INT result_type;
885 
886 	int row_of_query;
887 	int rows_written;
888 	const char *bcpdatefmt;
889 	TDSRET tdsret;
890 
891 	tdsdump_log(TDS_DBG_FUNC, "_bcp_exec_out(%p, %p)\n", dbproc, rows_copied);
892 	assert(dbproc);
893 	assert(rows_copied);
894 
895 	tds = dbproc->tds_socket;
896 	assert(tds);
897 
898 	bcpdatefmt = getenv("FREEBCP_DATEFMT");
899 	if (!bcpdatefmt)
900 		bcpdatefmt = "%Y-%m-%d %H:%M:%S.%z";
901 
902 	if (dbproc->bcpinfo->direction == DB_QUERYOUT ) {
903 		if (TDS_FAILED(tds_submit_query(tds, tds_dstr_cstr(&dbproc->bcpinfo->tablename))))
904 			return FAIL;
905 	} else {
906 		/* TODO quote if needed */
907 		if (TDS_FAILED(tds_submit_queryf(tds, "select * from %s", tds_dstr_cstr(&dbproc->bcpinfo->tablename))))
908 			return FAIL;
909 	}
910 
911 	tdsret = tds_process_tokens(tds, &result_type, NULL, TDS_TOKEN_RESULTS);
912 	if (TDS_FAILED(tdsret))
913 		return FAIL;
914 
915 	if (!tds->res_info) {
916 		/* TODO flush/cancel to keep consistent state */
917 		return FAIL;
918 	}
919 
920 	resinfo = tds->res_info;
921 
922 	row_of_query = 0;
923 	rows_written = 0;
924 
925 	/* allocate at least 256 bytes */
926 	/* allocate data for buffer conversion */
927 	data = tds_new(TDS_UCHAR, 256);
928 	if (!data) {
929 		dbperror(dbproc, SYBEMEM, errno);
930 		goto Cleanup;
931 	}
932 
933 	/*
934 	 * TODO above we allocate many buffer just to convert and store
935 	 * to file.. avoid all that passages...
936 	 */
937 
938 	if (!(hostfile = fopen(dbproc->hostfileinfo->hostfile, "w"))) {
939 		dbperror(dbproc, SYBEBCUO, errno);
940 		goto Cleanup;
941 	}
942 
943 	/* fetch a row of data from the server */
944 
945 	while (tds_process_tokens(tds, &result_type, NULL, TDS_STOPAT_ROWFMT|TDS_RETURN_DONE|TDS_RETURN_ROW|TDS_RETURN_COMPUTE)
946 		== TDS_SUCCESS) {
947 
948 		if (result_type != TDS_ROW_RESULT && result_type != TDS_COMPUTE_RESULT)
949 			break;
950 
951 		row_of_query++;
952 
953 		/* skip rows outside of the firstrow/lastrow range, if specified */
954 		if (dbproc->hostfileinfo->firstrow > row_of_query ||
955 						      row_of_query > MAX(dbproc->hostfileinfo->lastrow, 0x7FFFFFFF))
956 			continue;
957 
958 		/* Go through the hostfile columns, finding those that relate to database columns. */
959 		for (i = 0; i < dbproc->hostfileinfo->host_colcount; i++) {
960 			hostcol = dbproc->hostfileinfo->host_columns[i];
961 			if (hostcol->tab_colnum < 1 || hostcol->tab_colnum > resinfo->num_cols)
962 				continue;
963 
964 			curcol = resinfo->columns[hostcol->tab_colnum - 1];
965 
966 			if (curcol->column_cur_size < 0) {
967 				buflen = 0;
968 			} else {
969 				buflen = _bcp_convert_out(dbproc, curcol, hostcol, &data, bcpdatefmt);
970 			}
971 			if (buflen < 0) {
972 				_dblib_convert_err(dbproc, buflen);
973 				goto Cleanup;
974 			}
975 
976 			/* The prefix */
977 			if (bcp_write_prefix(hostfile, hostcol, curcol, buflen) != SUCCEED)
978 				goto write_error;
979 
980 			/* The data */
981 			if (hostcol->column_len != -1) {
982 				buflen = buflen > hostcol->column_len ? hostcol->column_len : buflen;
983 			}
984 
985 			if (buflen > 0) {
986 				if (fwrite(data, buflen, 1, hostfile) != 1)
987 					goto write_error;
988 			}
989 
990 			/* The terminator */
991 			if (hostcol->terminator && hostcol->term_len > 0) {
992 				if (fwrite(hostcol->terminator, hostcol->term_len, 1, hostfile) != 1)
993 					goto write_error;
994 			}
995 		}
996 		rows_written++;
997 	}
998 	if (fclose(hostfile) != 0) {
999 		dbperror(dbproc, SYBEBCUC, errno);
1000 		goto Cleanup;
1001 	}
1002 	hostfile = NULL;
1003 
1004 	if (row_of_query + 1 < dbproc->hostfileinfo->firstrow) {
1005 		/*
1006 		 * The table which bulk-copy is attempting to
1007 		 * copy to a host-file is shorter than the
1008 		 * number of rows which bulk-copy was instructed to skip.
1009 		 */
1010 		/* TODO reset TDSSOCKET state */
1011 		dbperror(dbproc, SYBETTS, 0);
1012 		goto Cleanup;
1013 	}
1014 
1015 	*rows_copied = rows_written;
1016 	free(data);
1017 	return SUCCEED;
1018 
1019 write_error:
1020 	dbperror(dbproc, SYBEBCWE, errno);
1021 
1022 Cleanup:
1023 	if (hostfile)
1024 		fclose(hostfile);
1025 	free(data);
1026 	return FAIL;
1027 }
1028 
1029 static STATUS
_bcp_check_eof(DBPROCESS * dbproc,FILE * file,int icol)1030 _bcp_check_eof(DBPROCESS * dbproc, FILE *file, int icol)
1031 {
1032 	int errnum = errno;
1033 
1034 	tdsdump_log(TDS_DBG_FUNC, "_bcp_check_eof(%p, %p, %d)\n", dbproc, file, icol);
1035 	assert(dbproc);
1036 	assert(file);
1037 
1038 	if (feof(file)) {
1039 		if (icol == 0) {
1040 			tdsdump_log(TDS_DBG_FUNC, "Normal end-of-file reached while loading bcp data file.\n");
1041 			return NO_MORE_ROWS;
1042 		}
1043 		dbperror(dbproc, SYBEBEOF, errnum);
1044 		return FAIL;
1045 	}
1046 	dbperror(dbproc, SYBEBCRE, errnum);
1047 	return FAIL;
1048 }
1049 
1050 /**
1051  * Convert column for input to a table
1052  */
1053 static TDSRET
_bcp_convert_in(DBPROCESS * dbproc,TDS_SERVER_TYPE srctype,const TDS_CHAR * src,TDS_UINT srclen,TDS_SERVER_TYPE desttype,BCPCOLDATA * coldata)1054 _bcp_convert_in(DBPROCESS *dbproc, TDS_SERVER_TYPE srctype, const TDS_CHAR *src, TDS_UINT srclen,
1055 		TDS_SERVER_TYPE desttype, BCPCOLDATA *coldata)
1056 {
1057 	int variable = 1;
1058 	CONV_RESULT cr, *p_cr;
1059 	TDS_INT len;
1060 
1061 	coldata->is_null = false;
1062 
1063 	if (!is_variable_type(desttype)) {
1064 		variable = 0;
1065 		p_cr = (CONV_RESULT *) coldata->data;
1066 	} else {
1067 		p_cr = &cr;
1068 	}
1069 
1070 	len = tds_convert(dbproc->tds_socket->conn->tds_ctx, srctype, src, srclen, desttype, p_cr);
1071 	if (len < 0) {
1072 		_dblib_convert_err(dbproc, len);
1073 		return TDS_FAIL;
1074 	}
1075 
1076 	coldata->datalen = len;
1077 	if (variable) {
1078 		free(coldata->data);
1079 		coldata->data = (TDS_UCHAR *) cr.c;
1080 	}
1081 	return TDS_SUCCESS;
1082 }
1083 
1084 static void
rtrim_bcpcol(TDSCOLUMN * bcpcol)1085 rtrim_bcpcol(TDSCOLUMN *bcpcol)
1086 {
1087 	/* trim trailing blanks from character data */
1088 	if (is_ascii_type(bcpcol->on_server.column_type)) {
1089 		/* A single NUL byte indicates an empty string. */
1090 		if (bcpcol->bcp_column_data->datalen == 1
1091 		    && bcpcol->bcp_column_data->data[0] == '\0') {
1092 			bcpcol->bcp_column_data->datalen = 0;
1093 			return;
1094 		}
1095 		bcpcol->bcp_column_data->datalen = rtrim((char *) bcpcol->bcp_column_data->data,
1096 								  bcpcol->bcp_column_data->datalen);
1097 		return;
1098 	}
1099 
1100 	/* unicode part */
1101 	if (is_unicode_type(bcpcol->on_server.column_type)) {
1102 		uint16_t *data, space;
1103 
1104 		if (!bcpcol->char_conv || bcpcol->char_conv->to.charset.min_bytes_per_char != 2)
1105 			return;
1106 
1107 		data = (uint16_t *) bcpcol->bcp_column_data->data;
1108 		/* A single NUL byte indicates an empty string. */
1109 		if (bcpcol->bcp_column_data->datalen == 2 && data[0] == 0) {
1110 			bcpcol->bcp_column_data->datalen = 0;
1111 			return;
1112 		}
1113 		switch (bcpcol->char_conv->to.charset.canonic) {
1114 		case TDS_CHARSET_UTF_16BE:
1115 		case TDS_CHARSET_UCS_2BE:
1116 			TDS_PUT_A2BE(&space, 0x20);
1117 			break;
1118 		case TDS_CHARSET_UTF_16LE:
1119 		case TDS_CHARSET_UCS_2LE:
1120 			TDS_PUT_A2LE(&space, 0x20);
1121 			break;
1122 		default:
1123 			return;
1124 		}
1125 		bcpcol->bcp_column_data->datalen = rtrim_u16(data, bcpcol->bcp_column_data->datalen, space);
1126 	}
1127 }
1128 
1129 /**
1130  * \ingroup dblib_bcp_internal
1131  * \brief
1132  *
1133  * \param dbproc contains all information needed by db-lib to manage communications with the server.
1134  * \param hostfile
1135  * \param row_error
1136  *
1137  * \return MORE_ROWS, NO_MORE_ROWS, or FAIL.
1138  * \sa 	BCP_SETL(), bcp_batch(), bcp_bind(), bcp_colfmt(), bcp_colfmt_ps(), bcp_collen(), bcp_colptr(), bcp_columns(), bcp_control(), bcp_done(), bcp_exec(), bcp_getl(), bcp_init(), bcp_moretext(), bcp_options(), bcp_readfmt(), bcp_sendrow()
1139  */
1140 static STATUS
_bcp_read_hostfile(DBPROCESS * dbproc,FILE * hostfile,int * row_error,bool skip)1141 _bcp_read_hostfile(DBPROCESS * dbproc, FILE * hostfile, int *row_error, bool skip)
1142 {
1143 	int i;
1144 
1145 	tdsdump_log(TDS_DBG_FUNC, "_bcp_read_hostfile(%p, %p, %p, %d)\n", dbproc, hostfile, row_error, skip);
1146 	assert(dbproc);
1147 	assert(hostfile);
1148 	assert(row_error);
1149 
1150 	/* for each host file column defined by calls to bcp_colfmt */
1151 
1152 	for (i = 0; i < dbproc->hostfileinfo->host_colcount; i++) {
1153 		TDSCOLUMN *bcpcol = NULL;
1154 		BCP_HOSTCOLINFO *hostcol;
1155 		TDS_CHAR *coldata;
1156 		int collen = 0;
1157 		bool data_is_null = false;
1158 		offset_type col_start;
1159 
1160 		tdsdump_log(TDS_DBG_FUNC, "parsing host column %d\n", i + 1);
1161 		hostcol = dbproc->hostfileinfo->host_columns[i];
1162 
1163 		hostcol->column_error = 0;
1164 
1165 		/*
1166 		 * If this host file column contains table data,
1167 		 * find the right element in the table/column list.
1168 		 */
1169 		if (hostcol->tab_colnum > 0) {
1170 			if (hostcol->tab_colnum > dbproc->bcpinfo->bindinfo->num_cols) {
1171 				tdsdump_log(TDS_DBG_FUNC, "error: file wider than table: %d/%d\n",
1172 							  i+1, dbproc->bcpinfo->bindinfo->num_cols);
1173 				dbperror(dbproc, SYBEBEOF, 0);
1174 				return FAIL;
1175 			}
1176 			tdsdump_log(TDS_DBG_FUNC, "host column %d uses bcpcol %d (%p)\n",
1177 				                  i+1, hostcol->tab_colnum, bcpcol);
1178 			bcpcol = dbproc->bcpinfo->bindinfo->columns[hostcol->tab_colnum - 1];
1179 			assert(bcpcol != NULL);
1180 		}
1181 
1182 		/* detect prefix len */
1183 		if (bcpcol && hostcol->prefix_len == -1)
1184 			bcp_cache_prefix_len(hostcol, bcpcol);
1185 
1186 		/* a prefix length, if extant, specifies how many bytes to read */
1187 		if (hostcol->prefix_len > 0) {
1188 			union {
1189 				TDS_TINYINT ti;
1190 				TDS_SMALLINT si;
1191 				TDS_INT li;
1192 			} u;
1193 
1194 			switch (hostcol->prefix_len) {
1195 			case 1:
1196 				if (fread(&u.ti, 1, 1, hostfile) != 1)
1197 					return _bcp_check_eof(dbproc, hostfile, i);
1198 				collen = u.ti ? u.ti : -1;
1199 				break;
1200 			case 2:
1201 				if (fread(&u.si, 2, 1, hostfile) != 1)
1202 					return _bcp_check_eof(dbproc, hostfile, i);
1203 				collen = u.si;
1204 				break;
1205 			case 4:
1206 				if (fread(&u.li, 4, 1, hostfile) != 1)
1207 					return _bcp_check_eof(dbproc, hostfile, i);
1208 				collen = u.li;
1209 				break;
1210 			default:
1211 				/* FIXME return error, remember that prefix_len can be 3 */
1212 				assert(hostcol->prefix_len <= 4);
1213 				break;
1214 			}
1215 
1216 			/* TODO test all NULL types */
1217 			/* TODO for < -1 error */
1218 			if (collen <= -1) {
1219 				data_is_null = true;
1220 				collen = 0;
1221 			}
1222 		}
1223 
1224 		/* if (Max) column length specified take that into consideration. (Meaning what, exactly?) */
1225 
1226 		if (!data_is_null && hostcol->column_len >= 0) {
1227 			if (hostcol->column_len == 0)
1228 				data_is_null = true;
1229 			else if (collen)
1230 				collen = (hostcol->column_len < collen) ? hostcol->column_len : collen;
1231 			else
1232 				collen = hostcol->column_len;
1233 		}
1234 
1235 		tdsdump_log(TDS_DBG_FUNC, "prefix_len = %d collen = %d \n", hostcol->prefix_len, collen);
1236 
1237 		/* Fixed Length data - this overrides anything else specified */
1238 
1239 		if (is_fixed_type(hostcol->datatype))
1240 			collen = tds_get_size_by_type(hostcol->datatype);
1241 
1242 		col_start = ftello(hostfile);
1243 
1244 		/*
1245 		 * The data file either contains prefixes stating the length, or is delimited.
1246 		 * If delimited, we "measure" the field by looking for the terminator, then read it,
1247 		 * and set collen to the field's post-iconv size.
1248 		 */
1249 		if (hostcol->term_len > 0) { /* delimited data file */
1250 			size_t col_bytes;
1251 			TDSRET conv_res;
1252 
1253 			/*
1254 			 * Read and convert the data
1255 			 */
1256 			coldata = NULL;
1257 			conv_res = tds_bcp_fread(dbproc->tds_socket, bcpcol ? bcpcol->char_conv : NULL, hostfile,
1258 						 (const char *) hostcol->terminator, hostcol->term_len, &coldata, &col_bytes);
1259 
1260 			if (TDS_FAILED(conv_res)) {
1261 				tdsdump_log(TDS_DBG_FUNC, "col %d: error converting %ld bytes!\n",
1262 							(i+1), (long) collen);
1263 				*row_error = TRUE;
1264 				free(coldata);
1265 				dbperror(dbproc, SYBEBCOR, 0);
1266 				return FAIL;
1267 			}
1268 
1269 			if (conv_res == TDS_NO_MORE_RESULTS) {
1270 				free(coldata);
1271 				return _bcp_check_eof(dbproc, hostfile, i);
1272 			}
1273 
1274 			if (col_bytes > 0x7fffffffl) {
1275 				free(coldata);
1276 				*row_error = TRUE;
1277 				tdsdump_log(TDS_DBG_FUNC, "data from file is too large!\n");
1278 				dbperror(dbproc, SYBEBCOR, 0);
1279 				return FAIL;
1280 			}
1281 
1282 			collen = (int)col_bytes;
1283 			if (collen == 0)
1284 				data_is_null = true;
1285 
1286 			/*
1287 			 * TODO:
1288 			 *    Dates are a problem.  In theory, we should be able to read non-English dates, which
1289 			 *    would contain non-ASCII characters.  One might suppose we should convert date
1290 			 *    strings to ISO-8859-1 (or another canonical form) here, because tds_convert() can't be
1291 			 *    expected to deal with encodings. But instead date strings are read verbatim and
1292 			 *    passed to tds_convert() without even waving to iconv().  For English dates, this works,
1293 			 *    because English dates expressed as UTF-8 strings are indistinguishable from the ASCII.
1294 			 */
1295 		} else {	/* unterminated field */
1296 
1297 			coldata = tds_new(TDS_CHAR, 1 + collen);
1298 			if (coldata == NULL) {
1299 				*row_error = TRUE;
1300 				dbperror(dbproc, SYBEMEM, errno);
1301 				return FAIL;
1302 			}
1303 
1304 			coldata[collen] = 0;
1305 			if (collen) {
1306 				/*
1307 				 * Read and convert the data
1308 				 * TODO: Call tds_bcp_fread() instead of fread(3).
1309 				 *       The columns should each have their iconv cd set, and noncharacter data
1310 				 *       should have -1 as the iconv cd, causing tds_bcp_fread() to not attempt
1311 				 * 	 any conversion.  We do not need a datatype switch here to decide what to do.
1312 				 *	 As of 0.62, this *should* actually work.  All that remains is to change the
1313 				 *	 call and test it.
1314 				 */
1315 				tdsdump_log(TDS_DBG_FUNC, "Reading %d bytes from hostfile.\n", collen);
1316 				if (fread(coldata, collen, 1, hostfile) != 1) {
1317 					free(coldata);
1318 					return _bcp_check_eof(dbproc, hostfile, i);
1319 				}
1320 			}
1321 		}
1322 
1323 		/*
1324 		 * At this point, however the field was read, however big it was, its address is coldata and its size is collen.
1325 		 */
1326 		tdsdump_log(TDS_DBG_FUNC, "Data read from hostfile: collen is now %d, data_is_null is %d\n", collen, data_is_null);
1327 		if (!skip && bcpcol) {
1328 			if (data_is_null) {
1329 				bcpcol->bcp_column_data->is_null = true;
1330 				bcpcol->bcp_column_data->datalen = 0;
1331 			} else {
1332 				TDSRET rc;
1333 				TDS_SERVER_TYPE desttype;
1334 
1335 				desttype = tds_get_conversion_type(bcpcol->column_type, bcpcol->column_size);
1336 
1337 				rc = _bcp_convert_in(dbproc, hostcol->datatype, (const TDS_CHAR*) coldata, collen,
1338 						     desttype, bcpcol->bcp_column_data);
1339 				if (TDS_FAILED(rc)) {
1340 					hostcol->column_error = HOST_COL_CONV_ERROR;
1341 					*row_error = 1;
1342 					tdsdump_log(TDS_DBG_FUNC,
1343 						"_bcp_read_hostfile failed to convert %d bytes at offset 0x%" PRIx64 " in the data file.\n",
1344 						    collen, (TDS_INT8) col_start);
1345 				}
1346 
1347 				rtrim_bcpcol(bcpcol);
1348 			}
1349 #if USING_SYBEBCNN
1350 			if (!hostcol->column_error) {
1351 				if (bcpcol->bcp_column_data->datalen <= 0) {	/* Are we trying to insert a NULL ? */
1352 					if (!bcpcol->column_nullable) {
1353 						/* too bad if the column is not nullable */
1354 						hostcol->column_error = HOST_COL_NULL_ERROR;
1355 						*row_error = 1;
1356 						dbperror(dbproc, SYBEBCNN, 0);
1357 					}
1358 				}
1359 			}
1360 #endif
1361 		}
1362 		free(coldata);
1363 	}
1364 	return MORE_ROWS;
1365 }
1366 
1367 /**
1368  * \ingroup dblib_bcp
1369  * \brief Write data in host variables to the table.
1370  *
1371  * \param dbproc contains all information needed by db-lib to manage communications with the server.
1372  *
1373  * \remarks Call bcp_bind() first to describe the variables to be used.
1374  *	Use bcp_batch() to commit sets of rows.
1375  *	After sending the last row call bcp_done().
1376  * \return SUCCEED or FAIL.
1377  * \sa 	bcp_batch(), bcp_bind(), bcp_colfmt(), bcp_collen(), bcp_colptr(), bcp_columns(),
1378  * 	bcp_control(), bcp_done(), bcp_exec(), bcp_init(), bcp_moretext(), bcp_options()
1379  */
1380 RETCODE
bcp_sendrow(DBPROCESS * dbproc)1381 bcp_sendrow(DBPROCESS * dbproc)
1382 {
1383 	TDSSOCKET *tds;
1384 
1385 	tdsdump_log(TDS_DBG_FUNC, "bcp_sendrow(%p)\n", dbproc);
1386 	CHECK_CONN(FAIL);
1387 	CHECK_PARAMETER(dbproc->bcpinfo, SYBEBCPI, FAIL);
1388 
1389 	tds = dbproc->tds_socket;
1390 
1391 	if (dbproc->bcpinfo->direction != DB_IN) {
1392 		dbperror(dbproc, SYBEBCPN, 0);
1393 		return FAIL;
1394 	}
1395 
1396 	if (dbproc->hostfileinfo != NULL) {
1397 		dbperror(dbproc, SYBEBCPB, 0);
1398 		return FAIL;
1399 	}
1400 
1401 	/*
1402 	 * The first time sendrow is called after bcp_init,
1403 	 * there is a certain amount of initialisation to be done.
1404 	 */
1405 	if (dbproc->bcpinfo->xfer_init == 0) {
1406 
1407 		/* The start_copy function retrieves details of the table's columns */
1408 		if (TDS_FAILED(tds_bcp_start_copy_in(tds, dbproc->bcpinfo))) {
1409 			dbperror(dbproc, SYBEBULKINSERT, 0);
1410 			return FAIL;
1411 		}
1412 
1413 		dbproc->bcpinfo->xfer_init = 1;
1414 
1415 	}
1416 
1417 	dbproc->bcpinfo->parent = dbproc;
1418 	return TDS_FAILED(tds_bcp_send_record(dbproc->tds_socket, dbproc->bcpinfo,
1419 			  _bcp_get_col_data, _bcp_null_error, 0)) ? FAIL : SUCCEED;
1420 }
1421 
1422 
1423 /**
1424  * \ingroup dblib_bcp_internal
1425  * \brief
1426  *
1427  * \param dbproc contains all information needed by db-lib to manage communications with the server.
1428  * \param rows_copied
1429  *
1430  * \return SUCCEED or FAIL.
1431  * \sa 	BCP_SETL(), bcp_batch(), bcp_bind(), bcp_colfmt(), bcp_colfmt_ps(), bcp_collen(), bcp_colptr(), bcp_columns(), bcp_control(), bcp_done(), bcp_exec(), bcp_getl(), bcp_init(), bcp_moretext(), bcp_options(), bcp_readfmt(), bcp_sendrow()
1432  */
1433 static RETCODE
_bcp_exec_in(DBPROCESS * dbproc,DBINT * rows_copied)1434 _bcp_exec_in(DBPROCESS * dbproc, DBINT * rows_copied)
1435 {
1436 	FILE *hostfile, *errfile = NULL;
1437 	TDSSOCKET *tds = dbproc->tds_socket;
1438 	BCP_HOSTCOLINFO *hostcol;
1439 	STATUS ret;
1440 
1441 	int i, row_of_hostfile, rows_written_so_far;
1442 	int row_error, row_error_count;
1443 	offset_type row_start, row_end;
1444 	offset_type error_row_size;
1445 	const size_t chunk_size = 0x20000u;
1446 
1447 	tdsdump_log(TDS_DBG_FUNC, "_bcp_exec_in(%p, %p)\n", dbproc, rows_copied);
1448 	assert(dbproc);
1449 	assert(rows_copied);
1450 
1451 	*rows_copied = 0;
1452 
1453 	if (!(hostfile = fopen(dbproc->hostfileinfo->hostfile, "r"))) {
1454 		dbperror(dbproc, SYBEBCUO, 0);
1455 		return FAIL;
1456 	}
1457 
1458 	if (TDS_FAILED(tds_bcp_start_copy_in(tds, dbproc->bcpinfo))) {
1459 		fclose(hostfile);
1460 		return FAIL;
1461 	}
1462 
1463 	row_of_hostfile = 0;
1464 	rows_written_so_far = 0;
1465 
1466 	row_error_count = 0;
1467 	dbproc->bcpinfo->parent = dbproc;
1468 
1469 	for (;;) {
1470 		bool skip;
1471 
1472 		row_start = ftello(hostfile);
1473 		row_error = 0;
1474 
1475 		row_of_hostfile++;
1476 
1477 		if (row_of_hostfile > MAX(dbproc->hostfileinfo->lastrow, 0x7FFFFFFF))
1478 			break;
1479 
1480 		skip = dbproc->hostfileinfo->firstrow > row_of_hostfile;
1481 		ret = _bcp_read_hostfile(dbproc, hostfile, &row_error, skip);
1482 		if (ret != MORE_ROWS)
1483 			break;
1484 
1485 		if (row_error) {
1486 			int count;
1487 
1488 			if (errfile == NULL && dbproc->hostfileinfo->errorfile) {
1489 				if (!(errfile = fopen(dbproc->hostfileinfo->errorfile, "w"))) {
1490 					fclose(hostfile);
1491 					dbperror(dbproc, SYBEBUOE, 0);
1492 					return FAIL;
1493 				}
1494 			}
1495 
1496 			if (errfile != NULL) {
1497 				char *row_in_error = NULL;
1498 
1499 				for (i = 0; i < dbproc->hostfileinfo->host_colcount; i++) {
1500 					hostcol = dbproc->hostfileinfo->host_columns[i];
1501 					if (hostcol->column_error == HOST_COL_CONV_ERROR) {
1502 						count = fprintf(errfile,
1503 							"#@ data conversion error on host data file Row %d Column %d\n",
1504 							row_of_hostfile, i + 1);
1505 						if( count < 0 ) {
1506 							dbperror(dbproc, SYBEBWEF, errno);
1507 						}
1508 					} else if (hostcol->column_error == HOST_COL_NULL_ERROR) {
1509 						count = fprintf(errfile, "#@ Attempt to bulk-copy a NULL value into Server column"
1510 								" which does not accept NULL values. Row %d, Column %d\n",
1511 								row_of_hostfile, i + 1);
1512 						if( count < 0 ) {
1513 							dbperror(dbproc, SYBEBWEF, errno);
1514 						}
1515 
1516 					}
1517 				}
1518 
1519 				row_end = ftello(hostfile);
1520 
1521 				/* error data can be very long so split in chunks */
1522 				error_row_size = row_end - row_start;
1523 				fseeko(hostfile, row_start, SEEK_SET);
1524 
1525 				while (error_row_size > 0) {
1526 					size_t chunk = error_row_size > chunk_size ? chunk_size : (size_t) error_row_size;
1527 
1528 					if (!row_in_error) {
1529 						if ((row_in_error = tds_new(char, chunk)) == NULL) {
1530 							dbperror(dbproc, SYBEMEM, errno);
1531 						}
1532 					}
1533 
1534 					if (fread(row_in_error, chunk, 1, hostfile) != 1) {
1535 						printf("BILL fread failed after fseek\n");
1536 					}
1537 					count = (int)fwrite(row_in_error, chunk, 1, errfile);
1538 					if( (size_t)count < chunk ) {
1539 						dbperror(dbproc, SYBEBWEF, errno);
1540 					}
1541 					error_row_size -= chunk;
1542 				}
1543 				free(row_in_error);
1544 
1545 				fseeko(hostfile, row_end, SEEK_SET);
1546 				count = fprintf(errfile, "\n");
1547 				if( count < 0 ) {
1548 					dbperror(dbproc, SYBEBWEF, errno);
1549 				}
1550 			}
1551 			row_error_count++;
1552 			if (row_error_count >= dbproc->hostfileinfo->maxerrs)
1553 				break;
1554 			continue;
1555 		}
1556 
1557 		if (skip)
1558 			continue;
1559 
1560 		if (TDS_SUCCEED(tds_bcp_send_record(dbproc->tds_socket, dbproc->bcpinfo,
1561 						    _bcp_no_get_col_data, _bcp_null_error, 0))) {
1562 
1563 			rows_written_so_far++;
1564 
1565 			if (dbproc->hostfileinfo->batch > 0 && rows_written_so_far == dbproc->hostfileinfo->batch) {
1566 				if (TDS_FAILED(tds_bcp_done(tds, &rows_written_so_far))) {
1567 					if (errfile)
1568 						fclose(errfile);
1569 					fclose(hostfile);
1570 					return FAIL;
1571 				}
1572 
1573 				*rows_copied += rows_written_so_far;
1574 				rows_written_so_far = 0;
1575 
1576 				dbperror(dbproc, SYBEBBCI, 0); /* batch copied to server */
1577 
1578 				tds_bcp_start(tds, dbproc->bcpinfo);
1579 			}
1580 		}
1581 	}
1582 
1583 	if (row_error_count == 0 && row_of_hostfile < dbproc->hostfileinfo->firstrow) {
1584 		/* "The BCP hostfile '%1!' contains only %2! rows.  */
1585 		dbperror(dbproc, SYBEBCSA, 0, dbproc->hostfileinfo->hostfile, row_of_hostfile);
1586 	}
1587 
1588 	if (errfile &&  0 != fclose(errfile) ) {
1589 		dbperror(dbproc, SYBEBUCE, 0);
1590 	}
1591 
1592 	if (fclose(hostfile) != 0) {
1593 		dbperror(dbproc, SYBEBCUC, 0);
1594 		ret = FAIL;
1595 	}
1596 
1597 	tds_bcp_done(tds, &rows_written_so_far);
1598 	*rows_copied += rows_written_so_far;
1599 
1600 	return ret == NO_MORE_ROWS? SUCCEED : FAIL;	/* (ret is returned from _bcp_read_hostfile) */
1601 }
1602 
1603 /**
1604  * \ingroup dblib_bcp
1605  * \brief Write a datafile to a table.
1606  *
1607  *
1608  * \param dbproc contains all information needed by db-lib to manage communications with the server.
1609  * \param rows_copied bcp_exec will write the count of rows successfully written to this address.
1610  *	If \a rows_copied is NULL, it will be ignored by db-lib.
1611  *
1612  * \return SUCCEED or FAIL.
1613  * \sa 	bcp_batch(), bcp_bind(), bcp_colfmt(), bcp_collen(), bcp_colptr(), bcp_columns(),
1614  *	bcp_control(), bcp_done(), bcp_init(), bcp_sendrow()
1615  */
1616 RETCODE
bcp_exec(DBPROCESS * dbproc,DBINT * rows_copied)1617 bcp_exec(DBPROCESS * dbproc, DBINT *rows_copied)
1618 {
1619 	DBINT dummy_copied;
1620 	RETCODE ret = FAIL;
1621 
1622 	tdsdump_log(TDS_DBG_FUNC, "bcp_exec(%p, %p)\n", dbproc, rows_copied);
1623 	CHECK_CONN(FAIL);
1624 	CHECK_PARAMETER(dbproc->bcpinfo, SYBEBCPI, FAIL);
1625 	CHECK_PARAMETER(dbproc->hostfileinfo, SYBEBCVH, FAIL);
1626 
1627 	if (rows_copied == NULL) /* NULL means we should ignore it */
1628 		rows_copied = &dummy_copied;
1629 
1630 	if (dbproc->bcpinfo->direction == DB_OUT || dbproc->bcpinfo->direction == DB_QUERYOUT) {
1631 		ret = _bcp_exec_out(dbproc, rows_copied);
1632 	} else if (dbproc->bcpinfo->direction == DB_IN) {
1633 		ret = _bcp_exec_in(dbproc, rows_copied);
1634 	}
1635 	_bcp_free_storage(dbproc);
1636 
1637 	return ret;
1638 }
1639 
1640 /**
1641  * \ingroup dblib_bcp_internal
1642  * \brief
1643  *
1644  * \param buffer
1645  * \param size
1646  * \param f
1647  *
1648  * \return SUCCEED or FAIL.
1649  * \sa 	BCP_SETL(), bcp_batch(), bcp_bind(), bcp_colfmt(), bcp_colfmt_ps(), bcp_collen(), bcp_colptr(), bcp_columns(), bcp_control(), bcp_done(), bcp_exec(), bcp_getl(), bcp_init(), bcp_moretext(), bcp_options(), bcp_readfmt(), bcp_sendrow()
1650  */
1651 static char *
_bcp_fgets(char * buffer,int size,FILE * f)1652 _bcp_fgets(char *buffer, int size, FILE *f)
1653 {
1654 	char *p = fgets(buffer, size, f);
1655 	if (p == NULL)
1656 		return p;
1657 
1658 	/* discard newline */
1659 	p = strchr(buffer, 0) - 1;
1660 	if (p >= buffer && *p == '\n')
1661 		*p = 0;
1662 	return buffer;
1663 }
1664 
1665 /**
1666  * \ingroup dblib_bcp
1667  * \brief Read a format definition file.
1668  *
1669  * \param dbproc contains all information needed by db-lib to manage communications with the server.
1670  * \param filename Name that will be passed to fopen(3).
1671  *
1672  * \remarks Reads a format file and calls bcp_columns() and bcp_colfmt() as needed.
1673  *
1674  * \return SUCCEED or FAIL.
1675  * \sa 	bcp_colfmt(), bcp_colfmt_ps(), bcp_columns(), bcp_writefmt()
1676  */
1677 RETCODE
bcp_readfmt(DBPROCESS * dbproc,const char filename[])1678 bcp_readfmt(DBPROCESS * dbproc, const char filename[])
1679 {
1680 	BCP_HOSTCOLINFO hostcol[1];
1681 	FILE *ffile;
1682 	char buffer[1024];
1683 	float lf_version = 0.0;
1684 	int li_numcols = 0;
1685 	int colinfo_count = 0;
1686 
1687 	tdsdump_log(TDS_DBG_FUNC, "bcp_readfmt(%p, %s)\n", dbproc, filename? filename:"NULL");
1688 	CHECK_CONN(FAIL);
1689 	CHECK_PARAMETER(dbproc->bcpinfo, SYBEBCPI, FAIL);
1690 	CHECK_NULP(filename, "bcp_readfmt", 2, FAIL);
1691 
1692 	memset(hostcol, 0, sizeof(hostcol));
1693 
1694 	if ((ffile = fopen(filename, "r")) == NULL) {
1695 		dbperror(dbproc, SYBEBUOF, 0);
1696 		goto Cleanup;
1697 	}
1698 
1699 	if ((_bcp_fgets(buffer, sizeof(buffer), ffile)) != NULL) {
1700 		lf_version = (float)atof(buffer);
1701 	} else if (ferror(ffile)) {
1702 		dbperror(dbproc, SYBEBRFF, errno);
1703 		goto Cleanup;
1704 	}
1705 
1706 	if ((_bcp_fgets(buffer, sizeof(buffer), ffile)) != NULL) {
1707 		li_numcols = atoi(buffer);
1708 	} else if (ferror(ffile)) {
1709 		dbperror(dbproc, SYBEBRFF, errno);
1710 		goto Cleanup;
1711 	}
1712 
1713 	if (li_numcols <= 0)
1714 		goto Cleanup;
1715 
1716 	if (bcp_columns(dbproc, li_numcols) == FAIL)
1717 		goto Cleanup;
1718 
1719 	do {
1720 		memset(hostcol, 0, sizeof(hostcol));
1721 
1722 		if (_bcp_fgets(buffer, sizeof(buffer), ffile) == NULL)
1723 			goto Cleanup;
1724 
1725 		if (!_bcp_readfmt_colinfo(dbproc, buffer, hostcol))
1726 			goto Cleanup;
1727 
1728 		if (bcp_colfmt(dbproc, hostcol->host_column, hostcol->datatype,
1729 			       hostcol->prefix_len, hostcol->column_len,
1730 			       hostcol->terminator, hostcol->term_len, hostcol->tab_colnum) == FAIL) {
1731 			goto Cleanup;
1732 		}
1733 
1734 		TDS_ZERO_FREE(hostcol->terminator);
1735 	} while (++colinfo_count < li_numcols);
1736 
1737 	if (ferror(ffile)) {
1738 		dbperror(dbproc, SYBEBRFF, errno);
1739 		goto Cleanup;
1740 	}
1741 
1742 	if (fclose(ffile) != 0) {
1743 		dbperror(dbproc, SYBEBUCF, 0);
1744 		/* even if failure is returned ffile is no more valid */
1745 		ffile = NULL;
1746 		goto Cleanup;
1747 	}
1748 	ffile = NULL;
1749 
1750 	if (colinfo_count != li_numcols)
1751 		goto Cleanup;
1752 
1753 	return SUCCEED;
1754 
1755 Cleanup:
1756 	TDS_ZERO_FREE(hostcol->terminator);
1757 	_bcp_free_columns(dbproc);
1758 	if (ffile)
1759 		fclose(ffile);
1760 	return FAIL;
1761 }
1762 
1763 /**
1764  * \ingroup dblib_bcp_internal
1765  * \brief
1766  *
1767  * \param dbproc contains all information needed by db-lib to manage communications with the server.
1768  * \param buf
1769  * \param ci
1770  *
1771  * \return SUCCEED or FAIL.
1772  * \sa 	BCP_SETL(), bcp_batch(), bcp_bind(), bcp_colfmt(), bcp_colfmt_ps(), bcp_collen(), bcp_colptr(), bcp_columns(), bcp_control(), bcp_done(), bcp_exec(), bcp_getl(), bcp_init(), bcp_moretext(), bcp_options(), bcp_readfmt(), bcp_sendrow()
1773  */
1774 static int
_bcp_readfmt_colinfo(DBPROCESS * dbproc,char * buf,BCP_HOSTCOLINFO * ci)1775 _bcp_readfmt_colinfo(DBPROCESS * dbproc, char *buf, BCP_HOSTCOLINFO * ci)
1776 {
1777 	char *tok;
1778 	int whichcol;
1779 	char term[30];
1780 	int i;
1781 	char *lasts;
1782 
1783 	enum nextcol
1784 	{
1785 		HOST_COLUMN,
1786 		DATATYPE,
1787 		PREFIX_LEN,
1788 		COLUMN_LEN,
1789 		TERMINATOR,
1790 		TAB_COLNUM,
1791 		NO_MORE_COLS
1792 	};
1793 
1794 	assert(dbproc);
1795 	assert(buf);
1796 	assert(ci);
1797 	tdsdump_log(TDS_DBG_FUNC, "_bcp_readfmt_colinfo(%p, %s, %p)\n", dbproc, buf, ci);
1798 
1799 	tok = strtok_r(buf, " \t", &lasts);
1800 	whichcol = HOST_COLUMN;
1801 
1802 	/* TODO use a better way to get an int atoi is very error prone */
1803 	while (tok != NULL && whichcol != NO_MORE_COLS) {
1804 		switch (whichcol) {
1805 
1806 		case HOST_COLUMN:
1807 			ci->host_column = atoi(tok);
1808 
1809 			if (ci->host_column < 1) {
1810 				dbperror(dbproc, SYBEBIHC, 0);
1811 				return (FALSE);
1812 			}
1813 
1814 			whichcol = DATATYPE;
1815 			break;
1816 
1817 		case DATATYPE:
1818 			if (strcmp(tok, "SYBCHAR") == 0)
1819 				ci->datatype = SYBCHAR;
1820 			else if (strcmp(tok, "SYBTEXT") == 0)
1821 				ci->datatype = SYBTEXT;
1822 			else if (strcmp(tok, "SYBBINARY") == 0)
1823 				ci->datatype = SYBBINARY;
1824 			else if (strcmp(tok, "SYBIMAGE") == 0)
1825 				ci->datatype = SYBIMAGE;
1826 			else if (strcmp(tok, "SYBINT1") == 0)
1827 				ci->datatype = SYBINT1;
1828 			else if (strcmp(tok, "SYBINT2") == 0)
1829 				ci->datatype = SYBINT2;
1830 			else if (strcmp(tok, "SYBINT4") == 0)
1831 				ci->datatype = SYBINT4;
1832 			else if (strcmp(tok, "SYBINT8") == 0)
1833 				ci->datatype = SYBINT8;
1834 			else if (strcmp(tok, "SYBFLT8") == 0)
1835 				ci->datatype = SYBFLT8;
1836 			else if (strcmp(tok, "SYBREAL") == 0)
1837 				ci->datatype = SYBREAL;
1838 			else if (strcmp(tok, "SYBBIT") == 0)
1839 				ci->datatype = SYBBIT;
1840 			else if (strcmp(tok, "SYBNUMERIC") == 0)
1841 				ci->datatype = SYBNUMERIC;
1842 			else if (strcmp(tok, "SYBDECIMAL") == 0)
1843 				ci->datatype = SYBDECIMAL;
1844 			else if (strcmp(tok, "SYBMONEY") == 0)
1845 				ci->datatype = SYBMONEY;
1846 			else if (strcmp(tok, "SYBMONEY4") == 0)
1847 				ci->datatype = SYBMONEY4;
1848 			else if (strcmp(tok, "SYBDATETIME") == 0)
1849 				ci->datatype = SYBDATETIME;
1850 			else if (strcmp(tok, "SYBDATETIME4") == 0)
1851 				ci->datatype = SYBDATETIME4;
1852 			/* TODO SQL* for MS
1853 			   SQLNCHAR SQLBIGINT SQLTINYINT SQLSMALLINT
1854 			   SQLUNIQUEID SQLVARIANT SQLUDT */
1855 			else {
1856 				dbperror(dbproc, SYBEBUDF, 0);
1857 				return (FALSE);
1858 			}
1859 
1860 			whichcol = PREFIX_LEN;
1861 			break;
1862 
1863 		case PREFIX_LEN:
1864 			ci->prefix_len = atoi(tok);
1865 			whichcol = COLUMN_LEN;
1866 			break;
1867 		case COLUMN_LEN:
1868 			ci->column_len = atoi(tok);
1869 			whichcol = TERMINATOR;
1870 			break;
1871 		case TERMINATOR:
1872 
1873 			if (*tok++ != '\"')
1874 				return (FALSE);
1875 
1876 			for (i = 0; *tok != '\"' && i < sizeof(term); i++) {
1877 				if (*tok == '\\') {
1878 					tok++;
1879 					switch (*tok) {
1880 					case 't':
1881 						term[i] = '\t';
1882 						break;
1883 					case 'n':
1884 						term[i] = '\n';
1885 						break;
1886 					case 'r':
1887 						term[i] = '\r';
1888 						break;
1889 					case '\\':
1890 						term[i] = '\\';
1891 						break;
1892 					case '0':
1893 						term[i] = '\0';
1894 						break;
1895 					default:
1896 						return (FALSE);
1897 					}
1898 					tok++;
1899 				} else
1900 					term[i] = *tok++;
1901 			}
1902 
1903 			if (*tok != '\"')
1904 				return (FALSE);
1905 
1906 			ci->term_len = i;
1907 			TDS_ZERO_FREE(ci->terminator);
1908 			if (i > 0) {
1909 				if ((ci->terminator = tds_new(BYTE, i)) == NULL) {
1910 					dbperror(dbproc, SYBEMEM, errno);
1911 					return FALSE;
1912 				}
1913 				memcpy(ci->terminator, term, i);
1914 			}
1915 
1916 			whichcol = TAB_COLNUM;
1917 			break;
1918 
1919 		case TAB_COLNUM:
1920 			ci->tab_colnum = atoi(tok);
1921 			whichcol = NO_MORE_COLS;
1922 			break;
1923 
1924 		}
1925 		tok = strtok_r(NULL, " \t", &lasts);
1926 	}
1927 	if (whichcol == NO_MORE_COLS)
1928 		return (TRUE);
1929 	else
1930 		return (FALSE);
1931 }
1932 
1933 #if defined(DBLIB_UNIMPLEMENTED)
1934 /**
1935  * \ingroup dblib_bcp
1936  * \brief Write a format definition file. Not Implemented.
1937  *
1938  * \param dbproc contains all information needed by db-lib to manage communications with the server.
1939  * \param filename Name that would be passed to fopen(3).
1940  *
1941  * \remarks Reads a format file and calls bcp_columns() and bcp_colfmt() as needed.
1942  * \a FreeTDS includes freebcp, a utility to copy data to or from a host file.
1943  *
1944  * \todo For completeness, \a freebcp ought to be able to create format files, but that functionality
1945  * 	is currently lacking, as is bcp_writefmt().
1946  * \todo See the vendors' documentation for the format of these files.
1947  *
1948  * \return SUCCEED or FAIL.
1949  * \sa 	bcp_colfmt(), bcp_colfmt_ps(), bcp_columns(), bcp_readfmt()
1950  */
1951 RETCODE
bcp_writefmt(DBPROCESS * dbproc,const char filename[])1952 bcp_writefmt(DBPROCESS * dbproc, const char filename[])
1953 {
1954 	tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED: bcp_writefmt(%p, %s)\n", dbproc, filename? filename:"NULL");
1955 	CHECK_CONN(FAIL);
1956 	CHECK_PARAMETER(dbproc->bcpinfo, SYBEBCPI, FAIL);
1957 	CHECK_NULP(filename, "bcp_writefmt", 2, FAIL);
1958 
1959 #if 0
1960 	dbperror(dbproc, SYBEBUFF, errno);	/* bcp: Unable to create format file */
1961 	dbperror(dbproc, SYBEBWFF, errno);	/* I/O error while writing bcp format file */
1962 #endif
1963 
1964 	return FAIL;
1965 }
1966 
1967 /**
1968  * \ingroup dblib_bcp
1969  * \brief Write some text or image data to the server.  Not implemented, sadly.
1970  *
1971  * \param dbproc contains all information needed by db-lib to manage communications with the server.
1972  * \param size How much to write, in bytes.
1973  * \param text Address of the data to be written.
1974  * \remarks For a SYBTEXT or SYBIMAGE column, bcp_bind() can be called with
1975  *	a NULL varaddr parameter.  If it is, bcp_sendrow() will return control
1976  *	to the application after the non-text data have been sent.  The application then calls
1977  *	bcp_moretext() -- usually in a loop -- to send the text data in manageable chunks.
1978  * \todo implement bcp_moretext().
1979  * \return SUCCEED or FAIL.
1980  * \sa 	bcp_bind(), bcp_sendrow(), dbmoretext(), dbwritetext()
1981  */
1982 RETCODE
bcp_moretext(DBPROCESS * dbproc,DBINT size,BYTE * text)1983 bcp_moretext(DBPROCESS * dbproc, DBINT size, BYTE * text)
1984 {
1985 	tdsdump_log(TDS_DBG_FUNC, "UNIMPLEMENTED: bcp_moretext(%p, %d, %p)\n", dbproc, size, text);
1986 	CHECK_CONN(FAIL);
1987 	CHECK_PARAMETER(dbproc->bcpinfo, SYBEBCPI, FAIL);
1988 	CHECK_NULP(text, "bcp_moretext", 3, FAIL);
1989 
1990 #if 0
1991 	dbperror(dbproc, SYBEBCMTXT, 0);
1992 		/* bcp_moretext may be used only when there is at least one text or image column in the server table */
1993 	dbperror(dbproc, SYBEBTMT, 0);
1994 		/* Attempt to send too much text data via the bcp_moretext call */
1995 #endif
1996 	return FAIL;
1997 }
1998 #endif
1999 
2000 /**
2001  * \ingroup dblib_bcp
2002  * \brief Commit a set of rows to the table.
2003  *
2004  * \param dbproc contains all information needed by db-lib to manage communications with the server.
2005  * \remarks If not called, bcp_done() will cause the rows to be saved.
2006  * \return Count of rows saved, or -1 on error.
2007  * \sa 	bcp_bind(), bcp_done(), bcp_sendrow()
2008  */
2009 DBINT
bcp_batch(DBPROCESS * dbproc)2010 bcp_batch(DBPROCESS * dbproc)
2011 {
2012 	int rows_copied = 0;
2013 
2014 	tdsdump_log(TDS_DBG_FUNC, "bcp_batch(%p)\n", dbproc);
2015 	CHECK_CONN(-1);
2016 	CHECK_PARAMETER(dbproc->bcpinfo, SYBEBCPI, -1);
2017 
2018 	if (TDS_FAILED(tds_bcp_done(dbproc->tds_socket, &rows_copied)))
2019 		return -1;
2020 
2021 	tds_bcp_start(dbproc->tds_socket, dbproc->bcpinfo);
2022 
2023 	return rows_copied;
2024 }
2025 
2026 /**
2027  * \ingroup dblib_bcp
2028  * \brief Conclude the transfer of data from program variables.
2029  *
2030  * \param dbproc contains all information needed by db-lib to manage communications with the server.
2031  * \remarks Do not overlook this function.  According to Sybase, failure to call bcp_done()
2032  * "will result in unpredictable errors".
2033  * \return As with bcp_batch(), the count of rows saved, or -1 on error.
2034  * \sa 	bcp_batch(), bcp_bind(), bcp_moretext(), bcp_sendrow()
2035  */
2036 DBINT
bcp_done(DBPROCESS * dbproc)2037 bcp_done(DBPROCESS * dbproc)
2038 {
2039 	int rows_copied;
2040 
2041 	tdsdump_log(TDS_DBG_FUNC, "bcp_done(%p)\n", dbproc);
2042 	CHECK_CONN(-1);
2043 
2044 	if (!(dbproc->bcpinfo))
2045 		return -1;
2046 
2047 	if (TDS_FAILED(tds_bcp_done(dbproc->tds_socket, &rows_copied)))
2048 		return -1;
2049 
2050 	_bcp_free_storage(dbproc);
2051 
2052 	return rows_copied;
2053 }
2054 
2055 /**
2056  * \ingroup dblib_bcp
2057  * \brief Bind a program host variable to a database column
2058  *
2059  * \param dbproc contains all information needed by db-lib to manage communications with the server.
2060  * \param varaddr address of host variable
2061  * \param prefixlen length of any prefix found at the beginning of \a varaddr, in bytes.
2062  	Use zero for fixed-length datatypes.
2063  * \param varlen bytes of data in \a varaddr.  Zero for NULL, -1 for fixed-length datatypes.
2064  * \param terminator byte sequence that marks the end of the data in \a varaddr
2065  * \param termlen length of \a terminator
2066  * \param vartype datatype of the host variable
2067  * \param table_column Nth column, starting at 1, in the table.
2068  *
2069  * \remarks The order of operation is:
2070  *	- bcp_init() with \a hfile == NULL and \a direction == DB_IN.
2071  * 	- bcp_bind(), once per column you want to write to
2072  *	- bcp_batch(), optionally, to commit a set of rows
2073  *	- bcp_done()
2074  * \return SUCCEED or FAIL.
2075  * \sa 	bcp_batch(), bcp_colfmt(), bcp_collen(), bcp_colptr(), bcp_columns(), bcp_control(),
2076  * 	bcp_done(), bcp_exec(), bcp_moretext(), bcp_sendrow()
2077  */
2078 RETCODE
bcp_bind(DBPROCESS * dbproc,BYTE * varaddr,int prefixlen,DBINT varlen,BYTE * terminator,int termlen,int db_vartype,int table_column)2079 bcp_bind(DBPROCESS * dbproc, BYTE * varaddr, int prefixlen, DBINT varlen,
2080 	 BYTE * terminator, int termlen, int db_vartype, int table_column)
2081 {
2082 	TDS_SERVER_TYPE vartype;
2083 	TDSCOLUMN *colinfo;
2084 
2085 	tdsdump_log(TDS_DBG_FUNC, "bcp_bind(%p, %p, %d, %d -- %p, %d, %s, %d)\n",
2086 						dbproc, varaddr, prefixlen, varlen,
2087 						terminator, termlen, dbprtype(db_vartype), table_column);
2088 	CHECK_CONN(FAIL);
2089 	CHECK_PARAMETER(dbproc->bcpinfo, SYBEBCPI, FAIL);
2090 	DBPERROR_RETURN(db_vartype != 0 && !is_tds_type_valid(db_vartype), SYBEUDTY);
2091 	vartype = (TDS_SERVER_TYPE) db_vartype;
2092 
2093 	if (dbproc->hostfileinfo != NULL) {
2094 		dbperror(dbproc, SYBEBCPB, 0);
2095 		return FAIL;
2096 	}
2097 
2098 	if (dbproc->bcpinfo->direction != DB_IN) {
2099 		dbperror(dbproc, SYBEBCPN, 0);
2100 		return FAIL;
2101 	}
2102 
2103 	if (varlen < -1) {
2104 		dbperror(dbproc, SYBEBCVLEN, 0);
2105 		return FAIL;
2106 	}
2107 
2108 	if (prefixlen != 0 && prefixlen != 1 && prefixlen != 2 && prefixlen != 4) {
2109 		dbperror(dbproc, SYBEBCBPREF, 0);
2110 		return FAIL;
2111 	}
2112 
2113 	if (prefixlen == 0 && varlen == -1 && termlen == -1 && !is_fixed_type(vartype)) {
2114 		tdsdump_log(TDS_DBG_FUNC, "bcp_bind(): non-fixed type %d requires prefix or terminator\n", vartype);
2115 		return FAIL;
2116 	}
2117 
2118 	if (is_fixed_type(vartype) && (varlen != -1 && varlen != 0)) {
2119 		dbperror(dbproc, SYBEBCIT, 0);
2120 		return FAIL;
2121 	}
2122 
2123 	if (table_column <= 0 ||  table_column > dbproc->bcpinfo->bindinfo->num_cols) {
2124 		dbperror(dbproc, SYBECNOR, 0);
2125 		return FAIL;
2126 	}
2127 
2128 	if (varaddr == NULL && (prefixlen != 0 || termlen != 0)) {
2129 		dbperror(dbproc, SYBEBCBNPR, 0);
2130 		return FAIL;
2131 	}
2132 
2133 	colinfo = dbproc->bcpinfo->bindinfo->columns[table_column - 1];
2134 
2135 	/* If varaddr is NULL and varlen greater than 0, the table column type must be SYBTEXT or SYBIMAGE
2136 		and the program variable type must be SYBTEXT, SYBCHAR, SYBIMAGE or SYBBINARY */
2137 	if (varaddr == NULL && varlen > 0) {
2138 		int fOK = (colinfo->column_type == SYBTEXT || colinfo->column_type == SYBIMAGE) &&
2139 			  (vartype == SYBTEXT || vartype == SYBCHAR || vartype == SYBIMAGE || vartype == SYBBINARY );
2140 		if( !fOK ) {
2141 			dbperror(dbproc, SYBEBCBNTYP, 0);
2142 			tdsdump_log(TDS_DBG_FUNC, "bcp_bind: SYBEBCBNTYP: column=%d and vartype=%d (should fail?)\n",
2143 							colinfo->column_type, vartype);
2144 			/* return FAIL; */
2145 		}
2146 	}
2147 
2148 	colinfo->column_varaddr  = (char *)varaddr;
2149 	colinfo->column_bindtype = vartype;
2150 	colinfo->column_bindlen  = varlen;
2151 	colinfo->bcp_prefix_len = prefixlen;
2152 
2153 	TDS_ZERO_FREE(colinfo->bcp_terminator);
2154 	colinfo->bcp_term_len = 0;
2155 	if (termlen > 0) {
2156 		if ((colinfo->bcp_terminator =  tds_new(TDS_CHAR, termlen)) == NULL) {
2157 			dbperror(dbproc, SYBEMEM, errno);
2158 			return FAIL;
2159 		}
2160 		memcpy(colinfo->bcp_terminator, terminator, termlen);
2161 		colinfo->bcp_term_len = termlen;
2162 	}
2163 
2164 	return SUCCEED;
2165 }
2166 
2167 static void
_bcp_null_error(TDSBCPINFO * bcpinfo,int index,int offset)2168 _bcp_null_error(TDSBCPINFO *bcpinfo, int index, int offset)
2169 {
2170 	DBPROCESS *dbproc = (DBPROCESS *) bcpinfo->parent;
2171 	dbperror(dbproc, SYBEBCNN, 0);
2172 }
2173 
2174 /**
2175  * \ingroup dblib_bcp_internal
2176  * \brief For a bcp in from program variables, get the data from the host variable
2177  *
2178  * \param dbproc contains all information needed by db-lib to manage communications with the server.
2179  * \param bindcol
2180  *
2181  * \return TDS_SUCCESS or TDS_FAIL.
2182  * \sa 	_bcp_add_fixed_columns, _bcp_add_variable_columns, _bcp_send_bcp_record
2183  */
2184 static TDSRET
_bcp_get_col_data(TDSBCPINFO * bcpinfo,TDSCOLUMN * bindcol,int offset)2185 _bcp_get_col_data(TDSBCPINFO *bcpinfo, TDSCOLUMN *bindcol, int offset)
2186 {
2187 	TDS_SERVER_TYPE coltype, desttype;
2188 	int collen;
2189 	int bytes_read;
2190 	BYTE *dataptr;
2191 	DBPROCESS *dbproc = (DBPROCESS *) bcpinfo->parent;
2192 	TDSRET rc;
2193 
2194 	tdsdump_log(TDS_DBG_FUNC, "_bcp_get_col_data(%p, %p)\n", bcpinfo, bindcol);
2195 	CHECK_CONN(TDS_FAIL);
2196 	CHECK_NULP(bindcol, "_bcp_get_col_data", 2, TDS_FAIL);
2197 
2198 	dataptr = (BYTE *) bindcol->column_varaddr;
2199 
2200 	collen = 0;
2201 
2202 	/* If a prefix length specified, read the correct  amount of data. */
2203 
2204 	if (bindcol->bcp_prefix_len > 0) {
2205 
2206 		switch (bindcol->bcp_prefix_len) {
2207 		case 1:
2208 			collen = TDS_GET_UA1(dataptr);
2209 			dataptr += 1;
2210 			break;
2211 		case 2:
2212 			collen = (TDS_SMALLINT) TDS_GET_UA2(dataptr);
2213 			dataptr += 2;
2214 			break;
2215 		case 4:
2216 			collen = (TDS_INT) TDS_GET_UA4(dataptr);
2217 			dataptr += 4;
2218 			break;
2219 		}
2220 		if (collen <= 0)
2221 			goto null_data;
2222 	}
2223 
2224 	/* if (Max) column length specified take that into consideration. */
2225 
2226 	if (bindcol->column_bindlen >= 0) {
2227 		if (bindcol->column_bindlen == 0)
2228 			goto null_data;
2229 		if (collen)
2230 			collen = (int) ((bindcol->column_bindlen < (TDS_UINT)collen) ? bindcol->column_bindlen : (TDS_UINT)collen);
2231 		else
2232 			collen = (int) bindcol->column_bindlen;
2233 	}
2234 
2235 	desttype = tds_get_conversion_type(bindcol->column_type, bindcol->column_size);
2236 
2237 	coltype = bindcol->column_bindtype == 0 ? desttype : (TDS_SERVER_TYPE) bindcol->column_bindtype;
2238 
2239 	/* Fixed Length data - this overrides anything else specified */
2240 	if (is_fixed_type(coltype))
2241 		collen = tds_get_size_by_type(coltype);
2242 
2243 	/* read the data, finally */
2244 
2245 	if (bindcol->bcp_term_len > 0) {	/* terminated field */
2246 		bytes_read = _bcp_get_term_var(dataptr, (BYTE *)bindcol->bcp_terminator, bindcol->bcp_term_len);
2247 
2248 		if (collen <= 0 || bytes_read < collen)
2249 			collen = bytes_read;
2250 
2251 		if (collen == 0)
2252 			goto null_data;
2253 	}
2254 
2255 	if (collen < 0)
2256 		collen = (int) strlen((char *) dataptr);
2257 
2258 	rc = _bcp_convert_in(dbproc, coltype, (const TDS_CHAR*) dataptr, collen,
2259 					    desttype, bindcol->bcp_column_data);
2260 	if (TDS_FAILED(rc))
2261 		return rc;
2262 
2263 	return TDS_SUCCESS;
2264 
2265 null_data:
2266 	bindcol->bcp_column_data->datalen = 0;
2267 	bindcol->bcp_column_data->is_null = true;
2268 	return TDS_SUCCESS;
2269 }
2270 
2271 /**
2272  * Function to read data from file. I this case is empty as data
2273  * are already on bcp_column_data
2274  */
2275 static TDSRET
_bcp_no_get_col_data(TDSBCPINFO * bcpinfo,TDSCOLUMN * bindcol,int offset)2276 _bcp_no_get_col_data(TDSBCPINFO *bcpinfo, TDSCOLUMN *bindcol, int offset)
2277 {
2278 	return TDS_SUCCESS;
2279 }
2280 
2281 /**
2282  * Get the data for bcp-in from program variables, where the program data
2283  * have been identified as character terminated,
2284  * This is a low-level, internal function.  Call it correctly.
2285  */
2286 /**
2287  * \ingroup dblib_bcp_internal
2288  * \brief
2289  *
2290  * \param pdata
2291  * \param term
2292  * \param term_len
2293  *
2294  * \return data length.
2295  */
2296 static int
_bcp_get_term_var(const BYTE * pdata,const BYTE * term,int term_len)2297 _bcp_get_term_var(const BYTE * pdata, const BYTE * term, int term_len)
2298 {
2299 	int bufpos;
2300 
2301 	assert(term_len > 0);
2302 
2303 	/* if bufpos becomes negative, we probably failed to find the terminator */
2304 	for (bufpos = 0; bufpos >= 0 && memcmp(pdata, term, term_len) != 0; pdata++) {
2305 		bufpos++;
2306 	}
2307 
2308 	assert(bufpos >= 0);
2309 	return bufpos;
2310 }
2311 
2312 /**
2313  * \ingroup dblib_bcp_internal
2314  * \brief trim a string of trailing blanks
2315  *
2316  *	Replaces spaces at the end of a string with NULs
2317  * \param str pointer to a character buffer (not null-terminated)
2318  * \param len size of the \a str in bytes
2319  *
2320  * \return modified length
2321  */
2322 static int
rtrim(char * str,int len)2323 rtrim(char *str, int len)
2324 {
2325 	char *p = str + len - 1;
2326 
2327 	while (p > str && *p == ' ') {
2328 		*p-- = '\0';
2329 	}
2330 	return (int)(1 + p - str);
2331 }
2332 
2333 static int
rtrim_u16(uint16_t * str,int len,uint16_t space)2334 rtrim_u16(uint16_t *str, int len, uint16_t space)
2335 {
2336 	uint16_t *p = str + len / 2 - 1;
2337 
2338 	while (p > str && *p == space) {
2339 		*p-- = '\0';
2340 	}
2341 	return (int)(1 + p - str) * 2;
2342 }
2343 
2344 /**
2345  * \ingroup dblib_bcp_internal
2346  * \brief
2347  *
2348  * \param dbproc contains all information needed by db-lib to manage communications with the server.
2349  */
2350 static void
_bcp_free_columns(DBPROCESS * dbproc)2351 _bcp_free_columns(DBPROCESS * dbproc)
2352 {
2353 	int i;
2354 
2355 	tdsdump_log(TDS_DBG_FUNC, "_bcp_free_columns(%p)\n", dbproc);
2356 	assert(dbproc && dbproc->hostfileinfo);
2357 
2358 	if (dbproc->hostfileinfo->host_columns) {
2359 		for (i = 0; i < dbproc->hostfileinfo->host_colcount; i++) {
2360 			TDS_ZERO_FREE(dbproc->hostfileinfo->host_columns[i]->terminator);
2361 			TDS_ZERO_FREE(dbproc->hostfileinfo->host_columns[i]);
2362 		}
2363 		TDS_ZERO_FREE(dbproc->hostfileinfo->host_columns);
2364 		dbproc->hostfileinfo->host_colcount = 0;
2365 	}
2366 }
2367 
2368 /**
2369  * \ingroup dblib_bcp_internal
2370  * \brief
2371  *
2372  * \param dbproc contains all information needed by db-lib to manage communications with the server.
2373  *
2374  * \sa 	bcp_done(), bcp_exec(), bcp_init()
2375  */
2376 static void
_bcp_free_storage(DBPROCESS * dbproc)2377 _bcp_free_storage(DBPROCESS * dbproc)
2378 {
2379 	tdsdump_log(TDS_DBG_FUNC, "_bcp_free_storage(%p)\n", dbproc);
2380 	assert(dbproc);
2381 
2382 	if (dbproc->hostfileinfo) {
2383 		TDS_ZERO_FREE(dbproc->hostfileinfo->hostfile);
2384 		TDS_ZERO_FREE(dbproc->hostfileinfo->errorfile);
2385 		_bcp_free_columns(dbproc);
2386 		TDS_ZERO_FREE(dbproc->hostfileinfo);
2387 	}
2388 
2389 	tds_free_bcpinfo(dbproc->bcpinfo);
2390 	dbproc->bcpinfo = NULL;
2391 }
2392 
2393