Пример #1
0
 public void _memcpy(VSystem ct)
 {
     ct.SizeOsFile  = this.SizeOsFile;
     ct.MaxPathname = this.MaxPathname;
     ct.Next        = this.Next;
     ct.Name        = this.Name;
     ct.Tag         = this.Tag;
 }
Пример #2
0
        public static RC UnregisterVfs(VSystem vfs)
        {
            var mutex = MutexEx.Alloc(MutexEx.MUTEX.STATIC_MASTER);

            MutexEx.Enter(mutex);
            UnlinkVfs(vfs);
            MutexEx.Leave(mutex);
            return(RC.OK);
        }
Пример #3
0
        public static VSystem FindVfs(string name)
        {
            VSystem vfs   = null;
            var     mutex = MutexEx.Alloc(MutexEx.MUTEX.STATIC_MASTER);

            MutexEx.Enter(mutex);
            for (vfs = _vfsList; vfs != null && name != vfs.Name; vfs = vfs.Next)
            {
            }
            MutexEx.Leave(mutex);
            return(vfs);
        }
Пример #4
0
 public static RC RegisterVfs(VSystem vfs, bool @default, Func<VFile> createOsFile)
 {
     var mutex = MutexEx.Alloc(MutexEx.MUTEX.STATIC_MASTER);
     MutexEx.Enter(mutex);
     UnlinkVfs(vfs);
     vfs.CreateOsFile = createOsFile;
     if (@default || _vfsList == null)
     {
         vfs.Next = _vfsList;
         _vfsList = vfs;
     }
     else
     {
         vfs.Next = _vfsList.Next;
         _vfsList.Next = vfs;
     }
     Debug.Assert(_vfsList != null);
     MutexEx.Leave(mutex);
     return RC.OK;
 }
Пример #5
0
 public static RC Shutdown()
 {
     if (_GlobalStatics.IsInit)
     {
         VSystem.Shutdown();
         //sqlite3_reset_auto_extension();
         _GlobalStatics.IsInit = false;
     }
     //if (SysEx_GlobalStatics.IsMallocInit)
     //{
     //	sqlite3MallocEnd();
     //	SysEx_GlobalStatics.IsMallocInit = false;
     //}
     if (_GlobalStatics.IsMutexInit)
     {
         //MutexEx_End();
         _GlobalStatics.IsMutexInit = false;
     }
     return(RC.OK);
 }
Пример #6
0
        public static RC RegisterVfs(VSystem vfs, bool default_, Func <VFile> createOsFile)
        {
            var mutex = MutexEx.Alloc(MutexEx.MUTEX.STATIC_MASTER);

            MutexEx.Enter(mutex);
            UnlinkVfs(vfs);
            vfs.CreateOsFile = createOsFile;
            if (default_ || _vfsList == null)
            {
                vfs.Next = _vfsList;
                _vfsList = vfs;
            }
            else
            {
                vfs.Next      = _vfsList.Next;
                _vfsList.Next = vfs;
            }
            Debug.Assert(_vfsList != null);
            MutexEx.Leave(mutex);
            return(RC.OK);
        }
Пример #7
0
        public static byte RandomByte()
        {
            // Initialize the state of the random number generator once, the first time this routine is called.  The seed value does
            // not need to contain a lot of randomness since we are not trying to do secure encryption or anything like that...
            //
            // Nothing in this file or anywhere else in SQLite does any kind of encryption.  The RC4 algorithm is being used as a PRNG (pseudo-random
            // number generator) not as an encryption device.
            byte t;

            if (!_prng.IsInit)
            {
                byte[] k = new byte[256];
                _prng.J = 0;
                _prng.I = 0;
                VSystem.FindVfs(string.Empty).Randomness(256, k);
                int i;
                for (i = 0; i < 255; i++)
                {
                    _prng.S[i] = (byte)i;
                }
                for (i = 0; i < 255; i++)
                {
                    _prng.J         += _prng.S[i] + k[i];
                    t                = _prng.S[_prng.J];
                    _prng.S[_prng.J] = _prng.S[i];
                    _prng.S[i]       = t;
                }
                _prng.IsInit = true;
            }
            // Generate and return single random u8
            _prng.I++;
            t                = _prng.S[_prng.I];
            _prng.J         += t;
            _prng.S[_prng.I] = _prng.S[_prng.J];
            _prng.S[_prng.J] = t;
            t               += _prng.S[_prng.I];
            return(_prng.S[t]);
        }
