瀏覽代碼

mingw: Defer the falloc warning until falloc is specified by option

Tatsuhiro Tsujikawa 9 年之前
父節點
當前提交
1126722bd3
共有 5 個文件被更改,包括 98 次插入82 次删除
  1. 19 0
      src/FallocFileAllocationIterator.cc
  2. 4 0
      src/FallocFileAllocationIterator.h
  3. 0 82
      src/Platform.cc
  4. 71 0
      src/util.cc
  5. 4 0
      src/util.h

+ 19 - 0
src/FallocFileAllocationIterator.cc

@@ -34,14 +34,33 @@
 /* copyright --> */
 #include "FallocFileAllocationIterator.h"
 #include "DlAbortEx.h"
+#include "util.h"
+#include "LogFactory.h"
 
 namespace aria2 {
 
+#ifdef __MINGW32__
+bool FallocFileAllocationIterator::gainPrivilegeAttempted_ = false;
+#endif // __MINGW32__
+
 FallocFileAllocationIterator::FallocFileAllocationIterator(BinaryStream* stream,
                                                            int64_t offset,
                                                            int64_t totalLength)
     : stream_(stream), offset_(offset), totalLength_(totalLength)
 {
+#ifdef __MINGW32__
+  // 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 (!gainPrivilegeAttempted_) {
+    if (!util::gainPrivilege(SE_MANAGE_VOLUME_NAME)) {
+      A2_LOG_WARN("--file-allocation=falloc will not work properly.");
+    }
+
+    gainPrivilegeAttempted_ = true;
+  }
+#endif // __MINGW32__
 }
 
 void FallocFileAllocationIterator::allocateChunk()

+ 4 - 0
src/FallocFileAllocationIterator.h

@@ -47,6 +47,10 @@ private:
   int64_t offset_;
   int64_t totalLength_;
 
+#ifdef __MINGW32__
+  static bool gainPrivilegeAttempted_;
+#endif // __MINGW32__
+
 public:
   FallocFileAllocationIterator(BinaryStream* stream, int64_t offset,
                                int64_t totalLength);

+ 0 - 82
src/Platform.cc

@@ -94,79 +94,6 @@ 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_) {
@@ -239,15 +166,6 @@ 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;

+ 71 - 0
src/util.cc

@@ -2121,6 +2121,77 @@ void make_fd_cloexec(int fd)
 #endif // !__MINGW32__
 }
 
+#ifdef __MINGW32__
+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;
+}
+#endif // __MINGW32__
+
 } // namespace util
 
 } // namespace aria2

+ 4 - 0
src/util.h

@@ -867,6 +867,10 @@ std::string formatLastError(int errNum);
 // CreateProcess call.
 void make_fd_cloexec(int fd);
 
+#ifdef __MINGW32__
+bool gainPrivilege(LPCTSTR privName);
+#endif // __MINGW32__
+
 } // namespace util
 
 } // namespace aria2