philote/src/stat.lua
Piotr Śliwka 29229d0641 Use json args inlining instead of WANT_JSON
This improves performance by limiting amount of `scp` calls needed to
run each task.
2019-07-27 11:57:17 +02:00

130 lines
3.4 KiB
Lua

#!/usr/bin/lua
local Ansible = require("ansible")
local File = require("fileutils")
local stat = require("posix.sys.stat")
local errno = require("posix.errno")
local bm = require("BinDecHex")
local stdlib = require("posix.stdlib")
local unistd = require("posix.unistd")
local pwd = require("posix.pwd")
local grp = require("posix.grp")
local function tohex(int)
return bm.Dec2Hex(string.format("%d", int))
end
local function S_IMODE(mode)
-- man 2 stat
-- "... and the least significant 9 bits (0777) as the file permission bits"
return tonumber(bm.Hex2Dec(bm.BMAnd(tohex(mode), tohex(0x1ff))))
end
local function boolmask(mode, mask)
local masked = tonumber(bm.Hex2Dec(bm.BMAnd(tohex(mode), tohex(mask))))
if 0 == masked then
return false
else
return true
end
end
function main(arg)
local module = Ansible.new(
{ path = { required=true, type='path' }
, follow = { default=false, type='bool' }
, get_md5 = { default=true, type='bool'}
, get_checksum = { default=true, type='bool' }
, checksum_algorithm = { default='sha1', type='str', choices={'sha1'}, aliases={'checksum_algo', 'checksum'}}
}
)
module:parse(arg[1])
local p = module:get_params()
local path = p['path']
local follow = p['follow']
local get_md5 = p['get_md5']
local get_checksum = p['get_checksum']
local checksum_algorithm = p['checksum_algorithm']
local st, err, rc
if follow then
st, err, rc = stat.stat(path)
else
st, err, rc = stat.lstat(path)
end
if not st then
if rc == errno.ENOENT then
d = { exists=false }
module:exit_json({msg="No such file exists", changed=false, stat=d})
end
module:fail_json({msg=err})
end
mode = st['st_mode']
-- back to ansible
d = {
exists = true
, path = path
, mode = string.format("%04o", S_IMODE(mode))
, isdir = stat.S_ISDIR(mode)
, ischr = stat.S_ISCHR(mode)
, isblk = stat.S_ISBLK(mode)
, isreg = stat.S_ISREG(mode)
, isfifo = stat.S_ISFIFO(mode)
, islnk = stat.S_ISLNK(mode)
, issock = stat.S_ISSOCK(mode)
, uid = st['st_uid']
, gid = st['st_gid']
, size = st['st_size']
, inode = st['st_ino']
, dev = st['st_dev']
, nlink = st['st_nlink']
, atime = st['st_atime']
, mtime = st['st_mtime']
, ctime = st['ctime']
, wusr = boolmask(mode, stat.S_IWUSR)
, rusr = boolmask(mode, stat.S_IRUSR)
, xusr = boolmask(mode, stat.S_IXUSR)
, wgrp = boolmask(mode, stat.S_IWGRP)
, rgrp = boolmask(mode, stat.S_IRGRP)
, xgrp = boolmask(mode, stat.S_IXGRP)
, woth = boolmask(mode, stat.S_IWOTH)
, roth = boolmask(mode, stat.S_IROTH)
, xoth = boolmask(mode, stat.S_IXOTH)
, isuid = boolmask(mode, stat.S_ISUID)
, isgid = boolmask(mode, stat.S_ISGID)
}
if 0 ~= d['islnk'] then
d['lnk_source'] = stdlib.realpath(path)
end
if 0 ~= d['isreg'] and get_md5 and 0 == unistd.access(path, "r") then
d['md5'] = File.md5(module, path)
end
if 0 ~= d['isreg'] and get_checksum and 0 == unistd.access(path, "r") then
local chksums = { sha1=File.sha1 }
d['checksum'] = chksums[p['checksum_algorithm']](module, path)
end
local pw = pwd.getpwuid(st['st_uid'])
d['pw_name'] = pw['pw_name']
local grp_info = grp.getgrgid(st['st_gid'])
d['gr_name'] = grp_info['gr_name']
d['mime_type'] = 'unknown'
d['charset'] = 'unknown'
module:exit_json({msg="Stat successful", changed=false, stat=d})
end
main(arg)