1 | class 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
|
---|
203 | end
|
---|