...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package fileutil
16
17 import (
18 "fmt"
19 "io"
20 "io/ioutil"
21 "os"
22 "path/filepath"
23
24 "go.uber.org/zap"
25 )
26
27 const (
28
29 PrivateFileMode = 0600
30 )
31
32
33
34 func IsDirWriteable(dir string) error {
35 f, err := filepath.Abs(filepath.Join(dir, ".touch"))
36 if err != nil {
37 return err
38 }
39 if err := ioutil.WriteFile(f, []byte(""), PrivateFileMode); err != nil {
40 return err
41 }
42 return os.Remove(f)
43 }
44
45
46
47 func TouchDirAll(lg *zap.Logger, dir string) error {
48
49
50 if Exist(dir) {
51 err := CheckDirPermission(dir, PrivateDirMode)
52 if err != nil {
53 lg.Warn("check file permission", zap.Error(err))
54 }
55 } else {
56 err := os.MkdirAll(dir, PrivateDirMode)
57 if err != nil {
58
59
60 return err
61 }
62 }
63
64 return IsDirWriteable(dir)
65 }
66
67
68
69 func CreateDirAll(lg *zap.Logger, dir string) error {
70 err := TouchDirAll(lg, dir)
71 if err == nil {
72 var ns []string
73 ns, err = ReadDir(dir)
74 if err != nil {
75 return err
76 }
77 if len(ns) != 0 {
78 err = fmt.Errorf("expected %q to be empty, got %q", dir, ns)
79 }
80 }
81 return err
82 }
83
84
85 func Exist(name string) bool {
86 _, err := os.Stat(name)
87 return err == nil
88 }
89
90
91 func DirEmpty(name string) bool {
92 ns, err := ReadDir(name)
93 return len(ns) == 0 && err == nil
94 }
95
96
97
98 func ZeroToEnd(f *os.File) error {
99
100 off, err := f.Seek(0, io.SeekCurrent)
101 if err != nil {
102 return err
103 }
104 lenf, lerr := f.Seek(0, io.SeekEnd)
105 if lerr != nil {
106 return lerr
107 }
108 if err = f.Truncate(off); err != nil {
109 return err
110 }
111
112 if err = Preallocate(f, lenf, true); err != nil {
113 return err
114 }
115 _, err = f.Seek(off, io.SeekStart)
116 return err
117 }
118
119
120
121 func CheckDirPermission(dir string, perm os.FileMode) error {
122 if !Exist(dir) {
123 return fmt.Errorf("directory %q empty, cannot check permission", dir)
124 }
125
126 dirInfo, err := os.Stat(dir)
127 if err != nil {
128 return err
129 }
130 dirMode := dirInfo.Mode().Perm()
131 if dirMode != perm {
132 err = fmt.Errorf("directory %q exist, but the permission is %q. The recommended permission is %q to prevent possible unprivileged access to the data", dir, dirInfo.Mode(), os.FileMode(PrivateDirMode))
133 return err
134 }
135 return nil
136 }
137
138
139
140 func RemoveMatchFile(lg *zap.Logger, dir string, matchFunc func(fileName string) bool) error {
141 if lg == nil {
142 lg = zap.NewNop()
143 }
144 if !Exist(dir) {
145 return fmt.Errorf("directory %s does not exist", dir)
146 }
147 fileNames, err := ReadDir(dir)
148 if err != nil {
149 return err
150 }
151 var removeFailedFiles []string
152 for _, fileName := range fileNames {
153 if matchFunc(fileName) {
154 file := filepath.Join(dir, fileName)
155 if err = os.Remove(file); err != nil {
156 removeFailedFiles = append(removeFailedFiles, fileName)
157 lg.Error("remove file failed",
158 zap.String("file", file),
159 zap.Error(err))
160 continue
161 }
162 }
163 }
164 if len(removeFailedFiles) != 0 {
165 return fmt.Errorf("remove file(s) %v error", removeFailedFiles)
166 }
167 return nil
168 }
169
View as plain text