Commit 3c12e3ca authored by Michal 'vorner' Vaner's avatar Michal 'vorner' Vaner

backend: Install dead symbolic links

If there's a dead symbolic link in between the files to be installed
(because the target has already been installed), then we want to use
lstat to determine the existence of the link, instead of stat (which
would say it doesn't exist). That way the symbolic link is installed as
well.
parent 67c0c60d
......@@ -667,7 +667,7 @@ function pkg_merge_files(dir, dirs, files, configs)
Now move all the files in place.
]]
for f in pairs(files) do
if stat(dir .. f) == nil then
if stat(dir .. f, true) == nil then
DBG("File " .. f .. " already installed")
else
DBG("Installing file " .. f)
......@@ -761,7 +761,7 @@ function pkg_cleanup_files(files, rm_configs)
local ok, err = pcall(function () os.remove(path) end)
-- If it failed because the file didn't exist, that's OK. Mostly.
if not ok then
local tp = stat(path)
local tp = stat(path, true)
if tp then
error(err)
else
......
......@@ -590,7 +590,12 @@ static const char *perm2str(struct stat *buf) {
static int lua_stat(lua_State *L) {
const char *fname = luaL_checkstring(L, 1);
struct stat buf;
int result = stat(fname, &buf);
int result;
if (lua_toboolean(L, 2))
// Use lstat instead of stat. Non-existent parameter is OK with lua_toboolean (and returns false)
result = lstat(fname, &buf);
else
result = stat(fname, &buf);
if (result == -1) {
if (errno == ENOENT)
// No result, because the file does not exist
......
......@@ -131,11 +131,14 @@ ls(directory)::
s;; A unix-domain socket
?;; Failed to determine the type
stat(path)::
stat(path, [lstat])::
Statistics about the given file. If the file does not exist, it
returns nothing. Otherwise, the file type is returned (see the types
of `ls`). The second result is the permissions of the file, in the
imitation of shell's `ls -l`, like `rwxr-x---`.
imitation of shell's `ls -l`, like `rwxr-x---`. If the second
parameter is set to true value, the `lstat` behaviour is preferred
(eg. provides info about symbolic link if it is a link, instead of
the target).
sync()::
Writes everything to a permanent storage (equivalent to the shell's
......
......@@ -46,9 +46,20 @@ function test_fsutils()
assert_table_equal({["d1"] = "d"}, ls(dir))
-- Exists and is a directory
events_wait(run_command(function () end, nil, nil, -1, -1, "/bin/chmod", "0750", dir .. "/d1"))
events_wait(run_command(function () end, nil, nil, -1, -1, "/bin/ln", "-s", dir .. "/d1", dir .. "/s1"))
local stat_type, stat_perm = stat(dir .. "/d1")
assert_equal("d", stat_type)
assert_equal("rwxr-x---", stat_perm)
stat_type, stat_perm = stat(dir .. "/s1")
assert_equal("d", stat_type)
assert_equal("rwxr-x---", stat_perm)
-- Check the symbolic link stat version
stat_type, stat_perm = stat(dir .. "/s1", true)
assert_equal("l", stat_type)
assert_equal("rwxrwxrwx", stat_perm)
stat_type, stat_perm = stat(dir .. "/d1", true)
assert_equal("d", stat_type)
assert_equal("rwxr-x---", stat_perm)
-- Doesn't exist
assert_table_equal({}, {stat(dir .. "/d2")})
-- Parent directory doesn't exist
......@@ -56,7 +67,11 @@ function test_fsutils()
-- Already exists
assert_error(function () mkdir(dir .. "/d1") end)
move(dir .. "/d1", dir .. "/d2")
assert_table_equal({["d2"] = "d"}, ls(dir))
assert_table_equal({["d2"] = "d", ["s1"] = "l"}, ls(dir))
-- It is a dead symlink, but that's OK
stat_type, stat_perm = stat(dir .. "/s1", true)
assert_equal("l", stat_type)
assert_equal("rwxrwxrwx", stat_perm)
-- Create a file
local f = io.open(dir .. "/d2/x", "w")
assert(f)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment