mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
8cee36b1b5
When system file descriptor table is full, errno is set to ENFILE instead of EMFILE. They are similar but different.
166 lines
3.7 KiB
Ruby
166 lines
3.7 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)
|
|
self._bless
|
|
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 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] == "/"
|
|
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.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
|