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

#define ATRACE_TAG ATRACE_TAG_PACKAGE_MANAGER

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>

#include <sys/mount.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>

#include <linux/kdev_t.h>

#include <android-base/logging.h>
#include <android-base/strings.h>
#include <android-base/stringprintf.h>
#include <android-base/unique_fd.h>
#include <utils/Trace.h>

#include "Loop.h"
#include "VoldUtil.h"
#include "sehandle.h"

using android::base::StringPrintf;
using android::base::unique_fd;

static const char* kVoldPrefix = "vold:";

int Loop::create(const std::string& target, std::string& out_device) {
    unique_fd ctl_fd(open("/dev/loop-control", O_RDWR | O_CLOEXEC));
    if (ctl_fd.get() == -1) {
        PLOG(ERROR) << "Failed to open loop-control";
        return -errno;
    }

    int num = ioctl(ctl_fd.get(), LOOP_CTL_GET_FREE);
    if (num == -1) {
        PLOG(ERROR) << "Failed LOOP_CTL_GET_FREE";
        return -errno;
    }

    out_device = StringPrintf("/dev/block/loop%d", num);

    unique_fd target_fd(open(target.c_str(), O_RDWR | O_CLOEXEC));
    if (target_fd.get() == -1) {
        PLOG(ERROR) << "Failed to open " << target;
        return -errno;
    }
    unique_fd device_fd(open(out_device.c_str(), O_RDWR | O_CLOEXEC));
    if (device_fd.get() == -1) {
        PLOG(ERROR) << "Failed to open " << out_device;
        return -errno;
    }

    if (ioctl(device_fd.get(), LOOP_SET_FD, target_fd.get()) == -1) {
        PLOG(ERROR) << "Failed to LOOP_SET_FD";
        return -errno;
    }

    struct loop_info64 li;
    memset(&li, 0, sizeof(li));
    strlcpy((char*) li.lo_crypt_name, kVoldPrefix, LO_NAME_SIZE);
    if (ioctl(device_fd.get(), LOOP_SET_STATUS64, &li) == -1) {
        PLOG(ERROR) << "Failed to LOOP_SET_STATUS64";
        return -errno;
    }

    return 0;
}

int Loop::destroyByDevice(const char *loopDevice) {
    int device_fd;

    device_fd = open(loopDevice, O_RDONLY | O_CLOEXEC);
    if (device_fd < 0) {
        PLOG(ERROR) << "Failed to open " << loopDevice;
        return -1;
    }

    if (ioctl(device_fd, LOOP_CLR_FD, 0) < 0) {
        PLOG(ERROR) << "Failed to destroy " << loopDevice;
        close(device_fd);
        return -1;
    }

    close(device_fd);
    return 0;
}

int Loop::destroyAll() {
    ATRACE_NAME("Loop::destroyAll");

    DIR* dir;
    struct dirent* de;

    std::string root = "/dev/block/";
    if (!(dir = opendir(root.c_str()))) {
        PLOG(ERROR) << "Failed to opendir";
        return -1;
    }

    // Poke through all devices looking for loops
    while ((de = readdir(dir))) {
        auto test = std::string(de->d_name);
        if (!android::base::StartsWith(test, "loop")) continue;

        auto path = root + de->d_name;
        unique_fd fd(open(path.c_str(), O_RDWR | O_CLOEXEC));
        if (fd.get() == -1) {
            if (errno != ENOENT) {
                PLOG(WARNING) << "Failed to open " << path;
            }
            continue;
        }

        struct loop_info64 li;
        if (ioctl(fd.get(), LOOP_GET_STATUS64, &li) < 0) {
            PLOG(WARNING) << "Failed to LOOP_GET_STATUS64 " << path;
            continue;
        }

        auto id = std::string((char*) li.lo_crypt_name);
        if (android::base::StartsWith(id, kVoldPrefix)) {
            LOG(DEBUG) << "Tearing down stale loop device at " << path << " named " << id;

            if (ioctl(fd.get(), LOOP_CLR_FD, 0) < 0) {
                PLOG(WARNING) << "Failed to LOOP_CLR_FD " << path;
            }
        } else {
            LOG(VERBOSE) << "Found unmanaged loop device at " << path << " named " << id;
        }
    }

    closedir(dir);
    return 0;
}

int Loop::createImageFile(const char *file, unsigned long numSectors) {
    unique_fd fd(open(file, O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC, 0600));
    if (fd.get() == -1) {
        PLOG(ERROR) << "Failed to create image " << file;
        return -errno;
    }
    if (fallocate(fd.get(), 0, 0, numSectors * 512) == -1) {
        PLOG(WARNING) << "Failed to fallocate; falling back to ftruncate";
        if (ftruncate(fd, numSectors * 512) == -1) {
            PLOG(ERROR) << "Failed to ftruncate";
            return -errno;
        }
    }
    return 0;
}

int Loop::resizeImageFile(const char *file, unsigned long numSectors) {
    int fd;

    if ((fd = open(file, O_RDWR | O_CLOEXEC)) < 0) {
        PLOG(ERROR) << "Failed to open " << file;
        return -1;
    }

    LOG(DEBUG) << "Attempting to increase " << file << " to " << numSectors;

    if (fallocate(fd, 0, 0, numSectors * 512)) {
        if (errno == ENOSYS || errno == ENOTSUP) {
            PLOG(WARNING) << "fallocate not found. Falling back to ftruncate.";
            if (ftruncate(fd, numSectors * 512) < 0) {
                PLOG(ERROR) << "Failed to ftruncate";
                close(fd);
                return -1;
            }
        } else {
            PLOG(ERROR) << "Failed to fallocate";
            close(fd);
            return -1;
        }
    }
    close(fd);
    return 0;
}
