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

69 lines
1.3 KiB
Go

//go:build windows
package appdata
import (
"errors"
"os"
"golang.org/x/sys/windows"
)
type bootstrapFileLock struct {
file *os.File
overlapped windows.Overlapped
}
func acquireBootstrapFileLock(path string) (*bootstrapFileLock, error) {
file, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR, 0o600)
if err != nil {
return nil, err
}
lock := &bootstrapFileLock{file: file}
if err := windows.LockFileEx(
windows.Handle(file.Fd()),
windows.LOCKFILE_EXCLUSIVE_LOCK,
0,
1,
0,
&lock.overlapped,
); err != nil {
_ = file.Close()
return nil, err
}
_ = file.Chmod(0o600)
return lock, nil
}
func (lock *bootstrapFileLock) Close() error {
if lock == nil || lock.file == nil {
return nil
}
unlockErr := windows.UnlockFileEx(
windows.Handle(lock.file.Fd()),
0,
1,
0,
&lock.overlapped,
)
closeErr := lock.file.Close()
lock.file = nil
return errors.Join(unlockErr, closeErr)
}
func atomicReplaceBootstrapFile(source string, target string) error {
sourcePath, err := windows.UTF16PtrFromString(source)
if err != nil {
return err
}
targetPath, err := windows.UTF16PtrFromString(target)
if err != nil {
return err
}
return windows.MoveFileEx(
sourcePath,
targetPath,
windows.MOVEFILE_REPLACE_EXISTING|windows.MOVEFILE_WRITE_THROUGH,
)
}