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

#include <inttypes.h>
#include <stdint.h>
#include <sys/xattr.h>

#include <android-base/logging.h>
#include <android-base/stringprintf.h>

#include "utils.h"

using android::base::StringPrintf;

namespace android {
namespace installd {

CacheItem::CacheItem(FTSENT* p) {
    level = p->fts_level;
    directory = S_ISDIR(p->fts_statp->st_mode);
    size = p->fts_statp->st_blocks * 512;
    modified = p->fts_statp->st_mtime;

    mParent = static_cast<CacheItem*>(p->fts_parent->fts_pointer);
    if (mParent) {
        atomic = mParent->atomic;
        tombstone = mParent->tombstone;
        mName = p->fts_name;
        mName.insert(0, "/");
    } else {
        atomic = false;
        tombstone = false;
        mName = p->fts_path;
    }
}

CacheItem::~CacheItem() {
}

std::string CacheItem::toString() {
    return StringPrintf("%s size=%" PRId64 " mod=%ld", buildPath().c_str(), size, modified);
}

std::string CacheItem::buildPath() {
    std::string res = mName;
    CacheItem* parent = mParent;
    while (parent) {
        res.insert(0, parent->mName);
        parent = parent->mParent;
    }
    return res;
}

int CacheItem::purge() {
    auto path = buildPath();
    if (directory) {
        FTS *fts;
        FTSENT *p;
        char *argv[] = { (char*) path.c_str(), nullptr };
        if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) {
            PLOG(WARNING) << "Failed to fts_open " << path;
            return -1;
        }
        while ((p = fts_read(fts)) != nullptr) {
            switch (p->fts_info) {
            case FTS_D:
                if (p->fts_level == 0) {
                    p->fts_number = tombstone;
                } else {
                    p->fts_number = p->fts_parent->fts_number
                            | (getxattr(p->fts_path, kXattrCacheTombstone, nullptr, 0) >= 0);
                }
                break;
            case FTS_F:
                if (p->fts_parent->fts_number) {
                    truncate(p->fts_path, 0);
                } else {
                    unlink(p->fts_path);
                }
                break;
            case FTS_DEFAULT:
            case FTS_SL:
            case FTS_SLNONE:
                unlink(p->fts_path);
                break;
            case FTS_DP:
                rmdir(p->fts_path);
                break;
            }
        }
        return 0;
    } else {
        if (tombstone) {
            return truncate(path.c_str(), 0);
        } else {
            return unlink(path.c_str());
        }
    }
}

}  // namespace installd
}  // namespace android
