public ConcatenationDirectory(ConcatenationFileSystem fs, IFileSystem baseFs, IDirectory parentDirectory, OpenDirectoryMode mode, U8Span path)
        {
            ParentFileSystem = fs;
            BaseFileSystem   = baseFs;
            ParentDirectory  = parentDirectory;
            Mode             = mode;

            StringUtils.Copy(_path.Str, path);
            _path.Str[PathTools.MaxPathLength] = StringTraits.NullTerminator;

            // Ensure the path ends with a separator
            int pathLength = StringUtils.GetLength(path, PathTools.MaxPathLength + 1);

            if (pathLength != 0 && _path.Str[pathLength - 1] == StringTraits.DirectorySeparator)
            {
                return;
            }

            if (pathLength >= PathTools.MaxPathLength)
            {
                throw new HorizonResultException(ResultFs.TooLongPath.Value, "abort");
            }

            _path.Str[pathLength]              = StringTraits.DirectorySeparator;
            _path.Str[pathLength + 1]          = StringTraits.NullTerminator;
            _path.Str[PathTools.MaxPathLength] = StringTraits.NullTerminator;
        }
 public ConcatenationDirectory(ConcatenationFileSystem fs, IFileSystem baseFs, IDirectory parentDirectory, OpenDirectoryMode mode, string path)
 {
     ParentFileSystem = fs;
     BaseFileSystem   = baseFs;
     ParentDirectory  = parentDirectory;
     Mode             = mode;
     Path             = path;
 }
        private bool IsConcatenationFile(DirectoryEntry entry)
        {
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                return(ConcatenationFileSystem.HasConcatenationFileAttribute(entry.Attributes));
            }
            else
            {
                string name     = Util.GetUtf8StringNullTerminated(entry.Name);
                string fullPath = PathTools.Combine(Path, name);

                return(ParentFileSystem.IsConcatenationFile(fullPath));
            }
        }
        private bool IsConcatenationFile(DirectoryEntry entry)
        {
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                return(ConcatenationFileSystem.HasConcatenationFileAttribute(entry.Attributes));
            }
            else
            {
                string name     = StringUtils.NullTerminatedUtf8ToString(entry.Name);
                var    fullPath = PathTools.Combine(_path.ToString(), name).ToU8Span();

                return(ParentFileSystem.IsConcatenationFile(fullPath));
            }
        }
        protected override Result SetSizeImpl(long size)
        {
            Result rc = GetSize(out long currentSize);

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

            if (currentSize == size)
            {
                return(Result.Success);
            }

            int currentSubFileCount = QuerySubFileCount(currentSize, SubFileSize);
            int newSubFileCount     = QuerySubFileCount(size, SubFileSize);

            if (size > currentSize)
            {
                IFile currentLastSubFile = Sources[currentSubFileCount - 1];
                long  newSubFileSize     = QuerySubFileSize(currentSubFileCount - 1, size, SubFileSize);

                rc = currentLastSubFile.SetSize(newSubFileSize);
                if (rc.IsFailure())
                {
                    return(rc);
                }

                for (int i = currentSubFileCount; i < newSubFileCount; i++)
                {
                    FsPath newSubFilePath;
                    unsafe { _ = &newSubFilePath; } // workaround for CS0165

                    rc = ConcatenationFileSystem.GetSubFilePath(newSubFilePath.Str, FilePath, i);
                    if (rc.IsFailure())
                    {
                        return(rc);
                    }

                    newSubFileSize = QuerySubFileSize(i, size, SubFileSize);

                    rc = BaseFileSystem.CreateFile(newSubFilePath, newSubFileSize, CreateFileOptions.None);
                    if (rc.IsFailure())
                    {
                        return(rc);
                    }

                    rc = BaseFileSystem.OpenFile(out IFile newSubFile, newSubFilePath, Mode);
                    if (rc.IsFailure())
                    {
                        return(rc);
                    }

                    Sources.Add(newSubFile);
                }
            }
            else
            {
                for (int i = currentSubFileCount - 1; i > newSubFileCount - 1; i--)
                {
                    Sources[i].Dispose();
                    Sources.RemoveAt(i);

                    FsPath subFilePath;
                    unsafe { _ = &subFilePath; } // workaround for CS0165

                    rc = ConcatenationFileSystem.GetSubFilePath(subFilePath.Str, FilePath, i);
                    if (rc.IsFailure())
                    {
                        return(rc);
                    }

                    rc = BaseFileSystem.DeleteFile(subFilePath);
                    if (rc.IsFailure())
                    {
                        return(rc);
                    }
                }

                long newLastFileSize = QuerySubFileSize(newSubFileCount - 1, size, SubFileSize);

                rc = Sources[newSubFileCount - 1].SetSize(newLastFileSize);
                if (rc.IsFailure())
                {
                    return(rc);
                }
            }

            return(Result.Success);
        }