...
1
2
3
4
5
6
7
8
9
10 package storage
11
12 import (
13 "os"
14 "syscall"
15 )
16
17 type unixFileLock struct {
18 f *os.File
19 }
20
21 func (fl *unixFileLock) release() error {
22 if err := setFileLock(fl.f, false, false); err != nil {
23 return err
24 }
25 return fl.f.Close()
26 }
27
28 func newFileLock(path string, readOnly bool) (fl fileLock, err error) {
29 var flag int
30 if readOnly {
31 flag = os.O_RDONLY
32 } else {
33 flag = os.O_RDWR
34 }
35 f, err := os.OpenFile(path, flag, 0)
36 if os.IsNotExist(err) {
37 f, err = os.OpenFile(path, flag|os.O_CREATE, 0644)
38 }
39 if err != nil {
40 return
41 }
42 err = setFileLock(f, readOnly, true)
43 if err != nil {
44 f.Close()
45 return
46 }
47 fl = &unixFileLock{f: f}
48 return
49 }
50
51 func setFileLock(f *os.File, readOnly, lock bool) error {
52 how := syscall.LOCK_UN
53 if lock {
54 if readOnly {
55 how = syscall.LOCK_SH
56 } else {
57 how = syscall.LOCK_EX
58 }
59 }
60 return syscall.Flock(int(f.Fd()), how|syscall.LOCK_NB)
61 }
62
63 func rename(oldpath, newpath string) error {
64 return os.Rename(oldpath, newpath)
65 }
66
67 func isErrInvalid(err error) bool {
68 if err == os.ErrInvalid {
69 return true
70 }
71
72 if syserr, ok := err.(*os.SyscallError); ok && syserr.Err == syscall.EINVAL {
73 return true
74 }
75
76 if patherr, ok := err.(*os.PathError); ok && patherr.Err == syscall.EINVAL {
77 return true
78 }
79 return false
80 }
81
82 func syncDir(name string) error {
83
84
85
86
87
88
89
90 f, err := os.Open(name)
91 if err != nil {
92 return err
93 }
94 defer f.Close()
95 if err := f.Sync(); err != nil && !isErrInvalid(err) {
96 return err
97 }
98 return nil
99 }
100
View as plain text