Skip to content
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

add --keep-dirlinks option to unpack #245

Merged
merged 7 commits into from
Aug 28, 2018

Conversation

tych0
Copy link
Member

@tych0 tych0 commented Jun 26, 2018

Similar to rsync's --keep-dirlinks, let's have an option to allow symlinks
that point to directories to be used as directories themselves.

Signed-off-by: Tycho Andersen tycho@tycho.ws

@tych0 tych0 force-pushed the keep-dirlinks branch 4 times, most recently from 2974170 to 5d5d9b2 Compare June 27, 2018 15:59
@tych0
Copy link
Member Author

tych0 commented Jul 18, 2018

Ping, just occurred to me that I hadn't heard anything on this.

Copy link
Member

@cyphar cyphar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm overall +1 on the idea, I just think that the conditional change is a bit hard to follow.

Flags: []cli.Flag{},
Flags: []cli.Flag{
cli.BoolFlag{
Name: "keep-dirlinks",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This flag should probably also be added to raw-unpack. And docs should be updated (it doesn't need much).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, I pushed a commit for these.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. :D

@@ -370,7 +396,13 @@ func (te *tarExtractor) unpackEntry(root string, hdr *tar.Header, r io.Reader) (
// "lower" file still exists (so the hard-link would point to the old
// inode). It's not clear if such an archive is actually valid though.
if !fi.IsDir() || hdr.Typeflag != tar.TypeDir {
if err := te.fsEval.RemoveAll(path); err != nil {
if fi.Mode()&os.ModeSymlink != 0 && hdr.Typeflag == tar.TypeDir &&
te.mapOptions.KeepDirlinks {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To me, this nested if looks a bit complicated (and is what stopped me from completing my review when you first sent the PR -- because I tried to come up with a more "clear" conditional and didn't get very far).

At the moment, I'm +1 on the design it just needs to be a bit less difficult to understand. I'll take another look and get back to you.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, no worries. Perhaps a comment explaining that we want to write through symlinks instead of overwriting them is enough?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I added the comment (back from vacation now). If you merge this, I have the v2 api done on top of this and I can post that too.

@tych0
Copy link
Member Author

tych0 commented Aug 6, 2018

Ping, any thoughts on this?

1 similar comment
@tych0
Copy link
Member Author

tych0 commented Aug 13, 2018

Ping, any thoughts on this?

@hallyn
Copy link
Contributor

hallyn commented Aug 13, 2018

... could really use this...

@cyphar
Copy link
Member

cyphar commented Aug 13, 2018

Needs a rebase, but I can do that. I don't really like the re-use of MapOptions for something unrelated to mapping -- but that just requires a struct type rename. I can fix that up later.

@tych0 tych0 force-pushed the keep-dirlinks branch 2 times, most recently from 5d3b7f3 to ef410ed Compare August 15, 2018 21:07
@tych0
Copy link
Member Author

tych0 commented Aug 15, 2018

Ok, I've rebased it. It turns out that renaming MapOptions isn't so easy, because the struct is emitted in UmociMeta, so we'd have to write some backwards compatible code for that. For now I just disabled it being emitted in the json, since it's not really relevant, and I'll let you decide how to handle it in the future as you say.

te.mapOptions.KeepDirlinks {
isDirlink, err = te.isDirlink(root, path, hdr)
if err != nil {
return err
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs an errors.Wrap(err, "check is dirlink").

return false, errors.Wrap(err, "sanitize old target")
}

linkInfo, err := te.fsEval.Lstat(linkPath)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just realised that this won't handle nested symlinks (a symlink to a symlink to a directory) properly -- we'd need to loop this logic and bail with an ELOOP. (I really wish we had openat(..., AT_THIS_ROOT) so we didn't have to write this logic in userspace.)

@@ -152,3 +152,35 @@ function teardown() {

image-verify "${IMAGE}"
}

@test "umoci unpack --keep-dirlinks" {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once the nested symlink thing is fixed, I'd recommend adding a test for it.

@tych0
Copy link
Member Author

tych0 commented Aug 16, 2018

Ok, I fixed those comments too.

@tych0 tych0 force-pushed the keep-dirlinks branch 2 times, most recently from 6b1a114 to 0bff8d0 Compare August 17, 2018 15:55
@tych0
Copy link
Member Author

tych0 commented Aug 17, 2018

Ok, my rebuild of this worked without http flakiness. I don't have perms to retrigger the travis build, but I think if you do it'll work and should be mergable.

Copy link
Member

@cyphar cyphar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aside from the small idiomatic comment, this looks fine. If I have push access to your branch, I'll send the fix-up.

return false, errors.Wrap(err, "read existing link")
}
func (te *tarExtractor) isDirlink(root string, path string) (bool, error) {
previous := []string{}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you make this a map[string]struct{} it would probably be more "idiomatic" -- but I can push that on top of your branch.

@cyphar
Copy link
Member

cyphar commented Aug 19, 2018

Yeah, Travis has been quite flaky recently. Not really sure what's going on there...

Similar to rsync's --keep-dirlinks, let's have an option to allow symlinks
that point to directories to be used as directories themselves.

Signed-off-by: Tycho Andersen <tycho@tycho.ws>
...also add some man page documentation for umoci unpack and umoci
raw-unpack.

Signed-off-by: Tycho Andersen <tycho@tycho.ws>
Signed-off-by: Tycho Andersen <tycho@tycho.ws>
Signed-off-by: Tycho Andersen <tycho@tycho.ws>
Signed-off-by: Tycho Andersen <tycho@tycho.ws>
* git-validation was not imported
* the stock zypper image apparently doesn't have `which`, so the tests
  always failed. switch to `type` instead.

Signed-off-by: Tycho Andersen <tycho@tycho.ws>
test coverage metrics are a waste of time.

Signed-off-by: Tycho Andersen <tycho@tycho.ws>
@cyphar
Copy link
Member

cyphar commented Aug 27, 2018

LGTM.

@cyphar cyphar merged commit cc0b5e1 into opencontainers:master Aug 28, 2018
cyphar added a commit that referenced this pull request Aug 28, 2018
  add some golang test code too!
  fix `make validate`
  handle nested symlinks + symlink loops
  wrap dirlink check error
  add clarifying comment about KeepDirlinks
  add --keep-dirlinks to umoci-raw-unpack
  add --keep-dirlinks option to unpack

LGTMs: @cyphar
Closes #245
@cyphar
Copy link
Member

cyphar commented Sep 3, 2018

I was just re-reading the tests and it looks like they actually don't quite test --keep-dirlink. But don't worry, I'll work on this (it'll require having an umoci raw add-layer or something where we add a tar archive generated externally -- because umoci repack won't generate a dirlink and so testing it with just umoci repack won't quite work).

@cyphar cyphar added this to the 0.4.2 milestone Sep 5, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants