| OLD | NEW | 
 | (Empty) | 
|    1 // Copyright 2008, Google Inc. |  | 
|    2 // |  | 
|    3 // Redistribution and use in source and binary forms, with or without |  | 
|    4 // modification, are permitted provided that the following conditions are met: |  | 
|    5 // |  | 
|    6 //  1. Redistributions of source code must retain the above copyright notice, |  | 
|    7 //     this list of conditions and the following disclaimer. |  | 
|    8 //  2. Redistributions in binary form must reproduce the above copyright notice, |  | 
|    9 //     this list of conditions and the following disclaimer in the documentation |  | 
|   10 //     and/or other materials provided with the distribution. |  | 
|   11 //  3. Neither the name of Google Inc. nor the names of its contributors may be |  | 
|   12 //     used to endorse or promote products derived from this software without |  | 
|   13 //     specific prior written permission. |  | 
|   14 // |  | 
|   15 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |  | 
|   16 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |  | 
|   17 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO |  | 
|   18 // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |  | 
|   19 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |  | 
|   20 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |  | 
|   21 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |  | 
|   22 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |  | 
|   23 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |  | 
|   24 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |  | 
|   25  |  | 
|   26 // This file contains code that is specific to Symbian. |  | 
|   27 // Differently from the rest of SQLite, it is implemented in C++ as this is |  | 
|   28 // the native language of the OS and all interfaces we need to use are C++. |  | 
|   29 // |  | 
|   30 // This file follows the Gears code style guidelines. |  | 
|   31  |  | 
|   32 #ifdef OS_SYMBIAN |  | 
|   33 #include <coemain.h> |  | 
|   34 #include <e32math.h> |  | 
|   35 #include <f32file.h> |  | 
|   36 #include <utf.h> |  | 
|   37  |  | 
|   38 extern "C" { |  | 
|   39 #include "sqliteInt.h" |  | 
|   40 #include "os_common.h" |  | 
|   41 } |  | 
|   42  |  | 
|   43 const TInt kFileLockAttempts = 3; |  | 
|   44  |  | 
|   45 // The global file system session. |  | 
|   46 RFs g_fs_session; |  | 
|   47  |  | 
|   48 static TInt UTF8ToUTF16(const char *in, TDes *out16) { |  | 
|   49   assert(in); |  | 
|   50   TPtrC8 in_des(reinterpret_cast<const unsigned char*>(in)); |  | 
|   51   return CnvUtfConverter::ConvertToUnicodeFromUtf8(*out16, in_des); |  | 
|   52 } |  | 
|   53  |  | 
|   54 static TInt UTF16ToUTF8(const TDesC16& in16, TDes8 *out8) { |  | 
|   55   return CnvUtfConverter::ConvertFromUnicodeToUtf8(*out8, in16); |  | 
|   56 } |  | 
|   57  |  | 
|   58 // The SymbianFile structure is a subclass of sqlite3_file* specific to the |  | 
|   59 // Symbian portability layer. |  | 
|   60 struct SymbianFile { |  | 
|   61   const sqlite3_io_methods *methods; |  | 
|   62   RFile handle;              // The file handle |  | 
|   63   TUint8 lock_type;          // Type of lock currently held on this file |  | 
|   64   TUint16 shared_lock_byte;  // Randomly chosen byte used as a shared lock |  | 
|   65 }; |  | 
|   66  |  | 
|   67 static SymbianFile* ConvertToSymbianFile(sqlite3_file* const id) { |  | 
|   68   assert(id); |  | 
|   69   return reinterpret_cast<SymbianFile*>(id); |  | 
|   70 } |  | 
|   71  |  | 
|   72 static int SymbianClose(sqlite3_file *id) { |  | 
|   73   SymbianFile *file_id = ConvertToSymbianFile(id); |  | 
|   74   file_id->handle.Close(); |  | 
|   75   OpenCounter(-1); |  | 
|   76   return SQLITE_OK; |  | 
|   77 } |  | 
|   78  |  | 
|   79 static int SymbianRead(sqlite3_file *id, |  | 
|   80                        void *buffer, |  | 
|   81                        int amount, |  | 
|   82                        sqlite3_int64 offset) { |  | 
|   83   assert(buffer); |  | 
|   84   assert(amount >=0); |  | 
|   85   assert(offset >=0); |  | 
|   86  |  | 
|   87   SymbianFile* file_id = ConvertToSymbianFile(id); |  | 
|   88   TPtr8 dest(static_cast<unsigned char*>(buffer), amount); |  | 
|   89  |  | 
|   90   if (KErrNone == file_id->handle.Read(offset, dest, amount)) { |  | 
|   91     if (dest.Length() == amount) { |  | 
|   92       return SQLITE_OK; |  | 
|   93     } else { |  | 
|   94       return SQLITE_IOERR_SHORT_READ; |  | 
|   95     } |  | 
|   96   } else { |  | 
|   97     return SQLITE_IOERR; |  | 
|   98   } |  | 
|   99 } |  | 
|  100  |  | 
|  101 static int SymbianWrite(sqlite3_file *id, |  | 
|  102                         const void *buffer, |  | 
|  103                         int amount, |  | 
|  104                         sqlite3_int64 offset) { |  | 
|  105   assert(buffer); |  | 
|  106   assert(amount >=0); |  | 
|  107   assert(offset >=0); |  | 
|  108  |  | 
|  109   SymbianFile *file_id = ConvertToSymbianFile(id); |  | 
|  110   TPtrC8 src(static_cast<const unsigned char*>(buffer), amount); |  | 
|  111   if (file_id->handle.Write(offset, src) != KErrNone) { |  | 
|  112     return SQLITE_IOERR_WRITE; |  | 
|  113   } |  | 
|  114  |  | 
|  115   return SQLITE_OK; |  | 
|  116 } |  | 
|  117  |  | 
|  118 static int SymbianTruncate(sqlite3_file *id, sqlite3_int64 bytes) { |  | 
|  119   assert(bytes >=0); |  | 
|  120  |  | 
|  121   SymbianFile *file_id = ConvertToSymbianFile(id); |  | 
|  122   if (file_id->handle.SetSize(bytes) != KErrNone) { |  | 
|  123     return SQLITE_IOERR; |  | 
|  124   } |  | 
|  125   return SQLITE_OK; |  | 
|  126 } |  | 
|  127  |  | 
|  128 static int SymbianSync(sqlite3_file *id, int /*flags*/) { |  | 
|  129   SymbianFile *file_id = ConvertToSymbianFile(id); |  | 
|  130   if (file_id->handle.Flush() != KErrNone) { |  | 
|  131     return SQLITE_IOERR; |  | 
|  132   } else { |  | 
|  133     return SQLITE_OK; |  | 
|  134   } |  | 
|  135 } |  | 
|  136  |  | 
|  137 static int SymbianFileSize(sqlite3_file *id, sqlite3_int64 *size) { |  | 
|  138   assert(size); |  | 
|  139  |  | 
|  140   SymbianFile *file_id = ConvertToSymbianFile(id); |  | 
|  141   TInt size_tmp; |  | 
|  142   if (file_id->handle.Size(size_tmp) != KErrNone) { |  | 
|  143     return SQLITE_IOERR; |  | 
|  144   } |  | 
|  145   *size = size_tmp; |  | 
|  146   return SQLITE_OK; |  | 
|  147 } |  | 
|  148  |  | 
|  149 // File lock/unlock functions; see os_win.c for a description |  | 
|  150 // of the algorithm used. |  | 
|  151 static int GetReadLock(SymbianFile *file) { |  | 
|  152   file->shared_lock_byte = Math::Random() % (SHARED_SIZE - 1); |  | 
|  153   return file->handle.Lock(SHARED_FIRST + file->shared_lock_byte, 1); |  | 
|  154 } |  | 
|  155  |  | 
|  156 static int UnlockReadLock(SymbianFile *file) { |  | 
|  157   return file->handle.UnLock(SHARED_FIRST + file->shared_lock_byte, 1); |  | 
|  158 } |  | 
|  159  |  | 
|  160 static int SymbianLock(sqlite3_file *id, int lock_type) { |  | 
|  161   SymbianFile *file = ConvertToSymbianFile(id); |  | 
|  162   if (file->lock_type >= lock_type) { |  | 
|  163     return SQLITE_OK; |  | 
|  164   } |  | 
|  165  |  | 
|  166   // Make sure the locking sequence is correct |  | 
|  167   assert(file->lock_type != NO_LOCK || lock_type == SHARED_LOCK); |  | 
|  168   assert(lock_type != PENDING_LOCK); |  | 
|  169   assert(lock_type != RESERVED_LOCK || file->lock_type == SHARED_LOCK); |  | 
|  170  |  | 
|  171   // Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or |  | 
|  172   // a SHARED lock.  If we are acquiring a SHARED lock, the acquisition of |  | 
|  173   // the PENDING_LOCK byte is temporary. |  | 
|  174   int new_lock_type = file->lock_type; |  | 
|  175   int got_pending_lock = 0; |  | 
|  176   int res = KErrNone; |  | 
|  177   if (file->lock_type == NO_LOCK || |  | 
|  178          (lock_type == EXCLUSIVE_LOCK && file->lock_type == RESERVED_LOCK)) { |  | 
|  179     int count = kFileLockAttempts; |  | 
|  180     while (count-- > 0 && |  | 
|  181         (res = file->handle.Lock(PENDING_BYTE, 1)) != KErrNone ) { |  | 
|  182       // Try 3 times to get the pending lock.  The pending lock might be |  | 
|  183       // held by another reader process who will release it momentarily. |  | 
|  184       OSTRACE2("could not get a PENDING lock. cnt=%d\n", cnt); |  | 
|  185       User::After(1000); |  | 
|  186     } |  | 
|  187     got_pending_lock = (res == KErrNone? 1 : 0); |  | 
|  188   } |  | 
|  189  |  | 
|  190   // Acquire a shared lock |  | 
|  191   if (lock_type == SHARED_LOCK && res == KErrNone) { |  | 
|  192     assert(file->lock_type == NO_LOCK); |  | 
|  193     res = GetReadLock(file); |  | 
|  194     if (res == KErrNone) { |  | 
|  195       new_lock_type = SHARED_LOCK; |  | 
|  196     } |  | 
|  197   } |  | 
|  198  |  | 
|  199   // Acquire a RESERVED lock |  | 
|  200   if (lock_type == RESERVED_LOCK && res == KErrNone) { |  | 
|  201     assert(file->lock_type == SHARED_LOCK); |  | 
|  202     res = file->handle.Lock(RESERVED_BYTE, 1); |  | 
|  203     if (res == KErrNone) { |  | 
|  204       new_lock_type = RESERVED_LOCK; |  | 
|  205     } |  | 
|  206   } |  | 
|  207  |  | 
|  208   // Acquire a PENDING lock |  | 
|  209   if (lock_type == EXCLUSIVE_LOCK && res == KErrNone) { |  | 
|  210     new_lock_type = PENDING_LOCK; |  | 
|  211     got_pending_lock = 0; |  | 
|  212   } |  | 
|  213  |  | 
|  214   // Acquire an EXCLUSIVE lock |  | 
|  215   if (lock_type == EXCLUSIVE_LOCK && res == KErrNone) { |  | 
|  216     assert(file->lock_type >= SHARED_LOCK); |  | 
|  217     res = UnlockReadLock(file); |  | 
|  218     OSTRACE2("unreadlock = %d\n", res); |  | 
|  219     res = file->handle.Lock(SHARED_FIRST, SHARED_SIZE); |  | 
|  220     if (res == KErrNone) { |  | 
|  221       new_lock_type = EXCLUSIVE_LOCK; |  | 
|  222     } else { |  | 
|  223       OSTRACE2("error-code = %d\n", GetLastError()); |  | 
|  224       GetReadLock(file); |  | 
|  225     } |  | 
|  226   } |  | 
|  227  |  | 
|  228   // If we are holding a PENDING lock that ought to be released, then |  | 
|  229   // release it now. |  | 
|  230   if (got_pending_lock && lock_type == SHARED_LOCK) { |  | 
|  231     file->handle.UnLock(PENDING_BYTE, 1); |  | 
|  232   } |  | 
|  233  |  | 
|  234   // Update the state of the lock held in the file descriptor, then |  | 
|  235   // return the appropriate result code. |  | 
|  236   file->lock_type = new_lock_type; |  | 
|  237   if (res == KErrNone) { |  | 
|  238     return SQLITE_OK; |  | 
|  239   } else { |  | 
|  240     OSTRACE4("LOCK FAILED %d trying for %d but got %d\n", file->handle, |  | 
|  241            lock_type, new_lock_type); |  | 
|  242     return SQLITE_BUSY; |  | 
|  243   } |  | 
|  244 } |  | 
|  245  |  | 
|  246 static int SymbianUnlock(sqlite3_file *id, int lock_type) { |  | 
|  247   int type; |  | 
|  248   int rc = SQLITE_OK; |  | 
|  249   SymbianFile *file = ConvertToSymbianFile(id); |  | 
|  250   assert(lock_type <= SHARED_LOCK); |  | 
|  251   OSTRACE5("UNLOCK %d to %d was %d(%d)\n", file->handle, lock_type, |  | 
|  252           file->lock_type, file->shared_lock_byte); |  | 
|  253   type = file->lock_type; |  | 
|  254   if (type >= EXCLUSIVE_LOCK) { |  | 
|  255     file->handle.UnLock(SHARED_FIRST, SHARED_SIZE); |  | 
|  256     if (lock_type == SHARED_LOCK && GetReadLock(file) != KErrNone) { |  | 
|  257       // This should never happen.  We should always be able to |  | 
|  258       // reacquire the read lock |  | 
|  259       rc = SQLITE_IOERR_UNLOCK; |  | 
|  260     } |  | 
|  261   } |  | 
|  262   if (type >= RESERVED_LOCK) { |  | 
|  263     file->handle.UnLock(RESERVED_BYTE, 1); |  | 
|  264   } |  | 
|  265   if (lock_type == NO_LOCK && type >= SHARED_LOCK) { |  | 
|  266     UnlockReadLock(file); |  | 
|  267   } |  | 
|  268   if (type >= PENDING_LOCK) { |  | 
|  269     file->handle.UnLock(PENDING_BYTE, 1); |  | 
|  270   } |  | 
|  271   file->lock_type = lock_type; |  | 
|  272   return rc; |  | 
|  273 } |  | 
|  274  |  | 
|  275 static int SymbianCheckReservedLock(sqlite3_file *id, int *result) { |  | 
|  276   int rc; |  | 
|  277   SymbianFile *file = ConvertToSymbianFile(id); |  | 
|  278   if (file->lock_type >= RESERVED_LOCK) { |  | 
|  279     rc = 1; |  | 
|  280     OSTRACE3("TEST WR-LOCK %d %d (local)\n", pFile->h, rc); |  | 
|  281   } else { |  | 
|  282     rc = file->handle.Lock(RESERVED_BYTE, 1); |  | 
|  283     if (rc == KErrNone) { |  | 
|  284       file->handle.UnLock(RESERVED_BYTE, 1); |  | 
|  285     } |  | 
|  286     rc = !rc; |  | 
|  287     OSTRACE3("TEST WR-LOCK %d %d (remote)\n", file->handle, rc); |  | 
|  288   } |  | 
|  289   *result = rc; |  | 
|  290   return SQLITE_OK; |  | 
|  291 } |  | 
|  292  |  | 
|  293 static int SymbianFileControl(sqlite3_file */*id*/, |  | 
|  294                               int /*op*/, |  | 
|  295                               void */*arg*/) { |  | 
|  296   return SQLITE_OK; |  | 
|  297 } |  | 
|  298  |  | 
|  299 static int SymbianSectorSize(sqlite3_file */*id*/) { |  | 
|  300   return SQLITE_DEFAULT_SECTOR_SIZE; |  | 
|  301 } |  | 
|  302  |  | 
|  303 static int SymbianDeviceCharacteristics(sqlite3_file */*id*/) { |  | 
|  304   return 0; |  | 
|  305 } |  | 
|  306  |  | 
|  307 /* |  | 
|  308 ** This vector defines all the methods that can operate on a |  | 
|  309 ** sqlite3_file for Symbian. |  | 
|  310 */ |  | 
|  311 static const sqlite3_io_methods SymbianIoMethod = { |  | 
|  312   1,    // iVersion |  | 
|  313   SymbianClose, |  | 
|  314   SymbianRead, |  | 
|  315   SymbianWrite, |  | 
|  316   SymbianTruncate, |  | 
|  317   SymbianSync, |  | 
|  318   SymbianFileSize, |  | 
|  319   SymbianLock, |  | 
|  320   SymbianUnlock, |  | 
|  321   SymbianCheckReservedLock, |  | 
|  322   SymbianFileControl, |  | 
|  323   SymbianSectorSize, |  | 
|  324   SymbianDeviceCharacteristics |  | 
|  325 }; |  | 
|  326  |  | 
|  327 // ============================================================================ |  | 
|  328 // vfs methods begin here |  | 
|  329 // ============================================================================ |  | 
|  330 static int SymbianOpen(sqlite3_vfs */*vfs*/, |  | 
|  331                        const char *name, |  | 
|  332                        sqlite3_file *id, |  | 
|  333                        int flags, |  | 
|  334                        int *out_flags) { |  | 
|  335   TUint desired_access; |  | 
|  336   TUint share_mode; |  | 
|  337   TInt err = KErrNone; |  | 
|  338   TFileName name_utf16; |  | 
|  339   SymbianFile *file = ConvertToSymbianFile(id); |  | 
|  340  |  | 
|  341   if (out_flags) { |  | 
|  342     *out_flags = flags; |  | 
|  343   } |  | 
|  344  |  | 
|  345   // if the name is NULL we have to open a temporary file. |  | 
|  346   if (!name) { |  | 
|  347     TPath private_path; |  | 
|  348     TFileName file_name; |  | 
|  349     if (g_fs_session.PrivatePath(private_path) != KErrNone) { |  | 
|  350       return SQLITE_CANTOPEN; |  | 
|  351     } |  | 
|  352     if (file->handle.Temp(g_fs_session, |  | 
|  353                           private_path, |  | 
|  354                           file_name, |  | 
|  355                           EFileWrite) != |  | 
|  356         KErrNone) { |  | 
|  357       return SQLITE_CANTOPEN; |  | 
|  358     } |  | 
|  359     file->methods = &SymbianIoMethod; |  | 
|  360     file->lock_type = NO_LOCK; |  | 
|  361     file->shared_lock_byte = 0; |  | 
|  362     OpenCounter(+1); |  | 
|  363     return SQLITE_OK; |  | 
|  364   } |  | 
|  365  |  | 
|  366   if (UTF8ToUTF16(name, &name_utf16) != KErrNone) |  | 
|  367     return SQLITE_CANTOPEN; |  | 
|  368  |  | 
|  369   if (flags & SQLITE_OPEN_READWRITE) { |  | 
|  370     desired_access = EFileWrite; |  | 
|  371   } else { |  | 
|  372     desired_access = EFileRead; |  | 
|  373   } |  | 
|  374   if (flags & SQLITE_OPEN_MAIN_DB) { |  | 
|  375     share_mode = EFileShareReadersOrWriters; |  | 
|  376   } else { |  | 
|  377     share_mode = 0; |  | 
|  378   } |  | 
|  379  |  | 
|  380   if (flags & SQLITE_OPEN_CREATE) { |  | 
|  381     err = file->handle.Create(g_fs_session, |  | 
|  382                               name_utf16, |  | 
|  383                               desired_access | share_mode); |  | 
|  384     if (err != KErrNone && err != KErrAlreadyExists) { |  | 
|  385       return SQLITE_CANTOPEN; |  | 
|  386     } |  | 
|  387   } |  | 
|  388  |  | 
|  389   if (err != KErrNone) { |  | 
|  390     err = file->handle.Open(g_fs_session, |  | 
|  391                             name_utf16, |  | 
|  392                             desired_access | share_mode); |  | 
|  393     if (err != KErrNone && flags & SQLITE_OPEN_READWRITE) { |  | 
|  394       if (out_flags) { |  | 
|  395         *out_flags = (flags | SQLITE_OPEN_READONLY) & ~SQLITE_OPEN_READWRITE; |  | 
|  396       } |  | 
|  397       desired_access = EFileRead; |  | 
|  398       err = file->handle.Open(g_fs_session, |  | 
|  399                               name_utf16, |  | 
|  400                               desired_access | share_mode); |  | 
|  401     } |  | 
|  402     if (err != KErrNone) { |  | 
|  403       return SQLITE_CANTOPEN; |  | 
|  404     } |  | 
|  405   } |  | 
|  406   file->methods = &SymbianIoMethod; |  | 
|  407   file->lock_type = NO_LOCK; |  | 
|  408   file->shared_lock_byte = 0; |  | 
|  409   OpenCounter(+1); |  | 
|  410   return SQLITE_OK; |  | 
|  411 } |  | 
|  412  |  | 
|  413 static int SymbianDelete(sqlite3_vfs */*vfs*/, |  | 
|  414                          const char *file_name, |  | 
|  415                          int /*sync_dir*/) { |  | 
|  416   assert(file_name); |  | 
|  417   TFileName file_name_utf16; |  | 
|  418  |  | 
|  419   if (UTF8ToUTF16(file_name, &file_name_utf16) != KErrNone) { |  | 
|  420     return SQLITE_ERROR; |  | 
|  421   } |  | 
|  422  |  | 
|  423   TInt result = g_fs_session.Delete(file_name_utf16); |  | 
|  424   return (result == KErrNone || result == KErrPathNotFound)? |  | 
|  425          SQLITE_OK : SQLITE_IOERR_DELETE; |  | 
|  426 } |  | 
|  427  |  | 
|  428 static int SymbianAccess(sqlite3_vfs */*vfs*/, |  | 
|  429                          const char *file_name, |  | 
|  430                          int flags, |  | 
|  431                          int *result) { |  | 
|  432   assert(file_name); |  | 
|  433   TEntry entry; |  | 
|  434   TFileName file_name_utf16; |  | 
|  435  |  | 
|  436   if (UTF8ToUTF16(file_name, &file_name_utf16) != KErrNone) { |  | 
|  437     return SQLITE_ERROR; |  | 
|  438   } |  | 
|  439  |  | 
|  440   if (g_fs_session.Entry(file_name_utf16, entry) != KErrNone) { |  | 
|  441     *result = 0; |  | 
|  442     return SQLITE_OK; |  | 
|  443   } |  | 
|  444  |  | 
|  445   switch (flags) { |  | 
|  446     case SQLITE_ACCESS_READ: |  | 
|  447     case SQLITE_ACCESS_EXISTS: |  | 
|  448       *result = !entry.IsDir(); |  | 
|  449       break; |  | 
|  450     case SQLITE_ACCESS_READWRITE: |  | 
|  451       *result = !entry.IsDir() && !entry.IsReadOnly(); |  | 
|  452       break; |  | 
|  453     default: |  | 
|  454       return SQLITE_ERROR; |  | 
|  455   } |  | 
|  456  |  | 
|  457   return SQLITE_OK; |  | 
|  458 } |  | 
|  459  |  | 
|  460 static int SymbianFullPathname(sqlite3_vfs */*vfs*/, |  | 
|  461                                const char *relative, |  | 
|  462                                int full_len, |  | 
|  463                                char *full) { |  | 
|  464   assert(relative); |  | 
|  465   assert(full); |  | 
|  466  |  | 
|  467   TParse parse; |  | 
|  468   TPath relative_utf16; |  | 
|  469   TPath base_path; |  | 
|  470   TPtr8 full_utf8(reinterpret_cast<unsigned char*>(full), full_len); |  | 
|  471  |  | 
|  472   g_fs_session.PrivatePath(base_path); |  | 
|  473  |  | 
|  474   if (UTF8ToUTF16(relative, &relative_utf16) != KErrNone) { |  | 
|  475     return SQLITE_ERROR; |  | 
|  476   } |  | 
|  477  |  | 
|  478   if (parse.Set(relative_utf16, &base_path, NULL) != KErrNone) { |  | 
|  479     return SQLITE_ERROR; |  | 
|  480   } |  | 
|  481  |  | 
|  482   TDesC full_utf16(parse.FullName()); |  | 
|  483   if (UTF16ToUTF8(relative_utf16, &full_utf8) != KErrNone) { |  | 
|  484     return SQLITE_ERROR; |  | 
|  485   } |  | 
|  486  |  | 
|  487   full_utf8.PtrZ(); |  | 
|  488   return SQLITE_OK; |  | 
|  489 } |  | 
|  490  |  | 
|  491 static int SymbianRandomness(sqlite3_vfs */*vfs*/, int buf_len, char *buffer) { |  | 
|  492   assert(buffer); |  | 
|  493   TInt64 seed = User::TickCount(); |  | 
|  494   for (TInt i = 0; i < buf_len; i++) { |  | 
|  495     buffer[i] = Math::Rand(seed) % 255; |  | 
|  496   } |  | 
|  497   return SQLITE_OK; |  | 
|  498 } |  | 
|  499  |  | 
|  500 static int SymbianSleep(sqlite3_vfs */*vfs*/, int microsec) { |  | 
|  501   User::After(microsec); |  | 
|  502   return SQLITE_OK; |  | 
|  503 } |  | 
|  504  |  | 
|  505 int SymbianCurrentTime(sqlite3_vfs */*vfs*/, double *now) { |  | 
|  506   _LIT(kEpoch, "19700101:000000.000000"); |  | 
|  507   assert(now); |  | 
|  508   TTime time; |  | 
|  509   TTime epoch_time(kEpoch); |  | 
|  510   TTimeIntervalSeconds interval; |  | 
|  511  |  | 
|  512   time.HomeTime(); |  | 
|  513   // calculate seconds elapsed since 1-1-1970 |  | 
|  514   time.SecondsFrom(epoch_time, interval); |  | 
|  515  |  | 
|  516   // Julian date @ 1-1-1970 = 2440587.5 |  | 
|  517   // seconds per day = 86400.0 |  | 
|  518   *now = interval.Int()/86400.0 + 2440587.5; |  | 
|  519   return SQLITE_OK; |  | 
|  520 } |  | 
|  521  |  | 
|  522 static int SymbianGetLastError(sqlite3_vfs */*vfs*/, |  | 
|  523                                int /*buf_len*/, |  | 
|  524                                char */*buf*/) { |  | 
|  525   assert(buf[0] == '\0'); |  | 
|  526   return 0; |  | 
|  527 } |  | 
|  528  |  | 
|  529 // Interfaces for opening a shared library, finding entry points |  | 
|  530 // within the shared library, and closing the shared library. |  | 
|  531 // TODO(marcogelmi): implement. |  | 
|  532 #define SymbianDlOpen  0 |  | 
|  533 #define SymbianDlError 0 |  | 
|  534 #define SymbianDlSym   0 |  | 
|  535 #define SymbianDlClose 0 |  | 
|  536  |  | 
|  537 // Initialize and deinitialize the operating system interface. |  | 
|  538 int sqlite3_os_init(void) { |  | 
|  539   static sqlite3_vfs symbian_vfs = { |  | 
|  540     1,                     // iVersion |  | 
|  541     sizeof(SymbianFile),   // szOsFile |  | 
|  542     KMaxPath,              // mxPathname |  | 
|  543     0,                     // pNext |  | 
|  544     "symbian",             // name |  | 
|  545     0,                     // pAppData |  | 
|  546  |  | 
|  547     SymbianOpen,           // xOpen |  | 
|  548     SymbianDelete,         // xDelete |  | 
|  549     SymbianAccess,         // xAccess |  | 
|  550     SymbianFullPathname,   // xFullPathname |  | 
|  551     SymbianDlOpen,         // xDlOpen |  | 
|  552     SymbianDlError,        // xDlError |  | 
|  553     SymbianDlSym,          // xDlSym |  | 
|  554     SymbianDlClose,        // xDlClose |  | 
|  555     SymbianRandomness,     // xRandomness |  | 
|  556     SymbianSleep,          // xSleep |  | 
|  557     SymbianCurrentTime,    // xCurrentTime |  | 
|  558     SymbianGetLastError    // xGetLastError |  | 
|  559   }; |  | 
|  560  |  | 
|  561   if (g_fs_session.Connect() != KErrNone) { |  | 
|  562     return SQLITE_ERROR; |  | 
|  563   } |  | 
|  564  |  | 
|  565   if (g_fs_session.ShareAuto() != KErrNone) { |  | 
|  566     g_fs_session.Close(); |  | 
|  567     return SQLITE_ERROR; |  | 
|  568   } |  | 
|  569  |  | 
|  570   sqlite3_vfs_register(&symbian_vfs, 1); |  | 
|  571   return SQLITE_OK; |  | 
|  572 } |  | 
|  573  |  | 
|  574 int sqlite3_os_end(void) { |  | 
|  575   g_fs_session.Close(); |  | 
|  576   return SQLITE_OK; |  | 
|  577 } |  | 
|  578  |  | 
|  579 #endif /* OS_SYMBIAN*/ |  | 
| OLD | NEW |