| 111 | } |
| 112 | |
| 113 | func remount(m mounter, src, dest, libDir string, libsSymlinks map[string][]string) error { |
| 114 | stat, err := m.Stat(src) |
| 115 | if err != nil { |
| 116 | return fmt.Errorf("stat %s: %w", src, err) |
| 117 | } |
| 118 | |
| 119 | var destDir string |
| 120 | if stat.IsDir() { |
| 121 | destDir = dest |
| 122 | } else { |
| 123 | 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 | } |
| 129 | } |
| 130 | |
| 131 | if err := m.MkdirAll(destDir, 0o750); err != nil { |
| 132 | return fmt.Errorf("ensure path: %w", err) |
| 133 | } |
| 134 | |
| 135 | if !stat.IsDir() { |
| 136 | f, err := m.OpenFile(dest, os.O_CREATE, 0o640) |
| 137 | if err != nil { |
| 138 | return fmt.Errorf("ensure file path: %w", err) |
| 139 | } |
| 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 | } |
| 149 | } |
| 150 | |
| 151 | if err := m.Mount(src, dest, "bind", syscall.MS_BIND, ""); err != nil { |
| 152 | return fmt.Errorf("bind mount %s => %s: %w", src, dest, err) |
| 153 | } |
| 154 | |
| 155 | if err := m.Unmount(src, 0); err != nil { |
| 156 | return fmt.Errorf("unmount orig src %s: %w", src, err) |
| 157 | } |
| 158 | return nil |
| 159 | } |
| 160 | |
| 161 | // mounter is an interface to system-level calls used by TempRemount. |
| 162 | type mounter interface { |