Blame ma_platform_posix.c

Packit Service 17f749
/************************************************************************************
Packit Service 17f749
   Copyright (C) 2014,2020 MariaDB Corporation AB
Packit Service 17f749
   
Packit Service 17f749
   This library is free software; you can redistribute it and/or
Packit Service 17f749
   modify it under the terms of the GNU Library General Public
Packit Service 17f749
   License as published by the Free Software Foundation; either
Packit Service 17f749
   version 2.1 of the License, or (at your option) any later version.
Packit Service 17f749
   
Packit Service 17f749
   This library is distributed in the hope that it will be useful,
Packit Service 17f749
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 17f749
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 17f749
   Library General Public License for more details.
Packit Service 17f749
   
Packit Service 17f749
   You should have received a copy of the GNU Library General Public
Packit Service 17f749
   License along with this library; if not see <http://www.gnu.org/licenses>
Packit Service 17f749
   or write to the Free Software Foundation, Inc., 
Packit Service 17f749
   51 Franklin St., Fifth Floor, Boston, MA 02110, USA
Packit Service 17f749
*************************************************************************************/
Packit Service 17f749
Packit Service 17f749
Packit Service 17f749
/* MariaDB ODBC driver helper functions for platforms other than windows(so far) */
Packit Service 17f749
Packit Service 17f749
/* NOTE If you change something in this program, please consider if other platform's version 
Packit Service 17f749
        of the function you are changing, needs to be changed accordingly */
