diff options
author | Neil Fuller <nfuller@google.com> | 2017-02-21 14:15:21 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2017-02-21 14:15:22 +0000 |
commit | b8806fa29cd5d71127cdb374724e720d657de9f3 (patch) | |
tree | 9683f14560196a9ed8f0419436405db34ce24014 /tzdata | |
parent | fd4e69fdfc0e1a0cc1ce598020eaaf8512519903 (diff) | |
parent | c20667d337002eaa9b0ff4cc89a3c93a61b4bc92 (diff) | |
download | libcore-b8806fa29cd5d71127cdb374724e720d657de9f3.tar.gz |
Merge "Remove V1 updater code now V2 is in use"
Diffstat (limited to 'tzdata')
-rw-r--r-- | tzdata/tools/Android.mk | 27 | ||||
-rwxr-xr-x | tzdata/tools/createIcuUpdateResources.sh | 89 | ||||
-rwxr-xr-x | tzdata/tools/createTzDataBundle.sh | 25 | ||||
-rw-r--r-- | tzdata/tools/src/main/libcore/tzdata/update/tools/CreateTzDataBundle.java | 127 | ||||
-rw-r--r-- | tzdata/tools/src/main/libcore/tzdata/update/tools/TzDataBundleBuilder.java | 134 | ||||
-rwxr-xr-x | tzdata/tools/testing/prepareTzDataUpdates.sh | 173 | ||||
-rwxr-xr-x | tzdata/tools/testing/rebootAndGrabLogs.sh | 25 | ||||
-rw-r--r-- | tzdata/tools/tzupdate.properties | 14 | ||||
-rw-r--r-- | tzdata/update/Android.mk | 35 | ||||
-rw-r--r-- | tzdata/update/src/main/libcore/tzdata/update/ConfigBundle.java | 123 | ||||
-rw-r--r-- | tzdata/update/src/main/libcore/tzdata/update/FileUtils.java | 197 | ||||
-rw-r--r-- | tzdata/update/src/main/libcore/tzdata/update/TzDataBundleInstaller.java | 141 | ||||
-rw-r--r-- | tzdata/update/src/test/libcore/tzdata/update/ConfigBundleTest.java | 151 | ||||
-rw-r--r-- | tzdata/update/src/test/libcore/tzdata/update/FileUtilsTest.java | 329 | ||||
-rw-r--r-- | tzdata/update/src/test/libcore/tzdata/update/TzDataBundleInstallerTest.java | 210 |
15 files changed, 0 insertions, 1800 deletions
diff --git a/tzdata/tools/Android.mk b/tzdata/tools/Android.mk deleted file mode 100644 index 906d8666bd2..00000000000 --- a/tzdata/tools/Android.mk +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright (C) 2015 The Android Open Source Project -# -# 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. - -LOCAL_PATH:= $(call my-dir) - -# Library of tools classes for tzdata updates. Not required on device, except in tests. -include $(CLEAR_VARS) -LOCAL_MODULE := tzdata_tools -LOCAL_MODULE_TAGS := optional -LOCAL_SRC_FILES := $(call all-java-files-under, src/main) -LOCAL_JAVACFLAGS := -encoding UTF-8 -LOCAL_JAVA_LIBRARIES := core-oj core-libart -LOCAL_NO_STANDARD_LIBRARIES := true -LOCAL_STATIC_JAVA_LIBRARIES := tzdata_update -LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk -include $(BUILD_STATIC_JAVA_LIBRARY) diff --git a/tzdata/tools/createIcuUpdateResources.sh b/tzdata/tools/createIcuUpdateResources.sh deleted file mode 100755 index 2db71328415..00000000000 --- a/tzdata/tools/createIcuUpdateResources.sh +++ /dev/null @@ -1,89 +0,0 @@ -#!/bin/bash -# -# A script that generates an ICU data file containing just timezone rules data. -# The file can be used to provide time zone rules updates for compatible -# devices. Note: Only the rules are contained and new timezones will not have -# the translations. -# -# Usage: -# ./createIcuUpdateResources.sh <tzdata tar.gz file> <ICU version> -# -# e.g. -# ./createIcuUpdateResources.sh ~/Downloads/tzdata2015b.tar.gz 55 -# -# After execution the file is generated. - -if (( $# != 2 )); then - echo "Missing arguments" - echo "Usage:" - echo "./createIcuUpdateResources.sh <tzdata tar.gz file> <ICU version>" - exit 1 -fi - -if [[ -z "${ANDROID_BUILD_TOP}" ]]; then - echo "Configure your environment with build/envsetup.sh and lunch" - exit 1 -fi - -TZ_DATA_FILE=$1 -ICU_VERSION=$2 - -if [[ ! -f ${TZ_DATA_FILE} ]]; then - echo "${TZ_DATA_FILE} not found" - exit 1 -fi - -# Keep track of the original working dir. Must be the "tools" dir. -START_DIR=`pwd` -ICU_DIR=${ANDROID_BUILD_TOP}/external/icu/icu4c/source -BUILD_DIR=${START_DIR}/icu_build - -# Fail if anything below fails -set -e - -rm -rf ${BUILD_DIR} -mkdir -p ${BUILD_DIR} -cd ${BUILD_DIR} - -# Configure the build -${ICU_DIR}/runConfigureICU Linux -mkdir -p ${BUILD_DIR}/bin -cd ${BUILD_DIR}/tools/tzcode -ln -s ${ICU_DIR}/tools/tzcode/icuregions ./icuregions -ln -s ${ICU_DIR}/tools/tzcode/icuzones ./icuzones -cp ${TZ_DATA_FILE} . - -# Make the tools -make - -# Then make the whole thing -cd ${BUILD_DIR} -make -j32 - -# Generate the tzdata.lst file used to configure which files are included. -ICU_LIB_DIR=${BUILD_DIR}/lib -BIN_DIR=${BUILD_DIR}/bin -TZ_FILES=tzdata.lst - -echo metaZones.res > ${TZ_FILES} -echo timezoneTypes.res >> ${TZ_FILES} -echo windowsZones.res >> ${TZ_FILES} -echo zoneinfo64.res >> ${TZ_FILES} - -# Copy all the .res files we need here a from, e.g. ./data/out/build/icudt55l -RES_DIR=data/out/build/icudt${ICU_VERSION}l -cp ${RES_DIR}/metaZones.res ${BUILD_DIR} -cp ${RES_DIR}/timezoneTypes.res ${BUILD_DIR} -cp ${RES_DIR}/windowsZones.res ${BUILD_DIR} -cp ${RES_DIR}/zoneinfo64.res ${BUILD_DIR} - -# This is the package name required for the .dat file to be accepted by ICU. -# This also affects the generated file name. -ICU_PACKAGE=icudt${ICU_VERSION}l - -# Create the file -LD_LIBRARY_PATH=${ICU_LIB_DIR} ${BIN_DIR}/pkgdata -F -m common -v -T . -d . -p ${ICU_PACKAGE} ${TZ_FILES} -cp ${ICU_PACKAGE}.dat ${START_DIR}/icu_tzdata.dat - -# Copy the file to the original working dir. -echo File can be found here: ${START_DIR}/icu_tzdata.dat diff --git a/tzdata/tools/createTzDataBundle.sh b/tzdata/tools/createTzDataBundle.sh deleted file mode 100755 index 05646fc157f..00000000000 --- a/tzdata/tools/createTzDataBundle.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash - -# A script to generate TZ data updates. -# -# Usage: ./createTzDataBundle.sh <tzupdate.properties file> <output file> -# See libcore.tzdata.update.tools.CreateTzDataBundle for more information. - -TOOLS_DIR=src/main/libcore/tzdata/update/tools -UPDATE_DIR=../update/src/main/libcore/tzdata/update -GEN_DIR=./gen - -# Fail if anything below fails -set -e - -rm -rf ${GEN_DIR} -mkdir -p ${GEN_DIR} - -javac \ - ${TOOLS_DIR}/CreateTzDataBundle.java \ - ${TOOLS_DIR}/TzDataBundleBuilder.java \ - ${UPDATE_DIR}/ConfigBundle.java \ - ${UPDATE_DIR}/FileUtils.java \ - -d ${GEN_DIR} - -java -cp ${GEN_DIR} libcore.tzdata.update.tools.CreateTzDataBundle $@ diff --git a/tzdata/tools/src/main/libcore/tzdata/update/tools/CreateTzDataBundle.java b/tzdata/tools/src/main/libcore/tzdata/update/tools/CreateTzDataBundle.java deleted file mode 100644 index cdb004a0aa0..00000000000 --- a/tzdata/tools/src/main/libcore/tzdata/update/tools/CreateTzDataBundle.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * 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 libcore.tzdata.update.tools; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.Reader; -import java.util.Properties; -import libcore.tzdata.update.ConfigBundle; -import libcore.tzdata.update.FileUtils; - -/** - * A command-line tool for creating a TZ data update bundle. - * - * Args: - * tzdata.properties file - the file describing the bundle (see template file in tzdata/tools) - * output file - the name of the file to be generated - */ -public class CreateTzDataBundle { - - private CreateTzDataBundle() {} - - public static void main(String[] args) throws Exception { - if (args.length != 2) { - printUsage(); - System.exit(1); - } - File f = new File(args[0]); - if (!f.exists()) { - System.err.println("Properties file " + f + " not found"); - printUsage(); - System.exit(2); - } - Properties p = loadProperties(f); - TzDataBundleBuilder builder = new TzDataBundleBuilder() - .setTzDataVersion(getMandatoryProperty(p, "tzdata.version")) - .addBionicTzData(getMandatoryPropertyFile(p, "bionic.file")) - .addIcuTzData(getMandatoryPropertyFile(p, "icu.file")); - - int i = 1; - while (true) { - String localFileNameProperty = "checksum.file.local." + i; - String localFileName = p.getProperty(localFileNameProperty); - String onDeviceFileNameProperty = "checksum.file.ondevice." + i; - String onDeviceFileName = p.getProperty(onDeviceFileNameProperty); - boolean foundLocalFileNameProperty = localFileName != null; - boolean foundOnDeviceFileNameProperty = onDeviceFileName != null; - if (!foundLocalFileNameProperty && !foundOnDeviceFileNameProperty) { - break; - } else if (foundLocalFileNameProperty != foundOnDeviceFileNameProperty) { - System.out.println("Properties file must specify both, or neither of: " - + localFileNameProperty + " and " + onDeviceFileNameProperty); - System.exit(5); - } - - long checksum = FileUtils.calculateChecksum(new File(localFileName)); - builder.addChecksum(onDeviceFileName, checksum); - i++; - } - if (i == 1) { - // For safety we enforce >= 1 checksum entry. The installer does not require it. - System.out.println("There must be at least one checksum file"); - System.exit(6); - } - System.out.println("Update contains checksums for " + (i-1) + " files"); - - ConfigBundle bundle = builder.build(); - File outputFile = new File(args[1]); - try (OutputStream os = new FileOutputStream(outputFile)) { - os.write(bundle.getBundleBytes()); - } - System.out.println("Wrote: " + outputFile); - } - - private static File getMandatoryPropertyFile(Properties p, String propertyName) { - String fileName = getMandatoryProperty(p, propertyName); - File file = new File(fileName); - if (!file.exists()) { - System.out.println( - "Missing file: " + file + " for property " + propertyName + " does not exist."); - printUsage(); - System.exit(4); - } - return file; - } - - private static String getMandatoryProperty(Properties p, String propertyName) { - String value = p.getProperty(propertyName); - if (value == null) { - System.out.println("Missing property: " + propertyName); - printUsage(); - System.exit(3); - } - return value; - } - - private static Properties loadProperties(File f) throws IOException { - Properties p = new Properties(); - try (Reader reader = new InputStreamReader(new FileInputStream(f))) { - p.load(reader); - } - return p; - } - - private static void printUsage() { - System.out.println("Usage:"); - System.out.println("\t" + CreateTzDataBundle.class.getName() + - " <tzupdate.properties file> <output file>"); - } -} diff --git a/tzdata/tools/src/main/libcore/tzdata/update/tools/TzDataBundleBuilder.java b/tzdata/tools/src/main/libcore/tzdata/update/tools/TzDataBundleBuilder.java deleted file mode 100644 index 3550c6f9f61..00000000000 --- a/tzdata/tools/src/main/libcore/tzdata/update/tools/TzDataBundleBuilder.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * 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 libcore.tzdata.update.tools; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; -import libcore.tzdata.update.ConfigBundle; - -/** - * A class for creating a {@link ConfigBundle} containing timezone update data. - */ -public final class TzDataBundleBuilder { - - private String tzDataVersion; - private StringBuilder checksumsFileContent = new StringBuilder(); - private File zoneInfoFile; - private File icuTzDataFile; - - public TzDataBundleBuilder setTzDataVersion(String tzDataVersion) { - this.tzDataVersion = tzDataVersion; - return this; - } - - public TzDataBundleBuilder addChecksum(String fileName, long checksum) { - checksumsFileContent.append(Long.toString(checksum)) - .append(',') - .append(fileName) - .append('\n'); - return this; - } - - public TzDataBundleBuilder addBionicTzData(File zoneInfoFile) { - this.zoneInfoFile = zoneInfoFile; - return this; - } - - public TzDataBundleBuilder addIcuTzData(File icuTzDataFile) { - this.icuTzDataFile = icuTzDataFile; - return this; - } - - /** - * Builds a {@link libcore.tzdata.update.ConfigBundle}. - */ - public ConfigBundle build() throws IOException { - if (tzDataVersion == null) { - throw new IllegalStateException("Missing tzDataVersion"); - } - if (zoneInfoFile == null) { - throw new IllegalStateException("Missing zoneInfo file"); - } - - return buildUnvalidated(); - } - - // For use in tests. - public TzDataBundleBuilder clearChecksumEntries() { - checksumsFileContent.setLength(0); - return this; - } - - // For use in tests. - public TzDataBundleBuilder clearBionicTzData() { - this.zoneInfoFile = null; - return this; - } - - /** - * For use in tests. Use {@link #build()}. - */ - public ConfigBundle buildUnvalidated() throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try (ZipOutputStream zos = new ZipOutputStream(baos)) { - addZipEntry(zos, ConfigBundle.CHECKSUMS_FILE_NAME, - checksumsFileContent.toString().getBytes(StandardCharsets.UTF_8)); - if (tzDataVersion != null) { - addZipEntry(zos, ConfigBundle.TZ_DATA_VERSION_FILE_NAME, - tzDataVersion.getBytes(StandardCharsets.UTF_8)); - } - if (zoneInfoFile != null) { - addZipEntry(zos, ConfigBundle.ZONEINFO_FILE_NAME, - readFileAsByteArray(zoneInfoFile)); - } - if (icuTzDataFile != null) { - addZipEntry(zos, ConfigBundle.ICU_DATA_FILE_NAME, - readFileAsByteArray(icuTzDataFile)); - } - } - return new ConfigBundle(baos.toByteArray()); - } - - private static void addZipEntry(ZipOutputStream zos, String name, byte[] content) - throws IOException { - ZipEntry zipEntry = new ZipEntry(name); - zipEntry.setSize(content.length); - zos.putNextEntry(zipEntry); - zos.write(content); - zos.closeEntry(); - } - - /** - * Returns the contents of 'path' as a byte array. - */ - public static byte[] readFileAsByteArray(File file) throws IOException { - byte[] buffer = new byte[8192]; - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try (FileInputStream fis = new FileInputStream(file)) { - int count; - while ((count = fis.read(buffer)) != -1) { - baos.write(buffer, 0, count); - } - } - return baos.toByteArray(); - } -} - diff --git a/tzdata/tools/testing/prepareTzDataUpdates.sh b/tzdata/tools/testing/prepareTzDataUpdates.sh deleted file mode 100755 index a9fe10c54f3..00000000000 --- a/tzdata/tools/testing/prepareTzDataUpdates.sh +++ /dev/null @@ -1,173 +0,0 @@ -#!/bin/bash - -# Used as part of manual testing of tzdata update mechanism. - -if [[ -z "${ANDROID_BUILD_TOP}" ]]; then - echo "Configure your environment with build/envsetup.sh and lunch" - exit 1 -fi - -# Fail if anything below fails -set -e - -cd $ANDROID_BUILD_TOP - -# Get the ICU version by looking at the stubdata file -ICU_STUB_FILE=$(ls external/icu/icu4c/source/stubdata/icudt*l.dat) -if [ $(echo "$ICU_STUB_FILE" | wc -l) -ne 1 ]; then - echo "Could not find unique ICU version from external/icu/icu4c/source/stubdata/icudt*l.dat" - exit 1 -fi - -ICU_VERSION=${ICU_STUB_FILE##*icudt} -ICU_VERSION=${ICU_VERSION%l.dat} - -echo "Current ICU version is ${ICU_VERSION}" - -# Get the current tzdata version and find both the previous and new versions. -TZDATA=libc/zoneinfo/tzdata - -TZHEADER=$(head -n1 bionic/$TZDATA | cut -c1-11) - -TZ_CURRENT=${TZHEADER:6} - -let currentYear=${TZ_CURRENT:0:4} -update=${TZ_CURRENT:4:1} - -let currentUpdate=$(LC_CTYPE=C printf '%d' "'$update") -let previousUpdate=currentUpdate-1 -if [ $previousUpdate -lt 97 ]; then - let previousYear=currentYear-1 - PREVIOUSCOMMIT=$(cd bionic; git log --format=oneline ${TZDATA} | grep -E "${previousYear}.$" | head -n1) - TZ_PREVIOUS=$(echo $PREVIOUSCOMMIT | sed "s|.*\(${previousYear}.\)\$|\1|") -else - TZ_PREVIOUS=${currentYear}$(printf "\\$(printf '%03o' "${previousUpdate}")") - PREVIOUSCOMMIT=$(cd bionic; git log --format=oneline ${TZDATA} | grep -E "${TZ_PREVIOUS}$" | head -n1) -fi - -let nextUpdate=currentUpdate+1 -TZ_NEXT=${currentYear}$(printf "\\$(printf '%03o' "${nextUpdate}")") - -echo "Current version of bionic/${TZDATA} is ${TZ_CURRENT}" -echo "Previous version of bionic/${TZDATA} is ${TZ_PREVIOUS} from commit:" -echo " ${PREVIOUSCOMMIT}" -echo "Next version of bionic/${TZDATA} is ${TZ_NEXT}" - -TMP=$(mktemp -d) - -TZ_PREVIOUS_SHA=${PREVIOUSCOMMIT%% *} - -TMP_PREVIOUS=${TMP}/${TZ_PREVIOUS}_test -mkdir -p ${TMP_PREVIOUS} - -echo "Copied ${TZ_PREVIOUS} tzdata to ${TMP_PREVIOUS}" -(cd bionic; git show ${TZ_PREVIOUS_SHA}:${TZDATA} > ${TMP_PREVIOUS}/tzdata) - -cd libcore/tzdata/tools - -################################################################ -# Preparing previous update version. -################################################################ - -# Create an icu_tzdata.dat for the previous tzdata version. -# Download the archive for the previous tzdata version. -PREVIOUS_TAR_GZ="tzdata${TZ_PREVIOUS}.tar.gz" -TMP_PREVIOUS_TAR_GZ=${TMP}/${PREVIOUS_TAR_GZ} -IANA_PREVIOUS_URL="ftp://ftp.iana.org/tz/releases/${PREVIOUS_TAR_GZ}" -echo "Downloading archive for ${TZ_PREVIOUS} version from ${IANA_PREVIOUS_URL}" -wget -O ${TMP_PREVIOUS_TAR_GZ} ftp://ftp.iana.org/tz/releases/tzdata2016d.tar.gz -o ${TMP}/${PREVIOUS_TAR_GZ}.log - -ICU_UPDATE_RESOURCES_LOG=${TMP}/icuUpdateResources.log -echo "Creating icu_tzdata.dat file for ${TZ_PREVIOUS}/ICU ${ICU_VERSION}, may take a while, check ${ICU_UPDATE_RESOURCES_LOG} for details" -./createIcuUpdateResources.sh ${TMP_PREVIOUS_TAR_GZ} ${ICU_VERSION} &> ${ICU_UPDATE_RESOURCES_LOG} -mv icu_tzdata.dat ${TMP_PREVIOUS} - -TZ_PREVIOUS_UPDATE_PROPERTIES=${TMP}/tzupdate.properties.${TZ_PREVIOUS} -cat > ${TZ_PREVIOUS_UPDATE_PROPERTIES} <<EOF -tzdata.version=${TZ_PREVIOUS} -bionic.file=${TMP_PREVIOUS}/tzdata -icu.file=${TMP_PREVIOUS}/icu_tzdata.dat - -checksum.file.local.1=../../../bionic/libc/zoneinfo/tzdata -checksum.file.ondevice.1=/system/usr/share/zoneinfo/tzdata -checksum.file.local.2=../../../external/icu/icu4c/source/stubdata/icudt${ICU_VERSION}l.dat -checksum.file.ondevice.2=/system/usr/icu/icudt${ICU_VERSION}l.dat -EOF - -TZ_PREVIOUS_UPDATE_ZIP=update_${TZ_PREVIOUS}_test.zip -./createTzDataBundle.sh ${TZ_PREVIOUS_UPDATE_PROPERTIES} ${TMP}/update_${TZ_PREVIOUS}_test.zip -adb push ${TMP}/${TZ_PREVIOUS_UPDATE_ZIP} /data/local/tmp -echo "Pushed ${TZ_PREVIOUS_UPDATE_ZIP} to /data/local/tmp" - -################################################################ -# Preparing next update version. -################################################################ - -# Replace the version number in the previous tzdata to create the next version -TMP_NEXT=${TMP}/${TZ_NEXT}_test -mkdir -p ${TMP_NEXT} -sed "1s/^tzdata${TZ_PREVIOUS}/tzdata${TZ_NEXT}/" ${TMP_PREVIOUS}/tzdata > ${TMP_NEXT}/tzdata -echo "Transformed version ${TZ_PREVIOUS} of tzdata into version ${TZ_NEXT}" - -# Replace the version number in the previous icu_tzdata to create the next version -SEARCH=$(echo ${TZ_PREVIOUS} | sed "s/\(.\)/\1\\\x00/g") -REPLACE=$(echo ${TZ_NEXT} | sed "s/\(.\)/\1\\\x00/g") -sed "s/$SEARCH/$REPLACE/" ${TMP_PREVIOUS}/icu_tzdata.dat > ${TMP_NEXT}/icu_tzdata.dat -echo "Transformed version ${TZ_PREVIOUS} of icu_tzdata into version ${TZ_NEXT}" - -TZ_NEXT_UPDATE_PROPERTIES=${TMP}/tzupdate.properties.${TZ_NEXT} -cat > ${TZ_NEXT_UPDATE_PROPERTIES} <<EOF -tzdata.version=${TZ_NEXT} -bionic.file=${TMP_NEXT}/tzdata -icu.file=${TMP_NEXT}/icu_tzdata.dat - -checksum.file.local.1=../../../bionic/libc/zoneinfo/tzdata -checksum.file.ondevice.1=/system/usr/share/zoneinfo/tzdata -checksum.file.local.2=../../../external/icu/icu4c/source/stubdata/icudt${ICU_VERSION}l.dat -checksum.file.ondevice.2=/system/usr/icu/icudt${ICU_VERSION}l.dat -EOF - -TZ_NEXT_UPDATE_ZIP=update_${TZ_NEXT}_test.zip -./createTzDataBundle.sh ${TZ_NEXT_UPDATE_PROPERTIES} ${TMP}/update_${TZ_NEXT}_test.zip -adb push ${TMP}/${TZ_NEXT_UPDATE_ZIP} /data/local/tmp -echo "Pushed ${TZ_NEXT_UPDATE_ZIP} to /data/local/tmp" - -################################################################ -# Preparing bad update version. -################################################################ - -TZ_BAD=${TZ_NEXT}_bad_sum -TZ_BAD_UPDATE_PROPERTIES=${TMP}/tzupdate.properties.${TZ_BAD} -cat > ${TZ_BAD_UPDATE_PROPERTIES} <<EOF -tzdata.version=${TZ_BAD} -bionic.file=${TMP_NEXT}/tzdata -icu.file=${TMP_NEXT}/icu_tzdata.dat - -checksum.file.local.1=${ANDROID_BUILD_TOP}/bionic/${TZDATA} -checksum.file.ondevice.1=/system/usr/share/zoneinfo/tzdata - -# The wrong checksum -checksum.file.local.2=${ANDROID_BUILD_TOP}/libcore/Android.mk -checksum.file.ondevice.2=/system/usr/icu/icudt${ICU_VERSION}l.dat -EOF - -TZ_BAD_UPDATE_ZIP=update_${TZ_BAD}_test.zip -./createTzDataBundle.sh ${TZ_BAD_UPDATE_PROPERTIES} ${TMP}/update_${TZ_BAD}_test.zip -adb push ${TMP}/${TZ_BAD_UPDATE_ZIP} /data/local/tmp -echo "Pushed ${TZ_BAD_UPDATE_ZIP} to /data/local/tmp" - -################################################################ -# Preparing UpdateTestApp -################################################################ - -UPDATE_TEST_APP_LOG=${TMP}/updateTestApp.log -echo "Building and installing UpdateTestApp, check ${UPDATE_TEST_APP_LOG}" -cd $ANDROID_BUILD_TOP -make -j -l8 UpdateTestApp &> ${UPDATE_TEST_APP_LOG} -adb install -r ${ANDROID_PRODUCT_OUT}/data/app/UpdateTestApp/UpdateTestApp.apk &>> ${UPDATE_TEST_APP_LOG} - -echo -echo "Paste the following into your shell" -echo "OLD_TZUPDATE=${TMP}/${TZ_PREVIOUS_UPDATE_ZIP}" -echo "NEW_TZUPDATE=${TMP}/${TZ_NEXT_UPDATE_ZIP}" -echo "BAD_TZUPDATE=${TMP}/${TZ_BAD_UPDATE_ZIP}" diff --git a/tzdata/tools/testing/rebootAndGrabLogs.sh b/tzdata/tools/testing/rebootAndGrabLogs.sh deleted file mode 100755 index a85481f9637..00000000000 --- a/tzdata/tools/testing/rebootAndGrabLogs.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash - -# Used as part of manual testing of tzdata update mechanism. - -PREFIX=${1-bootlogs} - -echo "Rebooting...." -adb reboot && adb wait-for-device - -TIME=${2-5} -LOGCAT=${PREFIX}.logcat -echo "Dumping logcat output in ${LOGCAT}, waiting for ${TIME} seconds" -adb logcat > ${LOGCAT} 2>/dev/null & -LOGCAT_PID=$! - -sleep ${TIME} - -# Kill the logcat process and wait, suppresses the Terminated message -# output by the shell. -kill ${LOGCAT_PID} -wait ${LOGCAT_PID} 2>/dev/null - -DMESG=${PREFIX}.dmesg -echo "Dumping dmesg output in ${DMESG}" -adb shell dmesg > ${DMESG} diff --git a/tzdata/tools/tzupdate.properties b/tzdata/tools/tzupdate.properties deleted file mode 100644 index e3fe00256c3..00000000000 --- a/tzdata/tools/tzupdate.properties +++ /dev/null @@ -1,14 +0,0 @@ -# Edit these to reflect the update files. - -# This should be the tzdata version. e.g. "2015a". Lexicographical sort order -# may become important in future so if inventing interim releases only add -# characters to the end. -tzdata.version= -bionic.file= -icu.file= - -# Edit these as required to point to the file expected to exist on the device. -checksum.file.local.1=../../../bionic/libc/zoneinfo/tzdata -checksum.file.ondevice.1=/system/usr/share/zoneinfo/tzdata -checksum.file.local.2=../../../external/icu/icu4c/source/stubdata/icudt55l.dat -checksum.file.ondevice.2=/system/usr/icu/icudt55l.dat diff --git a/tzdata/update/Android.mk b/tzdata/update/Android.mk deleted file mode 100644 index 8b45b7f12f3..00000000000 --- a/tzdata/update/Android.mk +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright (C) 2015 The Android Open Source Project -# -# 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. - -LOCAL_PATH:= $(call my-dir) - -# Library of support classes for tzdata updates. Shared between update generation and -# on-device code. -include $(CLEAR_VARS) -LOCAL_MODULE := tzdata_update -LOCAL_MODULE_TAGS := optional -LOCAL_SRC_FILES := $(call all-java-files-under, src/main) -LOCAL_JAVACFLAGS := -encoding UTF-8 -LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk -include $(BUILD_STATIC_JAVA_LIBRARY) - -# Tests for tzdata_update code -include $(CLEAR_VARS) -LOCAL_MODULE := tzdata_update-tests -LOCAL_MODULE_TAGS := optional -LOCAL_SRC_FILES := $(call all-java-files-under, src/test) -LOCAL_JAVACFLAGS := -encoding UTF-8 -LOCAL_STATIC_JAVA_LIBRARIES := tzdata_update tzdata_tools junit -LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk -include $(BUILD_STATIC_JAVA_LIBRARY) diff --git a/tzdata/update/src/main/libcore/tzdata/update/ConfigBundle.java b/tzdata/update/src/main/libcore/tzdata/update/ConfigBundle.java deleted file mode 100644 index b497c856417..00000000000 --- a/tzdata/update/src/main/libcore/tzdata/update/ConfigBundle.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * 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 libcore.tzdata.update; - -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Arrays; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; - -/** - * A configuration bundle. This is a thin wrapper around some in-memory bytes representing a zip - * archive and logic for its safe extraction. - */ -public final class ConfigBundle { - - /** The name of the file inside the bundle containing the TZ data version. */ - public static final String TZ_DATA_VERSION_FILE_NAME = "tzdata_version"; - - /** The name of the file inside the bundle containing the expected device checksums. */ - public static final String CHECKSUMS_FILE_NAME = "checksums"; - - /** The name of the file inside the bundle containing bionic/libcore TZ data. */ - public static final String ZONEINFO_FILE_NAME = "tzdata"; - - /** The name of the file inside the bundle containing ICU TZ data. */ - public static final String ICU_DATA_FILE_NAME = "icu/icu_tzdata.dat"; - - private static final int BUFFER_SIZE = 8192; - - private final byte[] bytes; - - public ConfigBundle(byte[] bytes) { - this.bytes = bytes; - } - - public byte[] getBundleBytes() { - return bytes; - } - - public void extractTo(File targetDir) throws IOException { - extractZipSafely(new ByteArrayInputStream(bytes), targetDir, true /* makeWorldReadable */); - } - - /** Visible for testing */ - static void extractZipSafely(InputStream is, File targetDir, boolean makeWorldReadable) - throws IOException { - - // Create the extraction dir, if needed. - FileUtils.ensureDirectoriesExist(targetDir, makeWorldReadable); - - try (ZipInputStream zipInputStream = new ZipInputStream(is)) { - byte[] buffer = new byte[BUFFER_SIZE]; - ZipEntry entry; - while ((entry = zipInputStream.getNextEntry()) != null) { - // Validate the entry name: make sure the unpacked file will exist beneath the - // targetDir. - String name = entry.getName(); - // Note, we assume that nothing will quickly insert a symlink after createSubFile() - // that might invalidate the guarantees about name existing beneath targetDir. - File entryFile = FileUtils.createSubFile(targetDir, name); - - if (entry.isDirectory()) { - FileUtils.ensureDirectoriesExist(entryFile, makeWorldReadable); - } else { - // Create the path if there was no directory entry. - if (!entryFile.getParentFile().exists()) { - FileUtils.ensureDirectoriesExist( - entryFile.getParentFile(), makeWorldReadable); - } - - try (FileOutputStream fos = new FileOutputStream(entryFile)) { - int count; - while ((count = zipInputStream.read(buffer)) != -1) { - fos.write(buffer, 0, count); - } - // sync to disk - fos.getFD().sync(); - } - // mark entryFile -rw-r--r-- - if (makeWorldReadable) { - FileUtils.makeWorldReadable(entryFile); - } - } - } - } - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - ConfigBundle that = (ConfigBundle) o; - - if (!Arrays.equals(bytes, that.bytes)) { - return false; - } - - return true; - } - -} diff --git a/tzdata/update/src/main/libcore/tzdata/update/FileUtils.java b/tzdata/update/src/main/libcore/tzdata/update/FileUtils.java deleted file mode 100644 index 652b7867145..00000000000 --- a/tzdata/update/src/main/libcore/tzdata/update/FileUtils.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * 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 libcore.tzdata.update; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.LinkedList; -import java.util.List; -import java.util.zip.CRC32; - -/** - * Utility methods for files operations. - */ -public final class FileUtils { - - private FileUtils() { - } - - /** - * Creates a new {@link java.io.File} from the {@code parentDir} and {@code name}, but only if - * the resulting file would exist beneath {@code parentDir}. Useful if {@code name} could - * contain "/../" or symlinks. The returned object has a canonicalized path. - * - * @throws java.io.IOException if the file would not exist beneath {@code parentDir} - */ - public static File createSubFile(File parentDir, String name) throws IOException { - // The subFile must exist beneath parentDir. If name contains "/../" this may not be the - // case so we check. - File subFile = new File(parentDir, name).getCanonicalFile(); - if (!subFile.getPath().startsWith(parentDir.getCanonicalPath())) { - throw new IOException(name + " must exist beneath " + parentDir + - ". Canonicalized subpath: " + subFile); - } - return subFile; - } - - /** - * Makes sure a directory exists. If it doesn't exist, it is created. Parent directories are - * also created as needed. If {@code makeWorldReadable} is {@code true} the directory's default - * permissions will be set. Even when {@code makeWorldReadable} is {@code true}, only - * directories explicitly created will have their permissions set; existing directories are - * untouched. - * - * @throws IOException if the directory or one of its parents did not already exist and could - * not be created - */ - public static void ensureDirectoriesExist(File dir, boolean makeWorldReadable) - throws IOException { - LinkedList<File> dirs = new LinkedList<>(); - File currentDir = dir; - do { - dirs.addFirst(currentDir); - currentDir = currentDir.getParentFile(); - } while (currentDir != null); - - for (File dirToCheck : dirs) { - if (!dirToCheck.exists()) { - if (!dirToCheck.mkdir()) { - throw new IOException("Unable to create directory: " + dir); - } - if (makeWorldReadable) { - makeDirectoryWorldAccessible(dirToCheck); - } - } else if (!dirToCheck.isDirectory()) { - throw new IOException(dirToCheck + " exists but is not a directory"); - } - } - } - - public static void makeDirectoryWorldAccessible(File directory) throws IOException { - if (!directory.isDirectory()) { - throw new IOException(directory + " must be a directory"); - } - makeWorldReadable(directory); - if (!directory.setExecutable(true, false /* ownerOnly */)) { - throw new IOException("Unable to make " + directory + " world-executable"); - } - } - - public static void makeWorldReadable(File file) throws IOException { - if (!file.setReadable(true, false /* ownerOnly */)) { - throw new IOException("Unable to make " + file + " world-readable"); - } - } - - /** - * Calculates the checksum from the contents of a file. - */ - public static long calculateChecksum(File file) throws IOException { - final int BUFFER_SIZE = 8196; - CRC32 crc32 = new CRC32(); - try (FileInputStream fis = new FileInputStream(file)) { - byte[] buffer = new byte[BUFFER_SIZE]; - int count; - while ((count = fis.read(buffer)) != -1) { - crc32.update(buffer, 0, count); - } - } - return crc32.getValue(); - } - - public static void rename(File from, File to) throws IOException { - ensureFileDoesNotExist(to); - if (!from.renameTo(to)) { - throw new IOException("Unable to rename " + from + " to " + to); - } - } - - public static void ensureFileDoesNotExist(File file) throws IOException { - if (file.exists()) { - if (!file.isFile()) { - throw new IOException(file + " is not a file"); - } - doDelete(file); - } - } - - public static void doDelete(File file) throws IOException { - if (!file.delete()) { - throw new IOException("Unable to delete: " + file); - } - } - - public static boolean isSymlink(File file) throws IOException { - String baseName = file.getName(); - String canonicalPathExceptBaseName = - new File(file.getParentFile().getCanonicalFile(), baseName).getPath(); - return !file.getCanonicalPath().equals(canonicalPathExceptBaseName); - } - - public static void deleteRecursive(File toDelete) throws IOException { - if (toDelete.isDirectory()) { - for (File file : toDelete.listFiles()) { - if (file.isDirectory() && !FileUtils.isSymlink(file)) { - // The isSymlink() check is important so that we don't delete files in other - // directories: only the symlink itself. - deleteRecursive(file); - } else { - // Delete symlinks to directories or files. - FileUtils.doDelete(file); - } - } - String[] remainingFiles = toDelete.list(); - if (remainingFiles.length != 0) { - throw new IOException("Unable to delete files: " + Arrays - .toString(remainingFiles)); - } - } - FileUtils.doDelete(toDelete); - } - - public static boolean filesExist(File rootDir, String... fileNames) throws IOException { - for (String fileName : fileNames) { - File file = new File(rootDir, fileName); - if (!file.exists()) { - return false; - } - } - return true; - } - - /** - * Read all lines from a UTF-8 encoded file, returning them as a list of strings. - */ - public static List<String> readLines(File file) throws IOException { - FileInputStream in = new FileInputStream(file); - try (BufferedReader fileReader = new BufferedReader( - new InputStreamReader(in, StandardCharsets.UTF_8)); - ) { - List<String> lines = new ArrayList<>(); - String line; - while ((line = fileReader.readLine()) != null) { - lines.add(line); - } - return lines; - } - } -} diff --git a/tzdata/update/src/main/libcore/tzdata/update/TzDataBundleInstaller.java b/tzdata/update/src/main/libcore/tzdata/update/TzDataBundleInstaller.java deleted file mode 100644 index df0b2a7d227..00000000000 --- a/tzdata/update/src/main/libcore/tzdata/update/TzDataBundleInstaller.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * 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 libcore.tzdata.update; - -import android.util.Slog; - -import java.io.File; -import java.io.IOException; - -/** - * A bundle-validation / extraction class. Separate from the services code that uses it for easier - * testing. - */ -public final class TzDataBundleInstaller { - - static final String CURRENT_TZ_DATA_DIR_NAME = "current"; - static final String WORKING_DIR_NAME = "working"; - static final String OLD_TZ_DATA_DIR_NAME = "old"; - - private final String logTag; - private final File installDir; - - public TzDataBundleInstaller(String logTag, File installDir) { - this.logTag = logTag; - this.installDir = installDir; - } - - /** - * Install the supplied content. - * - * <p>Errors during unpacking or installation will throw an {@link IOException}. - * If the content is invalid this method returns {@code false}. - * If the installation completed successfully this method returns {@code true}. - */ - public boolean install(byte[] content) throws IOException { - File oldTzDataDir = new File(installDir, OLD_TZ_DATA_DIR_NAME); - if (oldTzDataDir.exists()) { - FileUtils.deleteRecursive(oldTzDataDir); - } - - File currentTzDataDir = new File(installDir, CURRENT_TZ_DATA_DIR_NAME); - File workingDir = new File(installDir, WORKING_DIR_NAME); - - Slog.i(logTag, "Applying time zone update"); - File unpackedContentDir = unpackBundle(content, workingDir); - try { - if (!checkBundleFilesExist(unpackedContentDir)) { - Slog.i(logTag, "Update not applied: Bundle is missing files"); - return false; - } - - if (verifySystemChecksums(unpackedContentDir)) { - FileUtils.makeDirectoryWorldAccessible(unpackedContentDir); - - if (currentTzDataDir.exists()) { - Slog.i(logTag, "Moving " + currentTzDataDir + " to " + oldTzDataDir); - FileUtils.rename(currentTzDataDir, oldTzDataDir); - } - Slog.i(logTag, "Moving " + unpackedContentDir + " to " + currentTzDataDir); - FileUtils.rename(unpackedContentDir, currentTzDataDir); - Slog.i(logTag, "Update applied: " + currentTzDataDir + " successfully created"); - return true; - } - Slog.i(logTag, "Update not applied: System checksum did not match"); - return false; - } finally { - deleteBestEffort(oldTzDataDir); - deleteBestEffort(unpackedContentDir); - } - } - - private void deleteBestEffort(File dir) { - if (dir.exists()) { - try { - FileUtils.deleteRecursive(dir); - } catch (IOException e) { - // Logged but otherwise ignored. - Slog.w(logTag, "Unable to delete " + dir, e); - } - } - } - - private File unpackBundle(byte[] content, File targetDir) throws IOException { - Slog.i(logTag, "Unpacking update content to: " + targetDir); - ConfigBundle bundle = new ConfigBundle(content); - bundle.extractTo(targetDir); - return targetDir; - } - - private boolean checkBundleFilesExist(File unpackedContentDir) throws IOException { - Slog.i(logTag, "Verifying bundle contents"); - return FileUtils.filesExist(unpackedContentDir, - ConfigBundle.TZ_DATA_VERSION_FILE_NAME, - ConfigBundle.CHECKSUMS_FILE_NAME, - ConfigBundle.ZONEINFO_FILE_NAME, - ConfigBundle.ICU_DATA_FILE_NAME); - } - - private boolean verifySystemChecksums(File unpackedContentDir) throws IOException { - Slog.i(logTag, "Verifying system file checksums"); - File checksumsFile = new File(unpackedContentDir, ConfigBundle.CHECKSUMS_FILE_NAME); - for (String line : FileUtils.readLines(checksumsFile)) { - int delimiterPos = line.indexOf(','); - if (delimiterPos <= 0 || delimiterPos == line.length() - 1) { - throw new IOException("Bad checksum entry: " + line); - } - long expectedChecksum; - try { - expectedChecksum = Long.parseLong(line.substring(0, delimiterPos)); - } catch (NumberFormatException e) { - throw new IOException("Invalid checksum value: " + line); - } - String filePath = line.substring(delimiterPos + 1); - File file = new File(filePath); - if (!file.exists()) { - Slog.i(logTag, "Failed checksum test for file: " + file + ": file not found"); - return false; - } - long actualChecksum = FileUtils.calculateChecksum(file); - if (actualChecksum != expectedChecksum) { - Slog.i(logTag, "Failed checksum test for file: " + file - + ": required=" + expectedChecksum + ", actual=" + actualChecksum); - return false; - } - } - return true; - } -} diff --git a/tzdata/update/src/test/libcore/tzdata/update/ConfigBundleTest.java b/tzdata/update/src/test/libcore/tzdata/update/ConfigBundleTest.java deleted file mode 100644 index f1325e768c6..00000000000 --- a/tzdata/update/src/test/libcore/tzdata/update/ConfigBundleTest.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * 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 libcore.tzdata.update; - -import junit.framework.TestCase; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FilterInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; -import libcore.io.IoUtils; - -/** - * Tests for {@link ConfigBundle}. - */ -public class ConfigBundleTest extends TestCase { - - private final List<File> testFiles = new ArrayList<>(); - - @Override - public void tearDown() throws Exception { - // Delete files / directories in reverse order. - Collections.reverse(testFiles); - for (File tempFile : testFiles) { - tempFile.delete(); - } - super.tearDown(); - } - - public void testExtractZipSafely_goodZip() throws Exception { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try (ZipOutputStream zipOutputStream = new ZipOutputStream(baos)) { - addZipEntry(zipOutputStream, "/leadingSlash"); - addZipEntry(zipOutputStream, "absolute"); - addZipEntry(zipOutputStream, "subDir/../file"); - addZipEntry(zipOutputStream, "subDir/subDir/subDir/file"); - addZipEntry(zipOutputStream, "subDir/subDir2/"); // Directory entry - addZipEntry(zipOutputStream, "subDir/../subDir3/"); // Directory entry - } - File dir = createTempDir(); - File targetDir = new File(dir, "target"); - TestInputStream inputStream = - new TestInputStream(new ByteArrayInputStream(baos.toByteArray())); - ConfigBundle.extractZipSafely(inputStream, targetDir, true /* makeWorldReadable */); - inputStream.assertClosed(); - assertFilesExist( - new File(targetDir, "leadingSlash"), - new File(targetDir, "absolute"), - new File(targetDir, "file"), - new File(targetDir, "subDir/subDir/subDir/file")); - assertDirsExist( - new File(targetDir, "subDir/subDir2"), - new File(targetDir, "subDir3")); - } - - public void testExtractZipSafely_badZip_fileOutsideTarget() throws Exception { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try (ZipOutputStream zipOutputStream = new ZipOutputStream(baos)) { - addZipEntry(zipOutputStream, "../one"); - } - doExtractZipFails(baos); - } - - public void testExtractZipSafely_badZip_dirOutsideTarget() throws Exception { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try (ZipOutputStream zipOutputStream = new ZipOutputStream(baos)) { - addZipEntry(zipOutputStream, "../one/"); - } - doExtractZipFails(baos); - } - - private void doExtractZipFails(ByteArrayOutputStream baos) { - File dir = createTempDir(); - File targetDir = new File(dir, "target"); - TestInputStream inputStream = new TestInputStream( - new ByteArrayInputStream(baos.toByteArray())); - try { - ConfigBundle.extractZipSafely(inputStream, targetDir, true /* makeWorldReadable */); - fail(); - } catch (IOException expected) { - } - inputStream.assertClosed(); - } - - private static void addZipEntry(ZipOutputStream zipOutputStream, String name) - throws IOException { - ZipEntry zipEntry = new ZipEntry(name); - zipOutputStream.putNextEntry(zipEntry); - if (!zipEntry.isDirectory()) { - zipOutputStream.write('a'); - } - } - - private File createTempDir() { - final String tempPrefix = getClass().getSimpleName(); - File tempDir = IoUtils.createTemporaryDirectory(tempPrefix); - testFiles.add(tempDir); - return tempDir; - } - - private static void assertFilesExist(File... files) { - for (File f : files) { - assertTrue(f + " file expected to exist", f.exists() && f.isFile()); - } - } - - private static void assertDirsExist(File... dirs) { - for (File dir : dirs) { - assertTrue(dir + " directory expected to exist", dir.exists() && dir.isDirectory()); - } - } - - private static class TestInputStream extends FilterInputStream { - - private boolean closed; - - public TestInputStream(InputStream in) { - super(in); - } - - @Override - public void close() throws IOException { - closed = true; - super.close(); - } - - public void assertClosed() { - assertTrue(closed); - } - } -} diff --git a/tzdata/update/src/test/libcore/tzdata/update/FileUtilsTest.java b/tzdata/update/src/test/libcore/tzdata/update/FileUtilsTest.java deleted file mode 100644 index d0028204585..00000000000 --- a/tzdata/update/src/test/libcore/tzdata/update/FileUtilsTest.java +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * 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 libcore.tzdata.update; - -import junit.framework.TestCase; - -import android.system.Os; -import android.system.OsConstants; -import android.system.StructStat; - -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStreamWriter; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import libcore.io.IoUtils; -import libcore.io.Libcore; - -/** - * Tests for {@link FileUtils}. - */ -public class FileUtilsTest extends TestCase { - - private List<File> testFiles = new ArrayList<>(); - - @Override - public void tearDown() throws Exception { - // Delete in reverse order - Collections.reverse(testFiles); - for (File tempFile : testFiles) { - tempFile.delete(); - } - super.tearDown(); - } - - public void testCalculateChecksum() throws Exception { - final String content = "Content"; - File file1 = createTextFile(content); - File file2 = createTextFile(content); - File file3 = createTextFile(content + "!"); - - long file1CheckSum = FileUtils.calculateChecksum(file1); - long file2CheckSum = FileUtils.calculateChecksum(file2); - long file3Checksum = FileUtils.calculateChecksum(file3); - - assertEquals(file1CheckSum, file2CheckSum); - assertTrue(file1CheckSum != file3Checksum); - } - - public void testDeleteRecursive() throws Exception { - File dir = createTempDir(); - File file1 = createRegularFile(dir, "file1"); - File file2 = createRegularFile(dir, "file2"); - File symLink1 = createSymlink(file1, dir, "symLink1"); - File subDir = createDir(dir, "subDir"); - File file3 = createRegularFile(subDir, "subFile1"); - File file4 = createRegularFile(subDir, "subFile2"); - File symLink2 = createSymlink(file1, dir, "symLink2"); - - File otherDir = createTempDir(); - File otherFile = createRegularFile(otherDir, "kept"); - - File linkToOtherDir = createSymlink(otherDir, subDir, "linkToOtherDir"); - File linkToOtherFile = createSymlink(otherFile, subDir, "linkToOtherFile"); - - File[] filesToDelete = { dir, file1, file2, symLink1, subDir, file3, file4, symLink2, - linkToOtherDir, linkToOtherFile }; - File[] filesToKeep = { otherDir, otherFile }; - assertFilesExist(filesToDelete); - assertFilesExist(filesToKeep); - - FileUtils.deleteRecursive(dir); - assertFilesDoNotExist(filesToDelete); - assertFilesExist(filesToKeep); - } - - public void testIsSymlink() throws Exception { - File dir = createTempDir(); - File subDir = createDir(dir, "subDir"); - File fileInSubDir = createRegularFile(subDir, "fileInSubDir"); - File normalFile = createRegularFile(dir, "normalFile"); - File symlinkToDir = createSymlink(subDir, dir, "symlinkToDir"); - File symlinkToFile = createSymlink(fileInSubDir, dir, "symlinkToFile"); - File symlinkToFileInSubDir = createSymlink(fileInSubDir, dir, "symlinkToFileInSubDir"); - File normalFileViaSymlink = new File(symlinkToDir, "normalFile"); - - assertFalse(FileUtils.isSymlink(dir)); - assertFalse(FileUtils.isSymlink(subDir)); - assertFalse(FileUtils.isSymlink(fileInSubDir)); - assertFalse(FileUtils.isSymlink(normalFile)); - assertTrue(FileUtils.isSymlink(symlinkToDir)); - assertTrue(FileUtils.isSymlink(symlinkToFile)); - assertTrue(FileUtils.isSymlink(symlinkToFileInSubDir)); - assertFalse(FileUtils.isSymlink(normalFileViaSymlink)); - } - - public void testCreateSubFile() throws Exception { - File dir1 = createTempDir().getCanonicalFile(); - - File actualSubFile = FileUtils.createSubFile(dir1, "file"); - assertEquals(new File(dir1, "file"), actualSubFile); - - File existingSubFile = createRegularFile(dir1, "file"); - actualSubFile = FileUtils.createSubFile(dir1, "file"); - assertEquals(existingSubFile, actualSubFile); - - File existingSubDir = createDir(dir1, "subdir"); - actualSubFile = FileUtils.createSubFile(dir1, "subdir"); - assertEquals(existingSubDir, actualSubFile); - - assertCreateSubFileThrows(dir1, "../file"); - assertCreateSubFileThrows(dir1, "../../file"); - assertCreateSubFileThrows(dir1, "../otherdir/file"); - - File dir2 = createTempDir().getCanonicalFile(); - createSymlink(dir2, dir1, "symlinkToDir2"); - assertCreateSubFileThrows(dir1, "symlinkToDir2"); - - assertCreateSubFileThrows(dir1, "symlinkToDir2/fileInSymlinkedDir"); - - createRegularFile(dir1, "symlinkToDir2/fileInSymlinkedDir"); - assertCreateSubFileThrows(dir1, "symlinkToDir2/fileInSymlinkedDir"); - } - - public void testEnsureDirectoryExists() throws Exception { - File dir = createTempDir(); - - File exists = new File(dir, "exists"); - assertTrue(exists.mkdir()); - assertTrue(exists.setReadable(true /* readable */, true /* ownerOnly */)); - assertTrue(exists.setExecutable(true /* readable */, true /* ownerOnly */)); - FileUtils.ensureDirectoriesExist(exists, true /* makeWorldReadable */); - assertDirExistsAndIsAccessible(exists, false /* requireWorldReadable */); - - File subDir = new File(dir, "subDir"); - assertFalse(subDir.exists()); - FileUtils.ensureDirectoriesExist(subDir, true /* makeWorldReadable */); - assertDirExistsAndIsAccessible(subDir, true /* requireWorldReadable */); - - File one = new File(dir, "one"); - File two = new File(one, "two"); - File three = new File(two, "three"); - FileUtils.ensureDirectoriesExist(three, true /* makeWorldReadable */); - assertDirExistsAndIsAccessible(one, true /* requireWorldReadable */); - assertDirExistsAndIsAccessible(two, true /* requireWorldReadable */); - assertDirExistsAndIsAccessible(three, true /* requireWorldReadable */); - } - - public void testEnsureDirectoriesExist_noPermissions() throws Exception { - File dir = createTempDir(); - assertDirExistsAndIsAccessible(dir, false /* requireWorldReadable */); - - File unreadableSubDir = new File(dir, "unreadableSubDir"); - assertTrue(unreadableSubDir.mkdir()); - assertTrue(unreadableSubDir.setReadable(false /* readable */, true /* ownerOnly */)); - assertTrue(unreadableSubDir.setExecutable(false /* readable */, true /* ownerOnly */)); - - File toCreate = new File(unreadableSubDir, "toCreate"); - try { - FileUtils.ensureDirectoriesExist(toCreate, true /* makeWorldReadable */); - fail(); - } catch (IOException expected) { - } - assertDirExistsAndIsAccessible(dir, false /* requireWorldReadable */); - assertFalse(unreadableSubDir.canRead() && unreadableSubDir.canExecute()); - assertFalse(toCreate.exists()); - } - - public void testEnsureFileDoesNotExist() throws Exception { - File dir = createTempDir(); - - FileUtils.ensureFileDoesNotExist(new File(dir, "doesNotExist")); - - File exists1 = createRegularFile(dir, "exists1"); - assertTrue(exists1.exists()); - FileUtils.ensureFileDoesNotExist(exists1); - assertFalse(exists1.exists()); - - exists1 = createRegularFile(dir, "exists1"); - File symlink = createSymlink(exists1, dir, "symlinkToFile"); - assertTrue(symlink.exists()); - FileUtils.ensureFileDoesNotExist(symlink); - assertFalse(symlink.exists()); - assertTrue(exists1.exists()); - - // Only files and symlinks supported. We do not delete directories. - File emptyDir = createTempDir(); - try { - FileUtils.ensureFileDoesNotExist(emptyDir); - fail(); - } catch (IOException expected) { - } - assertTrue(emptyDir.exists()); - } - - // This test does not pass when run as root because root can do anything even if the permissions - // don't allow it. - public void testEnsureFileDoesNotExist_noPermission() throws Exception { - File dir = createTempDir(); - - File protectedDir = createDir(dir, "protected"); - File undeletable = createRegularFile(protectedDir, "undeletable"); - assertTrue(protectedDir.setWritable(false)); - assertTrue(undeletable.exists()); - try { - FileUtils.ensureFileDoesNotExist(undeletable); - fail(); - } catch (IOException expected) { - } finally { - assertTrue(protectedDir.setWritable(true)); // Reset for clean-up - } - assertTrue(undeletable.exists()); - } - - public void testCheckFilesExist() throws Exception { - File dir = createTempDir(); - createRegularFile(dir, "exists1"); - File subDir = createDir(dir, "subDir"); - createRegularFile(subDir, "exists2"); - assertTrue(FileUtils.filesExist(dir, "exists1", "subDir/exists2")); - assertFalse(FileUtils.filesExist(dir, "doesNotExist")); - assertFalse(FileUtils.filesExist(dir, "subDir/doesNotExist")); - } - - public void testReadLines() throws Exception { - File file = createTextFile("One\nTwo\nThree\n"); - - List<String> lines = FileUtils.readLines(file); - assertEquals(3, lines.size()); - assertEquals(lines, Arrays.asList("One", "Two", "Three")); - } - - private File createTextFile(String contents) throws IOException { - File file = File.createTempFile(getClass().getSimpleName(), ".txt"); - try (FileOutputStream fos = new FileOutputStream(file)) { - BufferedWriter writer = new BufferedWriter( - new OutputStreamWriter(fos, StandardCharsets.UTF_8)); - writer.write(contents); - writer.close(); - } - return file; - } - - private File createSymlink(File file, File symlinkDir, String symlinkName) throws Exception { - assertTrue(file.exists()); - - File symlink = new File(symlinkDir, symlinkName); - Os.symlink(file.getAbsolutePath(), symlink.getAbsolutePath()); - testFiles.add(symlink); - return symlink; - } - - private static void assertCreateSubFileThrows(File parentDir, String name) { - try { - FileUtils.createSubFile(parentDir, name); - fail(); - } catch (IOException expected) { - assertTrue(expected.getMessage().contains("must exist beneath")); - } - } - - private static void assertFilesDoNotExist(File... files) { - for (File f : files) { - assertFalse(f + " unexpectedly exists", f.exists()); - } - } - - private static void assertFilesExist(File... files) { - for (File f : files) { - assertTrue(f + " expected to exist", f.exists()); - } - } - - private static void assertDirExistsAndIsAccessible(File dir, boolean requireWorldReadable) - throws Exception { - assertTrue(dir.exists() && dir.isDirectory() && dir.canRead() && dir.canExecute()); - - String path = dir.getCanonicalPath(); - StructStat sb = Libcore.os.stat(path); - int mask = OsConstants.S_IXUSR | OsConstants.S_IRUSR; - if (requireWorldReadable) { - mask = mask | OsConstants.S_IXGRP | OsConstants.S_IRGRP - | OsConstants.S_IXOTH | OsConstants.S_IROTH; - } - assertTrue("Permission mask required: " + Integer.toOctalString(mask), - (sb.st_mode & mask) == mask); - } - - private File createTempDir() { - final String tempPrefix = getClass().getSimpleName(); - File tempDir = IoUtils.createTemporaryDirectory(tempPrefix); - testFiles.add(tempDir); - return tempDir; - } - - private File createDir(File parentDir, String name) { - File dir = new File(parentDir, name); - assertTrue(dir.mkdir()); - testFiles.add(dir); - return dir; - } - - private File createRegularFile(File dir, String name) throws Exception { - File file = new File(dir, name); - try (FileOutputStream fos = new FileOutputStream(file)) { - fos.write("Hello".getBytes()); - } - testFiles.add(file); - return file; - } -} diff --git a/tzdata/update/src/test/libcore/tzdata/update/TzDataBundleInstallerTest.java b/tzdata/update/src/test/libcore/tzdata/update/TzDataBundleInstallerTest.java deleted file mode 100644 index 1825bb34e3a..00000000000 --- a/tzdata/update/src/test/libcore/tzdata/update/TzDataBundleInstallerTest.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * 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 libcore.tzdata.update; - -import junit.framework.TestCase; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import libcore.tzdata.update.tools.TzDataBundleBuilder; - -/** - * Tests for {@link libcore.tzdata.update.TzDataBundleInstaller}. - */ -public class TzDataBundleInstallerTest extends TestCase { - - private static final File SYSTEM_ZONE_INFO_FILE = new File("/system/usr/share/zoneinfo/tzdata"); - - private TzDataBundleInstaller installer; - private File tempDir; - private File testInstallDir; - - @Override - public void setUp() throws Exception { - super.setUp(); - tempDir = createDirectory("tempDir"); - testInstallDir = createDirectory("testInstall"); - installer = new TzDataBundleInstaller("TzDataBundleInstallerTest", testInstallDir); - } - - private static File createDirectory(String prefix) throws IOException { - File dir = File.createTempFile(prefix, ""); - assertTrue(dir.delete()); - assertTrue(dir.mkdir()); - return dir; - } - - @Override - public void tearDown() throws Exception { - if (testInstallDir.exists()) { - FileUtils.deleteRecursive(testInstallDir); - } - if (tempDir.exists()) { - FileUtils.deleteRecursive(tempDir); - } - super.tearDown(); - } - - /** Tests the first update on a device */ - public void testSuccessfulFirstUpdate() throws Exception { - ConfigBundle tzData = createValidTzDataBundle("2030a"); - - assertTrue(install(tzData)); - assertTzDataInstalled(tzData); - } - - /** - * Tests an update on a device when there is a prior update already applied. - */ - public void testSuccessfulFollowOnUpdate() throws Exception { - ConfigBundle tzData1 = createValidTzDataBundle("2030a"); - assertTrue(install(tzData1)); - assertTzDataInstalled(tzData1); - - ConfigBundle tzData2 = createValidTzDataBundle("2030b"); - assertTrue(install(tzData2)); - assertTzDataInstalled(tzData2); - } - - - /** Tests that a bundle with a missing file will not update the content. */ - public void testMissingRequiredBundleFile() throws Exception { - ConfigBundle installedConfigBundle = createValidTzDataBundle("2030a"); - assertTrue(install(installedConfigBundle)); - assertTzDataInstalled(installedConfigBundle); - - ConfigBundle incompleteUpdate = - createValidTzDataBundleBuilder("2030b").clearBionicTzData().buildUnvalidated(); - assertFalse(install(incompleteUpdate)); - assertTzDataInstalled(installedConfigBundle); - } - - /** - * Tests that an update will be unpacked even if there is a partial update from a previous run. - */ - public void testInstallWithWorkingDir() throws Exception { - File workingDir = new File(testInstallDir, TzDataBundleInstaller.WORKING_DIR_NAME); - assertTrue(workingDir.mkdir()); - createFile(new File(workingDir, "myFile")); - - ConfigBundle tzData = createValidTzDataBundle("2030a"); - assertTrue(install(tzData)); - assertTzDataInstalled(tzData); - } - - /** - * Tests that a bundle with a checksum entry that references a missing file will not update the - * content. - */ - public void testChecksumBundleEntry_fileMissing() throws Exception { - ConfigBundle badUpdate = - createValidTzDataBundleBuilder("2030b") - .addChecksum("/fileDoesNotExist", 1234) - .build(); - assertFalse(install(badUpdate)); - assertNoContentInstalled(); - } - - /** - * Tests that a bundle with a checksum entry with a bad checksum will not update the - * content. - */ - public void testChecksumBundleEntry_incorrectChecksum() throws Exception { - File fileToChecksum = SYSTEM_ZONE_INFO_FILE; - long badChecksum = FileUtils.calculateChecksum(fileToChecksum) + 1; - ConfigBundle badUpdate = - createValidTzDataBundleBuilder("2030b") - .clearChecksumEntries() - .addChecksum(fileToChecksum.getPath(), badChecksum) - .build(); - assertFalse(install(badUpdate)); - assertNoContentInstalled(); - } - - private boolean install(ConfigBundle configBundle) throws Exception { - return installer.install(configBundle.getBundleBytes()); - } - - private ConfigBundle createValidTzDataBundle(String tzDataVersion) - throws IOException { - return createValidTzDataBundleBuilder(tzDataVersion).build(); - } - - private TzDataBundleBuilder createValidTzDataBundleBuilder(String tzDataVersion) - throws IOException { - - // The file to include in the installation-time checksum check. - File fileToChecksum = SYSTEM_ZONE_INFO_FILE; - long checksum = FileUtils.calculateChecksum(fileToChecksum); - - File bionicTzData = new File(tempDir, "zoneinfo"); - createFile(bionicTzData); - - File icuData = new File(tempDir, "icudata"); - createFile(icuData); - - return new TzDataBundleBuilder() - .addChecksum(fileToChecksum.getPath(), checksum) - .setTzDataVersion(tzDataVersion) - .addBionicTzData(bionicTzData) - .addIcuTzData(icuData); - } - - private void assertTzDataInstalled(ConfigBundle expectedTzData) throws Exception { - assertTrue(testInstallDir.exists()); - - File currentTzDataDir = new File(testInstallDir, TzDataBundleInstaller.CURRENT_TZ_DATA_DIR_NAME); - assertTrue(currentTzDataDir.exists()); - - File checksumFile = new File(currentTzDataDir, ConfigBundle.CHECKSUMS_FILE_NAME); - assertTrue(checksumFile.exists()); - - File versionFile = new File(currentTzDataDir, - ConfigBundle.TZ_DATA_VERSION_FILE_NAME); - assertTrue(versionFile.exists()); - - File bionicFile = new File(currentTzDataDir, ConfigBundle.ZONEINFO_FILE_NAME); - assertTrue(bionicFile.exists()); - - File icuFile = new File(currentTzDataDir, ConfigBundle.ICU_DATA_FILE_NAME); - assertTrue(icuFile.exists()); - - // Also check no working directory is left lying around. - File workingDir = new File(testInstallDir, TzDataBundleInstaller.WORKING_DIR_NAME); - assertFalse(workingDir.exists()); - } - - private void assertNoContentInstalled() { - File currentTzDataDir = new File(testInstallDir, TzDataBundleInstaller.CURRENT_TZ_DATA_DIR_NAME); - assertFalse(currentTzDataDir.exists()); - - // Also check no working directories are left lying around. - File workingDir = new File(testInstallDir, TzDataBundleInstaller.WORKING_DIR_NAME); - assertFalse(workingDir.exists()); - - File oldDataDir = new File(testInstallDir, TzDataBundleInstaller.OLD_TZ_DATA_DIR_NAME); - assertFalse(oldDataDir.exists()); - } - - private static void createFile(File file) { - try (FileOutputStream fos = new FileOutputStream(file)) { - fos.write('a'); - } catch (IOException e) { - fail(e.getMessage()); - } - } -} |