// Copyright (c) 2013, Thomas Goyne // // Permission to use, copy, modify, and distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // // Aegisub Project http://www.aegisub.org/ #include "libaegisub/fs.h" #include "libaegisub/access.h" #include "libaegisub/charset_conv_win.h" #include "libaegisub/exception.h" #include "libaegisub/scoped_ptr.h" #include "libaegisub/util.h" using agi::charset::ConvertW; using agi::charset::ConvertLocal; #include namespace bfs = boost::filesystem; #define WIN32_LEAN_AND_MEAN #include #undef CreateDirectory namespace agi { namespace fs { std::string ShortName(path const& p) { DWORD length = GetShortPathName(p.c_str(), NULL, 0); if (!length) return p.string(); std::wstring out(length, 0); DWORD len = GetShortPathName(p.c_str(), &out[0], out.size()); if (!len) return p.string(); out.resize(len); return ConvertLocal(out); } void Touch(path const& file) { CreateDirectory(file.parent_path()); SYSTEMTIME st; FILETIME ft; GetSystemTime(&st); if(!SystemTimeToFileTime(&st, &ft)) throw EnvironmentError("SystemTimeToFileTime failed with error: " + util::ErrorString(GetLastError())); scoped_holder h(CreateFile(file.c_str(), GENERIC_WRITE, 0, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr), CloseHandle); // error handling etc. if (!SetFileTime(h, nullptr, nullptr, &ft)) throw EnvironmentError("SetFileTime failed with error: " + util::ErrorString(GetLastError())); } void Copy(fs::path const& from, fs::path const& to) { CreateDirectory(to.parent_path()); if (!CopyFile(from.wstring().c_str(), to.wstring().c_str(), false)) { switch (GetLastError()) { case ERROR_FILE_NOT_FOUND: throw FileNotFound(from); case ERROR_ACCESS_DENIED: throw fs::WriteDenied("Could not overwrite " + to.string()); default: throw fs::WriteDenied("Could not copy: " + util::ErrorString(GetLastError())); } } } struct DirectoryIterator::PrivData { scoped_holder h{INVALID_HANDLE_VALUE, FindClose}; }; DirectoryIterator::DirectoryIterator() { } DirectoryIterator::DirectoryIterator(path const& p, std::string const& filter) : privdata(new PrivData) { WIN32_FIND_DATA data; privdata->h = FindFirstFileEx((p/(filter.empty() ? "*.*" : filter)).c_str(), FindExInfoBasic, &data, FindExSearchNameMatch, nullptr, 0); if (privdata->h == INVALID_HANDLE_VALUE) { privdata.reset(); return; } value = ConvertW(data.cFileName); while (value[0] == '.' && (value[1] == 0 || value[1] == '.')) ++*this; } bool DirectoryIterator::operator==(DirectoryIterator const& rhs) const { return privdata.get() == rhs.privdata.get(); } DirectoryIterator& DirectoryIterator::operator++() { WIN32_FIND_DATA data; if (FindNextFile(privdata->h, &data)) value = ConvertW(data.cFileName); else { privdata.reset(); value.clear(); } return *this; } DirectoryIterator::~DirectoryIterator() { } } }