Packit Service 17f749
Packit Service 17f749
#include <ma_odbc.h>
Packit Service 17f749
#include <stdarg.h>
Packit Service 17f749
#include "ma_conv_charset.h"
Packit Service 17f749
Packit Service 17f749
extern MARIADB_CHARSET_INFO *DmUnicodeCs;
Packit Service 17f749
extern Client_Charset utf8;
Packit Service 17f749
Packit Service 17f749
char LogFile[256];
Packit Service 17f749
Packit Service 17f749
Packit Service 17f749
void InitializeCriticalSection(CRITICAL_SECTION *cs)
Packit Service 17f749
{
Packit Service 17f749
  pthread_mutexattr_t attr;
Packit Service 17f749
Packit Service 17f749
  pthread_mutexattr_init(&attr);
Packit Service 17f749
  pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
Packit Service 17f749
  pthread_mutex_init(cs, &attr);
Packit Service 17f749
}
Packit Service 17f749
Packit Service 17f749
int DSNPrompt_Lookup(MADB_Prompt *prompt, const char * SetupLibName)
Packit Service 17f749
{
Packit Service 17f749
  return MADB_PROMPT_NOT_SUPPORTED;
Packit Service 17f749
}
Packit Service 17f749
Packit Service 17f749
Packit Service 17f749
int DSNPrompt_Free  (MADB_Prompt *prompt)
Packit Service 17f749
{
Packit Service 17f749
  prompt->LibraryHandle= NULL;
Packit Service 17f749
Packit Service 17f749
  return 0;
Packit Service 17f749
}
Packit Service 17f749
Packit Service 17f749
/* Mimicking of VS' _snprintf */
Packit Service 17f749
int _snprintf(char *buffer, size_t count, const char *format, ...)
Packit Service 17f749
{
Packit Service 17f749
    va_list list;
Packit Service 17f749
    va_start(list, format);
Packit Service 17f749
    int result= vsnprintf(buffer, count, format, list);
Packit Service 17f749
Packit Service 17f749
    va_end(list);
Packit Service 17f749
Packit Service 17f749
    /* _snprintf returns negative number if buffer is not big enough */
Packit Service 17f749
    if (result > count)
Packit Service 17f749
    {
Packit Service 17f749
      return count - result - 1;
Packit Service 17f749
    }
Packit Service 17f749
    return result;
Packit Service 17f749
}
Packit Service 17f749
Packit Service 17f749
Packit Service 17f749
int strcpy_s(char *dest, size_t buffer_size, const char *src)
Packit Service 17f749
{
Packit Service 17f749
  size_t src_len;
Packit Service 17f749
Packit Service 17f749
  if (dest == NULL)
Packit Service 17f749
  {
Packit Service 17f749
    return EINVAL;
Packit Service 17f749
  }
Packit Service 17f749
Packit Service 17f749
  if (src == NULL)
Packit Service 17f749
  {
Packit Service 17f749
    *dest= '\0';
Packit Service 17f749
    return EINVAL;
Packit Service 17f749
  }
Packit Service 17f749
Packit Service 17f749
  src_len= strlen(src);
Packit Service 17f749
Packit Service 17f749
  if (buffer_size < src_len + 1)
Packit Service 17f749
  {
Packit Service 17f749
    *dest= 0;
Packit Service 17f749
    return ERANGE;
Packit Service 17f749
  }
Packit Service 17f749
Packit Service 17f749
  memcpy((void*)dest, (void*)src, src_len + 1);
Packit Service 17f749
Packit Service 17f749
  return 0;
Packit Service 17f749
}
Packit Service 17f749
Packit Service 17f749
Packit Service 17f749
const char* GetDefaultLogDir()
Packit Service 17f749
{
Packit Service 17f749
  const char *DefaultLogDir="/tmp";
Packit Service 17f749
  char *tmp= getenv("HOME");
Packit Service 17f749
Packit Service 17f749
  if (tmp)
Packit Service 17f749
  {
Packit Service 17f749
    DefaultLogDir= tmp;
Packit Service 17f749
  }
Packit Service 17f749
Packit Service 17f749
  _snprintf(LogFile, sizeof(LogFile), "%s/maodbc.log", DefaultLogDir);
Packit Service 17f749
Packit Service 17f749
  return LogFile;
Packit Service 17f749
}
Packit Service 17f749
Packit Service 17f749
Packit Service 17f749
/* CharLen < 0 - treat as NTS */
Packit Service 17f749
SQLINTEGER SqlwcsOctetLen(const SQLWCHAR *str, SQLINTEGER *CharLen)
Packit Service 17f749
{
Packit Service 17f749
  SQLINTEGER result= 0, inChars= *CharLen;
Packit Service 17f749
Packit Service 17f749
  if (str)
Packit Service 17f749
  {
Packit Service 17f749
    while (inChars > 0 || (inChars < 0 && *str))
Packit Service 17f749
    {
Packit Service 17f749
      result+= DmUnicodeCs->mb_charlen(*str);
Packit Service 17f749
      --inChars;
Packit Service 17f749
      str+= DmUnicodeCs->mb_charlen(*str)/sizeof(SQLWCHAR);
Packit Service 17f749
    }
Packit Service 17f749
  }
Packit Service 17f749
Packit Service 17f749
  if (*CharLen < 0)
Packit Service 17f749
  {
Packit Service 17f749
    *CharLen-= inChars;
Packit Service 17f749
  }
Packit Service 17f749
  return result;
Packit Service 17f749
}
Packit Service 17f749
Packit Service 17f749
Packit Service 17f749
SQLWCHAR *MADB_ConvertToWchar(const char *Ptr, SQLLEN PtrLength, Client_Charset* cc)
Packit Service 17f749
{
Packit Service 17f749
  SQLWCHAR *WStr= NULL;
Packit Service 17f749
  size_t Length= 0;
Packit Service 17f749
Packit Service 17f749
  if (!Ptr)
Packit Service 17f749
    return WStr;
Packit Service 17f749
Packit Service 17f749
  if (PtrLength == SQL_NTS)
Packit Service 17f749
  {
Packit Service 17f749
    PtrLength= -1;
Packit Service 17f749
    /* To copy terminating null as well */
Packit Service 17f749
    Length= 1;
Packit Service 17f749
  }
Packit Service 17f749
Packit Service 17f749
  if (!cc || !cc->CodePage)
Packit Service 17f749
    cc= &utf;;
Packit Service 17f749
Packit Service 17f749
  Length+= MbstrOctetLen(Ptr, &PtrLength, cc->cs_info);
Packit Service 17f749
Packit Service 17f749
  if ((WStr= (SQLWCHAR *)MADB_CALLOC(sizeof(SQLWCHAR) * (PtrLength + 1))))
Packit Service 17f749
  {
Packit Service 17f749
    size_t wstr_octet_len= sizeof(SQLWCHAR) * (PtrLength + 1);
Packit Service 17f749
    /* TODO: Need error processing. i.e. if MADB_ConvertString returns -1 */
Packit Service 17f749
    MADB_ConvertString(Ptr, &Length, cc->cs_info, (char*)WStr, &wstr_octet_len, DmUnicodeCs, NULL);
Packit Service 17f749
  }
Packit Service 17f749
Packit Service 17f749
  return WStr;
Packit Service 17f749
}
Packit Service 17f749
Packit Service 17f749
Packit Service 17f749
/* {{{ MADB_ConvertFromWChar */
Packit Service 17f749
char *MADB_ConvertFromWChar(const SQLWCHAR *Ptr, SQLINTEGER PtrLength, SQLULEN *Length, Client_Charset *cc,
Packit Service 17f749
                            BOOL *Error)
Packit Service 17f749
{
Packit Service 17f749
  char *AscStr;
Packit Service 17f749
  size_t AscLen= PtrLength, PtrOctetLen;
Packit Service 17f749
  BOOL dummyError= 0;
Packit Service 17f749
  
Packit Service 17f749
  if (Error)
Packit Service 17f749
  {
Packit Service 17f749
    *Error= 0;
Packit Service 17f749
  }
Packit Service 17f749
  else
Packit Service 17f749
  {
Packit Service 17f749
    Error= &dummyError;
Packit Service 17f749
  }
Packit Service 17f749
Packit Service 17f749
  if (cc == NULL || cc->CodePage < 1)
Packit Service 17f749
  {
Packit Service 17f749
    cc= &utf;;
Packit Service 17f749
  }
Packit Service 17f749
Packit Service 17f749
  if (PtrLength == SQL_NTS)
Packit Service 17f749
  {
Packit Service 17f749
    /*-1 - to calculate length as of nts */
Packit Service 17f749
    SQLINTEGER InCharLen= -1;
Packit Service 17f749
    PtrOctetLen= SqlwcsOctetLen(Ptr, &InCharLen);
Packit Service 17f749
    /* Allocating +1 character for terminating symbol */
Packit Service 17f749
    AscLen= (InCharLen+1)*cc->cs_info->char_maxlen;
Packit Service 17f749
  }
Packit Service 17f749
  else
Packit Service 17f749
  {
Packit Service 17f749
    /* PtrLength is in characters. MADB_ConvertString(iconv) needs bytes */
Packit Service 17f749
    PtrOctetLen= SqlwcsOctetLen(Ptr, &PtrLength);
Packit Service 17f749
    AscLen= PtrLength*cc->cs_info->char_maxlen;
Packit Service 17f749
  }
Packit Service 17f749
Packit Service 17f749
  if (!(AscStr = (char *)MADB_CALLOC(AscLen)))
Packit Service 17f749
    return NULL;
Packit Service 17f749
Packit Service 17f749
  AscLen= MADB_ConvertString((char*)Ptr, &PtrOctetLen, DmUnicodeCs, AscStr, &AscLen, cc->cs_info, Error);
Packit Service 17f749
Packit Service 17f749
  if (AscLen != (size_t)-1)
Packit Service 17f749
  {
Packit Service 17f749
    if (PtrLength == -1 && AscLen > 0)
Packit Service 17f749
    {
Packit Service 17f749
      --AscLen;
Packit Service 17f749
    }
Packit Service 17f749
  }
Packit Service 17f749
  else
Packit Service 17f749
  {
Packit Service 17f749
    MADB_FREE(AscStr);
Packit Service 17f749
    AscLen= 0;
Packit Service 17f749
  }
Packit Service 17f749
  if (Length)
Packit Service 17f749
    *Length= (SQLINTEGER)AscLen;
Packit Service 17f749
Packit Service 17f749
  return AscStr;
Packit Service 17f749
}
Packit Service 17f749
/* }}} */
Packit Service 17f749
Packit Service 17f749
/* {{{ MADB_ConvertAnsi2Unicode
Packit Service 17f749
       @AnsiLength[in]    - number of bytes to copy, negative if AnsiString is Null terminated and the terminating blank has to be copied
Packit Service 17f749
       @UnicodeLength[in] - size of output buffer in chars, that effectively mean in SQLWCHAR units
Packit Service 17f749
       @LengthIndicator[out] - number of available characters not counting terminating null(unless it was included in AnsiLength, and IsNull
Packit Service 17f749
                            is FALSE) 
Packit Service 17f749
       @IsNull[in]        - whether to copy terminating blank. The value has to be 1 or 0(TRUE/FALSE)
Packit Service 17f749
                            If AnsiString is negative, its value is neglected(null is copied)
Packit Service 17f749
       @returns 1 in case of error, 0 otherwise */
Packit Service 17f749
int MADB_ConvertAnsi2Unicode(Client_Charset *cc, const char *AnsiString, SQLLEN AnsiLength, 
Packit Service 17f749
                             SQLWCHAR *UnicodeString, SQLLEN UnicodeLength, 
Packit Service 17f749
                             SQLLEN *LengthIndicator, BOOL IsNull, MADB_Error *Error)
