mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
177 lines
3.9 KiB
Ruby
177 lines
3.9 KiB
Ruby
class File < IO
|
|
include Enumerable
|
|
|
|
class FileError < Exception; end
|
|
class NoFileError < FileError; end
|
|
class UnableToStat < FileError; end
|
|
class PermissionError < FileError; end
|
|
|
|
attr_accessor :path
|
|
|
|
def initialize(fd_or_path, mode = "r", perm = 0666)
|
|
if fd_or_path.kind_of? Fixnum
|
|
super(fd_or_path, mode)
|
|
else
|
|
@path = fd_or_path
|
|
begin
|
|
fd = IO.sysopen(@path, mode, perm)
|
|
rescue RuntimeError => e
|
|
raise FileError, "Could not open file (#{e})"
|
|
rescue Errno::EMFILE, Errno::ENFILE
|
|
GC.start
|
|
fd = IO.sysopen(@path, mode, perm)
|
|
end
|
|
super(fd, mode)
|
|
end
|
|
end
|
|
|
|
def self.join(*names)
|
|
if names.size == 0
|
|
""
|
|
elsif names.size == 1
|
|
names[0]
|
|
else
|
|
if names[0][-1] == File::SEPARATOR
|
|
s = names[0][0..-2]
|
|
else
|
|
s = names[0].dup
|
|
end
|
|
(1..names.size-2).each { |i|
|
|
t = names[i]
|
|
if t[0] == File::SEPARATOR and t[-1] == File::SEPARATOR
|
|
t = t[1..-2]
|
|
elsif t[0] == File::SEPARATOR
|
|
t = t[1..-1]
|
|
elsif t[-1] == File::SEPARATOR
|
|
t = t[0..-2]
|
|
end
|
|
s += File::SEPARATOR + t if t != ""
|
|
}
|
|
if names[-1][0] == File::SEPARATOR
|
|
s += File::SEPARATOR + names[-1][1..-1]
|
|
else
|
|
s += File::SEPARATOR + names[-1]
|
|
end
|
|
s
|
|
end
|
|
end
|
|
|
|
def self.expand_path(path, default_dir = '.')
|
|
def concat_path(path, base_path)
|
|
if path[0] == "/" || path[1] == ':' # Windows root!
|
|
expanded_path = path
|
|
elsif path[0] == "~"
|
|
if (path[1] == "/" || path[1] == nil)
|
|
dir = path[1, path.size]
|
|
home_dir = _gethome
|
|
|
|
unless home_dir
|
|
raise ArgumentError, "couldn't find HOME environment -- expanding '~'"
|
|
end
|
|
|
|
expanded_path = home_dir
|
|
expanded_path += dir if dir
|
|
expanded_path += "/"
|
|
else
|
|
splitted_path = path.split("/")
|
|
user = splitted_path[0][1, splitted_path[0].size]
|
|
dir = "/" + splitted_path[1, splitted_path.size].join("/")
|
|
|
|
home_dir = _gethome(user)
|
|
|
|
unless home_dir
|
|
raise ArgumentError, "user #{user} doesn't exist"
|
|
end
|
|
|
|
expanded_path = home_dir
|
|
expanded_path += dir if dir
|
|
expanded_path += "/"
|
|
end
|
|
else
|
|
expanded_path = concat_path(base_path, _getwd)
|
|
expanded_path += "/" + path
|
|
end
|
|
|
|
expanded_path
|
|
end
|
|
|
|
expanded_path = concat_path(path, default_dir)
|
|
expand_path_array = []
|
|
while expanded_path.include?('//')
|
|
expanded_path = expanded_path.gsub('//', '/')
|
|
end
|
|
|
|
if expanded_path == "/"
|
|
expanded_path
|
|
else
|
|
expanded_path.split('/').each do |path_token|
|
|
if path_token == '..'
|
|
if expand_path_array.size > 1
|
|
expand_path_array.pop
|
|
end
|
|
elsif path_token == '.'
|
|
# nothing to do.
|
|
else
|
|
expand_path_array << path_token
|
|
end
|
|
end
|
|
|
|
expand_path = expand_path_array.join("/")
|
|
expand_path.empty? ? '/' : expand_path
|
|
end
|
|
end
|
|
|
|
def self.foreach(file)
|
|
if block_given?
|
|
self.open(file) do |f|
|
|
f.each {|l| yield l}
|
|
end
|
|
else
|
|
return self.new(file)
|
|
end
|
|
end
|
|
|
|
def self.directory?(file)
|
|
FileTest.directory?(file)
|
|
end
|
|
|
|
def self.exist?(file)
|
|
FileTest.exist?(file)
|
|
end
|
|
|
|
def self.exists?(file)
|
|
FileTest.exists?(file)
|
|
end
|
|
|
|
def self.file?(file)
|
|
FileTest.file?(file)
|
|
end
|
|
|
|
def self.pipe?(file)
|
|
FileTest.pipe?(file)
|
|
end
|
|
|
|
def self.size?(file)
|
|
FileTest.size?(file)
|
|
end
|
|
|
|
def self.socket?(file)
|
|
FileTest.socket?(file)
|
|
end
|
|
|
|
def self.symlink?(file)
|
|
FileTest.symlink?(file)
|
|
end
|
|
|
|
def self.zero?(file)
|
|
FileTest.zero?(file)
|
|
end
|
|
|
|
def self.extname(filename)
|
|
fname = self.basename(filename)
|
|
return '' if fname[0] == '.' || fname.index('.').nil?
|
|
ext = fname.split('.').last
|
|
ext.empty? ? '' : ".#{ext}"
|
|
end
|
|
end
|