diff options
author | Dan Willemsen <dwillemsen@google.com> | 2016-08-03 00:35:25 -0700 |
---|---|---|
committer | Dan Willemsen <dwillemsen@google.com> | 2016-08-10 16:57:03 -0700 |
commit | 3bf1a085050c797f4af31353325c9ee69ca6c02f (patch) | |
tree | 6cc35038a938a8b195c45f8103152bf5c709ec8c | |
parent | 25a4e07df8d4c6f653d69baa16cd22d1f07e89a1 (diff) | |
download | build_soong-3bf1a085050c797f4af31353325c9ee69ca6c02f.tar.gz build_soong-3bf1a085050c797f4af31353325c9ee69ca6c02f.tar.bz2 build_soong-3bf1a085050c797f4af31353325c9ee69ca6c02f.zip |
Add zip2zip tool to copy zip entries from one file to another
This doesn't do any decompression / recompression, but just copies over
the already compressed contents. So it's similar to zip -U, but allows
rewriting of the paths.
The first expected usecase is to replace img_from_target_files during
the build, since it does the equivalent of this:
zip2zip -i <target-files.zip> -o <img.zip> OTA/android-info.txt:android-info.txt IMAGES/*:.
Except it decompresses and recompresses the images, which takes over a
minute instead of a few seconds.
Change-Id: I88d0df188635088783223873f78e193272dbdf1c
-rw-r--r-- | Android.bp | 10 | ||||
-rw-r--r-- | cmd/zip2zip/zip2zip.go | 128 | ||||
-rw-r--r-- | third_party/zip/Android.bp | 31 | ||||
-rw-r--r-- | third_party/zip/android.go | 70 |
4 files changed, 239 insertions, 0 deletions
@@ -10,6 +10,8 @@ // 2) Build again // +subdirs = ["third_party/zip"] + bootstrap_go_binary { name: "soong_build", deps: [ @@ -195,6 +197,14 @@ bootstrap_go_package { } blueprint_go_binary { + name: "zip2zip", + deps: ["android-archive-zip"], + srcs: [ + "cmd/zip2zip/zip2zip.go", + ], +} + +blueprint_go_binary { name: "soong_jar", srcs: [ "cmd/soong_jar/soong_jar.go", diff --git a/cmd/zip2zip/zip2zip.go b/cmd/zip2zip/zip2zip.go new file mode 100644 index 00000000..8e7523ff --- /dev/null +++ b/cmd/zip2zip/zip2zip.go @@ -0,0 +1,128 @@ +// Copyright 2016 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "flag" + "fmt" + "os" + "path/filepath" + "strings" + + "android/soong/third_party/zip" +) + +var ( + input = flag.String("i", "", "zip file to read from") + output = flag.String("o", "", "output file") +) + +func usage() { + fmt.Fprintln(os.Stderr, "usage: zip2zip -i zipfile -o zipfile [filespec]...") + flag.PrintDefaults() + fmt.Fprintln(os.Stderr, " filespec:") + fmt.Fprintln(os.Stderr, " <name>") + fmt.Fprintln(os.Stderr, " <in_name>:<out_name>") + fmt.Fprintln(os.Stderr, " <glob>:<out_dir>/") + fmt.Fprintln(os.Stderr, "") + fmt.Fprintln(os.Stderr, "Files will be copied with their existing compression from the input zipfile to") + fmt.Fprintln(os.Stderr, "the output zipfile, in the order of filespec arguments") + os.Exit(2) +} + +func main() { + flag.Parse() + + if flag.NArg() == 0 || *input == "" || *output == "" { + usage() + } + + reader, err := zip.OpenReader(*input) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(3) + } + defer reader.Close() + + output, err := os.Create(*output) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(4) + } + defer output.Close() + + writer := zip.NewWriter(output) + defer func() { + err := writer.Close() + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(5) + } + }() + + for _, arg := range flag.Args() { + var input string + var output string + + // Reserve escaping for future implementation, so make sure no + // one is using \ and expecting a certain behavior. + if strings.Contains(arg, "\\") { + fmt.Fprintln(os.Stderr, "\\ characters are not currently supported") + os.Exit(6) + } + + args := strings.SplitN(arg, ":", 2) + input = args[0] + if len(args) == 2 { + output = args[1] + } + + if strings.IndexAny(input, "*?[") >= 0 { + for _, file := range reader.File { + if match, err := filepath.Match(input, file.Name); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(7) + } else if match { + var newFileName string + if output == "" { + newFileName = file.Name + } else { + _, name := filepath.Split(file.Name) + newFileName = filepath.Join(output, name) + } + err = writer.CopyFrom(file, newFileName) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(8) + } + } + } + } else { + if output == "" { + output = input + } + for _, file := range reader.File { + if input == file.Name { + err = writer.CopyFrom(file, output) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(8) + } + break + } + } + } + } +} diff --git a/third_party/zip/Android.bp b/third_party/zip/Android.bp new file mode 100644 index 00000000..044e6f8e --- /dev/null +++ b/third_party/zip/Android.bp @@ -0,0 +1,31 @@ +// Copyright 2016 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +bootstrap_go_package { + name: "android-archive-zip", + pkgPath: "android/soong/third_party/zip", + srcs: [ + "reader.go", + "register.go", + "struct.go", + "writer.go", + + "android.go", + ], + testSrcs: [ + "reader_test.go", + "writer_test.go", + "zip_test.go", + ], +} diff --git a/third_party/zip/android.go b/third_party/zip/android.go new file mode 100644 index 00000000..7a3a2213 --- /dev/null +++ b/third_party/zip/android.go @@ -0,0 +1,70 @@ +// Copyright 2016 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package zip + +import ( + "io" +) + +func (w *Writer) CopyFrom(orig *File, newName string) error { + if w.last != nil && !w.last.closed { + if err := w.last.close(); err != nil { + return err + } + w.last = nil + } + + fileHeader := orig.FileHeader + fileHeader.Name = newName + fh := &fileHeader + fh.Flags |= 0x8 + + h := &header{ + FileHeader: fh, + offset: uint64(w.cw.count), + } + w.dir = append(w.dir, h) + + if err := writeHeader(w.cw, fh); err != nil { + return err + } + + // Copy data + dataOffset, err := orig.DataOffset() + if err != nil { + return err + } + io.Copy(w.cw, io.NewSectionReader(orig.zipr, dataOffset, int64(orig.CompressedSize64))) + + // Write data descriptor. + var buf []byte + if fh.isZip64() { + buf = make([]byte, dataDescriptor64Len) + } else { + buf = make([]byte, dataDescriptorLen) + } + b := writeBuf(buf) + b.uint32(dataDescriptorSignature) + b.uint32(fh.CRC32) + if fh.isZip64() { + b.uint64(fh.CompressedSize64) + b.uint64(fh.UncompressedSize64) + } else { + b.uint32(fh.CompressedSize) + b.uint32(fh.UncompressedSize) + } + _, err = w.cw.Write(buf) + return err +} |