1 /* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 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 */ 15 16 package ohos; 17 18 import ohos.utils.fastjson.JSONObject; 19 20 import java.io.File; 21 import java.io.IOException; 22 import java.io.RandomAccessFile; 23 import java.util.Optional; 24 25 /** 26 * bin file to hap tool main class. 27 * 28 */ 29 public class CollectBinInfo { 30 private static final String JSON_FILE_NAME = "config.json"; 31 private static final String PROFILE_KEY = "app"; 32 private static final String VERSION_KEY = "version"; 33 private static final String CODE_KEY = "code"; 34 private static final String BIN_PATH = "--bin-path"; 35 private static final String VERSION_CODE = "--version-code"; 36 private static final int PARA_COUNT = 3; 37 private static final int MAGIC_NUMBER = 190; 38 private static final int INT_LENGTH = 4; 39 private static final int LONG_LENGTH = 8; 40 private static int bundleNameLen = 0; 41 42 /** 43 * get versionCode from bin file 44 * 45 * @param binPath: bin path 46 * @return versionCode 47 */ getVersionCode(final String binPath)48 public static String getVersionCode(final String binPath) { 49 String versionCode = ""; 50 if (!FileUtils.checkFileIsExists(binPath)) { 51 return versionCode; 52 } 53 54 Optional<String> absBinPath = FileUtils.getFormatedPath(binPath); 55 RandomAccessFile binStream = null; 56 try { 57 binStream = new RandomAccessFile(absBinPath.get(), "r"); 58 if (!readBinFileHeader(binStream)) { 59 return versionCode; 60 } 61 long fileDataPos = 1 + INT_LENGTH + bundleNameLen; 62 byte [] fileDataByte = readBinFileData(JSON_FILE_NAME, binStream, fileDataPos); 63 if (fileDataByte == null) { 64 return versionCode; 65 } 66 String fileData = new String(fileDataByte, "UTF-8"); 67 JSONObject object = JSONObject.parseObject(fileData); 68 if (object == null || !object.containsKey(PROFILE_KEY)) { 69 return versionCode; 70 } 71 object = object.getJSONObject(PROFILE_KEY); 72 if (object == null || !object.containsKey(VERSION_KEY)) { 73 return versionCode; 74 } 75 object = object.getJSONObject(VERSION_KEY); 76 if (object != null) { 77 versionCode = object.getInteger(CODE_KEY).toString(); 78 } 79 return versionCode; 80 } catch (IOException msg) { 81 return versionCode; 82 } finally { 83 if (binStream != null) { 84 FileUtils.closeStream(binStream); 85 } 86 } 87 } 88 89 /** 90 * read bin file header 91 * 92 * @param binStream: bin randAccessFileStream 93 * @return true or false 94 */ readBinFileHeader(RandomAccessFile binStream)95 private static boolean readBinFileHeader(RandomAccessFile binStream) { 96 try { 97 byte magic = binStream.readByte(); 98 if ((magic & 0xff) != MAGIC_NUMBER) { 99 return false; 100 } 101 bundleNameLen = binStream.readInt(); 102 if (bundleNameLen >= 0) { 103 byte [] bundleNameByte = new byte[bundleNameLen]; 104 binStream.readFully(bundleNameByte, 0, bundleNameLen); 105 return true; 106 } 107 return false; 108 } catch (IOException msg) { 109 return false; 110 } 111 } 112 113 /** 114 * read bin file data 115 * 116 * @param fileName: file name 117 * @param binStream: bin randAccessFileStream 118 * @param fileDataPos: position which begin to read file data 119 * @return fileData byte 120 */ readBinFileData(final String fileName, RandomAccessFile binStream, long fileDataPos)121 private static byte [] readBinFileData(final String fileName, RandomAccessFile binStream, long fileDataPos) { 122 try { 123 long fileSize = binStream.length(); 124 long pos = fileDataPos; 125 while (pos < fileSize) { 126 int nameLen = binStream.readInt(); 127 if (nameLen <= 0) { 128 return null; 129 } 130 byte [] fileNameByte = new byte[nameLen]; 131 binStream.readFully(fileNameByte, 0, nameLen); 132 int relativePathLen = binStream.readInt(); 133 if (relativePathLen < 0) { 134 return null; 135 } 136 binStream.seek(pos + INT_LENGTH + nameLen + INT_LENGTH + relativePathLen); 137 long dataLen = binStream.readLong(); 138 if (dataLen > Integer.MAX_VALUE || dataLen <= 0) { 139 return null; 140 } 141 byte [] fileData = new byte[(int) dataLen]; 142 binStream.readFully(fileData, 0, (int) dataLen); 143 pos = pos + INT_LENGTH + nameLen + INT_LENGTH + relativePathLen + LONG_LENGTH + dataLen; 144 String name = new String(fileNameByte, "UTF-8"); 145 if (name.equals(fileName)) { 146 return fileData; 147 } 148 } 149 return null; 150 } catch (IOException msg) { 151 return null; 152 } 153 } 154 155 /** 156 * tool main function. 157 * 158 * @param args command line 159 */ main(String[] args)160 public static void main(String[] args) { 161 if (args.length != PARA_COUNT) { 162 return; 163 } 164 String binPath = ""; 165 int count = 0; 166 boolean versionFlag = false; 167 for (String para : args) { 168 if (para.equals(BIN_PATH) && count < args.length - 1) { 169 binPath = args[count + 1]; 170 } 171 if (para.equals(VERSION_CODE) && count < args.length) { 172 versionFlag = true; 173 } 174 count++; 175 } 176 if (!binPath.isEmpty() && versionFlag) { 177 String versionCode = getVersionCode(binPath); 178 } 179 } 180 }