/*
 * Copyright (C) 2014 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.
 */

// This program takes a file on an ext4 filesystem and produces a list
// of the blocks that file occupies, which enables the file contents
// to be read directly from the block device without mounting the
// filesystem.
//
// If the filesystem is using an encrypted block device, it will also
// read the file and rewrite it to the same blocks of the underlying
// (unencrypted) block device, so the file contents can be read
// without the need for the decryption key.
//
// The output of this program is a "block map" which looks like this:
//
//     /dev/block/platform/msm_sdcc.1/by-name/userdata     # block device
//     49652 4096                        # file size in bytes, block size
//     3                                 # count of block ranges
//     1000 1008                         # block range 0
//     2100 2102                         # ... block range 1
//     30 33                             # ... block range 2
//
// Each block range represents a half-open interval; the line "30 33"
// reprents the blocks [30, 31, 32].
//
// Recovery can take this block map file and retrieve the underlying
// file data to use as an update package.

#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <libgen.h>
#include <linux/fs.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <algorithm>
#include <memory>
#include <vector>

#include <android-base/file.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <cutils/android_reboot.h>
#include <cutils/properties.h>
#include <fs_mgr.h>

#define LOG_TAG "uncrypt"
#include <log/log.h>

#include "unique_fd.h"

#define WINDOW_SIZE 5

static const std::string cache_block_map = "/cache/recovery/block.map";
static const std::string status_file = "/cache/recovery/uncrypt_status";
static const std::string uncrypt_file = "/cache/recovery/uncrypt_file";

static struct fstab* fstab = NULL;

static int write_at_offset(unsigned char* buffer, size_t size, int wfd, off64_t offset) {
    if (TEMP_FAILURE_RETRY(lseek64(wfd, offset, SEEK_SET)) == -1) {
        ALOGE("error seeking to offset %" PRId64 ": %s\n", offset, strerror(errno));
        return -1;
    }
    if (!android::base::WriteFully(wfd, buffer, size)) {
        ALOGE("error writing offset %" PRId64 ": %s\n", offset, strerror(errno));
        return -1;
    }
    return 0;
}

static void add_block_to_ranges(std::vector<int>& ranges, int new_block) {
    if (!ranges.empty() && new_block == ranges.back()) {
        // If the new block comes immediately after the current range,
        // all we have to do is extend the current range.
        ++ranges.back();
    } else {
        // We need to start a new range.
        ranges.push_back(new_block);
        ranges.push_back(new_block + 1);
    }
}

static struct fstab* read_fstab() {
    fstab = NULL;

    // The fstab path is always "/fstab.${ro.hardware}".
    char fstab_path[PATH_MAX+1] = "/fstab.";
    if (!property_get("ro.hardware", fstab_path+strlen(fstab_path), "")) {
        ALOGE("failed to get ro.hardware\n");
        return NULL;
    }

    fstab = fs_mgr_read_fstab(fstab_path);
    if (!fstab) {
        ALOGE("failed to read %s\n", fstab_path);
        return NULL;
    }

    return fstab;
}

static const char* find_block_device(const char* path, bool* encryptable, bool* encrypted) {
    // Look for a volume whose mount point is the prefix of path and
    // return its block device.  Set encrypted if it's currently
    // encrypted.
    for (int i = 0; i < fstab->num_entries; ++i) {
        struct fstab_rec* v = &fstab->recs[i];
        if (!v->mount_point) {
            continue;
        }
        int len = strlen(v->mount_point);
        if (strncmp(path, v->mount_point, len) == 0 &&
            (path[len] == '/' || path[len] == 0)) {
            *encrypted = false;
            *encryptable = false;
            if (fs_mgr_is_encryptable(v) || fs_mgr_is_file_encrypted(v)) {
                *encryptable = true;
                char buffer[PROPERTY_VALUE_MAX+1];
                if (property_get("ro.crypto.state", buffer, "") &&
                    strcmp(buffer, "encrypted") == 0) {
                    *encrypted = true;
                }
            }
            return v->blk_device;
        }
    }

    return NULL;
}

