platform

package
v1.3.0 Latest Latest
Warning

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

Go to latest
Published: Aug 15, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ConfirmWithButtons added in v1.3.0

func ConfirmWithButtons(title, message, allowLabel string) (bool, error)

ConfirmWithButtons shows a modal, foreground native dialog with exactly two buttons — allowLabel and "Deny", Deny the default — and reports whether the user chose allowLabel. Same contract as Confirm: always a real OS dialog a page cannot spoof or auto-confirm, failing closed to false on any error, timeout, or unsupported platform. Platforms whose dialog cannot relabel its buttons (Windows) fold the label into the message and map their affirmative button to it, which degrades wording, never safety.

func DirIdentity added in v1.3.0

func DirIdentity(path string) string

DirIdentity returns a device+inode fingerprint for the directory at path, or "" when one cannot be derived. Stat follows symlinks deliberately: a stored trusted-folder path whose directory was later swapped for a symlink stats through to the link's target, whose fingerprint differs from the recorded one, which is exactly the swap the comparison exists to catch.

func IsLoginItem

func IsLoginItem() bool

func Notify

func Notify(title, message string) error

Notify shows a best-effort native error message to the user. It exists for failures the user must see even though no window opened, such as opening a file outside the home directory. The error is returned so callers can fall back to logging when no native mechanism is available.

func OnOpenFile

func OnOpenFile(cb func(string))

OnOpenFile is a no-op on platforms where the OS delivers opened file paths via argv (Linux, Windows); those are handled through the normal argv + single- instance forwarding path.

func OpenShared added in v1.3.0

func OpenShared(path string) (*os.File, error)

OpenShared opens path read-only for a handle the caller intends to HOLD, without preventing anyone else from DELETING the file underneath it.

This exists because os.Open is the wrong tool for a long-lived handle on Windows. Windows only permits a delete if every open handle to the file allowed it up front via FILE_SHARE_DELETE, and Go's os.Open asks for read and write sharing but not delete. So a handle kept open for bookkeeping silently becomes a lock on removing the file. Unix has no such rule, so there this is plain os.Open.

KNOWN LIMIT, measured on the Windows CI runner rather than assumed: this buys delete, NOT rename-over. MoveFileEx with MOVEFILE_REPLACE_EXISTING is still refused while any handle is open, whatever sharing mode it asked for, so a held handle still breaks htmlclay's atomic save. openshared_windows_test.go pins both halves of that. The only fix for the save path is to stop holding a handle on a file we intend to replace; sharing mode cannot rescue it.

Because of that limit nothing calls this any more: live-sync's identity anchor was the one caller and now goes through platform.Anchor, which holds no handle on Windows at all. It stays because its tests are the measurement the Anchor comments cite, and because the warning above is worth having written down somewhere before the next person reaches for a long-lived handle.

func RealPath added in v1.2.0

func RealPath(f *os.File) (string, error)

RealPath returns the canonical filesystem path of the file the descriptor f actually points at, asked of the OS by handle rather than derived from the pathname used to open it. Because it reads through the open descriptor, a concurrent rename or symlink swap of the pathname cannot change the answer: it always names where the held inode really lives. Callers use it to enforce "never serve internal state" against the descriptor they hold, which closes the check-vs-open TOCTOU that any later pathname re-resolution leaves open. It fails closed (returns an error) on platforms without a native handle-to-path call.

func SelectFolder added in v1.2.0

func SelectFolder(prompt string) (path string, ok bool, err error)

SelectFolder shows a native folder-picker dialog and returns the chosen path. ok is false when the user cancels, which is a normal outcome rather than an error. On an unsupported platform it returns an error. The returned path is whatever the OS picker yields; the caller canonicalizes and validates it before trusting it.

func SetLoginItem

func SetLoginItem(enabled bool, executablePath string) error

Types

type Anchor added in v1.3.0

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

Anchor identifies one file across time, so a caller can tell whether the file sitting at a path is still the file it saw before or a different one that took the name. Live-sync needs this: retained frames and resume cursors belong to a document, not to a pathname, and serving one document's bytes into a page showing another is the failure worth spending code to avoid.

The two operating-system halves are opposites, by necessity rather than taste.

On Unix the anchor HOLDS an open descriptor. Comparing (device, inode) is only meaningful while something keeps the inode alive: once the last reference goes, the number is free for the next file created, and a recycled inode makes a stranger look like the file we anchored. Holding the descriptor costs nothing there, because a Unix handle never blocks a rename or an unlink.

On Windows the anchor holds NO descriptor, and must not. Windows refuses to rename over a file while any handle to it is open, whatever sharing mode that handle asked for (openshared_windows_test.go pins that), so a handle parked for bookkeeping makes the file unsaveable by htmlclay and by every other program for as long as it is held. Nothing is lost: NTFS answers with a 128-bit file id whose low half carries an MFT sequence number that increments when a record is reused, so a recycled record produces a different id without anyone holding anything.

Deliberately NOT used as identity, and worth recording so it is not retried: content hashes (cannot tell "same file, edited" from "different file"), the htmlclay id attribute (never written to disk, absent from plain .html, and copyable, so cp would alias two documents), and Windows creation time (NTFS file system tunnelling caches a deleted file's creation time for 15 seconds and reapplies it to a new file of the same name in the same directory, which is precisely the atomic-replace window we care about).

func NewAnchor added in v1.3.0

func NewAnchor(path string) (*Anchor, error)

NewAnchor reads the identity of the regular file at path. It touches the disk, so build it outside any lock you hold and install it under one. A directory or any other non-regular file is an error, not an anchor.

func (*Anchor) Close added in v1.3.0

func (a *Anchor) Close()

Close releases whatever the anchor holds, which on Windows is nothing. Safe on a nil anchor and safe to call more than once, so callers can drop one without first working out whether they have one.

func (*Anchor) Same added in v1.3.0

func (a *Anchor) Same(b *Anchor) bool

Same reports whether both anchors name the same file. A nil anchor is never the same as anything, including another nil: an identity nobody established is not evidence that nothing changed.

type ConfirmChoice added in v1.2.0

type ConfirmChoice int

ConfirmChoice is the outcome of a native permission dialog.

const (
	// ConfirmDeny is also the fail-closed default: any error, timeout, or
	// unsupported platform resolves to Deny so access is never granted by accident.
	ConfirmDeny ConfirmChoice = iota
	ConfirmAllowOnce
	// ConfirmTrustFolder is the durable choice: allow this read AND remember the
	// folder as trusted, so files opened from inside it stop asking. Platforms with
	// no clean third button degrade it to ConfirmAllowOnce, which errs toward less
	// permission rather than more.
	ConfirmTrustFolder
)

func Confirm added in v1.2.0

func Confirm(title, message string) (ConfirmChoice, error)

Confirm shows a modal, foreground native dialog for a permission grant and returns the user's choice. It is always a real OS dialog, never page content, so a served page cannot spoof, style, obscure, or auto-confirm it. On any error or unsupported platform it fails closed to ConfirmDeny.

func (ConfirmChoice) String added in v1.2.0

func (c ConfirmChoice) String() string

type SingleInstance

type SingleInstance interface {
	TryLock() (bool, error)
	SendFilePath(path string) error
	OnFileReceived(callback func(path string))
	Unlock() error
}

func NewSingleInstance

func NewSingleInstance(configDir string) SingleInstance

Jump to

Keyboard shortcuts

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