blob: fa0e693509e69fbd12f597aabefe00e9d3f6ffe6 [file] [log] [blame]
Jeff Gaston01547b22017-08-21 20:13:28 -07001// Copyright 2017 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package jar
16
17import (
Colin Cross635acc92017-09-12 22:50:46 -070018 "bytes"
Jeff Gaston01547b22017-08-21 20:13:28 -070019 "fmt"
Colin Cross635acc92017-09-12 22:50:46 -070020 "os"
Jeff Gaston01547b22017-08-21 20:13:28 -070021 "strings"
Colin Cross635acc92017-09-12 22:50:46 -070022 "time"
23
24 "android/soong/third_party/zip"
Jeff Gaston01547b22017-08-21 20:13:28 -070025)
26
Colin Cross34540312017-09-06 12:52:37 -070027const (
28 MetaDir = "META-INF/"
29 ManifestFile = MetaDir + "MANIFEST.MF"
30 ModuleInfoClass = "module-info.class"
31)
32
Colin Crossbddcf132017-10-04 17:02:23 -070033var DefaultTime = time.Date(2008, 1, 1, 0, 0, 0, 0, time.UTC)
Colin Cross635acc92017-09-12 22:50:46 -070034
35var MetaDirExtra = [2]byte{0xca, 0xfe}
36
Jeff Gaston01547b22017-08-21 20:13:28 -070037// EntryNamesLess tells whether <filepathA> should precede <filepathB> in
38// the order of files with a .jar
39func EntryNamesLess(filepathA string, filepathB string) (less bool) {
40 diff := index(filepathA) - index(filepathB)
41 if diff == 0 {
42 return filepathA < filepathB
43 }
44 return diff < 0
45}
46
47// Treats trailing * as a prefix match
48func patternMatch(pattern, name string) bool {
49 if strings.HasSuffix(pattern, "*") {
50 return strings.HasPrefix(name, strings.TrimSuffix(pattern, "*"))
51 } else {
52 return name == pattern
53 }
54}
55
56var jarOrder = []string{
Colin Cross34540312017-09-06 12:52:37 -070057 MetaDir,
58 ManifestFile,
59 MetaDir + "*",
Jeff Gaston01547b22017-08-21 20:13:28 -070060 "*",
61}
62
63func index(name string) int {
64 for i, pattern := range jarOrder {
65 if patternMatch(pattern, name) {
66 return i
67 }
68 }
69 panic(fmt.Errorf("file %q did not match any pattern", name))
70}
Colin Cross635acc92017-09-12 22:50:46 -070071
72func MetaDirFileHeader() *zip.FileHeader {
73 dirHeader := &zip.FileHeader{
74 Name: MetaDir,
75 Extra: []byte{MetaDirExtra[1], MetaDirExtra[0], 0, 0},
76 }
77 dirHeader.SetMode(0700 | os.ModeDir)
78 dirHeader.SetModTime(DefaultTime)
79
80 return dirHeader
81}
82
Colin Cross05518bc2018-09-27 15:06:19 -070083// Create a manifest zip header and contents using the provided contents if any.
84func ManifestFileContents(contents []byte) (*zip.FileHeader, []byte, error) {
85 b, err := manifestContents(contents)
Colin Cross635acc92017-09-12 22:50:46 -070086 if err != nil {
87 return nil, nil, err
88 }
89
90 fh := &zip.FileHeader{
91 Name: ManifestFile,
92 Method: zip.Store,
93 UncompressedSize64: uint64(len(b)),
94 }
Colin Cross2825cb32017-09-29 13:57:10 -070095 fh.SetMode(0700)
96 fh.SetModTime(DefaultTime)
Colin Cross635acc92017-09-12 22:50:46 -070097
98 return fh, b, nil
99}
100
Colin Cross05518bc2018-09-27 15:06:19 -0700101// Create manifest contents, using the provided contents if any.
102func manifestContents(contents []byte) ([]byte, error) {
Colin Cross635acc92017-09-12 22:50:46 -0700103 manifestMarker := []byte("Manifest-Version:")
104 header := append(manifestMarker, []byte(" 1.0\nCreated-By: soong_zip\n")...)
105
106 var finalBytes []byte
Colin Cross05518bc2018-09-27 15:06:19 -0700107 if !bytes.Contains(contents, manifestMarker) {
108 finalBytes = append(append(header, contents...), byte('\n'))
Colin Cross635acc92017-09-12 22:50:46 -0700109 } else {
Colin Cross05518bc2018-09-27 15:06:19 -0700110 finalBytes = contents
Colin Cross635acc92017-09-12 22:50:46 -0700111 }
112
113 return finalBytes, nil
114}