/*
 * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

#include <memory>
#include <algorithm>
#include <shlwapi.h>
#include <stdlib.h>
#include <direct.h>

#include "FileUtils.h"
#include "WinFileUtils.h"
#include "WinErrorHandling.h"
#include "Log.h"


// Needed by FileUtils::isDirectoryNotEmpty - shlwapi


namespace FileUtils {

namespace {

tstring reservedFilenameChars() {
    tstring buf;
    for (char charCode = 0; charCode < 32; ++charCode) {
        buf.append(1, charCode);
    }
    buf += _T("<>:\"|?*/\\");
    return buf;
}

} // namespace

bool isFileExists(const tstring &filePath) {
    return GetFileAttributes(filePath.c_str()) != INVALID_FILE_ATTRIBUTES;
}

namespace {
bool isDirectoryAttrs(const DWORD attrs) {
    return attrs != INVALID_FILE_ATTRIBUTES
            && (attrs & FILE_ATTRIBUTE_DIRECTORY) != 0;
}
} // namespace

bool isDirectory(const tstring &filePath) {
    return isDirectoryAttrs(GetFileAttributes(filePath.c_str()));
}

bool isDirectoryNotEmpty(const tstring &dirPath) {
    if (!isDirectory(dirPath)) {
        return false;
    }
    return FALSE == PathIsDirectoryEmpty(dirPath.c_str());
}


tstring toAbsolutePath(const tstring& path) {
    if (path.empty()) {
        TCHAR* buf = _tgetcwd(0, 1);
        if (buf) {
            const tstring result(buf);
            free(buf);
            if (result.empty()) {
                JP_THROW(tstrings::any() << "_tgetcwd() returned empty string");
            }
            return result;
        }

        JP_THROW(tstrings::any() << "_tgetcwd() failed");
    }

    TCHAR* buf = _tfullpath(0, path.c_str(), size_t(1));
    if (buf) {
        const tstring result(buf);
        free(buf);
        return result;
    }

    JP_THROW(tstrings::any() << "_tfullpath(" << path << ") failed");
}


namespace {

bool createNewFile(const tstring& path) {
    HANDLE h = CreateFile(path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_NEW,
            FILE_ATTRIBUTE_NORMAL, NULL);
    // if the file exists => h == INVALID_HANDLE_VALUE & GetLastError
    // returns ERROR_FILE_EXISTS
    if (h != INVALID_HANDLE_VALUE) {
        CloseHandle(h);
        LOG_TRACE(tstrings::any() << "Created [" << path << "] file");
        return true;
    }
    return false;
}

} // namespace

tstring createTempFile(const tstring &prefix, const tstring &suffix,
        const tstring &path) {
    const tstring invalidChars = reservedFilenameChars();

    if (prefix.find_first_of(invalidChars) != tstring::npos) {
        JP_THROW(tstrings::any() << "Illegal characters in prefix=" << prefix);
    }

    if (suffix.find_first_of(invalidChars) != tstring::npos) {
        JP_THROW(tstrings::any() << "Illegal characters in suffix=" << suffix);
    }

    int rnd = (int)GetTickCount();

    // do no more than 100 attempts
    for (int i=0; i<100; i++) {
        const tstring filePath = mkpath() << path << (prefix
                + (tstrings::any() << (rnd + i)).tstr() + suffix);
        if (createNewFile(filePath)) {
            return filePath;
        }
    }

    // 100 attempts failed
    JP_THROW(tstrings::any() << "createTempFile("  << prefix << ", "
                                                    << suffix << ", "
                                                    << path << ") failed");
}

tstring createTempDirectory(const tstring &prefix, const tstring &suffix,
        const tstring &basedir) {
    const tstring filePath = createTempFile(prefix, suffix, basedir);
    // delete the file and create directory with the same name
    deleteFile(filePath);
    createDirectory(filePath);
    return filePath;
}

