windows.go 20 KB

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