1class File < IO 2 attr_accessor :path 3 4 def initialize(fd_or_path, mode = "r", perm = 0666) 5 if fd_or_path.kind_of? Fixnum 6 super(fd_or_path, mode) 7 else 8 @path = fd_or_path 9 fd = IO.sysopen(@path, mode, perm) 10 super(fd, mode) 11 end 12 end 13 14 def self.join(*names) 15 return "" if names.empty? 16 17 names.map! do |name| 18 case name 19 when String 20 name 21 when Array 22 if names == name 23 raise ArgumentError, "recursive array" 24 end 25 join(*name) 26 else 27 raise TypeError, "no implicit conversion of #{name.class} into String" 28 end 29 end 30 31 return names[0] if names.size == 1 32 33 if names[0][-1] == File::SEPARATOR 34 s = names[0][0..-2] 35 else 36 s = names[0].dup 37 end 38 39 (1..names.size-2).each { |i| 40 t = names[i] 41 if t[0] == File::SEPARATOR and t[-1] == File::SEPARATOR 42 t = t[1..-2] 43 elsif t[0] == File::SEPARATOR 44 t = t[1..-1] 45 elsif t[-1] == File::SEPARATOR 46 t = t[0..-2] 47 end 48 s += File::SEPARATOR + t if t != "" 49 } 50 if names[-1][0] == File::SEPARATOR 51 s += File::SEPARATOR + names[-1][1..-1] 52 else 53 s += File::SEPARATOR + names[-1] 54 end 55 s 56 end 57 58 def self._concat_path(path, base_path) 59 if path[0] == "/" || path[1] == ':' # Windows root! 60 expanded_path = path 61 elsif path[0] == "~" 62 if (path[1] == "/" || path[1] == nil) 63 dir = path[1, path.size] 64 home_dir = _gethome 65 66 unless home_dir 67 raise ArgumentError, "couldn't find HOME environment -- expanding '~'" 68 end 69 70 expanded_path = home_dir 71 expanded_path += dir if dir 72 expanded_path += "/" 73 else 74 splitted_path = path.split("/") 75 user = splitted_path[0][1, splitted_path[0].size] 76 dir = "/" + splitted_path[1, splitted_path.size].join("/") 77 78 home_dir = _gethome(user) 79 80 unless home_dir 81 raise ArgumentError, "user #{user} doesn't exist" 82 end 83 84 expanded_path = home_dir 85 expanded_path += dir if dir 86 expanded_path += "/" 87 end 88 else 89 expanded_path = _concat_path(base_path, _getwd) 90 expanded_path += "/" + path 91 end 92 93 expanded_path 94 end 95 96 def self.expand_path(path, default_dir = '.') 97 expanded_path = _concat_path(path, default_dir) 98 drive_prefix = "" 99 if File::ALT_SEPARATOR && expanded_path.size > 2 && 100 ("A".."Z").include?(expanded_path[0].upcase) && expanded_path[1] == ":" 101 drive_prefix = expanded_path[0, 2] 102 expanded_path = expanded_path[2, expanded_path.size] 103 end 104 expand_path_array = [] 105 if File::ALT_SEPARATOR && expanded_path.include?(File::ALT_SEPARATOR) 106 expanded_path.gsub!(File::ALT_SEPARATOR, '/') 107 end 108 while expanded_path.include?('//') 109 expanded_path = expanded_path.gsub('//', '/') 110 end 111 112 if expanded_path != "/" 113 expanded_path.split('/').each do |path_token| 114 if path_token == '..' 115 if expand_path_array.size > 1 116 expand_path_array.pop 117 end 118 elsif path_token == '.' 119 # nothing to do. 120 else 121 expand_path_array << path_token 122 end 123 end 124 125 expanded_path = expand_path_array.join("/") 126 if expanded_path.empty? 127 expanded_path = '/' 128 end 129 end 130 if drive_prefix.empty? 131 expanded_path 132 else 133 drive_prefix + expanded_path.gsub("/", File::ALT_SEPARATOR) 134 end 135 end 136 137 def self.foreach(file) 138 if block_given? 139 self.open(file) do |f| 140 f.each {|l| yield l} 141 end 142 else 143 return self.new(file) 144 end 145 end 146 147 def self.directory?(file) 148 FileTest.directory?(file) 149 end 150 151 def self.exist?(file) 152 FileTest.exist?(file) 153 end 154 155 def self.exists?(file) 156 FileTest.exists?(file) 157 end 158 159 def self.file?(file) 160 FileTest.file?(file) 161 end 162 163 def self.pipe?(file) 164 FileTest.pipe?(file) 165 end 166 167 def self.size(file) 168 FileTest.size(file) 169 end 170 171 def self.size?(file) 172 FileTest.size?(file) 173 end 174 175 def self.socket?(file) 176 FileTest.socket?(file) 177 end 178 179 def self.symlink?(file) 180 FileTest.symlink?(file) 181 end 182 183 def self.zero?(file) 184 FileTest.zero?(file) 185 end 186 187 def self.extname(filename) 188 fname = self.basename(filename) 189 return '' if fname[0] == '.' || fname.index('.').nil? 190 ext = fname.split('.').last 191 ext.empty? ? '' : ".#{ext}" 192 end 193 194 def self.path(filename) 195 if filename.kind_of?(String) 196 filename 197 elsif filename.respond_to?(:to_path) 198 filename.to_path 199 else 200 raise TypeError, "no implicit conversion of #{filename.class} into String" 201 end 202 end 203end 204