From f0836851087785a15da22927846da1d7171f3157 Mon Sep 17 00:00:00 2001 From: sneak Date: Fri, 16 Oct 2026 01:20:27 +0000 Subject: [PATCH] Keep the empty host for a state_dir starting with // With OmitHost set, a state_dir starting with // gave a db_url starting file://, and SQLite read the first directory name as a host, so pixa failed to start. OmitHost is now left off for such a directory: the URL starts file://// and SQLite reads an empty host followed by the path. Every other state_dir gives the same URL as before. Model: opus-5-5 --- README.md | 13 +++++++------ TODO.md | 4 +++- internal/config/config.go | 6 ++++-- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index c8f7cac..1a66907 100644 --- a/README.md +++ b/README.md @@ -694,12 +694,13 @@ Key settings in more detail: - `db_url` — the SQLite database to open; omitted, it is `file:/state.sqlite3?_pragma=journal_mode(WAL)`, which keeps the database in WAL mode. `state_dir` is percent-encoded in it, so a `%`, `?` or - `#` in the name is written as `%25`, `%3F` or `%23`. pixa opens one connection - to it, so its own reads and writes run one at a time. pixa adds - `_pragma=busy_timeout(5000)` to any `db_url`, so a write that finds another - program writing to the file waits up to five seconds for it instead of - failing. WAL mode comes only from the URL: keep `_pragma=journal_mode(WAL)` in - one you set + `#` in the name is written as `%25`, `%3F` or `%23`. For a `state_dir` + starting with `//` it starts `file:////`, so SQLite does not read the first + directory name as a host. pixa opens one connection to it, so its own reads + and writes run one at a time. pixa adds `_pragma=busy_timeout(5000)` to any + `db_url`, so a write that finds another program writing to the file waits up + to five seconds for it instead of failing. WAL mode comes only from the URL: + keep `_pragma=journal_mode(WAL)` in one you set - `cache_max_bytes` — disk cache size limit in bytes; `0` disables the disk cache entirely; omitted defaults to 75% of the sum of the free space on the filesystem containing `/cache/` and the bytes of source and diff --git a/TODO.md b/TODO.md index 89f3ed1..fefc8d1 100644 --- a/TODO.md +++ b/TODO.md @@ -35,7 +35,9 @@ P2: security: per-origin rate limiting it put the name into a `file:` URL as it was, so SQLite read `%41` as `A`, a `?` or `#` ended the path early, and the journal mode parameter was lost. The derived `db_url` is now built with Go's `net/url`, which writes those - characters as `%25`, `%3F` and `%23`. + characters as `%25`, `%3F` and `%23`. For a `state_dir` starting with `//` it + starts `file:////`, so SQLite no longer reads the first directory name as a + host. - 2026-10-15 a thin source requested with `fit=cover` no longer makes libvips build a huge image (closes #282): libvips' thumbnail scaled the whole source to cover the requested size and copied that into memory before it cut out the diff --git a/internal/config/config.go b/internal/config/config.go index d94fb74..bc657ff 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -359,11 +359,13 @@ func newFromSmartConfig(sc *smartconfig.Config) (*Config, error) { // the directory name, which SQLite decodes back, so the URL names exactly // this file. OmitHost writes file:/var/lib/pixa/... instead of // file:///var/lib/pixa/..., and keeps a relative stateDir from being read -// as a host name. +// as a host name. A stateDir starting with // keeps the empty host, so the +// URL starts file://// and SQLite does not read the first directory name +// as a host. func defaultDBURL(stateDir string) string { dbURL := url.URL{ Scheme: "file", - OmitHost: true, + OmitHost: !strings.HasPrefix(stateDir, "//"), Path: stateDir + "/state.sqlite3", RawQuery: "_pragma=journal_mode(WAL)", }