PsychOSPackages/diskpart/lib/diskpart.lua

148 lines
3.7 KiB
Lua
Raw Normal View History

local partition = {}
local eformat = "c20c4>I4>I4"
function partition.parse(s)
local rt = {}
for i = 1, s:len(), 32 do
local n, t, start, length = string.unpack(eformat, s, i)
n = n:gsub("\0", "")
if n ~= "" then
rt[#rt+1] = {n,t,start,length}
end
end
return rt
end
function partition.generate(pt)
local ps = ""
for k,v in ipairs(pt) do
ps = ps .. string.pack(eformat, table.unpack(v))
end
return ps
end
local function getProxy(addr)
if type(addr) == "string" then
return component.proxy(component.get(addr))
end
return addr
end
2023-08-04 20:34:16 +10:00
local function aop(td,n,mn,...)
local rv
if td.getPosition then
local rts = td.getPosition()
if rts ~= n then
td.seek(n - rts)
end
rv = {td[mn](...)}
-- td.seek(rts - n)
else
local rts = td.seek(-math.huge)
td.seek(n)
rv = {td[mn](...)}
td.seek(-math.huge)
td.seek(rts)
end
return table.unpack(rv)
end
function partition.getPartitions(drive)
drive = getProxy(drive)
2023-08-04 20:34:16 +10:00
local rv
if drive.type == "tape_drive" then
td = getProxy(td)
local ts = drive.getSize()
local lso = (math.floor(ts / 512) - 1) * 512
rv = partition.parse(aop(drive, lso, "read", ts - lso))
else
rv = partition.parse(drive.readSector(drive.getCapacity() / drive.getSectorSize()))
end
return #rv > 0 and rv[1][2] == "mtpt" and rv or {}
end
function partition.setPartitions(drive, pt, name)
drive = getProxy(drive)
2023-08-04 20:34:16 +10:00
if pt[1][2] ~= "mtpt" then table.insert(pt, 1, {name or drive.address:sub(1,8), "mtpt", 0, 0}) end
local ns = partition.generate(pt)
2023-08-04 20:34:16 +10:00
if drive.type == "tape_drive" then
local ts = drive.getSize()
local lso = (math.floor(ts / 512) - 1) * 512
return aop(drive, lso, "write", partition.generate(pt) .. ("\0"):rep(ts - lso))
end
return drive.writeSector(drive.getCapacity() / drive.getSectorSize(), ns .. ("\0"):rep(drive.getSectorSize() - #ns))
end
function partition.proxyPartition(drive, index)
drive = getProxy(drive)
local part = partition.getPartitions(drive)[index]
2023-08-04 20:34:16 +10:00
local proxy = {label=part[1],ptype=part[2],address=drive.address.."/"..tostring(index),type="partition"}
function proxy.getLabel()
return part[1]
end
function proxy.setLabel()
return false
end
2023-08-04 20:34:16 +10:00
if drive.type == "tape_drive" then
local start, len, bs= part[3]-1, part[4], 512
local proxy = {}
local function checkBounds(n)
if n < 0 or n > len * bs then
error("out of bounds")
end
return (start * bs) + n
end
function proxy.readSector(n)
return aop(drive, checkBounds((n-1) * bs), "read", bs)
end
function proxy.writeSector(n,d)
return aop(drive, checkBounds((n-1) * bs), "write", d .. ("\0"):rep(512-#d))
end
function proxy.readByte(n)
return aop(drive, checkBounds(n-1), "read")
end
function proxy.writeByte(n,d)
return aop(drive, checkBounds(n-1), "write",d)
end
function proxy.getSectorSize()
return bs
end
function proxy.getCapacity()
return len * 512
end
return proxy
end
local sectorOffset, byteOffset = part[3] - 1, (part[3]-1) * drive.getSectorSize()
function proxy.getCapacity()
return drive.getSectorSize() * part[4]
end
local function offsetSector(sector)
if sector < 1 or sector > part[4] then error("invalid offset, not in a usable sector") end
return sectorOffset + sector
end
function proxy.readSector(sector)
return drive.readSector(offsetSector(sector))
end
function proxy.writeSector(sector, data)
return drive.writeSector(offsetSector(sector), data)
end
local function offsetByte(byte)
if byte < 1 or byte > part[4]*drive.getSectorSize() then return 0 end
return byteOffset + byte
end
function proxy.readByte(byte)
return drive.readByte(offsetByte(byte))
end
function proxy.writeByte(byte, data)
return drive.writeByte(offsetByte(byte), data)
end
for k,v in pairs(drive) do
proxy[k] = proxy[k] or v
end
return proxy
end
return partition