| 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 |