private void InitializeFs(MfsFsHeader *header, MfsParameters createParams)
        {
            header->Magic         = MfsMagic;
            header->NextFreeBlock = 1;

            if (createParams != null)
            {
                // Validate the parameters.
                this.ValidateFsParameters(createParams.BlockSize, createParams.CellSize);

                header->BlockSize = createParams.BlockSize;
                header->CellSize  = createParams.CellSize;
            }
            else
            {
                header->BlockSize = MfsDefaultBlockSize;
                header->CellSize  = MfsDefaultCellSize;
            }

            // Store root object in the next cell.
            MfsObjectHeader *obj = (MfsObjectHeader *)((byte *)header + header->CellSize);

            this.InitializeObject(obj, _rootObjectCellId);
            this.SetObjectName(obj, "root");
        }
        internal void SetObjectName(MfsObjectHeader* obj, string name)
        {
            if (_readOnly)
                throw new MfsInvalidOperationException();

            obj->NameLength = name.Length;
            Utils.StrCpy(obj->Name, name, 32);
        }
 protected override void DisposeObject(bool disposing)
 {
     if (!_fsInternal)
     {
         _fs.DereferenceObject(_cellId);
         _fs.Dereference(disposing);
         _obj = null;
     }
 }
 protected override void DisposeObject(bool disposing)
 {
     if (!_fsInternal)
     {
         _fs.DereferenceObject(_cellId);
         _fs.Dereference(disposing);
         _obj = null;
     }
 }
 private void InitializeObject(MfsObjectHeader *obj, MfsCellId cellId)
 {
     obj->Flink      = cellId;
     obj->Blink      = cellId;
     obj->Parent     = MfsCellId.Empty;
     obj->ChildFlink = cellId;
     obj->ChildBlink = cellId;
     obj->DataLength = 0;
     obj->Data       = MfsCellId.Empty;
     obj->LastData   = MfsCellId.Empty;
 }
        internal MemoryObject(MemoryFileSystem fs, MfsCellId cellId, bool fsInternal)
        {
            _fs = fs;
            _cellId = cellId;
            _obj = _fs.ReferenceObject(cellId);

            _fsInternal = fsInternal;

            if (!_fsInternal)
                _fs.Reference();

            // Prevent users from disposing the root object wrapper.
            if (_fsInternal)
                this.DisableOwnership(false);
        }
        internal MfsCellId CreateObject(MfsCellId parent, string name)
        {
            MfsCellId        cellId;
            MfsObjectHeader *obj;

            if (_readOnly)
            {
                throw new MfsInvalidOperationException();
            }

            obj = (MfsObjectHeader *)this.AllocateCell(out cellId);
            this.InitializeObject(obj, cellId);
            this.SetObjectName(obj, name);

            obj->Parent = parent;

            MfsObjectHeader *parentObj = this.ReferenceObject(parent);
            MfsCellId        blink;
            MfsObjectHeader *blinkObj;

            // Increment the child count.
            parentObj->ChildCount++;

            // Insert tail.
            blink                 = parentObj->ChildBlink;
            blinkObj              = this.ReferenceObject(blink);
            obj->Flink            = parent;
            obj->Blink            = blink;
            parentObj->ChildBlink = cellId;

            // Special case - we are not using linked lists properly,
            // so we have to use this hack.
            if (blink == parent)
            {
                blinkObj->ChildFlink = cellId;
            }
            else
            {
                blinkObj->Flink = cellId;
            }

            this.DereferenceObject(blink);
            this.DereferenceObject(parent);
            this.DereferenceObject(cellId);

            return(cellId);
        }
        protected override void DisposeObject(bool disposing)
        {
            foreach (var vd in _views.Values)
            {
                vd.View.Dispose(disposing);
            }

            if (_rootObjectMo != null)
            {
                _rootObjectMo.Dispose();
            }
            if (_section != null)
            {
                _section.Dispose();
            }
            _header     = null;
            _rootObject = null;
        }
        internal MemoryObject(MemoryFileSystem fs, MfsCellId cellId, bool fsInternal)
        {
            _fs     = fs;
            _cellId = cellId;
            _obj    = _fs.ReferenceObject(cellId);

            _fsInternal = fsInternal;

            if (!_fsInternal)
            {
                _fs.Reference();
            }

            // Prevent users from disposing the root object wrapper.
            if (_fsInternal)
            {
                this.DisableOwnership(false);
            }
        }
        public MemoryFileSystem(string fileName, MfsOpenMode mode, bool readOnly, MfsParameters createParams)
        {
            FileCreationDispositionWin32 cdWin32;

            if (readOnly && mode != MfsOpenMode.Open)
            {
                throw new ArgumentException("Invalid mode for read only access.");
            }

            switch (mode)
            {
            case MfsOpenMode.Open:
                cdWin32 = FileCreationDispositionWin32.OpenExisting;
                break;

            default:
            case MfsOpenMode.OpenIf:
                cdWin32 = FileCreationDispositionWin32.OpenAlways;
                break;

            case MfsOpenMode.OverwriteIf:
                cdWin32 = FileCreationDispositionWin32.CreateAlways;
                break;
            }

            using (var fhandle = FileHandle.CreateWin32(
                       fileName,
                       FileAccess.GenericRead | (!readOnly ? FileAccess.GenericWrite : 0),
                       FileShareMode.Read,
                       cdWin32
                       ))
            {
                bool justCreated = false;

                _readOnly   = readOnly;
                _protection = !readOnly ? MemoryProtection.ReadWrite : MemoryProtection.ReadOnly;

                if (fhandle.GetSize() == 0)
                {
                    if (readOnly)
                    {
                        throw new MfsInvalidFileSystemException();
                    }
                    else
                    {
                        // File is too small. Make it 1 byte large and we'll deal with it
                        // soon.
                        fhandle.SetEnd(1);
                    }
                }

                _section = new Section(fhandle, _protection);

                _blockSize = MfsBlockSizeBase; // fake block size to begin with; we'll fix it up later.

                if (fhandle.GetSize() < _blockSize)
                {
                    if (readOnly)
                    {
                        throw new MfsInvalidFileSystemException();
                    }
                    else
                    {
                        // We're creating a new file system. We need the correct block size
                        // now.
                        if (createParams != null)
                        {
                            _blockSize = createParams.BlockSize;
                        }
                        else
                        {
                            _blockSize = MfsDefaultBlockSize;
                        }

                        _section.Extend(_blockSize);

                        using (var view = _section.MapView(0, _blockSize, _protection))
                            this.InitializeFs((MfsFsHeader *)view.Memory, createParams);

                        justCreated = true;
                    }
                }

                _header = (MfsFsHeader *)this.ReferenceBlock(0);

                // Check the magic.
                if (_header->Magic != MfsMagic)
                {
                    throw new MfsInvalidFileSystemException();
                }

                // Set up the local constants.
                _blockSize = _header->BlockSize;
                _cellSize  = _header->CellSize;

                // Backwards compatibility.
                if (_blockSize == 0)
                {
                    _blockSize = MfsDefaultBlockSize;
                }
                if (_cellSize == 0)
                {
                    _cellSize = MfsDefaultCellSize;
                }

                // Validate the parameters.
                this.ValidateFsParameters(_blockSize, _cellSize);

                _blockMask             = _blockSize - 1;
                _cellCount             = _blockSize / _cellSize;
                _dataCellDataMaxLength = _cellSize - MfsDataCell.DataOffset;

                // Remap block 0 with the correct block size.
                this.DereferenceBlock(0);

                // If we just created a new file system, fix the section size.
                if (justCreated)
                {
                    _section.Extend(_blockSize);
                }

                _header = (MfsFsHeader *)this.ReferenceBlock(0);

                // Set up the root object.
                _rootObject   = (MfsObjectHeader *)((byte *)_header + _cellSize);
                _rootObjectMo = new MemoryObject(this, _rootObjectCellId, true);

                if (_header->NextFreeBlock != 1 && !readOnly)
                {
                    ushort lastBlockId = (ushort)(_header->NextFreeBlock - 1);

                    this.ReferenceBlock(lastBlockId);
                    _cachedLastBlockView = _views[lastBlockId];
                }
            }
        }
 internal string GetObjectName(MfsObjectHeader *obj)
 {
     return(new string(obj->Name, 0, obj->NameLength));
 }