Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   /*
    ***** BEGIN LICENSE BLOCK *****
    * Version: EPL 1.0/GPL 2.0/LGPL 2.1
    *
    * The contents of this file are subject to the Eclipse Public
    * License Version 1.0 (the "License"); you may not use this file
    * except in compliance with the License. You may obtain a copy of
    * the License at http://www.eclipse.org/legal/epl-v10.html
    *
   * Software distributed under the License is distributed on an "AS
   * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
   * implied. See the License for the specific language governing
   * rights and limitations under the License.
   *
   * Copyright (C) 2002 Benoit Cerrina <b.cerrina@wanadoo.fr>
   * Copyright (C) 2002-2004 Jan Arne Petersen <jpetersen@uni-bonn.de>
   * Copyright (C) 2002-2004 Anders Bengtsson <ndrsbngtssn@yahoo.se>
   * Copyright (C) 2003 Joey Gibson <joey@joeygibson.com>
   * Copyright (C) 2004-2007 Thomas E Enebo <enebo@acm.org>
   * Copyright (C) 2004-2007 Charles O Nutter <headius@headius.com>
   * Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de>
   * Copyright (C) 2006 Miguel Covarrubias <mlcovarrubias@gmail.com>
   * 
   * Alternatively, the contents of this file may be used under the terms of
   * either of the GNU General Public License Version 2 or later (the "GPL"),
   * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
   * in which case the provisions of the GPL or the LGPL are applicable instead
   * of those above. If you wish to allow use of your version of this file only
   * under the terms of either the GPL or the LGPL, and not to allow others to
   * use your version of this file under the terms of the EPL, indicate your
   * decision by deleting the provisions above and replace them with the notice
   * and other provisions required by the GPL or the LGPL. If you do not delete
   * the provisions above, a recipient may use your version of this file under
   * the terms of any one of the EPL, the GPL or the LGPL.
   ***** END LICENSE BLOCK *****/
  package org.jruby;
  
  import java.io.File;
  import java.io.Reader;
  import java.net.URI;
  import java.net.URL;
  
  import static org.jruby.runtime.Visibility.*;
  import static org.jruby.CompatVersion.*;