// Parse uncrypt_file to find the update package name.
static bool find_uncrypt_package(std::string& package_name)
{
    if (!android::base::ReadFileToString(uncrypt_file, &package_name)) {
        ALOGE("failed to open \"%s\": %s\n", uncrypt_file.c_str(), strerror(errno));
        return false;
    }

    // Remove the trailing '\n' if present.
    package_name = android::base::Trim(package_name);

    return true;
}

static int produce_block_map(const char* path, const char* map_file, const char* blk_dev,
                             bool encrypted, int status_fd) {
    std::string err;
    if (!android::base::RemoveFileIfExists(map_file, &err)) {
        ALOGE("failed to remove the existing map file %s: %s\n", map_file, err.c_str());
        return -1;
    }
    std::string tmp_map_file = std::string(map_file) + ".tmp";
    unique_fd mapfd(open(tmp_map_file.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR));
    if (!mapfd) {
        ALOGE("failed to open %s: %s\n", tmp_map_file.c_str(), strerror(errno));
        return -1;
    }

    // Make sure we can write to the status_file.
    if (!android::base::WriteStringToFd("0\n", status_fd)) {
        ALOGE("failed to update \"%s\"\n", status_file.c_str());
        return -1;
    }

    struct stat sb;
    if (stat(path, &sb) != 0) {
        ALOGE("failed to stat %s\n", path);
        return -1;
    }

    ALOGI(" block size: %ld bytes\n", static_cast<long>(sb.st_blksize));

    int blocks = ((sb.st_size-1) / sb.st_blksize) + 1;
    ALOGI("  file size: %" PRId64 " bytes, %d blocks\n", sb.st_size, blocks);

    std::vector<int> ranges;

    std::string s = android::base::StringPrintf("%s\n%" PRId64 " %ld\n",
                       blk_dev, sb.st_size, static_cast<long>(sb.st_blksize));
    if (!android::base::WriteStringToFd(s, mapfd.get())) {
        ALOGE("failed to write %s: %s\n", tmp_map_file.c_str(), strerror(errno));
        return -1;
    }

    std::vector<std::vector<unsigned char>> buffers;
    if (encrypted) {
        buffers.resize(WINDOW_SIZE, std::vector<unsigned char>(sb.st_blksize));
    }
    int head_block = 0;
    int head = 0, tail = 0;

    unique_fd fd(open(path, O_RDONLY));
    if (!fd) {
        ALOGE("failed to open %s for reading: %s\n", path, strerror(errno));
        return -1;
    }

    unique_fd wfd(-1);
    if (encrypted) {
        wfd = open(blk_dev, O_WRONLY);
        if (!wfd) {
            ALOGE("failed to open fd for writing: %s\n", strerror(errno));
            return -1;
        }
    }

    off64_t pos = 0;
    int last_progress = 0;
    while (pos < sb.st_size) {
        // Update the status file, progress must be between [0, 99].
        int progress = static_cast<int>(100 * (double(pos) / double(sb.st_size)));
        if (progress > last_progress) {
          last_progress = progress;
          android::base::WriteStringToFd(std::to_string(progress) + "\n", status_fd);
        }

        if ((tail+1) % WINDOW_SIZE == head) {
            // write out head buffer
            int block = head_block;
            if (ioctl(fd.get(), FIBMAP, &block) != 0) {
                ALOGE("failed to find block %d\n", head_block);
                return -1;
            }
            add_block_to_ranges(ranges, block);
            if (encrypted) {
                if (write_at_offset(buffers[head].data(), sb.st_blksize, wfd.get(),
                        static_cast<off64_t>(sb.st_blksize) * block) != 0) {
                    return -1;
                }
            }
            head = (head + 1) % WINDOW_SIZE;
            ++head_block;
        }

        // read next block to tail
        if (encrypted) {
            size_t to_read = static_cast<size_t>(
                    std::min(static_cast<off64_t>(sb.st_blksize), sb.st_size - pos));
            if (!android::base::ReadFully(fd.get(), buffers[tail].data(), to_read)) {
                ALOGE("failed to read: %s\n", strerror(errno));
                return -1;
            }
            pos += to_read;
        } else {
            // If we're not encrypting; we don't need to actually read
            // anything, just skip pos forward as if we'd read a
            // block.
            pos += sb.st_blksize;
        }
        tail = (tail+1) % WINDOW_SIZE;
    }

    while (head != tail) {
        // write out head buffer
        int block = head_block;
        if (ioctl(fd.get(), FIBMAP, &block) != 0) {
            ALOGE("failed to find block %d\n", head_block);
            return -1;
        }
        add_block_to_ranges(ranges, block);
        if (encrypted) {
            if (write_at_offset(buffers[head].data(), sb.st_blksize, wfd.get(),
                    static_cast<off64_t>(sb.st_blksize) * block) != 0) {
                return -1;
            }
        }
        head = (head + 1) % WINDOW_SIZE;
        ++head_block;
    }

    if (!android::base::WriteStringToFd(
            android::base::StringPrintf("%zu\n", ranges.size() / 2), mapfd.get())) {
        ALOGE("failed to write %s: %s\n", tmp_map_file.c_str(), strerror(errno));
        return -1;
    }
    for (size_t i = 0; i < ranges.size(); i += 2) {
        if (!android::base::WriteStringToFd(
                android::base::StringPrintf("%d %d\n", ranges[i], ranges[i+1]), mapfd.get())) {
            ALOGE("failed to write %s: %s\n", tmp_map_file.c_str(), strerror(errno));
            return -1;
        }
    }

    if (fsync(mapfd.get()) == -1) {
        ALOGE("failed to fsync \"%s\": %s\n", tmp_map_file.c_str(), strerror(errno));
        return -1;
    }
    if (close(mapfd.get() == -1)) {
        ALOGE("failed to close %s: %s\n", tmp_map_file.c_str(), strerror(errno));
        return -1;
    }
    mapfd = -1;

    if (encrypted) {
        if (fsync(wfd.get()) == -1) {
            ALOGE("failed to fsync \"%s\": %s\n", blk_dev, strerror(errno));
            return -1;
        }
        if (close(wfd.get()) == -1) {
            ALOGE("failed to close %s: %s\n", blk_dev, strerror(errno));
            return -1;
        }
        wfd = -1;
    }

    if (rename(tmp_map_file.c_str(), map_file) == -1) {
        ALOGE("failed to rename %s to %s: %s\n", tmp_map_file.c_str(), map_file, strerror(errno));
        return -1;
    }
    // Sync dir to make rename() result written to disk.
    std::string file_name = map_file;
    std::string dir_name = dirname(&file_name[0]);
    unique_fd dfd(open(dir_name.c_str(), O_RDONLY | O_DIRECTORY));
    if (!dfd) {
        ALOGE("failed to open dir %s: %s\n", dir_name.c_str(), strerror(errno));
        return -1;
    }
    if (fsync(dfd.get()) == -1) {
        ALOGE("failed to fsync %s: %s\n", dir_name.c_str(), strerror(errno));
        return -1;
    }
    if (close(dfd.get() == -1)) {
        ALOGE("failed to close %s: %s\n", dir_name.c_str(), strerror(errno));
        return -1;
    }
    dfd = -1;
    return 0;
}

static void wipe_misc() {
    ALOGI("removing old commands from misc");
    for (int i = 0; i < fstab->num_entries; ++i) {
        struct fstab_rec* v = &fstab->recs[i];
        if (!v->mount_point) continue;
        if (strcmp(v->mount_point, "/misc") == 0) {
            int fd = open(v->blk_device, O_WRONLY | O_SYNC);
            unique_fd fd_holder(fd);

            uint8_t zeroes[1088];   // sizeof(bootloader_message) from recovery
            memset(zeroes, 0, sizeof(zeroes));

            size_t written = 0;
            size_t size = sizeof(zeroes);
            while (written < size) {
                ssize_t w = TEMP_FAILURE_RETRY(write(fd, zeroes, size-written));
                if (w == -1) {
                    ALOGE("zero write failed: %s\n", strerror(errno));
                    return;
                } else {
                    written += w;
                }
            }
            if (fsync(fd) == -1) {
                ALOGE("failed to fsync \"%s\": %s\n", v->blk_device, strerror(errno));
                return;
            }
        }
    }
}

static void reboot_to_recovery() {
    ALOGI("rebooting to recovery");
    property_set("sys.powerctl", "reboot,recovery");
    while (true) {
      pause();
    }
    ALOGE("reboot didn't succeed?");
}

