/ Check-in [cafa8ac2]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Support UTF-8 filenames on OS/2 by converting them to and from the local codepage. Ticket 3052. (CVS 5014)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: cafa8ac2687890355a7faa751d71859eb0fadd01
User & Date: pweilbacher 2008-04-15 18:50:02
Context
2008-04-16
00:28
Back out the zero-terminator optimization introduced in check-in (4915). Ticket #3056. (CVS 5015) check-in: cce8deae user: drh tags: trunk
2008-04-15
18:50
Support UTF-8 filenames on OS/2 by converting them to and from the local codepage. Ticket 3052. (CVS 5014) check-in: cafa8ac2 user: pweilbacher tags: trunk
14:37
Increment the version number. (CVS 5013) check-in: a12fa025 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/os.h.

    80     80   # define INCL_DOSFILEMGR
    81     81   # define INCL_DOSERRORS
    82     82   # define INCL_DOSMISC
    83     83   # define INCL_DOSPROCESS
    84     84   # define INCL_DOSMODULEMGR
    85     85   # define INCL_DOSSEMAPHORES
    86     86   # include <os2.h>
           87  +# include <uconv.h>
    87     88   # define SQLITE_TEMPNAME_SIZE (CCHMAXPATHCOMP)
    88     89   #else
    89     90   # define SQLITE_TEMPNAME_SIZE 200
    90     91   #endif
    91     92   
    92     93   /* If the SET_FULLSYNC macro is not defined above, then make it
    93     94   ** a no-op

Changes to src/os_os2.c.

   287    287     memset(&LockArea, 0, sizeof(LockArea));
   288    288     memset(&UnlockArea, 0, sizeof(UnlockArea));
   289    289     assert( pFile!=0 );
   290    290     OSTRACE4( "LOCK %d %d was %d\n", pFile->h, locktype, pFile->locktype );
   291    291   
   292    292     /* If there is already a lock of this type or more restrictive on the
   293    293     ** os2File, do nothing. Don't use the end_lock: exit path, as
   294         -  ** sqlite3OsEnterMutex() hasn't been called yet.
          294  +  ** sqlite3_mutex_enter() hasn't been called yet.
   295    295     */
   296    296     if( pFile->locktype>=locktype ){
   297    297       OSTRACE3( "LOCK %d %d ok (already held)\n", pFile->h, locktype );
   298    298       return SQLITE_OK;
   299    299     }
   300    300   
   301    301     /* Make sure the locking sequence is correct
................................................................................
   548    548   
   549    549   /*
   550    550   ** Return a vector of device characteristics.
   551    551   */
   552    552   static int os2DeviceCharacteristics(sqlite3_file *id){
   553    553     return 0;
   554    554   }
          555  +
          556  +/*
          557  +** Helper function to convert UTF-8 filenames to local OS/2 codepage.
          558  +** The two-step process: first convert the incoming UTF-8 string
          559  +** into UCS-2 and then from UCS-2 to the current codepage.
          560  +** The returned char pointer has to be freed.
          561  +*/
          562  +char *convertUtf8PathToCp(const char *in)
          563  +{
          564  +  UconvObject uconv;
          565  +  UniChar ucsUtf8Cp[12],
          566  +          tempPath[CCHMAXPATH];
          567  +  char *out;
          568  +  int rc = 0;
          569  +
          570  +  out = (char *)calloc(CCHMAXPATH, 1);
          571  +
          572  +  /* determine string for the conversion of UTF-8 which is CP1208 */
          573  +  rc = UniMapCpToUcsCp(1208, ucsUtf8Cp, 12);
          574  +  rc = UniCreateUconvObject(ucsUtf8Cp, &uconv);
          575  +  rc = UniStrToUcs(uconv, tempPath, (char *)in, CCHMAXPATH);
          576  +  rc = UniFreeUconvObject(uconv);
          577  +
          578  +  /* conversion for current codepage which can be used for paths */
          579  +  rc = UniCreateUconvObject((UniChar *)L"@path=yes", &uconv);
          580  +  rc = UniStrFromUcs(uconv, out, tempPath, CCHMAXPATH);
          581  +  rc = UniFreeUconvObject(uconv);
          582  +
          583  +  return out;
          584  +}
          585  +
          586  +/*
          587  +** Helper function to convert filenames from local codepage to UTF-8.
          588  +** The two-step process: first convert the incoming codepage-specific
          589  +** string into UCS-2 and then from UCS-2 to the codepage of UTF-8.
          590  +** The returned char pointer has to be freed.
          591  +*/
          592  +char *convertCpPathToUtf8(const char *in)
          593  +{
          594  +  UconvObject uconv;
          595  +  UniChar ucsUtf8Cp[12],
          596  +          tempPath[CCHMAXPATH];
          597  +  char *out;
          598  +  int rc = 0;
          599  +
          600  +  out = (char *)calloc(CCHMAXPATH, 1);
          601  +
          602  +  /* conversion for current codepage which can be used for paths */
          603  +  rc = UniCreateUconvObject((UniChar *)L"@path=yes", &uconv);
          604  +  rc = UniStrToUcs(uconv, tempPath, (char *)in, CCHMAXPATH);
          605  +  rc = UniFreeUconvObject(uconv);
          606  +
          607  +  /* determine string for the conversion of UTF-8 which is CP1208 */
          608  +  rc = UniMapCpToUcsCp(1208, ucsUtf8Cp, 12);
          609  +  rc = UniCreateUconvObject(ucsUtf8Cp, &uconv);
          610  +  rc = UniStrFromUcs(uconv, out, tempPath, CCHMAXPATH);
          611  +  rc = UniFreeUconvObject(uconv);
          612  +
          613  +  return out;
          614  +}
   555    615   
   556    616   /*
   557    617   ** This vector defines all the methods that can operate on an
   558    618   ** sqlite3_file for os2.
   559    619   */
   560    620   static const sqlite3_io_methods os2IoMethod = {
   561    621     1,                        /* iVersion */
................................................................................
   593    653     ULONG ulFileAttribute = 0;
   594    654     ULONG ulOpenFlags = 0;
   595    655     ULONG ulOpenMode = 0;
   596    656     os2File *pFile = (os2File*)id;
   597    657     APIRET rc = NO_ERROR;
   598    658     ULONG ulAction;
   599    659   
   600         -  memset(pFile, 0, sizeof(*pFile));
          660  +  memset( pFile, 0, sizeof(*pFile) );
   601    661   
   602    662     OSTRACE2( "OPEN want %d\n", flags );
   603    663   
   604    664     //ulOpenMode = flags & SQLITE_OPEN_READWRITE ? OPEN_ACCESS_READWRITE : OPEN_ACCESS_READONLY;
   605    665     if( flags & SQLITE_OPEN_READWRITE ){
   606    666       ulOpenMode |= OPEN_ACCESS_READWRITE;
   607    667       OSTRACE1( "OPEN read/write\n" );
................................................................................
   643    703       OSTRACE1( "OPEN normal file attribute\n" );
   644    704     }
   645    705   
   646    706     /* always open in random access mode for possibly better speed */
   647    707     ulOpenMode |= OPEN_FLAGS_RANDOM;
   648    708     ulOpenMode |= OPEN_FLAGS_FAIL_ON_ERROR;
   649    709   
   650         -  rc = DosOpen( (PSZ)zName,
          710  +  char *zNameCp = convertUtf8PathToCp( zName );
          711  +  rc = DosOpen( (PSZ)zNameCp,
   651    712                   &h,
   652    713                   &ulAction,
   653    714                   0L,
   654    715                   ulFileAttribute,
   655    716                   ulOpenFlags,
   656    717                   ulOpenMode,
   657    718                   (PEAOP2)NULL );
          719  +  free( zNameCp );
   658    720     if( rc != NO_ERROR ){
   659    721       OSTRACE7( "OPEN Invalid handle rc=%d: zName=%s, ulAction=%#lx, ulAttr=%#lx, ulFlags=%#lx, ulMode=%#lx\n",
   660    722                 rc, zName, ulAction, ulFileAttribute, ulOpenFlags, ulOpenMode );
   661    723       if( flags & SQLITE_OPEN_READWRITE ){
   662    724         OSTRACE2( "OPEN %d Invalid handle\n", ((flags | SQLITE_OPEN_READONLY) & ~SQLITE_OPEN_READWRITE) );
   663    725         return os2Open( 0, zName, id,
   664    726                         ((flags | SQLITE_OPEN_READONLY) & ~SQLITE_OPEN_READWRITE),
................................................................................
   685    747   int os2Delete(
   686    748     sqlite3_vfs *pVfs,                     /* Not used on os2 */
   687    749     const char *zFilename,                 /* Name of file to delete */
   688    750     int syncDir                            /* Not used on os2 */
   689    751   ){
   690    752     APIRET rc = NO_ERROR;
   691    753     SimulateIOError(return SQLITE_IOERR_DELETE);
   692         -  rc = DosDelete( (PSZ)zFilename );
          754  +  char *zFilenameCp = convertUtf8PathToCp( zFilename );
          755  +  rc = DosDelete( (PSZ)zFilenameCp );
          756  +  free( zFilenameCp );
   693    757     OSTRACE2( "DELETE \"%s\"\n", zFilename );
   694    758     return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
   695    759   }
   696    760   
   697    761   /*
   698    762   ** Check the existance and status of a file.
   699    763   */
................................................................................
   701    765     sqlite3_vfs *pVfs,        /* Not used on os2 */
   702    766     const char *zFilename,    /* Name of file to check */
   703    767     int flags                 /* Type of test to make on this file */
   704    768   ){
   705    769     FILESTATUS3 fsts3ConfigInfo;
   706    770     APIRET rc = NO_ERROR;
   707    771   
   708         -  memset(&fsts3ConfigInfo, 0, sizeof(fsts3ConfigInfo));
   709         -  rc = DosQueryPathInfo( (PSZ)zFilename, FIL_STANDARD,
          772  +  memset( &fsts3ConfigInfo, 0, sizeof(fsts3ConfigInfo) );
          773  +  char *zFilenameCp = convertUtf8PathToCp( zFilename );
          774  +  rc = DosQueryPathInfo( (PSZ)zFilenameCp, FIL_STANDARD,
   710    775                            &fsts3ConfigInfo, sizeof(FILESTATUS3) );
          776  +  free( zFilenameCp );
   711    777     OSTRACE4( "ACCESS fsts3ConfigInfo.attrFile=%d flags=%d rc=%d\n",
   712    778               fsts3ConfigInfo.attrFile, flags, rc );
   713    779     switch( flags ){
   714    780       case SQLITE_ACCESS_READ:
   715    781       case SQLITE_ACCESS_EXISTS:
   716    782         rc = (rc == NO_ERROR);
   717    783         OSTRACE3( "ACCESS %s access of read and exists  rc=%d\n", zFilename, rc );
................................................................................
   735    801     static const unsigned char zChars[] =
   736    802       "abcdefghijklmnopqrstuvwxyz"
   737    803       "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
   738    804       "0123456789";
   739    805     int i, j;
   740    806     char zTempPathBuf[3];
   741    807     PSZ zTempPath = (PSZ)&zTempPathBuf;
          808  +  char *zTempPathUTF;
   742    809     if( DosScanEnv( (PSZ)"TEMP", &zTempPath ) ){
   743    810       if( DosScanEnv( (PSZ)"TMP", &zTempPath ) ){
   744    811         if( DosScanEnv( (PSZ)"TMPDIR", &zTempPath ) ){
   745    812              ULONG ulDriveNum = 0, ulDriveMap = 0;
   746    813              DosQueryCurrentDisk( &ulDriveNum, &ulDriveMap );
   747    814              sprintf( (char*)zTempPath, "%c:", (char)( 'A' + ulDriveNum - 1 ) );
   748    815         }
................................................................................
   751    818     /* strip off a trailing slashes or backslashes, otherwise we would get *
   752    819      * multiple (back)slashes which causes DosOpen() to fail               */
   753    820     j = strlen(zTempPath);
   754    821     while( j > 0 && ( zTempPath[j-1] == '\\' || zTempPath[j-1] == '/' ) ){
   755    822       j--;
   756    823     }
   757    824     zTempPath[j] = '\0';
          825  +  zTempPathUTF = convertCpPathToUtf8( zTempPath );
   758    826     sqlite3_snprintf( nBuf-30, zBuf,
   759         -                    "%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPath );
          827  +                    "%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPathUTF );
          828  +  free( zTempPathUTF );
   760    829     j = strlen( zBuf );
   761    830     sqlite3_randomness( 20, &zBuf[j] );
   762    831     for( i = 0; i < 20; i++, j++ ){
   763    832       zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
   764    833     }
   765    834     zBuf[j] = 0;
   766    835     OSTRACE2( "TEMP FILENAME: %s\n", zBuf );
................................................................................
   775    844   */
   776    845   static int os2FullPathname(
   777    846     sqlite3_vfs *pVfs,          /* Pointer to vfs object */
   778    847     const char *zRelative,      /* Possibly relative input path */
   779    848     int nFull,                  /* Size of output buffer in bytes */
   780    849     char *zFull                 /* Output buffer */
   781    850   ){
   782         -  APIRET rc = DosQueryPathInfo( zRelative, FIL_QUERYFULLNAME, zFull, nFull );
          851  +  char *zRelativeCp = convertUtf8PathToCp( zRelative );
          852  +  char zFullCp[CCHMAXPATH];
          853  +  char *zFullUTF;
          854  +  APIRET rc = DosQueryPathInfo( zRelativeCp, FIL_QUERYFULLNAME, zFullCp,
          855  +                                CCHMAXPATH );
          856  +  free( zRelativeCp );
          857  +  zFullUTF = convertCpPathToUtf8( zFullCp );
          858  +  sqlite3_snprintf( nFull, zFull, zFullUTF );
          859  +  free( zFullUTF );
   783    860     return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
   784    861   }
   785    862   
   786    863   #ifndef SQLITE_OMIT_LOAD_EXTENSION
   787    864   /*
   788    865   ** Interfaces for opening a shared library, finding entry points
   789    866   ** within the shared library, and closing the shared library.
................................................................................
   792    869   ** Interfaces for opening a shared library, finding entry points
   793    870   ** within the shared library, and closing the shared library.
   794    871   */
   795    872   static void *os2DlOpen(sqlite3_vfs *pVfs, const char *zFilename){
   796    873     UCHAR loadErr[256];
   797    874     HMODULE hmod;
   798    875     APIRET rc;
   799         -  rc = DosLoadModule((PSZ)loadErr, sizeof(loadErr), zFilename, &hmod);
          876  +  char *zFilenameCp = convertUtf8PathToCp(zFilename);
          877  +  rc = DosLoadModule((PSZ)loadErr, sizeof(loadErr), zFilenameCp, &hmod);
          878  +  free(zFilenameCp);
   800    879     return rc != NO_ERROR ? 0 : (void*)hmod;
   801    880   }
   802    881   /*
   803    882   ** A no-op since the error code is returned on the DosLoadModule call.
   804    883   ** os2Dlopen returns zero if DosLoadModule is not successful.
   805    884   */
   806    885   static void os2DlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){

Changes to src/shell.c.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains code to implement the "sqlite" command line
    13     13   ** utility for accessing SQLite databases.
    14     14   **
    15         -** $Id: shell.c,v 1.176 2008/03/04 17:45:01 mlcreech Exp $
           15  +** $Id: shell.c,v 1.177 2008/04/15 18:50:02 pweilbacher Exp $
    16     16   */
    17     17   #include <stdlib.h>
    18     18   #include <string.h>
    19     19   #include <stdio.h>
    20     20   #include <assert.h>
    21     21   #include "sqlite3.h"
    22     22   #include <ctype.h>
................................................................................
  1940   1940         i++;
  1941   1941       }else if( strcmp(argv[i],"-init")==0 ){
  1942   1942         i++;
  1943   1943         zInitFile = argv[i];
  1944   1944       }
  1945   1945     }
  1946   1946     if( i<argc ){
         1947  +#ifdef OS_OS2
         1948  +    data.zDbFilename = (const char *)convertCpPathToUtf8( argv[i++] );
         1949  +#else
  1947   1950       data.zDbFilename = argv[i++];
         1951  +#endif
  1948   1952     }else{
  1949   1953   #ifndef SQLITE_OMIT_MEMORYDB
  1950   1954       data.zDbFilename = ":memory:";
  1951   1955   #else
  1952   1956       data.zDbFilename = 0;
  1953   1957   #endif
  1954   1958     }