tstring createUniqueFile(const tstring &prototype) {
    if (createNewFile(prototype)) {
        return prototype;
    }

    return createTempFile(replaceSuffix(basename(prototype)),
            suffix(prototype), dirname(prototype));
}

namespace {

void createDir(const tstring path, LPSECURITY_ATTRIBUTES saAttr,
        tstring_array* createdDirs=0) {
    if (CreateDirectory(path.c_str(), saAttr)) {
        LOG_TRACE(tstrings::any() << "Created [" << path << "] directory");
        if (createdDirs) {
            createdDirs->push_back(removeTrailingSlash(path));
        }
    } else {
        const DWORD createDirectoryErr = GetLastError();
        // if saAttr is specified, fail even if the directory exists
        if (saAttr != NULL || !isDirectory(path)) {
            JP_THROW(SysError(tstrings::any() << "CreateDirectory("
                << path << ") failed", CreateDirectory, createDirectoryErr));
        }
    }
}

}

void createDirectory(const tstring &path, tstring_array* createdDirs) {
    const tstring dirPath = removeTrailingSlash(path) + _T("\\");

    tstring::size_type pos = dirPath.find_first_of(_T("\\/"));
    while (pos != tstring::npos) {
        const tstring subdirPath = dirPath.substr(0, pos + 1);
        createDir(subdirPath, NULL, createdDirs);
        pos = dirPath.find_first_of(_T("\\/"), pos + 1);
    }
}


void copyFile(const tstring& fromPath, const tstring& toPath,
        bool failIfExists) {
    createDirectory(dirname(toPath));
    if (!CopyFile(fromPath.c_str(), toPath.c_str(),
            (failIfExists ? TRUE : FALSE))) {
        JP_THROW(SysError(tstrings::any()
                << "CopyFile(" << fromPath << ", " << toPath << ", "
                << failIfExists << ") failed", CopyFile));
    }
    LOG_TRACE(tstrings::any() << "Copied [" << fromPath << "] file to ["
            << toPath << "]");
}


namespace {

void moveFileImpl(const tstring& fromPath, const tstring& toPath,
        DWORD flags) {
    const bool isDir = isDirectory(fromPath);
    if (!MoveFileEx(fromPath.c_str(), toPath.empty() ? NULL : toPath.c_str(),
            flags)) {
        JP_THROW(SysError(tstrings::any() << "MoveFileEx(" << fromPath
                << ", " << toPath << ", " << flags << ") failed", MoveFileEx));
    }

    const bool onReboot = 0 != (flags & MOVEFILE_DELAY_UNTIL_REBOOT);

    const LPCTSTR label = isDir ? _T("folder") : _T("file");

    tstrings::any msg;
    if (!toPath.empty()) {
        if (onReboot) {
            msg << "Move";
        } else {
            msg << "Moved";
        }
        msg << " '" << fromPath << "' " << label << " to '" << toPath << "'";
    } else {
        if (onReboot) {
            msg << "Delete";
        } else {
            msg << "Deleted";
        }
        msg << " '" << fromPath << "' " << label;
    }
    if (onReboot) {
        msg << " on reboot";
    }
    LOG_TRACE(msg);
}

} // namespace


void moveFile(const tstring& fromPath, const tstring& toPath,
        bool failIfExists) {
    createDirectory(dirname(toPath));

    DWORD flags = MOVEFILE_COPY_ALLOWED;
    if (!failIfExists) {
        flags |= MOVEFILE_REPLACE_EXISTING;
    }

    moveFileImpl(fromPath, toPath, flags);
}

void deleteFile(const tstring &path)
{
    if (!deleteFile(path, std::nothrow)) {
        JP_THROW(SysError(tstrings::any()
                << "DeleteFile(" << path << ") failed", DeleteFile));
    }
}

namespace {

bool notFound(const DWORD status=GetLastError()) {
    return status == ERROR_FILE_NOT_FOUND || status == ERROR_PATH_NOT_FOUND;
}

bool deleteFileImpl(const std::nothrow_t &, const tstring &path) {
    const bool deleted = (DeleteFile(path.c_str()) != 0);
    if (deleted) {
        LOG_TRACE(tstrings::any() << "Deleted [" << path << "] file");
        return true;
    }
    return notFound();
}

} // namespace

