1/* 2 * SQLInstallDriver.c 3 * 4 * $Id: SQLInstallDriver.c,v 1.10 2006/01/20 15:58:35 source Exp $ 5 * 6 * Install a driver 7 * 8 * The iODBC driver manager. 9 * 10 * Copyright (C) 1996-2006 by OpenLink Software <iodbc@openlinksw.com> 11 * All Rights Reserved. 12 * 13 * This software is released under the terms of either of the following 14 * licenses: 15 * 16 * - GNU Library General Public License (see LICENSE.LGPL) 17 * - The BSD License (see LICENSE.BSD). 18 * 19 * Note that the only valid version of the LGPL license as far as this 20 * project is concerned is the original GNU Library General Public License 21 * Version 2, dated June 1991. 22 * 23 * While not mandated by the BSD license, any patches you make to the 24 * iODBC source code may be contributed back into the iODBC project 25 * at your discretion. Contributions will benefit the Open Source and 26 * Data Access community as a whole. Submissions may be made at: 27 * 28 * http://www.iodbc.org 29 * 30 * 31 * GNU Library Generic Public License Version 2 32 * ============================================ 33 * This library is free software; you can redistribute it and/or 34 * modify it under the terms of the GNU Library General Public 35 * License as published by the Free Software Foundation; only 36 * Version 2 of the License dated June 1991. 37 * 38 * This library is distributed in the hope that it will be useful, 39 * but WITHOUT ANY WARRANTY; without even the implied warranty of 40 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 41 * Library General Public License for more details. 42 * 43 * You should have received a copy of the GNU Library General Public 44 * License along with this library; if not, write to the Free 45 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 46 * 47 * 48 * The BSD License 49 * =============== 50 * Redistribution and use in source and binary forms, with or without 51 * modification, are permitted provided that the following conditions 52 * are met: 53 * 54 * 1. Redistributions of source code must retain the above copyright 55 * notice, this list of conditions and the following disclaimer. 56 * 2. Redistributions in binary form must reproduce the above copyright 57 * notice, this list of conditions and the following disclaimer in 58 * the documentation and/or other materials provided with the 59 * distribution. 60 * 3. Neither the name of OpenLink Software Inc. nor the names of its 61 * contributors may be used to endorse or promote products derived 62 * from this software without specific prior written permission. 63 * 64 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 65 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 66 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 67 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OPENLINK OR 68 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 69 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 70 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 71 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 72 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 73 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 74 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 75 */ 76 77 78#include <iodbc.h> 79#include <odbcinst.h> 80#include <unicode.h> 81 82#include "misc.h" 83#include "inifile.h" 84#include "iodbc_error.h" 85 86#ifdef _MAC 87# include <getfpn.h> 88#endif 89 90#if !defined(WINDOWS) && !defined(WIN32) && !defined(OS2) && !defined(macintosh) 91# include <pwd.h> 92# include <unistd.h> 93# include <sys/types.h> 94# include <sys/stat.h> 95# define UNIX_PWD 96#endif 97 98 99BOOL 100InstallDriverPath (LPSTR lpszPath, WORD cbPathMax, WORD * pcbPathOut, 101 LPSTR envname) 102{ 103#ifdef _MAC 104 OSErr result; 105 long fldrDid; 106 short fldrRef; 107#endif 108 BOOL retcode = FALSE; 109 char *ptr; 110 111 lpszPath[cbPathMax - 1] = 0; 112 113#if !defined(UNIX_PWD) 114#ifdef _MAC 115 result = FindFolder (kOnSystemDisk, kExtensionFolderType, kDontCreateFolder, 116 &fldrRef, &fldrDid); 117 if (result != noErr) 118 { 119 PUSH_ERROR (ODBC_ERROR_GENERAL_ERR); 120 goto quit; 121 } 122 123 ptr = get_full_pathname (fldrDid, fldrRef); 124 STRNCPY (lpszPath, ptr, cbPathMax - 1); 125 free (ptr); 126 127 if (STRLEN (ptr) >= cbPathMax) 128 { 129 PUSH_ERROR (ODBC_ERROR_INVALID_BUFF_LEN); 130 goto quit; 131 } 132 else 133 goto done; 134#else 135 /* 136 * On Windows, there is only one place to look 137 */ 138 if (GetWindowsDirectory ((LPSTR) buf, cbPathMax) >= cbPathMax) 139 { 140 PUSH_ERROR (ODBC_ERROR_INVALID_BUFF_LEN); 141 goto quit; 142 } 143 else 144 goto done; 145#endif 146#else 147 148 /* 149 * 1. Check $ODBCDRIVERS environment variable 150 */ 151 if ((ptr = getenv (envname))) 152 if (access (ptr, R_OK | W_OK | X_OK) == 0) 153 { 154 STRNCPY (lpszPath, ptr, cbPathMax - 1); 155 if (STRLEN (ptr) >= cbPathMax) 156 { 157 PUSH_ERROR (ODBC_ERROR_INVALID_BUFF_LEN); 158 goto quit; 159 } 160 else 161 goto done; 162 } 163 164 /* 165 * 2. Check /usr/local/lib and /usr/lib 166 */ 167#ifdef _BE 168 STRNCPY (lpszPath, "/boot/beos/system/lib", cbPathMax - 1); 169 if (STRLEN (lpszPath) != STRLEN ("/boot/beos/system/lib")) 170#else 171 STRNCPY (lpszPath, "/usr/local/lib", cbPathMax - 1); 172 if (STRLEN (lpszPath) != STRLEN ("/usr/local/lib")) 173#endif 174 { 175 PUSH_ERROR (ODBC_ERROR_INVALID_BUFF_LEN); 176 goto quit; 177 } 178 if (access (lpszPath, R_OK | W_OK | X_OK) == 0) 179 goto done; 180 181#ifdef _BE 182 STRNCPY (lpszPath, "/boot/home/config/lib", cbPathMax - 1); 183 if (STRLEN (lpszPath) != STRLEN ("/boot/home/config/lib")) 184#else 185 STRNCPY (lpszPath, "/usr/lib", cbPathMax - 1); 186 if (STRLEN (lpszPath) != STRLEN ("/usr/lib")) 187#endif 188 { 189 PUSH_ERROR (ODBC_ERROR_INVALID_BUFF_LEN); 190 goto quit; 191 } 192 if (access (lpszPath, R_OK | W_OK | X_OK) == 0) 193 goto done; 194 195 /* 196 * 3. Check either $HOME 197 */ 198 if (!(ptr = getenv ("HOME"))) 199 { 200 ptr = (char *) getpwuid (getuid ()); 201 if (ptr) 202 ptr = ((struct passwd *) ptr)->pw_dir; 203 } 204 205 if (ptr) 206 { 207#ifdef _BE 208 sprintf (lpszPath, "%s/config/lib", ptr); 209#else 210 sprintf (lpszPath, "%s/lib", ptr); 211#endif 212 if (access (lpszPath, R_OK | W_OK | X_OK) == 0) 213 goto done; 214 } 215 216 if (!mkdir (lpszPath, 0755)) 217 goto done; 218 219#endif 220 221 SQLPostInstallerError (ODBC_ERROR_GENERAL_ERR, 222 "Cannot retrieve a directory where to install the driver or translator."); 223 goto quit; 224 225done: 226 retcode = TRUE; 227 228quit: 229 if (pcbPathOut) 230 *pcbPathOut = STRLEN (lpszPath); 231 return retcode; 232} 233 234 235BOOL INSTAPI 236SQLInstallDriver (LPCSTR lpszInfFile, LPCSTR lpszDriver, LPSTR lpszPath, 237 WORD cbPathMax, WORD * pcbPathOut) 238{ 239 PCONFIG pCfg = NULL, pOdbcCfg = NULL; 240 BOOL retcode = FALSE; 241 242 /* Check input parameters */ 243 CLEAR_ERROR (); 244 if (!lpszDriver || !STRLEN (lpszDriver)) 245 { 246 PUSH_ERROR (ODBC_ERROR_INVALID_PARAM_SEQUENCE); 247 goto quit; 248 } 249 250 if (!lpszPath || !cbPathMax) 251 { 252 PUSH_ERROR (ODBC_ERROR_INVALID_BUFF_LEN); 253 goto quit; 254 } 255 256 /* Write the out path */ 257 if (!InstallDriverPath (lpszPath, cbPathMax, pcbPathOut, "ODBCDRIVERS")) 258 goto quit; 259 260 /* Else go through user/system odbcinst.ini */ 261 switch (configMode) 262 { 263 case ODBC_BOTH_DSN: 264 case ODBC_USER_DSN: 265 wSystemDSN = USERDSN_ONLY; 266 break; 267 268 case ODBC_SYSTEM_DSN: 269 wSystemDSN = SYSTEMDSN_ONLY; 270 break; 271 } 272 273 if (_iodbcdm_cfg_search_init (&pCfg, "odbcinst.ini", TRUE)) 274 { 275 PUSH_ERROR (ODBC_ERROR_GENERAL_ERR); 276 goto quit; 277 } 278 279 if (_iodbcdm_cfg_search_init (&pOdbcCfg, "odbc.ini", TRUE)) 280 { 281 PUSH_ERROR (ODBC_ERROR_GENERAL_ERR); 282 pOdbcCfg = NULL; 283 goto done; 284 } 285 286 if (lpszInfFile) 287 { 288 if (!install_from_ini (pCfg, pOdbcCfg, (char *) lpszInfFile, 289 (char *) lpszDriver, TRUE)) 290 { 291 PUSH_ERROR (ODBC_ERROR_INVALID_INF); 292 goto done; 293 } 294 } 295 else if (!install_from_string (pCfg, pOdbcCfg, (char *) lpszDriver, TRUE)) 296 { 297 PUSH_ERROR (ODBC_ERROR_INVALID_KEYWORD_VALUE); 298 goto done; 299 } 300 301 if (_iodbcdm_cfg_commit (pCfg) || _iodbcdm_cfg_commit (pOdbcCfg)) 302 { 303 PUSH_ERROR (ODBC_ERROR_GENERAL_ERR); 304 goto done; 305 } 306 307 retcode = TRUE; 308 309done: 310 _iodbcdm_cfg_done (pCfg); 311 if (pOdbcCfg) 312 _iodbcdm_cfg_done (pOdbcCfg); 313 314quit: 315 wSystemDSN = USERDSN_ONLY; 316 configMode = ODBC_BOTH_DSN; 317 318 return retcode; 319} 320 321BOOL INSTAPI 322SQLInstallDriverW (LPCWSTR lpszInfFile, LPCWSTR lpszDriver, LPWSTR lpszPath, 323 WORD cbPathMax, WORD FAR * pcbPathOut) 324{ 325 char *_inf_u8 = NULL; 326 char *_driver_u8 = NULL; 327 char *_path_u8 = NULL; 328 BOOL retcode = FALSE; 329 330 _inf_u8 = (char *) dm_SQL_WtoU8 ((SQLWCHAR *) lpszInfFile, SQL_NTS); 331 if (_inf_u8 == NULL && lpszInfFile) 332 { 333 PUSH_ERROR (ODBC_ERROR_OUT_OF_MEM); 334 goto done; 335 } 336 337 _driver_u8 = (char *) dm_SQL_WtoU8 ((SQLWCHAR *) lpszDriver, SQL_NTS); 338 if (_driver_u8 == NULL && lpszDriver) 339 { 340 PUSH_ERROR (ODBC_ERROR_OUT_OF_MEM); 341 goto done; 342 } 343 344 if (cbPathMax > 0) 345 { 346 if ((_path_u8 = malloc (cbPathMax * UTF8_MAX_CHAR_LEN + 1)) == NULL) 347 { 348 PUSH_ERROR (ODBC_ERROR_OUT_OF_MEM); 349 goto done; 350 } 351 } 352 353 retcode = 354 SQLInstallDriver (_inf_u8, _driver_u8, _path_u8, 355 cbPathMax * UTF8_MAX_CHAR_LEN, pcbPathOut); 356 357 if (retcode == TRUE) 358 { 359 dm_StrCopyOut2_U8toW (_path_u8, lpszPath, cbPathMax, pcbPathOut); 360 } 361 362done: 363 MEM_FREE (_inf_u8); 364 MEM_FREE (_driver_u8); 365 MEM_FREE (_path_u8); 366 367 return retcode; 368} 369