LCOV - code coverage report
Current view: top level - src/apps - freebcp.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 152 368 41.3 %
Date: 2026-05-09 08:39:35 Functions: 11 14 78.6 %

          Line data    Source code
       1             : /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
       2             :  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005  Brian Bruns
       3             :  * Copyright (C) 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 <stdio.h>
      24             : #include <ctype.h>
      25             : 
      26             : #if HAVE_ERRNO_H
      27             : #include <errno.h>
      28             : #endif /* HAVE_ERRNO_H */
      29             : 
      30             : #if HAVE_STDLIB_H
      31             : #include <stdlib.h>
      32             : #endif /* HAVE_STDLIB_H */
      33             : 
      34             : /* These should be in stdlib */
      35             : #ifndef EXIT_SUCCESS
      36             : #define EXIT_SUCCESS 0
      37             : #endif
      38             : #ifndef EXIT_FAILURE
      39             : #define EXIT_FAILURE 1
      40             : #endif
      41             : 
      42             : #if HAVE_STRING_H
      43             : #include <string.h>
      44             : #endif /* HAVE_STRING_H */
      45             : 
      46             : #if HAVE_STRINGS_H
      47             : #include <strings.h>
      48             : #endif /* HAVE_STRINGS_H */
      49             : 
      50             : #if HAVE_UNISTD_H
      51             : #include <unistd.h>
      52             : #endif
      53             : 
      54             : #if HAVE_LOCALE_H
      55             : #include <locale.h>
      56             : #endif
      57             : 
      58             : #include <sybfront.h>
      59             : #include <sybdb.h>
      60             : 
      61             : #include <freetds/macros.h>
      62             : #include <freetds/bool.h>
      63             : #include <freetds/version.h>
      64             : #include <freetds/utils.h>
      65             : #include <freetds/utils/path.h>
      66             : #include <freetds/replacements.h>
      67             : 
      68             : #include "freebcp.h"
      69             : 
      70             : enum
      71             : {
      72             :         BCPFORMAT_NONE, BCPFORMAT_CHARACTER, BCPFORMAT_NATIVE, BCPFORMAT_FORMATTED
      73             : };
      74             : typedef int BCPFORMAT;
      75             : 
      76             : int tdsdump_open(const char *filename);
      77             : 
      78             : static void pusage(void);
      79             : static int process_parameters(int, char **, BCPPARAMDATA *);
      80             : static int unescape(char arg[]);
      81             : static int login_to_database(BCPPARAMDATA * pdata, DBPROCESS ** pdbproc);
      82             : 
      83             : static int setoptions(DBPROCESS * dbproc, BCPPARAMDATA * params);
      84             : static BCPFORMAT get_format(BCPPARAMDATA * params);
      85             : static int file_process(BCPPARAMDATA * pdata, DBPROCESS * dbproc, DBINT dir);
      86             : static int err_handler(DBPROCESS * dbproc, int severity, int dberr, int oserr, char *dberrstr, char *oserrstr);
      87             : static int msg_handler(DBPROCESS * dbproc TDS_UNUSED, DBINT msgno, int msgstate, int severity, char *msgtext, char *srvname,
      88             :                        char *procname, int line);
      89             : static int set_bcp_hints(BCPPARAMDATA * pdata, DBPROCESS * pdbproc);
      90             : static void bcpparamdata_free(BCPPARAMDATA * params);
      91             : 
      92             : int
      93          10 : main(int argc, char **argv)
      94             : {
      95             :         BCPPARAMDATA params;
      96             :         DBPROCESS *dbproc;
      97          10 :         int ok = FALSE;
      98             : 
      99          10 :         setlocale(LC_ALL, "");
     100             : 
     101             : #ifdef __VMS
     102             :         /* Convert VMS-style arguments to Unix-style */
     103             :         parse_vms_args(&argc, &argv);
     104             : #endif
     105             : 
     106          10 :         memset(&params, '\0', sizeof(params));
     107             : 
     108          10 :         params.textsize = 4096; /* our default text size is 4K */
     109             : 
     110          10 :         if (process_parameters(argc, argv, &params) == FALSE) {
     111           0 :                 exit(EXIT_FAILURE);
     112             :         }
     113          10 :         if (getenv("FREEBCP")) {
     114           0 :                 fprintf(stderr, "User name: \"%s\"\n", params.user);
     115             :         }
     116             : 
     117             : 
     118          10 :         if (login_to_database(&params, &dbproc) == FALSE) {
     119           0 :                 exit(EXIT_FAILURE);
     120             :         }
     121             : 
     122          10 :         if (!setoptions(dbproc, &params))
     123             :                 return FALSE;
     124             : 
     125          10 :         ok = file_process(&params, dbproc, params.direction);
     126             : 
     127          10 :         dbclose(dbproc);
     128          10 :         dbexit();
     129          10 :         bcpparamdata_free(&params);
     130             : 
     131          10 :         return (ok == TRUE) ? EXIT_SUCCESS : EXIT_FAILURE;
     132             : }
     133             : 
     134             : static BCPFORMAT
     135             : get_format(BCPPARAMDATA *params)
     136             : {
     137          10 :         if (params->cflag)
     138             :                 return BCPFORMAT_CHARACTER;
     139             : 
     140           0 :         if (params->nflag)
     141             :                 return BCPFORMAT_NATIVE;
     142             : 
     143           0 :         if (params->fflag)
     144             :                 return BCPFORMAT_FORMATTED;
     145             : 
     146             :         return BCPFORMAT_NONE;
     147             : }
     148             : 
     149             : static int
     150           0 : unescape_hex(char *arg)
     151             : {
     152             :         char *buf;
     153             :         size_t len;
     154             :         DBINT out_len;
     155             : 
     156           0 :         if (strncasecmp(arg, "0x", 2) != 0)
     157             :                 return -1;
     158             : 
     159           0 :         len = strlen(arg);
     160           0 :         buf = xstrdup(arg);
     161           0 :         out_len = dbconvert(NULL, SYBVARCHAR, (void *) arg, len, SYBVARBINARY, (void *) buf, (DBINT) len);
     162           0 :         if (out_len < 0) {
     163           0 :                 free(buf);
     164           0 :                 return -1;
     165             :         }
     166             : 
     167             :         /* As documented we stop at the first NUL character */
     168           0 :         buf[out_len] = 0;
     169           0 :         out_len = (int) strlen(buf);
     170             : 
     171           0 :         memcpy(arg, buf, out_len);
     172           0 :         free(buf);
     173           0 :         return out_len;
     174             : }
     175             : 
     176             : static int
     177           0 : unescape(char arg[])
     178             : {
     179           0 :         char *p = arg, *next;
     180             :         char escaped;
     181             :         int hex_res;
     182             : 
     183           0 :         hex_res = unescape_hex(arg);
     184           0 :         if (hex_res >= 0)
     185             :                 return hex_res;
     186             : 
     187           0 :         while ((next = strchr(p, '\\')) != NULL) {
     188             : 
     189           0 :                 p = next;
     190             : 
     191           0 :                 switch (p[1]) {
     192             :                 case '0':
     193             :                         escaped = '\0';
     194             :                         break;
     195           0 :                 case 't':
     196           0 :                         escaped = '\t';
     197           0 :                         break;
     198           0 :                 case 'r':
     199           0 :                         escaped = '\r';
     200           0 :                         break;
     201           0 :                 case 'n':
     202             : #ifdef _WIN32
     203             :                         memcpy(p, "\r\n", 2);
     204             :                         continue;
     205             : #else
     206           0 :                         escaped = '\n';
     207             : #endif
     208           0 :                         break;
     209           0 :                 case '\\':
     210           0 :                         escaped = '\\';
     211           0 :                         break;
     212           0 :                 default:
     213           0 :                         ++p;
     214           0 :                         continue;
     215             :                 }
     216             : 
     217             :                 /* Overwrite the backslash with the intended character, and shift everything down one */
     218           0 :                 *p++ = escaped;
     219           0 :                 memmove(p, p+1, 1 + strlen(p+1));
     220             :         }
     221           0 :         return strchr(p, 0) - arg;
     222             : }
     223             : 
     224             : static int
     225          10 : process_parameters(int argc, char **argv, BCPPARAMDATA *pdata)
     226             : {
     227             :         extern char *optarg;
     228             :         extern int optind;
     229             :         extern int optopt;
     230             : 
     231             :         int ch;
     232             : 
     233          10 :         if (argc < 6) {
     234           0 :                 pusage();
     235           0 :                 return (FALSE);
     236             :         }
     237             : 
     238             :         /*
     239             :          * Set some defaults and read the table, file, and direction arguments.
     240             :          */
     241          10 :         pdata->firstrow = 0;
     242          10 :         pdata->lastrow = 0;
     243          10 :         pdata->batchsize = 1000;
     244          10 :         pdata->maxerrors = 10;
     245             : 
     246             :         /* argument 1 - the database object */
     247          10 :         pdata->dbobject = xstrdup(argv[1]);
     248             : 
     249             :         /* argument 2 - the direction */
     250          10 :         strlcpy(pdata->dbdirection, argv[2], sizeof(pdata->dbdirection));
     251             : 
     252          10 :         if (strcasecmp(pdata->dbdirection, "in") == 0) {
     253          10 :                 pdata->direction = DB_IN;
     254           0 :         } else if (strcasecmp(pdata->dbdirection, "out") == 0) {
     255           0 :                 pdata->direction = DB_OUT;
     256           0 :         } else if (strcasecmp(pdata->dbdirection, "queryout") == 0) {
     257           0 :                 pdata->direction = DB_QUERYOUT;
     258             :         } else {
     259           0 :                 fprintf(stderr, "Copy direction must be either 'in', 'out' or 'queryout'.\n");
     260           0 :                 return (FALSE);
     261             :         }
     262             : 
     263             :         /* argument 3 - the datafile name */
     264          10 :         free(pdata->hostfilename);
     265          10 :         pdata->hostfilename = xstrdup(argv[3]);
     266             : 
     267             :         /*
     268             :          * Get the rest of the arguments
     269             :          */
     270          10 :         optind = 4;             /* start processing options after table, direction, & filename */
     271          80 :         while ((ch = getopt(argc, argv, "m:f:e:F:L:b:t:r:U:P:i:I:S:h:T:A:o:O:0:C:ncEdvVD:k")) != -1) {
     272          60 :                 switch (ch) {
     273           0 :                 case 'v':
     274             :                 case 'V':
     275           0 :                         printf("freebcp version %s\n", TDS_VERSION_NO);
     276           0 :                         return FALSE;
     277             :                         break;
     278           0 :                 case 'm':
     279           0 :                         pdata->maxerrors = atoi(optarg);
     280           0 :                         break;
     281           0 :                 case 'f':
     282           0 :                         pdata->fflag = true;
     283           0 :                         free(pdata->formatfile);
     284           0 :                         pdata->formatfile = xstrdup(optarg);
     285           0 :                         break;
     286          10 :                 case 'e':
     287          10 :                         pdata->errorfile = xstrdup(optarg);
     288          10 :                         break;
     289           0 :                 case 'F':
     290           0 :                         pdata->firstrow = atoi(optarg);
     291           0 :                         break;
     292           0 :                 case 'L':
     293           0 :                         pdata->lastrow = atoi(optarg);
     294           0 :                         break;
     295           0 :                 case 'b':
     296           0 :                         pdata->batchsize = atoi(optarg);
     297           0 :                         break;
     298           0 :                 case 'n':
     299           0 :                         pdata->nflag = true;
     300           0 :                         break;
     301          10 :                 case 'c':
     302          10 :                         pdata->cflag = true;
     303          10 :                         break;
     304           0 :                 case 'E':
     305           0 :                         pdata->Eflag = true;
     306           0 :                         break;
     307           0 :                 case 'd':
     308           0 :                         tdsdump_open("stderr");
     309           0 :                         break;
     310           0 :                 case 't':
     311           0 :                         pdata->tflag = true;
     312           0 :                         pdata->fieldterm = xstrdup(optarg);
     313           0 :                         pdata->fieldtermlen = unescape(pdata->fieldterm);
     314           0 :                         break;
     315           0 :                 case 'r':
     316           0 :                         pdata->rflag = true;
     317           0 :                         pdata->rowterm = xstrdup(optarg);
     318           0 :                         pdata->rowtermlen = unescape(pdata->rowterm);
     319           0 :                         break;
     320          10 :                 case 'U':
     321          10 :                         pdata->user = xstrdup(optarg);
     322          10 :                         break;
     323          10 :                 case 'P':
     324          10 :                         pdata->pass = tds_getpassarg(optarg);
     325          10 :                         break;
     326           0 :                 case 'i':
     327           0 :                         free(pdata->inputfile);
     328           0 :                         pdata->inputfile = xstrdup(optarg);
     329           0 :                         break;
     330           0 :                 case 'I':
     331           0 :                         free(pdata->interfacesfile);
     332           0 :                         pdata->interfacesfile = xstrdup(optarg);
     333           0 :                         break;
     334          10 :                 case 'S':
     335          10 :                         pdata->Sflag = true;
     336          10 :                         pdata->server = xstrdup(optarg);
     337          10 :                         break;
     338          10 :                 case 'D':
     339          10 :                         pdata->dbname = xstrdup(optarg);
     340          10 :                         break;
     341           0 :                 case 'h':
     342           0 :                         pdata->hint = xstrdup(optarg);
     343           0 :                         break;
     344           0 :                 case 'o':
     345           0 :                         free(pdata->outputfile);
     346           0 :                         pdata->outputfile = xstrdup(optarg);
     347           0 :                         break;
     348           0 :                 case 'O':
     349             :                 case '0':
     350           0 :                         pdata->options = xstrdup(optarg);
     351           0 :                         break;
     352           0 :                 case 'T':
     353           0 :                         pdata->textsize = atoi(optarg);
     354           0 :                         break;
     355           0 :                 case 'A':
     356           0 :                         pdata->Aflag = true;
     357           0 :                         pdata->packetsize = atoi(optarg);
     358           0 :                         break;
     359           0 :                 case 'C':
     360           0 :                         pdata->charset = xstrdup(optarg);
     361           0 :                         break;
     362           0 :                 case 'k':
     363           0 :                         pdata->ignoreDefaults = true;
     364           0 :                         break;
     365           0 :                 case '?':
     366             :                 default:
     367           0 :                         pusage();
     368           0 :                         return (FALSE);
     369             :                 }
     370             :         }
     371             : 
     372             :         /*
     373             :          * Check for required/disallowed option combinations
     374             :          * If no username is provided, rely on domain login.
     375             :          */
     376             : 
     377             :         /* Server */
     378          10 :         if (!pdata->Sflag) {
     379           0 :                 if ((pdata->server = getenv("DSQUERY")) != NULL) {
     380           0 :                         pdata->server = xstrdup(pdata->server);   /* can be freed */
     381           0 :                         pdata->Sflag = true;
     382             :                 } else {
     383           0 :                         fprintf(stderr, "-S must be supplied.\n");
     384           0 :                         return (FALSE);
     385             :                 }
     386             :         }
     387             : 
     388             :         /* Only one of these can be specified */
     389          10 :         if (!!pdata->cflag + !!pdata->nflag + !!pdata->fflag != 1) {
     390           0 :                 fprintf(stderr, "Exactly one of options -c, -n, -f must be supplied.\n");
     391           0 :                 return (FALSE);
     392             :         }
     393             : 
     394             :         /* Character mode file: fill in default values */
     395          10 :         if (pdata->cflag) {
     396             : 
     397          10 :                 if (!pdata->tflag || !pdata->fieldterm) { /* field terminator not specified */
     398          10 :                         pdata->fieldterm = xstrdup("\t");
     399          10 :                         pdata->fieldtermlen = 1;
     400             :                 }
     401          10 :                 if (!pdata->rflag || !pdata->rowterm) {   /* row terminator not specified */
     402             : #ifdef _WIN32
     403             :                         pdata->rowterm = xstrdup("\r\n");
     404             :                         pdata->rowtermlen = 2;
     405             : #else
     406          10 :                         pdata->rowterm = xstrdup("\n");
     407          10 :                         pdata->rowtermlen = 1;
     408             : #endif
     409             :                 }
     410             :         }
     411             : 
     412             :         /* -k will be implemented on MSSQL by -hKEEP_NULLS */
     413          10 :         if (pdata->ignoreDefaults) {
     414           0 :                 if (!pdata->hint)
     415           0 :                         pdata->hint = xstrdup("KEEP_NULLS");
     416           0 :                 else if (strstr(pdata->hint, "KEEP_NULLS") == NULL) {
     417             :                         /* Append to existing hints if not already present */
     418             :                         char *hints;
     419           0 :                         int ret = asprintf(&hints, "%s,KEEP_NULLS", pdata->hint);
     420             : 
     421           0 :                         if (ret < 0) {
     422           0 :                                 fprintf(stderr, "Failed to apply -k flag to hints");
     423           0 :                                 return FALSE;
     424             :                         }
     425           0 :                         free(pdata->hint);
     426           0 :                         pdata->hint = hints;
     427             :                 }
     428             :         }
     429             : 
     430             :         /*
     431             :          * Override stdin and/or stdout if requested.
     432             :          */
     433             : 
     434             :         /* FIXME -- Since we don't implement prompting for field data types when neither -c nor -n
     435             :          * is specified, redirecting stdin doesn't do much yet.
     436             :          */
     437          10 :         if (pdata->inputfile) {
     438           0 :                 if (freopen(pdata->inputfile, "rb", stdin) == NULL) {
     439           0 :                         fprintf(stderr, "%s: unable to open %s: %s\n", "freebcp", pdata->inputfile, strerror(errno));
     440           0 :                         exit(EXIT_FAILURE);
     441             :                 }
     442             :         }
     443             : 
     444          10 :         if (pdata->outputfile) {
     445           0 :                 if (freopen(pdata->outputfile, "wb", stdout) == NULL) {
     446           0 :                         fprintf(stderr, "%s: unable to open %s: %s\n", "freebcp", pdata->outputfile, strerror(errno));
     447           0 :                         exit(EXIT_FAILURE);
     448             :                 }
     449             :         }
     450             : 
     451             :         return (TRUE);
     452             : 
     453             : }
     454             : 
     455             : static int
     456          10 : process_Eflag(BCPPARAMDATA *pdata, DBPROCESS *dbproc)
     457             : {
     458          10 :         if (pdata->Eflag) {
     459             : 
     460           0 :                 bcp_control(dbproc, BCPKEEPIDENTITY, 1);
     461             : 
     462           0 :                 if (dbfcmd(dbproc, "set identity_insert %s on", pdata->dbobject) == FAIL) {
     463           0 :                         fprintf(stderr, "dbfcmd failed\n");
     464             :                         return FALSE;
     465             :                 }
     466             : 
     467           0 :                 if (dbsqlexec(dbproc) == FAIL) {
     468           0 :                         fprintf(stderr, "dbsqlexec failed\n");
     469             :                         return FALSE;
     470             :                 }
     471             : 
     472           0 :                 while (NO_MORE_RESULTS != dbresults(dbproc))
     473           0 :                         continue;
     474             :         }
     475             :         return TRUE;
     476             : }
     477             : 
     478             : static int
     479          10 : login_to_database(BCPPARAMDATA *pdata, DBPROCESS **pdbproc)
     480             : {
     481             :         LOGINREC *login;
     482             : 
     483             :         /* Initialize DB-Library. */
     484             : 
     485          10 :         if (dbinit() == FAIL)
     486             :                 return (FALSE);
     487             : 
     488             :         /*
     489             :          * Install the user-supplied error-handling and message-handling
     490             :          * routines. They are defined at the bottom of this source file.
     491             :          */
     492             : 
     493          10 :         dberrhandle(err_handler);
     494          10 :         dbmsghandle(msg_handler);
     495             : 
     496             :         /* If the interfaces file was specified explicitly, set it. */
     497          10 :         if (pdata->interfacesfile != NULL)
     498           0 :                 dbsetifile(pdata->interfacesfile);
     499             : 
     500             :         /*
     501             :          * Allocate and initialize the LOGINREC structure to be used
     502             :          * to open a connection to SQL Server.
     503             :          */
     504             : 
     505          10 :         login = dblogin();
     506          10 :         if (!login)
     507             :                 return FALSE;
     508             : 
     509          10 :         if (pdata->user)
     510          10 :                 DBSETLUSER(login, pdata->user);
     511          10 :         if (pdata->pass) {
     512          10 :                 DBSETLPWD(login, pdata->pass);
     513          10 :                 memset(pdata->pass, 0, strlen(pdata->pass));
     514             :         }
     515             : 
     516          10 :         DBSETLAPP(login, "FreeBCP");
     517          10 :         if (pdata->charset)
     518           0 :                 DBSETLCHARSET(login, pdata->charset);
     519             : 
     520          10 :         if (pdata->Aflag && pdata->packetsize > 0) {
     521           0 :                 DBSETLPACKET(login, pdata->packetsize);
     522             :         }
     523             : 
     524          10 :         if (pdata->dbname)
     525          10 :                 DBSETLDBNAME(login, pdata->dbname);
     526             : 
     527             :         /* Enable bulk copy for this connection. */
     528             : 
     529          10 :         BCP_SETL(login, TRUE);
     530             : 
     531             :         /*
     532             :          * Get a connection to the database.
     533             :          */
     534             : 
     535          10 :         if ((*pdbproc = dbopen(login, pdata->server)) == NULL) {
     536           0 :                 fprintf(stderr, "Can't connect to server \"%s\".\n", pdata->server);
     537           0 :                 dbloginfree(login);
     538           0 :                 return (FALSE);
     539             :         }
     540          10 :         dbloginfree(login);
     541          10 :         login = NULL;
     542             : 
     543          10 :         return (TRUE);
     544             : 
     545             : }
     546             : 
     547             : static RETCODE
     548          10 : format_column(BCPPARAMDATA *pdata, DBPROCESS *dbproc, BCPFORMAT file_format, int i, int is_last_column)
     549             : {
     550          10 :         int li_coltype = SYBCHAR;
     551          10 :         int host_prefixlen = 0;
     552          10 :         char *host_term = NULL;
     553          10 :         int host_termlen = -1;
     554             : 
     555          10 :         if (file_format == BCPFORMAT_NATIVE) {
     556           0 :                 li_coltype = dbcoltype(dbproc, i);
     557           0 :                 host_prefixlen = -1;
     558          10 :         } else if (is_last_column) {
     559          10 :                 host_term = pdata->rowterm;
     560          10 :                 host_termlen = pdata->rowtermlen;
     561             :         } else {
     562           0 :                 host_term = pdata->fieldterm;
     563           0 :                 host_termlen = pdata->fieldtermlen;
     564             :         }
     565             : 
     566          10 :         return bcp_colfmt(dbproc, i, li_coltype, host_prefixlen, -1, (const BYTE *) host_term, host_termlen, i);
     567             : }
     568             : 
     569             : static int
     570          10 : file_process(BCPPARAMDATA *pdata, DBPROCESS *dbproc, DBINT dir)
     571             : {
     572          10 :         DBINT li_rowsread = 0;
     573          10 :         DBINT li_rowscopied = 0;
     574             :         int i;
     575             :         int li_numcols;
     576             : 
     577          10 :         BCPFORMAT file_format = get_format(pdata);
     578             : 
     579             :         if (file_format == BCPFORMAT_NONE)
     580             :                 return FALSE;
     581             : 
     582          10 :         if (FAIL == bcp_init(dbproc, pdata->dbobject, pdata->hostfilename, pdata->errorfile, dir))
     583             :                 return FALSE;
     584             : 
     585          10 :         if (!set_bcp_hints(pdata, dbproc))
     586             :                 return FALSE;
     587             : 
     588          10 :         bcp_control(dbproc, BCPFIRST, pdata->firstrow);
     589          10 :         bcp_control(dbproc, BCPLAST, pdata->lastrow);
     590          10 :         bcp_control(dbproc, BCPMAXERRS, pdata->maxerrors);
     591             : 
     592          10 :         switch (file_format) {
     593           0 :         case BCPFORMAT_FORMATTED:
     594           0 :                 if (FAIL == bcp_readfmt(dbproc, pdata->formatfile))
     595             :                         return FALSE;
     596             :                 break;
     597             : 
     598             :                 /* The data file does not use TDS nullable types. It uses non-nullable
     599             :                  * representations, and a Length prefix if the target column was nullable.
     600             :                  * The length prefix typically takes value 0 or -1 to indicate a null.
     601             :                  * So, we need to check format of all columns.
     602             :                  */
     603          10 :         case BCPFORMAT_NATIVE:
     604             :         case BCPFORMAT_CHARACTER:
     605          10 :                 li_numcols = bcp_gethostcolcount(dbproc);
     606          20 :                 for (i = 1; i <= li_numcols; ++i) {
     607          10 :                         if (format_column(pdata, dbproc, file_format, i, i == li_numcols) == FAIL) {
     608           0 :                                 fprintf(stderr, "Error in bcp_colfmt col %d\n", i);
     609           0 :                                 return FALSE;
     610             :                         }
     611             :                 }
     612             :                 break;
     613             :         }
     614             : 
     615          10 :         if (file_format == BCPFORMAT_CHARACTER)
     616          10 :                 bcp_control(dbproc, BCPBATCH, pdata->batchsize);
     617             : 
     618             :         /* note: process_Eflag frees data needed by format_column() for NATIVE type,
     619             :          * so call this after the column loop. */
     620          10 :         if (!process_Eflag(pdata, dbproc))
     621             :                 return FALSE;
     622             : 
     623          10 :         printf("\nStarting copy...\n\n");
     624             : 
     625          10 :         if (FAIL == bcp_exec(dbproc, &li_rowscopied)) {
     626           0 :                 fprintf(stderr, "bcp copy %s failed\n", (dir == DB_IN) ? "in" : "out");
     627           0 :                 return FALSE;
     628             :         }
     629             : 
     630          10 :         if (li_rowsread > li_rowscopied)
     631           0 :                 printf("%d rows unable to be copied.\n", li_rowsread - li_rowscopied);
     632             : 
     633          10 :         printf("%d rows copied.\n", li_rowscopied);
     634             : 
     635          10 :         return TRUE;
     636             : }
     637             : 
     638             : static int
     639          10 : setoptions(DBPROCESS *dbproc, BCPPARAMDATA *params)
     640             : {
     641             :         RETCODE fOK;
     642             : 
     643          10 :         if (dbfcmd(dbproc, "set textsize %d ", params->textsize) == FAIL) {
     644           0 :                 fprintf(stderr, "setoptions() could not set textsize at %s:%d\n", __FILE__, __LINE__);
     645             :                 return FALSE;
     646             :         }
     647             : 
     648             :         /*
     649             :          * If the option is a filename, read the SQL text from the file.
     650             :          * Else pass the option verbatim to the server.
     651             :          */
     652          10 :         if (params->options) {
     653             :                 FILE *optFile;
     654             :                 char optBuf[256];
     655             : 
     656           0 :                 if ((optFile = fopen(params->options, "r")) == NULL) {
     657           0 :                         if (dbcmd(dbproc, params->options) == FAIL) {
     658           0 :                                 fprintf(stderr, "setoptions() failed preparing options at %s:%d\n", __FILE__, __LINE__);
     659           0 :                                 return FALSE;
     660             :                         }
     661             :                 } else {
     662           0 :                         while (fgets (optBuf, sizeof(optBuf), optFile) != NULL) {
     663           0 :                                 if (dbcmd(dbproc, optBuf) == FAIL) {
     664           0 :                                         fprintf(stderr, "setoptions() failed preparing options at %s:%d\n", __FILE__, __LINE__);
     665           0 :                                         fclose(optFile);
     666             :                                         return FALSE;
     667             :                                 }
     668             :                         }
     669           0 :                         if (!feof (optFile)) {
     670           0 :                                 perror("freebcp");
     671           0 :                                 fprintf(stderr, "error reading options file \"%s\" at %s:%d\n", params->options, __FILE__, __LINE__);
     672           0 :                                 fclose(optFile);
     673             :                                 return FALSE;
     674             :                         }
     675           0 :                         fclose(optFile);
     676             :                 }
     677             :         }
     678             : 
     679          10 :         if (dbsqlexec(dbproc) == FAIL) {
     680           0 :                 fprintf(stderr, "setoptions() failed sending options at %s:%d\n", __FILE__, __LINE__);
     681             :                 return FALSE;
     682             :         }
     683             : 
     684          20 :         while ((fOK = dbresults(dbproc)) == SUCCEED) {
     685          10 :                 while ((fOK = dbnextrow(dbproc)) == REG_ROW)
     686           0 :                         continue;
     687          10 :                 if (fOK == FAIL) {
     688           0 :                         fprintf(stderr, "setoptions() failed sending options at %s:%d\n", __FILE__, __LINE__);
     689             :                         return FALSE;
     690             :                 }
     691             :         }
     692          10 :         if (fOK == FAIL) {
     693           0 :                 fprintf(stderr, "setoptions() failed sending options at %s:%d\n", __FILE__, __LINE__);
     694             :                 return FALSE;
     695             :         }
     696             : 
     697             :         return TRUE;
     698             : }
     699             : 
     700             : static int
     701          10 : set_bcp_hints(BCPPARAMDATA *pdata, DBPROCESS *pdbproc)
     702             : {
     703             :         /* set hint if any */
     704          10 :         if (pdata->hint) {
     705           0 :                 if (bcp_options(pdbproc, BCPHINTS, (BYTE *) pdata->hint, strlen(pdata->hint)) != SUCCEED) {
     706           0 :                         fprintf(stderr, "db-lib: Unable to set hint \"%s\"\n", pdata->hint);
     707             :                         return FALSE;
     708             :                 }
     709             :         }
     710             :         return TRUE;
     711             : }
     712             : 
     713             : static void
     714           0 : pusage(void)
     715             : {
     716           0 :         fprintf(stderr, "usage:  freebcp [[database_name.]owner.]table_name|query {in | out | queryout } datafile\n");
     717           0 :         fprintf(stderr, "        [-m maxerrors] [-f formatfile] [-e errfile]\n");
     718           0 :         fprintf(stderr, "        [-F firstrow] [-L lastrow] [-b batchsize]\n");
     719           0 :         fprintf(stderr, "        [-n] [-c] [-t field_terminator] [-r row_terminator]\n");
     720           0 :         fprintf(stderr, "        [-U username] [-P password] [-I interfaces_file] [-S server] [-D database]\n");
     721           0 :         fprintf(stderr, "        [-v] [-d] [-h \"hint [,...]\" [-O \"set connection_option on|off, ...]\"\n");
     722           0 :         fprintf(stderr, "        [-A packet size] [-T text or image size] [-E]\n");
     723           0 :         fprintf(stderr, "        [-i input_file] [-o output_file] [-k]\n");
     724           0 :         fprintf(stderr, "        \n");
     725           0 :         fprintf(stderr, "example: freebcp testdb.dbo.inserttest in inserttest.txt -S mssql -U guest -P password -c\n");
     726           0 : }
     727             : 
     728             : static int
     729          20 : err_handler(DBPROCESS *dbproc, int severity, int dberr, int oserr TDS_UNUSED, char *dberrstr, char *oserrstr TDS_UNUSED)
     730             : {
     731             :         static int sent = 0;
     732             : 
     733          20 :         if (dberr == SYBEBBCI) { /* Batch successfully bulk copied to the server */
     734           0 :                 int batch = bcp_getbatchsize(dbproc);
     735           0 :                 printf("%d rows sent to SQL Server.\n", sent += batch);
     736           0 :                 return INT_CANCEL;
     737             :         }
     738             : 
     739          20 :         if (dberr) {
     740          20 :                 fprintf(stderr, "Msg %d, Level %d\n", dberr, severity);
     741          20 :                 fprintf(stderr, "%s\n\n", dberrstr);
     742             :         } else {
     743           0 :                 fprintf(stderr, "DB-LIBRARY error:\n\t");
     744           0 :                 fprintf(stderr, "%s\n", dberrstr);
     745             :         }
     746             : 
     747             :         return INT_CANCEL;
     748             : }
     749             : 
     750             : static int
     751          20 : msg_handler(DBPROCESS *dbproc TDS_UNUSED, DBINT msgno, int msgstate, int severity,
     752             :             char *msgtext, char *srvname, char *procname, int line)
     753             : {
     754             :         /*
     755             :          * If it's a database change message, we'll ignore it.
     756             :          * Also ignore language change message.
     757             :          */
     758          20 :         if (msgno == 5701 || msgno == 5703)
     759             :                 return (0);
     760             : 
     761           0 :         fprintf(stderr, "Msg %ld, Level %d, State %d\n", (long) msgno, severity, msgstate);
     762             : 
     763           0 :         if (strlen(srvname) > 0)
     764           0 :                 fprintf(stderr, "Server '%s', ", srvname);
     765           0 :         if (strlen(procname) > 0)
     766           0 :                 fprintf(stderr, "Procedure '%s', ", procname);
     767           0 :         if (line > 0)
     768           0 :                 fprintf(stderr, "Line %d", line);
     769             : 
     770           0 :         fprintf(stderr, "\n\t%s\n", msgtext);
     771             : 
     772           0 :         return (0);
     773             : }
     774             : 
     775             : static void
     776          10 : bcpparamdata_free(BCPPARAMDATA *params)
     777             : {
     778          10 :         free(params->dbobject);
     779          10 :         free(params->hostfilename);
     780          10 :         free(params->formatfile);
     781          10 :         free(params->errorfile);
     782          10 :         free(params->interfacesfile);
     783          10 :         free(params->fieldterm);
     784          10 :         free(params->rowterm);
     785          10 :         free(params->user);
     786          10 :         free(params->pass);
     787          10 :         free(params->server);
     788          10 :         free(params->dbname);
     789          10 :         free(params->hint);
     790          10 :         free(params->options);
     791          10 :         free(params->charset);
     792          10 :         free(params->inputfile);
     793          10 :         free(params->outputfile);
     794          10 : }

Generated by: LCOV version 1.13