From fdb3e5129451faad1b63bb8f8ce5dcaf28662d08 Mon Sep 17 00:00:00 2001 From: Evan Lezar Date: Fri, 25 Nov 2022 13:16:47 +0100 Subject: [PATCH 1/8] Add egl_external_platform.d/10_nvidia_wayland.json to graphics mounts Signed-off-by: Evan Lezar --- internal/discover/graphics.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/discover/graphics.go b/internal/discover/graphics.go index c24cb4ad..17e252eb 100644 --- a/internal/discover/graphics.go +++ b/internal/discover/graphics.go @@ -81,6 +81,7 @@ func NewGraphicsMountsDiscoverer(logger *logrus.Logger, root string) (Discover, "/usr/share/vulkan/icd.d/nvidia_icd.json", "/usr/share/vulkan/implicit_layer.d/nvidia_layers.json", "/usr/share/egl/egl_external_platform.d/15_nvidia_gbm.json", + "/usr/share/egl/egl_external_platform.d/10_nvidia_wayland.json", }, ) From a7fc29d4bd8eaf780719eeecb3d63406205c3ac6 Mon Sep 17 00:00:00 2001 From: Evan Lezar Date: Fri, 25 Nov 2022 13:31:41 +0100 Subject: [PATCH 2/8] Add tests for file locator Signed-off-by: Evan Lezar --- internal/lookup/file_test.go | 53 ++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 internal/lookup/file_test.go diff --git a/internal/lookup/file_test.go b/internal/lookup/file_test.go new file mode 100644 index 00000000..78285554 --- /dev/null +++ b/internal/lookup/file_test.go @@ -0,0 +1,53 @@ +/** +# Copyright (c) 2022, NVIDIA CORPORATION. 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 lookup + +import ( + "fmt" + "testing" + + testlog "github.com/sirupsen/logrus/hooks/test" + "github.com/stretchr/testify/require" +) + +func TestFileLocator(t *testing.T) { + logger, _ := testlog.NewNullLogger() + + testCases := []struct { + root string + expectedPrefixes []string + }{ + { + expectedPrefixes: []string{""}, + }, + { + root: "/", + expectedPrefixes: []string{"/"}, + }, + { + root: "/some/root", + expectedPrefixes: []string{"/some/root"}, + }, + } + + for i, tc := range testCases { + t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { + f := newFileLocator(logger, tc.root) + require.EqualValues(t, tc.expectedPrefixes, f.prefixes) + }) + } +} From 55eb898186a0dcaa80eae5adced7f0bd16abea16 Mon Sep 17 00:00:00 2001 From: Evan Lezar Date: Fri, 25 Nov 2022 13:37:50 +0100 Subject: [PATCH 3/8] Add support for specifying multiple prefixes This change allows the file Locator to be instantiated with multiple search prefixes. Signed-off-by: Evan Lezar --- internal/lookup/file.go | 46 +++++++++++++++++++++++++++++++----- internal/lookup/file_test.go | 41 +++++++++++++++++++++++++++----- 2 files changed, 75 insertions(+), 12 deletions(-) diff --git a/internal/lookup/file.go b/internal/lookup/file.go index ab52d03d..724075a2 100644 --- a/internal/lookup/file.go +++ b/internal/lookup/file.go @@ -32,22 +32,56 @@ type file struct { filter func(string) error } -// NewFileLocator creates a Locator that can be used to find files at the specified root. A logger -// can also be specified. -func NewFileLocator(logger *log.Logger, root string) Locator { - l := newFileLocator(logger, root) +// NewFileLocator creates a Locator that can be used to find files at the specified root. +// An optional list of prefixes can aslo be specified with each of these being searched in order. +// The specified root is prefixed to each of the prefixes to determine the final search path. +func NewFileLocator(logger *log.Logger, root string, prefixes ...string) Locator { + l := newFileLocator(logger, root, prefixes...) return &l } -func newFileLocator(logger *log.Logger, root string) file { +func newFileLocator(logger *log.Logger, root string, prefixes ...string) file { + return file{ logger: logger, - prefixes: []string{root}, + prefixes: getSearchPrefixes(root, prefixes...), filter: assertFile, } } +// getSearchPrefixes generates a list of unique paths to be searched by a file locator. +// +// For each of the unique prefixes

specified the path

is searched, where is the +// specified root. If no prefixes are specified, is returned as the only search prefix. +// +// Note that an empty root is equivalent to searching relative to the current working directory, and +// if the root filesystem should be searched instead, root should be specified as "/" explicitly. +// +// Also, a prefix of "" forces the root to be included in returned set of paths. This means that if +// the root in addition to another prefix must be searched the function should be called with: +// +// getSearchPrefixes("/root", "", "another/path") +// +// and will result in the search paths []{"/root", "/root/another/path"} being returned. +func getSearchPrefixes(root string, prefixes ...string) []string { + seen := make(map[string]bool) + var uniquePrefixes []string + for _, p := range prefixes { + if seen[p] { + continue + } + seen[p] = true + uniquePrefixes = append(uniquePrefixes, filepath.Join(root, p)) + } + + if len(uniquePrefixes) == 0 { + uniquePrefixes = append(uniquePrefixes, root) + } + + return uniquePrefixes +} + var _ Locator = (*file)(nil) // Locate attempts to find files with names matching the specified pattern. diff --git a/internal/lookup/file_test.go b/internal/lookup/file_test.go index 78285554..b7006bf5 100644 --- a/internal/lookup/file_test.go +++ b/internal/lookup/file_test.go @@ -20,18 +20,17 @@ import ( "fmt" "testing" - testlog "github.com/sirupsen/logrus/hooks/test" "github.com/stretchr/testify/require" ) -func TestFileLocator(t *testing.T) { - logger, _ := testlog.NewNullLogger() - +func TestGetSearchPrefixes(t *testing.T) { testCases := []struct { root string + prefixes []string expectedPrefixes []string }{ { + root: "", expectedPrefixes: []string{""}, }, { @@ -42,12 +41,42 @@ func TestFileLocator(t *testing.T) { root: "/some/root", expectedPrefixes: []string{"/some/root"}, }, + { + root: "", + prefixes: []string{"foo", "bar"}, + expectedPrefixes: []string{"foo", "bar"}, + }, + { + root: "/", + prefixes: []string{"foo", "bar"}, + expectedPrefixes: []string{"/foo", "/bar"}, + }, + { + root: "/", + prefixes: []string{"/foo", "/bar"}, + expectedPrefixes: []string{"/foo", "/bar"}, + }, + { + root: "/some/root", + prefixes: []string{"foo", "bar"}, + expectedPrefixes: []string{"/some/root/foo", "/some/root/bar"}, + }, + { + root: "", + prefixes: []string{"foo", "bar", "bar", "foo"}, + expectedPrefixes: []string{"foo", "bar"}, + }, + { + root: "/some/root", + prefixes: []string{"foo", "bar", "foo", "bar"}, + expectedPrefixes: []string{"/some/root/foo", "/some/root/bar"}, + }, } for i, tc := range testCases { t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { - f := newFileLocator(logger, tc.root) - require.EqualValues(t, tc.expectedPrefixes, f.prefixes) + prefixes := getSearchPrefixes(tc.root, tc.prefixes...) + require.EqualValues(t, tc.expectedPrefixes, prefixes) }) } } From 8da7e74408dfef0987bb3ad53d2b0352c5cfadc2 Mon Sep 17 00:00:00 2001 From: Evan Lezar Date: Fri, 25 Nov 2022 13:59:11 +0100 Subject: [PATCH 4/8] Add tests for executable locator Signed-off-by: Evan Lezar --- internal/lookup/executable.go | 5 ++ internal/lookup/executable_test.go | 77 ++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 internal/lookup/executable_test.go diff --git a/internal/lookup/executable.go b/internal/lookup/executable.go index 2bfe04ea..d347732c 100644 --- a/internal/lookup/executable.go +++ b/internal/lookup/executable.go @@ -33,6 +33,10 @@ type executable struct { func NewExecutableLocator(logger *log.Logger, root string) Locator { paths := GetPaths(root) + return newExecutableLocator(logger, root, paths...) +} + +func newExecutableLocator(logger *log.Logger, root string, paths ...string) *executable { var prefixes []string for _, dir := range paths { prefixes = append(prefixes, filepath.Join(root, dir)) @@ -44,6 +48,7 @@ func NewExecutableLocator(logger *log.Logger, root string) Locator { filter: assertExecutable, }, } + return &l } diff --git a/internal/lookup/executable_test.go b/internal/lookup/executable_test.go new file mode 100644 index 00000000..68d7c678 --- /dev/null +++ b/internal/lookup/executable_test.go @@ -0,0 +1,77 @@ +/** +# Copyright (c) 2022, NVIDIA CORPORATION. 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 lookup + +import ( + "fmt" + "testing" + + testlog "github.com/sirupsen/logrus/hooks/test" + "github.com/stretchr/testify/require" +) + +func TestExecutableLocator(t *testing.T) { + logger, _ := testlog.NewNullLogger() + + testCases := []struct { + root string + paths []string + expectedPrefixes []string + }{ + { + root: "", + expectedPrefixes: nil, + }, + { + root: "", + paths: []string{"/"}, + expectedPrefixes: []string{"/"}, + }, + { + root: "", + paths: []string{"/", "/bin"}, + expectedPrefixes: []string{"/", "/bin"}, + }, + { + root: "/", + expectedPrefixes: nil, + }, + { + root: "/", + paths: []string{"/"}, + expectedPrefixes: []string{"/"}, + }, + { + root: "/", + paths: []string{"/", "/bin"}, + expectedPrefixes: []string{"/", "/bin"}, + }, + { + root: "/some/path", + paths: []string{"/", "/bin"}, + expectedPrefixes: []string{"/some/path", "/some/path/bin"}, + }, + } + + for i, tc := range testCases { + t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { + e := newExecutableLocator(logger, tc.root, tc.paths...) + + require.EqualValues(t, tc.expectedPrefixes, e.prefixes) + }) + } +} From d1a3de7671cc835d1c96c364c3125a5960a733b4 Mon Sep 17 00:00:00 2001 From: Evan Lezar Date: Fri, 25 Nov 2022 13:59:26 +0100 Subject: [PATCH 5/8] Add test for device locator Signed-off-by: Evan Lezar --- internal/lookup/device_test.go | 55 ++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 internal/lookup/device_test.go diff --git a/internal/lookup/device_test.go b/internal/lookup/device_test.go new file mode 100644 index 00000000..7062e51e --- /dev/null +++ b/internal/lookup/device_test.go @@ -0,0 +1,55 @@ +/** +# Copyright (c) 2022, NVIDIA CORPORATION. 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 lookup + +import ( + "fmt" + "testing" + + testlog "github.com/sirupsen/logrus/hooks/test" + "github.com/stretchr/testify/require" +) + +func TestCharDeviceLocator(t *testing.T) { + logger, _ := testlog.NewNullLogger() + + testCases := []struct { + root string + expectedPrefixes []string + }{ + { + root: "", + expectedPrefixes: []string{"", "/dev"}, + }, + { + root: "/", + expectedPrefixes: []string{"/", "/dev"}, + }, + { + root: "/some/root", + expectedPrefixes: []string{"/some/root", "/some/root/dev"}, + }, + } + + for i, tc := range testCases { + t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { + f := NewCharDeviceLocator(logger, tc.root).(*file) + + require.EqualValues(t, tc.expectedPrefixes, f.prefixes) + }) + } +} From db962c4bf2f278e4bbdfaf482576191752eb9530 Mon Sep 17 00:00:00 2001 From: Evan Lezar Date: Fri, 25 Nov 2022 14:19:07 +0100 Subject: [PATCH 6/8] Use getSearchPrefixes for all locators Signed-off-by: Evan Lezar --- internal/lookup/device.go | 3 +-- internal/lookup/dir.go | 2 +- internal/lookup/executable.go | 7 +------ internal/lookup/executable_test.go | 4 ++-- 4 files changed, 5 insertions(+), 11 deletions(-) diff --git a/internal/lookup/device.go b/internal/lookup/device.go index 29738cc7..aa4a2120 100644 --- a/internal/lookup/device.go +++ b/internal/lookup/device.go @@ -19,7 +19,6 @@ package lookup import ( "fmt" "os" - "path/filepath" "github.com/sirupsen/logrus" ) @@ -33,7 +32,7 @@ const ( func NewCharDeviceLocator(logger *logrus.Logger, root string) Locator { l := file{ logger: logger, - prefixes: []string{root, filepath.Join(root, devRoot)}, + prefixes: getSearchPrefixes(root, "", devRoot), filter: assertCharDevice, } diff --git a/internal/lookup/dir.go b/internal/lookup/dir.go index 695025a5..f1d0156c 100644 --- a/internal/lookup/dir.go +++ b/internal/lookup/dir.go @@ -28,7 +28,7 @@ import ( func NewDirectoryLocator(logger *log.Logger, root string) Locator { l := file{ logger: logger, - prefixes: []string{root}, + prefixes: getSearchPrefixes(root), filter: assertDirectory, } diff --git a/internal/lookup/executable.go b/internal/lookup/executable.go index d347732c..ac27634b 100644 --- a/internal/lookup/executable.go +++ b/internal/lookup/executable.go @@ -19,7 +19,6 @@ package lookup import ( "fmt" "os" - "path/filepath" "strings" log "github.com/sirupsen/logrus" @@ -37,14 +36,10 @@ func NewExecutableLocator(logger *log.Logger, root string) Locator { } func newExecutableLocator(logger *log.Logger, root string, paths ...string) *executable { - var prefixes []string - for _, dir := range paths { - prefixes = append(prefixes, filepath.Join(root, dir)) - } l := executable{ file: file{ logger: logger, - prefixes: prefixes, + prefixes: getSearchPrefixes(root, paths...), filter: assertExecutable, }, } diff --git a/internal/lookup/executable_test.go b/internal/lookup/executable_test.go index 68d7c678..09bbf2d9 100644 --- a/internal/lookup/executable_test.go +++ b/internal/lookup/executable_test.go @@ -34,7 +34,7 @@ func TestExecutableLocator(t *testing.T) { }{ { root: "", - expectedPrefixes: nil, + expectedPrefixes: []string{""}, }, { root: "", @@ -48,7 +48,7 @@ func TestExecutableLocator(t *testing.T) { }, { root: "/", - expectedPrefixes: nil, + expectedPrefixes: []string{"/"}, }, { root: "/", From bea83212056f7f0e30be5cc6598cc9a10b86fb19 Mon Sep 17 00:00:00 2001 From: Evan Lezar Date: Fri, 25 Nov 2022 14:19:59 +0100 Subject: [PATCH 7/8] Use prefix search for locating graphics files Signed-off-by: Evan Lezar --- internal/discover/graphics.go | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/internal/discover/graphics.go b/internal/discover/graphics.go index 17e252eb..4d66832b 100644 --- a/internal/discover/graphics.go +++ b/internal/discover/graphics.go @@ -70,18 +70,14 @@ func NewGraphicsMountsDiscoverer(logger *logrus.Logger, root string) (Discover, jsonMounts := NewMounts( logger, - lookup.NewFileLocator(logger, root), + lookup.NewFileLocator(logger, root, "/etc", "/usr/share"), root, []string{ - // TODO: We should handle this more cleanly - "/etc/glvnd/egl_vendor.d/10_nvidia.json", - "/etc/vulkan/icd.d/nvidia_icd.json", - "/etc/vulkan/implicit_layer.d/nvidia_layers.json", - "/usr/share/glvnd/egl_vendor.d/10_nvidia.json", - "/usr/share/vulkan/icd.d/nvidia_icd.json", - "/usr/share/vulkan/implicit_layer.d/nvidia_layers.json", - "/usr/share/egl/egl_external_platform.d/15_nvidia_gbm.json", - "/usr/share/egl/egl_external_platform.d/10_nvidia_wayland.json", + "glvnd/egl_vendor.d/10_nvidia.json", + "vulkan/icd.d/nvidia_icd.json", + "vulkan/implicit_layer.d/nvidia_layers.json", + "egl/egl_external_platform.d/15_nvidia_gbm.json", + "egl/egl_external_platform.d/10_nvidia_wayland.json", }, ) From 8604c255c406faf3df67a55138887df457cb5172 Mon Sep 17 00:00:00 2001 From: Evan Lezar Date: Fri, 2 Dec 2022 11:38:40 +0100 Subject: [PATCH 8/8] Use Options to set FileLocator options Signed-off-by: Evan Lezar --- cmd/nvidia-ctk/cdi/generate/ipc.go | 5 ++- internal/discover/gds.go | 5 ++- internal/discover/graphics.go | 11 ++++- internal/lookup/device.go | 13 +++--- internal/lookup/dir.go | 12 +++--- internal/lookup/executable.go | 13 +++--- internal/lookup/file.go | 64 ++++++++++++++++++++++++------ internal/lookup/symlinks.go | 6 ++- internal/modifier/tegra.go | 2 +- 9 files changed, 92 insertions(+), 39 deletions(-) diff --git a/cmd/nvidia-ctk/cdi/generate/ipc.go b/cmd/nvidia-ctk/cdi/generate/ipc.go index 0f5157ee..e7c940b1 100644 --- a/cmd/nvidia-ctk/cdi/generate/ipc.go +++ b/cmd/nvidia-ctk/cdi/generate/ipc.go @@ -26,7 +26,10 @@ import ( func NewIPCDiscoverer(logger *logrus.Logger, root string) (discover.Discover, error) { d := discover.NewMounts( logger, - lookup.NewFileLocator(logger, root), + lookup.NewFileLocator( + lookup.WithLogger(logger), + lookup.WithRoot(root), + ), root, []string{ "/var/run/nvidia-persistenced/socket", diff --git a/internal/discover/gds.go b/internal/discover/gds.go index dab2f735..7da5e07d 100644 --- a/internal/discover/gds.go +++ b/internal/discover/gds.go @@ -45,7 +45,10 @@ func NewGDSDiscoverer(logger *logrus.Logger, root string) (Discover, error) { cufile := NewMounts( logger, - lookup.NewFileLocator(logger, root), + lookup.NewFileLocator( + lookup.WithLogger(logger), + lookup.WithRoot(root), + ), root, []string{"/etc/cufile.json"}, ) diff --git a/internal/discover/graphics.go b/internal/discover/graphics.go index 4d66832b..ab858405 100644 --- a/internal/discover/graphics.go +++ b/internal/discover/graphics.go @@ -70,7 +70,11 @@ func NewGraphicsMountsDiscoverer(logger *logrus.Logger, root string) (Discover, jsonMounts := NewMounts( logger, - lookup.NewFileLocator(logger, root, "/etc", "/usr/share"), + lookup.NewFileLocator( + lookup.WithLogger(logger), + lookup.WithRoot(root), + lookup.WithSearchPaths("/etc", "/usr/share"), + ), root, []string{ "glvnd/egl_vendor.d/10_nvidia.json", @@ -161,7 +165,10 @@ func (d drmDevicesByPath) getSpecificLinkArgs(devices []Device) ([]string, error selectedDevices[filepath.Base(d.HostPath)] = true } - linkLocator := lookup.NewFileLocator(d.logger, d.root) + linkLocator := lookup.NewFileLocator( + lookup.WithLogger(d.logger), + lookup.WithRoot(d.root), + ) candidates, err := linkLocator.Locate("/dev/dri/by-path/pci-*-*") if err != nil { d.logger.Warningf("Failed to locate by-path links: %v; ignoring", err) diff --git a/internal/lookup/device.go b/internal/lookup/device.go index aa4a2120..dfa774ea 100644 --- a/internal/lookup/device.go +++ b/internal/lookup/device.go @@ -30,13 +30,12 @@ const ( // NewCharDeviceLocator creates a Locator that can be used to find char devices at the specified root. A logger is // also specified. func NewCharDeviceLocator(logger *logrus.Logger, root string) Locator { - l := file{ - logger: logger, - prefixes: getSearchPrefixes(root, "", devRoot), - filter: assertCharDevice, - } - - return &l + return NewFileLocator( + WithLogger(logger), + WithRoot(root), + WithSearchPaths("", devRoot), + WithFilter(assertCharDevice), + ) } // assertCharDevice checks whether the specified path is a char device and returns an error if this is not the case. diff --git a/internal/lookup/dir.go b/internal/lookup/dir.go index f1d0156c..87b32507 100644 --- a/internal/lookup/dir.go +++ b/internal/lookup/dir.go @@ -26,13 +26,11 @@ import ( // NewDirectoryLocator creates a Locator that can be used to find directories at the specified root. A logger // is also specified. func NewDirectoryLocator(logger *log.Logger, root string) Locator { - l := file{ - logger: logger, - prefixes: getSearchPrefixes(root), - filter: assertDirectory, - } - - return &l + return NewFileLocator( + WithLogger(logger), + WithRoot(root), + WithFilter(assertDirectory), + ) } // assertDirectory checks wither the specified path is a directory. diff --git a/internal/lookup/executable.go b/internal/lookup/executable.go index ac27634b..e7ddf450 100644 --- a/internal/lookup/executable.go +++ b/internal/lookup/executable.go @@ -36,12 +36,15 @@ func NewExecutableLocator(logger *log.Logger, root string) Locator { } func newExecutableLocator(logger *log.Logger, root string, paths ...string) *executable { + f := newFileLocator( + WithLogger(logger), + WithRoot(root), + WithSearchPaths(paths...), + WithFilter(assertExecutable), + ) + l := executable{ - file: file{ - logger: logger, - prefixes: getSearchPrefixes(root, paths...), - filter: assertExecutable, - }, + file: *f, } return &l diff --git a/internal/lookup/file.go b/internal/lookup/file.go index 724075a2..94702174 100644 --- a/internal/lookup/file.go +++ b/internal/lookup/file.go @@ -28,31 +28,69 @@ import ( // prefixes. The validity of a file is determined by a filter function. type file struct { logger *log.Logger + root string prefixes []string filter func(string) error } -// NewFileLocator creates a Locator that can be used to find files at the specified root. -// An optional list of prefixes can aslo be specified with each of these being searched in order. -// The specified root is prefixed to each of the prefixes to determine the final search path. -func NewFileLocator(logger *log.Logger, root string, prefixes ...string) Locator { - l := newFileLocator(logger, root, prefixes...) +// Option defines a function for passing options to the NewFileLocator() call +type Option func(*file) - return &l +// WithRoot sets the root for the file locator +func WithRoot(root string) Option { + return func(f *file) { + f.root = root + } } -func newFileLocator(logger *log.Logger, root string, prefixes ...string) file { - - return file{ - logger: logger, - prefixes: getSearchPrefixes(root, prefixes...), - filter: assertFile, +// WithLogger sets the logger for the file locator +func WithLogger(logger *log.Logger) Option { + return func(f *file) { + f.logger = logger } } +// WithSearchPaths sets the search paths for the file locator. +func WithSearchPaths(paths ...string) Option { + return func(f *file) { + f.prefixes = paths + } +} + +// WithFilter sets the filter for the file locator +// The filter is called for each candidate file and candidates that return nil are considered. +func WithFilter(assert func(string) error) Option { + return func(f *file) { + f.filter = assert + } +} + +// NewFileLocator creates a Locator that can be used to find files with the specified options. +func NewFileLocator(opts ...Option) Locator { + return newFileLocator(opts...) +} + +func newFileLocator(opts ...Option) *file { + f := &file{} + for _, opt := range opts { + opt(f) + } + if f.logger == nil { + f.logger = log.StandardLogger() + } + if f.filter == nil { + f.filter = assertFile + } + // Since the `Locate` implementations rely on the root already being specified we update + // the prefixes to include the root. + f.prefixes = getSearchPrefixes(f.root, f.prefixes...) + + return f +} + // getSearchPrefixes generates a list of unique paths to be searched by a file locator. // -// For each of the unique prefixes

specified the path

is searched, where is the +// For each of the unique prefixes

specified, the path

is searched, where is the // specified root. If no prefixes are specified, is returned as the only search prefix. // // Note that an empty root is equivalent to searching relative to the current working directory, and diff --git a/internal/lookup/symlinks.go b/internal/lookup/symlinks.go index 43e37123..0d82a9e1 100644 --- a/internal/lookup/symlinks.go +++ b/internal/lookup/symlinks.go @@ -35,8 +35,9 @@ type symlink struct { // NewSymlinkChainLocator creats a locator that can be used for locating files through symlinks. // A logger can also be specified. func NewSymlinkChainLocator(logger *logrus.Logger, root string) Locator { + f := newFileLocator(WithLogger(logger), WithRoot(root)) l := symlinkChain{ - file: newFileLocator(logger, root), + file: *f, } return &l @@ -45,8 +46,9 @@ func NewSymlinkChainLocator(logger *logrus.Logger, root string) Locator { // NewSymlinkLocator creats a locator that can be used for locating files through symlinks. // A logger can also be specified. func NewSymlinkLocator(logger *logrus.Logger, root string) Locator { + f := newFileLocator(WithLogger(logger), WithRoot(root)) l := symlink{ - file: newFileLocator(logger, root), + file: *f, } return &l diff --git a/internal/modifier/tegra.go b/internal/modifier/tegra.go index b6a7ef22..8ce590a8 100644 --- a/internal/modifier/tegra.go +++ b/internal/modifier/tegra.go @@ -33,7 +33,7 @@ func NewTegraPlatformFiles(logger *logrus.Logger) (oci.SpecModifier, error) { tegraSystemMounts := discover.NewMounts( logger, - lookup.NewFileLocator(logger, ""), + lookup.NewFileLocator(lookup.WithLogger(logger)), "", []string{ "/etc/nv_tegra_release",