Packit Service 17f749
{
Packit Service 17f749
  SQLINTEGER  RequiredLength;
Packit Service 17f749
  SQLWCHAR   *Tmp= UnicodeString;
Packit Service 17f749
  int         rc= 0, error;
Packit Service 17f749
  size_t      SrcOctetLen, DestOctetLen;
Packit Service 17f749
Packit Service 17f749
  if (LengthIndicator)
Packit Service 17f749
    *LengthIndicator= 0;
Packit Service 17f749
Packit Service 17f749
  if (Error)
Packit Service 17f749
    MADB_CLEAR_ERROR(Error);
Packit Service 17f749
Packit Service 17f749
  if (!AnsiLength || UnicodeLength < 0)
Packit Service 17f749
  {
Packit Service 17f749
    if (Error)
Packit Service 17f749
      MADB_SetError(Error, MADB_ERR_HY090, NULL, 0);
Packit Service 17f749
    return 1;
Packit Service 17f749
  }
Packit Service 17f749
Packit Service 17f749
  if (AnsiLength == SQL_NTS || AnsiLength == -1)
Packit Service 17f749
  {
Packit Service 17f749
    IsNull= 1;
Packit Service 17f749
    AnsiLength= strlen(AnsiString);
Packit Service 17f749
  }
Packit Service 17f749
Packit Service 17f749
  /* calculate required length */
Packit Service 17f749
  RequiredLength= MbstrCharLen(AnsiString, AnsiLength, cc->cs_info) + IsNull;
Packit Service 17f749
Packit Service 17f749
  /* Set LengthIndicator */
Packit Service 17f749
  if (LengthIndicator)
Packit Service 17f749
    *LengthIndicator= RequiredLength - IsNull;
Packit Service 17f749
  /* No buffer length, no need to copy - got length and run */
Packit Service 17f749
  if (!UnicodeLength)
Packit Service 17f749
    return 0;
Packit Service 17f749
Packit Service 17f749
  if (RequiredLength > UnicodeLength)
Packit Service 17f749
  {
Packit Service 17f749
    Tmp= (SQLWCHAR *)malloc(RequiredLength * sizeof(SQLWCHAR));
Packit Service 17f749
  }
Packit Service 17f749
  else
Packit Service 17f749
  {
Packit Service 17f749
    RequiredLength= UnicodeLength;
Packit Service 17f749
  }
Packit Service 17f749
Packit Service 17f749
  SrcOctetLen= AnsiLength + IsNull;
Packit Service 17f749
  DestOctetLen= sizeof(SQLWCHAR) * RequiredLength;
Packit Service 17f749
Packit Service 17f749
  RequiredLength= MADB_ConvertString(AnsiString, &SrcOctetLen, cc->cs_info, 
Packit Service 17f749
                                        (char*)Tmp, &DestOctetLen, DmUnicodeCs, &error);
Packit Service 17f749
Packit Service 17f749
  if (RequiredLength < 1)
Packit Service 17f749
  {
Packit Service 17f749
    if (Error)
Packit Service 17f749
      MADB_SetError(Error, MADB_ERR_HY000, "Ansi to Unicode conversion error occurred", error);
Packit Service 17f749
    rc= 1;
Packit Service 17f749
    goto end;
Packit Service 17f749
  }
Packit Service 17f749
Packit Service 17f749
  if (LengthIndicator)
Packit Service 17f749
    *LengthIndicator= SqlwcsCharLen(Tmp, RequiredLength);
Packit Service 17f749
Packit Service 17f749
  /* Truncation */
Packit Service 17f749
  if (Tmp != UnicodeString)
Packit Service 17f749
  {
Packit Service 17f749
    memcpy((void*)UnicodeString, (void*)Tmp, (UnicodeLength-1)*sizeof(SQLWCHAR));
Packit Service 17f749
    *(UnicodeString + UnicodeLength - 1)= 0;
Packit Service 17f749
Packit Service 17f749
    if (Error)
Packit Service 17f749
      MADB_SetError(Error, MADB_ERR_01004, NULL, 0);
Packit Service 17f749
  }
Packit Service 17f749
end:
Packit Service 17f749
  if (Tmp != UnicodeString)
Packit Service 17f749
    free(Tmp);
Packit Service 17f749
  return rc;
Packit Service 17f749
}
Packit Service 17f749
/* }}} */
Packit Service 17f749
Packit Service 17f749
/* {{{ MADB_ConvertAnsi2Unicode
Packit Service 17f749
       @returns number of characters available at Src */
