summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Sébastien Pédron <jean-sebastien@rabbitmq.com>2019-09-02 16:04:07 +0200
committerJean-Sébastien Pédron <jean-sebastien@rabbitmq.com>2019-09-02 16:06:25 +0200
commite1719f48b651dbb942c30d9a179ba476d71775c5 (patch)
tree1930930d7ef23c7d3778b768d786f3383f5b9574
parentcd114c44d8f0d2fdc72bb74bb0ff4fe1a1e8ddd1 (diff)
downloadrabbitmq-server-git-e1719f48b651dbb942c30d9a179ba476d71775c5.tar.gz
rabbit_disk_monitor: Tell Win32 API to not enforce path limits to dir's argument
On Windows, the Win32 API enforces a limit of 260 characters (MAX_PATH). If we call `dir` with a path longer than that, it fails with "File not found". Starting with Windows 10 version 1607, this limit was removed, but the administrator has to configure that. NTFS supports paths up to 32767 characters. Therefore, paths longer than 260 characters exist but they are "inaccessible" to `dir`. A workaround is to tell the Win32 API to not parse a path and just pass it raw to the underlying filesystem. To do this, the path must be prepended with "\\?\". That's what we do here. However, the underlying filesystem may not support forward slashes transparently, as the Win32 API does. Therefore, we convert all forward slashes to backslashes. See the following page to learn more about this: https://ss64.com/nt/syntax-filenames.html This was discovered while working on the common_test testsuites on Windows: we store RabbitMQ data files under common_test's `log_private` directory and we can quickly reach the 260-character limit.
-rw-r--r--src/rabbit_disk_monitor.erl23
1 files changed, 22 insertions, 1 deletions
diff --git a/src/rabbit_disk_monitor.erl b/src/rabbit_disk_monitor.erl
index 96e90ff53e..4bc6ba09d0 100644
--- a/src/rabbit_disk_monitor.erl
+++ b/src/rabbit_disk_monitor.erl
@@ -240,7 +240,28 @@ get_disk_free(Dir, {unix, _}) ->
Df = os:find_executable("df"),
parse_free_unix(rabbit_misc:os_cmd(Df ++ " -kP " ++ Dir));
get_disk_free(Dir, {win32, _}) ->
- parse_free_win32(rabbit_misc:os_cmd("dir /-C /W \"" ++ Dir ++ "\"")).
+ %% On Windows, the Win32 API enforces a limit of 260 characters
+ %% (MAX_PATH). If we call `dir` with a path longer than that, it
+ %% fails with "File not found". Starting with Windows 10 version
+ %% 1607, this limit was removed, but the administrator has to
+ %% configure that.
+ %%
+ %% NTFS supports paths up to 32767 characters. Therefore, paths
+ %% longer than 260 characters exist but they are "inaccessible" to
+ %% `dir`.
+ %%
+ %% A workaround is to tell the Win32 API to not parse a path and
+ %% just pass it raw to the underlying filesystem. To do this, the
+ %% path must be prepended with "\\?\". That's what we do here.
+ %%
+ %% However, the underlying filesystem may not support forward
+ %% slashes transparently, as the Win32 API does. Therefore, we
+ %% convert all forward slashes to backslashes.
+ %%
+ %% See the following page to learn more about this:
+ %% https://ss64.com/nt/syntax-filenames.html
+ RawDir = "\\\\?\\" ++ string:replace(Dir, "/", "\\", all),
+ parse_free_win32(rabbit_misc:os_cmd("dir /-C /W \"" ++ RawDir ++ "\"")).
parse_free_unix(Str) ->
case string:tokens(Str, "\n") of