bool deleteFile(const tstring &path, const std::nothrow_t &) throw()
{
    bool deleted = deleteFileImpl(std::nothrow, path);
    const DWORD status = GetLastError();
    if (!deleted && status == ERROR_ACCESS_DENIED) {
        DWORD attrs = GetFileAttributes(path.c_str());
        SetLastError(status);
        if (attrs == INVALID_FILE_ATTRIBUTES) {
            return false;
        }
        if (attrs & FILE_ATTRIBUTE_READONLY) {
            // DeleteFile() failed because file is R/O.
            // Remove R/O attribute and retry DeleteFile().
            attrs &= ~FILE_ATTRIBUTE_READONLY;
            if (SetFileAttributes(path.c_str(), attrs)) {
                LOG_TRACE(tstrings::any() << "Discarded R/O attribute from ["
                                                        << path << "] file");
                deleted = deleteFileImpl(std::nothrow, path);
            } else {
                LOG_WARNING(SysError(tstrings::any()
                            << "Failed to discard R/O attribute from ["
                            << path << "] file. File will not be deleted",
                            SetFileAttributes).what());
                SetLastError(status);
            }
        }
    }

    return deleted || notFound();
}

void deleteDirectory(const tstring &path)
{
    if (!deleteDirectory(path, std::nothrow)) {
        JP_THROW(SysError(tstrings::any()
                << "RemoveDirectory(" << path << ") failed", RemoveDirectory));
    }
}

bool deleteDirectory(const tstring &path, const std::nothrow_t &) throw()
{
    const bool deleted = (RemoveDirectory(path.c_str()) != 0);
    if (deleted) {
        LOG_TRACE(tstrings::any() << "Deleted [" << path << "] directory");
    }
    return deleted || notFound();
}

namespace {

class DeleteFilesCallback: public DirectoryCallback {
public:
    explicit DeleteFilesCallback(bool ff): failfast(ff), failed(false) {
    }

    virtual bool onFile(const tstring& path) {
        if (failfast) {
            deleteFile(path);
        } else {
            updateStatus(deleteFile(path, std::nothrow));
        }
        return true;
    }

    bool good() const {
        return !failed;
    }

protected:
    void updateStatus(bool success) {
        if (!success) {
            failed = true;
        }
    }

    const bool failfast;
private:
    bool failed;
};

class DeleteAllCallback: public DeleteFilesCallback {
public:
    explicit DeleteAllCallback(bool failfast): DeleteFilesCallback(failfast) {
    }

    virtual bool onDirectory(const tstring& path) {
        if (failfast) {
            deleteDirectoryRecursive(path);
        } else {
            updateStatus(deleteDirectoryRecursive(path, std::nothrow));
        }
        return true;
    }
};


class BatchDeleter {
    const tstring dirPath;
    bool recursive;
public:
    explicit BatchDeleter(const tstring& path): dirPath(path) {
        deleteSubdirs(false);
    }

    BatchDeleter& deleteSubdirs(bool v) {
        recursive = v;
        return *this;
    }

    void execute() const {
        if (!isFileExists(dirPath)) {
            return;
        }
        iterateDirectory(true /* fail fast */);
        if (recursive) {
            deleteDirectory(dirPath);
        }
    }

    bool execute(const std::nothrow_t&) const {
        if (!isFileExists(dirPath)) {
            return true;
        }

        if (!isDirectory(dirPath)) {
            return false;
        }

        JP_TRY;
        if (!iterateDirectory(false /* ignore errors */)) {
            return false;
        }
        if (recursive) {
            return deleteDirectory(dirPath, std::nothrow);
        }
        return true;
        JP_CATCH_ALL;

        return false;
    }

private:
    bool iterateDirectory(bool failfast) const {
        std::unique_ptr<DeleteFilesCallback> callback;
        if (recursive) {
            callback = std::unique_ptr<DeleteFilesCallback>(
                                            new DeleteAllCallback(failfast));
        } else {
            callback = std::unique_ptr<DeleteFilesCallback>(
                                            new DeleteFilesCallback(failfast));
        }

        FileUtils::iterateDirectory(dirPath, *callback);
        return callback->good();
    }
};

} // namespace

