From bf12327a64400884b2be50c88cc8b223db57260c Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Sat, 5 Dec 2015 15:07:21 -0200 Subject: Improve writability checks. LuaRocks does `mkdir -p` (or equivalent), so we can check for the entire chain of parents for a writable directory. Closes #449. --- src/luarocks/fs/lua.lua | 17 +++++++++++++---- src/luarocks/fs/unix.lua | 8 ++++++++ src/luarocks/fs/win32.lua | 18 ++++++++++++------ 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/src/luarocks/fs/lua.lua b/src/luarocks/fs/lua.lua index 18e6b01a..a444f014 100644 --- a/src/luarocks/fs/lua.lua +++ b/src/luarocks/fs/lua.lua @@ -833,10 +833,19 @@ function fs_lua.check_command_permissions(flags) break end end - local root_parent = dir.dir_name(root_dir) - if ok and not fs.exists(root_dir) and not fs.is_writable(root_parent) then - ok = false - err = root_dir.." does not exist and your user does not have write permissions in " .. root_parent + if ok and not fs.exists(root_dir) then + local root = fs.root_of(root_dir) + local parent = root_dir + repeat + parent = dir.dir_name(parent) + if parent == "" then + parent = root + end + until parent == root or fs.exists(parent) + if not fs.is_writable(parent) then + ok = false + err = root_dir.." does not exist and your user does not have write permissions in " .. parent + end end if ok then return true diff --git a/src/luarocks/fs/unix.lua b/src/luarocks/fs/unix.lua index 6ad5a678..8eb3386a 100644 --- a/src/luarocks/fs/unix.lua +++ b/src/luarocks/fs/unix.lua @@ -36,6 +36,14 @@ function unix.absolute_name(pathname, relative_to) end end +--- Return the root directory for the given path. +-- In Unix, root is always "/". +-- @param pathname string: pathname to use. +-- @return string: The root of the given pathname. +function unix.root_of(_) + return "/" +end + --- Create a wrapper to make a script executable from the command-line. -- @param file string: Pathname of script to be made executable. -- @param dest string: Directory where to put the wrapper. diff --git a/src/luarocks/fs/win32.lua b/src/luarocks/fs/win32.lua index 32766e53..0c8cc9e9 100644 --- a/src/luarocks/fs/win32.lua +++ b/src/luarocks/fs/win32.lua @@ -18,7 +18,6 @@ local _popen, _execute = io.popen, os.execute io.popen = function(cmd, ...) return _popen(_prefix..cmd, ...) end os.execute = function(cmd, ...) return _execute(_prefix..cmd, ...) end - --- Annotate command string for quiet execution. -- @param cmd string: A command-line string. -- @return string: The command-line, with silencing annotation. @@ -26,6 +25,7 @@ function win32.quiet(cmd) return cmd.." 2> NUL 1> NUL" end +local drive_letter = "[%.a-zA-Z]?:?[\\/]" local win_escape_chars = { ["%"] = "%%", @@ -47,7 +47,7 @@ end function win32.Q(arg) assert(type(arg) == "string") -- Quote DIR for Windows - if arg:match("^[%.a-zA-Z]?:?[\\/]") then + if arg:match("^"..drive_letter) then arg = arg:gsub("/", "\\") end if arg == "\\" then @@ -68,7 +68,7 @@ end function win32.Qb(arg) assert(type(arg) == "string") -- Quote DIR for Windows - if arg:match("^[%.a-zA-Z]?:?[\\/]") then + if arg:match("^"..drive_letter) then arg = arg:gsub("/", "\\") end if arg == "\\" then @@ -92,15 +92,21 @@ function win32.absolute_name(pathname, relative_to) assert(type(relative_to) == "string" or not relative_to) relative_to = relative_to or fs.current_dir() - -- FIXME I'm not sure this first \\ should be there at all. - -- What are the Windows rules for drive letters? - if pathname:match("^[\\.a-zA-Z]?:?[\\/]") then + if pathname:match("^"..drive_letter) then return pathname else return relative_to .. "/" .. pathname end end +--- Return the root directory for the given path. +-- For example, for "c:\hello", returns "c:\" +-- @param pathname string: pathname to use. +-- @return string: The root of the given pathname. +function win32.root_of(pathname) + return (fs.absolute_name(pathname):match("^("..drive_letter..")")) +end + --- Create a wrapper to make a script executable from the command-line. -- @param file string: Pathname of script to be made executable. -- @param dest string: Directory where to put the wrapper. -- cgit v1.2.3-55-g6feb