Index: src/org/jruby/ext/posix/BaseHeapFileStat.java =================================================================== --- src/org/jruby/ext/posix/BaseHeapFileStat.java (revision 0) +++ src/org/jruby/ext/posix/BaseHeapFileStat.java (revision 0) @@ -0,0 +1,190 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common 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/cpl-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. + * + * + * + * 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 CPL, 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 CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +/** + * $Id: $ + */ + +package org.jruby.ext.posix; + +import com.sun.jna.NativeMapped; + +/** + * + */ +public abstract class BaseHeapFileStat extends HeapStruct implements FileStat, NativeMapped { + protected final POSIX posix; + + public BaseHeapFileStat(POSIX posix) { + super(); + this.posix = posix; + } + + public String ftype() { + if (isFile()) { + return "file"; + } else if (isDirectory()) { + return "directory"; + } else if (isCharDev()) { + return "characterSpecial"; + } else if (isBlockDev()) { + return "blockSpecial"; + } else if (isFifo()) { + return "fifo"; + } else if (isSymlink()) { + return "link"; + } else if (isSocket()) { + return "socket"; + } + + return "unknown"; + } + + public boolean groupMember(int gid) { + if (posix.getgid() == gid || posix.getegid() == gid) { + return true; + } + + // FIXME: Though not Posix, windows has different mechanism for this. + + return false; + } + + public boolean isBlockDev() { + return (mode() & S_IFMT) == S_IFBLK; + } + + public boolean isCharDev() { + return (mode() & S_IFMT) == S_IFCHR; + } + + public boolean isDirectory() { + return (mode() & S_IFMT) == S_IFDIR; + } + + public boolean isEmpty() { + return st_size() == 0; + } + + public boolean isExecutable() { + if (posix.geteuid() == 0) return (mode() & S_IXUGO) != 0; + if (isOwned()) return (mode() & S_IXUSR) != 0; + if (isGroupOwned()) return (mode() & S_IXGRP) != 0; + return (mode() & S_IXOTH) != 0; + } + + public boolean isExecutableReal() { + if (posix.getuid() == 0) return (mode() & S_IXUGO) != 0; + if (isROwned()) return (mode() & S_IXUSR) != 0; + if (groupMember(gid())) return (mode() & S_IXGRP) != 0; + return (mode() & S_IXOTH) != 0; + } + + public boolean isFile() { + return (mode() & S_IFMT) == S_IFREG; + } + + public boolean isFifo() { + return (mode() & S_IFMT) == S_IFIFO; + } + + public boolean isGroupOwned() { + return groupMember(gid()); + } + + public boolean isIdentical(FileStat other) { + return dev() == other.dev() && ino() == other.ino(); + } + + public boolean isNamedPipe() { + return (mode() & S_IFIFO) != 0; + } + + public boolean isOwned() { + return posix.geteuid() == uid(); + } + + public boolean isROwned() { + return posix.getuid() == uid(); + } + + public boolean isReadable() { + if (posix.geteuid() == 0) return true; + if (isOwned()) return (mode() & S_IRUSR) != 0; + if (isGroupOwned()) return (mode() & S_IRGRP) != 0; + return (mode() & S_IROTH) != 0; + } + + public boolean isReadableReal() { + if (posix.getuid() == 0) return true; + if (isROwned()) return (mode() & S_IRUSR) != 0; + if (groupMember(gid())) return (mode() & S_IRGRP) != 0; + return (mode() & S_IROTH) != 0; + } + + public boolean isSetgid() { + return (mode() & S_ISGID) != 0; + } + + public boolean isSetuid() { + return (mode() & S_ISUID) != 0; + } + + public boolean isSocket() { + return (mode() & S_IFMT) == S_IFSOCK; + } + + public boolean isSticky() { + return (mode() & S_ISVTX) != 0; + } + + public boolean isSymlink() { + return (mode() & S_IFMT) == S_IFLNK; + } + + public boolean isWritable() { + if (posix.geteuid() == 0) return true; + if (isOwned()) return (mode() & S_IWUSR) != 0; + if (isGroupOwned()) return (mode() & S_IWGRP) != 0; + return (mode() & S_IWOTH) != 0; + } + + public boolean isWritableReal() { + if (posix.getuid() == 0) return true; + if (isROwned()) return (mode() & S_IWUSR) != 0; + if (groupMember(gid())) return (mode() & S_IWGRP) != 0; + return (mode() & S_IWOTH) != 0; + } + + public int major(long dev) { + return (int) (dev >> 24) & 0xff; + } + + public int minor(long dev) { + return (int) (dev & 0xffffff); + } +} Index: src/org/jruby/ext/posix/HeapStruct.java =================================================================== --- src/org/jruby/ext/posix/HeapStruct.java (revision 0) +++ src/org/jruby/ext/posix/HeapStruct.java (revision 0) @@ -0,0 +1,204 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common 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/cpl-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. + * + * + * + * 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 CPL, 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 CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +/** + * $Id: $ + */ + +package org.jruby.ext.posix; + +import com.sun.jna.FromNativeContext; +import com.sun.jna.Platform; +import com.sun.jna.Pointer; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +/** + * + */ +public class HeapStruct implements com.sun.jna.NativeMapped { + private static final String arch = System.getProperty("os.arch").toLowerCase(); + private static final boolean isSPARC = "sparc".equals(arch); + /* + * Most arches align long/double on the same size as a native long (or a pointer) + * Sparc (32bit) requires it to be aligned on an 8 byte boundary + */ + private static final int LONG_SIZE = (Platform.isWindows() ? 4 : Pointer.SIZE) * 8; + private static final int LONG_ALIGN = isSPARC ? 64 : LONG_SIZE; + private static final int DOUBLE_ALIGN = isSPARC ? 64 : LONG_SIZE; + private static final int FLOAT_ALIGN = isSPARC ? 64 : 32; + private ByteBuffer buffer; + private int size = 0; + + public Object fromNative(Object arg0, FromNativeContext arg1) { + throw new UnsupportedOperationException("Not supported yet."); + } + + public Object toNative() { + return getByteBuffer(); + } + + public Class nativeType() { + return ByteBuffer.class; + } + protected final ByteBuffer getByteBuffer() { + if (buffer == null) { + buffer = ByteBuffer.allocate(size).order(ByteOrder.nativeOrder()); + } + return buffer; + } + public final int getStructSize() { + return size; + } + protected final int addField(int size, int align) { + int mask = (align / 8) - 1; + if ((this.size & mask) != 0) { + this.size = (this.size & ~mask) + (align / 8); + } + int off = this.size; + this.size += size / 8; + return off; + } + protected abstract class Field { + public final int size; + public final int align; + public final int offset; + public Field(int size) { + this(size, size); + } + public Field(int size, int align) { + this.size = size; + this.align = align; + this.offset = addField(size, align); + } + } + protected class Int8 extends Field { + public Int8() { + super(8); + } + public Int8(byte value) { + this(); + set(value); + } + public final byte get() { + return getByteBuffer().get(offset); + } + public final void set(byte value) { + getByteBuffer().put(offset, value); + } + } + protected final class Byte extends Int8 { + public Byte() { } + public Byte(byte value) { + super(value); + } + } + protected class Int16 extends Field { + public Int16() { + super(16); + } + public Int16(short value) { + this(); + set(value); + } + public final short get() { + return getByteBuffer().getShort(offset); + } + public final void set(short value) { + getByteBuffer().putShort(offset, value); + } + } + protected class Short extends Int16 { + public Short() {} + public Short(short value) { + super(value); + } + } + protected class Int32 extends Field { + public Int32() { + super(32); + } + public Int32(int value) { + this(); + set(value); + } + public final int get() { + return getByteBuffer().getInt(offset); + } + public final void set(int value) { + getByteBuffer().putInt(offset, value); + } + } + protected class Integer extends Int32 { + public Integer() {} + public Integer(int value) { + super(value); + } + } + protected class Int64 extends Field { + public Int64() { + super(64, LONG_ALIGN); + } + public Int64(long value) { + this(); + set(value); + } + public final long get() { + return getByteBuffer().getLong(offset); + } + public final void set(long value) { + getByteBuffer().putLong(offset, value); + } + } + + protected class Long extends Field { + public Long() { + super(LONG_SIZE, LONG_ALIGN); + } + public Long(long value) { + this(); + set(value); + } + public final long get() { + return LONG_SIZE == 32 + ? getByteBuffer().getInt(offset) : getByteBuffer().getLong(offset); + } + public final void set(long value) { + if (LONG_SIZE == 32) { + getByteBuffer().putInt(offset, (int) value); + } else { + getByteBuffer().putLong(offset, value); + } + } + } + protected class LongLong extends Int64 { + public LongLong() { } + public LongLong(long value) { + super(value); + } + } +} Index: src/org/jruby/ext/posix/MacOSHeapFileStat.java =================================================================== --- src/org/jruby/ext/posix/MacOSHeapFileStat.java (revision 0) +++ src/org/jruby/ext/posix/MacOSHeapFileStat.java (revision 0) @@ -0,0 +1,116 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common 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/cpl-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. + * + * + * + * 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 CPL, 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 CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +/** + * $Id: $ + */ + +package org.jruby.ext.posix; + +public class MacOSHeapFileStat extends BaseHeapFileStat { + public final class time_t extends Long { + } + public final Int32 st_dev = new Int32(); + public final Int32 st_ino = new Int32(); + public final Int16 st_mode = new Int16(); + public final Int16 st_nlink = new Int16(); + public final Int32 st_uid = new Int32(); + public final Int32 st_gid = new Int32(); + public final Int32 st_rdev = new Int32(); + public final time_t st_atime = new time_t(); + public final Long st_atimensec = new Long(); + public final time_t st_mtime = new time_t(); + public final Long st_mtimensec = new Long(); + public final time_t st_ctime = new time_t(); + public final Long st_ctimensec = new Long(); + public final Int64 st_size = new Int64(); + public final Int64 st_blocks = new Int64(); + public final Int32 st_blksize = new Int32(); + public final Int32 st_flags = new Int32(); + public final Int32 st_gen = new Int32(); + public final Int32 st_lspare = new Int32(); + public final Int64 st_qspare0 = new Int64(); + public final Int64 st_qspare1 = new Int64(); + + public MacOSHeapFileStat() { + this(null); + } + public MacOSHeapFileStat(POSIX posix) { + super(posix); + } + public long atime() { + return st_atime.get(); + } + + public long blocks() { + return st_blocks.get(); + } + + public long blockSize() { + return st_blksize.get(); + } + + public long ctime() { + return st_ctime.get(); + } + + public long dev() { + return st_dev.get(); + } + + public int gid() { + return st_gid.get(); + } + + public int ino() { + return st_ino.get(); + } + + public int mode() { + return st_mode.get() & 0xffff; + } + + public long mtime() { + return st_mtime.get(); + } + + public int nlink() { + return st_nlink.get(); + } + + public long rdev() { + return st_rdev.get(); + } + + public long st_size() { + return st_size.get(); + } + + public int uid() { + return st_uid.get(); + } +} Index: src/org/jruby/ext/posix/MacOSPOSIX.java =================================================================== --- src/org/jruby/ext/posix/MacOSPOSIX.java (revision 6223) +++ src/org/jruby/ext/posix/MacOSPOSIX.java (working copy) @@ -6,6 +6,7 @@ } public FileStat allocateStat() { - return new MacOSFileStat(this); +// return new MacOSFileStat(this); + return new MacOSHeapFileStat(this); } }