diff options
author | Colin Cross <ccross@android.com> | 2020-06-29 23:01:52 -0700 |
---|---|---|
committer | Colin Cross <ccross@android.com> | 2020-06-29 23:30:38 -0700 |
commit | 7cdad45cf217097e262ca370aa2cc36a6545a49e (patch) | |
tree | a4145de01186fed596a7025b6e4c2a0246086dc7 /finder | |
parent | 7f8aa39abed0ca370b0686f89cb2f9a659d87549 (diff) | |
download | soong-7cdad45cf217097e262ca370aa2cc36a6545a49e.tar.gz |
Add Stat to finder/fs
Add a Stat method to finder/fs that will be used by finder to read
the mode of the target of a symlink.
Bug: 157656545
Test: fs_test.go
Change-Id: Ie2b4509b7d11857d9a1685de4477088b91d43c63
Diffstat (limited to 'finder')
-rw-r--r-- | finder/fs/Android.bp | 1 | ||||
-rw-r--r-- | finder/fs/fs.go | 33 | ||||
-rw-r--r-- | finder/fs/fs_test.go | 76 |
3 files changed, 101 insertions, 9 deletions
diff --git a/finder/fs/Android.bp b/finder/fs/Android.bp index 835eb0b31..b71934fbd 100644 --- a/finder/fs/Android.bp +++ b/finder/fs/Android.bp @@ -25,6 +25,7 @@ bootstrap_go_package { "test.go", ], testSrcs: [ + "fs_test.go", "readdir_test.go", ], darwin: { diff --git a/finder/fs/fs.go b/finder/fs/fs.go index 071f7640f..d2e3e4ab0 100644 --- a/finder/fs/fs.go +++ b/finder/fs/fs.go @@ -51,6 +51,7 @@ type FileSystem interface { // getting information about files Open(name string) (file io.ReadCloser, err error) Lstat(path string) (stats os.FileInfo, err error) + Stat(path string) (stats os.FileInfo, err error) ReadDir(path string) (contents []DirEntryInfo, err error) InodeNumber(info os.FileInfo) (number uint64, err error) @@ -99,6 +100,10 @@ func (osFs) Lstat(path string) (stats os.FileInfo, err error) { return os.Lstat(path) } +func (osFs) Stat(path string) (stats os.FileInfo, err error) { + return os.Stat(path) +} + func (osFs) ReadDir(path string) (contents []DirEntryInfo, err error) { entries, err := readdir(path) if err != nil { @@ -376,7 +381,7 @@ type mockFileInfo struct { size int64 modTime time.Time // time at which the inode's contents were modified permTime time.Time // time at which the inode's permissions were modified - isDir bool + mode os.FileMode inodeNumber uint64 deviceNumber uint64 } @@ -390,7 +395,7 @@ func (m *mockFileInfo) Size() int64 { } func (m *mockFileInfo) Mode() os.FileMode { - return 0 + return m.mode } func (m *mockFileInfo) ModTime() time.Time { @@ -398,7 +403,7 @@ func (m *mockFileInfo) ModTime() time.Time { } func (m *mockFileInfo) IsDir() bool { - return m.isDir + return m.mode&os.ModeDir != 0 } func (m *mockFileInfo) Sys() interface{} { @@ -407,11 +412,11 @@ func (m *mockFileInfo) Sys() interface{} { func (m *MockFs) dirToFileInfo(d *mockDir, path string) (info *mockFileInfo) { return &mockFileInfo{ - path: path, + path: filepath.Base(path), size: 1, modTime: d.modTime, permTime: d.permTime, - isDir: true, + mode: os.ModeDir, inodeNumber: d.inodeNumber, deviceNumber: m.deviceNumber, } @@ -420,11 +425,11 @@ func (m *MockFs) dirToFileInfo(d *mockDir, path string) (info *mockFileInfo) { func (m *MockFs) fileToFileInfo(f *mockFile, path string) (info *mockFileInfo) { return &mockFileInfo{ - path: path, + path: filepath.Base(path), size: 1, modTime: f.modTime, permTime: f.permTime, - isDir: false, + mode: 0, inodeNumber: f.inodeNumber, deviceNumber: m.deviceNumber, } @@ -432,11 +437,11 @@ func (m *MockFs) fileToFileInfo(f *mockFile, path string) (info *mockFileInfo) { func (m *MockFs) linkToFileInfo(l *mockLink, path string) (info *mockFileInfo) { return &mockFileInfo{ - path: path, + path: filepath.Base(path), size: 1, modTime: l.modTime, permTime: l.permTime, - isDir: false, + mode: os.ModeSymlink, inodeNumber: l.inodeNumber, deviceNumber: m.deviceNumber, } @@ -485,6 +490,16 @@ func (m *MockFs) Lstat(path string) (stats os.FileInfo, err error) { } } +func (m *MockFs) Stat(path string) (stats os.FileInfo, err error) { + // resolve symlinks + path, err = m.resolve(path, true) + if err != nil { + return nil, err + } + + return m.Lstat(path) +} + func (m *MockFs) InodeNumber(info os.FileInfo) (number uint64, err error) { mockInfo, ok := info.(*mockFileInfo) if ok { diff --git a/finder/fs/fs_test.go b/finder/fs/fs_test.go new file mode 100644 index 000000000..22a4d7aca --- /dev/null +++ b/finder/fs/fs_test.go @@ -0,0 +1,76 @@ +// Copyright 2020 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package fs + +import ( + "os" + "testing" +) + +func TestMockFs_LstatStatSymlinks(t *testing.T) { + // setup filesystem + filesystem := NewMockFs(nil) + Create(t, "/tmp/realdir/hi.txt", filesystem) + Create(t, "/tmp/realdir/ignoreme.txt", filesystem) + + Link(t, "/tmp/links/dir", "../realdir", filesystem) + Link(t, "/tmp/links/file", "../realdir/hi.txt", filesystem) + Link(t, "/tmp/links/broken", "nothingHere", filesystem) + Link(t, "/tmp/links/recursive", "recursive", filesystem) + + assertStat := func(t *testing.T, stat os.FileInfo, err error, wantName string, wantMode os.FileMode) { + t.Helper() + if err != nil { + t.Error(err) + return + } + if g, w := stat.Name(), wantName; g != w { + t.Errorf("want name %q, got %q", w, g) + } + if g, w := stat.Mode(), wantMode; g != w { + t.Errorf("%s: want mode %q, got %q", wantName, w, g) + } + } + + assertErr := func(t *testing.T, err error, wantErr string) { + if err == nil || err.Error() != wantErr { + t.Errorf("want error %q, got %q", wantErr, err) + } + } + + stat, err := filesystem.Lstat("/tmp/links/dir") + assertStat(t, stat, err, "dir", os.ModeSymlink) + + stat, err = filesystem.Stat("/tmp/links/dir") + assertStat(t, stat, err, "realdir", os.ModeDir) + + stat, err = filesystem.Lstat("/tmp/links/file") + assertStat(t, stat, err, "file", os.ModeSymlink) + + stat, err = filesystem.Stat("/tmp/links/file") + assertStat(t, stat, err, "hi.txt", 0) + + stat, err = filesystem.Lstat("/tmp/links/broken") + assertStat(t, stat, err, "broken", os.ModeSymlink) + + stat, err = filesystem.Stat("/tmp/links/broken") + assertErr(t, err, "stat /tmp/links/nothingHere: file does not exist") + + stat, err = filesystem.Lstat("/tmp/links/recursive") + assertStat(t, stat, err, "recursive", os.ModeSymlink) + + stat, err = filesystem.Stat("/tmp/links/recursive") + assertErr(t, err, "read /tmp/links/recursive: too many levels of symbolic links") +} |