local solvitdb = {} local fs = require("filesystem") local function checkValidityAndOpen(path) local handle = assert(fs.open(path)) local data = assert(handle:read(8)) if data:sub(5, 8) == "RTFM" then local patLength = string.unpack(" 512 then chunkLength = #data end buf2 = data while true do buf1 = readHandle:read(chunkLength) writeHandle:write(buf2) if not buf1 then break end buf2 = buf1 end end local function remove(filePath, location, length) local chunkLength = 512 if length > 512 then chunkLength = length end -- The file has to get shortened, so I have no choice but to do these shenanigans local readHandle = assert(fs.open(filePath, "r")) local tmpFilePath = filePath .. ".tmp" local writeHandle = assert(fs.open(tmpFilePath, "w")) local i = 0 while true do local readAmount = chunkLength if readAmount > location - i then readAmount = location - i end if readAmount == 0 then break end local data = readHandle:read(readAmount) i = i + readAmount assert(writeHandle:write(data)) end readHandle:seek(length) while true do local data = readHandle:read(chunkLength) if not data then break end assert(writeHandle:write(data)) end readHandle:close() writeHandle:close() fs.rename(tmpFilePath, filePath) fs.remove(tmpFilePath) end function solvitdb.create(path) checkArg(1, path, "string") local handle = assert(fs.open(path, "w")) assert(handle:write("\0\0\0\0RTFM")) handle:close() end function solvitdb.set(path, name, data) checkArg(1, path, "string") checkArg(2, name, "string") checkArg(3, data, "table") local readHandle, patLength = checkValidityAndOpen(path) local pat = readPat(readHandle, patLength) local writeHandle = assert(fs.open(path, "a")) if pat[name] then handle:seek(pat[name]) local data, tmpdata = "" repeat tmpdata = readHandle:read(math.huge) oldData = oldData .. (tmpdata or "") until oldData:find("\n", 1, true) or not tmpdata readHandle:close() if not oldData:find("\n", 1, true) and not tmpdata then error("hit unexpected EOF") end oldData = oldData:match("^[^\n]+") local difference = #data - #oldData if difference == 0 then writeHandle:seek("set", pat[name] + patLength + 8) readHandle:close() writeHandle:write(data) elseif difference < 0 then elseif difference > 0 then end else writeHandle:seek("end") local newPackageLocation = writeHandle:seek() - patLength - 8 if newPackageLocation > 4294967295 then -- The above is the 32 bit unsigned integer limit error("DB too large") end local encodedString if data.type == "package" then encodedString = "P" elseif data.type == "group" then encodedString = "G" elseif data.type == "virtual-package" then encodedString = "V" end if data.dependencies then encodedString = encodedString .. "d" .. table.concat(data.dependencies, ";") .. "." end if data.reverseDependencies then encodedString = encodedString .. "D" .. table.concat(data.reverseDependencies, ";") .. "." end if data.conflicts then encodedString = encodedString .. "c" .. table.concat(data.conflicts, ";") .. "." end if data.packages then encodedString = encodedString .. "p" .. table.concat(data.packages, ";") .. "." end writeHandle:write(encodedString .. "\n") writeHandle:seek("set", patLength + 8) -- + 8 because that's the length of the header local patData = ("%s.%s;"):format(name, string.pack(" 4294967295 then error("PAT too large") end writeHandle:write(string.pack("