diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d03863d..1a31f8a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: strategy: matrix: - go: [ '1.18.x', '1.19.x', '1.20.x' ] + go: [ '1.18.x', '1.19.x', '1.20.x', '1.21.x' ] steps: - name: Checkout @@ -82,4 +82,5 @@ jobs: uses: actions/checkout@v3 - name: Check spelling + continue-on-error: true uses: crate-ci/typos@master diff --git a/README.md b/README.md index 2f609c1..ae369b0 100644 --- a/README.md +++ b/README.md @@ -47,13 +47,15 @@ import ( ) func main() { - err := npck.Unpack("file.tar.gz", "/home/john") + file := "file.tar.gz" + err := npck.Unpack(file, "/home/john") if err != nil { - panic("Can't unpack file: %v", err) + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return } - fmt.Printf("File %s successfully unpacked!\n") + fmt.Printf("File %s successfully unpacked!\n", file) } ``` diff --git a/bz2/example_test.go b/bz2/example_test.go new file mode 100644 index 0000000..a2d06a5 --- /dev/null +++ b/bz2/example_test.go @@ -0,0 +1,46 @@ +package bz2 + +// ////////////////////////////////////////////////////////////////////////////////// // +// // +// Copyright (c) 2023 ESSENTIAL KAOS // +// Apache License, Version 2.0 // +// // +// ////////////////////////////////////////////////////////////////////////////////// // + +import ( + "fmt" + "os" +) + +// ////////////////////////////////////////////////////////////////////////////////// // + +func ExampleUnpack() { + file := "file.bz2" + err := Unpack(file, "/home/bob/data") + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + fmt.Printf("File %s successfully unpacked!\n", file) +} + +func ExampleRead() { + file := "file.bz2" + fd, err := os.OpenFile(file, os.O_RDONLY, 0) + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + err = Read(fd, "/home/bob/data") + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + fmt.Printf("File %s successfully unpacked!\n", file) +} diff --git a/example_test.go b/example_test.go new file mode 100644 index 0000000..7ef6d65 --- /dev/null +++ b/example_test.go @@ -0,0 +1,26 @@ +package npck + +// ////////////////////////////////////////////////////////////////////////////////// // +// // +// Copyright (c) 2023 ESSENTIAL KAOS // +// Apache License, Version 2.0 // +// // +// ////////////////////////////////////////////////////////////////////////////////// // + +import ( + "fmt" +) + +// ////////////////////////////////////////////////////////////////////////////////// // + +func ExampleUnpack() { + file := "file.tzg" + err := Unpack(file, "/home/bob/data") + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + fmt.Printf("File %s successfully unpacked!\n", file) +} diff --git a/go.mod b/go.mod index 67fdabc..f048bbd 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.19 require ( github.com/essentialkaos/check v1.4.0 - github.com/essentialkaos/ek/v12 v12.68.0 + github.com/essentialkaos/ek/v12 v12.75.1 github.com/klauspost/compress v1.16.7 github.com/pierrec/lz4/v4 v4.1.18 github.com/ulikunitz/xz v0.5.11 @@ -14,5 +14,5 @@ require ( github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect - golang.org/x/sys v0.9.0 // indirect + golang.org/x/sys v0.10.0 // indirect ) diff --git a/go.sum b/go.sum index d7e3b3a..58ee905 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/essentialkaos/check v1.4.0 h1:kWdFxu9odCxUqo1NNFNJmguGrDHgwi3A8daXX1nkuKk= github.com/essentialkaos/check v1.4.0/go.mod h1:LMKPZ2H+9PXe7Y2gEoKyVAwUqXVgx7KtgibfsHJPus0= -github.com/essentialkaos/ek/v12 v12.68.0 h1:/tNqKHfGypPUUu+aQ8LcmmWWEOO8itJZoJgOCPOZFY8= -github.com/essentialkaos/ek/v12 v12.68.0/go.mod h1:CAPhbYcAiQsCP7CMyBlkgD/MgvuLcbr4EXjCIKn3DIk= +github.com/essentialkaos/ek/v12 v12.75.1 h1:HE8/uWED+QgyT6HIcRULqjMYWKhqQ1rkfa/ozcva1eQ= +github.com/essentialkaos/ek/v12 v12.75.1/go.mod h1:juDcZWOWaj1QmYShZkT9RzdqJ3n0tmeP/iq4sw5fQF0= github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -17,5 +17,5 @@ github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjR github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= -golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/gz/example_test.go b/gz/example_test.go new file mode 100644 index 0000000..c77e304 --- /dev/null +++ b/gz/example_test.go @@ -0,0 +1,46 @@ +package gz + +// ////////////////////////////////////////////////////////////////////////////////// // +// // +// Copyright (c) 2023 ESSENTIAL KAOS // +// Apache License, Version 2.0 // +// // +// ////////////////////////////////////////////////////////////////////////////////// // + +import ( + "fmt" + "os" +) + +// ////////////////////////////////////////////////////////////////////////////////// // + +func ExampleUnpack() { + file := "file.gz" + err := Unpack(file, "/home/bob/data") + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + fmt.Printf("File %s successfully unpacked!\n", file) +} + +func ExampleRead() { + file := "file.gz" + fd, err := os.OpenFile(file, os.O_RDONLY, 0) + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + err = Read(fd, "/home/bob/data") + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + fmt.Printf("File %s successfully unpacked!\n", file) +} diff --git a/lz4/example_test.go b/lz4/example_test.go new file mode 100644 index 0000000..3b2ea68 --- /dev/null +++ b/lz4/example_test.go @@ -0,0 +1,46 @@ +package lz4 + +// ////////////////////////////////////////////////////////////////////////////////// // +// // +// Copyright (c) 2023 ESSENTIAL KAOS // +// Apache License, Version 2.0 // +// // +// ////////////////////////////////////////////////////////////////////////////////// // + +import ( + "fmt" + "os" +) + +// ////////////////////////////////////////////////////////////////////////////////// // + +func ExampleUnpack() { + file := "file.lz4" + err := Unpack(file, "/home/bob/data") + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + fmt.Printf("File %s successfully unpacked!\n", file) +} + +func ExampleRead() { + file := "file.lz4" + fd, err := os.OpenFile(file, os.O_RDONLY, 0) + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + err = Read(fd, "/home/bob/data") + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + fmt.Printf("File %s successfully unpacked!\n", file) +} diff --git a/tar/example_test.go b/tar/example_test.go new file mode 100644 index 0000000..7692b47 --- /dev/null +++ b/tar/example_test.go @@ -0,0 +1,46 @@ +package tar + +// ////////////////////////////////////////////////////////////////////////////////// // +// // +// Copyright (c) 2023 ESSENTIAL KAOS // +// Apache License, Version 2.0 // +// // +// ////////////////////////////////////////////////////////////////////////////////// // + +import ( + "fmt" + "os" +) + +// ////////////////////////////////////////////////////////////////////////////////// // + +func ExampleUnpack() { + file := "file.tar" + err := Unpack(file, "/home/bob/data") + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + fmt.Printf("File %s successfully unpacked!\n", file) +} + +func ExampleRead() { + file := "file.tar" + fd, err := os.OpenFile(file, os.O_RDONLY, 0) + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + err = Read(fd, "/home/bob/data") + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + fmt.Printf("File %s successfully unpacked!\n", file) +} diff --git a/tar/tar.go b/tar/tar.go index 80a73d5..f39aba9 100644 --- a/tar/tar.go +++ b/tar/tar.go @@ -158,8 +158,8 @@ func createFile(h *tar.Header, r io.Reader, path string) error { // createSymlink creates symbolic link func createSymlink(h *tar.Header, dir, path string) error { - if !AllowExternalLinks && isExternalLink(h.Linkname, dir) { - return fmt.Errorf("Symbolic link %s points to target outside of target directory (%s)", h.Name, h.Linkname) + if !AllowExternalLinks && isExternalLink(h.Linkname, path, dir) { + return fmt.Errorf("Symbolic link %s points to object outside of target directory (%s)", h.Name, h.Linkname) } return os.Symlink(h.Linkname, path) @@ -167,8 +167,8 @@ func createSymlink(h *tar.Header, dir, path string) error { // createHardlink creates hard link func createHardlink(h *tar.Header, dir, path string) error { - if !AllowExternalLinks && isExternalLink(h.Linkname, dir) { - return fmt.Errorf("Hard link %s points to target outside of target directory (%s)", h.Name, h.Linkname) + if !AllowExternalLinks && isExternalLink(h.Linkname, path, dir) { + return fmt.Errorf("Hard link %s points to object outside of target directory (%s)", h.Name, h.Linkname) } return os.Link(h.Linkname, path) @@ -198,16 +198,13 @@ func updateAttrs(h *tar.Header, path string) error { } // isExternalLink checks if link leads to object outside target directory -func isExternalLink(path, dir string) bool { - if filepath.IsAbs(path) && !strings.HasPrefix(path, dir) { +func isExternalLink(linkPath, objPath, targetDir string) bool { + if filepath.IsAbs(linkPath) && !strings.HasPrefix(linkPath, targetDir) { return true } - realPath, err := utils.Join(dir, path) - - if err != nil { - return true - } - - return !strings.HasPrefix(realPath, dir) + return !strings.HasPrefix( + filepath.Clean(filepath.Dir(objPath)+"/"+linkPath), + targetDir, + ) } diff --git a/tar/tar_test.go b/tar/tar_test.go index 0ecad9c..93be7ab 100644 --- a/tar/tar_test.go +++ b/tar/tar_test.go @@ -12,6 +12,7 @@ import ( "os" "strings" "testing" + "time" "github.com/essentialkaos/ek/v12/fsutil" "github.com/essentialkaos/ek/v12/hash" @@ -89,11 +90,19 @@ func (s *TarSuite) TestErrors(c *C) { c.Assert(err, NotNil) UpdateTimes, UpdateOwner = true, false - err = updateAttrs(&tar.Header{Linkname: "/__unknown"}, "/_unknown") + err = updateAttrs(&tar.Header{ + Linkname: "/__unknown", + AccessTime: time.Now(), + ModTime: time.Now(), + }, "/_unknown") c.Assert(err, NotNil) UpdateTimes, UpdateOwner = false, true - err = updateAttrs(&tar.Header{Linkname: "/__unknown"}, "/_unknown") + err = updateAttrs(&tar.Header{ + Linkname: "/__unknown", + AccessTime: time.Now(), + ModTime: time.Now(), + }, "/_unknown") c.Assert(err, NotNil) UpdateTimes, UpdateOwner = true, false @@ -104,5 +113,5 @@ func (s *TarSuite) TestErrors(c *C) { err = createHardlink(&tar.Header{Linkname: "/root/test"}, "/unknown", "/_unknown") c.Assert(err, NotNil) - c.Assert(isExternalLink("../unknown", "/root"), Equals, true) + c.Assert(isExternalLink("../../unknown", "/root/test", "/root"), Equals, true) } diff --git a/tbz2/example_test.go b/tbz2/example_test.go new file mode 100644 index 0000000..bd12e2b --- /dev/null +++ b/tbz2/example_test.go @@ -0,0 +1,46 @@ +package tbz2 + +// ////////////////////////////////////////////////////////////////////////////////// // +// // +// Copyright (c) 2023 ESSENTIAL KAOS // +// Apache License, Version 2.0 // +// // +// ////////////////////////////////////////////////////////////////////////////////// // + +import ( + "fmt" + "os" +) + +// ////////////////////////////////////////////////////////////////////////////////// // + +func ExampleUnpack() { + file := "file.tbz2" + err := Unpack(file, "/home/bob/data") + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + fmt.Printf("File %s successfully unpacked!\n", file) +} + +func ExampleRead() { + file := "file.tbz2" + fd, err := os.OpenFile(file, os.O_RDONLY, 0) + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + err = Read(fd, "/home/bob/data") + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + fmt.Printf("File %s successfully unpacked!\n", file) +} diff --git a/tgz/example_test.go b/tgz/example_test.go new file mode 100644 index 0000000..0f1a7ed --- /dev/null +++ b/tgz/example_test.go @@ -0,0 +1,46 @@ +package tgz + +// ////////////////////////////////////////////////////////////////////////////////// // +// // +// Copyright (c) 2023 ESSENTIAL KAOS // +// Apache License, Version 2.0 // +// // +// ////////////////////////////////////////////////////////////////////////////////// // + +import ( + "fmt" + "os" +) + +// ////////////////////////////////////////////////////////////////////////////////// // + +func ExampleUnpack() { + file := "file.tgz" + err := Unpack(file, "/home/bob/data") + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + fmt.Printf("File %s successfully unpacked!\n", file) +} + +func ExampleRead() { + file := "file.tgz" + fd, err := os.OpenFile(file, os.O_RDONLY, 0) + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + err = Read(fd, "/home/bob/data") + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + fmt.Printf("File %s successfully unpacked!\n", file) +} diff --git a/tlz4/example_test.go b/tlz4/example_test.go new file mode 100644 index 0000000..5c6491c --- /dev/null +++ b/tlz4/example_test.go @@ -0,0 +1,46 @@ +package tlz4 + +// ////////////////////////////////////////////////////////////////////////////////// // +// // +// Copyright (c) 2023 ESSENTIAL KAOS // +// Apache License, Version 2.0 // +// // +// ////////////////////////////////////////////////////////////////////////////////// // + +import ( + "fmt" + "os" +) + +// ////////////////////////////////////////////////////////////////////////////////// // + +func ExampleUnpack() { + file := "file.tlz4" + err := Unpack(file, "/home/bob/data") + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + fmt.Printf("File %s successfully unpacked!\n", file) +} + +func ExampleRead() { + file := "file.tlz4" + fd, err := os.OpenFile(file, os.O_RDONLY, 0) + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + err = Read(fd, "/home/bob/data") + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + fmt.Printf("File %s successfully unpacked!\n", file) +} diff --git a/txz/example_test.go b/txz/example_test.go new file mode 100644 index 0000000..1c1ab22 --- /dev/null +++ b/txz/example_test.go @@ -0,0 +1,46 @@ +package txz + +// ////////////////////////////////////////////////////////////////////////////////// // +// // +// Copyright (c) 2023 ESSENTIAL KAOS // +// Apache License, Version 2.0 // +// // +// ////////////////////////////////////////////////////////////////////////////////// // + +import ( + "fmt" + "os" +) + +// ////////////////////////////////////////////////////////////////////////////////// // + +func ExampleUnpack() { + file := "file.txz" + err := Unpack(file, "/home/bob/data") + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + fmt.Printf("File %s successfully unpacked!\n", file) +} + +func ExampleRead() { + file := "file.txz" + fd, err := os.OpenFile(file, os.O_RDONLY, 0) + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + err = Read(fd, "/home/bob/data") + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + fmt.Printf("File %s successfully unpacked!\n", file) +} diff --git a/tzst/example_test.go b/tzst/example_test.go new file mode 100644 index 0000000..956f452 --- /dev/null +++ b/tzst/example_test.go @@ -0,0 +1,46 @@ +package tzst + +// ////////////////////////////////////////////////////////////////////////////////// // +// // +// Copyright (c) 2023 ESSENTIAL KAOS // +// Apache License, Version 2.0 // +// // +// ////////////////////////////////////////////////////////////////////////////////// // + +import ( + "fmt" + "os" +) + +// ////////////////////////////////////////////////////////////////////////////////// // + +func ExampleUnpack() { + file := "file.tzst" + err := Unpack(file, "/home/bob/data") + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + fmt.Printf("File %s successfully unpacked!\n", file) +} + +func ExampleRead() { + file := "file.tzst" + fd, err := os.OpenFile(file, os.O_RDONLY, 0) + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + err = Read(fd, "/home/bob/data") + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + fmt.Printf("File %s successfully unpacked!\n", file) +} diff --git a/xz/example_test.go b/xz/example_test.go new file mode 100644 index 0000000..2e62aff --- /dev/null +++ b/xz/example_test.go @@ -0,0 +1,46 @@ +package xz + +// ////////////////////////////////////////////////////////////////////////////////// // +// // +// Copyright (c) 2023 ESSENTIAL KAOS // +// Apache License, Version 2.0 // +// // +// ////////////////////////////////////////////////////////////////////////////////// // + +import ( + "fmt" + "os" +) + +// ////////////////////////////////////////////////////////////////////////////////// // + +func ExampleUnpack() { + file := "file.xz" + err := Unpack(file, "/home/bob/data") + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + fmt.Printf("File %s successfully unpacked!\n", file) +} + +func ExampleRead() { + file := "file.xz" + fd, err := os.OpenFile(file, os.O_RDONLY, 0) + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + err = Read(fd, "/home/bob/data") + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + fmt.Printf("File %s successfully unpacked!\n", file) +} diff --git a/zip/example_test.go b/zip/example_test.go new file mode 100644 index 0000000..0e127fb --- /dev/null +++ b/zip/example_test.go @@ -0,0 +1,46 @@ +package zip + +// ////////////////////////////////////////////////////////////////////////////////// // +// // +// Copyright (c) 2023 ESSENTIAL KAOS // +// Apache License, Version 2.0 // +// // +// ////////////////////////////////////////////////////////////////////////////////// // + +import ( + "fmt" + "os" +) + +// ////////////////////////////////////////////////////////////////////////////////// // + +func ExampleUnpack() { + file := "file.zip" + err := Unpack(file, "/home/bob/data") + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + fmt.Printf("File %s successfully unpacked!\n", file) +} + +func ExampleRead() { + file := "file.zip" + fd, err := os.OpenFile(file, os.O_RDONLY, 0) + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + err = Read(fd, "/home/bob/data") + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + fmt.Printf("File %s successfully unpacked!\n", file) +} diff --git a/zst/example_test.go b/zst/example_test.go new file mode 100644 index 0000000..2b2cd15 --- /dev/null +++ b/zst/example_test.go @@ -0,0 +1,46 @@ +package zst + +// ////////////////////////////////////////////////////////////////////////////////// // +// // +// Copyright (c) 2023 ESSENTIAL KAOS // +// Apache License, Version 2.0 // +// // +// ////////////////////////////////////////////////////////////////////////////////// // + +import ( + "fmt" + "os" +) + +// ////////////////////////////////////////////////////////////////////////////////// // + +func ExampleUnpack() { + file := "file.zst" + err := Unpack(file, "/home/bob/data") + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + fmt.Printf("File %s successfully unpacked!\n", file) +} + +func ExampleRead() { + file := "file.zst" + fd, err := os.OpenFile(file, os.O_RDONLY, 0) + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + err = Read(fd, "/home/bob/data") + + if err != nil { + fmt.Printf("Error: Can't unpack %s: %v\n", file, err) + return + } + + fmt.Printf("File %s successfully unpacked!\n", file) +}