rubydirectorypathrelative-path

File referencing using relative paths on Ruby


I just completed a CTF machine, but my brain has a hard time figuring out why this worked, so I thought to ask because I won't be able to sleep until I know! My question is regarding the use of the relative paths.

Below is the source code of a Ruby script that includes the list_from_file function which uses a relative path for reading the dependencies.yml file.

henry@precious:~$ cat /opt/update_dependencies.rb
# Compare installed dependencies with those specified in "dependencies.yml"
require "yaml"
require 'rubygems'

# TODO: update versions automatically
def update_gems()
end

def list_from_file
  YAML.load(File.read("dependencies.yml"))
end

def list_local_gems
  Gem::Specification.sort_by{ |g| [g.name.downcase, g.version] }.map{|g| [g.name, g.version.to_s]}
end

gems_file = list_from_file
gems_local = list_local_gems

gems_file.each do |file_name, file_version|
  gems_local.each do |local_name, local_version|
    if(file_name == local_name)
      if(file_version != local_version)
        puts "Installed version differs from the one specified in file: " + local_name
      else
        puts "Installed version is equals to the one specified in file: " + local_name
      end
    end
  end
end

My limited knowledge infers that when I execute this script, it will only search to find the dependencies.yml file in the same directory as the script, in this case, /opt/.

However, this is not true! When I create this file within the /tmp directory, and then run the script, it actually picks it up!

I searched and read some articles as well as other stackoverflow posts regarding relative vs. absolute paths but none actually provided an explanation for why this is happening.

I am sorry in advance if I missed any closely-related post!


Solution

  • Relative paths in Ruby are always dependent on the current working directory. The current working directory is not necessarily the same as the directory in which the script resides, but rather in which directory you are at the moment when you launch Ruby.

    Example:

    > cd /tmp
    > ruby /some/path/somewhere/to/my/script.rb
    

    What is the current working directory of script.rb in this case?

    Answer: it is /tmp, because that is the directory you were in when you launched the script.

    To display the current working directory from the script itself, you can add a line puts Dir.pwd, and the script will print out in which folder it is running at that moment.

    To change the current working directory of the script, you can use Dir.chdir.

    You can see why using relative paths can easily lead to confusion, because it all depends on from which directory the launch of the Ruby executable was. It could be anywhere.

    This is why most scripts use either absolute paths, or paths relative to the script file itself. To use paths relative to the script file itself, you can use __dir__ as the starting point and build your script-relative paths from there.

    See more discussion here:
    Can a Ruby script tell what directory it’s in?