Skip to content

Commit

Permalink
Merge pull request jruby#2572 from lumeet/uninitialized_file_stat_jru…
Browse files Browse the repository at this point in the history
…by-1_7

Fix uninitialized usage of File::Stat on jruby-1_7
  • Loading branch information
enebo committed Feb 6, 2015
2 parents d827ef2 + fd0cdff commit b6f907f
Showing 1 changed file with 65 additions and 18 deletions.
83 changes: 65 additions & 18 deletions core/src/main/java/org/jruby/RubyFileStat.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ public class RubyFileStat extends RubyObject {
private FileResource file;
private FileStat stat;

private void checkInitialized() {
if (stat == null) throw getRuntime().newTypeError("uninitialized File::Stat");
}

private static ObjectAllocator ALLOCATOR = new ObjectAllocator() {
public IRubyObject allocate(Ruby runtime, RubyClass klass) {
return new RubyFileStat(runtime, klass);
Expand Down Expand Up @@ -134,31 +138,37 @@ public IRubyObject initialize19(IRubyObject fname, Block unusedBlock) {

@JRubyMethod(name = "atime")
public IRubyObject atime() {
checkInitialized();
return getRuntime().newTime(stat.atime() * 1000);
}

@JRubyMethod(name = "blksize")
public RubyFixnum blksize() {
checkInitialized();
return getRuntime().newFixnum(stat.blockSize());
}

@JRubyMethod(name = "blockdev?")
public IRubyObject blockdev_p() {
checkInitialized();
return getRuntime().newBoolean(stat.isBlockDev());
}

@JRubyMethod(name = "blocks")
public IRubyObject blocks() {
checkInitialized();
return getRuntime().newFixnum(stat.blocks());
}

@JRubyMethod(name = "chardev?")
public IRubyObject chardev_p() {
checkInitialized();
return getRuntime().newBoolean(stat.isCharDev());
}

@JRubyMethod(name = "<=>", required = 1)
public IRubyObject cmp(IRubyObject other) {
checkInitialized();
if (!(other instanceof RubyFileStat)) return getRuntime().getNil();

long time1 = stat.mtime();
Expand All @@ -175,56 +185,67 @@ public IRubyObject cmp(IRubyObject other) {

@JRubyMethod(name = "ctime")
public IRubyObject ctime() {
checkInitialized();
return getRuntime().newTime(stat.ctime() * 1000);
}

@JRubyMethod(name = "dev")
public IRubyObject dev() {
checkInitialized();
return getRuntime().newFixnum(stat.dev());
}

@JRubyMethod(name = "dev_major")
public IRubyObject devMajor() {
checkInitialized();
return getRuntime().newFixnum(stat.major(stat.dev()));
}

@JRubyMethod(name = "dev_minor")
public IRubyObject devMinor() {
checkInitialized();
return getRuntime().newFixnum(stat.minor(stat.dev()));
}

@JRubyMethod(name = "directory?")
public RubyBoolean directory_p() {
checkInitialized();
return getRuntime().newBoolean(stat.isDirectory());
}

@JRubyMethod(name = "executable?")
public IRubyObject executable_p() {
checkInitialized();
return getRuntime().newBoolean(stat.isExecutable());
}

@JRubyMethod(name = "executable_real?")
public IRubyObject executableReal_p() {
checkInitialized();
return getRuntime().newBoolean(stat.isExecutableReal());
}

@JRubyMethod(name = "file?")
public RubyBoolean file_p() {
checkInitialized();
return getRuntime().newBoolean(stat.isFile());
}

@JRubyMethod(name = "ftype")
public RubyString ftype() {
checkInitialized();
return getRuntime().newString(stat.ftype());
}

@JRubyMethod(name = "gid")
public IRubyObject gid() {
checkInitialized();
return getRuntime().newFixnum(stat.gid());
}

@JRubyMethod(name = "grpowned?")
public IRubyObject group_owned_p() {
checkInitialized();
return getRuntime().newBoolean(stat.isGroupOwned());
}

Expand All @@ -244,48 +265,56 @@ public IRubyObject initialize_copy(IRubyObject original) {

@JRubyMethod(name = "ino")
public IRubyObject ino() {
checkInitialized();
return getRuntime().newFixnum(stat.ino());
}

@JRubyMethod(name = "inspect")
public IRubyObject inspect() {
StringBuilder buf = new StringBuilder("#<");
buf.append(getMetaClass().getRealClass().getName());
buf.append(" ");
// FIXME: Obvious issue that not all platforms can display all attributes. Ugly hacks.
// Using generic posix library makes pushing inspect behavior into specific system impls
// rather painful.
try { buf.append("dev=0x").append(Long.toHexString(stat.dev())); } catch (Exception e) {} finally { buf.append(", "); }
try { buf.append("ino=").append(stat.ino()); } catch (Exception e) {} finally { buf.append(", "); }
buf.append("mode=0").append(Integer.toOctalString(stat.mode())).append(", ");
try { buf.append("nlink=").append(stat.nlink()); } catch (Exception e) {} finally { buf.append(", "); }
try { buf.append("uid=").append(stat.uid()); } catch (Exception e) {} finally { buf.append(", "); }
try { buf.append("gid=").append(stat.gid()); } catch (Exception e) {} finally { buf.append(", "); }
try { buf.append("rdev=0x").append(Long.toHexString(stat.rdev())); } catch (Exception e) {} finally { buf.append(", "); }
buf.append("size=").append(sizeInternal()).append(", ");
try { buf.append("blksize=").append(stat.blockSize()); } catch (Exception e) {} finally { buf.append(", "); }
try { buf.append("blocks=").append(stat.blocks()); } catch (Exception e) {} finally { buf.append(", "); }

buf.append("atime=").append(atime()).append(", ");
buf.append("mtime=").append(mtime()).append(", ");
buf.append("ctime=").append(ctime());
if (stat == null) {
buf.append(": uninitialized");
} else {
buf.append(" ");
// FIXME: Obvious issue that not all platforms can display all attributes. Ugly hacks.
// Using generic posix library makes pushing inspect behavior into specific system impls
// rather painful.
try { buf.append("dev=0x").append(Long.toHexString(stat.dev())); } catch (Exception e) {} finally { buf.append(", "); }
try { buf.append("ino=").append(stat.ino()); } catch (Exception e) {} finally { buf.append(", "); }
buf.append("mode=0").append(Integer.toOctalString(stat.mode())).append(", ");
try { buf.append("nlink=").append(stat.nlink()); } catch (Exception e) {} finally { buf.append(", "); }
try { buf.append("uid=").append(stat.uid()); } catch (Exception e) {} finally { buf.append(", "); }
try { buf.append("gid=").append(stat.gid()); } catch (Exception e) {} finally { buf.append(", "); }
try { buf.append("rdev=0x").append(Long.toHexString(stat.rdev())); } catch (Exception e) {} finally { buf.append(", "); }
buf.append("size=").append(sizeInternal()).append(", ");
try { buf.append("blksize=").append(stat.blockSize()); } catch (Exception e) {} finally { buf.append(", "); }
try { buf.append("blocks=").append(stat.blocks()); } catch (Exception e) {} finally { buf.append(", "); }

buf.append("atime=").append(atime()).append(", ");
buf.append("mtime=").append(mtime()).append(", ");
buf.append("ctime=").append(ctime());
}
buf.append(">");

return getRuntime().newString(buf.toString());
}

@JRubyMethod(name = "uid")
public IRubyObject uid() {
checkInitialized();
return getRuntime().newFixnum(stat.uid());
}

@JRubyMethod(name = "mode")
public IRubyObject mode() {
checkInitialized();
return getRuntime().newFixnum(stat.mode());
}

@JRubyMethod(name = "mtime")
public IRubyObject mtime() {
checkInitialized();
return getRuntime().newTime(stat.mtime() * 1000);
}

Expand All @@ -303,55 +332,66 @@ public IRubyObject mtimeLessThan(IRubyObject other) {

@JRubyMethod(name = "nlink")
public IRubyObject nlink() {
checkInitialized();
return getRuntime().newFixnum(stat.nlink());
}

@JRubyMethod(name = "owned?")
public IRubyObject owned_p() {
checkInitialized();
return getRuntime().newBoolean(stat.isOwned());
}

@JRubyMethod(name = "pipe?")
public IRubyObject pipe_p() {
checkInitialized();
return getRuntime().newBoolean(stat.isNamedPipe());
}

@JRubyMethod(name = "rdev")
public IRubyObject rdev() {
checkInitialized();
return getRuntime().newFixnum(stat.rdev());
}

@JRubyMethod(name = "rdev_major")
public IRubyObject rdevMajor() {
checkInitialized();
return getRuntime().newFixnum(stat.major(stat.rdev()));
}

@JRubyMethod(name = "rdev_minor")
public IRubyObject rdevMinor() {
checkInitialized();
return getRuntime().newFixnum(stat.minor(stat.rdev()));
}

@JRubyMethod(name = "readable?")
public IRubyObject readable_p() {
checkInitialized();
return getRuntime().newBoolean(stat.isReadable());
}

@JRubyMethod(name = "readable_real?")
public IRubyObject readableReal_p() {
checkInitialized();
return getRuntime().newBoolean(stat.isReadableReal());
}

@JRubyMethod(name = "setgid?")
public IRubyObject setgid_p() {
checkInitialized();
return getRuntime().newBoolean(stat.isSetgid());
}

@JRubyMethod(name = "setuid?")
public IRubyObject setuid_p() {
checkInitialized();
return getRuntime().newBoolean(stat.isSetuid());
}

private long sizeInternal() {
checkInitialized();
// Workaround for JRUBY-4149
if (Platform.IS_WINDOWS && file != null) {
try {
Expand Down Expand Up @@ -380,11 +420,13 @@ public IRubyObject size_p() {

@JRubyMethod(name = "socket?")
public IRubyObject socket_p() {
checkInitialized();
return getRuntime().newBoolean(stat.isSocket());
}

@JRubyMethod(name = "sticky?")
public IRubyObject sticky_p() {
checkInitialized();
Ruby runtime = getRuntime();

if (runtime.getPosix().isNative()) {
Expand All @@ -396,21 +438,25 @@ public IRubyObject sticky_p() {

@JRubyMethod(name = "symlink?")
public IRubyObject symlink_p() {
checkInitialized();
return getRuntime().newBoolean(stat.isSymlink());
}

@JRubyMethod(name = "writable?")
public IRubyObject writable_p() {
checkInitialized();
return getRuntime().newBoolean(stat.isWritable());
}

@JRubyMethod(name = "writable_real?")
public IRubyObject writableReal_p() {
checkInitialized();
return getRuntime().newBoolean(stat.isWritableReal());
}

@JRubyMethod(name = "zero?")
public IRubyObject zero_p() {
checkInitialized();
return getRuntime().newBoolean(stat.isEmpty());
}

Expand All @@ -425,6 +471,7 @@ public IRubyObject worldWritable(ThreadContext context) {
}

private IRubyObject getWorldMode(ThreadContext context, int mode) {
checkInitialized();
if ((stat.mode() & mode) == mode) {
return RubyNumeric.int2fix(context.runtime,
(stat.mode() & (S_IRUGO | S_IWUGO | S_IXUGO) ));
Expand Down

0 comments on commit b6f907f

Please sign in to comment.