Documentation
¶
Overview ¶
Package dsstore writes the .DS_Store file the Finder keeps in a directory, in pure Go with CGO_ENABLED=0 and no shelling out.
It exists for one job the rest of this fleet could not finish: a disk image that opens showing a background picture with its icons arranged on it. The picture is not a property of the volume, the image, or the filesystem — it is a record inside .DS_Store, and nothing in Go could write one.
The format ¶
A .DS_Store is a "buddy allocator" image (magic "Bud1") holding one B-tree named DSDB, whose records are (filename, four-character structure id, typed value) triples sorted by case-insensitive filename. EVERYTHING is big-endian, and every stored offset is relative to byte 4 of the file.
It is an allocator IMAGE, not a container with blocks placed in it, and the Finder reads it as one: a file whose blocks are laid out by hand parses perfectly and is silently ignored.
The layout here was read off files the Finder itself wrote on macOS 26, for exactly this case — a volume with a background picture and positioned icons. Where the published descriptions disagree with what the Finder does, the comments say so at the point it matters.
What it deliberately does not do ¶
The B-tree is written as a SINGLE leaf node. A window with a background has a handful of entries, which fits a 4 KiB page many times over; a store that needs more returns ErrTooLarge rather than emitting a file with a half-implemented split in it. Growing to a real B-tree is a change to this package, not to its callers.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrTooLarge = errors.New("dsstore: records exceed one 4 KiB node")
ErrTooLarge is returned when the records do not fit the single leaf node this package writes. See the package comment: a partial B-tree is worse than a refusal.
Functions ¶
func BuildAlias ¶
BuildAlias encodes an alias v2 pointing at relPath on the named volume.
relPath is the path INSIDE the volume, leading slash and all, because that is what tag 18 carries and what lets the reference survive being mounted somewhere else.
Types ¶
type Blob ¶
type Blob []byte
Blob is the "blob" type: a length-prefixed byte string. Both the window settings (a binary plist) and an icon position are blobs.
type IconView ¶
type IconView struct {
// Background names the picture inside the volume, leading slash and all
// (".background/bg.png" is conventional and hidden). Empty means no
// picture, and backgroundType drops to 1 — a plain colour.
Background string
// VolumeName is the volume the picture lives on. The alias records it,
// which is how the reference survives a different mount point.
VolumeName string
IconSize float64 // 96 is what a disk-image window usually wants
TextSize float64 // 12 in the Finder's own file
GridSpacing float64 // 100
LabelBottom bool
ShowPreview bool
ShowInfo bool
}
IconView is the window's icon-view settings — the "icvp" record, which is what carries the background picture.
The keys and their types were read off the Finder's own record: the numbers are REALS, not integers, and backgroundType is 2 for "a picture". The older BKGD and pict records are dead on modern macOS: a file carrying a valid BKGD/pict pair and no icvp made the Finder write a fresh icvp with backgroundType 0, ignoring them.
type Record ¶
type Record struct {
Name string
ID string // four characters: "Iloc", "icvp", "bwsp", "vSrn", …
Val Value
}
A Record is one (name, structure id, value) triple. Name is the entry the record is about; "." means the directory itself, which is where the window's own settings live.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store is a set of records destined for one directory's .DS_Store.
func Parse ¶
Parse reads a .DS_Store.
It exists as much for the tests as for callers: the only way to know this package writes what the Finder writes is to read the Finder's own file and compare. A writer checked against nothing but itself is checked against nothing.
func (*Store) Add ¶
Add appends a record, replacing any earlier one with the same name and id so that a builder layering defaults over a caller's wishes works.
func (*Store) SetIconPosition ¶
SetIconPosition places one entry's icon. x and y are the icon's CENTRE, in the window's coordinates.
func (*Store) SetIconView ¶
SetIconView records the window's icon-view settings.
type Value ¶
type Value interface {
// contains filtered or unexported methods
}
A Value is one of the typed payloads the format defines. Only the four this package needs are implemented; the rest are rejected rather than guessed at.
type Window ¶
type Window struct {
// X and Y are the window's BOTTOM-left corner, y measured up from the
// bottom of the screen -- a Cocoa rect, not the top-left corner it looks
// like. Asking for {{100, 100}, {600, 400}} on a screen whose desktop
// ends at 1117 put the window's bottom edge at 1017, which is where the
// Finder reported it. Width and Height are the content area, which is
// the area the background covers.
X, Y, Width, Height int
}
A Window is where the window opens and how large it is — the "bwsp" record.
It is separate from IconView because it is a different record and answers a different question: icvp says what the window shows behind its icons, bwsp says how big the window is. A background picture with no bwsp is a picture cropped to whatever size the Finder last used.
