OLD | NEW |
1 // Copyright 2016 The LUCI Authors. All rights reserved. | 1 // Copyright 2016 The LUCI Authors. All rights reserved. |
2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
3 // that can be found in the LICENSE file. | 3 // that can be found in the LICENSE file. |
4 | 4 |
5 package managedfs | 5 package managedfs |
6 | 6 |
7 import ( | 7 import ( |
8 "bytes" | 8 "bytes" |
9 "io" | 9 "io" |
10 "os" | 10 "os" |
11 "strings" | 11 "strings" |
12 "unicode/utf8" | 12 "unicode/utf8" |
13 | 13 |
14 "github.com/luci/luci-go/common/errors" | 14 "github.com/luci/luci-go/common/errors" |
15 ) | 15 ) |
16 | 16 |
17 func ensureDirectory(path string) error { | 17 func ensureDirectory(path string) error { |
18 if err := os.MkdirAll(path, 0755); err != nil { | 18 if err := os.MkdirAll(path, 0755); err != nil { |
19 » » return errors.Annotate(err).Reason("failed to create directory [
%(path)s]").D("path", path).Err() | 19 » » return errors.Annotate(err, "failed to create directory [%s]", p
ath).Err() |
20 } | 20 } |
21 return nil | 21 return nil |
22 } | 22 } |
23 | 23 |
24 // createFile creates a new file at the target location and returns it for | 24 // createFile creates a new file at the target location and returns it for |
25 // writing. This is built on to of "os.Create", as the latter will follow the | 25 // writing. This is built on to of "os.Create", as the latter will follow the |
26 // file path if it is a symlink, and we want to actually delete the link and | 26 // file path if it is a symlink, and we want to actually delete the link and |
27 // work with a new file. | 27 // work with a new file. |
28 func createFile(path string) (*os.File, error) { | 28 func createFile(path string) (*os.File, error) { |
29 switch st, err := os.Lstat(path); { | 29 switch st, err := os.Lstat(path); { |
30 case isNotExist(err): | 30 case isNotExist(err): |
31 // The path does not exist, so we're good. | 31 // The path does not exist, so we're good. |
32 break | 32 break |
33 | 33 |
34 case err != nil: | 34 case err != nil: |
35 » » return nil, errors.Annotate(err).Reason("failed to lstat [%(path
)s]").D("path", path).Err() | 35 » » return nil, errors.Annotate(err, "failed to lstat [%s]", path).E
rr() |
36 | 36 |
37 case st.IsDir(): | 37 case st.IsDir(): |
38 » » return nil, errors.Reason("cannot create; path [%(path)s] is a d
irectory").D("path", path).Err() | 38 » » return nil, errors.Reason("cannot create; path [%s] is a directo
ry", path).Err() |
39 | 39 |
40 default: | 40 default: |
41 // Exists, and is a file/link, so unlink. | 41 // Exists, and is a file/link, so unlink. |
42 if err := os.Remove(path); err != nil { | 42 if err := os.Remove(path); err != nil { |
43 » » » return nil, errors.Annotate(err).Reason("failed to remov
e existing [%(path)s]").D("path", path).Err() | 43 » » » return nil, errors.Annotate(err, "failed to remove exist
ing [%s]", path).Err() |
44 } | 44 } |
45 } | 45 } |
46 | 46 |
47 return os.Create(path) | 47 return os.Create(path) |
48 } | 48 } |
49 | 49 |
50 func isValidSinglePathComponent(elem string) bool { | 50 func isValidSinglePathComponent(elem string) bool { |
51 return (len(elem) > 0) && (strings.IndexRune(elem, os.PathSeparator) < 0
) | 51 return (len(elem) > 0) && (strings.IndexRune(elem, os.PathSeparator) < 0
) |
52 } | 52 } |
53 | 53 |
(...skipping 15 matching lines...) Expand all Loading... |
69 | 69 |
70 func isNotExist(err error) bool { | 70 func isNotExist(err error) bool { |
71 return os.IsNotExist(errors.Unwrap(err)) | 71 return os.IsNotExist(errors.Unwrap(err)) |
72 } | 72 } |
73 | 73 |
74 func byteCompare(a, b io.Reader, aBuf, bBuf []byte) (bool, error) { | 74 func byteCompare(a, b io.Reader, aBuf, bBuf []byte) (bool, error) { |
75 for done := false; !done; { | 75 for done := false; !done; { |
76 ac, err := a.Read(aBuf) | 76 ac, err := a.Read(aBuf) |
77 if err != nil { | 77 if err != nil { |
78 if err != io.EOF { | 78 if err != io.EOF { |
79 » » » » return false, errors.Annotate(err).Reason("faile
d to read").Err() | 79 » » » » return false, errors.Annotate(err, "failed to re
ad").Err() |
80 } | 80 } |
81 ac = 0 | 81 ac = 0 |
82 done = true | 82 done = true |
83 } | 83 } |
84 | 84 |
85 bc, err := b.Read(bBuf) | 85 bc, err := b.Read(bBuf) |
86 if err != nil { | 86 if err != nil { |
87 if err != io.EOF { | 87 if err != io.EOF { |
88 » » » » return false, errors.Annotate(err).Reason("faile
d to read").Err() | 88 » » » » return false, errors.Annotate(err, "failed to re
ad").Err() |
89 } | 89 } |
90 bc = 0 | 90 bc = 0 |
91 } | 91 } |
92 | 92 |
93 if !(ac == bc && bytes.Equal(aBuf[:ac], bBuf[:bc])) { | 93 if !(ac == bc && bytes.Equal(aBuf[:ac], bBuf[:bc])) { |
94 return false, nil | 94 return false, nil |
95 } | 95 } |
96 } | 96 } |
97 return true, nil | 97 return true, nil |
98 } | 98 } |
OLD | NEW |