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