2 class FileError < Exception; end
3 class NoFileError < FileError; end
4 class UnableToStat < FileError; end
5 class PermissionError < FileError; end
9 def initialize(fd_or_path, mode = "r", perm = 0666)
10 if fd_or_path.kind_of? Fixnum
11 super(fd_or_path, mode)
14 fd = IO.sysopen(@path, mode, perm)
20 return "" if names.empty?
28 raise ArgumentError, "recursive array"
32 raise TypeError, "no implicit conversion of #{name.class} into String"
36 return names[0] if names.size == 1
38 if names[0][-1] == File::SEPARATOR
44 (1..names.size-2).each { |i|
46 if t[0] == File::SEPARATOR and t[-1] == File::SEPARATOR
48 elsif t[0] == File::SEPARATOR
50 elsif t[-1] == File::SEPARATOR
53 s += File::SEPARATOR + t if t != ""
55 if names[-1][0] == File::SEPARATOR
56 s += File::SEPARATOR + names[-1][1..-1]
58 s += File::SEPARATOR + names[-1]
63 def self.expand_path(path, default_dir = '.')
64 def concat_path(path, base_path)
65 if path[0] == "/" || path[1] == ':' # Windows root!
68 if (path[1] == "/" || path[1] == nil)
69 dir = path[1, path.size]
73 raise ArgumentError, "couldn't find HOME environment -- expanding '~'"
76 expanded_path = home_dir
77 expanded_path += dir if dir
80 splitted_path = path.split("/")
81 user = splitted_path[0][1, splitted_path[0].size]
82 dir = "/" + splitted_path[1, splitted_path.size].join("/")
84 home_dir = _gethome(user)
87 raise ArgumentError, "user #{user} doesn't exist"
90 expanded_path = home_dir
91 expanded_path += dir if dir
95 expanded_path = concat_path(base_path, _getwd)
96 expanded_path += "/" + path
102 expanded_path = concat_path(path, default_dir)
104 if File::ALT_SEPARATOR && expanded_path.size > 2 &&
105 ("A".."Z").include?(expanded_path[0].upcase) && expanded_path[1] == ":"
106 drive_prefix = expanded_path[0, 2]
107 expanded_path = expanded_path[2, expanded_path.size]
109 expand_path_array = []
110 if File::ALT_SEPARATOR && expanded_path.include?(File::ALT_SEPARATOR)
111 expanded_path.gsub!(File::ALT_SEPARATOR, '/')
113 while expanded_path.include?('//')
114 expanded_path = expanded_path.gsub('//', '/')
117 if expanded_path != "/"
118 expanded_path.split('/').each do |path_token|
119 if path_token == '..'
120 if expand_path_array.size > 1
121 expand_path_array.pop
123 elsif path_token == '.'
126 expand_path_array << path_token
130 expanded_path = expand_path_array.join("/")
131 if expanded_path.empty?
135 if drive_prefix.empty?
138 drive_prefix + expanded_path.gsub("/", File::ALT_SEPARATOR)
142 def self.foreach(file)
144 self.open(file) do |f|
148 return self.new(file)
152 def self.directory?(file)
153 FileTest.directory?(file)
156 def self.exist?(file)
157 FileTest.exist?(file)
160 def self.exists?(file)
161 FileTest.exists?(file)
180 def self.socket?(file)
181 FileTest.socket?(file)
184 def self.symlink?(file)
185 FileTest.symlink?(file)
192 def self.extname(filename)
193 fname = self.basename(filename)
194 return '' if fname[0] == '.' || fname.index('.').nil?
195 ext = fname.split('.').last
196 ext.empty? ? '' : ".#{ext}"
199 def self.path(filename)
200 if filename.kind_of?(String)
202 elsif filename.respond_to?(:to_path)
205 raise TypeError, "no implicit conversion of #{filename.class} into String"