func (s *ZipSuite) TestExtractSymlinkErrors(c *gc.C) { for i, test := range []struct { content []ft.Entry source string error string }{{ content: []ft.Entry{ ft.Dir{"dir", 0755}, ft.Symlink{"dir/symlink", "/blah"}, }, source: "dir", error: `cannot extract "dir/symlink": symlink "/blah" is absolute`, }, { content: []ft.Entry{ ft.Dir{"dir", 0755}, ft.Symlink{"dir/symlink", "../blah"}, }, source: "dir", error: `cannot extract "dir/symlink": symlink "../blah" leads out of scope`, }, { content: []ft.Entry{ ft.Symlink{"symlink", "blah"}, }, source: "symlink", error: `cannot extract "symlink": symlink "blah" leads out of scope`, }} { c.Logf("test %d: %s", i, test.error) targetPath := c.MkDir() reader := s.makeZip(c, test.content...) err := zip.Extract(reader, targetPath, test.source) c.Check(err, gc.ErrorMatches, test.error) } }
// processUploadedArchive opens the given charm archive from path, // inspects it to see if it has all files at the root of the archive // or it has subdirs. It repackages the archive so it has all the // files at the root dir, if necessary, replacing the original archive // at path. func (h *charmsHandler) processUploadedArchive(path string) error { // Open the archive as a zip. f, err := os.OpenFile(path, os.O_RDWR, 0644) if err != nil { return err } defer f.Close() fi, err := f.Stat() if err != nil { return err } zipr, err := zip.NewReader(f, fi.Size()) if err != nil { return errors.Annotate(err, "cannot open charm archive") } // Find out the root dir prefix from the archive. rootDir, err := h.findArchiveRootDir(zipr) if err != nil { return errors.Annotate(err, "cannot read charm archive") } if rootDir == "." { // Normal charm, just use charm.ReadBundle(). return nil } // There is one or more subdirs, so we need extract it to a temp // dir and then read it as a charm dir. tempDir, err := ioutil.TempDir("", "charm-extract") if err != nil { return errors.Annotate(err, "cannot create temp directory") } defer os.RemoveAll(tempDir) if err := ziputil.Extract(zipr, tempDir, rootDir); err != nil { return errors.Annotate(err, "cannot extract charm archive") } dir, err := charm.ReadDir(tempDir) if err != nil { return errors.Annotate(err, "cannot read extracted archive") } // Now repackage the dir as a bundle at the original path. if err := f.Truncate(0); err != nil { return err } if err := dir.BundleTo(f); err != nil { return err } return nil }
func (s *ZipSuite) TestExtractSingleFile(c *gc.C) { reader := s.makeZip(c, ft.Dir{"dir", 0755}, ft.Dir{"dir/dir", 0755}, ft.File{"dir/dir/some-file", "content 1", 0644}, ft.File{"dir/dir/some-file-wtf", "content 2", 0644}, ) targetParent := c.MkDir() targetPath := filepath.Join(targetParent, "just-the-one-file") err := zip.Extract(reader, targetPath, "dir/dir/some-file") c.Assert(err, gc.IsNil) fileInfos, err := ioutil.ReadDir(targetParent) c.Check(err, gc.IsNil) c.Check(fileInfos, gc.HasLen, 1) ft.File{"just-the-one-file", "content 1", 0644}.Check(c, targetParent) }
func (s *ZipSuite) TestExtractDir(c *gc.C) { reader := s.makeZip(c, ft.File{"bad-file", "xxx", 0644}, ft.Dir{"bad-dir", 0755}, ft.Symlink{"bad-symlink", "bad-file"}, ft.Dir{"some-dir", 0751}, ft.File{"some-dir-bad-lol", "xxx", 0644}, ft.File{"some-dir/some-file", "content 1", 0644}, ft.File{"some-dir/another-file", "content 2", 0600}, ft.Dir{"some-dir/another-dir", 0750}, ft.Symlink{"some-dir/another-dir/some-symlink", "../some-file"}, ) targetParent := c.MkDir() targetPath := filepath.Join(targetParent, "random-dir") err := zip.Extract(reader, targetPath, "some-dir") c.Assert(err, gc.IsNil) for i, test := range []ft.Entry{ ft.Dir{"random-dir", 0751}, ft.File{"random-dir/some-file", "content 1", 0644}, ft.File{"random-dir/another-file", "content 2", 0600}, ft.Dir{"random-dir/another-dir", 0750}, ft.Symlink{"random-dir/another-dir/some-symlink", "../some-file"}, } { c.Logf("test %d: %#v", i, test) test.Check(c, targetParent) } fileInfos, err := ioutil.ReadDir(targetParent) c.Check(err, gc.IsNil) c.Check(fileInfos, gc.HasLen, 1) fileInfos, err = ioutil.ReadDir(targetPath) c.Check(err, gc.IsNil) c.Check(fileInfos, gc.HasLen, 3) }
func (s *ZipSuite) TestExtractSourceError(c *gc.C) { reader := s.makeZip(c, ft.Dir{"dir", 0755}) err := zip.Extract(reader, c.MkDir(), "../lol") c.Assert(err, gc.ErrorMatches, `cannot extract files rooted at "../lol"`) }