windows.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813
  1. //+build windows
  2. package windows
  3. import (
  4. "bufio"
  5. "bytes"
  6. "encoding/json"
  7. "errors"
  8. "fmt"
  9. "io"
  10. "io/ioutil"
  11. "os"
  12. "path"
  13. "path/filepath"
  14. "strconv"
  15. "strings"
  16. "sync"
  17. "syscall"
  18. "unsafe"
  19. "github.com/Microsoft/go-winio"
  20. "github.com/Microsoft/go-winio/archive/tar"
  21. "github.com/Microsoft/go-winio/backuptar"
  22. "github.com/Microsoft/hcsshim"
  23. "github.com/Sirupsen/logrus"
  24. "github.com/docker/docker/daemon/graphdriver"
  25. "github.com/docker/docker/pkg/archive"
  26. "github.com/docker/docker/pkg/idtools"
  27. "github.com/docker/docker/pkg/ioutils"
  28. "github.com/docker/docker/pkg/longpath"
  29. "github.com/docker/docker/pkg/reexec"
  30. "github.com/docker/go-units"
  31. "github.com/vbatts/tar-split/tar/storage"
  32. )
  33. // filterDriver is an HCSShim driver type for the Windows Filter driver.
  34. const filterDriver = 1
  35. var (
  36. vmcomputedll = syscall.NewLazyDLL("vmcompute.dll")
  37. hcsExpandSandboxSize = vmcomputedll.NewProc("ExpandSandboxSize")
  38. hcsSandboxSizeSupported = hcsExpandSandboxSize.Find() == nil
  39. )
  40. // init registers the windows graph drivers to the register.
  41. func init() {
  42. graphdriver.Register("windowsfilter", InitFilter)
  43. reexec.Register("docker-windows-write-layer", writeLayer)
  44. }
  45. type checker struct {
  46. }
  47. func (c *checker) IsMounted(path string) bool {
  48. return false
  49. }
  50. // Driver represents a windows graph driver.
  51. type Driver struct {
  52. // info stores the shim driver information
  53. info hcsshim.DriverInfo
  54. ctr *graphdriver.RefCounter
  55. // it is safe for windows to use a cache here because it does not support
  56. // restoring containers when the daemon dies.
  57. cacheMu sync.Mutex
  58. cache map[string]string
  59. }
  60. // InitFilter returns a new Windows storage filter driver.
  61. func InitFilter(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) {
  62. logrus.Debugf("WindowsGraphDriver InitFilter at %s", home)
  63. fsType, err := getFileSystemType(string(home[0]))
  64. if err != nil {
  65. return nil, err
  66. }
  67. if strings.ToLower(fsType) == "refs" {
  68. return nil, fmt.Errorf("%s is on an ReFS volume - ReFS volumes are not supported", home)
  69. }
  70. d := &Driver{
  71. info: hcsshim.DriverInfo{
  72. HomeDir: home,
  73. Flavour: filterDriver,
  74. },
  75. cache: make(map[string]string),
  76. ctr: graphdriver.NewRefCounter(&checker{}),
  77. }
  78. return d, nil
  79. }
  80. // win32FromHresult is a helper function to get the win32 error code from an HRESULT
  81. func win32FromHresult(hr uintptr) uintptr {
  82. if hr&0x1fff0000 == 0x00070000 {
  83. return hr & 0xffff
  84. }
  85. return hr
  86. }
  87. // getFileSystemType obtains the type of a file system through GetVolumeInformation
  88. // https://msdn.microsoft.com/en-us/library/windows/desktop/aa364993(v=vs.85).aspx
  89. func getFileSystemType(drive string) (fsType string, hr error) {
  90. var (
  91. modkernel32 = syscall.NewLazyDLL("kernel32.dll")
  92. procGetVolumeInformation = modkernel32.NewProc("GetVolumeInformationW")
  93. buf = make([]uint16, 255)
  94. size = syscall.MAX_PATH + 1
  95. )
  96. if len(drive) != 1 {
  97. hr = errors.New("getFileSystemType must be called with a drive letter")
  98. return
  99. }
  100. drive += `:\`
  101. n := uintptr(unsafe.Pointer(nil))
  102. r0, _, _ := syscall.Syscall9(procGetVolumeInformation.Addr(), 8, uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(drive))), n, n, n, n, n, uintptr(unsafe.Pointer(&buf[0])), uintptr(size), 0)
  103. if int32(r0) < 0 {
  104. hr = syscall.Errno(win32FromHresult(r0))
  105. }
  106. fsType = syscall.UTF16ToString(buf)
  107. return
  108. }
  109. // String returns the string representation of a driver. This should match
  110. // the name the graph driver has been registered with.
  111. func (d *Driver) String() string {
  112. return "windowsfilter"
  113. }
  114. // Status returns the status of the driver.
  115. func (d *Driver) Status() [][2]string {
  116. return [][2]string{
  117. {"Windows", ""},
  118. }
  119. }
  120. // Exists returns true if the given id is registered with this driver.
  121. func (d *Driver) Exists(id string) bool {
  122. rID, err := d.resolveID(id)
  123. if err != nil {
  124. return false
  125. }
  126. result, err := hcsshim.LayerExists(d.info, rID)
  127. if err != nil {
  128. return false
  129. }
  130. return result
  131. }
  132. // CreateReadWrite creates a layer that is writable for use as a container
  133. // file system.
  134. func (d *Driver) CreateReadWrite(id, parent, mountLabel string, storageOpt map[string]string) error {
  135. return d.create(id, parent, mountLabel, false, storageOpt)
  136. }
  137. // Create creates a new read-only layer with the given id.
  138. func (d *Driver) Create(id, parent, mountLabel string, storageOpt map[string]string) error {
  139. return d.create(id, parent, mountLabel, true, storageOpt)
  140. }
  141. func (d *Driver) create(id, parent, mountLabel string, readOnly bool, storageOpt map[string]string) error {
  142. rPId, err := d.resolveID(parent)
  143. if err != nil {
  144. return err
  145. }
  146. parentChain, err := d.getLayerChain(rPId)
  147. if err != nil {
  148. return err
  149. }
  150. var layerChain []string
  151. if rPId != "" {
  152. parentPath, err := hcsshim.GetLayerMountPath(d.info, rPId)
  153. if err != nil {
  154. return err
  155. }
  156. if _, err := os.Stat(filepath.Join(parentPath, "Files")); err == nil {
  157. // This is a legitimate parent layer (not the empty "-init" layer),
  158. // so include it in the layer chain.
  159. layerChain = []string{parentPath}
  160. }
  161. }
  162. layerChain = append(layerChain, parentChain...)
  163. if readOnly {
  164. if err := hcsshim.CreateLayer(d.info, id, rPId); err != nil {
  165. return err
  166. }
  167. } else {
  168. var parentPath string
  169. if len(layerChain) != 0 {
  170. parentPath = layerChain[0]
  171. }
  172. if err := hcsshim.CreateSandboxLayer(d.info, id, parentPath, layerChain); err != nil {
  173. return err
  174. }
  175. storageOptions, err := parseStorageOpt(storageOpt)
  176. if err != nil {
  177. return fmt.Errorf("Failed to parse storage options - %s", err)
  178. }
  179. if hcsSandboxSizeSupported {
  180. if err := hcsshim.ExpandSandboxSize(d.info, id, storageOptions.size); err != nil {
  181. return err
  182. }
  183. }
  184. }
  185. if _, err := os.Lstat(d.dir(parent)); err != nil {
  186. if err2 := hcsshim.DestroyLayer(d.info, id); err2 != nil {
  187. logrus.Warnf("Failed to DestroyLayer %s: %s", id, err2)
  188. }
  189. return fmt.Errorf("Cannot create layer with missing parent %s: %s", parent, err)
  190. }
  191. if err := d.setLayerChain(id, layerChain); err != nil {
  192. if err2 := hcsshim.DestroyLayer(d.info, id); err2 != nil {
  193. logrus.Warnf("Failed to DestroyLayer %s: %s", id, err2)
  194. }
  195. return err
  196. }
  197. return nil
  198. }
  199. // dir returns the absolute path to the layer.
  200. func (d *Driver) dir(id string) string {
  201. return filepath.Join(d.info.HomeDir, filepath.Base(id))
  202. }
  203. // Remove unmounts and removes the dir information.
  204. func (d *Driver) Remove(id string) error {
  205. rID, err := d.resolveID(id)
  206. if err != nil {
  207. return err
  208. }
  209. os.RemoveAll(filepath.Join(d.info.HomeDir, "sysfile-backups", rID)) // ok to fail
  210. return hcsshim.DestroyLayer(d.info, rID)
  211. }
  212. // Get returns the rootfs path for the id. This will mount the dir at its given path.
  213. func (d *Driver) Get(id, mountLabel string) (string, error) {
  214. logrus.Debugf("WindowsGraphDriver Get() id %s mountLabel %s", id, mountLabel)
  215. var dir string
  216. rID, err := d.resolveID(id)
  217. if err != nil {
  218. return "", err
  219. }
  220. if count := d.ctr.Increment(rID); count > 1 {
  221. return d.cache[rID], nil
  222. }
  223. // Getting the layer paths must be done outside of the lock.
  224. layerChain, err := d.getLayerChain(rID)
  225. if err != nil {
  226. d.ctr.Decrement(rID)
  227. return "", err
  228. }
  229. if err := hcsshim.ActivateLayer(d.info, rID); err != nil {
  230. d.ctr.Decrement(rID)
  231. return "", err
  232. }
  233. if err := hcsshim.PrepareLayer(d.info, rID, layerChain); err != nil {
  234. d.ctr.Decrement(rID)
  235. if err2 := hcsshim.DeactivateLayer(d.info, rID); err2 != nil {
  236. logrus.Warnf("Failed to Deactivate %s: %s", id, err)
  237. }
  238. return "", err
  239. }
  240. mountPath, err := hcsshim.GetLayerMountPath(d.info, rID)
  241. if err != nil {
  242. d.ctr.Decrement(rID)
  243. if err2 := hcsshim.DeactivateLayer(d.info, rID); err2 != nil {
  244. logrus.Warnf("Failed to Deactivate %s: %s", id, err)
  245. }
  246. return "", err
  247. }
  248. d.cacheMu.Lock()
  249. d.cache[rID] = mountPath
  250. d.cacheMu.Unlock()
  251. // If the layer has a mount path, use that. Otherwise, use the
  252. // folder path.
  253. if mountPath != "" {
  254. dir = mountPath
  255. } else {
  256. dir = d.dir(id)
  257. }
  258. return dir, nil
  259. }
  260. // Put adds a new layer to the driver.
  261. func (d *Driver) Put(id string) error {
  262. logrus.Debugf("WindowsGraphDriver Put() id %s", id)
  263. rID, err := d.resolveID(id)
  264. if err != nil {
  265. return err
  266. }
  267. if count := d.ctr.Decrement(rID); count > 0 {
  268. return nil
  269. }
  270. d.cacheMu.Lock()
  271. delete(d.cache, rID)
  272. d.cacheMu.Unlock()
  273. if err := hcsshim.UnprepareLayer(d.info, rID); err != nil {
  274. return err
  275. }
  276. return hcsshim.DeactivateLayer(d.info, rID)
  277. }
  278. // Cleanup ensures the information the driver stores is properly removed.
  279. func (d *Driver) Cleanup() error {
  280. return nil
  281. }
  282. // Diff produces an archive of the changes between the specified
  283. // layer and its parent layer which may be "".
  284. // The layer should be mounted when calling this function
  285. func (d *Driver) Diff(id, parent string) (_ archive.Archive, err error) {
  286. rID, err := d.resolveID(id)
  287. if err != nil {
  288. return
  289. }
  290. layerChain, err := d.getLayerChain(rID)
  291. if err != nil {
  292. return
  293. }
  294. // this is assuming that the layer is unmounted
  295. if err := hcsshim.UnprepareLayer(d.info, rID); err != nil {
  296. return nil, err
  297. }
  298. prepare := func() {
  299. if err := hcsshim.PrepareLayer(d.info, rID, layerChain); err != nil {
  300. logrus.Warnf("Failed to Deactivate %s: %s", rID, err)
  301. }
  302. }
  303. arch, err := d.exportLayer(rID, layerChain)
  304. if err != nil {
  305. prepare()
  306. return
  307. }
  308. return ioutils.NewReadCloserWrapper(arch, func() error {
  309. err := arch.Close()
  310. prepare()
  311. return err
  312. }), nil
  313. }
  314. // Changes produces a list of changes between the specified layer
  315. // and its parent layer. If parent is "", then all changes will be ADD changes.
  316. // The layer should be mounted when calling this function
  317. func (d *Driver) Changes(id, parent string) ([]archive.Change, error) {
  318. rID, err := d.resolveID(id)
  319. if err != nil {
  320. return nil, err
  321. }
  322. parentChain, err := d.getLayerChain(rID)
  323. if err != nil {
  324. return nil, err
  325. }
  326. // this is assuming that the layer is unmounted
  327. if err := hcsshim.UnprepareLayer(d.info, rID); err != nil {
  328. return nil, err
  329. }
  330. defer func() {
  331. if err := hcsshim.PrepareLayer(d.info, rID, parentChain); err != nil {
  332. logrus.Warnf("Failed to Deactivate %s: %s", rID, err)
  333. }
  334. }()
  335. var changes []archive.Change
  336. err = winio.RunWithPrivilege(winio.SeBackupPrivilege, func() error {
  337. r, err := hcsshim.NewLayerReader(d.info, id, parentChain)
  338. if err != nil {
  339. return err
  340. }
  341. defer r.Close()
  342. for {
  343. name, _, fileInfo, err := r.Next()
  344. if err == io.EOF {
  345. return nil
  346. }
  347. if err != nil {
  348. return err
  349. }
  350. name = filepath.ToSlash(name)
  351. if fileInfo == nil {
  352. changes = append(changes, archive.Change{Path: name, Kind: archive.ChangeDelete})
  353. } else {
  354. // Currently there is no way to tell between an add and a modify.
  355. changes = append(changes, archive.Change{Path: name, Kind: archive.ChangeModify})
  356. }
  357. }
  358. })
  359. if err != nil {
  360. return nil, err
  361. }
  362. return changes, nil
  363. }
  364. // ApplyDiff extracts the changeset from the given diff into the
  365. // layer with the specified id and parent, returning the size of the
  366. // new layer in bytes.
  367. // The layer should not be mounted when calling this function
  368. func (d *Driver) ApplyDiff(id, parent string, diff archive.Reader) (int64, error) {
  369. var layerChain []string
  370. if parent != "" {
  371. rPId, err := d.resolveID(parent)
  372. if err != nil {
  373. return 0, err
  374. }
  375. parentChain, err := d.getLayerChain(rPId)
  376. if err != nil {
  377. return 0, err
  378. }
  379. parentPath, err := hcsshim.GetLayerMountPath(d.info, rPId)
  380. if err != nil {
  381. return 0, err
  382. }
  383. layerChain = append(layerChain, parentPath)
  384. layerChain = append(layerChain, parentChain...)
  385. }
  386. size, err := d.importLayer(id, diff, layerChain)
  387. if err != nil {
  388. return 0, err
  389. }
  390. if err = d.setLayerChain(id, layerChain); err != nil {
  391. return 0, err
  392. }
  393. return size, nil
  394. }
  395. // DiffSize calculates the changes between the specified layer
  396. // and its parent and returns the size in bytes of the changes
  397. // relative to its base filesystem directory.
  398. func (d *Driver) DiffSize(id, parent string) (size int64, err error) {
  399. rPId, err := d.resolveID(parent)
  400. if err != nil {
  401. return
  402. }
  403. changes, err := d.Changes(id, rPId)
  404. if err != nil {
  405. return
  406. }
  407. layerFs, err := d.Get(id, "")
  408. if err != nil {
  409. return
  410. }
  411. defer d.Put(id)
  412. return archive.ChangesSize(layerFs, changes), nil
  413. }
  414. // GetMetadata returns custom driver information.
  415. func (d *Driver) GetMetadata(id string) (map[string]string, error) {
  416. m := make(map[string]string)
  417. m["dir"] = d.dir(id)
  418. return m, nil
  419. }
  420. func writeTarFromLayer(r hcsshim.LayerReader, w io.Writer) error {
  421. t := tar.NewWriter(w)
  422. for {
  423. name, size, fileInfo, err := r.Next()
  424. if err == io.EOF {
  425. break
  426. }
  427. if err != nil {
  428. return err
  429. }
  430. if fileInfo == nil {
  431. // Write a whiteout file.
  432. hdr := &tar.Header{
  433. Name: filepath.ToSlash(filepath.Join(filepath.Dir(name), archive.WhiteoutPrefix+filepath.Base(name))),
  434. }
  435. err := t.WriteHeader(hdr)
  436. if err != nil {
  437. return err
  438. }
  439. } else {
  440. err = backuptar.WriteTarFileFromBackupStream(t, r, name, size, fileInfo)
  441. if err != nil {
  442. return err
  443. }
  444. }
  445. }
  446. return t.Close()
  447. }
  448. // exportLayer generates an archive from a layer based on the given ID.
  449. func (d *Driver) exportLayer(id string, parentLayerPaths []string) (archive.Archive, error) {
  450. archive, w := io.Pipe()
  451. go func() {
  452. err := winio.RunWithPrivilege(winio.SeBackupPrivilege, func() error {
  453. r, err := hcsshim.NewLayerReader(d.info, id, parentLayerPaths)
  454. if err != nil {
  455. return err
  456. }
  457. err = writeTarFromLayer(r, w)
  458. cerr := r.Close()
  459. if err == nil {
  460. err = cerr
  461. }
  462. return err
  463. })
  464. w.CloseWithError(err)
  465. }()
  466. return archive, nil
  467. }
  468. func writeLayerFromTar(r archive.Reader, w hcsshim.LayerWriter) (int64, error) {
  469. t := tar.NewReader(r)
  470. hdr, err := t.Next()
  471. totalSize := int64(0)
  472. buf := bufio.NewWriter(nil)
  473. for err == nil {
  474. base := path.Base(hdr.Name)
  475. if strings.HasPrefix(base, archive.WhiteoutPrefix) {
  476. name := path.Join(path.Dir(hdr.Name), base[len(archive.WhiteoutPrefix):])
  477. err = w.Remove(filepath.FromSlash(name))
  478. if err != nil {
  479. return 0, err
  480. }
  481. hdr, err = t.Next()
  482. } else if hdr.Typeflag == tar.TypeLink {
  483. err = w.AddLink(filepath.FromSlash(hdr.Name), filepath.FromSlash(hdr.Linkname))
  484. if err != nil {
  485. return 0, err
  486. }
  487. hdr, err = t.Next()
  488. } else {
  489. var (
  490. name string
  491. size int64
  492. fileInfo *winio.FileBasicInfo
  493. )
  494. name, size, fileInfo, err = backuptar.FileInfoFromHeader(hdr)
  495. if err != nil {
  496. return 0, err
  497. }
  498. err = w.Add(filepath.FromSlash(name), fileInfo)
  499. if err != nil {
  500. return 0, err
  501. }
  502. buf.Reset(w)
  503. hdr, err = backuptar.WriteBackupStreamFromTarFile(buf, t, hdr)
  504. ferr := buf.Flush()
  505. if ferr != nil {
  506. err = ferr
  507. }
  508. totalSize += size
  509. }
  510. }
  511. if err != io.EOF {
  512. return 0, err
  513. }
  514. return totalSize, nil
  515. }
  516. func addAceToSddlDacl(sddl, ace string) (string, bool) {
  517. daclStart := strings.Index(sddl, "D:")
  518. if daclStart < 0 {
  519. return sddl, false
  520. }
  521. dacl := sddl[daclStart:]
  522. daclEnd := strings.Index(dacl, "S:")
  523. if daclEnd < 0 {
  524. daclEnd = len(dacl)
  525. }
  526. dacl = dacl[:daclEnd]
  527. if strings.Contains(dacl, ace) {
  528. return sddl, true
  529. }
  530. i := 2
  531. for i+1 < len(dacl) {
  532. if dacl[i] != '(' {
  533. return sddl, false
  534. }
  535. if dacl[i+1] == 'A' {
  536. break
  537. }
  538. i += 2
  539. for p := 1; i < len(dacl) && p > 0; i++ {
  540. if dacl[i] == '(' {
  541. p++
  542. } else if dacl[i] == ')' {
  543. p--
  544. }
  545. }
  546. }
  547. return sddl[:daclStart+i] + ace + sddl[daclStart+i:], true
  548. }
  549. // importLayer adds a new layer to the tag and graph store based on the given data.
  550. func (d *Driver) importLayer(id string, layerData archive.Reader, parentLayerPaths []string) (size int64, err error) {
  551. cmd := reexec.Command(append([]string{"docker-windows-write-layer", d.info.HomeDir, id}, parentLayerPaths...)...)
  552. output := bytes.NewBuffer(nil)
  553. cmd.Stdin = layerData
  554. cmd.Stdout = output
  555. cmd.Stderr = output
  556. if err = cmd.Start(); err != nil {
  557. return
  558. }
  559. if err = cmd.Wait(); err != nil {
  560. return 0, fmt.Errorf("re-exec error: %v: output: %s", err, output)
  561. }
  562. return strconv.ParseInt(output.String(), 10, 64)
  563. }
  564. // writeLayer is the re-exec entry point for writing a layer from a tar file
  565. func writeLayer() {
  566. home := os.Args[1]
  567. id := os.Args[2]
  568. parentLayerPaths := os.Args[3:]
  569. err := func() error {
  570. err := winio.EnableProcessPrivileges([]string{winio.SeBackupPrivilege, winio.SeRestorePrivilege})
  571. if err != nil {
  572. return err
  573. }
  574. info := hcsshim.DriverInfo{
  575. Flavour: filterDriver,
  576. HomeDir: home,
  577. }
  578. w, err := hcsshim.NewLayerWriter(info, id, parentLayerPaths)
  579. if err != nil {
  580. return err
  581. }
  582. size, err := writeLayerFromTar(os.Stdin, w)
  583. if err != nil {
  584. return err
  585. }
  586. err = w.Close()
  587. if err != nil {
  588. return err
  589. }
  590. fmt.Fprint(os.Stdout, size)
  591. return nil
  592. }()
  593. if err != nil {
  594. fmt.Fprint(os.Stderr, err)
  595. os.Exit(1)
  596. }
  597. }
  598. // resolveID computes the layerID information based on the given id.
  599. func (d *Driver) resolveID(id string) (string, error) {
  600. content, err := ioutil.ReadFile(filepath.Join(d.dir(id), "layerID"))
  601. if os.IsNotExist(err) {
  602. return id, nil
  603. } else if err != nil {
  604. return "", err
  605. }
  606. return string(content), nil
  607. }
  608. // setID stores the layerId in disk.
  609. func (d *Driver) setID(id, altID string) error {
  610. err := ioutil.WriteFile(filepath.Join(d.dir(id), "layerId"), []byte(altID), 0600)
  611. if err != nil {
  612. return err
  613. }
  614. return nil
  615. }
  616. // getLayerChain returns the layer chain information.
  617. func (d *Driver) getLayerChain(id string) ([]string, error) {
  618. jPath := filepath.Join(d.dir(id), "layerchain.json")
  619. content, err := ioutil.ReadFile(jPath)
  620. if os.IsNotExist(err) {
  621. return nil, nil
  622. } else if err != nil {
  623. return nil, fmt.Errorf("Unable to read layerchain file - %s", err)
  624. }
  625. var layerChain []string
  626. err = json.Unmarshal(content, &layerChain)
  627. if err != nil {
  628. return nil, fmt.Errorf("Failed to unmarshall layerchain json - %s", err)
  629. }
  630. return layerChain, nil
  631. }
  632. // setLayerChain stores the layer chain information in disk.
  633. func (d *Driver) setLayerChain(id string, chain []string) error {
  634. content, err := json.Marshal(&chain)
  635. if err != nil {
  636. return fmt.Errorf("Failed to marshall layerchain json - %s", err)
  637. }
  638. jPath := filepath.Join(d.dir(id), "layerchain.json")
  639. err = ioutil.WriteFile(jPath, content, 0600)
  640. if err != nil {
  641. return fmt.Errorf("Unable to write layerchain file - %s", err)
  642. }
  643. return nil
  644. }
  645. type fileGetCloserWithBackupPrivileges struct {
  646. path string
  647. }
  648. func (fg *fileGetCloserWithBackupPrivileges) Get(filename string) (io.ReadCloser, error) {
  649. var f *os.File
  650. // Open the file while holding the Windows backup privilege. This ensures that the
  651. // file can be opened even if the caller does not actually have access to it according
  652. // to the security descriptor.
  653. err := winio.RunWithPrivilege(winio.SeBackupPrivilege, func() error {
  654. path := longpath.AddPrefix(filepath.Join(fg.path, filename))
  655. p, err := syscall.UTF16FromString(path)
  656. if err != nil {
  657. return err
  658. }
  659. h, err := syscall.CreateFile(&p[0], syscall.GENERIC_READ, syscall.FILE_SHARE_READ, nil, syscall.OPEN_EXISTING, syscall.FILE_FLAG_BACKUP_SEMANTICS, 0)
  660. if err != nil {
  661. return &os.PathError{Op: "open", Path: path, Err: err}
  662. }
  663. f = os.NewFile(uintptr(h), path)
  664. return nil
  665. })
  666. return f, err
  667. }
  668. func (fg *fileGetCloserWithBackupPrivileges) Close() error {
  669. return nil
  670. }
  671. type fileGetDestroyCloser struct {
  672. storage.FileGetter
  673. path string
  674. }
  675. func (f *fileGetDestroyCloser) Close() error {
  676. // TODO: activate layers and release here?
  677. return os.RemoveAll(f.path)
  678. }
  679. // DiffGetter returns a FileGetCloser that can read files from the directory that
  680. // contains files for the layer differences. Used for direct access for tar-split.
  681. func (d *Driver) DiffGetter(id string) (graphdriver.FileGetCloser, error) {
  682. id, err := d.resolveID(id)
  683. if err != nil {
  684. return nil, err
  685. }
  686. return &fileGetCloserWithBackupPrivileges{d.dir(id)}, nil
  687. }
  688. type storageOptions struct {
  689. size uint64
  690. }
  691. func parseStorageOpt(storageOpt map[string]string) (*storageOptions, error) {
  692. options := storageOptions{}
  693. // Read size to change the block device size per container.
  694. for key, val := range storageOpt {
  695. key := strings.ToLower(key)
  696. switch key {
  697. case "size":
  698. size, err := units.RAMInBytes(val)
  699. if err != nil {
  700. return nil, err
  701. }
  702. options.size = uint64(size)
  703. default:
  704. return nil, fmt.Errorf("Unknown storage option: %s", key)
  705. }
  706. }
  707. return &options, nil
  708. }