use of org.graalvm.nativeimage.c.type.CCharPointer in project graal by oracle.
the class PosixJavaIOSubstitutions method setPermission.
@Substitute
public boolean setPermission(File f, int access, boolean enable, boolean owneronly) {
int amode = 0;
if (access == Target_java_io_FileSystem.ACCESS_READ) {
amode = owneronly ? S_IRUSR() : S_IRUSR() | S_IRGRP() | S_IROTH();
} else if (access == Target_java_io_FileSystem.ACCESS_WRITE) {
amode = owneronly ? S_IWUSR() : S_IWUSR() | S_IWGRP() | S_IWOTH();
} else if (access == Target_java_io_FileSystem.ACCESS_EXECUTE) {
amode = owneronly ? S_IXUSR() : S_IXUSR() | S_IXGRP() | S_IXOTH();
} else {
throw VMError.shouldNotReachHere("illegal access mode");
}
stat stat = StackValue.get(SizeOf.get(stat.class));
try (CCharPointerHolder pathPin = CTypeConversion.toCString(f.getPath())) {
CCharPointer pathPtr = pathPin.get();
if (stat(pathPtr, stat) == 0) {
int newMode;
if (enable) {
newMode = stat.st_mode() | amode;
} else {
newMode = stat.st_mode() & ~amode;
}
if (chmod(pathPtr, newMode) >= 0) {
return true;
}
}
}
return false;
}
use of org.graalvm.nativeimage.c.type.CCharPointer in project graal by oracle.
the class PosixJavaIOSubstitutions method list.
@Substitute
public String[] list(File f) {
DIR dir;
try (CCharPointerHolder pathPin = CTypeConversion.toCString(f.getPath())) {
CCharPointer pathPtr = pathPin.get();
dir = opendir(pathPtr);
}
if (dir.isNull()) {
return null;
}
List<String> entries = new ArrayList<>();
dirent dirent = StackValue.get(SizeOf.get(dirent.class) + PATH_MAX() + 1);
direntPointer resultDirent = StackValue.get(SizeOf.get(direntPointer.class));
while (readdir_r(dir, dirent, resultDirent) == 0 && !resultDirent.read().isNull()) {
String name = CTypeConversion.toJavaString(dirent.d_name());
if (name.equals(".") || name.equals("..")) {
continue;
}
entries.add(name);
}
closedir(dir);
return entries.toArray(new String[entries.size()]);
}
use of org.graalvm.nativeimage.c.type.CCharPointer in project graal by oracle.
the class PosixJavaLangSubstitutions method forkAndExec.
/*
* NOTE: This implementation uses simple fork() and exec() calls. However, OpenJDK uses
* posix_spawn() on some platforms, specifically on Solaris to avoid swap exhaustion when memory
* is reserved conservatively for the fork'ed process. That implementation is more complex and
* requires a helper tool to cleanly launch the actual target executable.
*/
@Substitute
@SuppressWarnings({ "unused", "static-method" })
int forkAndExec(int mode, byte[] helperpath, byte[] file, byte[] argBlock, int argCount, byte[] envBlock, int envCount, byte[] dir, int[] fds, boolean redirectErrorStream) throws IOException {
int[] pipes = new int[8];
Arrays.fill(pipes, -1);
try (//
PinnedObject filePin = PinnedObject.create(file);
PinnedObject dirPin = PinnedObject.create(dir);
PinnedObject argBlockPin = PinnedObject.create(argBlock);
PinnedObject argvPin = PinnedObject.create(new CCharPointerPointer[argCount + 2]);
PinnedObject envBlockPin = PinnedObject.create(envBlock);
PinnedObject envpPin = PinnedObject.create(new CCharPointerPointer[envCount + 1]);
//
PinnedObject pipesPin = PinnedObject.create(pipes)) {
CCharPointerPointer argv = argvPin.addressOfArrayElement(0);
argv.write(0, filePin.addressOfArrayElement(0));
Java_lang_UNIXProcess_Supplement.gatherCStringPointers(argBlockPin.addressOfArrayElement(0), argBlock.length, argv.addressOf(1), argCount + 1);
CCharPointerPointer envp = WordFactory.nullPointer();
if (envBlock != null) {
envp = envpPin.addressOfArrayElement(0);
Java_lang_UNIXProcess_Supplement.gatherCStringPointers(envBlockPin.addressOfArrayElement(0), envBlock.length, envp.addressOf(0), envCount + 1);
}
CIntPointer[] stdioPipes = new CIntPointer[3];
for (int i = 0; i <= 2; i++) {
if (fds[i] == -1) {
stdioPipes[i] = pipesPin.addressOfArrayElement(2 * i);
if (Unistd.pipe(stdioPipes[i]) < 0) {
throw new IOException("pipe() failed");
}
}
}
CIntPointer failPipe = pipesPin.addressOfArrayElement(2 * stdioPipes.length);
if (Unistd.pipe(failPipe) < 0) {
throw new IOException("pipe() failed");
}
int[] childStdioFds = new int[3];
childStdioFds[0] = (fds[0] != -1) ? fds[0] : stdioPipes[0].read(0);
childStdioFds[1] = (fds[1] != -1) ? fds[1] : stdioPipes[1].read(1);
childStdioFds[2] = (fds[2] != -1) ? fds[2] : stdioPipes[2].read(1);
int childFailFd = failPipe.read(1);
CCharPointer filep = filePin.addressOfArrayElement(0);
CCharPointer dirp = (dir != null) ? dirPin.addressOfArrayElement(0) : WordFactory.nullPointer();
int childPid = Java_lang_UNIXProcess_Supplement.doForkAndExec(filep, dirp, argv, envp, childStdioFds, childFailFd);
if (childPid < 0) {
throw new IOException("fork() failed");
}
// If we are here, we are the parent.
// store fds of our pipe ends for caller, close unused fds (those of the child)
fds[0] = fds[1] = fds[2] = -1;
if (stdioPipes[0].isNonNull()) {
fds[0] = stdioPipes[0].read(1);
Unistd.close(stdioPipes[0].read(0));
}
if (stdioPipes[1].isNonNull()) {
fds[1] = stdioPipes[1].read(0);
Unistd.close(stdioPipes[1].read(1));
}
if (stdioPipes[2].isNonNull()) {
fds[2] = stdioPipes[2].read(0);
Unistd.close(stdioPipes[2].read(1));
}
Unistd.close(failPipe.read(1));
// read status from child
final int intSize = SizeOf.get(CIntPointer.class);
CIntPointer pErrno = StackValue.get(intSize);
SignedWord failBytes = Java_lang_UNIXProcess_Supplement.readEntirely(failPipe.read(0), pErrno, WordFactory.unsigned(intSize));
Unistd.close(failPipe.read(0));
if (failBytes.equal(0)) {
// success: pipe closed during exec()
return childPid;
} else if (failBytes.equal(SizeOf.get(CIntPointer.class))) {
int errbuflen = 256;
try (PinnedObject errbuf = PinnedObject.create(new byte[errbuflen])) {
CCharPointer detailCstr = Errno.strerror_r(pErrno.read(), errbuf.addressOfArrayElement(0), WordFactory.unsigned(errbuflen));
String detail = CTypeConversion.toJavaString(detailCstr);
throw new IOException("error=" + pErrno.read() + ", " + detail);
}
} else {
throw new IOException("unexpected data from child");
}
} catch (IOException e) {
// NOTE: not a finally statement because when successful, some pipes need to stay open
for (int fd : pipes) {
if (fd != -1) {
Unistd.close(fd);
}
}
throw e;
}
}
use of org.graalvm.nativeimage.c.type.CCharPointer in project graal by oracle.
the class PosixJavaLangSubstitutions method environ.
// This code is derived from the C implementation of the JDK.
@Substitute
static byte[][] environ() {
CCharPointerPointer environ = LibCHelper.getEnviron();
int count = 0;
for (int i = 0; environ.read(i).isNonNull(); i++) {
/* Ignore corrupted environment variables */
if (LibC.strchr(environ.read(i), '=').isNonNull()) {
count++;
}
}
byte[][] result = new byte[count * 2][];
int j = 0;
for (int i = 0; environ.read(i).isNonNull(); i++) {
CCharPointer varBeg = environ.read(i);
CCharPointer varEnd = LibC.strchr(varBeg, '=');
/* Ignore corrupted environment variables */
if (varEnd.isNonNull()) {
CCharPointer valBeg = varEnd.addressOf(1);
int varLength = (int) PointerUtils.absoluteDifference(varEnd, varBeg).rawValue();
int valLength = (int) LibC.strlen(valBeg).rawValue();
byte[] var = new byte[varLength];
SubstrateUtil.wrapAsByteBuffer(varBeg, varLength).get(var);
result[2 * j] = var;
byte[] val = new byte[valLength];
SubstrateUtil.wrapAsByteBuffer(valBeg, valLength).get(val);
result[2 * j + 1] = val;
j++;
}
}
assert j == count;
return result;
}
use of org.graalvm.nativeimage.c.type.CCharPointer in project graal by oracle.
the class PosixJavaLangSubstitutions method uninterruptibleForkAndExec.
@Uninterruptible(reason = "fragile state after fork()")
private static int uninterruptibleForkAndExec(CCharPointer file, CCharPointer dir, CCharPointerPointer argv, CCharPointerPointer envp, int[] stdioFds, int initialFailFd, PointerBase buffer, int buflen, CCharPointer procFdsPath, CCharPointer searchPaths, CCharPointer searchPathSeparator) {
int childPid;
childPid = UnistdNoTransitions.fork();
if (childPid != 0) {
return childPid;
}
// If we are here, we are the child process.
int failFd = initialFailFd;
try {
// In case of an error, we "return" to end up in the finally block below and notify the
// parent process of the failure.
final int gotoFinally = -1;
if (Java_lang_UNIXProcess_Supplement.dup2(stdioFds[0], 0) < 0) {
return gotoFinally;
}
if (Java_lang_UNIXProcess_Supplement.dup2(stdioFds[1], 1) < 0) {
return gotoFinally;
}
if (Java_lang_UNIXProcess_Supplement.dup2(stdioFds[2], 2) < 0) {
return gotoFinally;
}
if (Java_lang_UNIXProcess_Supplement.dup2(failFd, 3) < 0) {
return gotoFinally;
}
failFd = 3;
// FD_CLOEXEC: close fail pipe on exec() to indicate success to parent
if (Fcntl.fcntl_no_transition(failFd, Fcntl.F_SETFD(), Fcntl.FD_CLOEXEC()) < 0) {
return gotoFinally;
}
/*
* opendir() below allocates a file descriptor. We close failFd+1 so it should become
* the descriptor allocated to opendir() and we can avoid closing it together with the
* other descriptors.
*/
final int maxFd = failFd + 1;
if (UnistdNoTransitions.close(maxFd) < 0) {
return gotoFinally;
}
if (procFdsPath.isNull()) {
// We have no procfs, resort to close file descriptors by trial and error
int maxOpenFds = (int) UnistdNoTransitions.sysconf(Unistd._SC_OPEN_MAX());
for (int fd = maxFd + 1; fd < maxOpenFds; fd++) {
if (UnistdNoTransitions.close(fd) != 0 && Errno.errno() != Errno.EBADF()) {
return gotoFinally;
}
}
} else {
DIR fddir = Dirent.opendir_no_transition(procFdsPath);
if (fddir.isNull()) {
return gotoFinally;
}
dirent dirent = WordFactory.pointer(buffer.rawValue());
direntPointer direntptr = StackValue.get(SizeOf.get(direntPointer.class));
int status;
while ((status = Dirent.readdir_r_no_transition(fddir, dirent, direntptr)) == 0 && direntptr.read().isNonNull()) {
CCharPointerPointer endptr = StackValue.get(SizeOf.get(CCharPointerPointer.class));
long fd = LibC.strtol(dirent.d_name(), endptr, 10);
if (fd > maxFd && endptr.read().isNonNull() && endptr.read().read() == '\0') {
UnistdNoTransitions.close((int) fd);
}
}
if (status != 0) {
// readdir_r() does not set errno
Errno.set_errno(status);
return gotoFinally;
}
Dirent.closedir_no_transition(fddir);
}
if (dir.isNonNull()) {
if (UnistdNoTransitions.chdir(dir) < 0) {
return gotoFinally;
}
}
CCharPointerPointer actualEnvp = envp;
if (actualEnvp.isNull()) {
actualEnvp = LibCHelper.getEnviron();
}
if (LibC.strchr(file, '/').isNonNull()) {
UnistdNoTransitions.execve(argv.read(0), argv, actualEnvp);
} else {
// Scan PATH for the file to execute. We cannot use execvpe()
// because it is a GNU extension that is not universally available.
final int fileStrlen = (int) LibC.strlen(file).rawValue();
int stickyErrno = 0;
final CCharPointerPointer saveptr = StackValue.get(SizeOf.get(CCharPointerPointer.class));
saveptr.write(WordFactory.nullPointer());
CCharPointer searchDir = LibC.strtok_r(searchPaths, searchPathSeparator, saveptr);
while (searchDir.isNonNull()) {
CCharPointer bufptr = WordFactory.pointer(buffer.rawValue());
int len0 = (int) LibC.strlen(searchDir).rawValue();
if (len0 + fileStrlen + 2 > buflen) {
Errno.set_errno(Errno.ENAMETOOLONG());
continue;
}
if (len0 > 0) {
LibC.strcpy(bufptr, searchDir);
if (bufptr.read(len0 - 1) != '/') {
bufptr.write(len0, (byte) '/');
len0++;
}
}
LibC.strcpy(bufptr.addressOf(len0), file);
UnistdNoTransitions.execve(bufptr, argv, actualEnvp);
int e = Errno.errno();
if (e == Errno.EACCES()) {
// as exec(): report EACCES unless we succeed later
stickyErrno = e;
} else if (e == Errno.ENOENT() || e == Errno.ENOTDIR() || e == Errno.ELOOP() || e == Errno.ESTALE() || e == Errno.ENODEV() || e == Errno.ETIMEDOUT()) {
// ignore
} else {
stickyErrno = e;
// bad
break;
}
searchDir = LibC.strtok_r(WordFactory.nullPointer(), searchPathSeparator, saveptr);
}
if (stickyErrno != 0) {
Errno.set_errno(stickyErrno);
}
}
// If we are here, exec certainly failed.
} catch (Throwable t) {
Errno.set_errno(Integer.MIN_VALUE);
} finally {
try {
// notify parent of failure
final int intSize = SizeOf.get(CIntPointer.class);
CIntPointer pErrno = StackValue.get(intSize);
pErrno.write(Errno.errno());
Java_lang_UNIXProcess_Supplement.writeEntirely(failFd, pErrno, WordFactory.unsigned(intSize));
UnistdNoTransitions.close(failFd);
} finally {
UnistdNoTransitions._exit(-1);
}
}
throw VMError.shouldNotReachHere();
}
Aggregations