This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
GoldenSun's profile picture

Rewrite fs.open

Started by GoldenSun, 28 August 2015 - 02:29 PM
GoldenSun #1
Posted 28 August 2015 - 04:29 PM
Hello,

I'm trying to rewrite the fs.open function, but i don't know how. I want to add automatic Base64 functions to read/write operations, like this:
  1. Any program uses fs.open to read file content -> The fs.open function returns Base64 decoded text.
  2. Any program uses fs.open to write file content -> The fs.open function encode data and write it to the file.
I want to rewrite the fs api because I need (almost) full compatibility with all programs, and encode all files in disk. I tried to make this myself but I can't.

Additionally my english are very bad, sorry :S
Bomb Bloke #2
Posted 29 August 2015 - 02:41 AM
Why base64? The files will take up more disk space. What's the benefit?
Anavrins #3
Posted 29 August 2015 - 03:18 AM
I'm actually doing to same thing, with actual encryption instead of base64.
How I do it is by iterating through the handlers functions with a for loops, and overriding each function.


local _fs = fs

#-- New fs.open
fs.open = function(path, mode)
  local handler = _fs.open(path, mode)
  local ret = {}
  for name, func in pairs(handler) do
	if name == "read" then
	  table.insert(ret, function()
			#-- Your custom function, base64 decoder would be there
	  end
	elseif name == "write" then
	  table.insert(ret, function()
			#-- Custom write, base64 encoder would be there
	  end
	else
	  table.insert(ret, func)
	end
  end
  return ret
end
Edited on 29 August 2015 - 01:26 AM
Exerro #4
Posted 29 August 2015 - 05:33 PM
Just to save you a headache when debugging, that code won't quite work. You're using table.insert(), so the handle that function returns will contain things like h[1]() to read, h[2]() to write, etc. Instead, you should use `ret[name] = func` or `ret[name] = function() … end`. You'll also want to modify readAll() and writeLine(), and take into account files opened in rb, wb (and ab?) mode.
Bomb Bloke #5
Posted 30 August 2015 - 01:17 AM
You're also creating an infinite loop of calls by having both _fs and fs point to the same table. Hence when fs.open() calls _fs.open(), it's really calling fs.open(), which calls _fs.open(), which is fs.open(), etc…
Anavrins #6
Posted 30 August 2015 - 02:16 AM
Ah, interesting, how could I avoid doing that?
Also the table,insert was a mistype out of habit :P/>, it is actually ret[name] = func in my code.
Bomb Bloke #7
Posted 30 August 2015 - 03:18 AM
Normally I'd say "copy the table contents manually", but since you really just want to overwrite fs.open() (not the whole API), instead of:

local _fs = fs

… you'd want to do something like:

local _fsopen = fs.open

While we're at it, you could also do away with that "for" loop. Instead, check to see what specific functions exist within your handle, then rewrite based on those:

if handler.write and handler.writeLine then
  -- Text output.
elseif handler.write then
  -- Binary output.
elseif handler.read then
  -- Binary input.
else
  -- Text input.
end

Append mode makes matters more difficult. The simple way to deal with it is to spot it BEFORE you open your file handle for output, manually read in the existing file content first, decode it, get whatever the user wants to add to it, then finally re-encode the whole stream and write the lot to disk when a request to close the handle comes through.
Bomb Bloke #8
Posted 30 August 2015 - 04:33 AM
Actually, another relevant factor comes to mind: You'd want to sandbox the replacement function, or else you'll break the system's ability to work with regular files (eg, all the scripts in rom).
valithor #9
Posted 30 August 2015 - 05:01 AM
Actually, another relevant factor comes to mind: You'd want to sandbox the replacement function, or else you'll break the system's ability to work with regular files (eg, all the scripts in rom).

Seeing as this would really only be a problem with the ability to read from a file you could alternatively make any file encoded with base64 have a commented out string at the top of it saying that it is encoded with base64. If that exists then when you read decode it, if it does not then just treat it like a normal file.
Anavrins #10
Posted 30 August 2015 - 04:52 PM
Normally I'd say "copy the table contents manually", but since you really just want to overwrite fs.open() (not the whole API), instead of:

local _fs = fs

… you'd want to do something like:

local _fsopen = fs.open
Oh of course, I was originally planning to replace most of the functions, but finally only needed .open and .isReadOnly.

About the rom files, I already took care of it by placing a header/magic number in the encrypted files and only tries to decrypt if it contains it.
Edited on 30 August 2015 - 02:55 PM