Пример #8
0
        static Pager Open(VSystem vfs)
        {
            var dbHeader = new byte[100]; // Database header content

            IPager.PAGEROPEN flags = 0;
            var vfsFlags = VSystem.OPEN.CREATE | VSystem.OPEN.READWRITE | VSystem.OPEN.MAIN_DB;
            //
            Pager pager;
            var rc = Pager.Open(vfs, out pager, @"C:\T_\Test.db", 0, flags, vfsFlags, x => { }, null);
            if (rc == RC.OK)
                rc = pager.ReadFileHeader(dbHeader.Length, dbHeader);
            if (rc != RC.OK)
                goto _out;
            pager.SetBusyHandler(BusyHandler, null);
            var readOnly = pager.get_Readonly();
            //
            int reserves;
            var pageSize = (uint)((dbHeader[16] << 8) | (dbHeader[17] << 16));
            if (pageSize < 512 || pageSize > Pager.MAX_PAGE_SIZE || ((pageSize - 1) & pageSize) != 0)
            {
                pageSize = 0;
                reserves = 0;
            }
            else
                reserves = dbHeader[20];
            rc = pager.SetPageSize(ref pageSize, reserves);
            if (rc != RC.OK) goto _out;
            _out:
            if (rc != RC.OK)
            {
                if (pager != null)
                    pager.Close();
                pager = null;
            }
            else
                pager.SetCacheSize(2000);
            return pager;
        }
Пример #9
0
 internal static void UnlinkVfs(VSystem vfs)
 {
     Debug.Assert(MutexEx.Held(MutexEx.Alloc(MutexEx.MUTEX.STATIC_MASTER)));
     if (vfs == null)
     {
     }
     else if (_vfsList == vfs)
     {
         _vfsList = vfs.Next;
     }
     else if (_vfsList != null)
     {
         var p = _vfsList;
         while (p.Next != null && p.Next != vfs)
         {
             p = p.Next;
         }
         if (p.Next == vfs)
         {
             p.Next = vfs.Next;
         }
     }
 }
Пример #10
0
        public static RC Open(VSystem vfs, string filename, BContext ctx, ref Btree btree, OPEN flags, VSystem.OPEN vfsFlags)
        {
            // True if opening an ephemeral, temporary database
            bool tempDB = string.IsNullOrEmpty(filename);

            // Set the variable isMemdb to true for an in-memory database, or false for a file-based database.
            bool memoryDB = (filename == ":memory:") ||
                (tempDB && ctx.TempInMemory()) ||
                (vfsFlags & VSystem.OPEN.MEMORY) != 0;

            Debug.Assert(ctx != null);
            Debug.Assert(vfs != null);
            Debug.Assert(MutexEx.Held(ctx.Mutex));
            Debug.Assert(((uint)flags & 0xff) == (uint)flags); // flags fit in 8 bits

            // Only a BTREE_SINGLE database can be BTREE_UNORDERED
            Debug.Assert((flags & OPEN.UNORDERED) == 0 || (flags & OPEN.SINGLE) != 0);

            // A BTREE_SINGLE database is always a temporary and/or ephemeral
            Debug.Assert((flags & OPEN.SINGLE) == 0 || tempDB);

            if (memoryDB)
                flags |= OPEN.MEMORY;
            if ((vfsFlags & VSystem.OPEN.MAIN_DB) != 0 && (memoryDB || tempDB))
                vfsFlags = (vfsFlags & ~VSystem.OPEN.MAIN_DB) | VSystem.OPEN.TEMP_DB;
            var p = new Btree(); // Handle to return
            if (p == null)
                return RC.NOMEM;
            p.InTrans = TRANS.NONE;
            p.Ctx = ctx;
#if !OMIT_SHARED_CACHE
            p.Lock.Btree = p;
            p.Lock.Table = 1;
#endif

            RC rc = RC.OK; // Result code from this function
            BtShared bt = null; // Shared part of btree structure
            MutexEx mutexOpen = null;
#if !OMIT_SHARED_CACHE && !OMIT_DISKIO
            // If this Btree is a candidate for shared cache, try to find an existing BtShared object that we can share with
            if (!tempDB && (!memoryDB || (vfsFlags & VSystem.OPEN.URI) != 0))
                if ((vfsFlags & VSystem.OPEN.SHAREDCACHE) != 0)
                {
                    string fullPathname;
                    p.Sharable_ = true;
                    if (memoryDB)
                        fullPathname = filename;
                    else
                        vfs.FullPathname(filename, out fullPathname);
                    MutexEx mutexShared;
#if THREADSAFE
                    mutexOpen = MutexEx.Alloc(MutexEx.MUTEX.STATIC_OPEN); // Prevents a race condition. Ticket #3537
                    MutexEx.Enter(mutexOpen);
                    mutexShared = MutexEx.Alloc(MutexEx.MUTEX.STATIC_MASTER);
                    MutexEx.Enter(mutexShared);
#endif
                    for (bt = _sharedCacheList; bt != null; bt = bt.Next)
                    {
                        Debug.Assert(bt.Refs > 0);
                        if (fullPathname == bt.Pager.get_Filename(false) && bt.Pager.get_Vfs() == vfs)
                        {
                            for (var i = ctx.DBs.length - 1; i >= 0; i--)
                            {
                                var existing = ctx.DBs[i].Bt;
                                if (existing != null && existing.Bt == bt)
                                {
                                    MutexEx.Leave(mutexShared);
                                    MutexEx.Leave(mutexOpen);
                                    fullPathname = null;
                                    p = null;
                                    return RC.CONSTRAINT;
                                }
                            }
                            p.Bt = bt;
                            bt.Refs++;
                            break;
                        }
                    }
                    MutexEx.Leave(mutexShared);
                    fullPathname = null;
                }
#if DEBUG
                else
                    // In debug mode, we mark all persistent databases as sharable even when they are not.  This exercises the locking code and
                    // gives more opportunity for asserts(sqlite3_mutex_held()) statements to find locking problems.
                    p.Sharable_ = true;
#endif
#endif

            byte reserves; // Byte of unused space on each page
            var dbHeader = new byte[100]; // Database header content
            if (bt == null)
            {
                // The following asserts make sure that structures used by the btree are the right size.  This is to guard against size changes that result
                // when compiling on a different architecture.
                Debug.Assert(sizeof(long) == 8 || sizeof(long) == 4);
                Debug.Assert(sizeof(ulong) == 8 || sizeof(ulong) == 4);
                Debug.Assert(sizeof(uint) == 4);
                Debug.Assert(sizeof(ushort) == 2);
                Debug.Assert(sizeof(Pid) == 4);

                bt = new BtShared();
                if (bt == null)
                {
                    rc = RC.NOMEM;
                    goto btree_open_out;
                }
                rc = Pager.Open(vfs, out bt.Pager, filename, EXTRA_SIZE, (IPager.PAGEROPEN)flags, vfsFlags, pageReinit, null);
                if (rc == RC.OK)
                    rc = bt.Pager.ReadFileHeader(dbHeader.Length, dbHeader);
                if (rc != RC.OK)
                    goto btree_open_out;
                bt.OpenFlags = flags;
                bt.Ctx = ctx;
                bt.Pager.SetBusyHandler(btreeInvokeBusyHandler, bt);
                p.Bt = bt;

                bt.Cursor = null;
                bt.Page1 = null;
                if (bt.Pager.get_Readonly()) bt.BtsFlags |= BTS.READ_ONLY;
#if SECURE_DELETE
                bt.BtsFlags |= BTS.SECURE_DELETE;
#endif
                bt.PageSize = (Pid)((dbHeader[16] << 8) | (dbHeader[17] << 16));
                if (bt.PageSize < 512 || bt.PageSize > Pager.MAX_PAGE_SIZE || ((bt.PageSize - 1) & bt.PageSize) != 0)
                {
                    bt.PageSize = 0;
#if !OMIT_AUTOVACUUM
                    // If the magic name ":memory:" will create an in-memory database, then leave the autoVacuum mode at 0 (do not auto-vacuum), even if
                    // SQLITE_DEFAULT_AUTOVACUUM is true. On the other hand, if SQLITE_OMIT_MEMORYDB has been defined, then ":memory:" is just a
                    // regular file-name. In this case the auto-vacuum applies as per normal.
                    if (filename != null && !memoryDB)
                    {
                        bt.AutoVacuum = (DEFAULT_AUTOVACUUM != 0);
                        bt.IncrVacuum = (DEFAULT_AUTOVACUUM == AUTOVACUUM.INCR);
                    }
#endif
                    reserves = 0;
                }
                else
                {
                    reserves = dbHeader[20];
                    bt.BtsFlags |= BTS.PAGESIZE_FIXED;
#if !OMIT_AUTOVACUUM
                    bt.AutoVacuum = (ConvertEx.Get4(dbHeader, 36 + 4 * 4) != 0);
                    bt.IncrVacuum = (ConvertEx.Get4(dbHeader, 36 + 7 * 4) != 0);
#endif
                }
                rc = bt.Pager.SetPageSize(ref bt.PageSize, reserves);
                if (rc != RC.OK) goto btree_open_out;
                bt.UsableSize = (ushort)(bt.PageSize - reserves);
                Debug.Assert((bt.PageSize & 7) == 0); // 8-byte alignment of pageSize

#if !SHARED_CACHE && !OMIT_DISKIO
                // Add the new BtShared object to the linked list sharable BtShareds.
                if (p.Sharable_)
                {
                    bt.Refs = 1;
                    MutexEx mutexShared;
#if THREADSAFE
                    mutexShared = MutexEx.Alloc(MutexEx.MUTEX.STATIC_MASTER);
                    bt.Mutex = MutexEx.Alloc(MutexEx.MUTEX.FAST);
#endif
                    MutexEx.Enter(mutexShared);
                    bt.Next = _sharedCacheList;
                    _sharedCacheList = bt;
                    MutexEx.Leave(mutexShared);
                }
#endif
            }

#if !OMIT_SHARED_CACHE && !OMIT_DISKIO
            // If the new Btree uses a sharable pBtShared, then link the new Btree into the list of all sharable Btrees for the same connection.
            // The list is kept in ascending order by pBt address.
            if (p.Sharable_)
            {
                Btree sib;
                for (var i = 0; i < ctx.DBs.length; i++)
                    if ((sib = ctx.DBs[i].Bt) != null && sib.Sharable_)
                    {
                        while (sib.Prev != null) { sib = sib.Prev; }
                        if (p.Bt.AutoID < sib.Bt.AutoID)
                        {
                            p.Next = sib;
                            p.Prev = null;
                            sib.Prev = p;
                        }
                        else
                        {
                            while (sib.Next != null && sib.Next.Bt.AutoID < p.Bt.AutoID)
                                sib = sib.Next;
                            p.Next = sib.Next;
                            p.Prev = sib;
                            if (p.Next != null)
                                p.Next.Prev = p;
                            sib.Next = p;
                        }
                        break;
                    }
            }
#endif
            btree = p;

        btree_open_out:
            if (rc != RC.OK)
            {
                if (bt != null && bt.Pager != null)
                    bt.Pager.Close();
                bt = null;
                p = null;
                btree = null;
            }
            else
                // If the B-Tree was successfully opened, set the pager-cache size to the default value. Except, when opening on an existing shared pager-cache,
                // do not change the pager-cache size.
                if (p.Schema(0, null) == null)
                    p.Bt.Pager.SetCacheSize(DEFAULT_CACHE_SIZE);
#if THREADSAFE
            Debug.Assert(MutexEx.Held(mutexOpen));
            MutexEx.Leave(mutexOpen);
#endif
            return rc;
        }
Пример #11
0
        public static RC LoadExtension_(Context ctx, string fileName, string procName, ref string errMsgOut)
        {
            if (errMsgOut != null)
            {
                errMsgOut = null;
            }

            // Ticket #1863.  To avoid a creating security problems for older applications that relink against newer versions of SQLite, the
            // ability to run load_extension is turned off by default.  One must call core_enable_load_extension() to turn on extension
            // loading.  Otherwise you get the following error.
            if ((ctx.Flags & Context.FLAG.LoadExtension) == 0)
            {
                errMsgOut = C._mprintf("not authorized");
                return(RC.ERROR);
            }

            if (procName == null)
            {
                procName = "sqlite3_extension_init";
            }

            VSystem       vfs       = ctx.Vfs;
            HANDLE        handle    = (HANDLE)vfs.DlOpen(fileName);
            StringBuilder errmsg    = new StringBuilder(100);
            int           msgLength = 300;

            if (handle == IntPtr.Zero)
            {
                errMsgOut = string.Empty;
                C.__snprintf(errmsg, msgLength, "unable to open shared library [%s]", fileName);
                vfs.DlError(msgLength - 1, errmsg.ToString());
                return(RC.ERROR);
            }
            Func <Context, StringBuilder, core_api_routines, RC> init = (Func <Context, StringBuilder, core_api_routines, RC>)vfs.DlSym(handle, procName);

            Debugger.Break();
            if (init == null)
            {
                msgLength += procName.Length;
                C.__snprintf(errmsg, msgLength, "no entry point [%s] in shared library [%s]", procName, fileName);
                vfs.DlError(msgLength - 1, errMsgOut = errmsg.ToString());
                vfs.DlClose(handle);
                return(RC.ERROR);
            }
            else if (init(ctx, errmsg, g_apis) != 0)
            {
                errMsgOut = C._mprintf("error during initialization: %s", errmsg.ToString());
                C._tagfree(ctx, ref errmsg);
                vfs.DlClose(handle);
                return(RC.ERROR);
            }

            // Append the new shared library handle to the db.aExtension array.
            object[] handles = new object[ctx.Extensions.length + 1];
            if (handles == null)
            {
                return(RC.NOMEM);
            }
            if (ctx.Extensions.length > 0)
            {
                Array.Copy(ctx.Extensions.data, handles, ctx.Extensions.length);
            }
            C._tagfree(ctx, ref ctx.Extensions.data);
            ctx.Extensions.data = handles;

            ctx.Extensions[ctx.Extensions.length++] = handle;
            return(RC.OK);
        }
Пример #12
0
 internal static void UnlinkVfs(VSystem vfs)
 {
     Debug.Assert(MutexEx.Held(MutexEx.Alloc(MutexEx.MUTEX.STATIC_MASTER)));
     if (vfs == null) { }
     else if (_vfsList == vfs)
         _vfsList = vfs.Next;
     else if (_vfsList != null)
     {
         var p = _vfsList;
         while (p.Next != null && p.Next != vfs)
             p = p.Next;
         if (p.Next == vfs)
             p.Next = vfs.Next;
     }
 }
Пример #13
0
 public static RC UnregisterVfs(VSystem vfs)
 {
     var mutex = MutexEx.Alloc(MutexEx.MUTEX.STATIC_MASTER);
     MutexEx.Enter(mutex);
     UnlinkVfs(vfs);
     MutexEx.Leave(mutex);
     return RC.OK;
 }
Пример #14
0
        public static RC ParseUri(string defaultVfsName, string uri, ref VSystem.OPEN flagsRef, out VSystem vfsOut, out string fileNameOut, out string errMsgOut)
        {
            vfsOut      = null;
            fileNameOut = null;
            errMsgOut   = null;

            VSystem.OPEN flags     = flagsRef;
            string       vfsName   = defaultVfsName;
            int          uriLength = uri.Length;

            RC            rc       = RC.OK;
            StringBuilder fileName = null;

            if (((flags & VSystem.OPEN.URI) != 0 || SysEx._GlobalStatics.OpenUri) && uriLength >= 5 && uri.StartsWith("file:"))
            {
                // Make sure the SQLITE_OPEN_URI flag is set to indicate to the VFS xOpen method that there may be extra parameters following the file-name.
                flags |= VSystem.OPEN.URI;

                int bytes = uriLength + 2; // Bytes of space to allocate
                int uriIdx;                // Input character index
                for (uriIdx = 0; uriIdx < uriLength; uriIdx++)
                {
                    bytes += (uri[uriIdx] == '&' ? 1 : 0);
                }
                fileName = new StringBuilder(bytes);
                if (fileName == null)
                {
                    return(RC.NOMEM);
                }

                // Discard the scheme and authority segments of the URI.
                if (uri[5] == '/' && uri[6] == '/')
                {
                    uriIdx = 7;
                    while (uriIdx < uriLength && uri[uriIdx] != '/')
                    {
                        uriIdx++;
                    }
                    if (uriIdx != 7 && (uriIdx != 16 || !string.Equals("localhost", uri.Substring(7, 9), StringComparison.InvariantCultureIgnoreCase)))
                    {
                        errMsgOut = C._mprintf("invalid uri authority: %.*s", uriIdx - 7, uri.Substring(7));
                        rc        = RC.ERROR;
                        goto parse_uri_out;
                    }
                }
                else
                {
                    uriIdx = 5;
                }

                // Copy the filename and any query parameters into the zFile buffer. Decode %HH escape codes along the way.
                //
                // Within this loop, variable eState may be set to 0, 1 or 2, depending on the parsing context. As follows:
                //
                //   0: Parsing file-name.
                //   1: Parsing name section of a name=value query parameter.
                //   2: Parsing value section of a name=value query parameter.
                int  state = 0; // Parser state when parsing URI
                char c;
                //int fileNameIdx = 0; // Output character index
                while (uriIdx < uriLength && (c = uri[uriIdx]) != 0 && c != '#')
                {
                    uriIdx++;

                    if (c == '%' && C._isxdigit(uri[uriIdx]) && C._isxdigit(uri[uriIdx + 1]))
                    {
                        int octet = (C._hextobyte(uri[uriIdx++]) << 4);
                        octet += C._hextobyte(uri[uriIdx++]);
                        Debug.Assert(octet >= 0 && octet < 256);
                        if (octet == 0)
                        {
                            // This branch is taken when "%00" appears within the URI. In this case we ignore all text in the remainder of the path, name or
                            // value currently being parsed. So ignore the current character and skip to the next "?", "=" or "&", as appropriate.
                            while (uriIdx < uriLength && (c = uri[uriIdx]) != 0 && c != '#' &&
                                   (state != 0 || c != '?') &&
                                   (state != 1 || (c != '=' && c != '&')) &&
                                   (state != 2 || c != '&'))
                            {
                                uriIdx++;
                            }
                            continue;
                        }
                        c = (char)octet;
                    }
                    else if (state == 1 && (c == '&' || c == '='))
                    {
                        if (fileName[fileName.Length - 1] == '\0')
                        {
                            // An empty option name. Ignore this option altogether.
                            while (uri[uriIdx] != '\0' && uri[uriIdx] != '#' && uri[uriIdx - 1] != '&')
                            {
                                uriIdx++;
                            }
                            continue;
                        }
                        if (c == '&')
                        {
                            fileName.Append('\0');
                        }
                        else
                        {
                            state = 2;
                        }
                        c = '\0';
                    }
                    else if ((state == 0 && c == '?') || (state == 2 && c == '&'))
                    {
                        c     = '\0';
                        state = 1;
                    }
                    fileName.Append(c);
                }
                if (state == 1)
                {
                    fileName.Append('\0');
                }
                fileName.Append('\0');
                fileName.Append('\0');

                // Check if there were any options specified that should be interpreted here. Options that are interpreted here include "vfs" and those that
                // correspond to flags that may be passed to the sqlite3_open_v2() method.
                string opt = fileName.ToString().Substring(fileName.Length + 1);
                while (opt.Length > 0)
                {
                    int    optLength = opt.Length;
                    string val       = opt.Substring(optLength);
                    int    valLength = val.Length;
                    if (optLength == 3 && opt.StartsWith("vfs"))
                    {
                        vfsName = val;
                    }
                    else
                    {
                        OpenMode[]   modes    = null;
                        string       modeType = null;
                        VSystem.OPEN mask     = (VSystem.OPEN) 0;
                        VSystem.OPEN limit    = (VSystem.OPEN) 0;
                        if (optLength == 5 && opt.StartsWith("cache"))
                        {
                            mask     = VSystem.OPEN.SHAREDCACHE | VSystem.OPEN.PRIVATECACHE;
                            modes    = _cacheModes;
                            limit    = mask;
                            modeType = "cache";
                        }
                        if (optLength == 4 && opt.StartsWith("mode"))
                        {
                            mask     = VSystem.OPEN.READONLY | VSystem.OPEN.READWRITE | VSystem.OPEN.CREATE;
                            modes    = _openModes;
                            limit    = mask & flags;
                            modeType = "access";
                        }
                        if (modes != null)
                        {
                            VSystem.OPEN mode = 0;
                            for (int i = 0; modes[i].Z != null; i++)
                            {
                                string z = modes[i].Z;
                                if (valLength == z.Length && z.StartsWith(val))
                                {
                                    mode = modes[i].Mode;
                                    break;
                                }
                            }
                            if (mode == 0)
                            {
                                errMsgOut = C._mprintf("no such %s mode: %s", modeType, val);
                                rc        = RC.ERROR;
                                goto parse_uri_out;
                            }
                            if (mode > limit)
                            {
                                errMsgOut = C._mprintf("%s mode not allowed: %s", modeType, val);
                                rc        = RC.PERM;
                                goto parse_uri_out;
                            }
                            flags = ((flags & ~mask) | mode);
                        }
                    }
                    opt = val.Substring(valLength + 1);
                }
            }
            else
            {
                fileName = (uri == null ? new StringBuilder() : new StringBuilder(uri.Substring(0, uriLength)));
                if (fileName == null)
                {
                    return(RC.NOMEM);
                }
                fileName.Append('\0');
                fileName.Append('\0');
            }

            vfsOut = FindVfs(vfsName);
            if (vfsOut == null)
            {
                errMsgOut = C._mprintf("no such vfs: %s", vfsName);
                rc        = RC.ERROR;
            }
parse_uri_out:
            if (rc != RC.OK)
            {
                C._free(ref fileName);
                fileName = null;
            }
            flagsRef    = flags;
            fileNameOut = (fileName == null ? null : fileName.ToString().Substring(0, fileName.Length));
            return(rc);
        }
