blob: 381df5a8340429701db1f24f164826e1264902cf [file] [log] [blame]
Neil Fuller08913222015-03-31 18:24:29 +01001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Neil Fullereec2bfb2016-12-13 16:26:02 +000017#include <ctype.h>
Neil Fuller08913222015-03-31 18:24:29 +010018#include <errno.h>
19#include <ftw.h>
20#include <libgen.h>
21#include <stdarg.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <unistd.h>
26#include <iostream>
27#include <memory>
28#include <string>
29#include <vector>
30
Elliott Hughes4f713192015-12-04 22:00:26 -080031#include "android-base/logging.h"
Neil Fuller08913222015-03-31 18:24:29 +010032
Neil Fullerc65c61b2017-02-09 13:47:03 +000033// The name of the file containing the distro version information.
Neil Fullerc749c9a2017-03-20 10:21:46 +000034// See also libcore.tzdata.shared2.TimeZoneDistro / libcore.tzdata.shared2.DistroVersion.
Neil Fuller16e64872017-02-09 13:31:57 +000035static const char* DISTRO_VERSION_FILENAME = "/distro_version";
Neil Fullerc65c61b2017-02-09 13:47:03 +000036
Neil Fuller16e64872017-02-09 13:31:57 +000037// distro_version is an ASCII file consisting of 17 bytes in the form: AAA.BBB|CCCCC|DDD
38// AAA.BBB is the major/minor version of the distro format (e.g. 001.001),
Neil Fullereec2bfb2016-12-13 16:26:02 +000039// CCCCC is the rules version (e.g. 2016g)
Neil Fuller16e64872017-02-09 13:31:57 +000040// DDD is the android revision for this rules version to allow for distro corrections (e.g. 001)
Neil Fullereec2bfb2016-12-13 16:26:02 +000041// We only need the first 13 to determine if it is suitable for the device.
Neil Fuller16e64872017-02-09 13:31:57 +000042static const int DISTRO_VERSION_LENGTH = 13;
Neil Fullerc65c61b2017-02-09 13:47:03 +000043
Neil Fuller16e64872017-02-09 13:31:57 +000044// The major version of the distro format supported by this code as a null-terminated char[].
Neil Fullerc749c9a2017-03-20 10:21:46 +000045// See also libcore.tzdata.shared2.TimeZoneDistro / libcore.tzdata.shared2.DistroVersion.
Neil Fuller16e64872017-02-09 13:31:57 +000046static const char SUPPORTED_DISTRO_MAJOR_VERSION[] = "001";
Neil Fullerc65c61b2017-02-09 13:47:03 +000047
Neil Fuller16e64872017-02-09 13:31:57 +000048// The length of the distro format major version excluding the \0
49static const size_t SUPPORTED_DISTRO_MAJOR_VERSION_LEN = sizeof(SUPPORTED_DISTRO_MAJOR_VERSION) - 1;
Neil Fullerc65c61b2017-02-09 13:47:03 +000050
Neil Fuller16e64872017-02-09 13:31:57 +000051// The minor version of the distro format supported by this code as a null-terminated char[].
Neil Fullerc749c9a2017-03-20 10:21:46 +000052// See also libcore.tzdata.shared2.TimeZoneDistro / libcore.tzdata.shared2.DistroVersion.
Neil Fuller16e64872017-02-09 13:31:57 +000053static const char SUPPORTED_DISTRO_MINOR_VERSION[] = "001";
Neil Fullerc65c61b2017-02-09 13:47:03 +000054
Neil Fuller16e64872017-02-09 13:31:57 +000055// The length of the distro format minor version excluding the \0
56static const size_t SUPPORTED_DISTRO_MINOR_VERSION_LEN = sizeof(SUPPORTED_DISTRO_MINOR_VERSION) - 1;
Neil Fullerc65c61b2017-02-09 13:47:03 +000057
Neil Fuller16e64872017-02-09 13:31:57 +000058// The length of the distro format version. e.g. 001.001
59static const size_t SUPPORTED_DISTRO_VERSION_LEN =
60 SUPPORTED_DISTRO_MAJOR_VERSION_LEN + SUPPORTED_DISTRO_MINOR_VERSION_LEN + 1;
Neil Fullerc65c61b2017-02-09 13:47:03 +000061
Neil Fullereec2bfb2016-12-13 16:26:02 +000062// The length of the IANA rules version bytes. e.g. 2016a
63static const size_t RULES_VERSION_LEN = 5;
Neil Fullerc65c61b2017-02-09 13:47:03 +000064
Neil Fuller16e64872017-02-09 13:31:57 +000065// Distro version bytes are: AAA.BBB|CCCCC - the rules version is CCCCC
66static const size_t DISTRO_VERSION_RULES_IDX = 8;
Neil Fullereec2bfb2016-12-13 16:26:02 +000067
Neil Fullerc749c9a2017-03-20 10:21:46 +000068// See also libcore.tzdata.shared2.TimeZoneDistro.
Neil Fuller08913222015-03-31 18:24:29 +010069static const char* TZDATA_FILENAME = "/tzdata";
Neil Fullerc65c61b2017-02-09 13:47:03 +000070
Neil Fuller08913222015-03-31 18:24:29 +010071// tzdata file header (as much as we need for the version):
72// byte[11] tzdata_version -- e.g. "tzdata2012f"
73static const int TZ_HEADER_LENGTH = 11;
Neil Fullerc65c61b2017-02-09 13:47:03 +000074
Neil Fullereec2bfb2016-12-13 16:26:02 +000075static const char TZ_DATA_HEADER_PREFIX[] = "tzdata";
76static const size_t TZ_DATA_HEADER_PREFIX_LEN = sizeof(TZ_DATA_HEADER_PREFIX) - 1; // exclude \0
77
Neil Fuller08913222015-03-31 18:24:29 +010078
79static void usage() {
80 std::cerr << "Usage: tzdatacheck SYSTEM_TZ_DIR DATA_TZ_DIR\n"
81 "\n"
Neil Fuller16e64872017-02-09 13:31:57 +000082 "Checks whether any timezone update distro in DATA_TZ_DIR is compatible with the\n"
Neil Fullereec2bfb2016-12-13 16:26:02 +000083 "current Android release and better than or the same as base system timezone rules in\n"
84 "SYSTEM_TZ_DIR. If the timezone rules in SYSTEM_TZ_DIR are a higher version than the\n"
85 "one in DATA_TZ_DIR the DATA_TZ_DIR is renamed and then deleted.\n";
Neil Fuller08913222015-03-31 18:24:29 +010086 exit(1);
87}
88
89/*
Neil Fullereec2bfb2016-12-13 16:26:02 +000090 * Opens a file and fills buffer with the first byteCount bytes from the file.
91 * If the file does not exist or cannot be opened or is too short then false is returned.
Neil Fuller08913222015-03-31 18:24:29 +010092 * If the bytes were read successfully then true is returned.
93 */
Neil Fullereec2bfb2016-12-13 16:26:02 +000094static bool readBytes(const std::string& fileName, char* buffer, size_t byteCount) {
95 FILE* file = fopen(fileName.c_str(), "r");
96 if (file == nullptr) {
97 if (errno != ENOENT) {
98 PLOG(WARNING) << "Error opening file " << fileName;
Neil Fuller08913222015-03-31 18:24:29 +010099 }
Neil Fullereec2bfb2016-12-13 16:26:02 +0000100 return false;
Neil Fuller08913222015-03-31 18:24:29 +0100101 }
Neil Fullereec2bfb2016-12-13 16:26:02 +0000102 size_t bytesRead = fread(buffer, 1, byteCount, file);
103 fclose(file);
Neil Fuller08913222015-03-31 18:24:29 +0100104 if (bytesRead != byteCount) {
Neil Fullereec2bfb2016-12-13 16:26:02 +0000105 LOG(WARNING) << fileName << " is too small. " << byteCount << " bytes required";
106 return false;
Neil Fuller08913222015-03-31 18:24:29 +0100107 }
Neil Fuller08913222015-03-31 18:24:29 +0100108 return true;
109}
110
Neil Fullereec2bfb2016-12-13 16:26:02 +0000111/*
112 * Checks the contents of headerBytes. Returns true if it is valid (starts with "tzdata"), false
113 * otherwise.
114 */
115static bool checkValidTzDataHeader(const std::string& fileName, const char* headerBytes) {
Neil Fuller08913222015-03-31 18:24:29 +0100116 if (strncmp("tzdata", headerBytes, 6) != 0) {
Neil Fullereec2bfb2016-12-13 16:26:02 +0000117 LOG(WARNING) << fileName << " does not start with the expected bytes (tzdata)";
118 return false;
Neil Fuller08913222015-03-31 18:24:29 +0100119 }
Neil Fullereec2bfb2016-12-13 16:26:02 +0000120 return true;
121}
122
123static bool checkDigits(const char* buffer, const size_t count, size_t* i) {
124 for (size_t j = 0; j < count; j++) {
125 char toCheck = buffer[(*i)++];
126 if (!isdigit(toCheck)) {
127 return false;
128 }
129 }
130 return true;
131}
132
Neil Fuller16e64872017-02-09 13:31:57 +0000133static bool checkValidDistroVersion(const char* buffer) {
134 // See DISTRO_VERSION_LENGTH comments above for a description of the format.
Neil Fullereec2bfb2016-12-13 16:26:02 +0000135 size_t i = 0;
136 if (!checkDigits(buffer, 3, &i)) {
137 return false;
138 }
139 if (buffer[i++] != '.') {
140 return false;
141 }
142 if (!checkDigits(buffer, 3, &i)) {
143 return false;
144 }
145 if (buffer[i++] != '|') {
146 return false;
147 }
148 if (!checkDigits(buffer, 4, &i)) {
149 return false;
150 }
151 // Ignore the last character. It is assumed to be a letter but we don't check because it's not
152 // obvious what would happen at 'z'.
153 return true;
Neil Fuller08913222015-03-31 18:24:29 +0100154}
155
156/* Return the parent directory of dirName. */
157static std::string getParentDir(const std::string& dirName) {
158 std::unique_ptr<char> mutable_dirname(strdup(dirName.c_str()));
159 return dirname(mutable_dirname.get());
160}
161
162/* Deletes a single file, symlink or directory. Called from nftw(). */
163static int deleteFn(const char* fpath, const struct stat*, int typeflag, struct FTW*) {
164 LOG(DEBUG) << "Inspecting " << fpath;
165 switch (typeflag) {
166 case FTW_F:
167 case FTW_SL:
168 LOG(DEBUG) << "Unlinking " << fpath;
169 if (unlink(fpath)) {
170 PLOG(WARNING) << "Failed to unlink file/symlink " << fpath;
171 }
172 break;
173 case FTW_D:
174 case FTW_DP:
175 LOG(DEBUG) << "Removing dir " << fpath;
176 if (rmdir(fpath)) {
177 PLOG(WARNING) << "Failed to remove dir " << fpath;
178 }
179 break;
180 default:
181 LOG(WARNING) << "Unsupported file type " << fpath << ": " << typeflag;
182 break;
183 }
184 return 0;
185}
186
Neil Fullereec2bfb2016-12-13 16:26:02 +0000187enum PathStatus { ERR, NONE, IS_DIR, NOT_DIR };
188
189static PathStatus checkPath(const std::string& path) {
190 struct stat buf;
191 if (stat(path.c_str(), &buf) != 0) {
192 if (errno != ENOENT) {
193 PLOG(WARNING) << "Unable to stat " << path;
194 return ERR;
195 }
196 return NONE;
197 }
198 return S_ISDIR(buf.st_mode) ? IS_DIR : NOT_DIR;
199}
200
Neil Fuller08913222015-03-31 18:24:29 +0100201/*
202 * Deletes dirToDelete and returns true if it is successful in removing or moving the directory out
Neil Fullereec2bfb2016-12-13 16:26:02 +0000203 * of the way. If dirToDelete does not exist this function does nothing and returns true. If
204 * dirToDelete is not a directory or cannot be accessed this method returns false.
Neil Fuller08913222015-03-31 18:24:29 +0100205 *
206 * During deletion, this function first renames the directory to a temporary name. If the temporary
207 * directory cannot be created, or the directory cannot be renamed, false is returned. After the
208 * rename, deletion of files and subdirs beneath the directory is performed on a "best effort"
209 * basis. Symlinks beneath the directory are not followed.
210 */
211static bool deleteDir(const std::string& dirToDelete) {
212 // Check whether the dir exists.
Neil Fullereec2bfb2016-12-13 16:26:02 +0000213 int pathStatus = checkPath(dirToDelete);
214 if (pathStatus == NONE) {
215 LOG(INFO) << "Path " << dirToDelete << " does not exist";
216 return true;
217 }
218 if (pathStatus != IS_DIR) {
219 LOG(WARNING) << "Path " << dirToDelete << " failed to stat() or is not a directory.";
Neil Fuller08913222015-03-31 18:24:29 +0100220 return false;
Neil Fuller08913222015-03-31 18:24:29 +0100221 }
222
223 // First, rename dirToDelete.
Neil Fullereec2bfb2016-12-13 16:26:02 +0000224
Neil Fuller08913222015-03-31 18:24:29 +0100225 std::string tempDirNameTemplate = getParentDir(dirToDelete);
226 tempDirNameTemplate += "/tempXXXXXX";
227
228 // Create an empty directory with the temporary name. For this we need a non-const char*.
229 std::vector<char> tempDirName(tempDirNameTemplate.length() + 1);
230 strcpy(&tempDirName[0], tempDirNameTemplate.c_str());
231 if (mkdtemp(&tempDirName[0]) == nullptr) {
232 PLOG(WARNING) << "Unable to create a temporary directory: " << tempDirNameTemplate;
233 return false;
234 }
235
Neil Fullereec2bfb2016-12-13 16:26:02 +0000236 // Rename dirToDelete to tempDirName (replacing the empty tempDirName directory created above).
Neil Fuller08913222015-03-31 18:24:29 +0100237 int rc = rename(dirToDelete.c_str(), &tempDirName[0]);
238 if (rc == -1) {
239 PLOG(WARNING) << "Unable to rename directory from " << dirToDelete << " to "
240 << &tempDirName[0];
241 return false;
242 }
243
244 // Recursively delete contents of tempDirName.
Neil Fullereec2bfb2016-12-13 16:26:02 +0000245
Neil Fuller08913222015-03-31 18:24:29 +0100246 rc = nftw(&tempDirName[0], deleteFn, 10 /* openFiles */,
247 FTW_DEPTH | FTW_MOUNT | FTW_PHYS);
248 if (rc == -1) {
249 LOG(INFO) << "Could not delete directory: " << &tempDirName[0];
250 }
251 return true;
252}
253
254/*
Neil Fullereec2bfb2016-12-13 16:26:02 +0000255 * Deletes the ConfigInstaller metadata directory.
256 * TODO(nfuller). http://b/31008728 Remove this when ConfigInstaller is no longer used.
257 */
258static void deleteConfigUpdaterMetadataDir(const char* dataZoneInfoDir) {
259 // Delete the update metadata
260 std::string dataUpdatesDirName(dataZoneInfoDir);
261 dataUpdatesDirName += "/updates";
262 LOG(INFO) << "Removing: " << dataUpdatesDirName;
263 bool deleted = deleteDir(dataUpdatesDirName);
264 if (!deleted) {
265 LOG(WARNING) << "Deletion of install metadata " << dataUpdatesDirName
266 << " was not successful";
267 }
268}
269
270/*
Neil Fuller16e64872017-02-09 13:31:57 +0000271 * Deletes the timezone update distro directory.
Neil Fullereec2bfb2016-12-13 16:26:02 +0000272 */
Neil Fuller16e64872017-02-09 13:31:57 +0000273static void deleteUpdateDistroDir(std::string& distroDirName) {
274 LOG(INFO) << "Removing: " << distroDirName;
275 bool deleted = deleteDir(distroDirName);
Neil Fullereec2bfb2016-12-13 16:26:02 +0000276 if (!deleted) {
Neil Fuller16e64872017-02-09 13:31:57 +0000277 LOG(WARNING) << "Deletion of distro dir " << distroDirName << " was not successful";
Neil Fullereec2bfb2016-12-13 16:26:02 +0000278 }
279}
280
281/*
Neil Fuller08913222015-03-31 18:24:29 +0100282 * After a platform update it is likely that timezone data found on the system partition will be
283 * newer than the version found in the data partition. This tool detects this case and removes the
Neil Fullereec2bfb2016-12-13 16:26:02 +0000284 * version in /data.
Neil Fuller08913222015-03-31 18:24:29 +0100285 *
286 * Note: This code is related to code in com.android.server.updates.TzDataInstallReceiver. The
287 * paths for the metadata and current timezone data must match.
288 *
289 * Typically on device the two args will be:
290 * /system/usr/share/zoneinfo /data/misc/zoneinfo
291 *
292 * See usage() for usage notes.
293 */
294int main(int argc, char* argv[]) {
295 if (argc != 3) {
296 usage();
Neil Fullereec2bfb2016-12-13 16:26:02 +0000297 return 1;
Neil Fuller08913222015-03-31 18:24:29 +0100298 }
299
300 const char* systemZoneInfoDir = argv[1];
301 const char* dataZoneInfoDir = argv[2];
302
Neil Fuller16e64872017-02-09 13:31:57 +0000303 // Check the distro directory exists. If it does not, exit quickly: nothing to do.
Neil Fuller08913222015-03-31 18:24:29 +0100304 std::string dataCurrentDirName(dataZoneInfoDir);
305 dataCurrentDirName += "/current";
Neil Fullereec2bfb2016-12-13 16:26:02 +0000306 int dataCurrentDirStatus = checkPath(dataCurrentDirName);
307 if (dataCurrentDirStatus == NONE) {
Neil Fuller16e64872017-02-09 13:31:57 +0000308 LOG(INFO) << "timezone distro dir " << dataCurrentDirName
Neil Fullereec2bfb2016-12-13 16:26:02 +0000309 << " does not exist. No action required.";
Neil Fuller08913222015-03-31 18:24:29 +0100310 return 0;
311 }
Neil Fuller16e64872017-02-09 13:31:57 +0000312 // If the distro directory path is not a directory or we can't stat() the path, exit with a
Neil Fullereec2bfb2016-12-13 16:26:02 +0000313 // warning: either there's a problem accessing storage or the world is not as it should be;
314 // nothing to do.
315 if (dataCurrentDirStatus != IS_DIR) {
Neil Fuller16e64872017-02-09 13:31:57 +0000316 LOG(WARNING) << "Current distro dir " << dataCurrentDirName
Neil Fullereec2bfb2016-12-13 16:26:02 +0000317 << " could not be accessed or is not a directory. result=" << dataCurrentDirStatus;
318 return 2;
319 }
Neil Fuller08913222015-03-31 18:24:29 +0100320
Neil Fuller16e64872017-02-09 13:31:57 +0000321 // Check the installed distro version.
322 std::string distroVersionFileName(dataCurrentDirName);
323 distroVersionFileName += DISTRO_VERSION_FILENAME;
324 std::vector<char> distroVersion;
325 distroVersion.reserve(DISTRO_VERSION_LENGTH);
326 bool distroVersionReadOk =
327 readBytes(distroVersionFileName, distroVersion.data(), DISTRO_VERSION_LENGTH);
328 if (!distroVersionReadOk) {
329 LOG(WARNING) << "distro version file " << distroVersionFileName
330 << " does not exist or is too short. Deleting distro dir.";
Neil Fullereec2bfb2016-12-13 16:26:02 +0000331 // Implies the contents of the data partition is corrupt in some way. Try to clean up.
332 deleteConfigUpdaterMetadataDir(dataZoneInfoDir);
Neil Fuller16e64872017-02-09 13:31:57 +0000333 deleteUpdateDistroDir(dataCurrentDirName);
Neil Fullereec2bfb2016-12-13 16:26:02 +0000334 return 3;
335 }
336
Neil Fuller16e64872017-02-09 13:31:57 +0000337 if (!checkValidDistroVersion(distroVersion.data())) {
338 LOG(WARNING) << "distro version file " << distroVersionFileName
339 << " is not valid. Deleting distro dir.";
Neil Fullereec2bfb2016-12-13 16:26:02 +0000340 // Implies the contents of the data partition is corrupt in some way. Try to clean up.
341 deleteConfigUpdaterMetadataDir(dataZoneInfoDir);
Neil Fuller16e64872017-02-09 13:31:57 +0000342 deleteUpdateDistroDir(dataCurrentDirName);
Neil Fullereec2bfb2016-12-13 16:26:02 +0000343 return 4;
344 }
345
Neil Fuller16e64872017-02-09 13:31:57 +0000346 std::string actualDistroVersion =
347 std::string(distroVersion.data(), SUPPORTED_DISTRO_VERSION_LEN);
348 // Check the first 3 bytes of the distro version: these are the major version (e.g. 001).
Neil Fullerf54cadb2017-02-09 11:53:07 +0000349 // It must match the one we support exactly to be ok.
350 if (strncmp(
Neil Fuller16e64872017-02-09 13:31:57 +0000351 &distroVersion[0],
352 SUPPORTED_DISTRO_MAJOR_VERSION,
353 SUPPORTED_DISTRO_MAJOR_VERSION_LEN) != 0) {
Neil Fullerf54cadb2017-02-09 11:53:07 +0000354
Neil Fuller16e64872017-02-09 13:31:57 +0000355 LOG(INFO) << "distro version file " << distroVersionFileName
356 << " major version is not the required version " << SUPPORTED_DISTRO_MAJOR_VERSION
357 << ", was \"" << actualDistroVersion << "\". Deleting distro dir.";
358 // This implies there has been an OTA and the installed distro is not compatible with the
359 // new version of Android. Remove the installed distro.
Neil Fullerf54cadb2017-02-09 11:53:07 +0000360 deleteConfigUpdaterMetadataDir(dataZoneInfoDir);
Neil Fuller16e64872017-02-09 13:31:57 +0000361 deleteUpdateDistroDir(dataCurrentDirName);
Neil Fullerf54cadb2017-02-09 11:53:07 +0000362 return 5;
363 }
364
Neil Fuller16e64872017-02-09 13:31:57 +0000365 // Check the last 3 bytes of the distro version: these are the minor version (e.g. 001).
366 // If the version in the distro is < the minor version required by this device it cannot be
Neil Fullerf54cadb2017-02-09 11:53:07 +0000367 // used.
368 if (strncmp(
Neil Fuller16e64872017-02-09 13:31:57 +0000369 &distroVersion[4],
370 SUPPORTED_DISTRO_MINOR_VERSION,
371 SUPPORTED_DISTRO_MINOR_VERSION_LEN) < 0) {
Neil Fullerf54cadb2017-02-09 11:53:07 +0000372
Neil Fuller16e64872017-02-09 13:31:57 +0000373 LOG(INFO) << "distro version file " << distroVersionFileName
374 << " minor version is not the required version " << SUPPORTED_DISTRO_MINOR_VERSION
375 << ", was \"" << actualDistroVersion << "\". Deleting distro dir.";
376 // This implies there has been an OTA and the installed distro is not compatible with the
377 // new version of Android. Remove the installed distro.
Neil Fullereec2bfb2016-12-13 16:26:02 +0000378 deleteConfigUpdaterMetadataDir(dataZoneInfoDir);
Neil Fuller16e64872017-02-09 13:31:57 +0000379 deleteUpdateDistroDir(dataCurrentDirName);
Neil Fullereec2bfb2016-12-13 16:26:02 +0000380 return 5;
381 }
382
383 // Read the system rules version out of the /system tzdata file.
Neil Fuller08913222015-03-31 18:24:29 +0100384 std::string systemTzDataFileName(systemZoneInfoDir);
385 systemTzDataFileName += TZDATA_FILENAME;
386 std::vector<char> systemTzDataHeader;
387 systemTzDataHeader.reserve(TZ_HEADER_LENGTH);
388 bool systemFileExists =
Neil Fullereec2bfb2016-12-13 16:26:02 +0000389 readBytes(systemTzDataFileName, systemTzDataHeader.data(), TZ_HEADER_LENGTH);
Neil Fuller08913222015-03-31 18:24:29 +0100390 if (!systemFileExists) {
Neil Fullereec2bfb2016-12-13 16:26:02 +0000391 // Implies the contents of the system partition is corrupt in some way. Nothing we can do.
392 LOG(WARNING) << systemTzDataFileName << " does not exist or could not be opened";
393 return 6;
Neil Fuller08913222015-03-31 18:24:29 +0100394 }
Neil Fullereec2bfb2016-12-13 16:26:02 +0000395 if (!checkValidTzDataHeader(systemTzDataFileName, systemTzDataHeader.data())) {
396 // Implies the contents of the system partition is corrupt in some way. Nothing we can do.
397 LOG(WARNING) << systemTzDataFileName << " does not have a valid header.";
398 return 7;
Neil Fuller08913222015-03-31 18:24:29 +0100399 }
400
Neil Fuller16e64872017-02-09 13:31:57 +0000401 // Compare the distro rules version against the system rules version.
Neil Fullereec2bfb2016-12-13 16:26:02 +0000402 if (strncmp(
403 &systemTzDataHeader[TZ_DATA_HEADER_PREFIX_LEN],
Neil Fuller16e64872017-02-09 13:31:57 +0000404 &distroVersion[DISTRO_VERSION_RULES_IDX],
Neil Fullereec2bfb2016-12-13 16:26:02 +0000405 RULES_VERSION_LEN) <= 0) {
Neil Fuller16e64872017-02-09 13:31:57 +0000406 LOG(INFO) << "Found an installed distro but it is valid. No action taken.";
Neil Fullereec2bfb2016-12-13 16:26:02 +0000407 // Implies there is an installed update, but it is good.
408 return 0;
409 }
410
411 // Implies there has been an OTA and the system version of the timezone rules is now newer
Neil Fuller16e64872017-02-09 13:31:57 +0000412 // than the version installed in /data. Remove the installed distro.
413 LOG(INFO) << "timezone distro in " << dataCurrentDirName << " is older than data in "
Neil Fullereec2bfb2016-12-13 16:26:02 +0000414 << systemTzDataFileName << "; fixing...";
415
416 deleteConfigUpdaterMetadataDir(dataZoneInfoDir);
Neil Fuller16e64872017-02-09 13:31:57 +0000417 deleteUpdateDistroDir(dataCurrentDirName);
Neil Fuller08913222015-03-31 18:24:29 +0100418 return 0;
419}