void deleteFilesInDirectory(const tstring &dirPath) {
    BatchDeleter(dirPath).execute();
}

bool deleteFilesInDirectory(const tstring &dirPath,
                                            const std::nothrow_t &) throw() {
    return BatchDeleter(dirPath).execute(std::nothrow);
}

void deleteDirectoryRecursive(const tstring &dirPath) {
    BatchDeleter(dirPath).deleteSubdirs(true).execute();
}

bool deleteDirectoryRecursive(const tstring &dirPath,
                                            const std::nothrow_t &) throw() {
    return BatchDeleter(dirPath).deleteSubdirs(true).execute(std::nothrow);
}

namespace {

struct FindFileDeleter {
    typedef HANDLE pointer;

    void operator()(HANDLE h) {
        if (h && h != INVALID_HANDLE_VALUE) {
            FindClose(h);
        }
    }
};

typedef std::unique_ptr<HANDLE, FindFileDeleter> UniqueFindFileHandle;

}; // namesace
void iterateDirectory(const tstring &dirPath, DirectoryCallback& callback)
{
    const tstring searchString = combinePath(dirPath, _T("*"));
    WIN32_FIND_DATA findData;
    UniqueFindFileHandle h(FindFirstFile(searchString.c_str(), &findData));
    if (h.get() == INVALID_HANDLE_VALUE) {
        // GetLastError() == ERROR_FILE_NOT_FOUND is OK
        // - no files in the directory
        // ERROR_PATH_NOT_FOUND is returned
        // if the parent directory does not exist
        if (GetLastError() != ERROR_FILE_NOT_FOUND) {
            JP_THROW(SysError(tstrings::any() << "FindFirstFile("
                    << dirPath << ") failed", FindFirstFile));
        }
        return;
    }

    do {
        const tstring fname(findData.cFileName);
        const tstring filePath = combinePath(dirPath, fname);
        if (!isDirectoryAttrs(findData.dwFileAttributes)) {
            if (!callback.onFile(filePath)) {
                return;
            }
        } else if (fname != _T(".") && fname != _T("..")) {
            if (!callback.onDirectory(filePath)) {
                return;
            }
        }
    } while (FindNextFile(h.get(), &findData));

    // expect GetLastError() == ERROR_NO_MORE_FILES
    if (GetLastError() != ERROR_NO_MORE_FILES) {
        JP_THROW(SysError(tstrings::any() << "FindNextFile("
                << dirPath << ") failed", FindNextFile));
    }
}


DirectoryIterator& DirectoryIterator::findItems(tstring_array& v) {
    if (!isDirectory(root)) {
        return *this;
    }

    iterateDirectory(root, *this);
    v.insert(v.end(), items.begin(), items.end());
    items = tstring_array();
    return *this;
}

bool DirectoryIterator::onFile(const tstring& path) {
    if (theWithFiles) {
        items.push_back(path);
    }
    return true;
}

bool DirectoryIterator::onDirectory(const tstring& path) {
    if (theWithFolders) {
        items.push_back(path);
    }
    if (theRecurse) {
        DirectoryIterator(path).recurse(theRecurse)
                .withFiles(theWithFiles)
                .withFolders(theWithFolders)
                .findItems(items);
    }
    return true;
}


namespace {

struct DeleterFunctor {
    // Order of items in the following enum is important!
    // It controls order in which items of particular type will be deleted.
    // See Deleter::execute().
    enum {
        File,
        FilesInDirectory,
        RecursiveDirectory,
        EmptyDirectory
    };

    void operator () (const Deleter::Path& path) const {
        switch (path.second) {
#define DELETE_SOME(o, f)\
        case o:\
            f(path.first, std::nothrow);\
            break

        DELETE_SOME(File, deleteFile);
        DELETE_SOME(EmptyDirectory, deleteDirectory);
        DELETE_SOME(FilesInDirectory, deleteFilesInDirectory);
        DELETE_SOME(RecursiveDirectory, deleteDirectoryRecursive);

#undef DELETE_SOME
        default:
            break;
        }
    }
};

} // namespace

void Deleter::execute() {
    Paths tmp;
    tmp.swap(paths);

    // Reorder items to delete.
    std::stable_sort(tmp.begin(), tmp.end(), [] (const Paths::value_type& a,
                                                const Paths::value_type& b) {
        return a.second < b.second;
    });

    std::for_each(tmp.begin(), tmp.end(), DeleterFunctor());
}

Deleter& Deleter::appendFile(const tstring& path) {
    paths.push_back(std::make_pair(path, DeleterFunctor::File));
    return *this;
}

Deleter& Deleter::appendEmptyDirectory(const Directory& dir) {
     tstring path =  normalizePath(removeTrailingSlash(dir));
     const tstring parent = normalizePath(removeTrailingSlash(dir.parent));
     while(parent != path) {
         appendEmptyDirectory(path);
         path = dirname(path);
     }

    return *this;
}

Deleter& Deleter::appendEmptyDirectory(const tstring& path) {
    paths.push_back(std::make_pair(path, DeleterFunctor::EmptyDirectory));
    return *this;
}

Deleter& Deleter::appendAllFilesInDirectory(const tstring& path) {
    paths.push_back(std::make_pair(path, DeleterFunctor::FilesInDirectory));
    return *this;
}

Deleter& Deleter::appendRecursiveDirectory(const tstring& path) {
    paths.push_back(std::make_pair(path, DeleterFunctor::RecursiveDirectory));
    return *this;
}


FileWriter::FileWriter(const tstring& path): dstPath(path) {
    tmpFile = FileUtils::createTempFile(_T("jds"), _T(".tmp"),
            FileUtils::dirname(path));

    cleaner.appendFile(tmpFile);

    // we want to get exception on error
    tmp.exceptions(std::ifstream::failbit | std::ifstream::badbit);
    tmp.open(tmpFile, std::ios::binary | std::ios::trunc);
}

FileWriter& FileWriter::write(const void* buf, size_t bytes) {
    tmp.write(static_cast<const char*>(buf), bytes);
    return *this;
}

void FileWriter::finalize() {
    tmp.close();

    FileUtils::moveFile(tmpFile, dstPath, false);

    // cancel file deletion
    cleaner.cancel();
}

tstring stripExeSuffix(const tstring& path) {
    // for windows - there is a ".exe" suffix to remove
    // allow for ".*" (last dot beyond the last slash)
    const tstring::size_type pos = path.rfind(_T("."));
    const tstring::size_type spos = path.rfind(_T("\\/"));
    if (pos == tstring::npos || (spos > pos && spos != tstring::npos)) {
        return path;
    }
    return path.substr(0, pos);
}

tstring toShortPath(const tstring& path) {
    const DWORD len = GetShortPathName(path.c_str(), nullptr, 0);
    if (0 == len) {
        JP_THROW(SysError(tstrings::any() << "GetShortPathName("
                << path << ") failed", GetShortPathName));
    }

    std::vector<TCHAR> buf;
    buf.resize(len);
    const DWORD copied = GetShortPathName(path.c_str(), buf.data(),
                                            static_cast<DWORD>(buf.size()));
    if (copied != buf.size() - 1) {
        JP_THROW(SysError(tstrings::any() << "GetShortPathName("
                << path << ") failed", GetShortPathName));
    }

    return tstring(buf.data(), buf.size() - 1);
}

} //  namespace FileUtils
