/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package libcore.io;
import java.io.FileDescriptor;
import java.nio.ByteBuffer;
import java.nio.NioUtils;
import libcore.util.MutableInt;
import libcore.util.MutableLong;
/*-[
#include "BufferUtils.h"
#include "Portability.h"
#include "TempFailureRetry.h"
#include "java/io/File.h"
#include "libcore/io/StructLinger.h"
#include "libcore/io/StructPollfd.h"
#include "libcore/io/StructStatVfs.h"
#include "libcore/io/StructTimeval.h"
#include <fcntl.h>
#include <poll.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/utsname.h>
#include <termios.h>
#include <unistd.h>
]-*/
public final class Posix implements Os {
Posix() { }
/*-[
static LibcoreIoStructStat *makeStructStat(const struct stat *sb) {
return AUTORELEASE([[LibcoreIoStructStat alloc]
initWithLong:sb->st_dev
withLong:sb->st_ino
withInt:sb->st_mode
withLong:sb->st_nlink
withInt:sb->st_uid
withInt:sb->st_gid
withLong:sb->st_rdev
withLong:sb->st_size
withLong:sb->st_atime
withLong:sb->st_mtime
withLong:sb->st_ctime
withLong:sb->st_blksize
withLong:sb->st_blocks]);
}
static LibcoreIoStructStatVfs *makeStructStatVfs(const struct statvfs *sb) {
return AUTORELEASE([[LibcoreIoStructStatVfs alloc]
initWithLong:(long long)sb->f_bsize
withLong:(long long)sb->f_frsize
withLong:(long long)sb->f_blocks
withLong:(long long)sb->f_bfree
withLong:(long long)sb->f_bavail
withLong:(long long)sb->f_files
withLong:(long long)sb->f_ffree
withLong:(long long)sb->f_favail
withLong:(long long)sb->f_fsid
withLong:(long long)sb->f_flag
withLong:255LL]); // __DARWIN_MAXNAMLEN
}
static LibcoreIoStructUtsname *makeStructUtsname(const struct utsname *buf) {
NSString *sysname = [NSString stringWithUTF8String:buf->sysname];
NSString *nodename = [NSString stringWithUTF8String:buf->nodename];
NSString *release = [NSString stringWithUTF8String:buf->release];
NSString *version = [NSString stringWithUTF8String:buf->version];
NSString *machine = [NSString stringWithUTF8String:buf->machine];
return AUTORELEASE([[LibcoreIoStructUtsname alloc] initWithNSString:sysname
withNSString:nodename
withNSString:release
withNSString:version
withNSString:machine]);
}
static id doStat(NSString *path, BOOL isLstat) {
if (!path) {
return nil;
}
const char* cpath = absolutePath(path);
struct stat sb;
int rc = isLstat ? TEMP_FAILURE_RETRY(lstat(cpath, &sb))
: TEMP_FAILURE_RETRY(stat(cpath, &sb));
if (rc == -1) {
LibcoreIoPosix_throwErrnoExceptionWithNSString_withInt_(
(isLstat ? @"lstat" : @"stat"), errno);
}
return makeStructStat(&sb);
}
BOOL setBlocking(int fd, bool blocking) {
int flags = fcntl(fd, F_GETFL);
if (flags == -1) {
return NO;
}
if (!blocking) {
flags |= O_NONBLOCK;
} else {
flags &= ~O_NONBLOCK;
}
int rc = fcntl(fd, F_SETFL, flags);
return (rc != -1);
}
const char *absolutePath(NSString *path) {
if ([path length] == 0) {
return "";
}
if ([path characterAtIndex:0] != '/') {
JavaIoFile *f = [[JavaIoFile alloc] initWithNSString:path];
path = [f getAbsolutePath];
RELEASE_(f);
}
return [path fileSystemRepresentation];
}
]-*/
static void throwErrnoException(String message, int errorCode) throws ErrnoException {
throw new ErrnoException(message, errorCode);
}
static native int throwIfMinusOne(String name, int resultCode) throws ErrnoException /*-[
if (resultCode == -1) {
LibcoreIoPosix_throwErrnoExceptionWithNSString_withInt_(name, errno);
}
return resultCode;
]-*/;
public native boolean access(String path, int mode) throws ErrnoException /*-[
if (!path) {
return NO;
}
const char* cpath = absolutePath(path);
int rc = TEMP_FAILURE_RETRY(access(cpath, mode));
if (rc == -1) {
LibcoreIoPosix_throwErrnoExceptionWithNSString_withInt_(@"access", errno);
}
return (rc == 0);
]-*/;
/**
* Like access(), but returns false on error instead of throwing an exception.
*/
public native boolean canAccess(String path, int mode) /*-[
if (!path) {
return NO;
}
const char* cpath = absolutePath(path);
return (TEMP_FAILURE_RETRY(access(cpath, mode)) == 0);
]-*/;
public native void chmod(String path, int mode) throws ErrnoException /*-[
if (path) {
const char* cpath = absolutePath(path);
int rc = TEMP_FAILURE_RETRY(chmod(cpath, mode));
LibcoreIoPosix_throwIfMinusOneWithNSString_withInt_(@"chmod", rc);
}
]-*/;
public native void chown(String path, int uid, int gid) throws ErrnoException /*-[
if (path) {
const char* cpath = absolutePath(path);
int rc = TEMP_FAILURE_RETRY(chown(cpath, uid, gid));
LibcoreIoPosix_throwIfMinusOneWithNSString_withInt_(@"chown", rc);
}
]-*/;
public native void close(FileDescriptor javaFd) throws ErrnoException /*-[
// Get the FileDescriptor's 'fd' field and clear it.
// We need to do this before we can throw an IOException.
int fd = [javaFd getInt$];
[javaFd setInt$WithInt:-1];
LibcoreIoPosix_throwIfMinusOneWithNSString_withInt_(@"close", close(fd));
]-*/;
public native FileDescriptor dup(FileDescriptor oldFd) throws ErrnoException /*-[
int nativeFd = TEMP_FAILURE_RETRY(dup([oldFd getInt$]));
LibcoreIoPosix_throwIfMinusOneWithNSString_withInt_(@"dup", nativeFd);
JavaIoFileDescriptor *newFd = AUTORELEASE([[JavaIoFileDescriptor alloc] init]);
[newFd setInt$WithInt:nativeFd];
return newFd;
]-*/;
public native FileDescriptor dup2(FileDescriptor oldFd, int newNativeFd)
throws ErrnoException /*-[
int nativeFd = TEMP_FAILURE_RETRY(dup2([oldFd getInt$], newNativeFd));
LibcoreIoPosix_throwIfMinusOneWithNSString_withInt_(@"dup2", nativeFd);
JavaIoFileDescriptor *newFd = AUTORELEASE([[JavaIoFileDescriptor alloc] init]);
[newFd setInt$WithInt:nativeFd];
return newFd;
]-*/;
public native void fchmod(FileDescriptor fd, int mode) throws ErrnoException /*-[
int rc = TEMP_FAILURE_RETRY(fchmod([fd getInt$], mode));
LibcoreIoPosix_throwIfMinusOneWithNSString_withInt_(@"fchmod", rc);
]-*/;
public native void fchown(FileDescriptor fd, int uid, int gid) throws ErrnoException /*-[
int rc = TEMP_FAILURE_RETRY(fchown([fd getInt$], uid, gid));
LibcoreIoPosix_throwIfMinusOneWithNSString_withInt_(@"fchown", rc);
]-*/;
public native int fcntlFlock(FileDescriptor fd, int cmd, StructFlock arg)
throws ErrnoException /*-[
struct flock64 lock;
memset(&lock, 0, sizeof(lock));
lock.l_type = arg->l_type_;
lock.l_whence = arg->l_whence_;
lock.l_start = arg->l_start_;
lock.l_len = arg->l_len_;
lock.l_pid = arg->l_pid_;
int rc = TEMP_FAILURE_RETRY(fcntl((int) [fd getInt$], cmd, &lock));
if (rc == -1) {
LibcoreIoPosix_throwErrnoExceptionWithNSString_withInt_(@"fcntl", errno);
}
arg->l_type_ = lock.l_type;
arg->l_whence_ = lock.l_whence;
arg->l_start_ = lock.l_start;
arg->l_len_ = lock.l_len;
arg->l_pid_ = lock.l_pid;
return rc;
]-*/;
public native int fcntlLong(FileDescriptor fd, int cmd, long arg) throws ErrnoException /*-[
int rc = TEMP_FAILURE_RETRY(fcntl([fd getInt$], cmd, arg));
return LibcoreIoPosix_throwIfMinusOneWithNSString_withInt_(@"fcntl", rc);
]-*/;
public native int fcntlVoid(FileDescriptor fd, int cmd) throws ErrnoException /*-[
int rc = TEMP_FAILURE_RETRY(fcntl([fd getInt$], cmd));
return LibcoreIoPosix_throwIfMinusOneWithNSString_withInt_(@"fcntl", rc);
]-*/;
public native void fdatasync(FileDescriptor fd) throws ErrnoException /*-[
int rc = TEMP_FAILURE_RETRY(fdatasync([fd getInt$]));
LibcoreIoPosix_throwIfMinusOneWithNSString_withInt_(@"fdatasync", rc);
]-*/;
public native StructStat fstat(FileDescriptor fd) throws ErrnoException /*-[
struct stat sb;
int rc = TEMP_FAILURE_RETRY(fstat([fd getInt$], &sb));
if (rc == -1) {
LibcoreIoPosix_throwErrnoExceptionWithNSString_withInt_(@"fstat", rc);
}
return makeStructStat(&sb);
]-*/;
public native void fsync(FileDescriptor fd) throws ErrnoException /*-[
int rc = TEMP_FAILURE_RETRY(fsync([fd getInt$]));
LibcoreIoPosix_throwIfMinusOneWithNSString_withInt_(@"fsync", rc);
]-*/;
public native void ftruncate(FileDescriptor fd, long length) throws ErrnoException /*-[
int rc = TEMP_FAILURE_RETRY(ftruncate([fd getInt$], (off_t) length));
LibcoreIoPosix_throwIfMinusOneWithNSString_withInt_(@"ftruncate", rc);
]-*/;
public native String if_indextoname(int index) /*-[
char buf[IF_NAMESIZE];
char *name = if_indextoname(index, buf);
// if_indextoname(3) returns NULL on failure. There's no useful information in errno,
// so we don't bother throwing. Callers can null-check.
return name ? [NSString stringWithUTF8String:name] : nil;
]-*/;
public native int ioctlInt(FileDescriptor fd, int cmd, MutableInt javaArg)
throws ErrnoException /*-[
int arg = javaArg->value_;
int rc = TEMP_FAILURE_RETRY(ioctl([fd getInt$], cmd, &arg));
if (rc == -1) {
LibcoreIoPosix_throwErrnoExceptionWithNSString_withInt_(@"ioctl", rc);
}
javaArg->value_ = arg;
return rc;
]-*/;
public native boolean isatty(FileDescriptor fd) /*-[
return TEMP_FAILURE_RETRY(isatty([fd getInt$])) == 1;
]-*/;
public native long lseek(FileDescriptor fd, long offset, int whence) throws ErrnoException /*-[
off_t rc = TEMP_FAILURE_RETRY(lseek([fd getInt$], offset, whence));
if (rc == -1) {
LibcoreIoPosix_throwErrnoExceptionWithNSString_withInt_(@"lseek", errno);
}
return rc;
]-*/;
public native StructStat lstat(String path) throws ErrnoException /*-[
return doStat(path, YES);
]-*/;
public native void listen(FileDescriptor fd, int backlog) throws ErrnoException /*-[
int rc = TEMP_FAILURE_RETRY(listen([fd getInt$], backlog));
LibcoreIoPosix_throwIfMinusOneWithNSString_withInt_(@"listen", rc);
]-*/;
public native void mincore(long address, long byteCount, byte[] vector) throws ErrnoException /*-[
int rc = TEMP_FAILURE_RETRY(mincore(
(caddr_t) address, (size_t) byteCount, (char *)vector->buffer_));
LibcoreIoPosix_throwIfMinusOneWithNSString_withInt_(@"mincore", rc);
]-*/;
public native void mkdir(String path, int mode) throws ErrnoException /*-[
if (path) {
const char* cpath = absolutePath(path);
int rc = TEMP_FAILURE_RETRY(mkdir(cpath, mode));
LibcoreIoPosix_throwIfMinusOneWithNSString_withInt_(@"mkdir", rc);
}
]-*/;
public native void mlock(long address, long byteCount) throws ErrnoException /*-[
int rc = TEMP_FAILURE_RETRY(mlock((void *) address, (size_t) byteCount));
LibcoreIoPosix_throwIfMinusOneWithNSString_withInt_(@"mlock", rc);
]-*/;
public native long mmap(long address, long byteCount, int prot, int flags,
FileDescriptor fd, long offset) throws ErrnoException /*-[
void* ptr = mmap((void *) address, (size_t) byteCount, prot, flags, [fd getInt$], offset);
if (ptr == MAP_FAILED) {
LibcoreIoPosix_throwErrnoExceptionWithNSString_withInt_(@"mmap", errno);
}
return (long long) ptr;
]-*/;
public native void msync(long address, long byteCount, int flags) throws ErrnoException /*-[
int rc = TEMP_FAILURE_RETRY(msync((void *) address, (size_t) byteCount, flags));
LibcoreIoPosix_throwIfMinusOneWithNSString_withInt_(@"msync", rc);
]-*/;
public native void munlock(long address, long byteCount) throws ErrnoException /*-[
int rc = TEMP_FAILURE_RETRY(munlock((void *) address, (size_t) byteCount));
LibcoreIoPosix_throwIfMinusOneWithNSString_withInt_(@"munlock", rc);
]-*/;
public native void munmap(long address, long byteCount) throws ErrnoException /*-[
int rc = TEMP_FAILURE_RETRY(munmap((void *) address, (size_t) byteCount));
LibcoreIoPosix_throwIfMinusOneWithNSString_withInt_(@"munmap", rc);
]-*/;
public native FileDescriptor open(String path, int flags, int mode) throws ErrnoException /*-[
if (!path) {
return nil;
}
const char* cpath = absolutePath(path);
int nativeFd = TEMP_FAILURE_RETRY(open(cpath, flags, mode));
LibcoreIoPosix_throwIfMinusOneWithNSString_withInt_(@"open", nativeFd);
JavaIoFileDescriptor *newFd = AUTORELEASE([[JavaIoFileDescriptor alloc] init]);
[newFd setInt$WithInt:nativeFd];
return newFd;
]-*/;
public native FileDescriptor[] pipe() throws ErrnoException /*-[
int fds[2];
LibcoreIoPosix_throwIfMinusOneWithNSString_withInt_(@"pipe", TEMP_FAILURE_RETRY(pipe(&fds[0])));
IOSObjectArray *result = [IOSObjectArray arrayWithLength:2 type:JavaIoFileDescriptor_class_()];
for (int i = 0; i < 2; ++i) {
JavaIoFileDescriptor *fd = AUTORELEASE([[JavaIoFileDescriptor alloc] init]);
[fd setInt$WithInt:fds[i]];
[result replaceObjectAtIndex:i withObject:fd];
}
return result;
]-*/;
public native int poll(StructPollfd[] fds, int timeoutMs) throws ErrnoException /*-[
jint count = fds->size_;
struct pollfd *pollFds = (struct pollfd *)calloc(count, sizeof(struct pollfd));
for (jint i = 0; i < count; i++) {
LibcoreIoStructPollfd *javaPollFd = [fds objectAtIndex:i];
if (javaPollFd) {
pollFds[i].fd = [javaPollFd->fd_ getInt$];
pollFds[i].events = javaPollFd->events_;
}
}
int rc = poll(pollFds, count, timeoutMs);
if (rc == -1) {
free(pollFds);
LibcoreIoPosix_throwErrnoExceptionWithNSString_withInt_(@"poll", rc);
}
for (jint i = 0; i < count; i++) {
LibcoreIoStructPollfd *javaPollFd = [fds objectAtIndex:i];
if (javaPollFd) {
javaPollFd->revents_ = pollFds[i].revents;
}
}
free(pollFds);
return rc;
]-*/;
public int pread(FileDescriptor fd, ByteBuffer buffer, long offset) throws ErrnoException {
if (buffer.isDirect()) {
return preadBytes(fd, buffer, buffer.position(), buffer.remaining(), offset);
} else {
return preadBytes(fd, NioUtils.unsafeArray(buffer),
NioUtils.unsafeArrayOffset(buffer) + buffer.position(), buffer.remaining(), offset);
}
}
public int pread(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, long offset)
throws ErrnoException {
return preadBytes(fd, bytes, byteOffset, byteCount, offset);
}
private native int preadBytes(FileDescriptor fd, Object buffer, int bufferOffset, int byteCount,
long offset) throws ErrnoException /*-[
char *bytes = BytesRW(buffer);
if (!bytes) {
return -1;
}
int rc =
TEMP_FAILURE_RETRY(pread64([fd getInt$], bytes + bufferOffset, byteCount, offset));
return LibcoreIoPosix_throwIfMinusOneWithNSString_withInt_(@"pread", rc);
]-*/;
public int pwrite(FileDescriptor fd, ByteBuffer buffer, long offset)
throws ErrnoException {
if (buffer.isDirect()) {
return pwriteBytes(fd, buffer, buffer.position(), buffer.remaining(),
offset);
} else {
return pwriteBytes(fd, NioUtils.unsafeArray(buffer),
NioUtils.unsafeArrayOffset(buffer) + buffer.position(),
buffer.remaining(), offset);
}
}
public int pwrite(FileDescriptor fd, byte[] bytes, int byteOffset,
int byteCount, long offset) throws ErrnoException {
return pwriteBytes(fd, bytes, byteOffset, byteCount, offset);
}
private native int pwriteBytes(FileDescriptor fd, Object buffer,
int bufferOffset, int byteCount, long offset) throws ErrnoException /*-[
const char *bytes = BytesRO(buffer);
if (!bytes) {
return -1;
}
if (byteCount + offset < 0) { // If buffer overflow.
LibcoreIoPosix_throwErrnoExceptionWithNSString_withInt_(@"pwrite", ERANGE);
}
int rc =
TEMP_FAILURE_RETRY(pwrite64([fd getInt$], bytes + bufferOffset, byteCount, offset));
return LibcoreIoPosix_throwIfMinusOneWithNSString_withInt_(@"pwrite", rc);
]-*/;
public int read(FileDescriptor fd, ByteBuffer buffer) throws ErrnoException {
if (buffer.isDirect()) {
return readBytes(fd, buffer, buffer.position(), buffer.remaining());
} else {
return readBytes(fd, NioUtils.unsafeArray(buffer),
NioUtils.unsafeArrayOffset(buffer) + buffer.position(), buffer.remaining());
}
}
public int read(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount)
throws ErrnoException {
return readBytes(fd, bytes, byteOffset, byteCount);
}
private native int readBytes(FileDescriptor fd, Object buffer, int offset, int byteCount)
throws ErrnoException /*-[
char *bytes = BytesRW(buffer);
if (!bytes) {
return -1;
}
int rc = TEMP_FAILURE_RETRY(read([fd getInt$], bytes + offset, byteCount));
return LibcoreIoPosix_throwIfMinusOneWithNSString_withInt_(@"read", rc);
]-*/;
public native int readv(FileDescriptor fd, Object[] buffers, int[] offsets, int[] byteCounts)
throws ErrnoException /*-[
int nIoVecs = buffers->size_;
struct iovec *ioVecs = (struct iovec *)malloc(nIoVecs * sizeof (struct iovec));
for (int i = 0; i < nIoVecs; i++) {
char *bytes = BytesRW([buffers objectAtIndex:i]);
if (!bytes) {
free(ioVecs);
return -1;
}
ioVecs[i].iov_base = ((char *) bytes) + IOSIntArray_Get(offsets, i);
ioVecs[i].iov_len = IOSIntArray_Get(byteCounts, i);
}
int rc = TEMP_FAILURE_RETRY(readv([fd getInt$], ioVecs, nIoVecs));
free(ioVecs);
return LibcoreIoPosix_throwIfMinusOneWithNSString_withInt_(@"readv", rc);
]-*/;
public native String realpath(String path) /*-[
if (!path) {
return nil;
}
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *standardizedPath = [path stringByStandardizingPath];
if (![fileManager fileExistsAtPath:standardizedPath]) {
return standardizedPath;
}
const char* cpath = [path UTF8String];
char *realPath = realpath(cpath, NULL);
if (!realPath) {
LibcoreIoPosix_throwErrnoExceptionWithNSString_withInt_(@"realpath", errno);
}
NSString *result =
[[NSFileManager defaultManager] stringWithFileSystemRepresentation:realPath
length:strlen(realPath)];
free(realPath);
return result;
]-*/;
public native void remove(String path) throws ErrnoException /*-[
if (path) {
const char* cpath = absolutePath(path);
int rc = TEMP_FAILURE_RETRY(remove(cpath));
LibcoreIoPosix_throwIfMinusOneWithNSString_withInt_(@"remove", rc);
}
]-*/;
public native void rename(String oldPath, String newPath) throws ErrnoException /*-[
if (oldPath && newPath) {
const char* cOldPath = absolutePath(oldPath);
const char* cNewPath = absolutePath(newPath);
int rc = TEMP_FAILURE_RETRY(rename(cOldPath, cNewPath));
LibcoreIoPosix_throwIfMinusOneWithNSString_withInt_(@"rename", rc);
}
]-*/;
public native long sendfile(FileDescriptor outFd, FileDescriptor inFd, MutableLong inOffset,
long byteCount) throws ErrnoException /*-[
off_t offset = 0;
off_t* offsetPtr = NULL;
if (inOffset != NULL) {
offset = inOffset->value_;
offsetPtr = &offset;
}
int rc = TEMP_FAILURE_RETRY(sendfile_([outFd getInt$], [inFd getInt$],
offsetPtr, (size_t) byteCount));
if (inOffset != NULL) {
inOffset->value_ = offset;
}
return LibcoreIoPosix_throwIfMinusOneWithNSString_withInt_(@"sendfile", rc);
]-*/;
public native void shutdown(FileDescriptor fd, int how) throws ErrnoException /*-[
int rc = TEMP_FAILURE_RETRY(shutdown([fd getInt$], how));
LibcoreIoPosix_throwIfMinusOneWithNSString_withInt_(@"shutdown", rc);
]-*/;
public native FileDescriptor socket(int domain, int type, int protocol) throws ErrnoException /*-[
int nativeFd = TEMP_FAILURE_RETRY(socket(domain, type, protocol));
LibcoreIoPosix_throwIfMinusOneWithNSString_withInt_(@"socket", nativeFd);
JavaIoFileDescriptor *newFd = AUTORELEASE([[JavaIoFileDescriptor alloc] init]);
[newFd setInt$WithInt:nativeFd];
return newFd;
]-*/;
public native void socketpair(int domain, int type, int protocol, FileDescriptor fd1,
FileDescriptor fd2) throws ErrnoException /*-[
int fds[2];
int rc = TEMP_FAILURE_RETRY(socketpair(domain, type, protocol, fds));
if (rc != -1) {
[fd1 setInt$WithInt:fds[0]];
[fd2 setInt$WithInt:fds[1]];
}
LibcoreIoPosix_throwIfMinusOneWithNSString_withInt_(@"socketpair", rc);
]-*/;
public native StructStat stat(String path) throws ErrnoException /*-[
return doStat(path, NO);
]-*/;
public native StructStatVfs statvfs(String path) throws ErrnoException /*-[
if (!path) {
return nil;
}
const char* cpath = absolutePath(path);
struct statvfs sb;
int rc = TEMP_FAILURE_RETRY(statvfs(cpath, &sb));
if (rc == -1) {
LibcoreIoPosix_throwErrnoExceptionWithNSString_withInt_(@"statvfs", errno);
}
return makeStructStatVfs(&sb);
]-*/;
public native String strerror(int errno) /*-[
char buffer[BUFSIZ];
int ret = strerror_r(errno_, buffer, BUFSIZ);
if (ret != 0) { // If not successful...
snprintf(buffer, BUFSIZ, "errno %d", errno_);
}
return [NSString stringWithUTF8String:buffer];
]-*/;
public native long sysconf(int name) /*-[
// Since -1 is a valid result from sysconf(3), detecting failure is a little more awkward.
errno = 0;
long result = sysconf(name);
if (result == -1L && errno == EINVAL) {
LibcoreIoPosix_throwErrnoExceptionWithNSString_withInt_(@"sysconf", errno);
}
return result;
]-*/;
public native void symlink(String oldPath, String newPath) throws ErrnoException /*-[
if (oldPath && newPath) {
const char* cOldPath = [oldPath UTF8String];
const char* cNewPath = [newPath UTF8String];
int rc = TEMP_FAILURE_RETRY(symlink(cOldPath, cNewPath));
LibcoreIoPosix_throwIfMinusOneWithNSString_withInt_(@"symlink", rc);
}
]-*/;
public native void tcdrain(FileDescriptor fd) throws ErrnoException /*-[
int rc = TEMP_FAILURE_RETRY(tcdrain([fd getInt$]));
LibcoreIoPosix_throwIfMinusOneWithNSString_withInt_(@"fcntl", rc);
]-*/;
public native StructUtsname uname() /*-[
struct utsname buf;
if (TEMP_FAILURE_RETRY(uname(&buf)) == -1) {
return nil;
}
return makeStructUtsname(&buf);
]-*/;
public int write(FileDescriptor fd, ByteBuffer buffer) throws ErrnoException {
if (buffer.isDirect()) {
return writeBytes(fd, buffer, buffer.position(), buffer.remaining());
} else {
return writeBytes(fd, NioUtils.unsafeArray(buffer),
NioUtils.unsafeArrayOffset(buffer) + buffer.position(), buffer.remaining());
}
}
public native int write(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount)
throws ErrnoException /*-[
if (!bytes) {
return -1;
}
IOSArray_checkRange(bytes->size_, byteOffset, byteCount);
int rc =
TEMP_FAILURE_RETRY(write([fd getInt$], bytes->buffer_ + byteOffset, byteCount));
return LibcoreIoPosix_throwIfMinusOneWithNSString_withInt_(@"write", rc);
]-*/;
private native int writeBytes(FileDescriptor fd, Object buffer, int offset, int byteCount)
throws ErrnoException /*-[
const char *bytes = BytesRO(buffer);
if (!bytes) {
return -1;
}
int rc = TEMP_FAILURE_RETRY(write([fd getInt$], bytes + offset, byteCount));
return LibcoreIoPosix_throwIfMinusOneWithNSString_withInt_(@"write", rc);
]-*/;
public native int writev(FileDescriptor fd, Object[] buffers, int[] offsets, int[] byteCounts)
throws ErrnoException /*-[
int nIoVecs = buffers->size_;
struct iovec *ioVecs = (struct iovec *)malloc(nIoVecs * sizeof (struct iovec));
for (int i = 0; i < nIoVecs; i++) {
const char *bytes = BytesRO([buffers objectAtIndex:i]);
if (!bytes) {
free(ioVecs);
return -1;
}
ioVecs[i].iov_base = ((char *) bytes) + IOSIntArray_Get(offsets, i);
ioVecs[i].iov_len = IOSIntArray_Get(byteCounts, i);
}
int rc = TEMP_FAILURE_RETRY(writev([fd getInt$], ioVecs, nIoVecs));
free(ioVecs);
return LibcoreIoPosix_throwIfMinusOneWithNSString_withInt_(@"writev", rc);
]-*/;
@Override
public native int getpid() /*-[
return getpid();
]-*/;
@Override
public native int getppid() /*-[
return getppid();
]-*/;
// Uncomment and implement as Os interface grows.
// public native String[] environ();
// public native StructStatFs fstatfs(FileDescriptor fd) throws ErrnoException;
// public native int getegid();
// public native int geteuid();
// public native int getgid();
// public native String getenv(String name);
// public native StructPasswd getpwnam(String name) throws ErrnoException;
// public native StructPasswd getpwuid(int uid) throws ErrnoException;
// public native int getuid();
// public native void kill(int pid, int signal) throws ErrnoException;
// public native void lchown(String path, int uid, int gid) throws ErrnoException;
// public native void listen(FileDescriptor fd, int backlog) throws ErrnoException;
// public native void setegid(int egid) throws ErrnoException;
// public native void setenv(String name, String value, boolean overwrite) throws ErrnoException;
// public native void seteuid(int euid) throws ErrnoException;
// public native void setgid(int gid) throws ErrnoException;
// public native int setsid() throws ErrnoException;
// public native void setuid(int uid) throws ErrnoException;
// public native FileDescriptor socket(int domain, int type, int protocol) throws ErrnoException;
// public native StructStatFs statfs(String path) throws ErrnoException;
// public native void tcsendbreak(FileDescriptor fd, int duration) throws ErrnoException;
// public int umask(int mask) {
// if ((mask & 0777) != mask) {
// throw new IllegalArgumentException("Invalid umask: " + mask);
// }
// return umaskImpl(mask);
// }
// private native int umaskImpl(int mask);
// public native void unsetenv(String name) throws ErrnoException;
// public native int waitpid(int pid, MutableInt status, int options) throws ErrnoException;
}