/**
* ****************************************************************************
* Copyright (c) 2010-2016 by Min Cai (min.cai.china@gmail.com).
* <p>
* This file is part of the Archimulator multicore architectural simulator.
* <p>
* Archimulator is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* <p>
* Archimulator is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License
* along with Archimulator. If not, see <http://www.gnu.org/licenses/>.
* ****************************************************************************
*/
package archimulator.os;
import org.jruby.ext.posix.*;
import org.jruby.ext.posix.util.Platform;
import java.io.FileDescriptor;
/**
* Enhanced Linux POSIX implementation.
*
* @author Min Cai
*/
public final class EnhancedLinuxPOSIX extends BaseNativePOSIX {
private final boolean hasFxstat;
private final boolean hasLxstat;
private final boolean hasXstat;
private final boolean hasFstat;
private final boolean hasLstat;
private final boolean hasStat;
private final int statVersion;
/**
* Create an enhanced Linux POSIX implementation.
*
* @param libraryName the library name
* @param libc the libc
* @param handler the POSIX handler
*/
public EnhancedLinuxPOSIX(String libraryName, LibC libc, POSIXHandler handler) {
super(libraryName, libc, handler);
this.statVersion = Platform.IS_32_BIT ? 3 : 0;
/*
* Most linux systems define stat/lstat/fstat as macros which force
* us to call these weird signature versions.
*/
this.hasFxstat = this.hasMethod("__fxstat64");
this.hasLxstat = this.hasMethod("__lxstat64");
this.hasXstat = this.hasMethod("__xstat64");
/*
* At least one person is using uLibc on linux which has real
* definitions for stat/lstat/fstat.
*/
this.hasFstat = !this.hasFxstat && this.hasMethod("fstat64");
this.hasLstat = !this.hasLxstat && this.hasMethod("lstat64");
this.hasStat = !this.hasXstat && this.hasMethod("stat64");
}
/**
* Allocate a file stat structure.
*
* @return the allocated file stat structure
*/
@Override
public FileStat allocateStat() {
if (Platform.IS_32_BIT) {
return new LinuxHeapFileStat(this);
} else {
return new Linux64HeapFileStat(this);
}
}
/**
* Create a file stat structure based on the specified file descriptor.
*
* @param fileDescriptor the file descriptor
* @return the newly created file stat structure based on the specified file descriptor
*/
@Override
public FileStat fstat(FileDescriptor fileDescriptor) {
if (!this.hasFxstat) {
if (this.hasFstat) return super.fstat(fileDescriptor);
this.handler.unimplementedError("fstat");
}
FileStat stat = allocateStat();
int fd = this.helper.getfd(fileDescriptor);
if (((LinuxLibC) this.libc).__fxstat64(this.statVersion, fd, stat) < 0)
this.handler.error(ERRORS.ENOENT, "" + fd);
return stat;
}
/**
* Create a file stat structure based on the specified file descriptor number.
*
* @param fd the file descriptor number
* @return the newly created file stat structure based on the specified file descriptor number
*/
public FileStat fstat(int fd) {
if (!this.hasFxstat) {
throw new UnsupportedOperationException();
}
FileStat stat = allocateStat();
if (((LinuxLibC) this.libc).__fxstat64(this.statVersion, fd, stat) < 0)
this.handler.error(ERRORS.ENOENT, "" + fd);
return stat;
}
}