Documentation
¶
Overview ¶
Package filesystem provides Scriptling's filesystem extension libraries: os and os.path, pathlib, glob, fs, shutil, tempfile, zipfile, tarfile, scriptling.grep, scriptling.find and scriptling.sed. Every library checks paths against the allowed paths it is registered with (nil allows all, an empty slice denies all). The package also exports a plain-Go API (Grep, Find, SedReplace, EditFile, ...) that needs no interpreter.
Index ¶
- Constants
- Variables
- func EditFile(ctx context.Context, path, search, replace string) (int, error)
- func Find(ctx context.Context, root string, opts FindOptions) ([]string, error)
- func NewFindLibrary(config fssecurity.Config) *object.Library
- func NewGlobLibrary(config fssecurity.Config) *object.Library
- func NewGrepLibrary(config fssecurity.Config) *object.Library
- func NewOSLibrary(config fssecurity.Config) (*object.Library, *object.Library)
- func NewPathlibLibrary(config fssecurity.Config) *object.Library
- func NewSedLibrary(config fssecurity.Config) *object.Library
- func NewShutilLibrary(config fssecurity.Config) *object.Library
- func NewTarfileLibrary(config fssecurity.Config) *object.Library
- func NewTempfileLibrary(config fssecurity.Config) *object.Library
- func NewZipfileLibrary(config fssecurity.Config) *object.Library
- func RegisterAll(registrar object.LibraryRegistrar, allowedPaths []string)
- func RegisterFS(registrar object.LibraryRegistrar, allowedPaths []string)
- func RegisterFind(registrar object.LibraryRegistrar, allowedPaths []string)
- func RegisterGlob(registrar object.LibraryRegistrar, allowedPaths []string)
- func RegisterGrep(registrar object.LibraryRegistrar, allowedPaths []string)
- func RegisterOS(registrar object.LibraryRegistrar, allowedPaths []string)
- func RegisterPathlib(registrar object.LibraryRegistrar, allowedPaths []string)
- func RegisterSed(registrar object.LibraryRegistrar, allowedPaths []string)
- func RegisterShutil(registrar object.LibraryRegistrar, allowedPaths []string)
- func RegisterTarfile(registrar object.LibraryRegistrar, allowedPaths []string)
- func RegisterTempfile(registrar object.LibraryRegistrar, allowedPaths []string)
- func RegisterZipfile(registrar object.LibraryRegistrar, allowedPaths []string)
- func SedReplace(ctx context.Context, old, replacement, path string, opts SedOptions) (int64, error)
- func SedReplacePattern(ctx context.Context, pattern, replacement, path string, opts SedOptions) (int64, error)
- type ExtractMatch
- type FindEntry
- type FindOptions
- type GlobLibraryInstance
- type GrepMatch
- type GrepOptions
- type PathlibLibraryInstance
- type SedOptions
Constants ¶
const ( OSLibraryName = "os" OSPathLibraryName = "os.path" PathlibLibraryName = "pathlib" GlobLibraryName = "glob" FSLibraryName = "fs" ShutilLibraryName = "shutil" TempfileLibraryName = "tempfile" ZipfileLibraryName = "zipfile" TarfileLibraryName = "tarfile" GrepLibraryName = "scriptling.grep" FindLibraryName = "scriptling.find" SedLibraryName = "scriptling.sed" )
Library names.
Variables ¶
var ErrPathNotAllowed = fssecurity.ErrPathNotAllowed
ErrPathNotAllowed is returned when a requested path falls outside the AllowedPaths configured on the options struct.
var ErrSearchNotFound = errors.New("search text not found")
ErrSearchNotFound is returned by EditFile when the search text does not appear in the file at all.
var ErrSearchNotUnique = errors.New("search text matched multiple times")
ErrSearchNotUnique is returned by EditFile when the search text appears more than once. The caller should provide more surrounding context to disambiguate.
Functions ¶
func EditFile ¶
EditFile performs a targeted search-and-replace on a single file: it finds the exact `search` text, verifies it appears exactly once, and replaces it with `replace`. The modification is written atomically (temp file + rename), matching sed's in-place edit semantics.
Unlike SedReplace (which replaces every occurrence line-by-line), EditFile operates on the full file content and requires the match to be unique — the gold standard for coding-agent edits where "replace all" is dangerous.
search and replace may span multiple lines. Returns the number of bytes written.
func Find ¶
Find returns the paths under root that match the given filters. It uses the same concurrent walker as scriptling.find. Paths are returned in arbitrary order. The root itself is never included in the result.
func NewFindLibrary ¶
func NewFindLibrary(config fssecurity.Config) *object.Library
NewFindLibrary creates a new scriptling.find library with the given configuration.
func NewGlobLibrary ¶
func NewGlobLibrary(config fssecurity.Config) *object.Library
NewGlobLibrary creates a new Glob library with the given configuration.
func NewGrepLibrary ¶
func NewGrepLibrary(config fssecurity.Config) *object.Library
NewGrepLibrary creates a new scriptling.grep library with the given configuration.
func NewOSLibrary ¶
NewOSLibrary creates a new OS library with the given configuration. The returned libraries are for "os" and "os.path". Prefer using RegisterOS which handles registration automatically.
func NewPathlibLibrary ¶
func NewPathlibLibrary(config fssecurity.Config) *object.Library
NewPathlibLibrary creates a new Pathlib library with the given configuration.
func NewSedLibrary ¶
func NewSedLibrary(config fssecurity.Config) *object.Library
NewSedLibrary creates a new scriptling.sed library with the given configuration.
func NewShutilLibrary ¶
func NewShutilLibrary(config fssecurity.Config) *object.Library
NewShutilLibrary creates a new shutil library with the given configuration.
func NewTarfileLibrary ¶
func NewTarfileLibrary(config fssecurity.Config) *object.Library
func NewTempfileLibrary ¶
func NewTempfileLibrary(config fssecurity.Config) *object.Library
NewTempfileLibrary creates a new tempfile library with the given configuration.
func NewZipfileLibrary ¶
func NewZipfileLibrary(config fssecurity.Config) *object.Library
func RegisterAll ¶
func RegisterAll(registrar object.LibraryRegistrar, allowedPaths []string)
RegisterAll registers every filesystem library (os and os.path, pathlib, glob, fs, shutil, tempfile, zipfile, tarfile, scriptling.grep, scriptling.find and scriptling.sed), all restricted to allowedPaths.
func RegisterFS ¶
func RegisterFS(registrar object.LibraryRegistrar, allowedPaths []string)
func RegisterFind ¶
func RegisterFind(registrar object.LibraryRegistrar, allowedPaths []string)
RegisterFind registers the scriptling.find library with a Scriptling instance. If allowedPaths is nil, all paths are allowed. If non-nil, all find operations are restricted to those directories (same semantics as RegisterGrep).
func RegisterGlob ¶
func RegisterGlob(registrar object.LibraryRegistrar, allowedPaths []string)
RegisterGlob registers the glob library with a Scriptling instance. If allowedPaths is empty or nil, all paths are allowed (no restrictions). If allowedPaths contains paths, all glob operations are restricted to those directories.
SECURITY: When running untrusted scripts, ALWAYS provide allowedPaths to restrict file system access. The security checks prevent: - Reading files outside allowed directories - Path traversal attacks (../../../etc/passwd) - Symlink attacks (symlinks pointing outside allowed dirs)
Example:
No restrictions - full filesystem access (DANGEROUS for untrusted code)
filesystem.RegisterGlob(s, nil)
Restricted to specific directories (SECURE)
filesystem.RegisterGlob(s, []string{"/tmp/sandbox", "/home/user/data"})
func RegisterGrep ¶
func RegisterGrep(registrar object.LibraryRegistrar, allowedPaths []string)
RegisterGrep registers the scriptling.grep library with a Scriptling instance. If allowedPaths is nil, all paths are allowed. If non-nil, operations are restricted to those directories (same semantics as RegisterOS).
func RegisterOS ¶
func RegisterOS(registrar object.LibraryRegistrar, allowedPaths []string)
RegisterOS registers the os and os.path libraries with a Scriptling instance. If allowedPaths is empty or nil, all paths are allowed (no restrictions). If allowedPaths contains paths, all file operations are restricted to those directories.
SECURITY: When running untrusted scripts, ALWAYS provide allowedPaths to restrict file system access. The security checks prevent: - Reading/writing files outside allowed directories - Path traversal attacks (../../../etc/passwd) - Symlink attacks (symlinks pointing outside allowed dirs)
Example:
No restrictions - full filesystem access (DANGEROUS for untrusted code)
filesystem.RegisterOS(s, nil)
Restricted to specific directories (SECURE)
filesystem.RegisterOS(s, []string{"/tmp/sandbox", "/home/user/data"})
func RegisterPathlib ¶
func RegisterPathlib(registrar object.LibraryRegistrar, allowedPaths []string)
RegisterPathlib registers the pathlib library with a Scriptling instance.
func RegisterSed ¶
func RegisterSed(registrar object.LibraryRegistrar, allowedPaths []string)
RegisterSed registers the scriptling.sed library with a Scriptling instance. If allowedPaths is nil, all paths are allowed. If non-nil, operations are restricted to those directories (same semantics as RegisterOS).
func RegisterShutil ¶
func RegisterShutil(registrar object.LibraryRegistrar, allowedPaths []string)
RegisterShutil registers the shutil library with a Scriptling instance.
func RegisterTarfile ¶
func RegisterTarfile(registrar object.LibraryRegistrar, allowedPaths []string)
func RegisterTempfile ¶
func RegisterTempfile(registrar object.LibraryRegistrar, allowedPaths []string)
RegisterTempfile registers the tempfile library with a Scriptling instance.
func RegisterZipfile ¶
func RegisterZipfile(registrar object.LibraryRegistrar, allowedPaths []string)
func SedReplace ¶
SedReplace replaces every occurrence of old with replacement in the file (or every matching file under the directory) at path. old is matched literally, not as a regular expression. Files are edited in place using an atomic temp-file + rename. The return value is the number of files modified.
func SedReplacePattern ¶
func SedReplacePattern(ctx context.Context, pattern, replacement, path string, opts SedOptions) (int64, error)
SedReplacePattern is SedReplace with old interpreted as a regular expression. Capture groups may be referenced in replacement as ${1}, ${2}, or ${name}.
Types ¶
type ExtractMatch ¶
ExtractMatch is a single regex match with its capture groups, returned by SedExtract.
func SedExtract ¶
func SedExtract(ctx context.Context, pattern, path string, opts SedOptions) ([]ExtractMatch, error)
SedExtract returns every match of pattern (a regular expression with capture groups) found in the file or directory at path. The result includes the captured groups for each match.
type FindEntry ¶
type FindEntry struct {
Path string
Size int64
Mtime time.Time
IsDir bool
Hash uint64 // crc64 of file content when FindOptions.IncludeHash is set; 0 otherwise
LinkTarget string // symlink target when the entry is a symlink; empty for regular files/dirs
FilePerm int // file permission bits; populated when FindOptions.IncludeMetadata is set
}
FindEntry is a single matching entry returned by FindEntries, carrying the metadata required to decide whether the entry has changed without re-reading it. Callers comparing two trees (e.g. a sync tool diffing local and remote) can rely on Size+Mtime alone for the common case.
func FindEntries ¶
FindEntries is like Find but returns FindEntry records with size, mtime, and type per match. Every matching entry is stat'd so the caller can compare trees without re-reading the bytes. Use Find instead when only the path strings are needed — Find skips the stat in the no-filter common case.
Like Find, the root itself is never included in the result, and paths are returned in arbitrary order.
type FindOptions ¶
type FindOptions struct {
Recursive *bool
Type string
Name string
MtimeMin *float64
MtimeMax *float64
SizeMin *int64
SizeMax *int64
IncludeHidden bool
FollowLinks bool
MaxDepth int
AllowedPaths []string
IncludeHash bool // when true, every entry's file content is crc64-hashed
IncludeSymlinks bool // when true, symlink entries are yielded with their target in LinkTarget
IncludeMetadata bool // when true, file_perm is populated
}
FindOptions controls a find search.
Recursive is a pointer so that the zero value (nil) preserves scriptling's default of descending into subdirectories. Pass a pointer to false to keep the search non-recursive.
Type selects "any" (the zero value), "file", or "dir".
MtimeMin/MtimeMax and SizeMin/SizeMax are pointers so that a zero value is not confused with the valid bound 0; nil means the filter is inactive.
MaxDepth of 0 means unlimited.
type GlobLibraryInstance ¶
type GlobLibraryInstance struct {
// contains filtered or unexported fields
}
GlobLibraryInstance holds the configured Glob library instance
type GrepMatch ¶
GrepMatch is a single matching line.
func Grep ¶
Grep searches path for needle. When path is a directory the search runs concurrently over its files using the same bounded worker pool as scriptling.grep, respecting opts.Recursive / opts.Glob / opts.MaxSize.
needle is interpreted as a regular expression unless opts.Literal is true. Matches are returned in arbitrary order.
type GrepOptions ¶
type GrepOptions struct {
Literal bool
Recursive bool
IgnoreCase bool
FollowLinks bool
Glob string
MaxSize int64
AllowedPaths []string
}
GrepOptions controls a Grep search.
Literal selects literal-string matching (scriptling.grep.string) when true, versus regular-expression matching (scriptling.grep.pattern) when false.
MaxSize skips files larger than this many bytes. The zero value applies the scriptling default of 1 MiB; a negative value disables the limit.
AllowedPaths, when non-nil, restricts every searched path to the listed absolute directories (nil = no restriction, matching the interpreter default).
type PathlibLibraryInstance ¶
type PathlibLibraryInstance struct {
PathClass *object.Class
// contains filtered or unexported fields
}
PathlibLibraryInstance holds the configured Pathlib library instance