@@ -18,11 +18,15 @@ package mount
1818
1919import (
2020 "encoding/json"
21+ "io/ioutil"
22+ "os"
2123 "path/filepath"
2224 "strings"
25+ "syscall"
2326
2427 "github.com/Microsoft/hcsshim"
2528 "github.com/pkg/errors"
29+ "golang.org/x/sys/windows"
2630)
2731
2832var (
3135)
3236
3337// Mount to the provided target
34- func (m * Mount ) Mount (target string ) error {
38+ func (m * Mount ) Mount (target string ) ( retErr error ) {
3539 home , layerID := filepath .Split (m .Source )
3640
3741 parentLayerPaths , err := m .GetParentPaths ()
@@ -47,14 +51,67 @@ func (m *Mount) Mount(target string) error {
4751 return errors .Wrapf (err , "failed to activate layer %s" , m .Source )
4852 }
4953 defer func () {
50- if err != nil {
54+ if retErr != nil {
5155 hcsshim .DeactivateLayer (di , layerID )
5256 }
5357 }()
5458
5559 if err = hcsshim .PrepareLayer (di , layerID , parentLayerPaths ); err != nil {
5660 return errors .Wrapf (err , "failed to prepare layer %s" , m .Source )
5761 }
62+ layerPath , err := hcsshim .GetLayerMountPath (di , layerID )
63+ if err != nil {
64+ return errors .Wrapf (err , "failed to get mount path for layer %s" , m .Source )
65+ }
66+
67+ if ! strings .HasPrefix (layerPath , "\\ \\ ?\\ " ) {
68+ layerPath = filepath .Join (layerPath , "Files" )
69+ if _ , err := os .Lstat (layerPath ); err != nil {
70+ if ! os .IsNotExist (err ) {
71+ return errors .Wrapf (err , "failed to find Files dir" )
72+ }
73+ if err := os .Mkdir (layerPath , 0755 ); err != nil {
74+ return errors .Wrap (err , "failed to create Files dir" )
75+ }
76+ }
77+ if err := os .Remove (target ); err != nil {
78+ return errors .Wrapf (err , "remove target prior to mounting %q" , target )
79+ }
80+ if err := os .Symlink (layerPath , target ); err != nil {
81+ return errors .Wrapf (err , "failed to mount layer %q at %q" , m .Source , target )
82+ }
83+ } else {
84+ target = filepath .Clean (target ) + string (filepath .Separator )
85+ targetp , err := syscall .UTF16PtrFromString (target )
86+ if err != nil {
87+ return err
88+ }
89+
90+ volName := filepath .Clean (layerPath ) + string (filepath .Separator )
91+ volNamep , err := syscall .UTF16PtrFromString (volName )
92+ if err != nil {
93+ return err
94+ }
95+
96+ if err := windows .SetVolumeMountPoint (targetp , volNamep ); err != nil {
97+ return errors .Wrapf (err , "failed to mount layer %q at %q, volume: %q" , m .Source , target , volName )
98+ }
99+ }
100+
101+ for strings .HasSuffix (target , string (os .PathSeparator )) {
102+ target = target [:len (target )- 1 ]
103+ }
104+
105+ idf , err := os .Create (target + ":layerid" )
106+ if err != nil {
107+ return err
108+ }
109+ defer idf .Close ()
110+
111+ _ , err = idf .Write ([]byte (m .Source ))
112+ if err != nil {
113+ return err
114+ }
58115 return nil
59116}
60117
@@ -78,13 +135,48 @@ func (m *Mount) GetParentPaths() ([]string, error) {
78135
79136// Unmount the mount at the provided path
80137func Unmount (mount string , flags int ) error {
138+ fi , err := os .Lstat (mount )
139+ if err != nil {
140+ return errors .Wrapf (err , "unable to find mounted volume %s" , mount )
141+ }
142+
143+ layerPathb , err := ioutil .ReadFile (mount + ":layerid" )
144+ if err != nil {
145+ return err
146+ }
147+ layerPath := string (layerPathb )
148+
81149 var (
82- home , layerID = filepath .Split (mount )
150+ home , layerID = filepath .Split (layerPath )
83151 di = hcsshim.DriverInfo {
84152 HomeDir : home ,
85153 }
86154 )
87155
156+ if fi .Mode ()& os .ModeSymlink != 0 {
157+ if err := os .Remove (mount ); err != nil {
158+ return errors .Wrap (err , "failed to delete mount" )
159+ }
160+ } else {
161+ mount = filepath .Clean (mount ) + string (filepath .Separator )
162+ mountp , err := syscall .UTF16PtrFromString (mount )
163+ if err != nil {
164+ return err
165+ }
166+
167+ const volumeNameLen = 50
168+ volumeNamep := make ([]uint16 , volumeNameLen )
169+ volumeNamep [0 ] = 0
170+
171+ if err := windows .GetVolumeNameForVolumeMountPoint (mountp , & volumeNamep [0 ], volumeNameLen ); err != nil {
172+ return errors .Wrapf (err , "unable to find mounted volume %s" , mount )
173+ }
174+
175+ if err := windows .DeleteVolumeMountPoint (& volumeNamep [0 ]); err != nil {
176+ return errors .Wrapf (err , "unable to delete mounted volume %s" , mount )
177+ }
178+ }
179+
88180 if err := hcsshim .UnprepareLayer (di , layerID ); err != nil {
89181 return errors .Wrapf (err , "failed to unprepare layer %s" , mount )
90182 }
0 commit comments