ODBC build fixes

* Require SQLGetPrivateProfileString in ODBC libraries

* Attempt to fix reported deadlock with unixODBC by rearranging
functions
This commit is contained in:
Evan Miller 2020-08-12 15:05:25 -04:00
parent acbace242c
commit 362938f17c
4 changed files with 60 additions and 286 deletions

View File

@ -68,7 +68,7 @@ AM_CONDITIONAL(SQL, test x$sql = xtrue)
AC_SUBST(SQL)
AC_SUBST(LFLAGS)
CFLAGS="$CFLAGS -Wall -Wstrict-prototypes -Werror"
CFLAGS="$CFLAGS -Wall -Werror"
AS_CASE([$host],
[*mingw*|*cygwin*], [LDFLAGS="$LDFLAGS -no-undefined"], [])
AS_CASE([$host],
@ -104,10 +104,8 @@ if test "$with_iodbc"; then
OLDLDFLAGS=$LDFLAGS
LDFLAGS="$LDFLAGS $ODBC_LIBS"
AC_CHECK_LIB(iodbcinst, SQLGetPrivateProfileString,
[ODBC_LIBS="$ODBC_LIBS -liodbcinst"
AC_DEFINE_UNQUOTED(HAVE_SQLGETPRIVATEPROFILESTRING, 1,
[Define to 1 if you have the SQLGetPrivateProfileString function.])])
AC_CHECK_LIB(iodbcinst, SQLGetPrivateProfileString, [FOO=bar],
AC_MSG_ERROR([Could not find SQLGetPrivateProfileString in -liodbcinst]))
LDFLAGS=$OLDLDFLAGS
fi
@ -127,10 +125,8 @@ if test "$with_unixodbc"; then
OLDLDFLAGS=$LDFLAGS
LDFLAGS="$LDFLAGS $ODBC_LIBS"
AC_CHECK_LIB(odbcinst, SQLGetPrivateProfileString,
[ODBC_LIBS="$ODBC_LIBS -lodbcinst"
AC_DEFINE_UNQUOTED(HAVE_SQLGETPRIVATEPROFILESTRING, 1,
[Define to 1 if you have the SQLGetPrivateProfileString function.])])
AC_CHECK_LIB(odbcinst, SQLGetPrivateProfileString, [ODBC_LIBS="$ODBC_LIBS -lodbcinst"],
AC_MSG_ERROR([Could not find SQLGetPrivateProfileString in -lodbcinst]))
LDFLAGS=$OLDLDFLAGS
fi
@ -146,6 +142,9 @@ if test "x$HAVE_ODBC" = "xtrue"; then
OPTDIRS="$OPTDIRS odbc"
fi
dnl Turn on -Wstrict-prototypes here because AC_CHECK_LIB is dumb
CFLAGS="$CFLAGS -Wstrict-prototypes"
dnl Conditionally build odbc wide version
AM_CONDITIONAL(ICONV, test "$am_cv_func_iconv" = "yes")

View File

@ -2,8 +2,8 @@ AUTOMAKE_OPTIONS = subdir-objects
noinst_PROGRAMS = unittest
lib_LTLIBRARIES = libmdbodbc.la
AM_CFLAGS = -I$(top_srcdir)/include $(GLIB_CFLAGS) $(ODBC_CFLAGS)
libmdbodbc_la_SOURCES = odbc.c connectparams.c mdbodbc.h connectparams.h
libmdbodbc_la_LIBADD = ../libmdb/libmdb.la ../sql/libmdbsql.la
libmdbodbc_la_SOURCES = odbc.c connectparams.c
libmdbodbc_la_LIBADD = ../libmdb/libmdb.la ../sql/libmdbsql.la $(ODBC_LIBS)
libmdbodbc_la_LDFLAGS = -avoid-version -export-symbols-regex '^(SQL|ODBCINST)'
if FAKE_GLIB
libmdbodbc_la_SOURCES += ../libmdb/fakeglib.c
@ -15,5 +15,5 @@ libmdbodbcW_la_LIBADD = $(libmdbodbc_la_LIBADD) @LIBICONV@
libmdbodbcW_la_LDFLAGS = $(libmdbodbc_la_LDFLAGS)
libmdbodbcW_la_CFLAGS = $(AM_CFLAGS) -D ENABLE_ODBC_W=1
endif
LIBS = $(GLIB_LIBS) $(ODBC_LIBS)
LIBS = $(GLIB_LIBS)
unittest_LDADD = libmdbodbc.la ../libmdb/libmdb.la ../sql/libmdbsql.la

View File

@ -23,6 +23,11 @@
#include <string.h>
#include <sys/stat.h>
#include <ctype.h>
#ifdef UNIXODBC
#include <odbcinstext.h>
#else
#include <odbcinst.h>
#endif
#include "connectparams.h"
/*
@ -42,20 +47,6 @@
static char line[max_line];
static guint HashFunction (gconstpointer key);
#if HAVE_SQLGETPRIVATEPROFILESTRING
#include <sqltypes.h>
extern int SQLGetPrivateProfileString( LPCSTR lpszSection,
LPCSTR lpszEntry,
LPCSTR lpszDefault,
LPSTR lpszRetBuffer,
int cbRetBuffer,
LPCSTR lpszFilename);
#else
static GString* GetIniFileName (void);
static int FileExists (const gchar* name);
static int FindSection (FILE* stream, const char* section);
static int GetNextItem (FILE* stream, char** name, char** value);
#endif //HAVE_SQLGETPRIVATEPROFILESTRING
static void visit (gpointer key, gpointer value, gpointer user_data);
static void cleanup (gpointer key, gpointer value, gpointer user_data);
@ -98,95 +89,18 @@ void FreeConnectParams (ConnectParams* params)
}
}
#if !HAVE_SQLGETPRIVATEPROFILESTRING
static int LoadDSN (
const gchar* iniFileName, const gchar* dsnName, GHashTable* table)
{
FILE* stream;
gchar* name;
gchar* value;
if ((stream = fopen (iniFileName, "r" )) != NULL )
{
if (!FindSection (stream, dsnName))
{
g_printerr ("Couldn't find DSN %s in %s\n", dsnName, iniFileName);
fclose (stream);
return 0;
}
else
{
while (GetNextItem (stream, &name, &value))
{
g_hash_table_insert (table, g_strdup (name), g_strdup (value));
}
}
fclose( stream );
}
return 1;
}
/*
* Find the settings for the specified ODBC DSN
*/
gboolean LookupDSN (ConnectParams* params, const gchar* dsnName)
{
if (!params) {
fprintf(stderr,"LookupDSN: no parameters, returning FALSE\n");
return FALSE;
}
/*
* Set the DSN name property
*/
/* params->dsnName = g_string_assign (params->dsnName, dsnName); */
/*
* Search for the ODBC ini file
*/
if (!(params->iniFileName = GetIniFileName ())) {
fprintf(stderr,"LookupDSN: GetIniFileName returned FALSE\n");
return FALSE;
}
if (!LoadDSN (params->iniFileName->str, dsnName, params->table)) {
fprintf(stderr,"LookupDSN: LoadDSN returned FALSE\n");
return FALSE;
}
return TRUE;
}
/*
* Get the value of a given ODBC Connection Parameter
*/
gchar* GetConnectParam (ConnectParams* params, const gchar* paramName)
{
if (!params || !params->table)
return NULL;
return g_hash_table_lookup (params->table, paramName);
}
#else
gboolean LookupDSN (ConnectParams* params, const gchar* dsnName)
{
return TRUE;
}
gchar* GetConnectParam (ConnectParams* params, const gchar* paramName)
{
static char tmp[FILENAME_MAX];
/* use old servername */
tmp[0] = '\0';
if (SQLGetPrivateProfileString(params->dsnName->str, paramName, "", tmp, FILENAME_MAX, "odbc.ini") > 0) {
if (SQLGetPrivateProfileString(params->dsnName->str, paramName, "", tmp, sizeof(tmp), "odbc.ini") > 0) {
return tmp;
}
return NULL;
}
#endif /* !HAVE_SQLGETPRIVATEPROFILESTRING */
/*
* Apply a connection string to the ODBC Parameter Settings
@ -379,135 +293,6 @@ static guint HashFunction (gconstpointer key)
return value;
}
#if !HAVE_SQLGETPRIVATEPROFILESTRING
static GString* GetIniFileName ()
{
char* setting;
GString* iniFileName = g_string_new ("");
/*
* First, try the ODBCINI environment variable
*/
if ((setting = getenv ("ODBCINI")) != NULL)
{
g_string_assign (iniFileName, getenv ("ODBCINI"));
if (FileExists (iniFileName->str))
return iniFileName;
g_string_assign (iniFileName, "");
}
/*
* Second, try the HOME environment variable
*/
if ((setting = getenv ("HOME")) != NULL)
{
g_string_assign (iniFileName, setting);
iniFileName = g_string_append (iniFileName, "/.odbc.ini");
if (FileExists (iniFileName->str))
return iniFileName;
g_string_assign (iniFileName, "");
}
/*
* As a last resort, try SYS_ODBC_INI
*/
g_string_assign (iniFileName, SYS_ODBC_INI);
if (FileExists (iniFileName->str))
return iniFileName;
g_string_assign (iniFileName, "");
return iniFileName;
}
static int FileExists (const gchar* name)
{
struct stat fileStat;
return (stat (name, &fileStat) == 0);
}
static int FindSection (FILE* stream, const char* section)
{
char* s;
char sectionPattern[max_line];
int len;
strcpy (sectionPattern, "[");
strcat (sectionPattern, section);
strcat (sectionPattern, "]");
s = fgets (line, max_line, stream);
while (s != NULL)
{
/*
* Get rid of the newline character
*/
len = strlen (line);
if (len > 0) line[strlen (line) - 1] = '\0';
/*
* look for the section header
*/
if (strcmp (line, sectionPattern) == 0)
return 1;
s = fgets (line, max_line, stream);
}
return 0;
}
static int GetNextItem (FILE* stream, char** name, char** value)
{
char* s;
int len;
char equals[] = "="; /* used for seperator for strtok */
char* token;
if (name == NULL || value == NULL)
{
g_printerr ("GetNextItem, invalid parameters");
return 0;
}
s = fgets (line, max_line, stream);
if (s == NULL)
{
//perror ("fgets");
return 0;
}
/*
* Get rid of the newline character
*/
len = strlen (line);
if (len > 0) line[strlen (line) - 1] = '\0';
/*
* Extract name from name = value
*/
if ((token = strtok (line, equals)) == NULL) return 0;
len = strlen (token);
while (len > 0 && isspace(token[len-1]))
{
len--;
token[len] = '\0';
}
*name = token;
/*
* extract value from name = value
*/
token = strtok (NULL, equals);
if (token == NULL) return 0;
while (*token && isspace(token[0]))
token++;
*value = token;
return 1;
}
#endif //!HAVE_SQLGETPRIVATEPROFILESTRING
static void visit (gpointer key, gpointer value, gpointer user_data)
{
FILE* output = (FILE*) user_data;
@ -522,7 +307,6 @@ static void cleanup (gpointer key, gpointer value, gpointer user_data)
#ifdef UNIXODBC
#include <odbcinstext.h>
int
ODBCINSTGetProperties(HODBCINSTPROPERTY hLastProperty)

View File

@ -200,7 +200,6 @@ SQLRETURN SQL_API SQLDriverConnect(
SQLSMALLINT *pcbConnStrOut,
SQLUSMALLINT fDriverCompletion)
{
char* dsn = NULL;
char* database = NULL;
ConnectParams* params;
SQLRETURN ret;
@ -210,11 +209,7 @@ SQLRETURN SQL_API SQLDriverConnect(
params = ((struct _hdbc*) hdbc)->params;
if ((dsn = ExtractDSN (params, (gchar*)szConnStrIn))) {
if (!LookupDSN (params, dsn)){
LogError ("Could not find DSN in odbc.ini");
return SQL_ERROR;
}
if (ExtractDSN(params, (gchar*)szConnStrIn)) {
SetConnectString (params, (gchar*)szConnStrIn);
if (!(database = GetConnectParam (params, "Database"))){
LogError ("Could not find Database parameter in '%s'", szConnStrIn);
@ -471,7 +466,6 @@ SQLRETURN SQL_API SQLSetEnvAttr (
return SQL_SUCCESS;
}
SQLRETURN SQL_API SQLBindParameter(
SQLHSTMT hstmt,
SQLUSMALLINT ipar,
@ -491,26 +485,6 @@ SQLRETURN SQL_API SQLBindParameter(
return SQL_SUCCESS;
}
SQLRETURN SQL_API SQLAllocHandle(
SQLSMALLINT HandleType,
SQLHANDLE InputHandle,
SQLHANDLE * OutputHandle)
{
TRACE("SQLAllocHandle");
switch(HandleType) {
case SQL_HANDLE_STMT:
return SQLAllocStmt(InputHandle,OutputHandle);
break;
case SQL_HANDLE_DBC:
return SQLAllocConnect(InputHandle,OutputHandle);
break;
case SQL_HANDLE_ENV:
return SQLAllocEnv(OutputHandle);
break;
}
return SQL_ERROR;
}
SQLRETURN SQL_API SQLAllocConnect(
SQLHENV henv,
SQLHDBC *phdbc)
@ -563,6 +537,27 @@ SQLRETURN SQL_API SQLAllocStmt(
return SQL_SUCCESS;
}
SQLRETURN SQL_API SQLAllocHandle(
SQLSMALLINT HandleType,
SQLHANDLE InputHandle,
SQLHANDLE * OutputHandle)
{
SQLRETURN retval = SQL_ERROR;
TRACE("SQLAllocHandle");
switch(HandleType) {
case SQL_HANDLE_STMT:
retval = SQLAllocStmt(InputHandle,OutputHandle);
break;
case SQL_HANDLE_DBC:
retval = SQLAllocConnect(InputHandle,OutputHandle);
break;
case SQL_HANDLE_ENV:
retval = SQLAllocEnv(OutputHandle);
break;
}
return retval;
}
SQLRETURN SQL_API SQLBindCol(
SQLHSTMT hstmt,
SQLUSMALLINT icol,
@ -639,12 +634,7 @@ SQLRETURN SQL_API SQLConnect(
params->dsnName = g_string_assign (params->dsnName, (gchar*)szDSN);
if (!LookupDSN (params, (gchar*)szDSN))
{
LogError ("Could not find DSN in odbc.ini");
return SQL_ERROR;
}
else if (!(database = GetConnectParam (params, "Database")))
if (!(database = GetConnectParam (params, "Database")))
{
LogError ("Could not find Database parameter in '%s'", szDSN);
return SQL_ERROR;
@ -1101,25 +1091,6 @@ SQLRETURN SQL_API SQLFetch(
}
}
SQLRETURN SQL_API SQLFreeHandle(
SQLSMALLINT HandleType,
SQLHANDLE Handle)
{
TRACE("SQLFreeHandle");
switch(HandleType) {
case SQL_HANDLE_STMT:
SQLFreeStmt(Handle,SQL_DROP);
break;
case SQL_HANDLE_DBC:
SQLFreeConnect(Handle);
break;
case SQL_HANDLE_ENV:
SQLFreeEnv(Handle);
break;
}
return SQL_SUCCESS;
}
SQLRETURN SQL_API SQLFreeConnect(
SQLHDBC hdbc)
{
@ -1189,6 +1160,26 @@ SQLRETURN SQL_API SQLFreeStmt(
return SQL_SUCCESS;
}
SQLRETURN SQL_API SQLFreeHandle(
SQLSMALLINT HandleType,
SQLHANDLE Handle)
{
SQLRETURN retval = SQL_ERROR;
TRACE("SQLFreeHandle");
switch(HandleType) {
case SQL_HANDLE_STMT:
retval = SQLFreeStmt(Handle,SQL_DROP);
break;
case SQL_HANDLE_DBC:
retval = SQLFreeConnect(Handle);
break;
case SQL_HANDLE_ENV:
retval = SQLFreeEnv(Handle);
break;
}
return retval;
}
SQLRETURN SQL_API SQLGetStmtAttr (
SQLHSTMT StatementHandle,
SQLINTEGER Attribute,