inode

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 12, 2025 License: MIT Imports: 13 Imported by: 1

README

inode - filesystem primitives for go

Go Reference Go Report Card CI License

The inode package provides Inode, Directory, and DirEntry primitives for inode style filesystems. This package does not implement any actual data storage features, only the data structures and logic needed to implement a storage system.

import "github.com/absfs/inode"

Example Usage

The basic idea is to use the inode package to handle file path resolution, directory entries, and basic file metadata such as file mode and modification time. The inode number can be used to link to actual file data.

Here's a simplified example using a map of byte slice to store file data.

See absfs/memfs for a complete in memory filesystem example.

package main

import (
	"fmt"
	"os"
	"path" // Use path (not path/filepath) for virtual filesystem paths

	"github.com/absfs/inode"
)

type SimpleFS struct {
  Ino  *inode.Ino
  Root *inode.Inode
  Data map[uint64][]byte
}

type SimpleFile struct {
  fs       *SimpleFS
  readonly bool
  node     *inode.Inode
  name     string
  data     []byte
}

func (fs *SimpleFS) Mkdir(name string, mode os.FileMode) error {
  child, err := fs.Root.Resolve(name)
  if err == nil {
    return os.ErrExist
  }

  dir, filename := path.Split(name)
  dir = path.Clean(dir)

  parent, err := fs.Root.Resolve(dir)
  if err != nil {
    return err
  }

  child = fs.Ino.NewDir(mode)
  parent.Link(filename, child)
  child.Link("..", parent)
  return nil
}

func (fs *SimpleFS) Create(name string) (f *SimpleFile, err error) {
  node, err := fs.Root.Resolve(name)
  if node != nil && err == nil {

    return &SimpleFile{
      fs:   fs,
      name: name,
      node: node,
      data: fs.Data[node.Ino],
    }, nil
  }

  dir, filename := path.Split(name)
  dir = path.Clean(dir)
  parent, err := fs.Root.Resolve(dir)
  if err != nil {
    return nil, err
  }

  node = fs.Ino.New(0644)
  fs.Data[node.Ino] = []byte{}
  parent.Link(filename, node)
  node.Link("..", parent)
  return &SimpleFile{
    fs:   fs,
    name: name,
    node: node,
    data: fs.Data[node.Ino],
  }, nil
}

func (fs *SimpleFS) Open(name string) (f *SimpleFile, err error) {
  node, err := fs.Root.Resolve(name)
  if err != nil {
    return nil, err
  }

  return &SimpleFile{
    fs:       fs,
    readonly: true,
    name:     name,
    node:     node,
    data:     fs.Data[node.Ino],
  }, nil
}

func (f *SimpleFile) Write(p []byte) (n int, err error) {
  if f.readonly {
    return 0, os.ErrPermission
  }

  f.data = append(f.data, p...)
  return len(p), nil
}

func (f *SimpleFile) Read(p []byte) (n int, err error) {
  n = copy(p, f.data)
  return n, nil
}

func (f *SimpleFile) Close() error {
  if !f.readonly {
    f.fs.Data[f.node.Ino] = f.data
  }
  return nil
}

func main() {

  ino := new(inode.Ino)
  fs := &SimpleFS{
    Ino:  ino,
    Root: ino.NewDir(0755),
    Data: make(map[uint64][]byte),
  }
  err := fs.Mkdir("/tmp", 0755)
  if err != nil {
    panic(err)
  }
  f, err := fs.Create("/tmp/testfile.txt")
  if err != nil {
    panic(err)
  }

  n, err := f.Write([]byte("Hello, World!\n"))
  if err != nil {
    panic(err)
  }
  f.Close()

  f, err = fs.Open("/tmp/testfile.txt")
  if err != nil {
    panic(err)
  }

  buffer := make([]byte, 512)
  n, err = f.Read(buffer)
  if err != nil {
    panic(err)
  }
  buffer = buffer[:n]
  if string(buffer) != "Hello, World!\n" {
    fmt.Fprintf(os.Stderr, "error buffer == %q\n", string(buffer))
  }
  fmt.Printf("%s", string(buffer))
}

LICENSE

This project is governed by the MIT License. See LICENSE

Documentation

Overview

Package inode provides block storage abstractions for filesystem implementations.

This file defines the BlockStore interfaces that enable different storage strategies ranging from simple byte arrays to sophisticated extent-based allocation.

Package inode provides thread-safe inode data structures for implementing in-memory filesystems.

Thread Safety

All exported methods are safe for concurrent use by multiple goroutines. The package uses a hybrid approach to minimize lock contention:

Lock-Free Operations (using sync/atomic):

  • Inode number allocation (Ino.New, Ino.NewDir)
  • Link count updates (Nlink field)
  • Timestamp updates (Ctime, Atime, Mtime via accessor methods)

RWMutex-Protected Operations:

  • Directory operations (Link, Unlink, Resolve, Rename, ReadDir, Lookup)

The Rename operation uses lock ordering by pointer address to prevent deadlocks when modifying multiple directories.

Direct Field Access

For callers that need to access Inode fields directly, Lock/Unlock and RLock/RUnlock methods are provided:

node.RLock()
entries := node.Dir  // Safe to read
node.RUnlock()

node.Lock()
node.Size = 1024  // Safe to write
node.Unlock()

However, prefer using the thread-safe methods (ReadDir, Lookup, etc.) when possible.

Usage Example

var ino inode.Ino
root := ino.NewDir(0755)

// Create a file
file := ino.New(0644)
root.Link("hello.txt", file)

// Create a subdirectory
subdir := ino.NewDir(0755)
root.Link("subdir", subdir)
subdir.Link("..", root)

// Resolve a path
node, err := root.Resolve("/subdir")

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Abs

func Abs(cwd, name string) string

Abs returns name if name is an absolute path. If name is a relative path then an absolute path is constructed by using cwd as the current working directory.

func BlockCount added in v0.9.0

func BlockCount(size int64, blockSize int) int64

BlockCount returns the number of blocks needed to store size bytes.

func BlockOffset added in v0.9.0

func BlockOffset(byteOffset int64, blockSize int) (block uint64, offset int64)

BlockOffset returns the block number and offset within block for a byte offset.

Example with 4096-byte blocks:

block, offset := BlockOffset(5000, 4096)  // returns (1, 904)

func BlockRange added in v0.9.0

func BlockRange(start, length int64, blockSize int) (firstBlock uint64, numBlocks uint64)

BlockRange returns the range of blocks that contain the byte range [start, start+length).

Returns the first block number and the number of blocks in the range.

Example with 4096-byte blocks:

first, count := BlockRange(5000, 3000, 4096)  // returns (1, 2)
// Covers bytes 5000-7999, which spans blocks 1-2

func PopPath

func PopPath(path string) (string, string)

PopPath returns the first name in `path` and the rest of the `path` string. The path provided must use forward slashes ("/").

func Walk

func Walk(node *Inode, path string, fn func(path string, n *Inode) error) error

Walk traverses a directory tree and calls fn for each file/directory encountered

Types

type BlockChainStore added in v0.9.0

type BlockChainStore interface {
	// BlockSize returns the fixed block size used by this store.
	BlockSize() int

	// AllocBlock allocates a new block and returns its unique ID.
	// The block's initial contents are undefined (may be zeros or garbage).
	AllocBlock() (blockID uint64, err error)

	// FreeBlock releases a block for reuse.
	// The block's contents become undefined after freeing.
	// Freeing a block that is already free should not return an error.
	FreeBlock(blockID uint64) error

	// ReadBlock reads the entire contents of a block.
	// Returns a byte slice of length BlockSize().
	// Reading a freed or never-allocated block returns undefined data.
	ReadBlock(blockID uint64) (data []byte, err error)

	// WriteBlock writes the entire contents of a block.
	// The data length must equal BlockSize().
	// Writing to a freed block is an error.
	WriteBlock(blockID uint64, data []byte) error

	// GetBlockChain returns the ordered list of block IDs for an inode.
	// For sparse files, unallocated blocks are represented as ID 0.
	// An empty or non-existent file returns an empty slice.
	GetBlockChain(ino uint64) (blockIDs []uint64, err error)

	// SetBlockChain updates the block chain for an inode.
	// This atomically replaces the entire block chain.
	// Block IDs of 0 represent holes (sparse regions).
	SetBlockChain(ino uint64, blockIDs []uint64) error
}

BlockChainStore provides fixed-size block storage with chaining.

Files are represented as sequences of fixed-size blocks, potentially with gaps (sparse files). This model enables incremental updates and efficient handling of large files with random access patterns.

