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

// Note that these check functions cannot check expanded arguments from properties, since they will
// not know what those properties would be at runtime.  They will be passed an empty string in the
// situation that the input line had a property expansion without a default value, since an empty
// string is otherwise an impossible value.  They should therefore disregard checking empty
// arguments.

#include "check_builtins.h"

#include <sys/time.h>

#include <android-base/logging.h>
#include <android-base/parseint.h>
#include <android-base/strings.h>

#include "builtin_arguments.h"
#include "host_init_verifier.h"
#include "interface_utils.h"
#include "property_type.h"
#include "rlimit_parser.h"
#include "service.h"
#include "util.h"

using android::base::ParseInt;
using android::base::StartsWith;

#define ReturnIfAnyArgsEmpty()     \
    for (const auto& arg : args) { \
        if (arg.empty()) {         \
            return {};             \
        }                          \
    }

namespace android {
namespace init {

Result<void> check_chown(const BuiltinArguments& args) {
    if (!args[1].empty()) {
        auto uid = DecodeUid(args[1]);
        if (!uid.ok()) {
            return Error() << "Unable to decode UID for '" << args[1] << "': " << uid.error();
        }
    }

    // GID is optional and pushes the index of path out by one if specified.
    if (args.size() == 4 && !args[2].empty()) {
        auto gid = DecodeUid(args[2]);
        if (!gid.ok()) {
            return Error() << "Unable to decode GID for '" << args[2] << "': " << gid.error();
        }
    }

    return {};
}

Result<void> check_exec(const BuiltinArguments& args) {
    ReturnIfAnyArgsEmpty();

    auto result = Service::MakeTemporaryOneshotService(args.args);
    if (!result.ok()) {
        return result.error();
    }

    return {};
}

Result<void> check_exec_background(const BuiltinArguments& args) {
    return check_exec(std::move(args));
}

Result<void> check_exec_reboot_on_failure(const BuiltinArguments& args) {
    BuiltinArguments remaining_args(args.context);

    remaining_args.args = std::vector<std::string>(args.begin() + 1, args.end());
    remaining_args.args[0] = args[0];

    return check_exec(remaining_args);
}

Result<void> check_interface_restart(const BuiltinArguments& args) {
    if (auto result = IsKnownInterface(args[1]); !result.ok()) {
        return result.error();
    }
    return {};
}

Result<void> check_interface_start(const BuiltinArguments& args) {
    return check_interface_restart(std::move(args));
}

Result<void> check_interface_stop(const BuiltinArguments& args) {
    return check_interface_restart(std::move(args));
}

Result<void> check_load_system_props(const BuiltinArguments& args) {
    return Error() << "'load_system_props' is deprecated";
}

Result<void> check_loglevel(const BuiltinArguments& args) {
    ReturnIfAnyArgsEmpty();

    int log_level = -1;
    ParseInt(args[1], &log_level);
    if (log_level < 0 || log_level > 7) {
        return Error() << "loglevel must be in the range of 0-7";
    }
    return {};
}

Result<void> check_mkdir(const BuiltinArguments& args) {
    auto options = ParseMkdir(args.args);
    if (!options.ok()) {
        return options.error();
    }
    return {};
}

Result<void> check_restorecon(const BuiltinArguments& args) {
    ReturnIfAnyArgsEmpty();

    auto restorecon_info = ParseRestorecon(args.args);
    if (!restorecon_info.ok()) {
        return restorecon_info.error();
    }

    return {};
}

Result<void> check_restorecon_recursive(const BuiltinArguments& args) {
    return check_restorecon(std::move(args));
}

Result<void> check_setprop(const BuiltinArguments& args) {
    const std::string& name = args[1];
    if (name.empty()) {
        return {};
    }
    const std::string& value = args[2];

    if (!IsLegalPropertyName(name)) {
        return Error() << "'" << name << "' is not a legal property name";
    }

    if (!value.empty()) {
        if (auto result = IsLegalPropertyValue(name, value); !result.ok()) {
            return result.error();
        }
    }

    if (StartsWith(name, "ctl.")) {
        return Error()
               << "Do not set ctl. properties from init; call the Service functions directly";
    }

    static constexpr const char kRestoreconProperty[] = "selinux.restorecon_recursive";
    if (name == kRestoreconProperty) {
        return Error() << "Do not set '" << kRestoreconProperty
                       << "' from init; use the restorecon builtin directly";
    }

    const char* target_context = nullptr;
    const char* type = nullptr;
    property_info_area->GetPropertyInfo(name.c_str(), &target_context, &type);

    if (!CheckType(type, value)) {
        return Error() << "Property type check failed, value doesn't match expected type '"
                       << (type ?: "(null)") << "'";
    }

    return {};
}

Result<void> check_setrlimit(const BuiltinArguments& args) {
    ReturnIfAnyArgsEmpty();

    auto rlimit = ParseRlimit(args.args);
    if (!rlimit.ok()) return rlimit.error();
    return {};
}

Result<void> check_sysclktz(const BuiltinArguments& args) {
    ReturnIfAnyArgsEmpty();

    struct timezone tz = {};
    if (!android::base::ParseInt(args[1], &tz.tz_minuteswest)) {
        return Error() << "Unable to parse mins_west_of_gmt";
    }
    return {};
}

Result<void> check_wait(const BuiltinArguments& args) {
    if (args.size() == 3 && !args[2].empty()) {
        int timeout_int;
        if (!android::base::ParseInt(args[2], &timeout_int)) {
            return Error() << "failed to parse timeout";
        }
    }
    return {};
}

Result<void> check_wait_for_prop(const BuiltinArguments& args) {
    return check_setprop(std::move(args));
}

}  // namespace init
}  // namespace android
