-
Notifications
You must be signed in to change notification settings - Fork 285
Base layer manipulation #1637
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
helsaawy
merged 12 commits into
microsoft:main
from
gabriel-samfira:base-layer-manipulation-rebased
Feb 28, 2023
Merged
Base layer manipulation #1637
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
58c65b8
Simple baseLayerReader to export parentless layers
TBBle 2de2a5c
Introduce hcsshim.ConvertToBaseLayer
TBBle a24bcbc
Include hard-linked files as hard-links in the tarstream
TBBle 9e4cbf3
Use offline registry library to generate min hive
gabriel-samfira 9edb4c9
Rename ofreg.go and close key
gabriel-samfira 5181c44
Fix temp dir creation
gabriel-samfira 99c9146
Cleanup tests
gabriel-samfira 9bfb46a
Fix ORCloseHive definition
gabriel-samfira 077be0f
Remove unused ctx from baseLayerReader
gabriel-samfira e79beb3
Use string in sys definition and check for err
gabriel-samfira b2acd4e
Close the r.proceed channel
gabriel-samfira ee3a0ed
Return if backup reader is nil
gabriel-samfira File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| package main | ||
|
|
||
| import ( | ||
| "path/filepath" | ||
|
|
||
| "github.com/Microsoft/hcsshim" | ||
| "github.com/Microsoft/hcsshim/internal/appargs" | ||
| "github.com/urfave/cli" | ||
| ) | ||
|
|
||
| var makeBaseLayerCommand = cli.Command{ | ||
| Name: "makebaselayer", | ||
| Usage: "converts a directory containing 'Files/' into a base layer", | ||
| ArgsUsage: "<layer path>", | ||
| Before: appargs.Validate(appargs.NonEmptyString), | ||
| Action: func(context *cli.Context) error { | ||
| path, err := filepath.Abs(context.Args().First()) | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| return hcsshim.ConvertToBaseLayer(path) | ||
| }, | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,216 @@ | ||
| package wclayer | ||
|
|
||
| import ( | ||
| "errors" | ||
| "io" | ||
| "os" | ||
| "path/filepath" | ||
| "strings" | ||
| "syscall" | ||
|
|
||
| "github.com/Microsoft/go-winio" | ||
| "github.com/Microsoft/hcsshim/internal/longpath" | ||
| "github.com/Microsoft/hcsshim/internal/oc" | ||
| "go.opencensus.io/trace" | ||
| ) | ||
|
|
||
| type baseLayerReader struct { | ||
| s *trace.Span | ||
| root string | ||
| result chan *fileEntry | ||
| proceed chan bool | ||
| currentFile *os.File | ||
| backupReader *winio.BackupFileReader | ||
| } | ||
|
|
||
| func newBaseLayerReader(root string, s *trace.Span) (r *baseLayerReader) { | ||
| r = &baseLayerReader{ | ||
| s: s, | ||
| root: root, | ||
| result: make(chan *fileEntry), | ||
| proceed: make(chan bool), | ||
| } | ||
| go r.walk() | ||
| return r | ||
| } | ||
|
|
||
| func (r *baseLayerReader) walkUntilCancelled() error { | ||
| root, err := longpath.LongAbs(r.root) | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| r.root = root | ||
|
|
||
| err = filepath.Walk(filepath.Join(r.root, filesPath), func(path string, info os.FileInfo, err error) error { | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| // Indirect fix for https://github.com/moby/moby/issues/32838#issuecomment-343610048. | ||
| // Handle failure from what may be a golang bug in the conversion of | ||
| // UTF16 to UTF8 in files which are left in the recycle bin. Os.Lstat | ||
| // which is called by filepath.Walk will fail when a filename contains | ||
| // unicode characters. Skip the recycle bin regardless which is goodness. | ||
| if strings.EqualFold(path, filepath.Join(r.root, `Files\$Recycle.Bin`)) && info.IsDir() { | ||
| return filepath.SkipDir | ||
| } | ||
|
|
||
| r.result <- &fileEntry{path, info, nil} | ||
| if !<-r.proceed { | ||
| return errorIterationCanceled | ||
| } | ||
|
|
||
| return nil | ||
| }) | ||
|
|
||
| if err == errorIterationCanceled { | ||
| return nil | ||
| } | ||
|
|
||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| utilityVMAbsPath := filepath.Join(r.root, utilityVMPath) | ||
| utilityVMFilesAbsPath := filepath.Join(r.root, utilityVMFilesPath) | ||
|
|
||
| // Ignore a UtilityVM without Files, that's not _really_ a UtiltyVM | ||
| if _, err = os.Lstat(utilityVMFilesAbsPath); err != nil { | ||
| if os.IsNotExist(err) { | ||
| return io.EOF | ||
| } | ||
| return err | ||
| } | ||
|
|
||
| err = filepath.Walk(utilityVMAbsPath, func(path string, info os.FileInfo, err error) error { | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| if path != utilityVMAbsPath && path != utilityVMFilesAbsPath && !hasPathPrefix(path, utilityVMFilesAbsPath) { | ||
| if info.IsDir() { | ||
| return filepath.SkipDir | ||
| } | ||
| return nil | ||
| } | ||
|
|
||
| r.result <- &fileEntry{path, info, nil} | ||
| if !<-r.proceed { | ||
| return errorIterationCanceled | ||
| } | ||
|
|
||
| return nil | ||
| }) | ||
|
|
||
| if err == errorIterationCanceled { | ||
| return nil | ||
| } | ||
|
|
||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| return io.EOF | ||
| } | ||
|
|
||
| func (r *baseLayerReader) walk() { | ||
| defer close(r.result) | ||
| if !<-r.proceed { | ||
| return | ||
| } | ||
|
|
||
| err := r.walkUntilCancelled() | ||
| if err != nil { | ||
| for { | ||
| r.result <- &fileEntry{err: err} | ||
| if !<-r.proceed { | ||
| return | ||
| } | ||
|
helsaawy marked this conversation as resolved.
|
||
| } | ||
| } | ||
| } | ||
|
|
||
| func (r *baseLayerReader) reset() { | ||
| if r.backupReader != nil { | ||
| r.backupReader.Close() | ||
| r.backupReader = nil | ||
| } | ||
| if r.currentFile != nil { | ||
| r.currentFile.Close() | ||
| r.currentFile = nil | ||
| } | ||
| } | ||
|
|
||
| func (r *baseLayerReader) Next() (path string, size int64, fileInfo *winio.FileBasicInfo, err error) { | ||
| r.reset() | ||
| r.proceed <- true | ||
| fe := <-r.result | ||
| if fe == nil { | ||
| err = errors.New("BaseLayerReader closed") | ||
| return | ||
| } | ||
| if fe.err != nil { | ||
| err = fe.err | ||
| return | ||
| } | ||
|
|
||
| path, err = filepath.Rel(r.root, fe.path) | ||
| if err != nil { | ||
| return | ||
| } | ||
|
|
||
| f, err := openFileOrDir(fe.path, syscall.GENERIC_READ, syscall.OPEN_EXISTING) | ||
| if err != nil { | ||
| return | ||
| } | ||
| defer func() { | ||
| if f != nil { | ||
| f.Close() | ||
| } | ||
| }() | ||
|
|
||
| fileInfo, err = winio.GetFileBasicInfo(f) | ||
| if err != nil { | ||
| return | ||
| } | ||
|
|
||
| size = fe.fi.Size() | ||
| r.backupReader = winio.NewBackupFileReader(f, true) | ||
|
|
||
| r.currentFile = f | ||
| f = nil | ||
| return | ||
| } | ||
|
|
||
| func (r *baseLayerReader) LinkInfo() (uint32, *winio.FileIDInfo, error) { | ||
| fileStandardInfo, err := winio.GetFileStandardInfo(r.currentFile) | ||
| if err != nil { | ||
| return 0, nil, err | ||
| } | ||
| fileIDInfo, err := winio.GetFileID(r.currentFile) | ||
| if err != nil { | ||
| return 0, nil, err | ||
| } | ||
| return fileStandardInfo.NumberOfLinks, fileIDInfo, nil | ||
| } | ||
|
|
||
| func (r *baseLayerReader) Read(b []byte) (int, error) { | ||
| if r.backupReader == nil { | ||
| return 0, io.EOF | ||
| } | ||
| return r.backupReader.Read(b) | ||
| } | ||
|
|
||
| func (r *baseLayerReader) Close() (err error) { | ||
| defer r.s.End() | ||
| defer func() { | ||
| oc.SetSpanStatus(r.s, err) | ||
| close(r.proceed) | ||
| }() | ||
| r.proceed <- false | ||
| // The r.result channel will be closed once walk() returns | ||
| <-r.result | ||
| r.reset() | ||
| return nil | ||
| } | ||
File renamed without changes.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.