You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
92 lines
1.7 KiB
Go
92 lines
1.7 KiB
Go
2 years ago
|
//+build linux
|
||
|
|
||
|
package staros
|
||
|
|
||
|
import (
|
||
|
"b612.me/stario"
|
||
|
"os"
|
||
|
"syscall"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
type FileLock struct {
|
||
|
fd int
|
||
|
filepath string
|
||
|
}
|
||
|
|
||
|
func timespecToTime(ts syscall.Timespec) time.Time {
|
||
|
return time.Unix(int64(ts.Sec), int64(ts.Nsec))
|
||
|
}
|
||
|
|
||
|
func GetFileCreationTime(fileinfo os.FileInfo) time.Time {
|
||
|
return timespecToTime(fileinfo.Sys().(*syscall.Stat_t).Ctim)
|
||
|
}
|
||
|
|
||
|
func GetFileAccessTime(fileinfo os.FileInfo) time.Time {
|
||
|
return timespecToTime(fileinfo.Sys().(*syscall.Stat_t).Atim)
|
||
|
}
|
||
|
|
||
|
func (f *FileLock) openFileForLock() error {
|
||
|
fd, err := syscall.Open(f.filepath, syscall.O_CREAT|syscall.O_RDONLY, 0600)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
f.filepath = f.filepath
|
||
|
f.fd = fd
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (f *FileLock) Lock(Exclusive bool) error {
|
||
|
var lockType int
|
||
|
if Exclusive {
|
||
|
lockType = syscall.LOCK_EX
|
||
|
} else {
|
||
|
lockType = syscall.LOCK_SH
|
||
|
}
|
||
|
if err := f.openFileForLock(); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
return syscall.Flock(f.fd, lockType)
|
||
|
}
|
||
|
|
||
|
func (f *FileLock) LockNoBlocking(Exclusive bool) error {
|
||
|
var lockType int
|
||
|
if Exclusive {
|
||
|
lockType = syscall.LOCK_EX
|
||
|
} else {
|
||
|
lockType = syscall.LOCK_SH
|
||
|
}
|
||
|
if err := f.openFileForLock(); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
err := syscall.Flock(f.fd, lockType|syscall.LOCK_NB)
|
||
|
if err != nil {
|
||
|
syscall.Close(f.fd)
|
||
|
if err == syscall.EWOULDBLOCK {
|
||
|
return ERR_ALREADY_LOCKED
|
||
|
}
|
||
|
}
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
func (f *FileLock) Unlock() error {
|
||
|
err := syscall.Flock(f.fd, syscall.LOCK_UN)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
return syscall.Close(f.fd)
|
||
|
}
|
||
|
|
||
|
func (f *FileLock) LockWithTimeout(tm time.Duration, Exclusive bool) error {
|
||
|
return stario.WaitUntilTimeout(tm, func(tmout chan struct{}) error {
|
||
|
err := f.Lock(Exclusive)
|
||
|
select {
|
||
|
case <-tmout:
|
||
|
f.Unlock()
|
||
|
return nil
|
||
|
default:
|
||
|
}
|
||
|
return err
|
||
|
})
|
||
|
}
|