| package jnr.posix; |
| |
| import jnr.constants.Constant; |
| import jnr.constants.platform.Errno; |
| import jnr.constants.platform.Fcntl; |
| import jnr.constants.platform.Signal; |
| import jnr.constants.platform.Sysconf; |
| import jnr.ffi.*; |
| import jnr.ffi.byref.NumberByReference; |
| import jnr.ffi.mapper.FromNativeContext; |
| import jnr.ffi.mapper.FromNativeConverter; |
| import jnr.ffi.mapper.ToNativeContext; |
| import jnr.ffi.mapper.ToNativeConverter; |
| import jnr.posix.util.Java5ProcessMaker; |
| import jnr.posix.util.MethodName; |
| import jnr.posix.util.ProcessMaker; |
| |
| import java.io.FileDescriptor; |
| import java.io.IOException; |
| import java.nio.ByteBuffer; |
| import java.nio.charset.Charset; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.Map; |
| import jnr.constants.platform.Confstr; |
| import jnr.constants.platform.Pathconf; |
| import jnr.ffi.annotations.Out; |
| |
| public abstract class BaseNativePOSIX extends NativePOSIX implements POSIX { |
| private final LibC libc; |
| private final Crypt crypt; |
| |
| protected final POSIXHandler handler; |
| protected final JavaLibCHelper helper; |
| |
| protected final Map<Signal, SignalHandler> signalHandlers = new HashMap(); |
| |
| protected BaseNativePOSIX(LibCProvider libcProvider, POSIXHandler handler) { |
| this.handler = handler; |
| this.libc = libcProvider.getLibC(); |
| this.crypt = libcProvider.getCrypt(); |
| this.helper = new JavaLibCHelper(handler); |
| } |
| |
| public ProcessMaker newProcessMaker(String... command) { |
| return new Java5ProcessMaker(handler, command); |
| } |
| |
| public ProcessMaker newProcessMaker() { |
| return new Java5ProcessMaker(handler); |
| } |
| |
| public final LibC libc() { |
| return libc; |
| } |
| |
| public final Crypt crypt() { |
| return crypt; |
| } |
| |
| POSIXHandler handler() { |
| return handler; |
| } |
| |
| protected <T> T unimplementedNull() { |
| handler().unimplementedError(MethodName.getCallerMethodName()); |
| return null; |
| } |
| |
| protected int unimplementedInt() { |
| handler().unimplementedError(MethodName.getCallerMethodName()); |
| return -1; |
| } |
| |
| public int chmod(String filename, int mode) { |
| return libc().chmod(filename, mode); |
| } |
| |
| public int fchmod(int fd, int mode) { |
| return libc().fchmod(fd, mode); |
| } |
| |
| public int chown(String filename, int user, int group) { |
| return libc().chown(filename, user, group); |
| } |
| |
| public int fchown(int fd, int user, int group) { |
| return libc().fchown(fd, user, group); |
| } |
| |
| public CharSequence crypt(CharSequence key, CharSequence salt) { |
| Crypt crypt = crypt(); |
| |
| if (crypt == null) { |
| return JavaLibCHelper.crypt(key, salt); |
| } |
| |
| return crypt.crypt(key, salt); |
| } |
| |
| public byte[] crypt(byte[] key, byte[] salt) { |
| Crypt crypt = crypt(); |
| |
| if (crypt == null) { |
| return JavaLibCHelper.crypt(key, salt); |
| } |
| |
| Pointer ptr = crypt().crypt(key, salt); |
| if (ptr == null) return null; |
| int end = ptr.indexOf(0, (byte)0); |
| byte[] bytes = new byte[end + 1]; |
| ptr.get(0, bytes, 0, end); |
| |
| return bytes; |
| } |
| |
| public int exec(String path, String... args) { |
| handler.unimplementedError("exec unimplemented"); |
| return -1; |
| } |
| |
| public int exec(String path, String[] args, String[] envp) { |
| handler.unimplementedError("exec unimplemented"); |
| return -1; |
| } |
| |
| public int execv(String path, String[] args) { |
| return libc().execv(path, args); |
| } |
| |
| public int execve(String path, String[] args, String[] env) { |
| return libc().execve(path, args, env); |
| } |
| |
| public FileStat fstat(FileDescriptor fileDescriptor) { |
| FileStat stat = allocateStat(); |
| |
| if (fstat(fileDescriptor, stat) < 0) handler.error(Errno.valueOf(errno()), "fstat", "" + helper.getfd(fileDescriptor)); |
| |
| return stat; |
| } |
| |
| public FileStat fstat(int fd) { |
| FileStat stat = allocateStat(); |
| if (fstat(fd, stat) < 0) handler.error(Errno.valueOf(errno()), "fstat", "" + fd); |
| return stat; |
| } |
| |
| |
| public int fstat(FileDescriptor fileDescriptor, FileStat stat) { |
| int fd = helper.getfd(fileDescriptor); |
| return libc().fstat(fd, stat); |
| } |
| |
| public int fstat(int fd, FileStat stat) { |
| return libc().fstat(fd, stat); |
| } |
| |
| public Pointer environ() { |
| return getRuntime().getMemoryManager().newPointer(libc().environ().get()); |
| } |
| |
| public String getenv(String envName) { |
| return libc().getenv(envName); |
| } |
| |
| public int getegid() { |
| return libc().getegid(); |
| } |
| |
| public int geteuid() { |
| return libc().geteuid(); |
| } |
| |
| public int getgid() { |
| return libc().getgid(); |
| } |
| |
| public int getdtablesize() { |
| return libc().getdtablesize(); |
| } |
| |
| public String getlogin() { |
| return libc().getlogin(); |
| } |
| |
| public int getpgid() { |
| return libc().getpgid(); |
| } |
| |
| public int getpgrp() { |
| return libc().getpgrp(); |
| } |
| |
| public int getpid() { |
| return libc().getpid(); |
| } |
| |
| public int getppid() { |
| return libc().getppid(); |
| } |
| |
| public Passwd getpwent() { |
| return libc().getpwent(); |
| } |
| |
| public Passwd getpwuid(int which) { |
| return libc().getpwuid(which); |
| } |
| |
| public Passwd getpwnam(String which) { |
| return libc().getpwnam(which); |
| } |
| |
| public Group getgrent() { |
| return libc().getgrent(); |
| } |
| public Group getgrgid(int which) { |
| return libc().getgrgid(which); |
| } |
| public Group getgrnam(String which) { |
| return libc().getgrnam(which); |
| } |
| |
| public int setpwent() { |
| return libc().setpwent(); |
| } |
| |
| public int endpwent() { |
| return libc().endpwent(); |
| } |
| |
| public int setgrent() { |
| return libc().setgrent(); |
| } |
| |
| public int endgrent() { |
| return libc().endgrent(); |
| } |
| |
| public int getuid() { |
| return libc().getuid(); |
| } |
| |
| public int getrlimit(int resource, RLimit rlim) { |
| return libc().getrlimit(resource, rlim); |
| } |
| |
| public int getrlimit(int resource, Pointer rlim) { |
| return libc().getrlimit(resource, rlim); |
| } |
| |
| public RLimit getrlimit(int resource) { |
| RLimit rlim = new DefaultNativeRLimit(getRuntime()); |
| |
| if (getrlimit(resource, rlim) < 0) handler.error(Errno.valueOf(errno()), "rlim"); |
| |
| return rlim; |
| } |
| |
| public int setrlimit(int resource, RLimit rlim) { |
| return libc().setrlimit(resource, rlim); |
| } |
| |
| public int setrlimit(int resource, Pointer rlim) { |
| return libc().setrlimit(resource, rlim); |
| } |
| |
| public int setrlimit(int resource, long rlimCur, long rlimMax) { |
| RLimit rlim = new DefaultNativeRLimit(getRuntime()); |
| rlim.init(rlimCur, rlimMax); |
| |
| return libc().setrlimit(resource, rlim); |
| } |
| |
| public int setegid(int egid) { |
| return libc().setegid(egid); |
| } |
| |
| public int seteuid(int euid) { |
| return libc().seteuid(euid); |
| } |
| |
| public int setgid(int gid) { |
| return libc().setgid(gid); |
| } |
| |
| public int getfd(FileDescriptor descriptor) { |
| return helper.getfd(descriptor); |
| } |
| |
| public int getpgid(int pid) { |
| return libc().getpgid(pid); |
| } |
| |
| public int setpgid(int pid, int pgid) { |
| return libc().setpgid(pid, pgid); |
| } |
| |
| public int setpgrp(int pid, int pgrp) { |
| return libc().setpgrp(pid, pgrp); |
| } |
| |
| public int setsid() { |
| return libc().setsid(); |
| } |
| |
| public int setuid(int uid) { |
| return libc().setuid(uid); |
| } |
| |
| public int kill(int pid, int signal) { |
| return kill((long) pid, signal); |
| } |
| |
| public int kill(long pid, int signal) { |
| return libc().kill(pid, signal); |
| } |
| |
| public SignalHandler signal(Signal sig, final SignalHandler handler) { |
| synchronized (signalHandlers) { |
| SignalHandler old = signalHandlers.get(sig); |
| |
| long result = libc().signal(sig.intValue(), new LibC.LibCSignalHandler() { |
| public void signal(int sig) { |
| handler.handle(sig); |
| } |
| }); |
| |
| if (result != -1) { |
| signalHandlers.put(sig, handler); |
| } |
| |
| return old; |
| } |
| } |
| |
| public int raise(int sig) { |
| return libc().raise(sig); |
| } |
| |
| public int lchmod(String filename, int mode) { |
| try { |
| return libc().lchmod(filename, mode); |
| } catch (UnsatisfiedLinkError ule) { |
| return unimplementedInt(); |
| } |
| } |
| |
| public int lchown(String filename, int user, int group) { |
| try { |
| return libc().lchown(filename, user, group); |
| } catch (UnsatisfiedLinkError ule) { |
| return unimplementedInt(); |
| } |
| } |
| |
| public int link(String oldpath, String newpath) { |
| return libc().link(oldpath, newpath); |
| } |
| |
| public FileStat lstat(String path) { |
| FileStat stat = allocateStat(); |
| |
| if (lstat(path, stat) < 0) handler.error(Errno.valueOf(errno()), "lstat", path); |
| |
| return stat; |
| } |
| |
| public int lstat(String path, FileStat stat) { |
| return libc().lstat(path, stat); |
| } |
| |
| public int mkdir(String path, int mode) { |
| int res = libc().mkdir(path, mode); |
| if (res < 0) { |
| int errno = errno(); |
| handler.error(Errno.valueOf(errno), "mkdir", path); |
| } |
| return res; |
| } |
| |
| public int rmdir(String path) { |
| int res = libc().rmdir(path); |
| |
| if (res < 0) handler.error(Errno.valueOf(errno()), "rmdir", path); |
| |
| return res; |
| } |
| |
| public int setenv(String envName, String envValue, int overwrite) { |
| return libc().setenv(envName, envValue, overwrite); |
| } |
| |
| public FileStat stat(String path) { |
| FileStat stat = allocateStat(); |
| |
| if (stat(path, stat) < 0) handler.error(Errno.valueOf(errno()), "stat", path); |
| |
| return stat; |
| } |
| |
| public int stat(String path, FileStat stat) { |
| return libc().stat(path, stat); |
| } |
| |
| public int symlink(String oldpath, String newpath) { |
| return libc().symlink(oldpath, newpath); |
| } |
| |
| public String readlink(String oldpath) throws IOException { |
| // TODO: this should not be hardcoded to 1024 bytes |
| ByteBuffer buffer = ByteBuffer.allocate(1024); |
| int result = libc().readlink(oldpath, buffer, buffer.capacity()); |
| |
| if (result == -1) return null; |
| |
| buffer.position(0); |
| buffer.limit(result); |
| return Charset.defaultCharset().decode(buffer).toString(); |
| } |
| |
| public int readlink(CharSequence path, byte[] buf, int bufsize) { |
| return libc().readlink(path, buf, bufsize); |
| } |
| |
| public int readlink(CharSequence path, ByteBuffer buf, int bufsize) { |
| return libc().readlink(path, buf, bufsize); |
| } |
| |
| public int readlink(CharSequence path, Pointer bufPtr, int bufsize) { |
| return libc().readlink(path, bufPtr, bufsize); |
| } |
| |
| public int unsetenv(String envName) { |
| return libc().unsetenv(envName); |
| } |
| |
| public int umask(int mask) { |
| return libc().umask(mask); |
| } |
| |
| public int utimes(String path, long[] atimeval, long[] mtimeval) { |
| Timeval[] times = null; |
| if (atimeval != null && mtimeval != null) { |
| times = Struct.arrayOf(getRuntime(), DefaultNativeTimeval.class, 2); |
| times[0].setTime(atimeval); |
| times[1].setTime(mtimeval); |
| } |
| return libc().utimes(path, times); |
| } |
| |
| public int utimes(String path, Pointer times) { |
| return libc().utimes(path, times); |
| } |
| |
| public int futimes(int fd, long[] atimeval, long[] mtimeval) { |
| Timeval[] times = null; |
| if (atimeval != null && mtimeval != null) { |
| times = Struct.arrayOf(getRuntime(), DefaultNativeTimeval.class, 2); |
| times[0].setTime(atimeval); |
| times[1].setTime(mtimeval); |
| } |
| return libc().futimes(fd, times); |
| } |
| |
| public int lutimes(String path, long[] atimeval, long[] mtimeval) { |
| Timeval[] times = null; |
| if (atimeval != null && mtimeval != null) { |
| times = Struct.arrayOf(getRuntime(), DefaultNativeTimeval.class, 2); |
| times[0].setTime(atimeval); |
| times[1].setTime(mtimeval); |
| } |
| return libc().lutimes(path, times); |
| } |
| |
| public int utimensat(int dirfd, String path, long[] atimespec, long[] mtimespec, int flag) { |
| Timespec[] times = null; |
| if (atimespec != null && mtimespec != null) { |
| times = Struct.arrayOf(getRuntime(), DefaultNativeTimespec.class, 2); |
| times[0].setTime(atimespec); |
| times[1].setTime(mtimespec); |
| } |
| return libc().utimensat(dirfd, path, times, flag); |
| } |
| |
| public int utimensat(int dirfd, String path, Pointer times, int flag) { |
| return libc().utimensat(dirfd, path, times, flag); |
| } |
| |
| public int futimens(int fd, long[] atimespec, long[] mtimespec) { |
| Timespec[] times = null; |
| if (atimespec != null && mtimespec != null) { |
| times = Struct.arrayOf(getRuntime(), DefaultNativeTimespec.class, 2); |
| times[0].setTime(atimespec); |
| times[1].setTime(mtimespec); |
| } |
| return libc().futimens(fd, times); |
| } |
| |
| public int futimens(int fd, Pointer times) { |
| return libc().futimens(fd, times); |
| } |
| |
| public int fork() { |
| return libc().fork(); |
| } |
| |
| public int waitpid(int pid, int[] status, int flags) { |
| return waitpid((long)pid, status, flags); |
| } |
| |
| public int waitpid(long pid, int[] status, int flags) { |
| return libc().waitpid(pid, status, flags); |
| } |
| |
| public int wait(int[] status) { |
| return libc().wait(status); |
| } |
| |
| public int getpriority(int which, int who) { |
| return libc().getpriority(which, who); |
| } |
| |
| public int setpriority(int which, int who, int prio) { |
| return libc().setpriority(which, who, prio); |
| } |
| |
| public boolean isatty(FileDescriptor fd) { |
| return isatty(helper.getfd(fd)) != 0; |
| } |
| |
| public int isatty(int fd) { |
| return libc().isatty(fd); |
| } |
| |
| public int errno() { |
| return LastError.getLastError(getRuntime()); |
| } |
| |
| public void errno(int value) { |
| LastError.setLastError(getRuntime(), value); |
| } |
| |
| public int chdir(String path) { |
| return libc().chdir(path); |
| } |
| |
| public boolean isNative() { |
| return true; |
| } |
| |
| public long posix_spawnp(String path, Collection<? extends SpawnFileAction> fileActions, |
| CharSequence[] argv, CharSequence[] envp) { |
| return posix_spawnp(path, fileActions, null, argv, envp); |
| } |
| |
| public long posix_spawnp(String path, Collection<? extends SpawnFileAction> fileActions, |
| Collection<? extends CharSequence> argv, Collection<? extends CharSequence> envp) { |
| return posix_spawnp(path, fileActions, null, argv, envp); |
| } |
| |
| public long posix_spawnp(String path, Collection<? extends SpawnFileAction> fileActions, |
| Collection<? extends SpawnAttribute> spawnAttributes, |
| Collection<? extends CharSequence> argv, Collection<? extends CharSequence> envp) { |
| |
| CharSequence[] nativeArgv = new CharSequence[argv.size()]; |
| argv.toArray(nativeArgv); |
| |
| CharSequence[] nativeEnv = new CharSequence[envp.size()]; |
| envp.toArray(nativeEnv); |
| |
| return posix_spawnp(path, fileActions, spawnAttributes, nativeArgv, nativeEnv); |
| } |
| |
| public long posix_spawnp(String path, Collection<? extends SpawnFileAction> fileActions, |
| Collection<? extends SpawnAttribute> spawnAttributes, |
| CharSequence[] argv, CharSequence[] envp) { |
| // AbstractNumberReference<? extends Number> pid = getRuntime().findType(TypeAlias.pid_t).size() == 4 |
| // ? new IntByReference(-1) : new LongLongByReference(-1); |
| NumberByReference pid = new NumberByReference(TypeAlias.pid_t); |
| Pointer nativeFileActions = fileActions != null && !fileActions.isEmpty() ? nativeFileActions(fileActions) : null; |
| Pointer nativeSpawnAttributes = spawnAttributes != null && !spawnAttributes.isEmpty() ? nativeSpawnAttributes(spawnAttributes) : null; |
| long result; |
| |
| try { |
| result = ((UnixLibC) libc()).posix_spawnp(pid, path, nativeFileActions, nativeSpawnAttributes, argv, envp); |
| } finally { |
| if (nativeFileActions != null) ((UnixLibC) libc()).posix_spawn_file_actions_destroy(nativeFileActions); |
| if (nativeSpawnAttributes != null) ((UnixLibC) libc()).posix_spawnattr_destroy(nativeSpawnAttributes); |
| } |
| |
| if (result != 0) return -1; // result will be errno, but we can't indicate error because we return pid |
| return pid.longValue(); |
| } |
| |
| public int flock(int fd, int mode) { |
| return libc().flock(fd, mode); |
| } |
| |
| public int dup(int fd) { |
| return libc().dup(fd); |
| } |
| |
| public int dup2(int oldFd, int newFd) { |
| return libc().dup2(oldFd, newFd); |
| } |
| |
| public int fcntlInt(int fd, Fcntl fcntl, int arg) { |
| return fcntl(fd, fcntl, arg); |
| } |
| |
| public int fcntl(int fd, Fcntl fcntl) { |
| return libc().fcntl(fd, fcntl.intValue()); |
| } |
| |
| public int fcntl(int fd, Fcntl fcntl, int arg) { |
| return libc().fcntl(fd, fcntl.intValue(), arg); |
| } |
| |
| @Deprecated |
| public int fcntl(int fd, Fcntl fcntl, int... args) { |
| if (args != null) { |
| if (args.length == 1) { |
| return fcntl(fd, fcntl, args[0]); |
| } |
| } |
| throw new IllegalArgumentException("fcntl with variadic int args is unsupported"); |
| } |
| |
| public int access(CharSequence path, int amode) { |
| return libc().access(path, amode); |
| } |
| |
| public int close(int fd) { |
| return libc().close(fd); |
| } |
| |
| private Pointer nativeFileActions(Collection<? extends SpawnFileAction> fileActions) { |
| Pointer nativeFileActions = allocatePosixSpawnFileActions(); |
| ((UnixLibC) libc()).posix_spawn_file_actions_init(nativeFileActions); |
| for (SpawnFileAction action : fileActions) { |
| action.act(this, nativeFileActions); |
| } |
| |
| return nativeFileActions; |
| } |
| |
| private Pointer nativeSpawnAttributes(Collection<? extends SpawnAttribute> spawnAttributes) { |
| Pointer nativeSpawnAttributes = allocatePosixSpawnattr(); |
| ((UnixLibC) libc()).posix_spawnattr_init(nativeSpawnAttributes); |
| for (SpawnAttribute action : spawnAttributes) { |
| action.set(this, nativeSpawnAttributes); |
| } |
| |
| return nativeSpawnAttributes; |
| } |
| |
| public abstract FileStat allocateStat(); |
| |
| public long sysconf(Sysconf name) { |
| switch (name) { |
| case _SC_CLK_TCK: |
| return JavaTimes.HZ; |
| |
| default: |
| errno(Errno.EOPNOTSUPP.intValue()); |
| return -1; |
| } |
| } |
| |
| public int confstr(Confstr name, ByteBuffer buf, int len) { |
| errno(Errno.EOPNOTSUPP.intValue()); |
| return -1; |
| } |
| |
| public int fpathconf(int fd, Pathconf name) { |
| errno(Errno.EOPNOTSUPP.intValue()); |
| return -1; |
| } |
| |
| public Times times() { |
| return new JavaTimes(); |
| } |
| |
| public int unlink(CharSequence path) { |
| return libc().unlink(path); |
| } |
| |
| public int open(CharSequence path, int flags, int perm) { |
| return libc().open(path, flags, perm); |
| } |
| |
| public long read(int fd, byte[] buf, long n) { |
| return libc().read(fd, buf, n); |
| } |
| public long write(int fd, byte[] buf, long n) { |
| return libc().write(fd, buf, n); |
| } |
| public long read(int fd, ByteBuffer buf, long n) { |
| return libc().read(fd, buf, n); |
| } |
| public long write(int fd, ByteBuffer buf, long n) { |
| return libc().write(fd, buf, n); |
| } |
| public long pread(int fd, byte[] buf, long n, long offset) { |
| return libc().pread(fd, buf, n, offset); |
| } |
| public long pwrite(int fd, byte[] buf, long n, long offset) { |
| return libc().pwrite(fd, buf, n, offset); |
| } |
| public long pread(int fd, ByteBuffer buf, long n, long offset) { |
| return libc().pread(fd, buf, n, offset); |
| } |
| public long pwrite(int fd, ByteBuffer buf, long n, long offset) { |
| return libc().pwrite(fd, buf, n, offset); |
| } |
| |
| public int read(int fd, byte[] buf, int n) { |
| return libc().read(fd, buf, n); |
| } |
| public int write(int fd, byte[] buf, int n) { |
| return libc().write(fd, buf, n); |
| } |
| public int read(int fd, ByteBuffer buf, int n) { |
| return libc().read(fd, buf, n); |
| } |
| public int write(int fd, ByteBuffer buf, int n) { |
| return libc().write(fd, buf, n); |
| } |
| public int pread(int fd, byte[] buf, int n, int offset) { |
| return libc().pread(fd, buf, n, offset); |
| } |
| public int pwrite(int fd, byte[] buf, int n, int offset) { |
| return libc().pwrite(fd, buf, n, offset); |
| } |
| public int pread(int fd, ByteBuffer buf, int n, int offset) { |
| return libc().pread(fd, buf, n, offset); |
| } |
| public int pwrite(int fd, ByteBuffer buf, int n, int offset) { |
| return libc().pwrite(fd, buf, n, offset); |
| } |
| |
| public int lseek(int fd, long offset, int whence) { |
| return (int) libc().lseek(fd, offset, whence); |
| } |
| |
| public long lseekLong(int fd, long offset, int whence) { |
| return libc().lseek(fd, offset, whence); |
| } |
| |
| public int pipe(int[] fds) { |
| return libc().pipe(fds); |
| } |
| |
| public int socketpair(int domain, int type, int protocol, int[] fds) { |
| return libc().socketpair(domain, type, protocol, fds); |
| } |
| |
| public int sendmsg(int socket, MsgHdr message, int flags) { |
| return libc().sendmsg( socket, message, flags ); |
| } |
| |
| public int recvmsg(int socket, MsgHdr message, int flags) { |
| return libc().recvmsg(socket, message, flags); |
| } |
| |
| public int truncate(CharSequence path, long length) { |
| return libc().truncate(path, length); |
| } |
| |
| public int ftruncate(int fd, long offset) { |
| return libc().ftruncate(fd, offset); |
| } |
| |
| public int rename(CharSequence oldName, CharSequence newName) { |
| return libc().rename(oldName, newName); |
| } |
| |
| public String gethostname() { |
| ByteBuffer buffer = ByteBuffer.allocate(256); |
| int result; |
| try { |
| result = libc().gethostname(buffer, buffer.capacity() - 1); |
| } catch (java.lang.UnsatisfiedLinkError e) { |
| result = -1; |
| } |
| if (result == -1) return helper.gethostname(); |
| buffer.position(0); |
| while (buffer.hasRemaining() && buffer.get() != 0); |
| buffer.limit(buffer.position() - 1); |
| buffer.position(0); |
| return Charset.forName("US-ASCII").decode(buffer).toString(); |
| } |
| |
| public String getcwd() { |
| byte[] cwd = new byte[1024]; |
| long result = libc().getcwd(cwd, 1024); |
| if (result == -1) return null; |
| int len = 0; |
| for (; len < 1024; len++) if (cwd[len] == 0) break; |
| return new String(cwd, 0, len); |
| } |
| |
| public int fsync(int fd) { |
| return libc().fsync(fd); |
| } |
| |
| public int fdatasync(int fd) { |
| return libc().fdatasync(fd); |
| } |
| |
| public static abstract class PointerConverter implements FromNativeConverter { |
| public Class nativeType() { |
| return Pointer.class; |
| } |
| } |
| |
| public static final PointerConverter GROUP = new PointerConverter() { |
| public Object fromNative(Object arg, FromNativeContext ctx) { |
| return arg != null ? new DefaultNativeGroup((Pointer) arg) : null; |
| } |
| }; |
| |
| public static final ToNativeConverter<FileStat, Pointer> FileStatConverter = new ToNativeConverter<FileStat, Pointer>() { |
| |
| public Pointer toNative(FileStat value, ToNativeContext context) { |
| if (value instanceof BaseFileStat) { |
| return ((BaseFileStat) value).memory; |
| |
| } else if (value instanceof Struct) { |
| return Struct.getMemory((Struct) value); |
| |
| } else if (value == null) { |
| return null; |
| } |
| |
| throw new IllegalArgumentException("instance of " + value.getClass() + " is not a struct"); |
| } |
| |
| public Class<Pointer> nativeType() { |
| return Pointer.class; |
| } |
| |
| }; |
| |
| public static final ToNativeConverter<NativeTimes, Pointer> TimesConverter = new ToNativeConverter<NativeTimes, Pointer>() { |
| |
| public Pointer toNative(NativeTimes value, ToNativeContext context) { |
| return value.memory; |
| } |
| |
| public Class<Pointer> nativeType() { |
| return Pointer.class; |
| } |
| }; |
| |
| public static final ToNativeConverter<Constant, Integer> ConstantConverter = new ToNativeConverter<Constant, Integer>() { |
| |
| public Integer toNative(Constant value, ToNativeContext context) { |
| return value.intValue(); |
| } |
| |
| public Class<Integer> nativeType() { |
| return Integer.class; |
| } |
| }; |
| |
| public static final ToNativeConverter<MsgHdr, Pointer> MsgHdrConverter = new ToNativeConverter<MsgHdr, Pointer>() { |
| public Pointer toNative(MsgHdr value, ToNativeContext context) { |
| if ( value instanceof BaseMsgHdr ) { |
| return ((BaseMsgHdr) value).memory; |
| } else if ( value instanceof Struct ) { |
| return Struct.getMemory((Struct) value); |
| } else if ( value == null ) { |
| return null; |
| } |
| |
| throw new IllegalArgumentException("instance of " + value.getClass() + " is not a struct"); |
| } |
| |
| public Class<Pointer> nativeType() { |
| return Pointer.class; |
| } |
| }; |
| |
| public int mkfifo(String filename, int mode) { |
| return ((UnixLibC) libc()).mkfifo(filename, mode); |
| } |
| |
| public int daemon(int nochdir, int noclose) { |
| return libc().daemon(nochdir, noclose); |
| } |
| |
| @Override |
| public long[] getgroups() { |
| final int size = getgroups(0, null); |
| final int[] groups = new int[size]; |
| final long[] castGroups = new long[size]; |
| |
| final int actualSize = getgroups(size, groups); |
| |
| if (actualSize == -1) { |
| return null; |
| } |
| |
| for (int i = 0; i < actualSize; i++) { |
| castGroups[i] = groups[i] & 0xFFFFFFFFL; |
| } |
| |
| if (actualSize < size) { |
| return Arrays.copyOfRange(castGroups, 0, actualSize); |
| } |
| |
| return castGroups; |
| } |
| |
| @Override |
| public int getgroups(int size, int[] groups) { |
| return libc().getgroups(size, groups); |
| } |
| |
| @Override |
| public String nl_langinfo(int item) { |
| return libc().nl_langinfo(item); |
| } |
| |
| @Override |
| public String setlocale(int category, String locale) { |
| return libc().setlocale(category, locale); |
| } |
| |
| @Override |
| public String strerror(int code) { |
| return libc().strerror(code); |
| } |
| |
| @Override |
| public Timeval allocateTimeval() { return new DefaultNativeTimeval(getRuntime()); } |
| |
| @Override |
| public int gettimeofday(Timeval tv) { return libc().gettimeofday(tv, 0); } |
| } |