saferio is a small Go library for safely handling temporary files and logs in monitoring-forge Mackerel plugins.
It provides helpers to read and write JSON files while reducing the risk of symlink-based attacks and partial writes.
- Atomic JSON writes:
WriteJSONwrites to a temporary file and renames it into place, minimizing the chance of leaving a partially written file. - Safe file opening:
OpenRD/OpenADopen files withO_NOFOLLOWon Unix-like systems to help prevent symlink attacks. - Cross-platform: Separate implementations for Unix and Windows.
- Small surface: Only three public functions plus platform-specific open helpers.
package main
import (
"log"
"github.com/monitoring-forge/saferio"
)
func main() {
dir := "/var/lib/mackerel-plugin"
// Write metrics state atomically.
state := map[string]any{"counter": 42}
if err := saferio.WriteJSON(dir, "mackerel-plugin-foo.json", state); err != nil {
log.Fatal(err)
}
// Read it back safely.
var loaded map[string]any
if err := saferio.ReadJSON(dir, "mackerel-plugin-foo.json", &loaded); err != nil {
log.Fatal(err)
}
// Check for a file presence.
if saferio.FileExists(dir, "mackerel-plugin-foo.json") {
log.Println("state file exists")
}
}Returns true if the file exists in dir.
Encodes v as JSON to a temporary file in dir and renames it to filename.
If filename already exists, it attempts to replace it atomically.
Opens filename safely (with O_NOFOLLOW on Unix) and decodes its JSON content into v.
If the file is empty, ReadJSON returns io.EOF. Callers that want to treat an empty file as "no state" can check for this error explicitly.
Opens a file for reading with O_RDONLY. On Unix-like systems, O_NOFOLLOW is added.
Opens a file for appending with O_WRONLY | O_CREATE | O_APPEND. On Unix-like systems, O_NOFOLLOW is added.
| Function | Unix-like | Windows |
|---|---|---|
OpenRD |
O_RDONLY | O_NOFOLLOW |
O_RDONLY |
OpenAD |
O_WRONLY | O_CREATE | O_APPEND | O_NOFOLLOW |
O_WRONLY | O_CREATE | O_APPEND |
Windows does not support O_NOFOLLOW, so the flag is omitted on that platform.
MIT License - see LICENSE for details.