github.com/ncruces/go-sqlite3@v0.15.1-0.20240520133447-53eef1510ff0/vfs/os_darwin.go (about) 1 //go:build !(sqlite3_flock || sqlite3_nosys) 2 3 package vfs 4 5 import ( 6 "io" 7 "os" 8 "time" 9 10 "golang.org/x/sys/unix" 11 ) 12 13 const ( 14 // https://github.com/apple/darwin-xnu/blob/main/bsd/sys/fcntl.h 15 _F_OFD_SETLK = 90 16 _F_OFD_SETLKW = 91 17 _F_OFD_SETLKWTIMEOUT = 93 18 ) 19 20 type flocktimeout_t struct { 21 fl unix.Flock_t 22 timeout unix.Timespec 23 } 24 25 func osSync(file *os.File, fullsync, _ /*dataonly*/ bool) error { 26 if fullsync { 27 return file.Sync() 28 } 29 return unix.Fsync(int(file.Fd())) 30 } 31 32 func osAllocate(file *os.File, size int64) error { 33 off, err := file.Seek(0, io.SeekEnd) 34 if err != nil { 35 return err 36 } 37 if size <= off { 38 return nil 39 } 40 41 store := unix.Fstore_t{ 42 Flags: unix.F_ALLOCATEALL | unix.F_ALLOCATECONTIG, 43 Posmode: unix.F_PEOFPOSMODE, 44 Offset: 0, 45 Length: size - off, 46 } 47 48 // Try to get a continuous chunk of disk space. 49 err = unix.FcntlFstore(file.Fd(), unix.F_PREALLOCATE, &store) 50 if err != nil { 51 // OK, perhaps we are too fragmented, allocate non-continuous. 52 store.Flags = unix.F_ALLOCATEALL 53 unix.FcntlFstore(file.Fd(), unix.F_PREALLOCATE, &store) 54 } 55 return file.Truncate(size) 56 } 57 58 func osUnlock(file *os.File, start, len int64) _ErrorCode { 59 err := unix.FcntlFlock(file.Fd(), _F_OFD_SETLK, &unix.Flock_t{ 60 Type: unix.F_UNLCK, 61 Start: start, 62 Len: len, 63 }) 64 if err != nil { 65 return _IOERR_UNLOCK 66 } 67 return _OK 68 } 69 70 func osLock(file *os.File, typ int16, start, len int64, timeout time.Duration, def _ErrorCode) _ErrorCode { 71 lock := flocktimeout_t{fl: unix.Flock_t{ 72 Type: typ, 73 Start: start, 74 Len: len, 75 }} 76 var err error 77 switch { 78 case timeout == 0: 79 err = unix.FcntlFlock(file.Fd(), _F_OFD_SETLK, &lock.fl) 80 case timeout < 0: 81 err = unix.FcntlFlock(file.Fd(), _F_OFD_SETLKW, &lock.fl) 82 default: 83 lock.timeout = unix.NsecToTimespec(int64(timeout / time.Nanosecond)) 84 err = unix.FcntlFlock(file.Fd(), _F_OFD_SETLKWTIMEOUT, &lock.fl) 85 } 86 return osLockErrorCode(err, def) 87 } 88 89 func osReadLock(file *os.File, start, len int64, timeout time.Duration) _ErrorCode { 90 return osLock(file, unix.F_RDLCK, start, len, timeout, _IOERR_RDLOCK) 91 } 92 93 func osWriteLock(file *os.File, start, len int64, timeout time.Duration) _ErrorCode { 94 return osLock(file, unix.F_WRLCK, start, len, timeout, _IOERR_LOCK) 95 }