windows.go 23 KB

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