Block IDs are opaque uint64 values. A block ID of 0 represents a hole (unallocated block) in sparse files.

Implementations should be safe for concurrent use by multiple goroutines.

type BlockSize added in v0.9.0

type BlockSize int

BlockSize represents a fixed block size in bytes.

const (
	// BlockSize4K is the standard 4 KiB block size used by most filesystems.
	BlockSize4K BlockSize = 4096

	// BlockSize8K is used by some filesystems for better performance.
	BlockSize8K BlockSize = 8192

	// BlockSize16K is used by filesystems optimized for larger files.
	BlockSize16K BlockSize = 16384

	// BlockSize64K is used for very large files or specific workloads.
	BlockSize64K BlockSize = 65536
)

type BlockStoreReadWriter added in v0.9.0

type BlockStoreReadWriter struct {
	Store ByteStore
	Ino   uint64
}

BlockStoreReadWriter wraps a ByteStore to implement io.ReaderAt and io.WriterAt.

func (*BlockStoreReadWriter) ReadAt added in v0.9.0

func (rw *BlockStoreReadWriter) ReadAt(p []byte, off int64) (n int, err error)

ReadAt implements io.ReaderAt.

func (*BlockStoreReadWriter) WriteAt added in v0.9.0

func (rw *BlockStoreReadWriter) WriteAt(p []byte, off int64) (n int, err error)

WriteAt implements io.WriterAt.

type BlockStoreReader added in v0.9.0

type BlockStoreReader struct {
	Store ByteStore
	Ino   uint64
}

BlockStoreReader wraps a ByteStore to implement io.ReaderAt.

func (*BlockStoreReader) ReadAt added in v0.9.0

func (r *BlockStoreReader) ReadAt(p []byte, off int64) (n int, err error)

ReadAt implements io.ReaderAt.

type BlockStoreWriter added in v0.9.0

type BlockStoreWriter struct {
	Store ByteStore
	Ino   uint64
}

BlockStoreWriter wraps a ByteStore to implement io.WriterAt.

func (*BlockStoreWriter) WriteAt added in v0.9.0

func (w *BlockStoreWriter) WriteAt(p []byte, off int64) (n int, err error)

WriteAt implements io.WriterAt.

type ByteStore added in v0.9.0

type ByteStore interface {
	// ReadAt reads len(p) bytes from the file at the given offset.
	// Returns the number of bytes read and any error encountered.
	// Returns io.EOF when offset is at or beyond the end of file.
	//
	// The behavior matches io.ReaderAt: a Read that encounters EOF
	// may return either (n, io.EOF) or (n, nil) and a subsequent
	// Read will return (0, io.EOF).
	ReadAt(ino uint64, p []byte, off int64) (n int, err error)

	// WriteAt writes len(p) bytes to the file at the given offset.
	// Extends the file if necessary, filling any gaps with zeros.
	// Returns the number of bytes written and any error encountered.
	//
	// WriteAt should not affect nor be affected by the underlying data
	// representation - it should handle sparse files efficiently.
	WriteAt(ino uint64, p []byte, off int64) (n int, err error)

	// Truncate changes the file size.
	// If the file is larger than size, it is truncated to size.
	// If the file is smaller, it is extended with zero bytes to size.
	Truncate(ino uint64, size int64) error

	// Remove deletes all data associated with the inode.
	// After Remove, operations on this inode should return an error.
	// Calling Remove on a non-existent inode should not return an error.
	Remove(ino uint64) error

	// Stat returns the current size of the file in bytes.
	// Returns (0, nil) for empty or non-existent files.
	Stat(ino uint64) (size int64, err error)
}

ByteStore provides simple byte-oriented file storage.

Each inode has a single variable-sized byte array. This is the simplest storage model, best suited for in-memory filesystems or small files.

Implementations should be safe for concurrent use by multiple goroutines.

Example usage:

store := NewMemByteStore()
store.WriteAt(ino, []byte("hello"), 0)
data := make([]byte, 5)
n, err := store.ReadAt(ino, data, 0)

type COWMemExtentStore added in v0.9.0

type COWMemExtentStore struct {
	*MemExtentStore
	// contains filtered or unexported fields
}

COWMemExtentStore extends MemExtentStore with copy-on-write support.

Implements the COWStore interface to enable efficient cloning and snapshots.

func NewCOWMemExtentStore added in v0.9.0