Packit Service 17f749
SQLLEN MADB_SetString(Client_Charset* cc, void *Dest, SQLULEN DestLength,
Packit Service 17f749
                      const char *Src, SQLLEN SrcLength/*bytes*/, MADB_Error *Error)
Packit Service 17f749
{
Packit Service 17f749
  SQLLEN Length= 0;
Packit Service 17f749
Packit Service 17f749
  if (SrcLength == SQL_NTS)
Packit Service 17f749
  {
Packit Service 17f749
    if (Src != NULL)
Packit Service 17f749
    {
Packit Service 17f749
      /* Thinking about utf8 - Should be probably len in characters */
Packit Service 17f749
      SrcLength= strlen(Src);
Packit Service 17f749
    }
Packit Service 17f749
    else
Packit Service 17f749
    {
Packit Service 17f749
      SrcLength= 0;
Packit Service 17f749
    }
Packit Service 17f749
  }
Packit Service 17f749
Packit Service 17f749
  /* Not enough space */
Packit Service 17f749
  if (!DestLength || !Dest)
Packit Service 17f749
  {
Packit Service 17f749
    if (Dest)
Packit Service 17f749
      MADB_SetError(Error, MADB_ERR_01004, NULL, 0);
Packit Service 17f749
    if (!cc)
Packit Service 17f749
      return SrcLength;
Packit Service 17f749
    else
Packit Service 17f749
    {
Packit Service 17f749
      Length= MbstrCharLen(Src, SrcLength, cc->cs_info);
Packit Service 17f749
Packit Service 17f749
      /* In case of !DestLength || !Dest(application didn't give buffer and probably wants to know required length)
Packit Service 17f749
       * we most probably have empty Src, and Length will be equal 0 in this case.
Packit Service 17f749
       * Taking source length as character length. MultiByteToWideChar on windows does that for us */
Packit Service 17f749
      return Length == 0 && SrcLength > 0 ? SrcLength : Length;
Packit Service 17f749
    }
Packit Service 17f749
  }
Packit Service 17f749
Packit Service 17f749
  if (!SrcLength || !Src || !strlen(Src))
Packit Service 17f749
  {
Packit Service 17f749
    memset((char *)Dest, 0, cc ? sizeof(SQLWCHAR) : sizeof(SQLCHAR));
Packit Service 17f749
    return 0;
Packit Service 17f749
  }
Packit Service 17f749
Packit Service 17f749
  if (!cc)
Packit Service 17f749
  {
Packit Service 17f749
    strncpy_s((char *)Dest, DestLength, Src ? Src : "", _TRUNCATE);
Packit Service 17f749
    /* strncpy does not write null at the end */
Packit Service 17f749
    *((char *)Dest + MIN(SrcLength, DestLength - 1))= '\0';
Packit Service 17f749
Packit Service 17f749
    if (Error && SrcLength >= DestLength)
Packit Service 17f749
      MADB_SetError(Error, MADB_ERR_01004, NULL, 0);
Packit Service 17f749
    return SrcLength;
Packit Service 17f749
  }
Packit Service 17f749
  else
Packit Service 17f749
  {
Packit Service 17f749
    MADB_ConvertAnsi2Unicode(cc, Src, -1, (SQLWCHAR *)Dest, DestLength, &Length, TRUE, Error);
Packit Service 17f749
    return Length;
Packit Service 17f749
  }
Packit Service 17f749
}
Packit Service 17f749
/* }}} */
Packit Service 17f749
Packit Service 17f749
Packit Service 17f749
/* Stub - needed on windows only */
Packit Service 17f749
int GetSourceAnsiCs(Client_Charset *cc)
Packit Service 17f749
{
Packit Service 17f749
  CopyClientCharset(&utf8, cc);
Packit Service 17f749
  return cc->CodePage;
Packit Service 17f749
}
Packit Service 17f749
Packit Service 17f749
/* {{{ MADB_DSN_PossibleConnect(MADB_Dsn *) */
Packit Service 17f749
BOOL MADB_DSN_PossibleConnect(MADB_Dsn *Dsn)
Packit Service 17f749
{
Packit Service 17f749
  return Dsn->Socket || (Dsn->ServerName && Dsn->Port > 0 && Dsn->IsTcpIp);
Packit Service 17f749
}
Packit Service 17f749
Packit Service 17f749
Packit Service 17f749
/* Stub - atm it looks like we don't need to do anything here */
Packit Service 17f749
char* MADB_GetDefaultPluginsDir(char* Buffer, size_t Size)
Packit Service 17f749
{
Packit Service 17f749
  return NULL;
Packit Service 17f749
}