/*
 * 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.
 */

#include <ctype.h>
#include <errno.h>
#include <ftw.h>
#include <libgen.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <iostream>
#include <memory>
#include <string>
#include <vector>

#include "android-base/logging.h"

// The name of the directory that holds a staged time zone update distro. If this exists it should
// replace the one in CURRENT_DIR_NAME.
// See also com.android.timezone.distro.installer.TimeZoneDistroInstaller.
static const char* STAGED_DIR_NAME = "/staged";

// The name of the directory that holds the (optional) installed time zone update distro.
// See also com.android.timezone.distro.installer.TimeZoneDistroInstaller.
static const char* CURRENT_DIR_NAME = "/current";

// The name of a file in the staged dir that indicates the staged operation is an "uninstall".
// See also com.android.timezone.distro.installer.TimeZoneDistroInstaller.
static const char* UNINSTALL_TOMBSTONE_FILE_NAME = "/STAGED_UNINSTALL_TOMBSTONE";

// The name of the file containing the distro version information.
// See also com.android.timezone.distro.TimeZoneDistro / com.android.timezone.distro.DistroVersion.
static const char* DISTRO_VERSION_FILENAME = "/distro_version";

// The name of the file containing the base tz data set version information.
// See also libcore.timezone.TzDataSetVersion.
static const char* BASE_VERSION_FILENAME = "/tz_version";

// distro_version / tz_version are ASCII files consisting of at least 17 bytes in the
// form: AAA.BBB|CCCCC|DDD
// AAA.BBB is the major/minor version of the format (e.g. 004.001),
// CCCCC is the rules version (e.g. 2016g),
// DDD is the android revision for this rules version to allow for data corrections (e.g. 001),
// We only use the first 13 to determine suitability of format / data.
static const int READ_DATA_LENGTH = 13;

// Version bytes are: AAA.BBB|CCCCC - the format version is AAA.BBB
// The length of the format version,  e.g. "004.001" == 7 bytes
static const size_t FORMAT_VERSION_LEN = 7;

// Version bytes are: AAA.BBB|CCCCC - the format major version is AAA
static const size_t FORMAT_MAJOR_VERSION_LEN = 3;

// Version bytes are: AAA.BBB|CCCCC - the format major version is AAA
static const size_t FORMAT_MAJOR_VERSION_IDX = 0;

// Version bytes are: AAA.BBB|CCCCC - the format major version is AAA
static const size_t FORMAT_MINOR_VERSION_LEN = 3;

// Version bytes are: AAA.BBB|CCCCC - the format minor version is BBB
static const size_t FORMAT_MINOR_VERSION_IDX = 4;

// Version bytes are: AAA.BBB|CCCCC - the IANA rules version is CCCCC
// The length of the IANA rules version bytes, e.g. 2016a
static const size_t RULES_VERSION_LEN = 5;

// Version bytes are: AAA.BBB|CCCCC - the rules version is CCCCC
static const size_t VERSION_RULES_IDX = 8;


static void usage() {
    std::cerr << "Usage: tzdatacheck BASE_TZ_DIR DATA_TZ_DIR\n"
            "\n"
            "Checks whether any timezone update distro in DATA_TZ_DIR is compatible with the\n"
            "current Android release and better than or the same as base timezone rules in\n"
            "BASE_TZ_DIR. If the timezone rules in BASE_TZ_DIR are a higher version than the\n"
            "one in DATA_TZ_DIR the DATA_TZ_DIR is renamed and then deleted.\n";
    exit(1);
}

/*
 * Opens a file and fills buffer with the first byteCount bytes from the file.
 * If the file does not exist or cannot be opened or is too short then false is returned.
 * If the bytes were read successfully then true is returned.
 */
static bool readBytes(const std::string& fileName, char* buffer, size_t byteCount) {
    FILE* file = fopen(fileName.c_str(), "r");
    if (file == nullptr) {
        if (errno != ENOENT) {
            PLOG(WARNING) << "Error opening file " << fileName;
        }
        return false;
    }
    size_t bytesRead = fread(buffer, 1, byteCount, file);
    fclose(file);
    if (bytesRead != byteCount) {
        LOG(WARNING) << fileName << " is too small. " << byteCount << " bytes required";
        return false;
    }
    return true;
}

static bool checkDigits(const char* buffer, const size_t count, size_t* i) {
    for (size_t j = 0; j < count; j++) {
      char toCheck = buffer[(*i)++];
      if (!isdigit(toCheck)) {
        return false;
      }
    }
    return true;
}

static bool checkValidVersionBytes(const char* buffer) {
    // See READ_DATA_LENGTH comments above for a description of the format.
    size_t i = 0;
    if (!checkDigits(buffer, 3, &i)) {
      return false;
    }
    if (buffer[i++] != '.') {
      return false;
    }
    if (!checkDigits(buffer, 3, &i)) {
      return false;
    }
    if (buffer[i++] != '|') {
      return false;
    }
    if (!checkDigits(buffer, 4, &i)) {
      return false;
    }
    // Ignore the last character. It is assumed to be a letter but we don't check because it's not
    // obvious what would happen at 'z'.
    return true;
}

/* Return the parent directory of dirName. */
static std::string getParentDir(const std::string& dirName) {
    char *cMutableDirName = strdup(dirName.c_str());
    std::string parentDir = dirname(cMutableDirName);
    free(cMutableDirName);
    return parentDir;
}

/* Deletes a single file, symlink or directory. Called from nftw(). */
static int deleteFn(const char* fpath, const struct stat*, int typeflag, struct FTW*) {
    LOG(DEBUG) << "Inspecting " << fpath;
    switch (typeflag) {
    case FTW_F:
    case FTW_SL:
        LOG(DEBUG) << "Unlinking " << fpath;
        if (unlink(fpath)) {
            PLOG(WARNING) << "Failed to unlink file/symlink " << fpath;
        }
        break;
    case FTW_D:
    case FTW_DP:
        LOG(DEBUG) << "Removing dir " << fpath;
        if (rmdir(fpath)) {
            PLOG(WARNING) << "Failed to remove dir " << fpath;
        }
        break;
    default:
        LOG(WARNING) << "Unsupported file type " << fpath << ": " << typeflag;
        break;
    }
    return 0;
}

enum PathStatus { ERR, NONE, IS_DIR, IS_REG, UNKNOWN };

static PathStatus checkPath(const std::string& path) {
    struct stat buf;
    if (stat(path.c_str(), &buf) != 0) {
        if (errno != ENOENT) {
            PLOG(WARNING) << "Unable to stat " << path;
            return ERR;
        }
        return NONE;
    }
    return S_ISDIR(buf.st_mode) ? IS_DIR : S_ISREG(buf.st_mode) ? IS_REG : UNKNOWN;
}

/*
 * Deletes fileToDelete and returns true if it is successful. If fileToDelete is not a file or
 * cannot be accessed this method returns false.
 */
static bool deleteFile(const std::string& fileToDelete) {
    // Check whether the file exists.
    PathStatus pathStatus = checkPath(fileToDelete);
    if (pathStatus == NONE) {
        LOG(INFO) << "Path " << fileToDelete << " does not exist";
        return true;
    }
    if (pathStatus != IS_REG) {
        LOG(WARNING) << "Path " << fileToDelete << " failed to stat() or is not a file.";
        return false;
    }

    // Attempt the deletion.
    int rc = unlink(fileToDelete.c_str());
    if (rc != 0) {
        PLOG(WARNING) << "unlink() failed for " << fileToDelete;
    }
    return rc == 0;
}

/*
 * Deletes dirToDelete and returns true if it is successful in removing or moving the directory out
 * of the way. If dirToDelete does not exist this function does nothing and returns true. If
 * dirToDelete is not a directory or cannot be accessed this method returns false.
 *
 * During deletion, this function first renames the directory to a temporary name. If the temporary
 * directory cannot be created, or the directory cannot be renamed, false is returned. After the
 * rename, deletion of files and subdirs beneath the directory is performed on a "best effort"
 * basis. Symlinks beneath the directory are not followed.
 */
static bool deleteDir(const std::string& dirToDelete) {
    // Check whether the dir exists.
    int pathStatus = checkPath(dirToDelete);
    if (pathStatus == NONE) {
        LOG(INFO) << "Path " << dirToDelete << " does not exist";
        return true;
    }
    if (pathStatus != IS_DIR) {
        LOG(WARNING) << "Path " << dirToDelete << " failed to stat() or is not a directory.";
        return false;
    }

    // First, rename dirToDelete.

    std::string tempDirNameTemplate = getParentDir(dirToDelete);
    tempDirNameTemplate += "/tempXXXXXX";

    // Create an empty directory with the temporary name. For this we need a non-const char*.
    std::vector<char> tempDirName(tempDirNameTemplate.length() + 1);
    strcpy(&tempDirName[0], tempDirNameTemplate.c_str());
    if (mkdtemp(&tempDirName[0]) == nullptr) {
        PLOG(WARNING) << "Unable to create a temporary directory: " << tempDirNameTemplate;
        return false;
    }

    // Rename dirToDelete to tempDirName (replacing the empty tempDirName directory created above).
    int rc = rename(dirToDelete.c_str(), &tempDirName[0]);
    if (rc == -1) {
        PLOG(WARNING) << "Unable to rename directory from " << dirToDelete << " to "
                << &tempDirName[0];
        return false;
    }

    // Recursively delete contents of tempDirName.

    rc = nftw(&tempDirName[0], deleteFn, 10 /* openFiles */,
            FTW_DEPTH | FTW_MOUNT | FTW_PHYS);
    if (rc == -1) {
        LOG(INFO) << "Could not delete directory: " << &tempDirName[0];
    }
    return true;
}

/*
 * Deletes the timezone update distro directory.
 */
static void deleteUpdateDistroDir(const std::string& distroDirName) {
    LOG(INFO) << "Removing: " << distroDirName;
    if (!deleteDir(distroDirName)) {
        LOG(WARNING) << "Deletion of distro dir " << distroDirName << " was not successful";
    }
}

static void handleStagedUninstall(const std::string& dataStagedDirName,
                                  const std::string& dataCurrentDirName,
                                  const PathStatus dataCurrentDirStatus) {
    LOG(INFO) << "Staged operation is an uninstall.";

    // Delete the current install directory.
    switch (dataCurrentDirStatus) {
        case NONE:
            // This is unexpected: No uninstall should be staged if there is nothing to
            // uninstall. Carry on anyway.
            LOG(WARNING) << "No current install to delete.";
            break;
        case IS_DIR:
            // This is normal. Delete the current install dir.
            if (!deleteDir(dataCurrentDirName)) {
                LOG(WARNING) << "Deletion of current distro " << dataCurrentDirName
                             << " was not successful";
                // If this happens we don't know whether we were able to delete or not. We don't
                // delete the staged operation so it will be retried next boot unless overridden.
                return;
            }
            break;
        case IS_REG:
        default:
            // This is unexpected: We can try to delete the unexpected file and carry on.
            LOG(WARNING) << "Current distro dir " << dataCurrentDirName
                         << " is not actually a directory. Attempting deletion.";
            if (!deleteFile(dataCurrentDirName)) {
                LOG(WARNING) << "Could not delete " << dataCurrentDirName;
                return;
            }
            break;
    }

    // Delete the staged uninstall dir.
    if (!deleteDir(dataStagedDirName)) {
        LOG(WARNING) << "Deletion of current distro " << dataCurrentDirName
                     << " was not successful";
        // If this happens we don't know whether we were able to delete the staged operation
        // or not.
        return;
    }
    LOG(INFO) << "Staged uninstall complete.";
}

static void handleStagedInstall(const std::string& dataStagedDirName,
                                const std::string& dataCurrentDirName,
                                const PathStatus dataCurrentDirStatus) {
    LOG(INFO) << "Staged operation is an install.";

    switch (dataCurrentDirStatus) {
        case NONE:
            // This is expected: This is the first install.
            LOG(INFO) << "No current install to replace.";
            break;
        case IS_DIR:
            // This is expected: We are replacing an existing install.
            // Delete the current dir so we can replace it.
            if (!deleteDir(dataCurrentDirName)) {
                LOG(WARNING) << "Deletion of current distro " << dataCurrentDirName
                             << " was not successful";
                // If this happens, we cannot proceed.
                return;
            }
            break;
        case IS_REG:
        default:
            // This is unexpected: We can try to delete the unexpected file and carry on.
            LOG(WARNING) << "Current distro dir " << dataCurrentDirName
                         << " is not actually a directory. Attempting deletion.";
            if (!deleteFile(dataCurrentDirName)) {
                LOG(WARNING) << "Could not delete " << dataCurrentDirName;
                return;
            }
            break;
    }

    // Move the staged dir so it is the new current dir, completing the install.
    LOG(INFO) << "Moving " << dataStagedDirName << " to " << dataCurrentDirName;
    int rc = rename(dataStagedDirName.c_str(), dataCurrentDirName.c_str());
    if (rc == -1) {
        PLOG(WARNING) << "Unable to rename directory from " << dataStagedDirName << " to "
                      << &dataCurrentDirName[0];
        return;
    }

    LOG(INFO) << "Staged install complete.";
}
/*
 * Process a staged operation if there is one.
 */
static void processStagedOperation(const std::string& dataStagedDirName,
                                   const std::string& dataCurrentDirName) {
    PathStatus dataStagedDirStatus = checkPath(dataStagedDirName);

    // Exit early for the common case.
    if (dataStagedDirStatus == NONE) {
        LOG(DEBUG) << "No staged time zone operation.";
        return;
    }

    // Check known directory names are in a good starting state.
    if (dataStagedDirStatus != IS_DIR) {
        LOG(WARNING) << "Staged distro dir " << dataStagedDirName
                     << " could not be accessed or is not a directory."
                     << " stagedDirStatus=" << dataStagedDirStatus;
        return;
    }

    // dataStagedDirStatus == IS_DIR.

    // Work out whether there is anything currently installed.
    PathStatus dataCurrentDirStatus = checkPath(dataCurrentDirName);
    if (dataCurrentDirStatus == ERR) {
        LOG(WARNING) << "Current install dir " << dataCurrentDirName << " could not be accessed"
                     << " dataCurrentDirStatus=" << dataCurrentDirStatus;
        return;
    }

    // We must perform the staged operation.

    // Check to see if the staged directory contains an uninstall or an install operation.
    std::string uninstallTombStoneFile(dataStagedDirName);
    uninstallTombStoneFile += UNINSTALL_TOMBSTONE_FILE_NAME;
    int uninstallTombStoneFileStatus = checkPath(uninstallTombStoneFile);
    if (uninstallTombStoneFileStatus != IS_REG && uninstallTombStoneFileStatus != NONE) {
        // Error case.
        LOG(WARNING) << "Unable to determine if the staged operation is an uninstall.";
        return;
    }
    if (uninstallTombStoneFileStatus == IS_REG) {
        handleStagedUninstall(dataStagedDirName, dataCurrentDirName, dataCurrentDirStatus);
    } else {
        // uninstallTombStoneFileStatus == NONE meaning this is a staged install.
        handleStagedInstall(dataStagedDirName, dataCurrentDirName, dataCurrentDirStatus);
    }
}

/*
 * After a platform update it is likely that the "base" timezone data found on the device will be
 * newer than the version found in the data partition. This tool detects this case and removes the
 * version in /data.
 *
 * Note: This code is related to code in com.android.server.updates.TzDataInstallReceiver. The
 * paths for the metadata and current timezone data must match.
 *
 * Typically on device the two args will be:
 *   /apex/com.google.runtime/etc/tz /data/misc/zoneinfo
 *
 * See usage() for usage notes.
 */
int main(int argc, char* argv[]) {
    if (argc != 3) {
        usage();
        return 1;
    }

    const char* baseZoneInfoDir = argv[1];
    const char* dataZoneInfoDir = argv[2];

    std::string dataStagedDirName(dataZoneInfoDir);
    dataStagedDirName += STAGED_DIR_NAME;

    std::string dataCurrentDirName(dataZoneInfoDir);
    dataCurrentDirName += CURRENT_DIR_NAME;

    // Check for an process any staged operation.
    // If the staged operation could not be handled we still have to validate the current installed
    // directory so we do not check for errors and do not quit early.
    processStagedOperation(dataStagedDirName, dataCurrentDirName);

    // Check the distro directory exists. If it does not, exit quickly: nothing to do.
    PathStatus dataCurrentDirStatus = checkPath(dataCurrentDirName);
    if (dataCurrentDirStatus == NONE) {
        LOG(INFO) << "timezone distro dir " << dataCurrentDirName
                << " does not exist. No action required.";
        return 0;
    }

    // If the distro directory path is not a directory or we can't stat() the path, exit with a
    // warning: either there's a problem accessing storage or the world is not as it should be;
    // nothing to do.
    if (dataCurrentDirStatus != IS_DIR) {
        LOG(WARNING) << "Current distro dir " << dataCurrentDirName
                << " could not be accessed or is not a directory. result=" << dataCurrentDirStatus;
        return 2;
    }

    // Check the installed distro version.
    std::string distroVersionFileName(dataCurrentDirName);
    distroVersionFileName += DISTRO_VERSION_FILENAME;
    std::vector<char> distroVersion;
    distroVersion.reserve(READ_DATA_LENGTH);
    bool distroVersionReadOk =
            readBytes(distroVersionFileName, distroVersion.data(), READ_DATA_LENGTH);
    if (!distroVersionReadOk) {
        LOG(WARNING) << "distro version file " << distroVersionFileName
                << " does not exist or is too short. Deleting distro dir.";
        // Implies the contents of the data partition is corrupt in some way. Try to clean up.
        deleteUpdateDistroDir(dataCurrentDirName);
        return 3;
    }

    if (!checkValidVersionBytes(distroVersion.data())) {
        LOG(WARNING) << "distro version file " << distroVersionFileName
                << " is not valid. Deleting distro dir.";
        // Implies the contents of the data partition is corrupt in some way. Try to clean up.
        deleteUpdateDistroDir(dataCurrentDirName);
        return 4;
    }

    // Check the base tz data set version.
    std::string baseVersionFileName(baseZoneInfoDir);
    baseVersionFileName += BASE_VERSION_FILENAME;
    std::vector<char> baseVersion;
    baseVersion.reserve(READ_DATA_LENGTH);
    bool baseVersionReadOk =
            readBytes(baseVersionFileName, baseVersion.data(), READ_DATA_LENGTH);
    if (!baseVersionReadOk) {
        // Implies the contents of the system partition is corrupt in some way. Nothing we can do.
        LOG(WARNING) << baseVersionFileName << " does not exist or could not be opened";
        return 6;
    }

    if (!checkValidVersionBytes(baseVersion.data())) {
        // Implies the contents of the system partition is corrupt in some way. Nothing we can do.
        LOG(WARNING) << baseVersionFileName << " is not valid.";
        return 7;
    }

    std::string actualDistroVersion = std::string(distroVersion.data(), FORMAT_VERSION_LEN);
    std::string baseTzVersion = std::string(baseVersion.data(), FORMAT_VERSION_LEN);

    // Check the first 3 bytes of the format version: these are the major version (e.g. 001).
    // It must match the one we support exactly to be ok.
    if (strncmp(
            &distroVersion[FORMAT_MAJOR_VERSION_IDX],
            &baseTzVersion[FORMAT_MAJOR_VERSION_IDX],
            FORMAT_MAJOR_VERSION_LEN) != 0) {

        LOG(INFO) << "distro version file " << distroVersionFileName
                << " major version is not the required version " << baseTzVersion
                << ", was \"" << actualDistroVersion << "\". Deleting distro dir.";
        // This implies there has been an OTA and the installed distro is not compatible with a
        // new version of Android. Remove the installed distro.
        deleteUpdateDistroDir(dataCurrentDirName);
        return 5;
    }

    // Check the last 3 bytes of the format version: these are the minor version (e.g. 001).
    // If the version in the distro is < the minor version required by this device it cannot be
    // used.
    if (strncmp(
            &distroVersion[FORMAT_MINOR_VERSION_IDX],
            &baseTzVersion[FORMAT_MINOR_VERSION_IDX],
            FORMAT_MINOR_VERSION_LEN) < 0) {

        LOG(INFO) << "distro version file " << distroVersionFileName
                << " minor version is not the required version " << baseTzVersion
                << ", was \"" << actualDistroVersion << "\". Deleting distro dir.";
        // This implies there has been an OTA and the installed distro is not compatible with a
        // new version of Android. Remove the installed distro.
        deleteUpdateDistroDir(dataCurrentDirName);
        return 5;
    }

    // Compare the distro rules version against the system rules version.
    if (strncmp(
            &baseVersion[VERSION_RULES_IDX],
            &distroVersion[VERSION_RULES_IDX],
            RULES_VERSION_LEN) <= 0) {
        LOG(INFO) << "Found an installed distro but it is valid. No action taken.";
        // Implies there is an installed update, but it is good.
        return 0;
    }

    // Implies there has been an OTA and the system version of the timezone rules is now newer
    // than the version installed in /data. Remove the installed distro.
    LOG(INFO) << "timezone distro in " << dataCurrentDirName << " is older than data in "
            << baseVersionFileName << "; fixing...";

    deleteUpdateDistroDir(dataCurrentDirName);
    return 0;
}