func NewCOWMemExtentStore(blockSize int) *COWMemExtentStore

NewCOWMemExtentStore creates a new COW-enabled ExtentStore.

func (*COWMemExtentStore) BreakCOW added in v0.9.0

func (s *COWMemExtentStore) BreakCOW(ino uint64, logicalBlock uint64) (uint64, error)

func (*COWMemExtentStore) CloneExtents added in v0.9.0

func (s *COWMemExtentStore) CloneExtents(srcIno, dstIno uint64) error

func (*COWMemExtentStore) RefCount added in v0.9.0

func (s *COWMemExtentStore) RefCount(physical uint64) uint64

type COWStore added in v0.9.0

type COWStore interface {
	// CloneExtents creates a copy-on-write clone of src's extent list for dst.
	// Both inodes will share the same physical blocks until one modifies them.
	// Reference counts for all shared blocks are incremented.
	CloneExtents(srcIno, dstIno uint64) error

	// BreakCOW ensures that the given extent is not shared.
	// If the extent is shared (refcount > 1), allocates a new extent,
	// copies the data, and updates the inode to use the new extent.
	// If the extent is not shared, does nothing.
	// Returns the (possibly new) physical block ID.
	BreakCOW(ino uint64, logicalBlock uint64) (physical uint64, err error)

	// RefCount returns the reference count for a physical block.
	// Returns 0 if the block is not allocated or not tracked.
	RefCount(physical uint64) uint64
}

COWStore extends a BlockStore with copy-on-write capabilities.

Copy-on-write allows multiple inodes to share the same physical blocks until one of them modifies the data. This enables efficient cloning and snapshotting.

Implementations must track reference counts for shared blocks and perform copy-before-write when modifying shared data.

type DirEntry

type DirEntry struct {
	Inode *Inode
	// contains filtered or unexported fields
}

DirEntry represents a single entry in a directory. It associates a name with an Inode pointer and implements fs.DirEntry.

func NewDirEntry added in v0.9.0

func NewDirEntry(name string, inode *Inode) *DirEntry

NewDirEntry creates a new directory entry with the given name and inode.

func (*DirEntry) Info added in v0.9.0

func (e *DirEntry) Info() (fs.FileInfo, error)

Info returns the FileInfo for the file or subdirectory described by the entry. This method implements fs.DirEntry.

func (*DirEntry) IsDir

func (e *DirEntry) IsDir() bool

IsDir returns true if this entry references a directory inode.

func (*DirEntry) Name

func (e *DirEntry) Name() string

Name returns the name of the file (or subdirectory) described by the entry. This implements fs.DirEntry.

func (*DirEntry) String

func (e *DirEntry) String() string

String returns a string representation of the directory entry.

func (*DirEntry) Type added in v0.9.0

func (e *DirEntry) Type() fs.FileMode

Type returns the type bits for the entry. This method implements fs.DirEntry.

type Directory

type Directory []*DirEntry

Directory is a sorted slice of directory entries. It implements sort.Interface for maintaining alphabetical order by name. This enables O(log n) lookups via binary search.

func (Directory) Len

func (d Directory) Len() int

Len returns the number of entries in the directory.

func (Directory) Less

func (d Directory) Less(i, j int) bool

Less reports whether the entry at i should sort before the entry at j.

func (Directory) Swap

func (d Directory) Swap(i, j int)

Swap exchanges entries at positions i and j.

type Extent added in v0.9.0

type Extent struct {
	// Logical is the starting logical block number in the file.
	// For a file with 4 KiB blocks, logical block 0 is bytes 0-4095,
	// logical block 1 is bytes 4096-8191, etc.
	Logical uint64

	// Physical is the physical block ID where this extent's data is stored.
	// This is opaque to the caller - the ExtentStore manages the mapping.
	Physical uint64

	// Length is the number of contiguous blocks in this extent.
	// An extent maps blocks [Logical, Logical+Length) to
	// physical blocks [Physical, Physical+Length).
	Length uint64
}

Extent represents a contiguous range of blocks.

An extent maps a logical range in a file to a physical range in storage. This enables efficient representation of large contiguous allocations.

type ExtentList added in v0.9.0

type ExtentList []Extent

ExtentList is a list of extents for a file. Extents should be sorted by Logical block number with no overlaps. Gaps between extents represent sparse regions (holes).

func (ExtentList) FindExtent added in v0.9.0

