// Copyright (c) 2012, Suryandaru Triandana // All rights reserved. // // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // +build darwin dragonfly freebsd linux netbsd openbsd package storage import ( "os" "syscall" ) type unixFileLock struct { f *os.File } func (fl *unixFileLock) release() error { if err := setFileLock(fl.f, false, false); err != nil { return err } return fl.f.Close() } func newFileLock(path string, readOnly bool) (fl fileLock, err error) { var flag int if readOnly { flag = os.O_RDONLY } else { flag = os.O_RDWR } f, err := os.OpenFile(path, flag, 0) if os.IsNotExist(err) { f, err = os.OpenFile(path, flag|os.O_CREATE, 0644) } if err != nil { return } err = setFileLock(f, readOnly, true) if err != nil { f.Close() return } fl = &unixFileLock{f: f} return } func setFileLock(f *os.File, readOnly, lock bool) error { how := syscall.LOCK_UN if lock { if readOnly { how = syscall.LOCK_SH } else { how = syscall.LOCK_EX } } return syscall.Flock(int(f.Fd()), how|syscall.LOCK_NB) } func rename(oldpath, newpath string) error { return os.Rename(oldpath, newpath) } func isErrInvalid(err error) bool { if err == os.ErrInvalid { return true } if syserr, ok := err.(*os.SyscallError); ok && syserr.Err == syscall.EINVAL { return true } return false } func syncDir(name string) error { f, err := os.Open(name) if err != nil { return err } defer f.Close() if err := f.Sync(); err != nil && !isErrInvalid(err) { return err } return nil }