diff --git a/files_darwin.go b/files_darwin.go index 9f14a43..919dcee 100644 --- a/files_darwin.go +++ b/files_darwin.go @@ -3,11 +3,81 @@ package staros import ( + "b612.me/stario" "os" "syscall" "time" ) +type FileLock struct { + fd int + filepath string +} + +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 + }) +} + func timespecToTime(ts syscall.Timespec) time.Time { return time.Unix(int64(ts.Sec), int64(ts.Nsec)) } diff --git a/go.mod b/go.mod index 11a6acc..819d836 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,10 @@ module b612.me/staros go 1.16 require ( - b612.me/stario v0.0.5 + b612.me/stario v0.0.7 b612.me/win32api v0.0.1 b612.me/wincmd v0.0.1 - golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 + golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd // indirect + golang.org/x/sys v0.0.0-20220318055525-2edf467146b5 + golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect ) diff --git a/go.sum b/go.sum index 7ab30c0..6aff4da 100644 --- a/go.sum +++ b/go.sum @@ -1,18 +1,26 @@ b612.me/stario v0.0.5 h1:Q1OGF+8eOoK49zMzkyh80GWaMuknhey6+PWJJL9ZuNo= b612.me/stario v0.0.5/go.mod h1:or4ssWcxQSjMeu+hRKEgtp0X517b3zdlEOAms8Qscvw= +b612.me/stario v0.0.7 h1:QbQcsHCVLE6vRgVrPN4+9DGiSaC6IWdtm4ClL2tpMUg= +b612.me/stario v0.0.7/go.mod h1:or4ssWcxQSjMeu+hRKEgtp0X517b3zdlEOAms8Qscvw= b612.me/win32api v0.0.1 h1:vLFB1xhO6pd9+zB2EyaapKB459Urv3v+C1YwgwOFEWo= b612.me/win32api v0.0.1/go.mod h1:MHu0JBQjzxQ2yxpZPUBbn5un45o67eF5iWKa4Q9e0yE= b612.me/wincmd v0.0.1 h1:4+RCFKHuD/JqAYsdtO6sTNKJs1nQVMQo87h6KhTJjkM= b612.me/wincmd v0.0.1/go.mod h1:32xTM7qWAI7jx6qwTrig05rxejSYbSp7CX5WD7qsMxY= golang.org/x/crypto v0.0.0-20220313003712-b769efc7c000 h1:SL+8VVnkqyshUSz5iNnXtrBQzvFF2SkROm6t5RczFAE= golang.org/x/crypto v0.0.0-20220313003712-b769efc7c000/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38= +golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40WUDnek3fPOyD08H5Vng= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220318055525-2edf467146b5 h1:saXMvIOKvRFwbOMicHXr0B1uwoxq9dGmLe5ExMES6c4= +golang.org/x/sys v0.0.0-20220318055525-2edf467146b5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=