tags:

views:

141

answers:

6

I'm writing some code that at run time may create or delete directories within the project path. I haven't really used ruby for file processing so i'm really uneasy about having code that, with a few mistypes weeks down the line, could result in wiping other directories outside of my project path.

Is there anyway to make it impossible for the program to delete files outside of its own path regardless of whats typed in destructive calls?

+1  A: 

You could generate an Array of filenames in your project directory using

my_files = Dir["/bla/bla/your/directory/**/*"]

and then simply check if the filename passed to your "delete" function exist in your my_files array.
I'm sure there is a more elegant solution, but this could work ^_^

Marc Seeger
Thanks! Ithought of this as well. But like you said, something in my head kept telling me there could be a more elegant solution.
adam
+2  A: 

You might want to create a wrapper method around your favourite delete method (or, perhaps, around whole class, because not only deleting files is potentially destructive file operation), which would expand all the submitted paths and check whether they begin with your "sandbox" path). You can also try to redefine delete method, if you are willing to cripple it through whole application.

And maybe the cleanest solution of them all would be to create a new user on your system and run your program as him.

Mladen Jablanović
I thought about creating a user, that was going to be my own answer to the solution. I wondered if it could be done via programming too.
adam
+1  A: 

You could use File.expand_path and File.dirname on the input, and check that against __FILE__. So something like this might work:

File.delete(path) if File.dirname(File.expand_path(path)).include? File.dirname(File.expand_path(__FILE__))
kejadlen
+2  A: 

On a POSIX system, you can use Dir.chroot to change the root that your application sees. Then ALL actions, not just delete ones, will be limited to the project directory. This does mean that external commands will be unavailable unless you make them part of your project directory as well.

This is the standard 'sandboxing' method used in Unix based systems. It can be difficult to setup (eliminating all external dependancies is sometimes hard), but affords significant protection when configured properly.

Myrddin Emrys
i have a feeling that might mess my rails app up with all the various gems etc it requires. But for some of my smaller projects such as scripting it could come in handy. Thanks for the tip!
adam
+2  A: 

Pathname is a wrapper class for almost any file operations.

require "pathname"
path= Pathname.new("/home/johannes")
path.directory? # => true
path.children # => [#<Pathname:.bash_history>, #<Pathname:Documents>, #<Pathname:Desktop>]
path.children.each do |p|
  p.delete if p.file?
end

Pathname#children does not contain . or .. so you don't accidently walk up the tree instead of down. If you still don't trust in the code, you can even check if on path is contained in another

Pathname.new("test") <=> Pathname.new("test/123") # => -1
johannes
this pathname looks interesting. Ill look it up on ruby core. The idea that i cant walk up the path specified has settled my nerves a lot!
adam
+1  A: 

I've got automated tests that routinely create and wipe out directories. I've taken two approaches:

  1. Use /tmp as much as possible. The 'tmpdir' standard library module will create temporary directories which will be destroyed when your program exits. Or,

  2. When the code creates a directory that it will later be deleting, it drops a marker file into the directory. When it comes time to delete the directory, if the marker file is not found, the code refuses to delete the directory. A marker file might be called ".ok_to_delete", for example.

Wayne Conrad
i like this because that my tests will have to do just this.
adam