示例#1
0
        public Result CheckSimulatedAccessFailureEvent(SimulatingDeviceTargetOperation operation)
        {
            if (_isEventSet)
            {
                return(Result.Success);
            }

            using ScopedLock <SdkRecursiveMutex> lk = ScopedLock.Lock(ref _mutex);

            if ((_simulatedOperation & operation) == 0)
            {
                return(Result.Success);
            }

            Result result = GetCorrespondingResult(_simulatedFailureType);

            if (result.IsFailure() && _failureResult.IsFailure())
            {
                result = _failureResult;
            }

            if (_simulatedFailureType == SimulatingDeviceAccessFailureEventType.AccessTimeoutFailure)
            {
                SimulateTimeout();
            }

            if (!_isRecurringEvent)
            {
                ClearDeviceEvent();
            }

            return(result);
        }
        public void Register(ReferenceCountedDisposable <DirectorySaveDataFileSystem> fileSystem)
        {
            if (_maxCachedFileSystemCount <= 0)
            {
                return;
            }

            Assert.SdkRequiresGreaterEqual(_nextCacheIndex, 0);
            Assert.SdkRequiresGreater(_maxCachedFileSystemCount, _nextCacheIndex);

            if (fileSystem.Target.GetSaveDataSpaceId() == SaveDataSpaceId.SdSystem)
            {
                return;
            }

            Result rc = fileSystem.Target.Rollback();

            if (rc.IsFailure())
            {
                return;
            }

            using ScopedLock <SdkRecursiveMutexType> scopedLock = ScopedLock.Lock(ref _mutex);

            _cachedFileSystems[_nextCacheIndex].Register(fileSystem.AddReference <IFileSystem>(),
                                                         fileSystem.Target.GetSaveDataSpaceId(), fileSystem.Target.GetSaveDataId());

            _nextCacheIndex = (_nextCacheIndex + 1) % _maxCachedFileSystemCount;
        }
示例#3
0
        public void SetDetectionSimulationMode(SimulatingDeviceDetectionMode mode)
        {
            using ScopedLock <SdkRecursiveMutex> lk = ScopedLock.Lock(ref _mutex);

            _isDetectionSimulationEnabled = mode != SimulatingDeviceDetectionMode.NoSimulation;
            _detectionSimulationMode      = mode;
        }
示例#4
0
        protected virtual void Dispose(bool disposing)
        {
            if (!disposing)
            {
                return;
            }

            using (ScopedLock.Lock(ref _openListLock))
            {
                Abort.DoAbortUnless(_openFiles.Count == 0, ResultFs.FileNotClosed.Value,
                                    "All files must be closed before unmounting.");

                Abort.DoAbortUnless(_openDirectories.Count == 0, ResultFs.DirectoryNotClosed.Value,
                                    "All directories must be closed before unmounting.");

                if (_isPathCacheAttached)
                {
                    throw new NotImplementedException();
                }
            }

            _saveDataAttributeGetter?.Dispose();
            _saveDataAttributeGetter = null;

            _mountNameGenerator?.Dispose();
            _mountNameGenerator = null;

            _fileSystem?.Dispose();
            _fileSystem = null;
        }
示例#5
0
        public void SetCurrentPosixTimeWithTimeDifference(long currentTime, int timeDifference)
        {
            using ScopedLock <SdkMutexType> lk = ScopedLock.Lock(ref _mutex);

            _basePosixTime  = currentTime - GetSystemSeconds();
            _timeDifference = timeDifference;
        }
示例#6
0
        public void ClearDeviceEvent()
        {
            using ScopedLock <SdkRecursiveMutex> lk = ScopedLock.Lock(ref _mutex);

            _isEventSet           = false;
            _simulatedFailureType = SimulatingDeviceAccessFailureEventType.None;
            _simulatedOperation   = SimulatingDeviceTargetOperation.None;
            _failureResult        = Result.Success;
            _isRecurringEvent     = false;
        }
        public Result Register(ReferenceCountedDisposable <ISaveDataExtraDataAccessor> accessor,
                               SaveDataSpaceId spaceId, ulong saveDataId)
        {
            var cache = new Cache(accessor, spaceId, saveDataId);

            using ScopedLock <SdkRecursiveMutexType> scopedLock = ScopedLock.Lock(ref _mutex);

            _accessorList.AddLast(cache);
            return(Result.Success);
        }
示例#8
0
        public Result Mount(FileSystemAccessor fileSystem)
        {
            using ScopedLock <SdkMutexType> lk = ScopedLock.Lock(ref _mutex);

            if (!CanAcceptMountName(fileSystem.GetName()))
            {
                return(ResultFs.MountNameAlreadyExists.Log());
            }

            _fileSystemList.AddLast(fileSystem);
            return(Result.Success);
        }