func (el ExtentList) FindExtent(logicalBlock uint64) (extIdx int, offset uint64, found bool)

FindExtent locates the extent containing the given logical block.

Returns:

  • extIdx: the index of the extent in the list
  • offset: the offset within the extent (logicalBlock - extent.Logical)
  • found: true if the block is within an allocated extent, false if it's in a hole

Example:

extents := ExtentList{
    {Logical: 0, Physical: 100, Length: 10},   // blocks 0-9
    {Logical: 20, Physical: 200, Length: 5},   // blocks 20-24
}
// Block 5 is in first extent at offset 5
extIdx, offset, found := extents.FindExtent(5)  // returns (0, 5, true)
// Block 15 is in a hole
extIdx, offset, found := extents.FindExtent(15) // returns (0, 0, false)

func (ExtentList) Len added in v0.9.0

func (el ExtentList) Len() int

Len returns the number of extents in the list.

func (ExtentList) Less added in v0.9.0

func (el ExtentList) Less(i, j int) bool

Less reports whether the extent at index i should sort before extent j.

func (ExtentList) LogicalSize added in v0.9.0

func (el ExtentList) LogicalSize() uint64

LogicalSize returns the logical size of the file in blocks.

This is the highest logical block number that could be accessed, including any sparse regions. For an empty extent list, returns 0.

Example:

extents := ExtentList{
    {Logical: 0, Physical: 100, Length: 10},
    {Logical: 20, Physical: 200, Length: 5},
}
size := extents.LogicalSize()  // returns 25 (blocks 0-24)

func (ExtentList) Swap added in v0.9.0

func (el ExtentList) Swap(i, j int)

Swap exchanges the extents at indices i and j.

func (ExtentList) TotalBlocks added in v0.9.0

func (el ExtentList) TotalBlocks() uint64

TotalBlocks returns the total number of allocated blocks across all extents.

This does not include sparse regions (holes). To get the total file size in blocks, use the last extent's Logical + Length.

type ExtentStore added in v0.9.0

type ExtentStore interface {
	// BlockSize returns the fixed block size used by this store.
	BlockSize() int

	// AllocExtent allocates a contiguous range of blocks.
	// Returns the physical block ID of the start and the actual length allocated.
	// May allocate less than requested if contiguous space is unavailable.
	// If any blocks are allocated, returns the extent and nil error.
	// If no blocks can be allocated, returns zero extent and an error.
	AllocExtent(desiredLength uint64) (physical uint64, length uint64, err error)

	// FreeExtent releases a contiguous range of blocks for reuse.
	// The blocks' contents become undefined after freeing.
	// All blocks [physical, physical+length) must be currently allocated.
	FreeExtent(physical uint64, length uint64) error

	// ReadExtent reads data from a physical extent.
	// Returns a byte slice of length (length * BlockSize()).
	// Reading from freed or never-allocated blocks returns undefined data.
	ReadExtent(physical uint64, length uint64) (data []byte, err error)

	// WriteExtent writes data to a physical extent.
	// The data length must equal (length * BlockSize()).
	// All blocks in the range must be currently allocated.
	WriteExtent(physical uint64, length uint64, data []byte) error

	// GetExtents returns the extent list for an inode.
	// Extents are sorted by logical block number.
	// Gaps between extents represent sparse regions.
	// An empty or non-existent file returns an empty extent list.
	GetExtents(ino uint64) (ExtentList, error)

	// SetExtents atomically updates the extent list for an inode.
	// This replaces the entire extent list.
	// Extents should be sorted by Logical block number with no overlaps.
	SetExtents(ino uint64, extents ExtentList) error
}

ExtentStore provides extent-based block storage.

Files are represented as lists of extents - contiguous ranges of blocks. This is the most sophisticated storage model, providing excellent performance for large sequential files while supporting sparse files and enabling copy-on-write semantics.

Implementations should be safe for concurrent use by multiple goroutines.

type Ino

type Ino uint64

Ino is an inode number allocator. It is safe for concurrent use. Each call to New or NewDir atomically increments the counter and returns a new Inode with a unique inode number.

func (*Ino) New

func (n *Ino) New(mode os.FileMode) *Inode

New creates a new Inode with the given mode and a unique inode number. This method is safe for concurrent use.

func (*Ino) NewDir

func (n *Ino) NewDir(mode os.FileMode) *Inode

