mirror of https://github.com/aria2/aria2
mingw: Use SetFileValidData to make --file-allocation=falloc work
parent
25243da039
commit
fc95a91eb6
|
@ -29,6 +29,12 @@ This build has the following difference from the original release:
|
|||
Known Issues
|
||||
------------
|
||||
|
||||
* --file-allocation=falloc uses SetFileValidData function to allocate
|
||||
disk space without filling zero. But it has security
|
||||
implications. Refer to
|
||||
https://msdn.microsoft.com/en-us/library/windows/desktop/aa365544%28v=vs.85%29.aspx
|
||||
for more details.
|
||||
|
||||
* When Ctrl-C is pressed, aria2 shows "Shutdown sequence
|
||||
commencing... Press Ctrl-C again for emergency shutdown." But
|
||||
mingw32 build cannot handle second Ctrl-C properly. The second
|
||||
|
|
|
@ -494,6 +494,15 @@ void AbstractDiskWriter::allocate(int64_t offset, int64_t length, bool sparse)
|
|||
#ifdef HAVE_SOME_FALLOCATE
|
||||
#ifdef __MINGW32__
|
||||
truncate(offset + length);
|
||||
if (!SetFileValidData(fd_, offset + length)) {
|
||||
auto errNum = fileError();
|
||||
A2_LOG_WARN(fmt(
|
||||
"File allocation (SetFileValidData) failed (cause: %s). File will be "
|
||||
"allocated by filling zero, which blocks whole aria2 execution. Run "
|
||||
"aria2 as an administrator or use a different file allocation method "
|
||||
"(see --file-allocation).",
|
||||
fileStrerror(errNum).c_str()));
|
||||
}
|
||||
#elif defined(__APPLE__) && defined(__MACH__)
|
||||
auto toalloc = offset + length - size();
|
||||
while (toalloc > 0) {
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
#include "a2gmp.h"
|
||||
#endif // HAVE_LIBGMP
|
||||
#include "LogFactory.h"
|
||||
#include "util.h"
|
||||
|
||||
namespace aria2 {
|
||||
|
||||
|
@ -93,6 +94,79 @@ Platform::Platform() { setUp(); }
|
|||
|
||||
Platform::~Platform() { tearDown(); }
|
||||
|
||||
#ifdef __MINGW32__
|
||||
namespace {
|
||||
bool gainPrivilege(LPCTSTR privName)
|
||||
{
|
||||
LUID luid;
|
||||
TOKEN_PRIVILEGES tp;
|
||||
|
||||
if (!LookupPrivilegeValue(nullptr, privName, &luid)) {
|
||||
auto errNum = GetLastError();
|
||||
A2_LOG_WARN(fmt("Lookup for privilege name %s failed. cause: %s", privName,
|
||||
util::formatLastError(errNum).c_str()));
|
||||
return false;
|
||||
}
|
||||
|
||||
tp.PrivilegeCount = 1;
|
||||
tp.Privileges[0].Luid = luid;
|
||||
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||
|
||||
HANDLE token;
|
||||
if (!OpenProcessToken(GetCurrentProcess(),
|
||||
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) {
|
||||
auto errNum = GetLastError();
|
||||
A2_LOG_WARN(fmt("Getting process token failed. cause: %s",
|
||||
util::formatLastError(errNum).c_str()));
|
||||
return false;
|
||||
}
|
||||
|
||||
auto tokenCloser = defer(token, CloseHandle);
|
||||
|
||||
if (!AdjustTokenPrivileges(token, FALSE, &tp, 0, NULL, NULL)) {
|
||||
auto errNum = GetLastError();
|
||||
A2_LOG_WARN(fmt("Gaining privilege %s failed. cause: %s", privName,
|
||||
util::formatLastError(errNum).c_str()));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check privilege was really gained
|
||||
DWORD bufsize = 0;
|
||||
GetTokenInformation(token, TokenPrivileges, nullptr, 0, &bufsize);
|
||||
if (bufsize == 0) {
|
||||
A2_LOG_WARN("Checking privilege failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto buf = make_unique<char[]>(bufsize);
|
||||
if (!GetTokenInformation(token, TokenPrivileges, buf.get(), bufsize,
|
||||
&bufsize)) {
|
||||
auto errNum = GetLastError();
|
||||
A2_LOG_WARN(fmt("Checking privilege failed. cause: %s",
|
||||
util::formatLastError(errNum).c_str()));
|
||||
return false;
|
||||
}
|
||||
|
||||
auto privs = reinterpret_cast<TOKEN_PRIVILEGES*>(buf.get());
|
||||
for (size_t i = 0; i < privs->PrivilegeCount; ++i) {
|
||||
auto& priv = privs->Privileges[i];
|
||||
if (memcmp(&priv.Luid, &luid, sizeof(luid)) != 0) {
|
||||
continue;
|
||||
}
|
||||
if (priv.Attributes == SE_PRIVILEGE_ENABLED) {
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
A2_LOG_WARN(fmt("Gaining privilege %s failed.", privName));
|
||||
|
||||
return false;
|
||||
}
|
||||
} // namespace
|
||||
#endif // __MINGW32__
|
||||
|
||||
bool Platform::setUp()
|
||||
{
|
||||
if (initialized_) {
|
||||
|
@ -165,6 +239,15 @@ bool Platform::setUp()
|
|||
(void)_setmode(_fileno(stdin), _O_BINARY);
|
||||
(void)_setmode(_fileno(stdout), _O_BINARY);
|
||||
(void)_setmode(_fileno(stderr), _O_BINARY);
|
||||
|
||||
// Windows build: --file-allocation=falloc uses SetFileValidData
|
||||
// which requires SE_MANAGE_VOLUME_NAME privilege. SetFileValidData
|
||||
// has security implications (see
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365544%28v=vs.85%29.aspx).
|
||||
if (!gainPrivilege(SE_MANAGE_VOLUME_NAME)) {
|
||||
A2_LOG_WARN("--file-allocation=falloc will not work properly.");
|
||||
}
|
||||
|
||||
#endif // __MINGW32__
|
||||
|
||||
return true;
|
||||
|
|
Loading…
Reference in New Issue