示例#9
0
        private Result GetLocationResolver(out LocationResolver resolver, StorageId storageId)
        {
            UnsafeHelpers.SkipParamInit(out resolver);

            if (!IsValidStorageId(storageId))
            {
                return(ResultLr.LocationResolverNotFound.Log());
            }

            using ScopedLock <SdkMutexType> lk = ScopedLock.Lock(ref _mutex);

            int index = GetResolverIndexFromStorageId(storageId);
            ref LocationResolver lr = ref _resolvers[index];
        public void Unregister(SaveDataSpaceId spaceId, ulong saveDataId)
        {
            Assert.SdkRequiresGreaterEqual(_maxCachedFileSystemCount, 0);

            using ScopedLock <SdkRecursiveMutexType> scopedLock = ScopedLock.Lock(ref _mutex);

            for (int i = 0; i < _maxCachedFileSystemCount; i++)
            {
                if (_cachedFileSystems[i].IsCached(spaceId, saveDataId))
                {
                    _cachedFileSystems[i].Unregister();
                }
            }
        }
示例#11
0
        public void Dispose()
        {
            using ScopedLock <SdkMutexType> scopedLock = ScopedLock.Lock(ref Globals.Mutex);

            LinkedListNode <Entry> currentEntry = _entryList.First;

            while (currentEntry is not null)
            {
                ref Entry entry = ref currentEntry.ValueRef;
                _entryList.Remove(currentEntry);
                entry.Dispose();

                currentEntry = _entryList.First;
            }
示例#12
0
        /// <summary>
        /// Defines a new runtime type.
        /// </summary>
        /// <param name="attributes">The custom type attributes.</param>
        /// <param name="baseClass">The base class.</param>
        /// <param name="typeBuilder">The type builder.</param>
        /// <returns>The acquired scoped lock.</returns>
        private ScopedLock DefineRuntimeType(
            TypeAttributes attributes,
            Type baseClass,
            out TypeBuilder typeBuilder)
        {
            var scopedLock = new ScopedLock(this);

            typeBuilder = moduleBuilder.DefineType(
                CustomTypeName + typeBuilderIdx++,
                attributes,
                baseClass);

            return(scopedLock);
        }
示例#13
0
        public Result Commit()
        {
            using (ScopedLock.Lock(ref _openListLock))
            {
                DumpUnclosedAccessorList(OpenMode.Write, 0);

                if (HasOpenWriteModeFiles(_openFiles))
                {
                    return(ResultFs.WriteModeFileNotClosed.Log());
                }
            }

            return(_fileSystem.Commit());
        }
示例#14
0
        public void SetDeviceEvent(SimulatingDeviceTargetOperation operation,
                                   SimulatingDeviceAccessFailureEventType failureType, Result failureResult, bool isRecurringEvent)
        {
            using ScopedLock <SdkRecursiveMutex> lk = ScopedLock.Lock(ref _mutex);

            if (failureResult.IsFailure())
            {
                _failureResult = failureResult;
            }

            _isEventSet           = true;
            _simulatedFailureType = failureType;
            _simulatedOperation   = operation;
            _isRecurringEvent     = isRecurringEvent;
        }
示例#15
0
        public Result OpenFile(out FileAccessor file, U8Span path, OpenMode mode)
        {
            UnsafeHelpers.SkipParamInit(out file);

            Result rc = CheckPath(new U8Span(_mountName.Name), path);

            if (rc.IsFailure())
            {
                return(rc);
            }

            IFile iFile = null;

            try
            {
                rc = _fileSystem.OpenFile(out iFile, path, mode);
                if (rc.IsFailure())
                {
                    return(rc);
                }

                var fileAccessor = new FileAccessor(FsClient, ref iFile, this, mode);

                using (ScopedLock.Lock(ref _openListLock))
                {
                    _openFiles.AddLast(fileAccessor);
                }

                if (_isPathCacheAttached)
                {
                    if (mode.HasFlag(OpenMode.AllowAppend))
                    {
                        throw new NotImplementedException();
                    }
                    else
                    {
                        throw new NotImplementedException();
                    }
                }

                file = Shared.Move(ref fileAccessor);
                return(Result.Success);
            }
            finally
            {
                iFile?.Dispose();
            }
        }
        public static FaultRule[] DeserializeRules(string fileName, Mutex mutex)
        {
            BinaryFormatter formatter = new BinaryFormatter();

            using (ScopedLock scope = new ScopedLock(mutex))
            {
                using (FileStream stream = File.Open(fileName, FileMode.Open))
                {
                    // Use assembly locations recorded to handle assembly resolvation
                    Dictionary <string, string> locations = (Dictionary <string, string>)formatter.Deserialize(stream);
                    resolver.AddAssemblyLocations(locations);

                    return((FaultRule[])formatter.Deserialize(stream));
                }
            }
        }
        public Result GetCache(out ReferenceCountedDisposable <ISaveDataExtraDataAccessor> accessor,
                               SaveDataSpaceId spaceId, ulong saveDataId)
        {
            UnsafeHelpers.SkipParamInit(out accessor);

            using ScopedLock <SdkRecursiveMutexType> scopedLock = ScopedLock.Lock(ref _mutex);

            LinkedListNode <Cache> currentNode = _accessorList.First;

            while (true)
            {
                if (currentNode is null)
                {
                    return(ResultFs.TargetNotFound.Log());
                }

                if (currentNode.ValueRef.Contains(spaceId, saveDataId))
                {
                    break;
                }

                currentNode = currentNode.Next;
            }

            ReferenceCountedDisposable <ISaveDataExtraDataAccessor> tempAccessor = null;

            try
            {
                tempAccessor = currentNode.ValueRef.Lock();

                // Return early if the accessor was already disposed
                if (tempAccessor is null)
                {
                    // Note: Nintendo doesn't remove the accessor from the list in this case
                    _accessorList.Remove(currentNode);
                    return(ResultFs.TargetNotFound.Log());
                }

                accessor = SaveDataExtraDataResultConvertAccessor.CreateShared(ref tempAccessor);
                return(Result.Success);
            }
            finally
            {
                tempAccessor?.Dispose();
            }
        }
示例#18
0
        /// <summary>
        /// Defines a new runtime method.
        /// </summary>
        /// <param name="returnType">The return type.</param>
        /// <param name="parameterTypes">All parameter types.</param>
        /// <param name="methodEmitter">The method emitter.</param>
        /// <returns>The acquired scoped lock.</returns>
        public ScopedLock DefineRuntimeMethod(
            Type returnType,
            Type[] parameterTypes,
            out MethodEmitter methodEmitter)
        {
            var scopedLock = new ScopedLock(this);

            methodEmitter = new MethodEmitter(
                new DynamicMethod(
                    LauncherMethodName,
                    returnType,
                    parameterTypes,
                    moduleBuilder,
                    true));

            return(scopedLock);
        }
        public Result Initialize(int maxCacheCount)
        {
            Assert.SdkRequiresGreaterEqual(maxCacheCount, 0);

            using ScopedLock <SdkRecursiveMutexType> scopedLock = ScopedLock.Lock(ref _mutex);

            Assert.SdkAssert(_cachedFileSystems is null);

            _maxCachedFileSystemCount = maxCacheCount;
            if (maxCacheCount <= 0)
            {
                return(Result.Success);
            }

            // Note: The original checks for overflow here
            _cachedFileSystems = new Cache[maxCacheCount];
            return(Result.Success);
        }
示例#20
0
        public Result Find(out FileSystemAccessor accessor, U8Span name)
        {
            UnsafeHelpers.SkipParamInit(out accessor);
            using ScopedLock <SdkMutexType> lk = ScopedLock.Lock(ref _mutex);

            for (LinkedListNode <FileSystemAccessor> currentNode = _fileSystemList.First;
                 currentNode is not null;
                 currentNode = currentNode.Next)
            {
                if (!Matches(currentNode.Value, name))
                {
                    continue;
                }
                accessor = currentNode.Value;
                return(Result.Success);
            }

            return(ResultFs.NotMounted.Log());
        }
示例#21
0
        public void UnsetOpenType(OpenType type)
        {
            using ScopedLock <SdkMutexType> scopedLock =
                      ScopedLock.Lock(ref Globals.Mutex);

            if (type == OpenType.Normal)
            {
                _isNormalStorageOpened = false;
            }
            else if (type == OpenType.Internal)
            {
                _isInternalStorageOpened = false;
            }

            if (!IsOpened())
            {
                Globals.SaveDataFileStorageHolder.Unregister(_spaceId, _saveDataId);
            }
        }
        public bool GetCache(out ReferenceCountedDisposable <IFileSystem> fileSystem, SaveDataSpaceId spaceId,
                             ulong saveDataId)
        {
            Assert.SdkRequiresGreaterEqual(_maxCachedFileSystemCount, 0);

            using ScopedLock <SdkRecursiveMutexType> scopedLock = ScopedLock.Lock(ref _mutex);

            for (int i = 0; i < _maxCachedFileSystemCount; i++)
            {
                if (_cachedFileSystems[i].IsCached(spaceId, saveDataId))
                {
                    fileSystem = _cachedFileSystems[i].Move();
                    return(true);
                }
            }

            fileSystem = default;
            return(false);
        }
        public static void SerializeRules(string fileName, FaultRule[] rules, Mutex mutex)
        {
            if (rules == null)
            {
                throw new FaultInjectionException(ApiErrorMessages.FaultRulesNullInSerialization);
            }

            // Recording locations for all assemblies loaded in AppDomain running test code
            // We need these information to find types while deserialization
            Dictionary <string, string> locations = new Dictionary <string, string>();

            foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
            {
                try
                {
                    locations[assembly.FullName] = assembly.Location;
                }
                catch (NotSupportedException)
                {
                    // Swallow NotSupportedException for dynamic assemblies
                }
            }

            // Serialize fault rules into a temporary file
            BinaryFormatter formatter = new BinaryFormatter();
            string          tempFile  = Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileName(Path.GetTempFileName()));

            using (FileStream stream = File.Open(tempFile, FileMode.Create))
            {
                formatter.Serialize(stream, locations);
                formatter.Serialize(stream, rules);
            }

            // Swap it to serialization file
            using (ScopedLock scope = new ScopedLock(mutex))
            {
                File.Delete(fileName);
                File.Move(tempFile, fileName);
            }
        }
示例#24
0
        public void Unmount(U8Span name)
        {
            using ScopedLock <SdkMutexType> lk = ScopedLock.Lock(ref _mutex);

            LinkedListNode <FileSystemAccessor> currentNode;

            for (currentNode = _fileSystemList.First; currentNode is not null; currentNode = currentNode.Next)
            {
                if (Matches(currentNode.Value, name))
                {
                    break;
                }
            }

            if (currentNode is null)
            {
                Abort.DoAbort(ResultFs.NotMounted.Log(), $"{name.ToString()} is not mounted.");
            }

            _fileSystemList.Remove(currentNode);
            currentNode.Value.Dispose();
        }
示例#25
0
        public Result GetCurrentPosixTimeWithTimeDifference(out long currentTime, out int timeDifference)
        {
            UnsafeHelpers.SkipParamInit(out currentTime, out timeDifference);

            using ScopedLock <SdkMutexType> lk = ScopedLock.Lock(ref _mutex);

            if (_basePosixTime == 0)
            {
                return(ResultFs.NotInitialized.Log());
            }

            if (!Unsafe.IsNullRef(ref currentTime))
            {
                currentTime = _basePosixTime + GetSystemSeconds();
            }

            if (!Unsafe.IsNullRef(ref timeDifference))
            {
                timeDifference = _timeDifference;
            }

            return(Result.Success);
        }
示例#26
0
        public Result OpenDirectory(out DirectoryAccessor directory, U8Span path, OpenDirectoryMode mode)
        {
            UnsafeHelpers.SkipParamInit(out directory);

            Result rc = CheckPath(new U8Span(_mountName.Name), path);

            if (rc.IsFailure())
            {
                return(rc);
            }

            IDirectory iDirectory = null;

            try
            {
                rc = _fileSystem.OpenDirectory(out iDirectory, path, mode);
                if (rc.IsFailure())
                {
                    return(rc);
                }

                var directoryAccessor = new DirectoryAccessor(ref iDirectory, this);

                using (ScopedLock.Lock(ref _openListLock))
                {
                    _openDirectories.AddLast(directoryAccessor);
                }

                directory = Shared.Move(ref directoryAccessor);
                return(Result.Success);
            }
            finally
            {
                iDirectory?.Dispose();
            }
        }
        public void Unregister(SaveDataSpaceId spaceId, ulong saveDataId)
        {
            using ScopedLock <SdkRecursiveMutexType> scopedLock = ScopedLock.Lock(ref _mutex);

            UnregisterImpl(spaceId, saveDataId);
        }
示例#28
0
 public void NotifyCloseFile(FileAccessor file)
 {
     using ScopedLock <SdkMutexType> lk = ScopedLock.Lock(ref _openListLock);
     Remove(_openFiles, file);
 }
示例#29
0
 public void NotifyCloseDirectory(DirectoryAccessor directory)
 {
     using ScopedLock <SdkMutexType> lk = ScopedLock.Lock(ref _openListLock);
     Remove(_openDirectories, directory);
 }