NewDir creates a new directory Inode with the given mode and a unique inode number. The directory is initialized with "." and ".." entries pointing to itself. This method is safe for concurrent use.

type Inode

type Inode struct {
	Ino   uint64
	Mode  os.FileMode
	Nlink uint64
	Size  int64

	Uid uint32
	Gid uint32

	Dir Directory
	// contains filtered or unexported fields
}

An Inode represents the basic metadata of a file.

Thread Safety:

  • Ino is immutable after creation
  • Nlink, Size, Mode, Uid, Gid use atomic operations (lock-free)
  • ctime, atime, mtime use atomic operations (lock-free, accessed via methods)
  • Dir is protected by an internal RWMutex
  • All exported methods are safe for concurrent use
  • Direct field access requires external synchronization or use of Lock/RLock methods

func (*Inode) Atime

func (n *Inode) Atime() time.Time

Atime returns the access time of the inode.

func (*Inode) Ctime

func (n *Inode) Ctime() time.Time

Ctime returns the creation time of the inode.

func (*Inode) IsDir

func (n *Inode) IsDir() bool

IsDir returns true if this inode represents a directory.

func (n *Inode) Link(name string, child *Inode) error

Link adds a directory entry (DirEntry) for the given node (assumed to be a directory) to the provided child Inode. If an entry with the same name exists, it is replaced. This method is safe for concurrent use.

func (*Inode) Lock added in v0.9.0

func (n *Inode) Lock()

Lock acquires an exclusive lock on this inode. Use this when modifying fields directly.

func (*Inode) Lookup added in v0.9.0

func (n *Inode) Lookup(name string) *DirEntry

Lookup finds a directory entry by name and returns it. Returns nil if not found. This method is safe for concurrent use.

func (*Inode) Mtime

func (n *Inode) Mtime() time.Time

Mtime returns the modification time of the inode.

func (*Inode) RLock added in v0.9.0

func (n *Inode) RLock()

RLock acquires a read lock on this inode. Use this when reading Dir or timestamp fields directly.

func (*Inode) RUnlock added in v0.9.0

func (n *Inode) RUnlock()

RUnlock releases the read lock.

func (*Inode) ReadDir added in v0.9.0

func (n *Inode) ReadDir() []*DirEntry

ReadDir returns a snapshot of directory entries. This method is safe for concurrent use.

func (*Inode) Rename

func (n *Inode) Rename(oldpath, newpath string) error

Rename moves/renames a file or directory from oldpath to newpath. Both paths are resolved relative to this inode. This method is safe for concurrent use. It uses lock ordering by pointer address to prevent deadlocks when locking multiple directories.

func (*Inode) Resolve

func (n *Inode) Resolve(path string) (*Inode, error)

Resolve traverses the path and returns the target Inode. Supports both absolute and relative paths. This method is safe for concurrent use.

func (*Inode) SetAtime added in v0.9.0

func (n *Inode) SetAtime(t time.Time)

SetAtime sets the access time of the inode.

func (*Inode) SetCtime added in v0.9.0

func (n *Inode) SetCtime(t time.Time)

SetCtime sets the creation time of the inode.

func (*Inode) SetMtime added in v0.9.0

func (n *Inode) SetMtime(t time.Time)

SetMtime sets the modification time of the inode.

func (*Inode) String

func (n *Inode) String() string
func (n *Inode) Unlink(name string) error

Unlink removes the directory entry with the given name. This method is safe for concurrent use.

func (*Inode) UnlinkAll

func (n *Inode) UnlinkAll()

UnlinkAll recursively unlinks all entries in this directory. This method is safe for concurrent use.

func (*Inode) Unlock added in v0.9.0

func (n *Inode) Unlock()

Unlock releases the exclusive lock.

type MemBlockChainStore added in v0.9.0

type MemBlockChainStore struct {
	// contains filtered or unexported fields
}

MemBlockChainStore implements BlockChainStore using in-memory storage.

Files are represented as chains of fixed-size blocks. This demonstrates the block chain pattern with support for sparse files.

Thread-safe for concurrent use.

func NewMemBlockChainStore added in v0.9.0

func NewMemBlockChainStore(blockSize int) *MemBlockChainStore

NewMemBlockChainStore creates a new in-memory BlockChainStore.

func (*MemBlockChainStore) AllocBlock added in v0.9.0

func (s *MemBlockChainStore) AllocBlock() (uint64, error)

func (*MemBlockChainStore) BlockSize added in v0.9.0

func (s *MemBlockChainStore) BlockSize() int

func (*MemBlockChainStore) FreeBlock added in v0.9.0

func (s *MemBlockChainStore) FreeBlock(blockID uint64) error

func (*MemBlockChainStore) GetBlockChain added in v0.9.0

func (s *MemBlockChainStore) GetBlockChain(ino uint64) ([]uint64, error)

func (*MemBlockChainStore) ReadBlock added in v0.9.0

func (s *MemBlockChainStore) ReadBlock(blockID uint64) ([]byte, error)

func (*MemBlockChainStore) SetBlockChain added in v0.9.0

func (s *MemBlockChainStore) SetBlockChain(ino uint64, blockIDs []uint64) error

func (*MemBlockChainStore) WriteBlock added in v0.9.0

func (s *MemBlockChainStore) WriteBlock(blockID uint64, data []byte) error

type MemByteStore added in v0.9.0

type MemByteStore struct {
	// contains filtered or unexported fields
}

MemByteStore implements ByteStore using an in-memory map.

This is the simplest implementation, suitable for testing and small in-memory filesystems. It stores each file as a single contiguous byte slice.

Thread-safe for concurrent use.

func NewMemByteStore added in v0.9.0

func NewMemByteStore() *MemByteStore

NewMemByteStore creates a new in-memory ByteStore.

func (*MemByteStore) ReadAt added in v0.9.0

func (s *MemByteStore) ReadAt(ino uint64, p []byte, off int64) (int, error)

func (*MemByteStore) Remove added in v0.9.0

func (s *MemByteStore) Remove(ino uint64) error

func (*MemByteStore) Stat added in v0.9.0

func (s *MemByteStore) Stat(ino uint64) (int64, error)

func (*MemByteStore) Truncate added in v0.9.0

func (s *MemByteStore) Truncate(ino uint64, size int64) error

func (*MemByteStore) WriteAt added in v0.9.0

func (s *MemByteStore) WriteAt(ino uint64, p []byte, off int64) (int, error)

type MemExtentStore added in v0.9.0

type MemExtentStore struct {
	// contains filtered or unexported fields
}

MemExtentStore implements ExtentStore using in-memory storage.

Files are represented as lists of extents. This demonstrates the extent-based pattern with support for sparse files and efficient contiguous allocation.

Thread-safe for concurrent use.

func NewMemExtentStore added in v0.9.0

func NewMemExtentStore(blockSize int) *MemExtentStore

NewMemExtentStore creates a new in-memory ExtentStore.

func (*MemExtentStore) AllocExtent added in v0.9.0

func (s *MemExtentStore) AllocExtent(desiredLength uint64) (uint64, uint64, error)

func (*MemExtentStore) BlockSize added in v0.9.0

func (s *MemExtentStore) BlockSize() int

func (*MemExtentStore) FreeExtent added in v0.9.0

func (s *MemExtentStore) FreeExtent(physical uint64, length uint64) error

func (*MemExtentStore) GetExtents added in v0.9.0

func (s *MemExtentStore) GetExtents(ino uint64) (ExtentList, error)

func (*MemExtentStore) ReadExtent added in v0.9.0

func (s *MemExtentStore) ReadExtent(physical uint64, length uint64) ([]byte, error)

func (*MemExtentStore) SetExtents added in v0.9.0

func (s *MemExtentStore) SetExtents(ino uint64, extents ExtentList) error

func (*MemExtentStore) WriteExtent added in v0.9.0

func (s *MemExtentStore) WriteExtent(physical uint64, length uint64, data []byte) error

type Stat

type Stat struct {
	Filename string
	Node     *Inode
}

Stat - implements the os.FileInfo interface

func (*Stat) IsDir

func (i *Stat) IsDir() bool

abbreviation for Mode().IsDir()

func (*Stat) ModTime

func (i *Stat) ModTime() time.Time

modification time

func (*Stat) Mode

func (i *Stat) Mode() os.FileMode

file mode bits

func (*Stat) Name

func (i *Stat) Name() string

base name of the file

func (*Stat) Size

func (i *Stat) Size() int64

length in bytes for regular files; system-dependent for others

func (*Stat) Sys

func (i *Stat) Sys() interface{}

underlying data source (can return nil)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL