/*
 * Copyright (C) 2009 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 "updater/updater.h"

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

#include <string>

#include <android-base/strings.h>
#include <selinux/label.h>
#include <selinux/selinux.h>
#include <ziparchive/zip_archive.h>

#include "config.h"
#include "edify/expr.h"
#include "otautil/DirUtil.h"
#include "otautil/SysUtil.h"
#include "updater/blockimg.h"
#include "updater/install.h"

// Generated by the makefile, this function defines the
// RegisterDeviceExtensions() function, which calls all the
// registration functions for device-specific extensions.
#include "register.inc"

// Where in the package we expect to find the edify script to execute.
// (Note it's "updateR-script", not the older "update-script".)
#define SCRIPT_NAME "META-INF/com/google/android/updater-script"

extern bool have_eio_error;

struct selabel_handle *sehandle;

int main(int argc, char** argv) {
    // Various things log information to stdout or stderr more or less
    // at random (though we've tried to standardize on stdout).  The
    // log file makes more sense if buffering is turned off so things
    // appear in the right order.
    setbuf(stdout, NULL);
    setbuf(stderr, NULL);

    if (argc != 4 && argc != 5) {
        printf("unexpected number of arguments (%d)\n", argc);
        return 1;
    }

    char* version = argv[1];
    if ((version[0] != '1' && version[0] != '2' && version[0] != '3') ||
        version[1] != '\0') {
        // We support version 1, 2, or 3.
        printf("wrong updater binary API; expected 1, 2, or 3; "
                        "got %s\n",
                argv[1]);
        return 2;
    }

    // Set up the pipe for sending commands back to the parent process.

    int fd = atoi(argv[2]);
    FILE* cmd_pipe = fdopen(fd, "wb");
    setlinebuf(cmd_pipe);

    // Extract the script from the package.

    const char* package_filename = argv[3];
    MemMapping map;
    if (sysMapFile(package_filename, &map) != 0) {
        printf("failed to map package %s\n", argv[3]);
        return 3;
    }
    ZipArchiveHandle za;
    int open_err = OpenArchiveFromMemory(map.addr, map.length, argv[3], &za);
    if (open_err != 0) {
        printf("failed to open package %s: %s\n",
               argv[3], ErrorCodeString(open_err));
        CloseArchive(za);
        return 3;
    }
    ota_io_init(za);

    ZipString script_name(SCRIPT_NAME);
    ZipEntry script_entry;
    int find_err = FindEntry(za, script_name, &script_entry);
    if (find_err != 0) {
        printf("failed to find %s in %s: %s\n", SCRIPT_NAME, package_filename,
               ErrorCodeString(find_err));
        CloseArchive(za);
        return 4;
    }

    std::string script;
    script.resize(script_entry.uncompressed_length);
    int extract_err = ExtractToMemory(za, &script_entry, reinterpret_cast<uint8_t*>(&script[0]),
                                      script_entry.uncompressed_length);
    if (extract_err != 0) {
        printf("failed to read script from package: %s\n", ErrorCodeString(extract_err));
        CloseArchive(za);
        return 5;
    }

    // Configure edify's functions.

    RegisterBuiltins();
    RegisterInstallFunctions();
    RegisterBlockImageFunctions();
    RegisterDeviceExtensions();

    // Parse the script.

    Expr* root;
    int error_count = 0;
    int error = parse_string(script.c_str(), &root, &error_count);
    if (error != 0 || error_count > 0) {
        printf("%d parse errors\n", error_count);
        CloseArchive(za);
        return 6;
    }

    struct selinux_opt seopts[] = {
      { SELABEL_OPT_PATH, "/file_contexts" }
    };

    sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1);

    if (!sehandle) {
        fprintf(cmd_pipe, "ui_print Warning: No file_contexts\n");
    }

    // Evaluate the parsed script.

    UpdaterInfo updater_info;
    updater_info.cmd_pipe = cmd_pipe;
    updater_info.package_zip = za;
    updater_info.version = atoi(version);
    updater_info.package_zip_addr = map.addr;
    updater_info.package_zip_len = map.length;

    State state(script, &updater_info);

    if (argc == 5) {
        if (strcmp(argv[4], "retry") == 0) {
            state.is_retry = true;
        } else {
            printf("unexpected argument: %s", argv[4]);
        }
    }

    std::string result;
    bool status = Evaluate(&state, root, &result);

    if (have_eio_error) {
        fprintf(cmd_pipe, "retry_update\n");
    }

    if (!status) {
        if (state.errmsg.empty()) {
            printf("script aborted (no error message)\n");
            fprintf(cmd_pipe, "ui_print script aborted (no error message)\n");
        } else {
            printf("script aborted: %s\n", state.errmsg.c_str());
            const std::vector<std::string> lines = android::base::Split(state.errmsg, "\n");
            for (const std::string& line : lines) {
                // Parse the error code in abort message.
                // Example: "E30: This package is for bullhead devices."
                if (!line.empty() && line[0] == 'E') {
                    if (sscanf(line.c_str(), "E%u: ", &state.error_code) != 1) {
                         printf("Failed to parse error code: [%s]\n", line.c_str());
                    }
                }
                fprintf(cmd_pipe, "ui_print %s\n", line.c_str());
            }
            fprintf(cmd_pipe, "ui_print\n");
        }

        if (state.error_code != kNoError) {
            fprintf(cmd_pipe, "log error: %d\n", state.error_code);
            // Cause code should provide additional information about the abort;
            // report only when an error exists.
            if (state.cause_code != kNoCause) {
                fprintf(cmd_pipe, "log cause: %d\n", state.cause_code);
            }
        }

        if (updater_info.package_zip) {
            CloseArchive(updater_info.package_zip);
        }
        return 7;
    } else {
        fprintf(cmd_pipe, "ui_print script succeeded: result was [%s]\n", result.c_str());
    }

    if (updater_info.package_zip) {
        CloseArchive(updater_info.package_zip);
    }
    sysReleaseMap(&map);

    return 0;
}
