func (s *ZipSuite) TestExtractAllSymlinkErrors(c *gc.C) { for i, test := range []struct { content []ft.Entry error string }{{ content: []ft.Entry{ ft.Symlink{"symlink", "/blah"}, }, error: `cannot extract "symlink": symlink "/blah" is absolute`, }, { content: []ft.Entry{ ft.Symlink{"symlink", "../blah"}, }, error: `cannot extract "symlink": symlink "../blah" leads out of scope`, }, { content: []ft.Entry{ ft.Dir{"dir", 0755}, ft.Symlink{"dir/symlink", "../../blah"}, }, error: `cannot extract "dir/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.ExtractAll(reader, targetPath) c.Check(err, gc.ErrorMatches, test.error) } }
func (s *ZipSuite) TestExtractAllMergeDirs(c *gc.C) { targetPath := c.MkDir() ft.Dir{"dir", 0755}.Create(c, targetPath) originals := []ft.Entry{ ft.Dir{"dir/original-dir", 0751}, ft.File{"dir/original-file", "content 1", 0600}, ft.Symlink{"dir/original-symlink", "original-file"}, } for _, entry := range originals { entry.Create(c, targetPath) } merges := []ft.Entry{ ft.Dir{"dir", 0751}, ft.Dir{"dir/merge-dir", 0750}, ft.File{"dir/merge-file", "content 2", 0640}, ft.Symlink{"dir/merge-symlink", "merge-file"}, } reader := s.makeZip(c, merges...) err := zip.ExtractAll(reader, targetPath) c.Assert(err, gc.IsNil) for i, test := range append(originals, merges...) { c.Logf("test %d: %#v", i, test) test.Check(c, targetPath) } }
func (s *ZipSuite) TestClosesFile(c *gc.C) { reader := s.makeZip(c, ft.File{"f", "echo hullo!", 0755}) targetPath := c.MkDir() err := zip.ExtractAll(reader, targetPath) c.Assert(err, gc.IsNil) cmd := exec.Command("/bin/sh", "-c", filepath.Join(targetPath, "f")) var buffer bytes.Buffer cmd.Stdout = &buffer err = cmd.Run() c.Assert(err, gc.IsNil) c.Assert(buffer.String(), gc.Equals, "hullo!\n") }
func (s *ZipSuite) TestExtractAllOverwriteDirs(c *gc.C) { name := "some-dir" for i, test := range []ft.Entry{ ft.File{name, "content", 0644}, ft.Dir{name, 0751}, ft.Symlink{name, "wherever"}, } { c.Logf("test %d: %#v", i, test) targetPath := c.MkDir() ft.Dir{name, 0}.Create(c, targetPath) reader := s.makeZip(c, test) err := zip.ExtractAll(reader, targetPath) c.Check(err, gc.IsNil) test.Check(c, targetPath) } }
func (s *ZipSuite) TestExtractAll(c *gc.C) { entries := []ft.Entry{ ft.File{"some-file", "content 1", 0644}, ft.File{"another-file", "content 2", 0640}, ft.Symlink{"some-symlink", "some-file"}, ft.Dir{"some-dir", 0750}, ft.File{"some-dir/another-file", "content 3", 0644}, ft.Dir{"some-dir/another-dir", 0755}, ft.Symlink{"some-dir/another-dir/another-symlink", "../../another-file"}, } reader := s.makeZip(c, entries...) targetPath := c.MkDir() err := zip.ExtractAll(reader, targetPath) c.Assert(err, gc.IsNil) for i, entry := range entries { c.Logf("test %d: %#v", i, entry) entry.Check(c, targetPath) } }
// Extract unpacks a tar or zip archive to outputDir (defaults to working directory). // Supported extension: tar, zip // Defaults: // - outputDir os.Getwd() // TODO: // - ignore file extensions, try to parse headers func Extract(filename, outputDir string) error { if _, err := os.Stat(filename); err != nil { return fmt.Errorf("couldn't access file %s: %+v", filename, err) } if outputDir == "" { outputDir, _ = os.Getwd() } if strings.HasSuffix(filename, ".tar") { r, err := os.Open(filename) if err != nil { return fmt.Errorf("couldn't open file %s: %+v", filename, err) } return tar.UntarFiles(r, outputDir) } if strings.HasSuffix(filename, ".zip") { r, err := zip.OpenReader(filename) if err != nil { return fmt.Errorf("couldn't open archive %s: %+v", filename, err) } return jzip.ExtractAll(&r.Reader, outputDir) } return fmt.Errorf("only supporting tar and zip files at the moment") }
// ExpandTo expands the charm bundle into dir, creating it if necessary. // If any errors occur during the expansion procedure, the process will // abort. func (b *Bundle) ExpandTo(dir string) (err error) { zipr, err := b.zipOpen() if err != nil { return err } defer zipr.Close() if err := ziputil.ExtractAll(zipr.Reader, dir); err != nil { return err } hooksDir := filepath.Join(dir, "hooks") fixHook := fixHookFunc(hooksDir, b.meta.Hooks()) if err := filepath.Walk(hooksDir, fixHook); err != nil { if !os.IsNotExist(err) { return err } } revFile, err := os.Create(filepath.Join(dir, "revision")) if err != nil { return err } _, err = revFile.Write([]byte(strconv.Itoa(b.revision))) revFile.Close() return err }