Help us shape the future of Go! Take the 2026 Go Developer Survey

workspacemedia

package
v1.151.0 Latest Latest
Warning

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

Go to latest
Published: Oct 19, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

Documentation

Overview

Package workspacemedia writes model-generated media into the user's workspace as ordinary, visible files — the same way generated code or text lands there. It is a pure naming/collision layer: the caller hands it a workspace root, a requested relative path (or a generic fallback name such as "generated"), the bytes, and the MIME type; it returns the exact workspace-relative path it wrote.

Guarantees:

  • Never overwrites. A completed sibling temp file is hard-linked to the final name, making name selection and publication one atomic no-replace operation. An existing entry of any kind (including a symlink) means "taken", so the writer retries with a dash suffix (name-1.ext, name-2.ext, ...), which also makes concurrent same-name writers safe.
  • Atomic publish. A reader observes either no final entry or the full content, never a placeholder or partial write. Filesystems without hard-link support return an explicit error rather than falling back to a replace-capable rename.
  • Workspace containment. Every directory and file operation goes through os.Root, so absolute paths, ".." traversal, invalid or Windows-reserved segments, and symlink escapes are rejected with ErrPathEscape rather than followed.
  • The final filename's extension always agrees with the MIME type when the type is known; a conflicting requested extension is corrected and reported via Result so the caller can show a notice.

Files use ordinary user-file modes (0o755 directories, 0o644 files, both umask-masked). On Windows modes are ignored and entries inherit the parent directory's ACLs — same convention as pkg/atomicfile.

Index

Constants

This section is empty.

Variables

View Source
var ErrNameExhausted = errors.New("no free filename after exhausting collision suffixes")

ErrNameExhausted classifies collision-suffix exhaustion: every candidate name up to maxNameAttempts already exists. Match with errors.Is when the failure must be explained without echoing the requested path.

View Source
var ErrPathEscape = errors.New("path escapes the workspace or has invalid segments")

ErrPathEscape classifies a requested path the writer refuses to touch: absolute, containing "..", an empty/invalid/Windows-reserved segment, or resolving outside the workspace root through a symlinked parent. Callers can redirect refused targets to a safe workspace basename.

Functions

func RequestedBasename

func RequestedBasename(requested string) string

RequestedBasename returns the final meaningful segment of a requested path — the name to redirect to when the full path is refused — or "" when none exists (empty, separators only, or only "."/".." segments).

Types

type PathClass

type PathClass int

PathClass is the outcome of classifying a model-requested target path before any I/O. Classification is purely lexical: a PathWorkspaceRelative path can still be refused at write time when a symlinked parent resolves outside the root (surfaced as ErrPathEscape by Write).

const (
	// PathInvalid marks a path that names nothing usable: empty, only
	// separators/dots, an invalid or Windows-reserved final segment. It is
	// unusable — callers should fall back to a safe generated name.
	PathInvalid PathClass = iota

	// PathWorkspaceRelative marks a path contained under the workspace
	// root, directly writable via [Write].
	PathWorkspaceRelative

	// PathEscaping marks a path that targets a location outside the
	// workspace: absolute, traversing above the root via "..", or rooted at
	// a home directory via a leading "~" segment.
	PathEscaping
)

func ClassifyRequestedPath

func ClassifyRequestedPath(requested string) (PathClass, string)

ClassifyRequestedPath classifies requested and, for PathWorkspaceRelative, returns the normalized slash-separated relative path to hand to Write (both separator styles accepted; interior "." and ".." segments resolved lexically, so "a/../b.png" is contained rather than escaping). For every other class the second return is "".

type Result

type Result struct {
	// RelPath is the exact final path written, relative to the workspace root
	// and slash-separated. Persist this verbatim.
	RelPath string

	// ExtensionCorrected reports that the requested filename's extension
	// conflicted with the MIME-derived one and was replaced. Callers should
	// surface a notice (e.g. "saved as sunshine.png — the provider returned
	// PNG data"). RequestedExtension holds the original, with leading dot.
	ExtensionCorrected bool
	RequestedExtension string
}

Result describes a completed write.

func Write

func Write(workspaceRoot, requestedPath string, data []byte, mimeType string) (Result, error)

Write stores data under workspaceRoot at requestedPath, sanitized and collision-avoided per the package contract, and returns the exact workspace-relative path written. Prompt-directed subdirectories in requestedPath are created as needed. A rejected path returns an error matching ErrPathEscape, collision-suffix exhaustion one matching ErrNameExhausted; any other failure (unwritable directory, full disk, ...) is returned as-is for the caller to surface.

Jump to

Keyboard shortcuts

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