@@ -31,6 +31,15 @@ import (
3131 "github.com/NVIDIA/nvidia-container-toolkit/internal/oci"
3232)
3333
34+ const (
35+ // ldsoconfdFilenamePattern specifies the pattern for the filename
36+ // in ld.so.conf.d that includes references to the specified directories.
37+ // The 00-nvcr prefix is chosen to ensure that these libraries have a
38+ // higher precedence than other libraries on the system, but lower than
39+ // the 00-cuda-compat that is included in some containers.
40+ ldsoconfdFilenamePattern = "00-nvcr-*.conf"
41+ )
42+
3443type command struct {
3544 logger logger.Interface
3645}
@@ -100,27 +109,29 @@ func (m command) run(c *cli.Context, cfg *options) error {
100109 return fmt .Errorf ("failed to load container state: %v" , err )
101110 }
102111
103- containerRoot , err := s .GetContainerRoot ()
112+ containerRootDir , err := s .GetContainerRoot ()
104113 if err != nil {
105114 return fmt .Errorf ("failed to determined container root: %v" , err )
106115 }
107116
108117 ldconfigPath := m .resolveLDConfigPath (cfg .ldconfigPath )
109118 args := []string {filepath .Base (ldconfigPath )}
110- if containerRoot != "" {
111- args = append (args , "-r" , containerRoot )
119+ if containerRootDir != "" {
120+ args = append (args , "-r" , containerRootDir )
112121 }
113122
114- if root (containerRoot ).hasPath ("/etc/ld.so.cache" ) {
123+ containerRoot := containerRoot (containerRootDir )
124+
125+ if containerRoot .hasPath ("/etc/ld.so.cache" ) {
115126 args = append (args , "-C" , "/etc/ld.so.cache" )
116127 } else {
117128 m .logger .Debugf ("No ld.so.cache found, skipping update" )
118129 args = append (args , "-N" )
119130 }
120131
121132 folders := cfg .folders .Value ()
122- if root ( containerRoot ) .hasPath ("/etc/ld.so.conf.d" ) {
123- err := m .createConfig (containerRoot , folders )
133+ if containerRoot .hasPath ("/etc/ld.so.conf.d" ) {
134+ err := m .createLdsoconfdFile (containerRoot , ldsoconfdFilenamePattern , folders ... )
124135 if err != nil {
125136 return fmt .Errorf ("failed to update ld.so.conf.d: %v" , err )
126137 }
@@ -136,61 +147,53 @@ func (m command) run(c *cli.Context, cfg *options) error {
136147 return syscall .Exec (ldconfigPath , args , nil )
137148}
138149
139- type root string
140-
141- func (r root ) hasPath (path string ) bool {
142- _ , err := os .Stat (filepath .Join (string (r ), path ))
143- if err != nil && os .IsNotExist (err ) {
144- return false
145- }
146- return true
147- }
148-
149150// resolveLDConfigPath determines the LDConfig path to use for the system.
150151// On systems such as Ubuntu where `/sbin/ldconfig` is a wrapper around
151152// /sbin/ldconfig.real, the latter is returned.
152153func (m command ) resolveLDConfigPath (path string ) string {
153154 return strings .TrimPrefix (config .NormalizeLDConfigPath ("@" + path ), "@" )
154155}
155156
156- // createConfig creates (or updates) /etc/ld.so.conf.d/00-nvcr-<RANDOM_STRING>.conf in the container
157- // to include the required paths.
158- // Note that the 00-nvcr prefix is chosen to ensure that these libraries have
159- // a higher precedence than other libraries on the system but are applied AFTER
160- // 00-cuda-compat.conf.
161- func (m command ) createConfig (root string , folders []string ) error {
162- if len (folders ) == 0 {
163- m .logger .Debugf ("No folders to add to /etc/ld.so.conf" )
157+ // createLdsoconfdFile creates a file at /etc/ld.so.conf.d/ in the specified root.
158+ // The file is created at /etc/ld.so.conf.d/{{ .pattern }} using `CreateTemp` and
159+ // contains the specified directories on each line.
160+ func (m command ) createLdsoconfdFile (in containerRoot , pattern string , dirs ... string ) error {
161+ if len (dirs ) == 0 {
162+ m .logger .Debugf ("No directories to add to /etc/ld.so.conf" )
164163 return nil
165164 }
166165
167- if err := os .MkdirAll (filepath .Join (root , "/etc/ld.so.conf.d" ), 0755 ); err != nil {
168- return fmt .Errorf ("failed to create ld.so.conf.d: %v" , err )
166+ ldsoconfdDir , err := in .resolve ("/etc/ld.so.conf.d" )
167+ if err != nil {
168+ return err
169+ }
170+ if err := os .MkdirAll (ldsoconfdDir , 0755 ); err != nil {
171+ return fmt .Errorf ("failed to create ld.so.conf.d: %w" , err )
169172 }
170173
171- configFile , err := os .CreateTemp (filepath . Join ( root , "/etc/ld.so.conf.d" ), "00-nvcr-*.conf" )
174+ configFile , err := os .CreateTemp (ldsoconfdDir , pattern )
172175 if err != nil {
173- return fmt .Errorf ("failed to create config file: %v " , err )
176+ return fmt .Errorf ("failed to create config file: %w " , err )
174177 }
175178 defer configFile .Close ()
176179
177- m .logger .Debugf ("Adding folders %v to %v" , folders , configFile .Name ())
180+ m .logger .Debugf ("Adding directories %v to %v" , dirs , configFile .Name ())
178181
179- configured := make (map [string ]bool )
180- for _ , folder := range folders {
181- if configured [ folder ] {
182+ added := make (map [string ]bool )
183+ for _ , dir := range dirs {
184+ if added [ dir ] {
182185 continue
183186 }
184- _ , err = configFile .WriteString (fmt .Sprintf ("%s\n " , folder ))
187+ _ , err = configFile .WriteString (fmt .Sprintf ("%s\n " , dir ))
185188 if err != nil {
186- return fmt .Errorf ("failed to update ld.so.conf.d : %v " , err )
189+ return fmt .Errorf ("failed to update config file : %w " , err )
187190 }
188- configured [ folder ] = true
191+ added [ dir ] = true
189192 }
190193
191194 // The created file needs to be world readable for the cases where the container is run as a non-root user.
192- if err := os .Chmod (configFile . Name (), 0644 ); err != nil {
193- return fmt .Errorf ("failed to chmod config file: %v " , err )
195+ if err := configFile .Chmod (0644 ); err != nil {
196+ return fmt .Errorf ("failed to chmod config file: %w " , err )
194197 }
195198
196199 return nil
0 commit comments