Files
MyGoNavi/internal/appdata/bootstrap_file_lock_unix.go
Syngnat 97cffa7809 feat(settings): 支持自定义并持久化日志目录
- 将日志目录配置整合到数据目录设置,支持选择、打开、恢复默认与保存
- 持久化日志目录并保留环境变量优先级,目录调整后重启生效
- 通过跨进程锁和原子写入保护数据目录与日志目录配置
- 移除重复标题并互斥目录修改操作,补齐六语言文案
- 补充桌面接口、浏览器模拟及并发回归测试
2026-07-23 11:40:17 +08:00

50 lines
1.1 KiB
Go

//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd
package appdata
import (
"errors"
"os"
"path/filepath"
"golang.org/x/sys/unix"
)
type bootstrapFileLock struct {
file *os.File
}
func acquireBootstrapFileLock(path string) (*bootstrapFileLock, error) {
file, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR, 0o600)
if err != nil {
return nil, err
}
if err := unix.Flock(int(file.Fd()), unix.LOCK_EX); err != nil {
_ = file.Close()
return nil, err
}
_ = file.Chmod(0o600)
return &bootstrapFileLock{file: file}, nil
}
func (lock *bootstrapFileLock) Close() error {
if lock == nil || lock.file == nil {
return nil
}
unlockErr := unix.Flock(int(lock.file.Fd()), unix.LOCK_UN)
closeErr := lock.file.Close()
lock.file = nil
return errors.Join(unlockErr, closeErr)
}
func atomicReplaceBootstrapFile(source string, target string) error {
if err := os.Rename(source, target); err != nil {
return err
}
directory, err := os.Open(filepath.Dir(target))
if err != nil {
return err
}
return errors.Join(directory.Sync(), directory.Close())
}