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 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) 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) 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) 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] 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 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