windows.go 19 KB

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