module (..., package.seeall) require("posix") require("modelfunctions") require("format") require("fs") require("validator") local configfile = "/etc/crontabs/root" local processname = "cron" local packagename = "busybox" local baseurl = "/etc/periodic/" local periods -- ################################################################################ -- LOCAL FUNCTIONS local function list_periods() if not periods then periods = {} local file = fs.read_file(configfile) or "" for dir in string.gmatch(file, baseurl.."(%S+)") do periods[#periods+1] = dir end --[[ local reverseperiods = {} for i,per in ipairs(periods) do reverseperiods[per] = i end if fs.is_dir(baseurl) then for dir in posix.files(baseurl) do if fs.is_dir(baseurl .. dir) and (dir ~= ".") and (dir ~= "..") and not reverseperiods[dir] then periods[#periods+1] = dir end end end--]] end return periods end local function list_jobs() local jobs = {} local alljobs = {} for i,period in ipairs(list_periods()) do local temp = {period=period, jobs={}} for file in fs.find("[^.]+", baseurl..period) do table.insert(temp.jobs, file) table.insert(alljobs, file) end table.sort(temp.jobs) jobs[#jobs+1] = temp end table.sort(alljobs) return jobs, alljobs end local function validate_filename(name) local success = false for i,per in ipairs(list_periods()) do if validator.is_valid_filename(name, baseurl..per) then success = true break end end return success end -- ################################################################################ -- PUBLIC FUNCTIONS function startstop_service(action) return modelfunctions.startstop_service(processname, action) end function getstatus() return modelfunctions.getstatus(processname, packagename, "Cron Status") end function listjobs() return cfe({ type="structure", value=list_jobs(), label="Cron Jobs" }) end function read_job(filename) return modelfunctions.getfiledetails(filename, validate_filename) end function update_job(filedetails) return modelfunctions.setfiledetails(filedetails, validate_filename) end function delete_job(filename) local retval = cfe({ label="Delete Job Result", errtxt="Invalid file" }) if validate_filename(filename) then os.remove(filename) retval.value = "Job File Deleted" retval.errtxt = nil end return retval end function get_move_job() local move = {} move.name = cfe({ type="select", label="Name", option=select(2, list_jobs()) }) move.period = cfe({ type="select", label="Period", option=list_periods() }) move.name.value = move.name.option[1] or "" move.period.value = move.period.option[1] or "" return cfe({ type="group", value=move, label="Move Job" }) end function move_job(move) local success = modelfunctions.validateselect(move.value.name) success = modelfunctions.validateselect(move.value.period) and success if success then local newpath = baseurl .. move.value.period.value .. "/" .. posix.basename(move.value.name.value) fs.move_file(move.value.name.value, newpath) move.value.name.option = select(2, list_jobs()) move.value.name.value = newpath else move.errtxt = "Failed to move job" end return move end function create_new_job() local newjob = {} newjob.name = cfe({ label="Name" }) newjob.period = cfe({ type="select", label="Period", option=list_periods() }) newjob.period.value = newjob.period.option[1] or "" return cfe({ type="group", value=newjob, label="Create New Job" }) end function create_job(newjob) local success = modelfunctions.validateselect(newjob.value.period) if newjob.value.name.value == "" then newjob.value.name.errtxt = "Missing File Name" success = false elseif string.find(newjob.value.name.value, "[^%w_-]") then newjob.value.name.errtxt = "Invalid File Name" success = false elseif posix.stat(baseurl..newjob.value.period.value.."/"..newjob.value.name.value) then newjob.value.name.errtxt = "File already exists" success = false end if success then fs.create_file(baseurl..newjob.value.period.value.."/"..newjob.value.name.value) posix.chmod(baseurl..newjob.value.period.value.."/"..newjob.value.name.value, "rwxr-xr-x") else newjob.errtxt = "Failed to create new job" end return newjob end function read_configfile() -- FIXME validate return modelfunctions.getfiledetails(configfile) end function update_configfile(filedetails) -- FIXME validate return modelfunctions.setfiledetails(filedetails, {configfile}) end