Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: a275c6acb556
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: b24e190bf650
Choose a head ref
  • 2 commits
  • 3 files changed
  • 1 contributor

Commits on Apr 16, 2015

  1. Copy the full SHA
    2cf023b View commit details
  2. Copy the full SHA
    b24e190 View commit details
10 changes: 9 additions & 1 deletion core/src/main/java/org/jruby/util/JRubyFile.java
Original file line number Diff line number Diff line change
@@ -76,8 +76,16 @@ public static FileResource createResource(Ruby runtime, String cwd, String pathn
FileResource jarResource = JarResource.create(pathname);
if (jarResource != null) return jarResource;

if (Platform.IS_WINDOWS &&
(pathname.equalsIgnoreCase("nul") || pathname.equalsIgnoreCase("nul:"))) {
return new NullDeviceResource(runtime.getPosix());
}

if (pathname.contains(":")) { // scheme-oriented resources
pathname = pathname.replace("classpath:/", "uri:classloader:/");
if (pathname.startsWith("classpath:")) {
pathname = pathname.replace("classpath:/", "uri:classloader:/");
}

// replace is needed for maven/jruby-complete/src/it/app_using_classpath_uri to work
if (pathname.startsWith("uri:")) return URLResource.create(runtime, pathname);

163 changes: 163 additions & 0 deletions core/src/main/java/org/jruby/util/NullDeviceResource.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
package org.jruby.util;

import jnr.posix.FileStat;
import jnr.posix.POSIX;
import org.jruby.util.io.ModeFlags;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.nio.channels.Channel;
import java.nio.channels.FileChannel;

/**
* Represents a the NUL: device on Windows, which is not a normal file.
*/
class NullDeviceResource extends AbstractFileResource {
private static final JRubyFile file = new JRubyFile("NUL:");
private final POSIX posix;

NullDeviceResource(POSIX posix) {
this.posix = posix;
}

@Override
public String absolutePath() {
return "NUL:";
}

@Override
public String canonicalPath() {
return "NUL:";
}

@Override
public long length() {
return 0;
}

@Override
public long lastModified() {
return 0;
}

@Override
public boolean exists() {
return true;
}

@Override
public boolean canExecute() {
return false;
}

public int errno() {
return posix.errno();
}

@Override
public boolean isFile() {
return true;
}

@Override
public boolean isDirectory() {
return false;
}

@Override
public boolean isSymLink() {
return false;
}

@Override
public boolean canRead() {
return true;
}

@Override
public boolean canWrite() {
return true;
}

@Override
public String[] list() {
return null;
}

@Override
public FileStat stat() {
return null;
}

@Override
public FileStat lstat() {
return null;
}

@Override
public String toString() {
return "NUL:";
}

@Override
public JRubyFile hackyGetJRubyFile() {
return file;
}

@Override
InputStream openInputStream() throws IOException {
return new FileInputStream(file);
}

@Override
public Channel openChannel(ModeFlags flags, int perm) throws ResourceException {
return createChannel(flags);
}

private Channel createChannel(ModeFlags flags) throws ResourceException {
FileChannel fileChannel;

/* Because RandomAccessFile does not provide a way to pass append
* mode, we must manually seek if using RAF. FileOutputStream,
* however, does properly honor append mode at the lowest levels,
* reducing append write costs when we're only doing writes.
*
* The code here will use a FileOutputStream if we're only writing,
* setting isInAppendMode to true to disable our manual seeking.
*
* RandomAccessFile does not handle append for us, so if we must
* also be readable we pass false for isInAppendMode to indicate
* we need manual seeking.
*/
try{
if (flags.isWritable() && !flags.isReadable()) {
FileOutputStream fos = new FileOutputStream(file, flags.isAppendable());
fileChannel = fos.getChannel();
} else {
RandomAccessFile raf = new RandomAccessFile(file, flags.toJavaModeString());
fileChannel = raf.getChannel();
}
} catch (FileNotFoundException fnfe) {
// Jave throws FileNotFoundException both if the file doesn't exist or there were
// permission issues, but Ruby needs to disambiguate those two cases
throw file.exists() ?
new ResourceException.PermissionDenied(absolutePath()) :
new ResourceException.NotFound(absolutePath());
} catch (IOException ioe) {
throw new ResourceException.IOError(ioe);
}

try {
if (flags.isTruncate()) fileChannel.truncate(0);
} catch (IOException ioe) {
// ignore; it's a pipe or fifo that can't be truncated (we only care about illegal seek).
if (!ioe.getMessage().equals("Illegal seek")) throw new ResourceException.IOError(ioe);
}

return fileChannel;
}
}
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/util/io/PosixShim.java
Original file line number Diff line number Diff line change
@@ -395,7 +395,7 @@ public Channel open(String cwd, String path, ModeFlags flags, int perm) {

public Channel open(String cwd, String path, ModeFlags flags, int perm, ClassLoader classLoader) {
if ((path.equals("/dev/null") || path.equalsIgnoreCase("nul")) && Platform.IS_WINDOWS) {
path = "nul:";
path = "NUL:";
}

if (path.startsWith("classpath:/") && classLoader != null) {