Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- 1 minute - 240 KiB - 480 blocks
- block pinters - 2 byte - 65536 blocks max
- Bytes in block starts from 1
- root block:
- 1-3 string: 3 bytes \236\32\45 (yes, it's a just 3 random bytes)
- 4 block size multiplier (m): default 1 (1 byte)
- 5-36 partiton component id (32 bytes)
- 38-68 partiotion name (32 bytes)
- 69-(m*512-2) list of dir/file headers (which have parent 0)
- (m*512-2)-(m*512) pointer to next block (type 3) or end block if this is end of list (2 bytes)
- file/dir block:
- 1-2 block type
- 3-4 parent block id: 2 bytes (if type is 3 or 4, points to header block, else points to parent dir header (if in root directory, then 0))
- 5-68 file/dir name: 64 bytes (header only)
- 69-70 size in blocks, type 5 only
- 69-(m*512-2) content of file or list of child dirs (2 bytes per entry)
- (m*512-1)-(m*512) pointer to next block or 0 if this is end of list/content (2 bytes)
- types
- 0: empty
- 1: dir header
- 2: dir childs
- 3: file header
- 4: file content
- 5: audio file -- somewhen
- 65535: partition end
- ]]--
- local component = component or require("component")
- local function nt2(n) --number to symbols (2 byte)
- return string.char(bit32.rshift(bit32.band(n,0xFF00),8), bit32.band(n,0xFF))
- end
- local function nt1(n) --number to symbol
- return string.char(bit32.band(n,0xFF))
- end
- local function nf2(s) --symbols to number (2 byte)
- local b1, b2 = string.byte(s,1,2)
- return bit32.bor(bit32.lshift(b1,8), b2)
- end
- local function nf1(s) --symbol to number
- return string.byte(s)
- end
- -------varuables-------
- local ufs = {}
- ufs.cache = {} --[block] fields: name:string, type:number, parent:number, next:number
- ufs.blocks = {} --blocks info
- --ufs.dirs = {} --dirs functions
- --ufs.files = {} --files functions
- ufs.fs = {} --fs functions
- ufs.tape = {} --use ufs.tape(address) to set tape address
- ufs.start = nil --root block/partition start offset
- ufs.endoff = nil --end offset
- ufs.pos = 0 --current position on tape
- ------blocks info------
- ufs.blocks[0] = {} --empty block
- ufs.blocks[0].name = false --name?
- ufs.blocks[0].next = false --next block?
- ufs.blocks[0].header = true --is header?
- ufs.blocks[0].cont = false --continue of header?
- ufs.blocks[1] = {}
- ufs.blocks[1].name = true
- ufs.blocks[1].next = true
- ufs.blocks[1].header = true
- ufs.blocks[1].cont = false
- ufs.blocks[2] = {}
- ufs.blocks[2].name = true
- ufs.blocks[2].next = true
- ufs.blocks[2].header = true
- ufs.blocks[2].cont = false
- ufs.blocks[3] = {}
- ufs.blocks[3].name = false
- ufs.blocks[3].next = true
- ufs.blocks[3].header = false
- ufs.blocks[3].cont = true
- ufs.blocks[4] = {}
- ufs.blocks[4].name = false
- ufs.blocks[4].next = true
- ufs.blocks[4].header = false
- ufs.blocks[4].cont = true
- ufs.blocks[5] = {}
- ufs.blocks[5].name = true
- ufs.blocks[5].next = false
- ufs.blocks[5].header = true
- ufs.blocks[5].cont = false
- ufs.blocks[65535] = {}
- ufs.blocks[65535].name = false
- ufs.blocks[65535].next = false
- ufs.blocks[65535].header= false
- ufs.blocks[65535].cont = false
- -----------------------
- setmetatable(ufs.tape,{
- __call = function(address)
- if type(ufs.tape.address) == "string" and ufs.tape.address ~= address and component.list()[address] == "tape_drive" then
- ufs.cache = {} --clear cache and positions because we will use different tape
- ufs.start = nil
- ufs.endoff = nil
- ufs.pos = 0
- --nah? ufs.fs.loaded = nil
- local mt = getmetatable(ufs.tape)
- ufs.tape = {}
- ufs.tape = component.proxy(address)
- setmetatable(ufs.tape,mt)
- mt = {}
- ufs.tape.address = address
- return true
- elseif ufs.tape.address == address then
- return false,"tape already set"
- elseif type(ufs.tape.address) ~= "string" then
- error("Address is not a string")
- else
- error("Component is not a tape drive")
- end
- end
- })
- function ufs.findRoot()
- ufs.tape.seek(ufs.tape.getSize())
- ufs.pos = 0
- ufs.start = nil
- ufs.endoff = nil
- repeat
- local b3 = ufs.tape.read(3)
- ufs.tape.seek(-2)
- ufs.pos = ufs.pos + 1
- if "\236\32\45" == b3 then
- ufs.start = ufs.pos - 1
- break
- end
- until ufs.tape.getSize() - 1024 == pos
- end
- function ufs.getMultiplier()
- if ufs.multiplier then
- return ufs.nultiplier, "use ufs.multiplier"
- end
- ufs.tape.seek(ufs.start - ufs.pos + 3)
- ufs.multiplier = read(1)
- ufs.pos = ufs.start + 3
- return ufs.multiplier
- end
- function ufs.getType(block)
- if block < 0 or block * ufs.multiplier * 512 >= ufs.endoff then
- return false, "not a ufs block"
- end
- if ufs.cache[block] and ufs.cache[block].type then --check cache
- return ufs.cache[block].type
- end
- ufs.pos = ufs.pos + ufs.tape.seek(ufs.start - ufs.pos + ufs.multiplier * 512 * block) + 2
- local btype = (ufs.cache[block] and ufs.cache[block].type) or nf2(ufs.tape.read(2))
- if ufs.cache[block] == nil then
- ufs.cache[block] = {}
- end
- if ufs.cache[block].type == nil then
- ufs.cache[block].type = btype
- end
- return btype
- end
- function ufs.isBlock(block)
- if ufs.block[(ufs.getType(block))] ~= nil then
- return true
- end
- return false
- end
- function ufs.getNext(block)
- if ufs.isBlocks(block) and ufs.blocks[ufs.getType(block)].next then
- if ufs.cache[block] and ufs.cache[block].next then
- return ufs.cache[block].next
- end
- ufs.pos = ufs.pos + ufs.tape.seek(ufs.start - ufs.pos + ufs.multiplier * 512 * (block + 1) - 2) + 2
- local nextb = nf2(ufs.tape.read(2))
- if ufs.cache[block] == nil then --cache for block exists?
- ufs.cache[block] = {}
- end
- ufs.cache[block].next = nextb
- return nextb
- end
- return false
- end
- function ufs.setNext(block)
- if ufs.isBlock(block) then
- if ufs.block[ufs.getType(block)].next then
- end
- end
- end
- function ufs.getParrent(block)
- if block == 0 then
- return false, "root block"
- elseif ufs.isBlock(block) then
- if ufs.cache[block] and ufs.cache[block].parrent then
- return ufs.cache[block].parrent
- end
- ufs.pos = ufs.pos + ufs.tape.seek(ufs.start - ufs.pos + ufs.multiplier * 512 * block + 2) + 2
- local parrent = nf2(ufs.tape.read(2))
- if ufs.cache[block] == nil then
- ufs.cache[block] = {}
- end
- if ufs.cache[block].parrent == nil then
- ufs.cache[block].parrent = parrent
- end
- return parrent
- end
- return false, "not a ufs block"
- end
- function ufs.getName(block) --get file/folder name
- if ufs.isBlock(block) and ufs.blocks[ufs.getType(block)].cont and block ~= 0 then
- return ufs.getName(ufs.getParrent(block)) --get name from header
- elseif ufs.isBlock(block) and blocks[ufs.getType(block)].name then --named block
- if ufs.cache[block] and ufs.cache[block].name then --check cache
- return ufs.cache[block].name
- end
- ufs.pos = ufs.pos + ufs.tape.seek(ufs.start - ufs.pos + ufs.multiplier * 512 * block + 4) + 64
- local name = string.grep(ufs.tape.read(64), "[\0/]", "")
- if ufs.cache[block] == nil then --cache for block exists?
- ufs.cache[block] = {}
- end
- ufs.cache[block].name = name
- return name
- else
- return false,(ufs.blocks[ufs.getType(block)] == nil and "not a ufs block") or "no field name on block"
- end
- end
- function ufs.setName(block,name) --set file/folder name
- if type(name) ~= "string" then
- error("Invalid argument #2: string expected, got " .. type(name))
- end
- if #name > 64 then
- error("Invalid argument #2: name cant be longer than 64 symbols")
- end
- if ufs.isBlock(block) and ufs.blocks[ufs.getType(block)].name then
- if ufs.cache[block] == nil then
- ufs.cache[block] = {}
- end
- if ufs.cache[block].name ~= name then
- ufs.pos = ufs.pos + ufs.tape.seek(ufs.start - ufs.pos + ufs.multiplier * 512 * block + 4) + 64
- ufs.tape.write(name .. string.rep("\0", 64 - #name))
- ufs.cache[block].name = name
- return true
- end
- return false, "name already set"
- elseif ufs.isBlock(block) then
- return false, "no field name on block"
- end
- end
- function ufs.findEnd()
- if ufs.endoff then
- return ufs.endoff, "use ufs.endoff"
- end
- local nblock = ufs.getNext(0)
- while ufs.getType(nblock) ~= 65535 do
- nblock = ufs.getNext(nblock)
- end
- if ufs.getType(nblock) == 65535 then
- ufs.endoff = ufs.start + ufs.multiplier * 512 * nblock
- else
- error("No end of partition found")
- end
- end
- function ufs.pathBlock(path) --returns path's block
- if path == "/" then
- return 0
- else
- end
- end
- function ufs.blockPath(block) --returns block's path
- if ufs.isBlock(block) and block ~= 0 then
- local bpath = ufs.getName(block)
- repeat
- local bparrent = ufs.getParrent(bparrent or block)
- bpath = (brappent ~= 0 and (ufs.getName(bparrent))) or "" .. "/" .. bpath
- until bparrent == 0
- return bpath
- elseif block == 0 then --so we wont add more if's to .fs path functions
- return "/"
- end
- end
- function ufs.childs(block) --returns table with addresses of child blocks, type
- local offs = 4
- if ufs.isBlock(block) == false then
- return false,"not a ufs block"
- elseif ufs.isBlock(block) and (ufs.getType(block) == 1 or ufs.getType(block) == 0) then
- offs = 68
- end
- local childs = {}
- for i=0,(ufs.multiplier * 256 - 3) do
- ufs.pos = ufs.pos + ufs.tape.seek(ufs.start - ufs.pos + ufs.multiplier * 512 * block + offs + i * 2) + 2
- local ch = nf2(ufs.tape.read(2))
- if ch ~= 0 then
- childs[#childs + 1] = ch
- end
- end
- return childs
- end
- function ufs.fs.list(path)
- end
- return ufs
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement