Aegisub/libaegisub/windows/fs.cpp
arch1t3cht b697ad6ca0 Remove access checks in windows fs operations
These were giving false negatives on samba shares, which broke the font
collector. Windows also recommends to not use access checks in these
cases, and instead just see if the operations succeeds or not.
2022-08-17 02:54:09 +02:00

115 lines
3.5 KiB
C++

// Copyright (c) 2013, Thomas Goyne <plorkyeran@aegisub.org>
//
// 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 <boost/filesystem.hpp>
namespace bfs = boost::filesystem;
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#undef CreateDirectory
namespace agi { namespace fs {
std::string ShortName(path const& p) {
std::wstring out(MAX_PATH + 1, 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<HANDLE, BOOL (__stdcall *)(HANDLE)>
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<HANDLE, BOOL (__stdcall *)(HANDLE)> 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() { }
} }