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

[Solved] Overwritting Fs Crashes

Started by lieudusty, 18 July 2013 - 05:06 PM
lieudusty #1
Posted 18 July 2013 - 07:06 PM
Hi everyone! :D/>

I'm trying to create a function that replaces fs.open but even if I strip it down to very basic code, it still doesn't work. After running this, when I use any FS function it has a java out of bounds error.


old = fs
function test(path, mode)
  han = old.open(path, mode)
  return han
end
fs.open = test

Any help is appreciated! Thank you in advanced :)/>
Engineer #2
Posted 18 July 2013 - 07:21 PM
However I cant seem to reproduce, I suggest 'direct overwriting'

For example:

local _fs.open = fs.open
fs.open = function( path, mode )
  local han = _fs.open( path, mode )
  return han
end

I know it! You are creating a pointer to fs, not the actual table. So you are actually doing recursion.
I figured out a way how to avoid it:

local test = {}
for k, v in pairs( _G["fs"] ) do
	test[k] = v
end

fs.open = function( mode, path )
	local han = test.open( mode, path )
	return han
end

print( fs.isDir("rom") )
local t = fs.open( "test", "w")
t.write( "qw" )
t.close()
lieudusty #3
Posted 18 July 2013 - 07:29 PM
However I cant seem to reproduce, I suggest 'direct overwriting'

For example:

local _fs.open = fs.open
fs.open = function( path, mode )
  local han = _fs.open( path, mode )
  return han
end

I know it! You are creating a pointer to fs, not the actual table. So you are actually doing recursion.
I figured out a way how to avoid it:

local test = {}
for k, v in pairs( _G["fs"] ) do
	test[k] = v
end

fs.open = function( mode, path )
	local han = test.open( mode, path )
	return han
end

print( fs.isDir("rom") )
local t = fs.open( "test", "w")
t.write( "qw" )
t.close()

Ah ok I see. Thanks a lot! :)/>
lieudusty #4
Posted 19 July 2013 - 06:17 PM
Ok so I tried the code again this time modifying somethings but I keep getting the Java out of bounds error. The full code had some other things but I stripped it down to basic idea but it doesn't work


oldFS = {}
for k, v in pairs(_G["fs"]) do
oldFS[k] = v
end

fs.open = function(path, mode)
  local fsHandle = oldFS.open(path, mode)
  local fsClose = fsHandle.close

  local function close()
     return fsHandle.close()
  end
  fsHandle["close"] = close
  return fsHandle
end

print( fs.isDir("rom") )
local t = fs.open( "test", "w")
t.write( "qw" )
t.close()
Grim Reaper #5
Posted 19 July 2013 - 07:09 PM
You're calling close recursively on the handle you're returning.

You define the function close to call fsHandle.close, then set the close function to the one you just defined, thus overwriting the original close function. Once you call close, it will keep trying to call itself and create a call stack which overflows because there are too many levels (never ending).

Try this:

local oldFs = {}

for functionName, _function in pairs (_G["fs"]) do
    oldFs[functionName] = _function
end

function _G["fs"].open (path, mode)
    -- Insert your other code here, if you want.

    -- Here is a test: if the file is a directory, then
    -- throw a huge fit about it... Hehe...
    if oldFs.isDir (path) then
        error ("What the hell are you thinking? Trying to open a directory... Dumbass...")
    end

    -- Things worked out? Return a handle using the original fs API.
    return oldFs.open (path, mode)
end
MysticT #6
Posted 19 July 2013 - 07:23 PM
You don't need to copy the whole fs api, just the open function:

local oldFsOpen = fs.open
function fs.open(path, mode)
  local handle = oldFsOpen(path, mode)
  -- do whatever you want now
  return handle
end
lieudusty #7
Posted 19 July 2013 - 08:18 PM
So how can I override the close function in fs.open without causing stack overflow?

EDIT: Never mind figured it out. Thanks for the help guys! :)/>
Engineer #8
Posted 21 July 2013 - 07:02 AM
However this is solved and such, I want to point out that there is another where to back-up some API's. It is very easy:

local oldFS = setmetatable( {}, { __index = _G["fs"] } )
It is way quicker and just one line :)/>
The only thing is, you cant loop through the table and get the keys, because it is a metatable.