storage

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Apr 17, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Overview

Package storage implements Pulp's storage primitives. v0.4 begins with a scoped filesystem (FS) that confines a plugin to a single root directory — all paths are relative, and traversal attempts (../, absolute paths, null bytes) are rejected before any syscall fires.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func FSCapability

func FSCapability(fs *FS) host.Capability

FSCapability returns the Capability that wires fs_read, fs_write, and fs_delete into the "pulp" host module. The plugin sees a single scoped root — all paths are relative; escape attempts fail at the host boundary before any syscall.

Host import signatures:

fs_read(path_ptr, path_len, data_ptr_out, data_len_out) -> error_code
  Reads the file; allocates the result buffer via pulp_alloc and
  stores (ptr, len) at the out-addresses.

fs_write(path_ptr, path_len, data_ptr, data_len) -> error_code

fs_delete(path_ptr, path_len) -> error_code

Error codes: 0 ok, 1 empty input, 2 memory read failed, 4 path invalid / escape, 5 fs operation failed, 6 not found, 7 alloc failed, 8 memory write failed.

func SQLiteCapability

func SQLiteCapability(s *SQLite) host.Capability

SQLiteCapability returns the Capability that wires sqlite_exec and sqlite_query into the "pulp" host module. One database per plugin lives at the host's chosen path.

Host import signatures:

sqlite_exec(query_ptr, query_len, params_ptr, params_len,
            res_ptr_out, res_len_out) -> error_code
  query   = SQL string bytes
  params  = MessagePack []any, or empty when no parameters
  result  = MessagePack ExecResult {rows_affected, last_insert_id}
            written to plugin memory via pulp_alloc; pointer and
            length are stored at the caller-supplied out-addresses.

sqlite_query(query_ptr, query_len, params_ptr, params_len,
             rows_ptr_out, rows_len_out) -> error_code
  rows bytes (written to plugin memory via pulp_alloc) =
    MessagePack [][]any — outer slice is rows, inner slice is
    column values in declaration order.

Error codes: 0 ok, 1 empty query, 2 memory read failed, 3 params decode failed, 5 sql error, 7 alloc failed, 8 memory write failed.

Types

type ExecResult

type ExecResult struct {
	RowsAffected int64 `msgpack:"rows_affected"`
	LastInsertID int64 `msgpack:"last_insert_id"`
}

ExecResult is what Exec returns: number of rows affected plus the auto-increment row ID created by an INSERT (0 if not applicable).

type FS

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

FS is a per-plugin scoped filesystem. Every path passed to its methods is resolved against Root; the result is required to remain underneath Root or the call fails. One FS per plugin — never share across plugins.

func NewFS

func NewFS(root string, logger *slog.Logger) (*FS, error)

NewFS creates the root directory if missing and returns an FS rooted there. Root is resolved to an absolute path so later prefix checks are robust to relative calls or working-directory changes.

func (*FS) Delete

func (f *FS) Delete(rel string) error

Delete removes rel. Missing files are reported as errors — callers that want "delete if exists" must handle os.IsNotExist themselves.

func (*FS) Read

func (f *FS) Read(rel string) ([]byte, error)

Read returns the bytes at rel. rel must be a relative path below the root; absolute paths, "..", and null bytes are rejected.

func (*FS) Root

func (f *FS) Root() string

Root returns the absolute root directory. Diagnostic only — plugins never see this path.

func (*FS) Write

func (f *FS) Write(rel string, data []byte) error

Write writes data to rel, creating any missing parent directories under the root. Existing files are truncated.

type QueryResult

type QueryResult struct {
	Columns []string `msgpack:"columns"`
	Rows    [][]any  `msgpack:"rows"`
}

QueryResult is the structured return value of Query: column names in declaration order plus the matching row values.

type SQLite

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

SQLite is a per-plugin SQLite database handle. The underlying database lives at a fixed on-disk path the host chooses; all access goes through Exec and Query, which the capability wires into host imports.

func NewSQLite

func NewSQLite(path string, logger *slog.Logger) (*SQLite, error)

NewSQLite opens (creating if absent) a SQLite database at path. The parent directory is created as needed. The returned handle owns the connection pool — call Close to release it.

MaxOpenConns is pinned to 1 so that BEGIN/COMMIT issued by the plugin as normal Exec statements always land on the same connection. Without this the pool would spread statements across connections and transactions would silently no-op.

func (*SQLite) Close

func (s *SQLite) Close() error

Close releases the connection pool.

func (*SQLite) Exec

func (s *SQLite) Exec(ctx context.Context, query string, args []any) (ExecResult, error)

Exec runs a statement that is not expected to return rows and returns both RowsAffected and LastInsertId. Callers that only care about one can ignore the other.

func (*SQLite) Path

func (s *SQLite) Path() string

Path returns the absolute DB file path. Diagnostic only.

func (*SQLite) Query

func (s *SQLite) Query(ctx context.Context, query string, args []any) (QueryResult, error)

Query runs a SELECT and returns the column names plus rows. Row values are ordered to match Columns. The encoder turns the QueryResult into MessagePack for delivery to the plugin.

Jump to

Keyboard shortcuts

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