int uncrypt(const char* input_path, const char* map_file, int status_fd) {

    ALOGI("update package is \"%s\"", input_path);

    // Turn the name of the file we're supposed to convert into an
    // absolute path, so we can find what filesystem it's on.
    char path[PATH_MAX+1];
    if (realpath(input_path, path) == NULL) {
        ALOGE("failed to convert \"%s\" to absolute path: %s", input_path, strerror(errno));
        return 1;
    }

    if (read_fstab() == NULL) {
        return 1;
    }

    bool encryptable;
    bool encrypted;
    const char* blk_dev = find_block_device(path, &encryptable, &encrypted);
    if (blk_dev == NULL) {
        ALOGE("failed to find block device for %s", path);
        return 1;
    }

    // If the filesystem it's on isn't encrypted, we only produce the
    // block map, we don't rewrite the file contents (it would be
    // pointless to do so).
    ALOGI("encryptable: %s\n", encryptable ? "yes" : "no");
    ALOGI("  encrypted: %s\n", encrypted ? "yes" : "no");

    // Recovery supports installing packages from 3 paths: /cache,
    // /data, and /sdcard.  (On a particular device, other locations
    // may work, but those are three we actually expect.)
    //
    // On /data we want to convert the file to a block map so that we
    // can read the package without mounting the partition.  On /cache
    // and /sdcard we leave the file alone.
    if (strncmp(path, "/data/", 6) == 0) {
        ALOGI("writing block map %s", map_file);
        if (produce_block_map(path, map_file, blk_dev, encrypted, status_fd) != 0) {
            return 1;
        }
    }

    return 0;
}

int main(int argc, char** argv) {

    if (argc != 3 && argc != 1 && (argc == 2 && strcmp(argv[1], "--reboot") != 0)) {
        fprintf(stderr, "usage: %s [--reboot] [<transform_path> <map_file>]\n", argv[0]);
        return 2;
    }

    // When uncrypt is started with "--reboot", it wipes misc and reboots.
    // Otherwise it uncrypts the package and writes the block map.
    if (argc == 2) {
        if (read_fstab() == NULL) {
            return 1;
        }
        wipe_misc();
        reboot_to_recovery();
    } else {
        // The pipe has been created by the system server.
        int status_fd = open(status_file.c_str(), O_WRONLY | O_CREAT | O_SYNC, S_IRUSR | S_IWUSR);
        if (status_fd == -1) {
            ALOGE("failed to open pipe \"%s\": %s\n", status_file.c_str(), strerror(errno));
            return 1;
        }
        unique_fd status_fd_holder(status_fd);

        std::string package;
        const char* input_path;
        const char* map_file;

        if (argc == 3) {
            // when command-line args are given this binary is being used
            // for debugging.
            input_path = argv[1];
            map_file = argv[2];
        } else {
            if (!find_uncrypt_package(package)) {
                android::base::WriteStringToFd("-1\n", status_fd);
                return 1;
            }
            input_path = package.c_str();
            map_file = cache_block_map.c_str();
        }

        int status = uncrypt(input_path, map_file, status_fd);
        if (status != 0) {
            android::base::WriteStringToFd("-1\n", status_fd);
            return 1;
        }

        android::base::WriteStringToFd("100\n", status_fd);
    }

    return 0;
}
