11package ebutil
22
33import (
4+ "errors"
45 "fmt"
56 "os"
67 "path/filepath"
@@ -44,15 +45,36 @@ func tempRemount(m mounter, logf func(notcodersdk.LogLevel, string, ...any), bas
4445 return func () error { return nil }, fmt .Errorf ("get mounts: %w" , err )
4546 }
4647
48+ libDir , err := libraryDirectoryPath (m )
49+ if err != nil {
50+ return func () error { return nil }, fmt .Errorf ("get lib directory: %w" , err )
51+ }
52+
53+ libsSymlinks , err := libraryDirectorySymlinks (m , libDir )
54+ if err != nil && ! errors .Is (err , os .ErrNotExist ) {
55+ return func () error { return nil }, fmt .Errorf ("read lib symlinks: %w" , err )
56+ }
57+
4758 // temp move of all ro mounts
4859 mounts := map [string ]string {}
4960 var restoreOnce sync.Once
5061 var merr error
5162 // closer to attempt to restore original mount points
5263 restore = func () error {
5364 restoreOnce .Do (func () {
65+ if len (mounts ) == 0 {
66+ return
67+ }
68+
69+ newLibDir , err := libraryDirectoryPath (m )
70+ if err != nil {
71+ merr = multierror .Append (merr , fmt .Errorf ("get new lib directory: %w" , err ))
72+ return
73+ }
74+
5475 for orig , moved := range mounts {
55- if err := remount (m , moved , orig ); err != nil {
76+ logf (notcodersdk .LogLevelTrace , "restore mount %s" , orig )
77+ if err := remount (m , moved , orig , newLibDir , libsSymlinks ); err != nil {
5678 merr = multierror .Append (merr , fmt .Errorf ("restore mount: %w" , err ))
5779 }
5880 }
7799
78100 src := mountInfo .MountPoint
79101 dest := filepath .Join (base , src )
80- if err := remount (m , src , dest ); err != nil {
102+ logf (notcodersdk .LogLevelTrace , "temp remount %s" , src )
103+ if err := remount (m , src , dest , libDir , libsSymlinks ); err != nil {
81104 return restore , fmt .Errorf ("temp remount: %w" , err )
82105 }
83106
@@ -87,30 +110,48 @@ outer:
87110 return restore , nil
88111}
89112
90- func remount (m mounter , src , dest string ) error {
113+ func remount (m mounter , src , dest , libDir string , libsSymlinks map [ string ][] string ) error {
91114 stat , err := m .Stat (src )
92115 if err != nil {
93116 return fmt .Errorf ("stat %s: %w" , src , err )
94117 }
118+
95119 var destDir string
96120 if stat .IsDir () {
97121 destDir = dest
98122 } else {
99123 destDir = filepath .Dir (dest )
124+ if destDir == usrLibDir || destDir == usrLibMultiarchDir {
125+ // Restore mount to libDir
126+ destDir = libDir
127+ dest = filepath .Join (destDir , stat .Name ())
128+ }
100129 }
130+
101131 if err := m .MkdirAll (destDir , 0o750 ); err != nil {
102132 return fmt .Errorf ("ensure path: %w" , err )
103133 }
134+
104135 if ! stat .IsDir () {
105136 f , err := m .OpenFile (dest , os .O_CREATE , 0o640 )
106137 if err != nil {
107138 return fmt .Errorf ("ensure file path: %w" , err )
108139 }
109- defer f .Close ()
140+ // This ensure the file is created, it will not be used. It can be closed immediately.
141+ f .Close ()
142+
143+ if symlinks , ok := libsSymlinks [stat .Name ()]; ok {
144+ srcDir := filepath .Dir (src )
145+ if err := moveLibSymlinks (m , symlinks , srcDir , destDir ); err != nil {
146+ return err
147+ }
148+ }
110149 }
150+
111151 if err := m .Mount (src , dest , "bind" , syscall .MS_BIND , "" ); err != nil {
112152 return fmt .Errorf ("bind mount %s => %s: %w" , src , dest , err )
113153 }
154+
114155 if err := m .Unmount (src , 0 ); err != nil {
115156 return fmt .Errorf ("unmount orig src %s: %w" , src , err )
116157 }
@@ -131,6 +172,12 @@ type mounter interface {
131172 Mount (string , string , string , uintptr , string ) error
132173 // Unmount wraps syscall.Unmount
133174 Unmount (string , int ) error
175+ // ReadDir wraps os.ReadDir
176+ ReadDir (string ) ([]os.DirEntry , error )
177+ // EvalSymlinks wraps filepath.EvalSymlinks
178+ EvalSymlinks (string ) (string , error )
179+ // Rename wraps os.Rename
180+ Rename (string , string ) error
134181}
135182
136183// realMounter implements mounter and actually does the thing.
@@ -161,3 +208,15 @@ func (m *realMounter) OpenFile(name string, flag int, perm os.FileMode) (*os.Fil
161208func (m * realMounter ) Stat (path string ) (os.FileInfo , error ) {
162209 return os .Stat (path )
163210}
211+
212+ func (m * realMounter ) ReadDir (name string ) ([]os.DirEntry , error ) {
213+ return os .ReadDir (name )
214+ }
215+
216+ func (m * realMounter ) EvalSymlinks (path string ) (string , error ) {
217+ return filepath .EvalSymlinks (path )
218+ }
219+
220+ func (m * realMounter ) Rename (oldpath , newpath string ) error {
221+ return os .Rename (oldpath , newpath )
222+ }
0 commit comments