Initial commit
Test / test (push) Successful in 7m5s
Release / gates (push) Successful in 7m28s
Release / build (amd64, freebsd) (push) Successful in 2m52s
Release / build (amd64, linux) (push) Successful in 2m46s
Release / build (arm64, freebsd) (push) Successful in 2m22s
Release / build (arm64, linux) (push) Successful in 2m38s
Release / build (loong64, linux) (push) Successful in 2m7s
Release / build (riscv64, linux) (push) Successful in 2m17s
Release / release (push) Successful in 1m0s
Test / test (push) Successful in 7m5s
Release / gates (push) Successful in 7m28s
Release / build (amd64, freebsd) (push) Successful in 2m52s
Release / build (amd64, linux) (push) Successful in 2m46s
Release / build (arm64, freebsd) (push) Successful in 2m22s
Release / build (arm64, linux) (push) Successful in 2m38s
Release / build (loong64, linux) (push) Successful in 2m7s
Release / build (riscv64, linux) (push) Successful in 2m17s
Release / release (push) Successful in 1m0s
Assisted-by: GLM 5.3
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
|
||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||
|
||||
package store
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// atomicWriteIn replaces name inside the root: a temporary file in the
|
||||
// same directory, fsync, rename, and a directory fsync.
|
||||
func atomicWriteIn(root *os.Root, name string, data []byte) error {
|
||||
dir := path.Dir(name)
|
||||
base := path.Base(name)
|
||||
handle, err := root.OpenFile(path.Join(dir, "."+base+".tmp"), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("create temp file: %w", err)
|
||||
}
|
||||
if _, err := handle.Write(data); err != nil {
|
||||
handle.Close()
|
||||
root.Remove(path.Join(dir, "."+base+".tmp"))
|
||||
return fmt.Errorf("write: %w", err)
|
||||
}
|
||||
if err := handle.Sync(); err != nil {
|
||||
handle.Close()
|
||||
root.Remove(path.Join(dir, "."+base+".tmp"))
|
||||
return fmt.Errorf("sync: %w", err)
|
||||
}
|
||||
if err := handle.Close(); err != nil {
|
||||
root.Remove(path.Join(dir, "."+base+".tmp"))
|
||||
return fmt.Errorf("close: %w", err)
|
||||
}
|
||||
if err := root.Rename(path.Join(dir, "."+base+".tmp"), name); err != nil {
|
||||
root.Remove(path.Join(dir, "."+base+".tmp"))
|
||||
return fmt.Errorf("replace: %w", err)
|
||||
}
|
||||
syncDirIn(root, dir)
|
||||
return nil
|
||||
}
|
||||
|
||||
// syncDirIn flushes a directory entry inside the root, so the rename is
|
||||
// durable.
|
||||
func syncDirIn(root *os.Root, dir string) {
|
||||
handle, err := root.Open(dir)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer handle.Close()
|
||||
_ = handle.Sync()
|
||||
}
|
||||
|
||||
func absPath(path string) string {
|
||||
abs, err := filepath.Abs(path)
|
||||
if err != nil {
|
||||
return path
|
||||
}
|
||||
return abs
|
||||
}
|
||||
|
||||
// within reports whether path is inside directory, comparing resolved
|
||||
// paths so that a symlinked content directory is not mistaken for an
|
||||
// escape. A path that does not exist yet is resolved through its
|
||||
// longest existing ancestor, which is what a new post file is.
|
||||
func within(directory, path string) bool {
|
||||
dirResolved := resolveExisting(directory)
|
||||
pathResolved := resolveExisting(path)
|
||||
if pathResolved == dirResolved {
|
||||
return true
|
||||
}
|
||||
rel, err := filepath.Rel(dirResolved, pathResolved)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return rel != ".." && !strings.HasPrefix(rel, ".."+string(filepath.Separator))
|
||||
}
|
||||
|
||||
// resolveExisting resolves symlinks in the longest existing prefix of
|
||||
// path and appends the remainder unchanged.
|
||||
func resolveExisting(path string) string {
|
||||
if resolved, err := filepath.EvalSymlinks(path); err == nil {
|
||||
return resolved
|
||||
}
|
||||
parent := filepath.Dir(path)
|
||||
if parent == path || parent == "." {
|
||||
return path
|
||||
}
|
||||
return filepath.Join(resolveExisting(parent), filepath.Base(path))
|
||||
}
|
||||
Reference in New Issue
Block a user