unixMain.io.matthewnelson.kmp.process.internal.stdio.UnixStdioDescriptor.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of process Show documentation
Show all versions of process Show documentation
Process for Kotlin Multiplatform
The newest version!
/*
* Copyright (c) 2024 Matthew Nelson
*
* 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
*
* https://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.
**/
@file:Suppress("KotlinRedundantDiagnosticSuppress")
package io.matthewnelson.kmp.process.internal.stdio
import io.matthewnelson.kmp.file.IOException
import io.matthewnelson.kmp.file.errnoToIOException
import io.matthewnelson.kmp.process.Stdio
import io.matthewnelson.kmp.process.internal.check
import kotlinx.cinterop.*
import platform.posix.*
@Suppress("NOTHING_TO_INLINE")
internal actual inline fun Int.orOCloExec(): Int = this or O_CLOEXEC
@Throws(IOException::class)
@OptIn(ExperimentalForeignApi::class)
internal actual fun ((fdRead: Int, fdWrite: Int) -> StdioDescriptor.Pipe).fdOpen(
stdio: Stdio.Pipe,
): StdioDescriptor.Pipe {
val pipeFD = IntArray(2) { -1 }
val isPipe2 = pipeFD.usePinned { pinned ->
val p0: CPointer = pinned.addressOf(0)
if (p0.pipe2(O_CLOEXEC) == 0) return@usePinned true
pipe(p0).check()
false
}
if (!isPipe2) {
pipeFD.forEach { fd ->
// val prev = fcntl(fd, F_GETFD)
// if (prev < 0) {\
// val e = errnoToIOException(errno)
// fdClose(pipeFD[0])
// fdClose(pipeFD[1])
// throw e
// }
// no need to check F_GETFD b/c it was just
// created via pipe1 with no flags set.
val result = fcntl(fd, F_SETFD, FD_CLOEXEC)
if (result != 0) {
val e = errnoToIOException(errno)
if (close(pipeFD[0]) == -1) {
e.addSuppressed(errnoToIOException(errno))
}
if (close(pipeFD[1]) == -1) {
e.addSuppressed(errnoToIOException(errno))
}
throw e
}
}
}
return this(/*fdRead =*/ pipeFD[0],/* fdWrite =*/ pipeFD[1])
}
// returns 0 for success, -1 for failure
@Suppress("NOTHING_TO_INLINE")
@OptIn(ExperimentalForeignApi::class)
internal expect inline fun CPointer.pipe2(
flags: Int,
): Int
© 2015 - 2025 Weber Informatics LLC | Privacy Policy