Пример #15
0
 internal static RC Open(VSystem x, VFile y, string z)
 {
     return(RC.OK);
 }
Пример #16
0
 internal static RC Open(VSystem x, VFile y, string z)
 {
     return RC.OK;
 }
Пример #17
0
 public void CopyTo(VSystem ct)
 {
     ct.SizeOsFile = this.SizeOsFile;
     ct.MaxPathname = this.MaxPathname;
     ct.Next = this.Next;
     ct.Name = this.Name;
     ct.Tag = this.Tag;
 }
Пример #18
0
        public static RC PreInitialize(out MutexEx masterMutex)
        {
            masterMutex = default(MutexEx);
            // If SQLite is already completely initialized, then this call to sqlite3_initialize() should be a no-op.  But the initialization
            // must be complete.  So isInit must not be set until the very end of this routine.
            if (_GlobalStatics.IsInit)
            {
                return(RC.OK);
            }

            // The following is just a sanity check to make sure SQLite has been compiled correctly.  It is important to run this code, but
            // we don't want to run it too often and soak up CPU cycles for no reason.  So we run it once during initialization.
#if !NDEBUG && !OMIT_FLOATING_POINT
            // This section of code's only "output" is via assert() statements.
            //ulong x = (((ulong)1)<<63)-1;
            //double y;
            //Debug.Assert(sizeof(ulong) == 8);
            //Debug.Assert(sizeof(ulong) == sizeof(double));
            //_memcpy<void>(&y, &x, 8);
            //Debug.Assert(double.IsNaN(y));
#endif

            RC rc;
#if ENABLE_SQLLOG
            {
                Init_Sqllog();
            }
#endif

            // Make sure the mutex subsystem is initialized.  If unable to initialize the mutex subsystem, return early with the error.
            // If the system is so sick that we are unable to allocate a mutex, there is not much SQLite is going to be able to do.
            // The mutex subsystem must take care of serializing its own initialization.
            rc = RC.OK; //_mutex_init();
            if (rc != 0)
            {
                return(rc);
            }

            // Initialize the malloc() system and the recursive pInitMutex mutex. This operation is protected by the STATIC_MASTER mutex.  Note that
            // MutexAlloc() is called for a static mutex prior to initializing the malloc subsystem - this implies that the allocation of a static
            // mutex must not require support from the malloc subsystem.
            masterMutex = MutexEx.Alloc(MutexEx.MUTEX.STATIC_MASTER); // The main static mutex
            MutexEx.Enter(masterMutex);
            _GlobalStatics.IsMutexInit = true;
            //if (!SysEx_GlobalStatics.IsMallocInit)
            //	rc = sqlite3MallocInit();
            if (rc == RC.OK)
            {
                _GlobalStatics.IsMallocInit = true;
                if (_GlobalStatics.InitMutex.Tag == null)
                {
                    _GlobalStatics.InitMutex = MutexEx.Alloc(MutexEx.MUTEX.RECURSIVE);
                    if (_GlobalStatics.CoreMutex && _GlobalStatics.InitMutex.Tag == null)
                    {
                        rc = RC.NOMEM;
                    }
                }
            }
            if (rc == RC.OK)
            {
                _GlobalStatics.InitMutexRefs++;
            }
            MutexEx.Leave(masterMutex);

            // If rc is not SQLITE_OK at this point, then either the malloc subsystem could not be initialized or the system failed to allocate
            // the pInitMutex mutex. Return an error in either case.
            if (rc != RC.OK)
            {
                return(rc);
            }

            // Do the rest of the initialization under the recursive mutex so that we will be able to handle recursive calls into
            // sqlite3_initialize().  The recursive calls normally come through sqlite3_os_init() when it invokes sqlite3_vfs_register(), but other
            // recursive calls might also be possible.
            //
            // IMPLEMENTATION-OF: R-00140-37445 SQLite automatically serializes calls to the xInit method, so the xInit method need not be threadsafe.
            //
            // The following mutex is what serializes access to the appdef pcache xInit methods.  The sqlite3_pcache_methods.xInit() all is embedded in the
            // call to sqlite3PcacheInitialize().
            MutexEx.Enter(_GlobalStatics.InitMutex);
            if (!_GlobalStatics.IsInit && !_GlobalStatics.InProgress)
            {
                _GlobalStatics.InProgress = true;
                rc = VSystem.Initialize();
            }
            if (rc != RC.OK)
            {
                MutexEx.Leave(_GlobalStatics.InitMutex);
            }
            return(rc);
        }