Ruby File class equivalent in java.
  
 @JRubyClass(name="File", parent="IO", include="FileTest")
 public class RubyFile extends RubyIO implements EncodingCapable {
     public static RubyClass createFileClass(Ruby runtime) {
         ThreadContext context = runtime.getCurrentContext();
 
         RubyClass fileClass = runtime.defineClass("File"runtime.getIO(), );
 
         runtime.setFile(fileClass);
 
         fileClass.defineAnnotatedMethods(RubyFile.class);
 
         fileClass.index = .;
         fileClass.setReifiedClass(RubyFile.class);
 
         fileClass.kindOf = new RubyModule.JavaClassKindOf(RubyFile.class);
 
         // file separator constants
         RubyString separator = runtime.newString("/");
         separator.freeze(context);
         fileClass.defineConstant("SEPARATOR"separator);
         fileClass.defineConstant("Separator"separator);
 
         if (. == '\\') {
             RubyString altSeparator = runtime.newString("\\");
             altSeparator.freeze(context);
             fileClass.defineConstant("ALT_SEPARATOR"altSeparator);
         } else {
             fileClass.defineConstant("ALT_SEPARATOR"runtime.getNil());
         }
 
         // path separator
         RubyString pathSeparator = runtime.newString(.);
         pathSeparator.freeze(context);
         fileClass.defineConstant("PATH_SEPARATOR"pathSeparator);
 
         // For JRUBY-5276, physically define FileTest methods on File's singleton
 
         // Create Constants class
         RubyModule constants = fileClass.defineModuleUnder("Constants");
 
         // open flags
         for (OpenFlags f : OpenFlags.values()) {
             // Strip off the O_ prefix, so they become File::RDONLY, and so on
             final String name = f.name();
             if (name.startsWith("O_")) {
                 final String cname = name.substring(2);
                 // Special case for handling ACCMODE, since constantine will generate
                 // an invalid value if it is not defined by the platform.
                 final RubyFixnum cvalue = f == .
                         ? runtime.newFixnum(.)
                         : runtime.newFixnum(f.intValue());
                 constants.setConstant(cnamecvalue);
             }
         }
 
         // case handling, escaping, path and dot matching
         constants.setConstant("FNM_NOESCAPE"runtime.newFixnum());
         constants.setConstant("FNM_CASEFOLD"runtime.newFixnum());
         constants.setConstant("FNM_SYSCASE"runtime.newFixnum());
         constants.setConstant("FNM_DOTMATCH"runtime.newFixnum());
         constants.setConstant("FNM_PATHNAME"runtime.newFixnum());
 
         // flock operations
         constants.setConstant("LOCK_SH"runtime.newFixnum(.));
         constants.setConstant("LOCK_EX"runtime.newFixnum(.));
         constants.setConstant("LOCK_NB"runtime.newFixnum(.));
         constants.setConstant("LOCK_UN"runtime.newFixnum(.));
         
         // NULL device
         if (runtime.is1_9() || runtime.is2_0()) {
             constants.setConstant("NULL"runtime.newString(getNullDevice()));
         }
 
         // File::Constants module is included in IO.
         runtime.getIO().includeModule(constants);
 
         return fileClass;
     }
 
     private static ObjectAllocator FILE_ALLOCATOR = new ObjectAllocator() {
         @Override
         public IRubyObject allocate(Ruby runtimeRubyClass klass) {
             RubyFile instance = new RubyFile(runtimeklass);
 
             instance.setMetaClass(klass);
 
             return instance;
         }
     };
 
     private static String getNullDevice() {
         // FIXME: MRI defines special null device for Amiga and VMS, but currently
         // we lack ability to detect these platforms
         String null_device;
         if (.) {
             null_device = "NUL";
         } else {
             null_device = "/dev/null";
         }
         return null_device;
     }
 
     public RubyFile(Ruby runtimeRubyClass type) {
         super(runtimetype);
     }
 
     // XXX This constructor is a hack to implement the __END__ syntax.
     //     Converting a reader back into an InputStream doesn't generally work.
     public RubyFile(Ruby runtimeString pathfinal Reader reader) {
         this(runtimepathnew InputStream() {
             @Override
             public int read() throws IOException {
                 return reader.read();
             }
         });
     }
 
     public RubyFile(Ruby runtimeString pathInputStream in) {
         super(runtimeruntime.getFile());
         MakeOpenFile();
         this. = path;
         try {
             this..setMainStream(ChannelStream.open(runtimenew ChannelDescriptor(Channels.newChannel(in))));
         } catch (BadDescriptorException e) {
             throw runtime.newErrnoEBADFError();
         } catch (InvalidValueException ex) {
             throw runtime.newErrnoEINVALError();
         }
     }
     
     @Override
     protected IRubyObject ioClose(Ruby runtime) {
         // Make sure any existing lock is released before we try and close the file
         if ( != null) {
             try {
                 .release();
             } catch (IOException e) {
                 throw getRuntime().newIOError(e.getMessage());
             }
         }
         return super.ioClose(runtime);
     }
 
     @JRubyMethod(required = 1)
     public IRubyObject flock(ThreadContext contextIRubyObject lockingConstant) {
         Ruby runtime = context.runtime;
         
         // TODO: port exact behavior from MRI, and move most locking logic into ChannelDescriptor
         // TODO: for all LOCK_NB cases, return false if they would block
         ChannelDescriptor descriptor;
         try {
             descriptor = .getMainStreamSafe().getDescriptor();
         } catch (BadDescriptorException e) {
             throw context.runtime.newErrnoEBADFError();
         }
 
         // null channel always succeeds for all locking operations
         if (descriptor.isNull()) return RubyFixnum.zero(runtime);
         
         int lockMode = RubyNumeric.num2int(lockingConstant);
         
         Channel channel = descriptor.getChannel();
         
         FileDescriptor fd = ChannelDescriptor.getDescriptorFromChannel(channel);
         int real_fd = JavaLibCHelper.getfdFromDescriptor(fd);
         
         if (real_fd != -1) {
             // we have a real fd...try native flocking
             try {
                 int result = runtime.getPosix().flock(real_fdlockMode);
                 if (result < 0) {
                     return runtime.getFalse();
                 }
                 return RubyFixnum.zero(runtime);
             } catch (RaiseException re) {
                 if (re.getException().getMetaClass() == runtime.getNotImplementedError()) {
                     // not implemented, probably pure Java; fall through
                 } else {
                     throw re;
                 }
             }
         }
 
         if (descriptor.getChannel() instanceof FileChannel) {
             FileChannel fileChannel = (FileChannel)descriptor.getChannel();
 
             checkSharedExclusive(runtimelockMode);
     
             if (!lockStateChanges(lockMode)) return RubyFixnum.zero(runtime);
 
             try {
                 synchronized (fileChannel) {
                     // check again, to avoid unnecessary overhead
                     if (!lockStateChanges(lockMode)) return RubyFixnum.zero(runtime);
                     
                     switch (lockMode) {
                         case :
                         case  | :
                             return unlock(runtime);
                         case :
                             return lock(runtimefileChanneltrue);
                         case  | :
                             return tryLock(runtimefileChanneltrue);
                         case :
                             return lock(runtimefileChannelfalse);
                         case  | :
                             return tryLock(runtimefileChannelfalse);
                     }
                 }
             } catch (IOException ioe) {
                 if (runtime.getDebug().isTrue()) {
                     ioe.printStackTrace(.);
                 }
             } catch (OverlappingFileLockException ioe) {
                 if (runtime.getDebug().isTrue()) {
                     ioe.printStackTrace(.);
                 }
             }
             return lockFailedReturn(runtimelockMode);
         } else {
             // We're not actually a real file, so we can't flock
             return runtime.getFalse();
         }
     }
 
     @JRubyMethod(required = 1, optional = 2, visibility = , compat = )
     @Override
     public IRubyObject initialize(IRubyObject[] argsBlock block) {
         if ( != null) {
             throw getRuntime().newRuntimeError("reinitializing File");
         }
         
         if (args.length > 0 && args.length < 3) {
             if (args[0] instanceof RubyInteger) {
                 return super.initialize(argsblock);
             }
         }
 
         return openFile(args);
     }
 
     @JRubyMethod(name = "initialize", required = 1, optional = 2, visibility = , compat = )
     public IRubyObject initialize19(ThreadContext contextIRubyObject[] argsBlock block) {
         if ( != null) {
             throw context.runtime.newRuntimeError("reinitializing File");
         }
 
         if (args.length > 0 && args.length <= 3) {
             IRubyObject fd = TypeConverter.convertToTypeWithCheck(args[0], context.runtime.getFixnum(), "to_int");
             if (!fd.isNil()) {
                 if (args.length == 1) {
                     return super.initialize19(contextfdblock);
                 } else if (args.length == 2) {
                     return super.initialize19(context, fd, args[1], block);
                 }
                 return super.initialize19(context, fd, args[1], args[2], block);
             }
         }
 
         return openFile19(contextargs);
     }
 
     @JRubyMethod(required = 1)
     public IRubyObject chmod(ThreadContext contextIRubyObject arg) {
         checkClosed(context);
         int mode = (intarg.convertToInteger().getLongValue();
 
         if (!new File().exists()) {
             throw context.runtime.newErrnoENOENTError();
         }
 
         return context.runtime.newFixnum(context.runtime.getPosix().chmod(mode));
     }
 
     @JRubyMethod(required = 2)
     public IRubyObject chown(ThreadContext contextIRubyObject arg1IRubyObject arg2) {
         checkClosed(context);
         int owner = -1;
         if (!arg1.isNil()) {
             owner = RubyNumeric.num2int(arg1);
         }
 
         int group = -1;
         if (!arg2.isNil()) {
             group = RubyNumeric.num2int(arg2);
         }
 
         if (!new File().exists()) {
             throw context.runtime.newErrnoENOENTError();
         }
 
         return context.runtime.newFixnum(context.runtime.getPosix().chown(ownergroup));
     }
 
     @JRubyMethod
     public IRubyObject atime(ThreadContext context) {
         checkClosed(context);
         return context.runtime.newFileStat(false).atime();
     }
 
     @JRubyMethod
     public IRubyObject ctime(ThreadContext context) {
         checkClosed(context);
         return context.runtime.newFileStat(false).ctime();
     }
 
     @JRubyMethod(required = 1)
     public IRubyObject lchmod(ThreadContext contextIRubyObject arg) {
         int mode = (intarg.convertToInteger().getLongValue();
 
         if (!new File().exists()) {
             throw context.runtime.newErrnoENOENTError();
         }
 
         return context.runtime.newFixnum(context.runtime.getPosix().lchmod(mode));
     }
 
     // TODO: this method is not present in MRI!
     @JRubyMethod(required = 2)
     public IRubyObject lchown(ThreadContext contextIRubyObject arg1IRubyObject arg2) {
         int owner = -1;
         if (!arg1.isNil()) {
             owner = RubyNumeric.num2int(arg1);
         }
 
         int group = -1;
         if (!arg2.isNil()) {
             group = RubyNumeric.num2int(arg2);
         }
 
         if (!new File().exists()) {
             throw context.runtime.newErrnoENOENTError();
         }
 
         return context.runtime.newFixnum(context.runtime.getPosix().lchown(ownergroup));
     }
 
     @JRubyMethod
     public IRubyObject lstat(ThreadContext context) {
         checkClosed(context);
         return context.runtime.newFileStat(true);
     }
     
     @JRubyMethod
     public IRubyObject mtime(ThreadContext context) {
         checkClosed(context);
         return context.runtime.newFileStat(false).mtime();
     }
 
     @JRubyMethod(meta = true, compat = )
     public static IRubyObject path(ThreadContext contextIRubyObject selfIRubyObject str) {
         return get_path(contextstr);
     }
 
     @JRubyMethod(name = {"path""to_path"})
     public IRubyObject path(ThreadContext context) {
         IRubyObject newPath = context.runtime.getNil();
         if ( != null) {
             newPath = context.runtime.newString();
             newPath.setTaint(true);
         }
         return newPath;
     }
 
     @JRubyMethod
     @Override
     public IRubyObject stat(ThreadContext context) {
         checkClosed(context);
         return context.runtime.newFileStat(false);
     }
 
     @JRubyMethod(required = 1)
     public IRubyObject truncate(ThreadContext contextIRubyObject arg) {
         RubyInteger newLength = arg.convertToInteger();
         if (newLength.getLongValue() < 0) {
             throw context.runtime.newErrnoEINVALError();
         }
         try {
             .checkWritable(context.runtime);
             .getMainStreamSafe().ftruncate(newLength.getLongValue());
         } catch (BadDescriptorException e) {
             throw context.runtime.newErrnoEBADFError();
         } catch (PipeException e) {
             throw context.runtime.newErrnoESPIPEError();
         } catch (InvalidValueException ex) {
             throw context.runtime.newErrnoEINVALError();
         } catch (IOException e) {
             // Should we do anything?
         }
 
         return RubyFixnum.zero(context.runtime);
     }
 
     @JRubyMethod
     @Override
     public IRubyObject inspect() {
         StringBuilder val = new StringBuilder();
         val.append("#<File:").append();
         if(!.isOpen()) {
             val.append(" (closed)");
         }
         val.append(">");
         return getRuntime().newString(val.toString());
     }
     
     /* File class methods */
     
     @JRubyMethod(required = 1, optional = 1, meta = true)
     public static IRubyObject basename(ThreadContext contextIRubyObject recvIRubyObject[] args) {
         String name = get_path(context,args[0]).getUnicodeValue();
 
         // MRI-compatible basename handling for windows drive letter paths
         if (.) {
             if (name.length() > 1 && name.charAt(1) == ':' && Character.isLetter(name.charAt(0))) {
                 switch (name.length()) {
                 case 2:
                     return RubyString.newEmptyString(context.runtime).infectBy(args[0]);
                 case 3:
                     return context.runtime.newString(name.substring(2)).infectBy(args[0]);
                 default:
                     switch (name.charAt(2)) {
                     case '/':
                     case '\\':
                         break;
                     default:
                         // strip c: away from relative-pathed name
                         name = name.substring(2);
                         break;
                     }
                     break;
                 }
             }
         }
 
         while (name.length() > 1 && name.charAt(name.length() - 1) == '/') {
             name = name.substring(0, name.length() - 1);
         }
         
         // Paths which end in "/" or "\\" must be stripped off.
         int slashCount = 0;
         int length = name.length();
         for (int i = length - 1; i >= 0; i--) {
             char c = name.charAt(i);
             if (c != '/' && c != '\\') {
                 break;
             }
             slashCount++;
         }
         if (slashCount > 0 && length > 1) {
             name = name.substring(0, name.length() - slashCount);
         }
         
         int index = name.lastIndexOf('/');
         if (index == -1) {
             // XXX actually only on windows...
             index = name.lastIndexOf('\\');
         }
         
         if (!name.equals("/") && index != -1) {
             name = name.substring(index + 1);
         }
         
         if (args.length == 2) {
             String ext = RubyString.stringValue(args[1]).toString();
             if (".*".equals(ext)) {
                 index = name.lastIndexOf('.');
                 if (index > 0) {  // -1 no match; 0 it is dot file not extension
                     name = name.substring(0, index);
                 }
             } else if (name.endsWith(ext)) {
                 name = name.substring(0, name.length() - ext.length());
             }
         }
         return context.runtime.newString(name).infectBy(args[0]);
     }
 
     @JRubyMethod(required = 2, rest = true, meta = true)
     public static IRubyObject chmod(ThreadContext contextIRubyObject recvIRubyObject[] args) {
         Ruby runtime = context.runtime;
         
         int count = 0;
         RubyInteger mode = args[0].convertToInteger();
         for (int i = 1; i < args.lengthi++) {
             JRubyFile filename = file(args[i]);
             
             if (!filename.exists()) {
                 throw runtime.newErrnoENOENTError(filename.toString());
             }
             
             if (0 != runtime.getPosix().chmod(filename.getAbsolutePath(), (int)mode.getLongValue())) {
                 throw runtime.newErrnoFromLastPOSIXErrno();
             } else {
                 count++;
             }
         }
         
         return runtime.newFixnum(count);
     }
     
     @JRubyMethod(required = 3, rest = true, meta = true)
     public static IRubyObject chown(ThreadContext contextIRubyObject recvIRubyObject[] args) {
         Ruby runtime = context.runtime;
 
         int count = 0;
         int owner = -1;
         if (!args[0].isNil()) {
             owner = RubyNumeric.num2int(args[0]);
         }
 
         int group = -1;
         if (!args[1].isNil()) {
             group = RubyNumeric.num2int(args[1]);
         }
         for (int i = 2; i < args.lengthi++) {
             JRubyFile filename = file(args[i]);
 
             if (!filename.exists()) {
                 throw runtime.newErrnoENOENTError(filename.toString());
             }
             
             if (0 != runtime.getPosix().chown(filename.getAbsolutePath(), ownergroup)) {
                 throw runtime.newErrnoFromLastPOSIXErrno();
             } else {
                 count++;
             }
         }
         
         return runtime.newFixnum(count);
     }
 
     @JRubyMethod(required = 1, meta = true)
     public static IRubyObject dirname(ThreadContext contextIRubyObject recvIRubyObject arg) {
         RubyString filename = get_path(contextarg);
 
         String jfilename = filename.asJavaString();
 
         return context.runtime.newString(dirname(contextjfilename)).infectBy(filename);
     }
 
     public static String dirname(ThreadContext contextString jfilename) {
         String name = jfilename.replace('\\''/');
         int minPathLength = 1;
         boolean trimmedSlashes = false;
 
         boolean startsWithDriveLetterOnWindows = startsWithDriveLetterOnWindows(name);
 
         if (startsWithDriveLetterOnWindows) {
             minPathLength = 3;
         }
 
         while (name.length() > minPathLength && name.charAt(name.length() - 1) == '/') {
             trimmedSlashes = true;
             name = name.substring(0, name.length() - 1);
         }
 
         String result;
         if (startsWithDriveLetterOnWindows && name.length() == 2) {
             if (trimmedSlashes) {
                 // C:\ is returned unchanged
                 result = jfilename.substring(0, 3);
             } else {
                 result = jfilename.substring(0, 2) + '.';
             }
         } else {
             //TODO deal with UNC names
             int index = name.lastIndexOf('/');
 
             if (index == -1) {
                 if (startsWithDriveLetterOnWindows) {
                     return jfilename.substring(0, 2) + ".";
                 } else {
                     return ".";
                 }
             }
             if (index == 0) {
                 return "/";
             }
 
             if (startsWithDriveLetterOnWindows && index == 2) {
                 // Include additional path separator
                 // (so that dirname of "C:\file.txt" is  "C:\", not "C:")
                 index++;
             }
 
             if (jfilename.startsWith("\\\\")) {
                 index = jfilename.length();
                 String[] splitted = jfilename.split(Pattern.quote("\\"));
                 int last = splitted.length-1;
                 if (splitted[last].contains(".")) {
                     index = jfilename.lastIndexOf("\\");
                 }
                 
             }
             
             result = jfilename.substring(0, index);
             
         }
         
         char endChar;
         // trim trailing slashes
         while (result.length() > minPathLength) {
             endChar = result.charAt(result.length() - 1);
             if (endChar == '/' || endChar == '\\') {
                 result = result.substring(0, result.length() - 1);
             } else {
                 break;
             }
         }
 
         return result;
     }

    
Returns the extension name of the file. An empty string is returned if the filename (not the entire path) starts or ends with a dot.

Parameters:
recv
arg Path to get extension name of
Returns:
Extension, including the dot, or an empty string
 
     @JRubyMethod(required = 1, meta = true)
     public static IRubyObject extname(ThreadContext contextIRubyObject recvIRubyObject arg) {
         IRubyObject baseFilename = basename(contextrecvnew IRubyObject[]{arg});
         
         String filename = RubyString.stringValue(baseFilename).getUnicodeValue();
         String result = "";
 
         int dotIndex = filename.lastIndexOf(".");
         if (dotIndex > 0 && dotIndex != (filename.length() - 1)) {
             // Dot is not at beginning and not at end of filename. 
             result = filename.substring(dotIndex);
         }
 
         return context.runtime.newString(result);
     }

    
Converts a pathname to an absolute pathname. Relative paths are referenced from the current working directory of the process unless a second argument is given, in which case it will be used as the starting point. If the second argument is also relative, it will first be converted to an absolute pathname.

Parameters:
recv
args
Returns:
Resulting absolute path as a String
 
     @JRubyMethod(required = 1, optional = 1, meta = true, compat = .)
     public static IRubyObject expand_path(ThreadContext contextIRubyObject recvIRubyObject[] args) {
         return expandPathInternal(contextrecvargstrue);
     }
 
     @JRubyMethod(name = "expand_path", required = 1, optional = 1, meta = true, compat = .)
     public static IRubyObject expand_path19(ThreadContext contextIRubyObject recvIRubyObject[] args) {
         RubyString path = (RubyStringexpandPathInternal(contextrecvargstrue);
         path.force_encoding(contextcontext.runtime.getEncodingService().getDefaultExternal());
 
         return path;
     }


    
---------------------------------------------------- File::absolute_path File.absolute_path(file_name [, dir_string] ) -> abs_file_name From Ruby 1.9.1 ------------------------------------------------------------------------ Converts a pathname to an absolute pathname. Relative paths are referenced from the current working directory of the process unless _dir_string_ is given, in which case it will be used as the starting point. If the given pathname starts with a ``+~+'' it is NOT expanded, it is treated as a normal directory name. File.absolute_path("~oracle/bin") #=> "<relative_path>/~oracle/bin"

Parameters:
context
recv
args
Returns:
 
     @JRubyMethod(required = 1, optional = 1, meta = true, compat = )
     public static IRubyObject absolute_path(ThreadContext contextIRubyObject recvIRubyObject[] args) {
         return expandPathInternal(contextrecvargsfalse);
     }
 
     @JRubyMethod(name = {"realdirpath"}, required = 1, optional = 1, meta = true, compat = )
     public static IRubyObject realdirpath(ThreadContext contextIRubyObject recvIRubyObject[] args) {
         return expandPathInternal(contextrecvargsfalse);
     }
 
     @JRubyMethod(name = {"realpath"}, required = 1, optional = 1, meta = true, compat = )
     public static IRubyObject realpath(ThreadContext contextIRubyObject recvIRubyObject[] args) {
         IRubyObject file = expandPathInternal(contextrecvargsfalse);
         if (!RubyFileTest.exist_p(recvfile).isTrue()) {
             throw context.runtime.newErrnoENOENTError(file.toString());
         }
         return file;
     }

    
Returns true if path matches against pattern The pattern is not a regular expression; instead it follows rules similar to shell filename globbing. It may contain the following metacharacters: *: Glob - match any sequence chars (re: .*). If like begins with '.' then it doesn't. ?: Matches a single char (re: .). [set]: Matches a single char in a set (re: [...]).
 
     @JRubyMethod(name = {"fnmatch""fnmatch?"}, required = 2, optional = 1, meta = true)
     public static IRubyObject fnmatch(ThreadContext contextIRubyObject recvIRubyObject[] args) {
         int flags = args.length == 3 ? RubyNumeric.num2int(args[2]) : 0;
 
         ByteList pattern = args[0].convertToString().getByteList();
         ByteList path = get_path(contextargs[1]).getByteList();
 
         if (org.jruby.util.Dir.fnmatch(pattern.getUnsafeBytes(), pattern.getBegin(), pattern.getBegin()+pattern.getRealSize(), path.getUnsafeBytes(), path.getBegin(), path.getBegin()+path.getRealSize(), flags) == 0) {
             return context.runtime.getTrue();
         }
         return context.runtime.getFalse();
     }
     
     @JRubyMethod(name = "ftype", required = 1, meta = true)
     public static IRubyObject ftype(ThreadContext contextIRubyObject recvIRubyObject filename) {
         return context.runtime.newFileStat(get_path(contextfilename).getUnicodeValue(), true).ftype();
     }
     
     /*
      * Fixme:  This does not have exact same semantics as RubyArray.join, but they
      * probably could be consolidated (perhaps as join(args[], sep, doChomp)).
      */
     @JRubyMethod(rest = true, meta = true)
     public static RubyString join(ThreadContext contextIRubyObject recvIRubyObject[] args) {
         return join(contextrecv, RubyArray.newArrayNoCopyLight(context.runtimeargs));
     }
     
     @JRubyMethod(name = "lstat", required = 1, meta = true)
     public static IRubyObject lstat(ThreadContext contextIRubyObject recvIRubyObject filename) {
         String f = get_path(contextfilename).getUnicodeValue();
         return context.runtime.newFileStat(ftrue);
     }
 
     @JRubyMethod(name = "stat", required = 1, meta = true)
     public static IRubyObject stat(ThreadContext contextIRubyObject recvIRubyObject filename) {
         String f = get_path(contextfilename).getUnicodeValue();
         return context.runtime.newFileStat(ffalse);
     }
 
     @JRubyMethod(name = "atime", required = 1, meta = true)
     public static IRubyObject atime(ThreadContext contextIRubyObject recvIRubyObject filename) {
         String f = get_path(contextfilename).getUnicodeValue();
         return context.runtime.newFileStat(ffalse).atime();
     }
 
     @JRubyMethod(name = "ctime", required = 1, meta = true)
     public static IRubyObject ctime(ThreadContext contextIRubyObject recvIRubyObject filename) {
         String f = get_path(contextfilename).getUnicodeValue();
         return context.runtime.newFileStat(ffalse).ctime();
     }
 
     @JRubyMethod(required = 1, rest = true, meta = true)
     public static IRubyObject lchmod(ThreadContext contextIRubyObject recvIRubyObject[] args) {
         Ruby runtime = context.runtime;
         
         int count = 0;
         RubyInteger mode = args[0].convertToInteger();
         for (int i = 1; i < args.lengthi++) {
             JRubyFile file = file(args[i]);
             if (0 != runtime.getPosix().lchmod(file.toString(), (int)mode.getLongValue())) {
                 throw runtime.newErrnoFromLastPOSIXErrno();
             } else {
                 count++;
             }
         }
         
         return runtime.newFixnum(count);
     }
 
     @JRubyMethod(required = 2, rest = true, meta = true)
     public static IRubyObject lchown(ThreadContext contextIRubyObject recvIRubyObject[] args) {
         Ruby runtime = context.runtime;
         int owner = !args[0].isNil() ? RubyNumeric.num2int(args[0]) : -1;
         int group = !args[1].isNil() ? RubyNumeric.num2int(args[1]) : -1;
         int count = 0;
 
         for (int i = 2; i < args.lengthi++) {
             JRubyFile file = file(args[i]);
 
             if (0 != runtime.getPosix().lchown(file.toString(), ownergroup)) {
                 throw runtime.newErrnoFromLastPOSIXErrno();
             } else {
                 count++;
             }
         }
 
         return runtime.newFixnum(count);
     }
 
     @JRubyMethod(required = 2, meta = true)
     public static IRubyObject link(ThreadContext contextIRubyObject recvIRubyObject fromIRubyObject to) {
         Ruby runtime = context.runtime;
         String fromStr = file(from).toString();
         String toStr = file(to).toString();
 
         int ret = runtime.getPosix().link(fromStrtoStr);
         if (ret != 0) {
             if (runtime.getPosix().isNative()) {
                 throw runtime.newErrnoFromInt(runtime.getPosix().errno(), String.format("(%s, %s)"fromStrtoStr));
             } else {
                 // In most cases, when there is an error during the call,
                 // the POSIX handler throws an exception, but not in case
                 // with pure Java POSIX layer (when native support is disabled),
                 // so we deal with it like this:
                 throw runtime.newErrnoEEXISTError(fromStr + " or " + toStr);
             }
         }
         return runtime.newFixnum(ret);
     }
 
     @JRubyMethod(name = "mtime", required = 1, meta = true)
     public static IRubyObject mtime(ThreadContext contextIRubyObject recvIRubyObject filename) {
         return context.runtime.newFileStat(get_path(contextfilename).getUnicodeValue(), false).mtime();
     }
     
     @JRubyMethod(required = 2, meta = true)
     public static IRubyObject rename(ThreadContext contextIRubyObject recvIRubyObject oldNameIRubyObject newName) {
         Ruby runtime = context.runtime;
         RubyString oldNameString = get_path(contextoldName);
         RubyString newNameString = get_path(contextnewName);
 
         String newNameJavaString = newNameString.getUnicodeValue();
         String oldNameJavaString = oldNameString.getUnicodeValue();
         JRubyFile oldFile = JRubyFile.create(runtime.getCurrentDirectory(), oldNameJavaString);
         JRubyFile newFile = JRubyFile.create(runtime.getCurrentDirectory(), newNameJavaString);
         
         if (!oldFile.exists() || !newFile.getParentFile().exists()) {
             throw runtime.newErrnoENOENTError(oldNameJavaString + " or " + newNameJavaString);
         }
 
         JRubyFile dest = JRubyFile.create(runtime.getCurrentDirectory(), newNameJavaString);
 
         if (oldFile.renameTo(dest)) {  // rename is successful
             return RubyFixnum.zero(runtime);
         }
 
         // rename via Java API call wasn't successful, let's try some tricks, similar to MRI 
 
         if (newFile.exists()) {
             runtime.getPosix().chmod(newNameJavaString, 0666);
             newFile.delete();
         }
 
         if (oldFile.renameTo(dest)) { // try to rename one more time
             return RubyFixnum.zero(runtime);
         }
 
         throw runtime.newErrnoEACCESError(oldNameJavaString + " or " + newNameJavaString);
     }
     
     @JRubyMethod(required = 1, meta = true)
     public static RubyArray split(ThreadContext contextIRubyObject recvIRubyObject arg) {
         RubyString filename = get_path(contextarg);
 
         return context.runtime.newArray(dirname(contextrecvfilename),
                 basename(contextrecvnew IRubyObject[]{filename}));
     }
     
     @JRubyMethod(required = 2, meta = true)
     public static IRubyObject symlink(ThreadContext contextIRubyObject recvIRubyObject fromIRubyObject to) {
         Ruby runtime = context.runtime;
         RubyString fromStr = get_path(contextfrom);
         RubyString toStr = get_path(contextto);
         String tovalue = toStr.getUnicodeValue();
         tovalue = JRubyFile.create(runtime.getCurrentDirectory(), tovalue).getAbsolutePath();
         try {
             if (runtime.getPosix().symlink(fromStr.getUnicodeValue(), tovalue) == -1) {
                 if (runtime.getPosix().isNative()) {
                     throw runtime.newErrnoFromInt(runtime.getPosix().errno(), String.format("(%s, %s)"fromStrtoStr));
                 } else {
                     throw runtime.newErrnoEEXISTError(String.format("(%s, %s)"fromStrtoStr));
                 }
             }
         } catch (java.lang.UnsatisfiedLinkError ule) {
             throw runtime.newNotImplementedError("symlink() function is unimplemented on this machine");
         }
         
         return RubyFixnum.zero(runtime);
     }
     
     @JRubyMethod(required = 1, meta = true)
     public static IRubyObject readlink(ThreadContext contextIRubyObject recvIRubyObject path) {
         Ruby runtime = context.runtime;
         JRubyFile link = file(path);
         
         try {
             String realPath = runtime.getPosix().readlink(link.toString());
         
             if (!RubyFileTest.exist_p(recvpath).isTrue()) {
                 throw runtime.newErrnoENOENTError(path.toString());
             }
         
            if (!RubyFileTest.symlink_p(recvpath).isTrue()) {
                // Can not check earlier, File.exist? might return false yet the symlink be there
                if (!RubyFileTest.exist_p(recvpath).isTrue()) {
                    throw runtime.newErrnoENOENTError(path.toString());
                }
                throw runtime.newErrnoEINVALError(path.toString());
            }
        
            if (realPath == null) {
                throw runtime.newErrnoFromLastPOSIXErrno();
            }
            return runtime.newString(realPath);
        } catch (IOException e) {
            throw runtime.newIOError(e.getMessage());
        }
    }
    // Can we produce IOError which bypasses a close?
    @JRubyMethod(required = 2, meta = true, compat = )
    public static IRubyObject truncate(ThreadContext contextIRubyObject recvIRubyObject arg1IRubyObject arg2) {