@@ -66,6 +66,10 @@ public class RubyFileStat extends RubyObject {
6666 private FileResource file ;
6767 private FileStat stat ;
6868
69+ private void checkInitialized () {
70+ if (stat == null ) throw getRuntime ().newTypeError ("uninitialized File::Stat" );
71+ }
72+
6973 private static ObjectAllocator ALLOCATOR = new ObjectAllocator () {
7074 @ Override
7175 public IRubyObject allocate (Ruby runtime , RubyClass klass ) {
@@ -148,31 +152,37 @@ public IRubyObject initialize19(IRubyObject fname, Block unusedBlock) {
148152
149153 @ JRubyMethod (name = "atime" )
150154 public IRubyObject atime () {
155+ checkInitialized ();
151156 return getRuntime ().newTime (stat .atime () * 1000 );
152157 }
153158
154159 @ JRubyMethod (name = "blksize" )
155160 public RubyFixnum blksize () {
161+ checkInitialized ();
156162 return getRuntime ().newFixnum (stat .blockSize ());
157163 }
158164
159165 @ JRubyMethod (name = "blockdev?" )
160166 public IRubyObject blockdev_p () {
167+ checkInitialized ();
161168 return getRuntime ().newBoolean (stat .isBlockDev ());
162169 }
163170
164171 @ JRubyMethod (name = "blocks" )
165172 public IRubyObject blocks () {
173+ checkInitialized ();
166174 return getRuntime ().newFixnum (stat .blocks ());
167175 }
168176
169177 @ JRubyMethod (name = "chardev?" )
170178 public IRubyObject chardev_p () {
179+ checkInitialized ();
171180 return getRuntime ().newBoolean (stat .isCharDev ());
172181 }
173182
174183 @ JRubyMethod (name = "<=>" , required = 1 )
175184 public IRubyObject cmp (IRubyObject other ) {
185+ checkInitialized ();
176186 if (!(other instanceof RubyFileStat )) return getRuntime ().getNil ();
177187
178188 long time1 = stat .mtime ();
@@ -189,63 +199,75 @@ public IRubyObject cmp(IRubyObject other) {
189199
190200 @ JRubyMethod (name = "ctime" )
191201 public IRubyObject ctime () {
202+ checkInitialized ();
192203 return getRuntime ().newTime (stat .ctime () * 1000 );
193204 }
194205
195206 @ JRubyMethod (name = "birthtime" )
196207 public IRubyObject birthtime () {
208+ checkInitialized ();
197209 FileTime btime = RubyFile .getBirthtimeWithNIO (file .absolutePath ());
198210 if (btime != null ) return getRuntime ().newTime (btime .toMillis ());
199211 return ctime ();
200212 }
201213
202214 @ JRubyMethod (name = "dev" )
203215 public IRubyObject dev () {
216+ checkInitialized ();
204217 return getRuntime ().newFixnum (stat .dev ());
205218 }
206219
207220 @ JRubyMethod (name = "dev_major" )
208221 public IRubyObject devMajor () {
222+ checkInitialized ();
209223 return getRuntime ().newFixnum (stat .major (stat .dev ()));
210224 }
211225
212226 @ JRubyMethod (name = "dev_minor" )
213227 public IRubyObject devMinor () {
228+ checkInitialized ();
214229 return getRuntime ().newFixnum (stat .minor (stat .dev ()));
215230 }
216231
217232 @ JRubyMethod (name = "directory?" )
218233 public RubyBoolean directory_p () {
234+ checkInitialized ();
219235 return getRuntime ().newBoolean (stat .isDirectory ());
220236 }
221237
222238 @ JRubyMethod (name = "executable?" )
223239 public IRubyObject executable_p () {
240+ checkInitialized ();
224241 return getRuntime ().newBoolean (stat .isExecutable ());
225242 }
226243
227244 @ JRubyMethod (name = "executable_real?" )
228245 public IRubyObject executableReal_p () {
246+ checkInitialized ();
229247 return getRuntime ().newBoolean (stat .isExecutableReal ());
230248 }
231249
232250 @ JRubyMethod (name = "file?" )
233251 public RubyBoolean file_p () {
252+ checkInitialized ();
234253 return getRuntime ().newBoolean (stat .isFile ());
235254 }
236255
237256 @ JRubyMethod (name = "ftype" )
238257 public RubyString ftype () {
258+ checkInitialized ();
239259 return getRuntime ().newString (stat .ftype ());
240260 }
241261
242262 @ JRubyMethod (name = "gid" )
243263 public IRubyObject gid () {
264+ checkInitialized ();
244265 return getRuntime ().newFixnum (stat .gid ());
245266 }
246267
247268 @ JRubyMethod (name = "grpowned?" )
248269 public IRubyObject group_owned_p () {
270+ checkInitialized ();
249271 return getRuntime ().newBoolean (stat .isGroupOwned ());
250272 }
251273
@@ -268,6 +290,7 @@ public IRubyObject initialize_copy(IRubyObject original) {
268290
269291 @ JRubyMethod (name = "ino" )
270292 public IRubyObject ino () {
293+ checkInitialized ();
271294 return getRuntime ().newFixnum (stat .ino ());
272295 }
273296
@@ -276,41 +299,48 @@ public IRubyObject ino() {
276299 public IRubyObject inspect () {
277300 StringBuilder buf = new StringBuilder ("#<" );
278301 buf .append (getMetaClass ().getRealClass ().getName ());
279- buf .append (" " );
280- // FIXME: Obvious issue that not all platforms can display all attributes. Ugly hacks.
281- // Using generic posix library makes pushing inspect behavior into specific system impls
282- // rather painful.
283- try { buf .append ("dev=0x" ).append (Long .toHexString (stat .dev ())); } catch (Exception e ) {} finally { buf .append (", " ); }
284- try { buf .append ("ino=" ).append (stat .ino ()); } catch (Exception e ) {} finally { buf .append (", " ); }
285- buf .append ("mode=0" ).append (Integer .toOctalString (stat .mode ())).append (", " );
286- try { buf .append ("nlink=" ).append (stat .nlink ()); } catch (Exception e ) {} finally { buf .append (", " ); }
287- try { buf .append ("uid=" ).append (stat .uid ()); } catch (Exception e ) {} finally { buf .append (", " ); }
288- try { buf .append ("gid=" ).append (stat .gid ()); } catch (Exception e ) {} finally { buf .append (", " ); }
289- try { buf .append ("rdev=0x" ).append (Long .toHexString (stat .rdev ())); } catch (Exception e ) {} finally { buf .append (", " ); }
290- buf .append ("size=" ).append (sizeInternal ()).append (", " );
291- try { buf .append ("blksize=" ).append (stat .blockSize ()); } catch (Exception e ) {} finally { buf .append (", " ); }
292- try { buf .append ("blocks=" ).append (stat .blocks ()); } catch (Exception e ) {} finally { buf .append (", " ); }
293-
294- buf .append ("atime=" ).append (atime ()).append (", " );
295- buf .append ("mtime=" ).append (mtime ()).append (", " );
296- buf .append ("ctime=" ).append (ctime ());
302+ if (stat == null ) {
303+ buf .append (": uninitialized" );
304+ } else {
305+ buf .append (" " );
306+ // FIXME: Obvious issue that not all platforms can display all attributes. Ugly hacks.
307+ // Using generic posix library makes pushing inspect behavior into specific system impls
308+ // rather painful.
309+ try { buf .append ("dev=0x" ).append (Long .toHexString (stat .dev ())); } catch (Exception e ) {} finally { buf .append (", " ); }
310+ try { buf .append ("ino=" ).append (stat .ino ()); } catch (Exception e ) {} finally { buf .append (", " ); }
311+ buf .append ("mode=0" ).append (Integer .toOctalString (stat .mode ())).append (", " );
312+ try { buf .append ("nlink=" ).append (stat .nlink ()); } catch (Exception e ) {} finally { buf .append (", " ); }
313+ try { buf .append ("uid=" ).append (stat .uid ()); } catch (Exception e ) {} finally { buf .append (", " ); }
314+ try { buf .append ("gid=" ).append (stat .gid ()); } catch (Exception e ) {} finally { buf .append (", " ); }
315+ try { buf .append ("rdev=0x" ).append (Long .toHexString (stat .rdev ())); } catch (Exception e ) {} finally { buf .append (", " ); }
316+ buf .append ("size=" ).append (sizeInternal ()).append (", " );
317+ try { buf .append ("blksize=" ).append (stat .blockSize ()); } catch (Exception e ) {} finally { buf .append (", " ); }
318+ try { buf .append ("blocks=" ).append (stat .blocks ()); } catch (Exception e ) {} finally { buf .append (", " ); }
319+
320+ buf .append ("atime=" ).append (atime ()).append (", " );
321+ buf .append ("mtime=" ).append (mtime ()).append (", " );
322+ buf .append ("ctime=" ).append (ctime ());
323+ }
297324 buf .append (">" );
298325
299326 return getRuntime ().newString (buf .toString ());
300327 }
301328
302329 @ JRubyMethod (name = "uid" )
303330 public IRubyObject uid () {
331+ checkInitialized ();
304332 return getRuntime ().newFixnum (stat .uid ());
305333 }
306334
307335 @ JRubyMethod (name = "mode" )
308336 public IRubyObject mode () {
337+ checkInitialized ();
309338 return getRuntime ().newFixnum (stat .mode ());
310339 }
311340
312341 @ JRubyMethod (name = "mtime" )
313342 public IRubyObject mtime () {
343+ checkInitialized ();
314344 return getRuntime ().newTime (stat .mtime () * 1000 );
315345 }
316346
@@ -328,55 +358,66 @@ public IRubyObject mtimeLessThan(IRubyObject other) {
328358
329359 @ JRubyMethod (name = "nlink" )
330360 public IRubyObject nlink () {
361+ checkInitialized ();
331362 return getRuntime ().newFixnum (stat .nlink ());
332363 }
333364
334365 @ JRubyMethod (name = "owned?" )
335366 public IRubyObject owned_p () {
367+ checkInitialized ();
336368 return getRuntime ().newBoolean (stat .isOwned ());
337369 }
338370
339371 @ JRubyMethod (name = "pipe?" )
340372 public IRubyObject pipe_p () {
373+ checkInitialized ();
341374 return getRuntime ().newBoolean (stat .isNamedPipe ());
342375 }
343376
344377 @ JRubyMethod (name = "rdev" )
345378 public IRubyObject rdev () {
379+ checkInitialized ();
346380 return getRuntime ().newFixnum (stat .rdev ());
347381 }
348382
349383 @ JRubyMethod (name = "rdev_major" )
350384 public IRubyObject rdevMajor () {
385+ checkInitialized ();
351386 return getRuntime ().newFixnum (stat .major (stat .rdev ()));
352387 }
353388
354389 @ JRubyMethod (name = "rdev_minor" )
355390 public IRubyObject rdevMinor () {
391+ checkInitialized ();
356392 return getRuntime ().newFixnum (stat .minor (stat .rdev ()));
357393 }
358394
359395 @ JRubyMethod (name = "readable?" )
360396 public IRubyObject readable_p () {
397+ checkInitialized ();
361398 return getRuntime ().newBoolean (stat .isReadable ());
362399 }
363400
364401 @ JRubyMethod (name = "readable_real?" )
365402 public IRubyObject readableReal_p () {
403+ checkInitialized ();
366404 return getRuntime ().newBoolean (stat .isReadableReal ());
367405 }
368406
369407 @ JRubyMethod (name = "setgid?" )
370408 public IRubyObject setgid_p () {
409+ checkInitialized ();
371410 return getRuntime ().newBoolean (stat .isSetgid ());
372411 }
373412
374413 @ JRubyMethod (name = "setuid?" )
375414 public IRubyObject setuid_p () {
415+ checkInitialized ();
376416 return getRuntime ().newBoolean (stat .isSetuid ());
377417 }
378418
379419 private long sizeInternal () {
420+ checkInitialized ();
380421 // Workaround for JRUBY-4149
381422 if (Platform .IS_WINDOWS && file != null ) {
382423 try {
@@ -405,11 +446,13 @@ public IRubyObject size_p() {
405446
406447 @ JRubyMethod (name = "socket?" )
407448 public IRubyObject socket_p () {
449+ checkInitialized ();
408450 return getRuntime ().newBoolean (stat .isSocket ());
409451 }
410452
411453 @ JRubyMethod (name = "sticky?" )
412454 public IRubyObject sticky_p () {
455+ checkInitialized ();
413456 Ruby runtime = getRuntime ();
414457
415458 if (runtime .getPosix ().isNative ()) {
@@ -421,21 +464,25 @@ public IRubyObject sticky_p() {
421464
422465 @ JRubyMethod (name = "symlink?" )
423466 public IRubyObject symlink_p () {
467+ checkInitialized ();
424468 return getRuntime ().newBoolean (stat .isSymlink ());
425469 }
426470
427471 @ JRubyMethod (name = "writable?" )
428472 public IRubyObject writable_p () {
473+ checkInitialized ();
429474 return getRuntime ().newBoolean (stat .isWritable ());
430475 }
431476
432477 @ JRubyMethod (name = "writable_real?" )
433478 public IRubyObject writableReal_p () {
479+ checkInitialized ();
434480 return getRuntime ().newBoolean (stat .isWritableReal ());
435481 }
436482
437483 @ JRubyMethod (name = "zero?" )
438484 public IRubyObject zero_p () {
485+ checkInitialized ();
439486 return getRuntime ().newBoolean (stat .isEmpty ());
440487 }
441488
@@ -450,6 +497,7 @@ public IRubyObject worldWritable(ThreadContext context) {
450497 }
451498
452499 private IRubyObject getWorldMode (ThreadContext context , int mode ) {
500+ checkInitialized ();
453501 if ((stat .mode () & mode ) == mode ) {
454502 return RubyNumeric .int2fix (context .runtime ,
455503 (stat .mode () & (S_IRUGO | S_IWUGO | S_IXUGO ) ));
0 commit comments