Files
2026-07-20 04:43:28 +00:00

77 lines
2.2 KiB
Go

//go:build linux
package process
import (
"errors"
"sync"
"golang.org/x/sys/unix"
)
var (
ErrSQLiteJournalUnsupported = errors.New("sqlite journal identity unsupported")
ErrSQLiteJournalIdentityMismatch = errors.New("sqlite journal identity mismatch")
)
type SQLiteJournalUnsupportedError struct{ Missing uint32 }
func (err *SQLiteJournalUnsupportedError) Error() string { return ErrSQLiteJournalUnsupported.Error() }
func (err *SQLiteJournalUnsupportedError) Unwrap() error { return ErrSQLiteJournalUnsupported }
type SQLiteJournalIdentity struct {
MountID uint64
DeviceMajor uint32
DeviceMinor uint32
Inode uint64
BirthTime unix.StatxTimestamp
}
func (identity SQLiteJournalIdentity) equal(other SQLiteJournalIdentity) bool {
return identity == other
}
func sqliteJournalIdentity(stat unix.Statx_t) (SQLiteJournalIdentity, error) {
required := uint32(unix.STATX_MNT_ID | unix.STATX_BTIME)
if stat.Mask&required != required {
return SQLiteJournalIdentity{}, &SQLiteJournalUnsupportedError{Missing: required &^ stat.Mask}
}
return SQLiteJournalIdentity{
MountID: stat.Mnt_id,
DeviceMajor: stat.Dev_major,
DeviceMinor: stat.Dev_minor,
Inode: stat.Ino,
BirthTime: stat.Btime,
}, nil
}
func readSQLiteJournalIdentity(fd int) (SQLiteJournalIdentity, error) {
var stat unix.Statx_t
err := unix.Statx(fd, "", unix.AT_EMPTY_PATH, unix.STATX_BASIC_STATS|unix.STATX_MNT_ID|unix.STATX_BTIME, &stat)
if err != nil {
if errors.Is(err, unix.ENOSYS) || errors.Is(err, unix.EINVAL) || errors.Is(err, unix.EPERM) {
return SQLiteJournalIdentity{}, &SQLiteJournalUnsupportedError{Missing: unix.STATX_MNT_ID | unix.STATX_BTIME}
}
return SQLiteJournalIdentity{}, err
}
if stat.Mode&unix.S_IFMT != unix.S_IFREG {
return SQLiteJournalIdentity{}, &SQLiteJournalUnsupportedError{}
}
return sqliteJournalIdentity(stat)
}
type SQLiteJournalIdentityError struct {
Expected SQLiteJournalIdentity
Actual SQLiteJournalIdentity
}
func (err *SQLiteJournalIdentityError) Error() string {
return ErrSQLiteJournalIdentityMismatch.Error()
}
func (err *SQLiteJournalIdentityError) Unwrap() error { return ErrSQLiteJournalIdentityMismatch }
type sqliteJournalCloser struct {
once sync.Once
err error
}