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