--:Minify:--
-- chgrp: change group ownership
local name  = syscall.getTask(syscall.getpid()).name
local cloptions = { R = false, help = false }
local args = {}

for _, v in ipairs({ ... }) do
    if v:sub(1, 2) == "--" then
        local opt = v:sub(3)
        if cloptions[opt] == nil then
            print(name .. ": unrecognized option '" .. v .. "'")
            print("try '" .. name .. " --help' for more information.")
            syscall.exit(1); return
        end
        cloptions[opt] = true
    elseif v:sub(1, 1) == "-" then
        for i = 2, #v do
            local opt = v:sub(i, i)
            if cloptions[opt] == nil then
                print(name .. ": invalid option '-" .. opt .. "'")
                print("try '" .. name .. " --help' for more information.")
                syscall.exit(1); return
            end
            cloptions[opt] = true
        end
    else
        table.insert(args, v)
    end
end

if cloptions.help then
    print("Usage: " .. name .. " [OPTION]... GROUP FILE...")
    print("Change the group of each FILE to GROUP.")
    print("GROUP may be a group name or numeric ID.")
    print("")
    print("Options:")
    print("  -R          operate on files and directories recursively")
    print("  --help      display this help and exit")
    return
end

if #args < 2 then
    print(name .. ": missing operand")
    print("try '" .. name .. " --help' for more information.")
    syscall.exit(1); return
end

local groupStr = args[1]

local function resolveGid(s)
    local n = tonumber(s)
    if n then return n end
    local uid = syscall.getuidbyname and syscall.getuidbyname(s)
    if uid then
        local pwent = syscall.getpasswd(uid)
        if pwent then return pwent.gid end
    end
    print(name .. ": invalid group: '" .. s .. "'")
    syscall.exit(1)
end

local newGid = resolveGid(groupStr)

local function chgrpPath(path)
    local stat = syscall.stat(path)
    if not stat then
        print(name .. ": cannot stat '" .. path .. "': no such file or directory")
        return false
    end
    local ok, err = pcall(syscall.chown, path, stat.owner, newGid)
    if not ok then
        local msg = tostring(err)
        if msg:find("EPERM") or msg:find("EACCES") then
            msg = "operation not permitted (must be root)"
        elseif msg:find("ENOENT") then
            msg = "no such file or directory"
        end
        print(name .. ": cannot change group of '" .. path .. "': " .. msg)
        return false
    end
    return true
end

local function chgrpRecursive(path)
    if not chgrpPath(path) then return end
    if syscall.type(path) == "directory" then
        local ok, list = pcall(syscall.listdir, path)
        if ok then
            for _, entry in ipairs(list) do
                local child = path
                if child:sub(-1) ~= "/" then child = child .. "/" end
                chgrpRecursive(child .. entry)
            end
        end
    end
end

local cwd = syscall.getcwd()
local function absPath(p)
    if p:sub(1,1) ~= "/" then p = cwd .. "/" .. p end
    return p
end

local exitCode = 0
for i = 2, #args do
    local path = absPath(args[i])
    if not syscall.exists(path) then
        print(name .. ": cannot access '" .. args[i] .. "': No such file or directory")
        exitCode = 1
    elseif cloptions.R then
        chgrpRecursive(path)
    else
        if not chgrpPath(path) then exitCode = 1 end
    end
end

syscall.exit(exitCode)
