Jump to content




Quarantine program not functioning

lua

  • You cannot reply to this topic
29 replies to this topic

#1 ViperLordX

  • Members
  • 43 posts
  • LocationEarth

Posted 06 November 2015 - 01:03 AM

I've been writing a program designed to move everything to a folder, q, and make it virtually undetectable. When it runs, it will move all files other than itself and q to q, and it modifies the fs api so that everything appears normal. The problem is that if you try to run a program in the q folder while quarantined, it won't run. However, if you try running q/[program], it will. Can anyone explain this? fs.exists, fs.open, and everything else still work like I made them work. I don't know what shell is doing to break out.
function main()
  local es = fs
  allowed = {"rom", "disk[1-6]"}
  function cover(file)
    file = es.combine(file, "")
    file = file:gsub("%.%.", "")
    permitted = false
    for _, v in pairs(allowed) do
	  if (string.find(file, v)) then
	    permitted = true
	  end
    end
    if (not (permitted)) then
	  file = "q/"..file
    end
    return file
  end
  function uncover(file)
    file = es.combine(file, "")
    file = string.gsub(file, "^q/", "")
    return file
  end
  if (not es.exists("q")) then
    es.makeDir("q")
  end
  files = es.list("/")
  for k, v in pairs(files) do
    if (not (v == "start") and not (v == "q")) then
	  if (not (es.exists(cover(v)))) then
	    es.copy(v, cover(v))
	  end
	  if (not (es.isReadOnly(v)) and not (v == "q")) then
	    es.delete(v)
	  end
    end
  end
  local vfs = {}
  function vfs.list(path)
    r = es.list(cover(path))
    if (path == "") then
	  r[#r + 1] = "rom"
    end
    for k, v in pairs(r) do
	  r[k] = uncover(v)
    end
    return r
  end
  function vfs.exists(path)
    return es.exists(cover(path))
  end
  function vfs.isDir(path)
    return es.isDir(cover(path))
  end
  function vfs.isReadOnly(path)
    return es.isReadOnly(cover(path))
  end
  function vfs.getDrive(path)
    return es.getDrive(cover(path))
  end
  function vfs.getSize(path)
    return es.getSize(cover(path))
  end
  function vfs.getFreeSpace(path)
    return es.getFreeSpace(cover(path))
  end
  function vfs.makeDir(path)
    es.makeDir(cover(path))
  end
  function vfs.move(fromPath, toPath)
    es.move(cover(fromPath), cover(toPath))
  end
  function vfs.copy(fromPath, toPath)
    es.copy(cover(fromPath), cover(toPath))
  end
  function vfs.delete(path)
    es.delete(cover(path))
  end
  function vfs.open(path, mode)
    return es.open(cover(path), mode)
  end
  function vfs.find(wildcard)
    value = es.find(cover(wildcard))
    for k, v in pairs(value) do
	  value[k] = uncover(v)
    end
    return value
  end
  vfs.complete = es.complete
  vfs.combine = es.combine
  vfs.getName = es.getName
  fs = vfs
end
main()


#2 valithor

  • Members
  • 1,053 posts

Posted 06 November 2015 - 02:56 PM

I do not really have time to look into it to help, but in the few minutes I had to look over it, I found that your problem is the shell.resolveProgram function, which is called inside shell.run. In my test, passing the file name only to shell.resolveProgram causes it to return nil (is what is being passed to the function), but passing the q/..filename caused it to return the correct file name. Would be worth looking into what causes that function to think the file does not exist. I would do it myself, but I do not have time.

Alternatively, you could make a alias through shell for each of the files you move.

Edited by valithor, 06 November 2015 - 02:57 PM.


#3 ViperLordX

  • Members
  • 43 posts
  • LocationEarth

Posted 06 November 2015 - 09:18 PM

Ok, I'll try it. Thanks!

#4 ViperLordX

  • Members
  • 43 posts
  • LocationEarth

Posted 06 November 2015 - 09:38 PM

When I overwrite shell.resolve() or shell.resolveProgram(), the entire computer freezes, including the event queue but not the cursor, and then shuts down after a while.

Ok, I tested it, and it only seems to freeze shell, and nothing else. If I use lua to manually overwrite it, then exit lua, the shell freezes. It also happens if I make shell.resolve() return the value of blah.resolve() where blah = shell.

#5 H4X0RZ

  • Members
  • 1,315 posts
  • LocationGermany

Posted 07 November 2015 - 01:07 AM

Are you simply doing
blah = shell
shell.resolve = blah.resolve
because that doesn't copy the table, it just adds a "pointer" for that table.

#6 ViperLordX

  • Members
  • 43 posts
  • LocationEarth

Posted 07 November 2015 - 02:47 AM

No, I did this:
function shell.resolve(name)
  return blah.resolve(name)
end


#7 valithor

  • Members
  • 1,053 posts

Posted 07 November 2015 - 02:51 AM

View PostViperLordX, on 07 November 2015 - 02:47 AM, said:

No, I did this:
function shell.resolve(name)
  return blah.resolve(name)
end

What he meant by that was, are you doing this to copy the table:
blah = shell

The second part really wasn't needed to ask what he was asking.

Edited by valithor, 07 November 2015 - 02:52 AM.


#8 ViperLordX

  • Members
  • 43 posts
  • LocationEarth

Posted 07 November 2015 - 02:52 AM

Yes, I am

#9 valithor

  • Members
  • 1,053 posts

Posted 07 November 2015 - 02:55 AM

View PostViperLordX, on 07 November 2015 - 02:52 AM, said:

Yes, I am

The reason it is crashing then is due to the way lua tables work. When you do "blah = shell" you are not making a new table with the same contents as shell, you are creating a variable that points to the same table as the shell variable points to. So, in short there is 1 table, and the function you overwrote shell.resolveProgram with, is just calling itself over and over (CC limits recursion to 255 times, which eventually causes a crash).

#10 ViperLordX

  • Members
  • 43 posts
  • LocationEarth

Posted 07 November 2015 - 02:55 AM

So how do I avoid this?

#11 valithor

  • Members
  • 1,053 posts

Posted 07 November 2015 - 02:57 AM

View PostViperLordX, on 07 November 2015 - 02:55 AM, said:

So how do I avoid this?

Right now I am starting minecraft in order to play around with it and help you find a answer to your original problem, but in order to overcome the problem you are having right now is fairly easy.

Instead of copying the entire table, just copy the single function you are going to overwrite:
local oldResolveProgram = shell.resolveProgram

shell.resolveProgram = function(...)
  return oldResolveProgram(...)
end

Edited by valithor, 07 November 2015 - 07:52 PM.


#12 KingofGamesYami

  • Members
  • 3,002 posts
  • LocationUnited States of America

Posted 07 November 2015 - 03:04 AM

Whenever modifying APIs, it's a good idea to back-up the API using a for loop.

local oldShell = {}
for k, v in pairs( shell )
  oldShell[ k ] = v
end

shell.resolveProgram = function( ... )
  return oldShell.resolveProgram( ... )
end

Edit: Clarification on this issue:

Variables pointing to tables really contain a pointer to the table.

This can be demonstrated with the following:

local t = {foo="bar"}
print( t.foo )
local _t = t
_t.foo = "foo"
print( t.foo )

As you can see, even though we assigned _t.foo a variable instead of t.foo, t.foo was also changed. This is because, in reality, both of these variables are simply labels - and they label the same table.

Edited by KingofGamesYami, 07 November 2015 - 03:08 AM.


#13 valithor

  • Members
  • 1,053 posts

Posted 07 November 2015 - 03:08 AM

A quick little fix that will fix your problem:

local oldResolveProgram = shell.resolveProgram

shell.resolveProgram = function(path)
  if oldResolveProgram(path) ~= nil then --# checking if it is nil without the "q/" added on.  Essentially if the path is for rom, or a disk
	return oldResolveProgram(path) --# returning it sense it isn't nil
  else
	return oldResolveProgram("q/"..path) --# returning the "q/" path
  end
end

Edited by valithor, 07 November 2015 - 05:56 PM.


#14 ViperLordX

  • Members
  • 43 posts
  • LocationEarth

Posted 07 November 2015 - 05:01 AM

Come to think of it, I could just do blah = {} then set blah.resolve(), then setmetatable(blah, {__index = shell}) shell = blah

#15 ViperLordX

  • Members
  • 43 posts
  • LocationEarth

Posted 07 November 2015 - 06:18 AM

My new code is below, and it's still not working. Now it thinks that anything within q does not exist, and it also errors if I do "edit ___" where ___ is anything, saying that it's too long without yielding on line 16 of all things: file = es.combine(file, ""). It's not even in a loop!
local function contains(table, value)
  for k, v in pairs(table) do
    if (v == value) then
	  return true;
    end
  end
  return false;
end
function main()
  local es = {}
  for k, v in pairs(fs) do
    es[k] = v
  end
  allowed = {"rom", "disk[1-6]"}
  function cover(file)
    file = es.combine(file, "")
    file = string.gsub(file, "%.%.", "")
    permitted = false
    for _, v in pairs(allowed) do
	  if (string.find(file, v)) then
	    permitted = true
	  end
    end
    if (not (permitted)) then
	  file = "q/"..file
    end
    return file
  end
  function uncover(file)
    file = es.combine(file, "")
    file = string.gsub(file, "^q/", "")
    return file
  end
  if (not es.exists("q")) then
    es.makeDir("q")
  end
  files = es.list("/")
  for k, v in pairs(files) do
    if (not (v == "start") and not (v == "q")) then
	  if (not (es.exists(cover(v)))) then
	    es.copy(v, cover(v))
	  end
	  if (not (es.isReadOnly(v)) and not (v == "q")) then
	    es.delete(v)
	  end
    end
  end
  local vfs = {}
  function vfs.list(path)
    r = es.list(cover(path))
    if (path == "") then
	  r[#r + 1] = "rom"
    end
    for k, v in pairs(r) do
	  r[k] = uncover(v)
    end
    return r
  end
  function vfs.exists(path)
    return es.exists(cover(path))
  end
  function vfs.isDir(path)
    return es.isDir(cover(path))
  end
  function vfs.isReadOnly(path)
    return es.isReadOnly(cover(path))
  end
  function vfs.getDrive(path)
    return es.getDrive(cover(path))
  end
  function vfs.getSize(path)
    return es.getSize(cover(path))
  end
  function vfs.getFreeSpace(path)
    return es.getFreeSpace(cover(path))
  end
  function vfs.makeDir(path)
    es.makeDir(cover(path))
  end
  function vfs.move(fromPath, toPath)
    es.move(cover(fromPath), cover(toPath))
  end
  function vfs.copy(fromPath, toPath)
    es.copy(cover(fromPath), cover(toPath))
  end
  function vfs.delete(path)
    es.delete(cover(path))
  end
  function vfs.open(path, mode)
    return es.open(cover(path), mode)
  end
  function vfs.find(wildcard)
    value = es.find(cover(wildcard))
    for k, v in pairs(value) do
	  value[k] = uncover(v)
    end
    return value
  end
  vfs.complete = es.complete
  vfs.combine = es.combine
  vfs.getName = es.getName
  fs = vfs
  local hell = {}
  function hell.resolve(name)
    return hell.resolve(cover(name))
  end
    function hell.resolveProgram(name)
    return hell.resolveProgram(cover(name))
  end
  setmetatable(hell, {__index = shell})
  shell = hell
end
main()


#16 valithor

  • Members
  • 1,053 posts

Posted 07 November 2015 - 05:58 PM

If you use the fix I gave you instead of the one you came up with it would work and would be much more efficient.

Also, when you do eventually switch over to the one I gave you, you will realize you are getting a error on line 65 of edit. In which case you will need to overwrite io.open in the same way you overwrote fs.open.

local oldResolveProgram = shell.resolveProgram

shell.resolveProgram = function(path)
  if oldResolveProgram(path) ~= nil then --# checking if it is nil without the "q/" added on.  Essentially if the path is for rom, or a disk
        return oldResolveProgram(path) --# returning it sense it isn't nil
  else
        return oldResolveProgram("q/"..path) --# returning the "q/" path
  end
end

local oldIoOpen = io.open

io.open = function(path,mode)
  return oldIoOpen(cover(path),mode)
end


#17 KingofGamesYami

  • Members
  • 3,002 posts
  • LocationUnited States of America

Posted 07 November 2015 - 06:10 PM

@valithor - that'd be a terrible idea, as overwriting fs already overwrites io. io uses fs.

#18 Lyqyd

    Lua Liquidator

  • Moderators
  • 8,465 posts

Posted 07 November 2015 - 06:12 PM

In ComputerCraft, io.open uses fs.open internally, so if you're overriding fs, you probably don't need to touch io.

#19 ViperLordX

  • Members
  • 43 posts
  • LocationEarth

Posted 07 November 2015 - 06:22 PM

So what is the issue with the code? Why is it saying that it's too long without yielding when it's not even in a loop, and it's the first line in the function?

#20 valithor

  • Members
  • 1,053 posts

Posted 07 November 2015 - 06:45 PM

View PostKingofGamesYami, on 07 November 2015 - 06:10 PM, said:

@valithor - that'd be a terrible idea, as overwriting fs already overwrites io. io uses fs.

View PostLyqyd, on 07 November 2015 - 06:12 PM, said:

In ComputerCraft, io.open uses fs.open internally, so if you're overriding fs, you probably don't need to touch io.

Apparently overwriting the fs api did not change the io api. It might be how he overwrote it, but when I was testing the program in a emulator the fs.exists check on line 63 of the edit program was returning true, but line 65 was erroring with attempt to call nil, aka io.opening the file that fs.exist said exist was returning nil. I came to the conclusion that io.open was still using the unmodified version of fs.open, which made no sense to me, but doing the overwrite i posted fixed it.

Put shortly. I thought the exact same as both of you, but it doesn't work without making that modification from my tests, and yes I do understand how the io api works internally.

Edited by valithor, 07 November 2015 - 06:51 PM.






1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users