From 42b85be332ebaabdbc7f457c484aeedd361d0528 Mon Sep 17 00:00:00 2001 From: George Roman Date: Sun, 13 May 2018 13:57:31 +0300 Subject: Replace fs.chmod with fs.set_permissions --- src/luarocks/admin/cmd/add.lua | 4 +-- src/luarocks/build.lua | 14 ++++---- src/luarocks/build/builtin.lua | 2 +- src/luarocks/cmd/unpack.lua | 2 +- src/luarocks/core/cfg.lua | 3 +- src/luarocks/download.lua | 2 +- src/luarocks/fs/lua.lua | 30 +++++++++++------ src/luarocks/fs/unix.lua | 4 +-- src/luarocks/fs/unix/tools.lua | 72 +++++++++++++++++++++++++++++++++++++---- src/luarocks/fs/win32.lua | 4 --- src/luarocks/fs/win32/tools.lua | 53 ++++++++++++++++++++++++++++++ src/luarocks/pack.lua | 6 ++-- src/luarocks/repos.lua | 4 +-- src/luarocks/tools/tar.lua | 1 + src/luarocks/upload/api.lua | 3 +- 15 files changed, 161 insertions(+), 43 deletions(-) diff --git a/src/luarocks/admin/cmd/add.lua b/src/luarocks/admin/cmd/add.lua index 5cfec980..19990b3c 100644 --- a/src/luarocks/admin/cmd/add.lua +++ b/src/luarocks/admin/cmd/add.lua @@ -62,7 +62,7 @@ local function add_files_to_server(refresh, rockfiles, server, upload_server, do if fs.exists(rockfile) then util.printout("Copying file "..rockfile.." to "..local_cache.."...") local absolute = fs.absolute_name(rockfile) - fs.copy(absolute, local_cache, cfg.perm_read) + fs.copy(absolute, local_cache, "read") table.insert(files, dir.base_name(absolute)) else util.printerr("File "..rockfile.." not found") @@ -83,7 +83,7 @@ local function add_files_to_server(refresh, rockfiles, server, upload_server, do if fs.exists("index.html") then do_index = true end - + if do_index then util.printout("Updating index.html...") index.make_index(local_cache) diff --git a/src/luarocks/build.lua b/src/luarocks/build.lua index dfc54cb8..fe004fb5 100644 --- a/src/luarocks/build.lua +++ b/src/luarocks/build.lua @@ -24,7 +24,7 @@ local writer = require("luarocks.manif.writer") -- @param location string: The base directory files should be copied to. -- @param is_module_path boolean: True if string keys in files should be -- interpreted as dotted module paths. --- @param perms string: Permissions of the newly created files installed. +-- @param perms string ("read" or "exec"): Permissions of the newly created files installed. -- Directories are always created with the default permissions. -- @return boolean or (nil, string): True if succeeded or -- nil and an error message. @@ -113,7 +113,7 @@ local function install_default_docs(name, version) fs.make_dir(dest) has_dir = true end - fs.copy(file, dest, cfg.perm_read) + fs.copy(file, dest, "read") break end end @@ -229,10 +229,10 @@ function build.build_rockspec(rockspec_file, need_to_fetch, minimal_mode, deps_m end local dirs = { - lua = { name = path.lua_dir(name, version), is_module_path = true, perms = cfg.perm_read }, - lib = { name = path.lib_dir(name, version), is_module_path = true, perms = cfg.perm_exec }, - conf = { name = path.conf_dir(name, version), is_module_path = false, perms = cfg.perm_read }, - bin = { name = path.bin_dir(name, version), is_module_path = false, perms = cfg.perm_exec }, + lua = { name = path.lua_dir(name, version), is_module_path = true, perms = "read" }, + lib = { name = path.lib_dir(name, version), is_module_path = true, perms = "exec" }, + conf = { name = path.conf_dir(name, version), is_module_path = false, perms = "read" }, + bin = { name = path.bin_dir(name, version), is_module_path = false, perms = "exec" }, } for _, d in pairs(dirs) do @@ -322,7 +322,7 @@ function build.build_rockspec(rockspec_file, need_to_fetch, minimal_mode, deps_m fs.pop_dir() - fs.copy(rockspec.local_filename, path.rockspec_file(name, version), cfg.perm_read) + fs.copy(rockspec.local_filename, path.rockspec_file(name, version), "read") if need_to_fetch then fs.pop_dir() end diff --git a/src/luarocks/build/builtin.lua b/src/luarocks/build/builtin.lua index 294ff52b..68fb75ed 100644 --- a/src/luarocks/build/builtin.lua +++ b/src/luarocks/build/builtin.lua @@ -290,7 +290,7 @@ function builtin.run(rockspec) ]] end end - for _, mods in ipairs({{ tbl = lua_modules, perms = cfg.perm_read }, { tbl = lib_modules, perms = cfg.perm_exec }}) do + for _, mods in ipairs({{ tbl = lua_modules, perms = "read" }, { tbl = lib_modules, perms = "exec" }}) do for name, dest in pairs(mods.tbl) do fs.make_dir(dir.dir_name(dest)) ok, err = fs.copy(name, dest, mods.perms) diff --git a/src/luarocks/cmd/unpack.lua b/src/luarocks/cmd/unpack.lua index f4232266..3e512d5d 100644 --- a/src/luarocks/cmd/unpack.lua +++ b/src/luarocks/cmd/unpack.lua @@ -126,7 +126,7 @@ local function run_unpacker(file, namespace, force) end if kind == "src" or kind == "rockspec" then if rockspec.source.dir ~= "." then - local ok = fs.copy(rockspec.local_filename, rockspec.source.dir, cfg.perm_read) + local ok = fs.copy(rockspec.local_filename, rockspec.source.dir, "read") if not ok then return nil, "Failed copying unpacked rockspec into unpacked source directory." end diff --git a/src/luarocks/core/cfg.lua b/src/luarocks/core/cfg.lua index 3326375f..f036aa44 100644 --- a/src/luarocks/core/cfg.lua +++ b/src/luarocks/core/cfg.lua @@ -327,8 +327,6 @@ local defaults = { hooks_enabled = true, deps_mode = "one", check_certificates = false, - perm_read = "0644", - perm_exec = "0755", lua_modules_path = "/share/lua/"..cfg.lua_version, lib_modules_path = "/lib/lua/"..cfg.lua_version, @@ -388,6 +386,7 @@ local defaults = { FIND = "find", TEST = "test", CHMOD = "chmod", + ICACLS = "icacls", MKTEMP = "mktemp", ZIP = "zip", diff --git a/src/luarocks/download.lua b/src/luarocks/download.lua index 77564b52..ac401f33 100644 --- a/src/luarocks/download.lua +++ b/src/luarocks/download.lua @@ -11,7 +11,7 @@ local cfg = require("luarocks.core.cfg") local function get_file(filename) local protocol, pathname = dir.split_url(filename) if protocol == "file" then - local ok, err = fs.copy(pathname, fs.current_dir(), cfg.perm_read) + local ok, err = fs.copy(pathname, fs.current_dir(), "read") if ok then return pathname else diff --git a/src/luarocks/fs/lua.lua b/src/luarocks/fs/lua.lua index dfb6de41..69c75cec 100644 --- a/src/luarocks/fs/lua.lua +++ b/src/luarocks/fs/lua.lua @@ -241,7 +241,7 @@ function fs_lua.make_dir(directory) if not ok then return false, err end - ok, err = fs.chmod(path, cfg.perm_exec) + ok, err = fs.set_permissions(path, "exec", "user") if not ok then return false, err end @@ -278,8 +278,8 @@ end --- Copy a file. -- @param src string: Pathname of source -- @param dest string: Pathname of destination --- @param perms string or nil: Permissions for destination file, --- or nil to use the source filename permissions +-- @param perms string ("read" or "exec") or nil: Permissions for destination +-- file or nil to use the source file permissions -- @return boolean or (boolean, string): true on success, false on failure, -- plus an error message. function fs_lua.copy(src, dest, perms) @@ -290,7 +290,6 @@ function fs_lua.copy(src, dest, perms) if destmode == "directory" then dest = dir.path(dest, dir.base_name(src)) end - if not perms then perms = fs.attributes(src, "permissions") end local src_h, err = io.open(src, "rb") if not src_h then return nil, err end local dest_h, err = io.open(dest, "w+b") @@ -302,15 +301,26 @@ function fs_lua.copy(src, dest, perms) end src_h:close() dest_h:close() - fs.chmod(dest, perms) - return true + + local fullattrs + if not perms then + fullattrs = lfs.attributes(src, "permissions") + end + if fullattrs and posix_ok then + return posix.chmod(dest, fullattrs) + else + if not perms then + perms = fullattrs:match("x") and "exec" or "read" + end + return fs.set_permissions(dest, perms, "all") + end end --- Implementation function for recursive copy of directory contents. -- Assumes paths are normalized. -- @param src string: Pathname of source -- @param dest string: Pathname of destination --- @param perms string or nil: Optional permissions. +-- @param perms string ("read" or "exec") or nil: Optional permissions. -- If not given, permissions of the source are copied over to the destination. -- @return boolean or (boolean, string): true on success, false on failure local function recursive_copy(src, dest, perms) @@ -339,7 +349,7 @@ end --- Recursively copy the contents of a directory. -- @param src string: Pathname of source -- @param dest string: Pathname of destination --- @param perms string or nil: Optional permissions. +-- @param perms string ("read" or "exec") or nil: Optional permissions. -- @return boolean or (boolean, string): true on success, false on failure, -- plus an error message. function fs_lua.copy_contents(src, dest, perms) @@ -833,8 +843,8 @@ end --- Move a file. -- @param src string: Pathname of source -- @param dest string: Pathname of destination --- @param perms string or nil: Permissions for destination file, --- or nil to use the source filename permissions. +-- @param perms string ("read" or "exec") or nil: Permissions for destination +-- file or nil to use the source file permissions. -- @return boolean or (boolean, string): true on success, false on failure, -- plus an error message. function fs_lua.move(src, dest, perms) diff --git a/src/luarocks/fs/unix.lua b/src/luarocks/fs/unix.lua index c99e1566..b64a4a38 100644 --- a/src/luarocks/fs/unix.lua +++ b/src/luarocks/fs/unix.lua @@ -81,7 +81,7 @@ function unix.wrap_script(file, dest, name, version) local addctx = "local k,l,_=pcall(require,"..util.LQ("luarocks.loader")..") _=k and l.add_context("..util.LQ(name)..","..util.LQ(version)..")" wrapper:write('exec '..fs.Q(lua)..' -e '..fs.Q(ppaths)..' -e '..fs.Q(addctx)..' '..fs.Q(file)..' "$@"\n') wrapper:close() - if fs.chmod(wrapname, cfg.perm_exec) then + if fs.set_permissions(wrapname, "exec", "user") then return true else return nil, "Could not make "..wrapname.." executable." @@ -111,7 +111,7 @@ function unix.is_actual_binary(filename) end function unix.copy_binary(filename, dest) - return fs.copy(filename, dest, cfg.perm_exec) + return fs.copy(filename, dest, "exec") end --- Move a file on top of the other. diff --git a/src/luarocks/fs/unix/tools.lua b/src/luarocks/fs/unix/tools.lua index be5ba7a7..06098399 100644 --- a/src/luarocks/fs/unix/tools.lua +++ b/src/luarocks/fs/unix/tools.lua @@ -51,7 +51,8 @@ end --- Copy a file. -- @param src string: Pathname of source -- @param dest string: Pathname of destination --- @param perm string or nil: Permissions for destination file, +-- @param perm string ("read" or "exec") or nil: Permissions for destination +-- file or nil to use the source permissions -- @return boolean or (boolean, string): true on success, false on failure, -- plus an error message. function tools.copy(src, dest, perm) @@ -61,7 +62,7 @@ function tools.copy(src, dest, perm) if fs.is_dir(dest) then dest = dir.path(dest, dir.base_name(src)) end - if fs.chmod(dest, perm) then + if fs.set_permissions(dest, perm, "all") then return true else return false, "Failed setting permissions of "..dest @@ -159,12 +160,71 @@ function tools.is_file(file) return fs.execute(vars.TEST, "-f", file) end -function tools.chmod(pathname, mode) - if mode then - return fs.execute(vars.CHMOD, mode, pathname) +--- Moderate the given permissions based on the local umask +-- @param perms string: permissions to moderate +-- @return string: the moderated permissions +local function moderate_permissions(perms) + local octal_to_rwx = { + ["0"] = "---", + ["1"] = "--x", + ["2"] = "-w-", + ["3"] = "-wx", + ["4"] = "r--", + ["5"] = "r-x", + ["6"] = "rw-", + ["7"] = "rwx", + } + local rwx_to_octal = {} + for octal, rwx in pairs(octal_to_rwx) do + rwx_to_octal[rwx] = octal + end + + local fd = assert(io.popen("umask")) + local umask = assert(fd:read("*a")) + umask = umask:gsub("\n", "") + umask = umask:sub(2, 4) + + local moderated_perms = "" + for i = 1, 3 do + local p_rwx = octal_to_rwx[perms:sub(i, i)] + local u_rwx = octal_to_rwx[umask:sub(i, i)] + local new_perm = "" + for j = 1, 3 do + local p_val = p_rwx:sub(j, j) + local u_val = u_rwx:sub(j, j) + if p_val == u_val then + new_perm = new_perm .. "-" + else + new_perm = new_perm .. p_val + end + end + moderated_perms = moderated_perms .. rwx_to_octal[new_perm] + end + return moderated_perms +end + +--- Set permissions for file or directory +-- @param filename string: filename whose permissions are to be modified +-- @param mode string ("read" or "exec"): permissions to set +-- @param scope string ("user" or "all"): the user(s) to whom the permission applies +-- @return boolean or (boolean, string): true on success, false on failure, +-- plus an error message +function tools.set_permissions(filename, mode, scope) + assert(filename and mode and scope) + + local perms + if mode == "read" and scope == "user" then + perms = moderate_permissions("600") + elseif mode == "exec" and scope == "user" then + perms = moderate_permissions("700") + elseif mode == "read" and scope == "all" then + perms = moderate_permissions("644") + elseif mode == "exec" and scope == "all" then + perms = moderate_permissions("755") else - return false + return false, "Invalid permission " .. mode .. " for " .. scope end + return fs.execute(vars.CHMOD, perms, filename) end --- Unpack an archive. diff --git a/src/luarocks/fs/win32.lua b/src/luarocks/fs/win32.lua index a915deb6..c2331cad 100644 --- a/src/luarocks/fs/win32.lua +++ b/src/luarocks/fs/win32.lua @@ -187,10 +187,6 @@ function win32.copy_binary(filename, dest) return true end -function win32.chmod(filename, mode) - return true -end - function win32.attributes(filename, attrtype) if attrtype == "permissions" then return "" -- FIXME diff --git a/src/luarocks/fs/win32/tools.lua b/src/luarocks/fs/win32/tools.lua index b59d9391..d0a7d8b2 100644 --- a/src/luarocks/fs/win32/tools.lua +++ b/src/luarocks/fs/win32/tools.lua @@ -159,6 +159,59 @@ function tools.is_file(file) return fs.execute(fs.Q(vars.TEST).." -f", file) end +--- Helper function for fs.set_permissions +-- @return table: an array of all system users +local function get_system_users() + result = {} + local fd = assert(io.popen("wmic UserAccount get name")) + for user in fd:lines() do + user = user:gsub("%s+$", "") + if user ~= "" and user ~= "Name" and user ~= "Administrator" then + table.insert(result, user) + end + end + return result +end + +--- Set permissions for file or directory +-- @param filename string: filename whose permissions are to be modified +-- @param mode string ("read" or "exec"): permission to set +-- @param scope string ("user" or "all"): the user(s) to whom the permission applies +-- @return boolean or (boolean, string): true on success, false on failure, +-- plus an error message +function tools.set_permissions(filename, mode, scope) + assert(filename and mode and scope) + + local who, what + if scope == "user" then + who = os.getenv("USERNAME") + elseif scope == "all" then + who = "Everyone" + end + if mode == "read" then + what = "(RD)" + elseif mode == "exec" then + what = "(X)" + end + if not who or not what then + return false, "Invalid permission " .. mode .. " for " .. scope + end + + if scope == "user" then + for _, user in pairs(get_system_users()) do + if user ~= who then + local ok = fs.execute(fs.Q(vars.ICACLS) .. " " .. fs.Q(filename) .. " /deny " .. fs.Q(user) .. ":" .. fs.Q(what)) + if not ok then + return false, "Failed setting permission " .. mode .. " for " .. scope + end + end + end + end + + return fs.execute(fs.Q(vars.ICACLS) .. " " .. fs.Q(filename) .. " /grant " .. fs.Q(who) .. ":" .. fs.Q(what)) +end + + --- Strip the last extension of a filename. -- Example: "foo.tar.gz" becomes "foo.tar". -- If filename has no dots, returns it unchanged. diff --git a/src/luarocks/pack.lua b/src/luarocks/pack.lua index e0e94283..6423de2c 100644 --- a/src/luarocks/pack.lua +++ b/src/luarocks/pack.lua @@ -42,7 +42,7 @@ function pack.pack_source_rock(rockspec_file) if not ok then return nil, err end fs.delete(rock_file) - fs.copy(rockspec_file, source_dir, cfg.perm_read) + fs.copy(rockspec_file, source_dir, "read") if not fs.zip(rock_file, dir.base_name(rockspec_file), dir.base_name(source_file)) then return nil, "Failed packing "..rock_file end @@ -101,12 +101,12 @@ function pack.pack_installed_rock(query, tree) local is_binary = false if rock_manifest.lib then - local ok, err = copy_back_files(name, version, rock_manifest.lib, path.deploy_lib_dir(root), dir.path(temp_dir, "lib"), cfg.perm_exec) + local ok, err = copy_back_files(name, version, rock_manifest.lib, path.deploy_lib_dir(root), dir.path(temp_dir, "lib"), "exec") if not ok then return nil, "Failed copying back files: " .. err end is_binary = true end if rock_manifest.lua then - local ok, err = copy_back_files(name, version, rock_manifest.lua, path.deploy_lua_dir(root), dir.path(temp_dir, "lua"), cfg.perm_read) + local ok, err = copy_back_files(name, version, rock_manifest.lua, path.deploy_lua_dir(root), dir.path(temp_dir, "lua"), "read") if not ok then return nil, "Failed copying back files: " .. err end end diff --git a/src/luarocks/repos.lua b/src/luarocks/repos.lua index 1464db96..54610489 100644 --- a/src/luarocks/repos.lua +++ b/src/luarocks/repos.lua @@ -330,10 +330,10 @@ function repos.deploy_files(name, version, wrap_bin_scripts, deps_mode) local ok, err = deploy_file_tree("bin", path.bin_dir(name, version), install_binary, cfg.wrapper_suffix) if not ok then return nil, err end - ok, err = deploy_file_tree("lua", path.lua_dir(name, version), make_mover(cfg.perm_read)) + ok, err = deploy_file_tree("lua", path.lua_dir(name, version), make_mover("read")) if not ok then return nil, err end - ok, err = deploy_file_tree("lib", path.lib_dir(name, version), make_mover(cfg.perm_exec)) + ok, err = deploy_file_tree("lib", path.lib_dir(name, version), make_mover("exec")) if not ok then return nil, err end local writer = require("luarocks.manif.writer") diff --git a/src/luarocks/tools/tar.lua b/src/luarocks/tools/tar.lua index 0d3b3c19..9ff8d04a 100644 --- a/src/luarocks/tools/tar.lua +++ b/src/luarocks/tools/tar.lua @@ -133,6 +133,7 @@ function tar.untar(filename, destdir) file_handle:write(file_data) file_handle:close() fs.set_time(pathname, header.mtime) + -- TODO Use fs.set_permissions if fs.chmod then fs.chmod(pathname, header.mode) end diff --git a/src/luarocks/upload/api.lua b/src/luarocks/upload/api.lua index f541e896..f9244258 100644 --- a/src/luarocks/upload/api.lua +++ b/src/luarocks/upload/api.lua @@ -42,7 +42,7 @@ function Api:save_config() return nil, err end persist.save_from_table(upload_conf, self.config) - fs.chmod(upload_conf, "0600") + fs.set_permissions(upload_conf, "read", "user") end function Api:check_version() @@ -286,4 +286,3 @@ function api.new(flags) end return api - -- cgit v1.2.3-55-g6feb