public RC xOpen(string zName, VirtualFile pFile, OPEN flags, out OPEN pOutFlags)
 {
     pOutFlags = 0;
     // If argument zPath is a NULL pointer, this function is required to open a temporary file. Use this buffer to store the file name in.
     //var zTmpname = new StringBuilder(MAX_PATH + 1);        // Buffer used to create temp filename
     var rc = RC.OK;
     var eType = (OPEN)((int)flags & 0xFFFFFF00);  // Type of file to open
     var isExclusive = (flags & OPEN.EXCLUSIVE) != 0;
     var isDelete = (flags & OPEN.DELETEONCLOSE) != 0;
     var isCreate = (flags & OPEN.CREATE) != 0;
     var isReadonly = (flags & OPEN.READONLY) != 0;
     var isReadWrite = (flags & OPEN.READWRITE) != 0;
     var isOpenJournal = (isCreate && (eType == OPEN.MASTER_JOURNAL || eType == OPEN.MAIN_JOURNAL || eType == OPEN.WAL));
     // Check the following statements are true:
     //   (a) Exactly one of the READWRITE and READONLY flags must be set, and
     //   (b) if CREATE is set, then READWRITE must also be set, and
     //   (c) if EXCLUSIVE is set, then CREATE must also be set.
     //   (d) if DELETEONCLOSE is set, then CREATE must also be set.
     Debug.Assert((!isReadonly || !isReadWrite) && (isReadWrite || isReadonly));
     Debug.Assert(!isCreate || isReadWrite);
     Debug.Assert(!isExclusive || isCreate);
     Debug.Assert(!isDelete || isCreate);
     // The main DB, main journal, WAL file and master journal are never automatically deleted. Nor are they ever temporary files.
     //Debug.Assert((!isDelete && !string.IsNullOrEmpty(zName)) || eType != OPEN.MAIN_DB);
     Debug.Assert((!isDelete && !string.IsNullOrEmpty(zName)) || eType != OPEN.MAIN_JOURNAL);
     Debug.Assert((!isDelete && !string.IsNullOrEmpty(zName)) || eType != OPEN.MASTER_JOURNAL);
     Debug.Assert((!isDelete && !string.IsNullOrEmpty(zName)) || eType != OPEN.WAL);
     // Assert that the upper layer has set one of the "file-type" flags.
     Debug.Assert(eType == OPEN.MAIN_DB || eType == OPEN.TEMP_DB || eType == OPEN.MAIN_JOURNAL || eType == OPEN.TEMP_JOURNAL ||
         eType == OPEN.SUBJOURNAL || eType == OPEN.MASTER_JOURNAL || eType == OPEN.TRANSIENT_DB || eType == OPEN.WAL);
     pFile.S = null;
     // If the second argument to this function is NULL, generate a temporary file name to use
     if (string.IsNullOrEmpty(zName))
     {
         Debug.Assert(isDelete && !isOpenJournal);
         zName = Path.GetRandomFileName();
     }
     // Convert the filename to the system encoding.
     if (zName.StartsWith("/") && !zName.StartsWith("//"))
         zName = zName.Substring(1);
     var dwDesiredAccess = (isReadWrite ? FileAccess.Read | FileAccess.Write : FileAccess.Read);
     // SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is created. SQLite doesn't use it to indicate "exclusive access" as it is usually understood.
     FileMode dwCreationDisposition;
     if (isExclusive)
         // Creates a new file, only if it does not already exist. */ If the file exists, it fails.
         dwCreationDisposition = FileMode.CreateNew;
     else if (isCreate)
         // Open existing file, or create if it doesn't exist
         dwCreationDisposition = FileMode.OpenOrCreate;
     else
         // Opens a file, only if it exists.
         dwCreationDisposition = FileMode.Open;
     var dwShareMode = FileShare.Read | FileShare.Write;
     #if !(SQLITE_SILVERLIGHT || WINDOWS_MOBILE)
     FileOptions dwFlagsAndAttributes;
     #endif
     if (isDelete)
     #if !(SQLITE_SILVERLIGHT || WINDOWS_MOBILE)
         dwFlagsAndAttributes = FileOptions.DeleteOnClose;
     #endif
     else
     #if !(SQLITE_SILVERLIGHT || WINDOWS_MOBILE)
         dwFlagsAndAttributes = FileOptions.None;
     #endif
     // Reports from the internet are that performance is always better if FILE_FLAG_RANDOM_ACCESS is used.
     FileStream fs = null;
     if (Environment.OSVersion.Platform >= PlatformID.Win32NT)
     {
         // retry opening the file a few times; this is because of a racing condition between a delete and open call to the FS
         var retries = 3;
         while (fs == null && retries > 0)
             try
             {
                 retries--;
     #if WINDOWS_PHONE || SQLITE_SILVERLIGHT
                 fs = new IsolatedStorageFileStream(zConverted, dwCreationDisposition, dwDesiredAccess, dwShareMode, IsolatedStorageFile.GetUserStoreForApplication());
     #elif !(SQLITE_SILVERLIGHT || WINDOWS_MOBILE)
                 fs = new FileStream(zName, dwCreationDisposition, dwDesiredAccess, dwShareMode, 4096, dwFlagsAndAttributes);
     #else
                 fs = new FileStream(zName, dwCreationDisposition, dwDesiredAccess, dwShareMode, 4096);
     #endif
     #if DEBUG
                 SysEx.OSTRACE("OPEN {0} ({1})", fs.GetHashCode(), fs.Name);
     #endif
             }
             catch (Exception) { Thread.Sleep(100); }
     }
     SysEx.OSTRACE("OPEN {0} {1} 0x{2:x} {3}", pFile.GetHashCode(), zName, dwDesiredAccess, fs == null ? "failed" : "ok");
     if (fs == null ||
     #if !(SQLITE_SILVERLIGHT || WINDOWS_MOBILE)
      fs.SafeFileHandle.IsInvalid
     #else
      !fs.CanRead
     #endif
     )
     {
     #if SQLITE_SILVERLIGHT
     pFile.lastErrno = 1;
     #else
         pFile.LastErrno = (uint)Marshal.GetLastWin32Error();
     #endif
         VirtualFile.winLogError(RC.CANTOPEN, "winOpen", zName);
         return (isReadWrite ? xOpen(zName, pFile, ((flags | OPEN.READONLY) & ~(OPEN.CREATE | OPEN.READWRITE)), out pOutFlags) : SysEx.SQLITE_CANTOPEN_BKPT());
     }
     pOutFlags = (isReadWrite ? OPEN.READWRITE : OPEN.READONLY);
     pFile.Clear();
     pFile.IsOpen = true;
     pFile.S = fs;
     pFile.LastErrno = 0;
     pFile.Vfs = this;
     pFile.Shm = null;
     pFile.Path = zName;
     pFile.SectorSize = (uint)getSectorSize(zName);
     return rc;
 }
示例#2
0
 private static int FILEHANDLEID(VirtualFile fd)
 {
     return fd.GetHashCode();
 }